1 /**************************************************************************
3 * isapnp.c -- Etherboot isapnp support for the 3Com 3c515
4 * Written 2002-2003 by Timothy Legge <tlegge@rogers.com>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 * Portions of this code:
21 * Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
26 * Version 0.1 April 26, 2002 TJL
27 * Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
28 * Version 0.3 Sept 23, 2003 timlegge Change delay to currticks
31 * Generalised into an ISAPnP bus that can be used by more than just
32 * the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
34 ***************************************************************************/
40 * Etherboot orignally gained ISAPnP support in a very limited way for
41 * the 3c515 NIC. The current implementation is almost a complete
42 * rewrite based on the ISAPnP specification, with passing reference
43 * to the Linux ISAPnP code.
45 * There can be only one ISAPnP bus in a system. Once the read port
46 * is known and all cards have been allocated CSNs, there's nothing to
47 * be gained by re-scanning for cards.
49 * External code (e.g. the ISAPnP ROM prefix) may already know the
50 * read port address, in which case it can store it in
51 * #isapnp_read_port. Note that setting the read port address in this
52 * way will prevent further isolation from taking place; you should
53 * set the read port address only if you know that devices have
54 * already been allocated CSNs.
65 #include <gpxe/isapnp.h>
68 * ISAPnP Read Port address.
70 * ROM prefix may be able to set this address, which is why this is
73 uint16_t isapnp_read_port
;
75 static struct isapnp_driver isapnp_drivers
[0]
76 __table_start ( struct isapnp_driver
, isapnp_drivers
);
77 static struct isapnp_driver isapnp_drivers_end
[0]
78 __table_end ( struct isapnp_driver
, isapnp_drivers
);
80 static void isapnpbus_remove ( struct root_device
*rootdev
);
83 * ISAPnP utility functions
87 #define ISAPNP_CARD_ID_FMT "ID %04x:%04x (\"%s\") serial %x"
88 #define ISAPNP_CARD_ID_DATA(identifier) \
89 (identifier)->vendor_id, (identifier)->prod_id, \
90 isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
92 #define ISAPNP_DEV_ID_FMT "ID %04x:%04x (\"%s\")"
93 #define ISAPNP_DEV_ID_DATA(isapnp) \
94 (isapnp)->vendor_id, (isapnp)->prod_id, \
95 isa_id_string ( (isapnp)->vendor_id, (isapnp)->prod_id )
97 static inline void isapnp_write_address ( unsigned int address
) {
98 outb ( address
, ISAPNP_ADDRESS
);
101 static inline void isapnp_write_data ( unsigned int data
) {
102 outb ( data
, ISAPNP_WRITE_DATA
);
105 static inline unsigned int isapnp_read_data ( void ) {
106 return inb ( isapnp_read_port
);
109 static inline void isapnp_write_byte ( unsigned int address
,
110 unsigned int value
) {
111 isapnp_write_address ( address
);
112 isapnp_write_data ( value
);
115 static inline unsigned int isapnp_read_byte ( unsigned int address
) {
116 isapnp_write_address ( address
);
117 return isapnp_read_data ();
120 static inline unsigned int isapnp_read_word ( unsigned int address
) {
121 /* Yes, they're in big-endian order */
122 return ( ( isapnp_read_byte ( address
) << 8 )
123 | isapnp_read_byte ( address
+ 1 ) );
126 /** Inform cards of a new read port address */
127 static inline void isapnp_set_read_port ( void ) {
128 isapnp_write_byte ( ISAPNP_READPORT
, ( isapnp_read_port
>> 2 ) );
132 * Enter the Isolation state.
134 * Only cards currently in the Sleep state will respond to this
137 static inline void isapnp_serialisolation ( void ) {
138 isapnp_write_address ( ISAPNP_SERIALISOLATION
);
142 * Enter the Wait for Key state.
144 * All cards will respond to this command, regardless of their current
147 static inline void isapnp_wait_for_key ( void ) {
148 isapnp_write_byte ( ISAPNP_CONFIGCONTROL
, ISAPNP_CONFIG_WAIT_FOR_KEY
);
152 * Reset (i.e. remove) Card Select Number.
154 * Only cards currently in the Sleep state will respond to this
157 static inline void isapnp_reset_csn ( void ) {
158 isapnp_write_byte ( ISAPNP_CONFIGCONTROL
, ISAPNP_CONFIG_RESET_CSN
);
162 * Place a specified card into the Config state.
164 * @v csn Card Select Number
168 * Only cards currently in the Sleep, Isolation, or Config states will
169 * respond to this command. The card that has the specified CSN will
170 * enter the Config state, all other cards will enter the Sleep state.
172 static inline void isapnp_wake ( uint8_t csn
) {
173 isapnp_write_byte ( ISAPNP_WAKE
, csn
);
176 static inline unsigned int isapnp_read_resourcedata ( void ) {
177 return isapnp_read_byte ( ISAPNP_RESOURCEDATA
);
180 static inline unsigned int isapnp_read_status ( void ) {
181 return isapnp_read_byte ( ISAPNP_STATUS
);
185 * Assign a Card Select Number to a card, and enter the Config state.
187 * @v csn Card Select Number
189 * Only cards in the Isolation state will respond to this command.
190 * The isolation protocol is designed so that only one card will
191 * remain in the Isolation state by the time the isolation protocol
194 static inline void isapnp_write_csn ( unsigned int csn
) {
195 isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER
, csn
);
198 static inline void isapnp_logicaldevice ( unsigned int logdev
) {
199 isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER
, logdev
);
202 static inline void isapnp_activate ( unsigned int logdev
) {
203 isapnp_logicaldevice ( logdev
);
204 isapnp_write_byte ( ISAPNP_ACTIVATE
, 1 );
207 static inline void isapnp_deactivate ( unsigned int logdev
) {
208 isapnp_logicaldevice ( logdev
);
209 isapnp_write_byte ( ISAPNP_ACTIVATE
, 0 );
212 static inline unsigned int isapnp_read_iobase ( unsigned int index
) {
213 return isapnp_read_word ( ISAPNP_IOBASE ( index
) );
216 static inline unsigned int isapnp_read_irqno ( unsigned int index
) {
217 return isapnp_read_byte ( ISAPNP_IRQNO ( index
) );
220 static void isapnp_delay ( void ) {
225 * Linear feedback shift register.
227 * @v lfsr Current value of the LFSR
228 * @v input_bit Current input bit to the LFSR
229 * @ret lfsr Next value of the LFSR
231 * This routine implements the linear feedback shift register as
232 * described in Appendix B of the PnP ISA spec. The hardware
233 * implementation uses eight D-type latches and two XOR gates. I
234 * think this is probably the smallest possible implementation in
235 * software. Six instructions when input_bit is a constant 0 (for
236 * isapnp_send_key). :)
238 static inline unsigned int isapnp_lfsr_next ( unsigned int lfsr
,
239 unsigned int input_bit
) {
240 register uint8_t lfsr_next
;
242 lfsr_next
= lfsr
>> 1;
243 lfsr_next
|= ( ( ( lfsr
^ lfsr_next
) ^ input_bit
) ) << 7;
248 * Send the ISAPnP initiation key.
250 * Sending the key causes all ISAPnP cards that are currently in the
251 * Wait for Key state to transition into the Sleep state.
253 static void isapnp_send_key ( void ) {
258 isapnp_write_address ( 0x00 );
259 isapnp_write_address ( 0x00 );
261 lfsr
= ISAPNP_LFSR_SEED
;
262 for ( i
= 0 ; i
< 32 ; i
++ ) {
263 isapnp_write_address ( lfsr
);
264 lfsr
= isapnp_lfsr_next ( lfsr
, 0 );
269 * Compute ISAPnP identifier checksum
271 * @v identifier ISAPnP identifier
272 * @ret checksum Expected checksum value
274 static unsigned int isapnp_checksum ( struct isapnp_identifier
*identifier
) {
279 lfsr
= ISAPNP_LFSR_SEED
;
280 for ( i
= 0 ; i
< 8 ; i
++ ) {
281 byte
= * ( ( ( uint8_t * ) identifier
) + i
);
282 for ( j
= 0 ; j
< 8 ; j
++ ) {
283 lfsr
= isapnp_lfsr_next ( lfsr
, byte
);
291 * Read a byte of resource data from the current location
293 * @ret byte Byte of resource data
295 static inline unsigned int isapnp_peek_byte ( void ) {
298 /* Wait for data to be ready */
299 for ( i
= 0 ; i
< 20 ; i
++ ) {
300 if ( isapnp_read_status() & 0x01 ) {
301 /* Byte ready - read it */
302 return isapnp_read_resourcedata();
306 /* Data never became ready - return 0xff */
311 * Read resource data.
313 * @v buf Buffer in which to store data, or NULL
314 * @v bytes Number of bytes to read
316 * Resource data is read from the current location. If #buf is NULL,
317 * the data is discarded.
319 static void isapnp_peek ( void *buf
, size_t len
) {
323 for ( i
= 0 ; i
< len
; i
++) {
324 byte
= isapnp_peek_byte();
326 * ( ( uint8_t * ) buf
+ i
) = byte
;
331 * Find a tag within the resource data.
333 * @v wanted_tag The tag that we're looking for
334 * @v buf Buffer in which to store the tag's contents
335 * @v len Length of buffer
336 * @ret rc Return status code
338 * Scan through the resource data until we find a particular tag, and
339 * read its contents into a buffer.
341 static int isapnp_find_tag ( unsigned int wanted_tag
, void *buf
, size_t len
) {
343 unsigned int tag_len
;
345 DBG2 ( "ISAPnP read tag" );
347 tag
= isapnp_peek_byte();
348 if ( ISAPNP_IS_SMALL_TAG ( tag
) ) {
349 tag_len
= ISAPNP_SMALL_TAG_LEN ( tag
);
350 tag
= ISAPNP_SMALL_TAG_NAME ( tag
);
352 tag_len
= ( isapnp_peek_byte() +
353 ( isapnp_peek_byte() << 8 ) );
354 tag
= ISAPNP_LARGE_TAG_NAME ( tag
);
356 DBG2 ( " %02x (%02x)", tag
, tag_len
);
357 if ( tag
== wanted_tag
) {
360 isapnp_peek ( buf
, len
);
364 isapnp_peek ( NULL
, tag_len
);
366 } while ( tag
!= ISAPNP_TAG_END
);
372 * Find specified Logical Device ID tag
374 * @v logdev Logical device ID
375 * @v logdevid Logical device ID structure to fill in
376 * @ret rc Return status code
378 static int isapnp_find_logdevid ( unsigned int logdev
,
379 struct isapnp_logdevid
*logdevid
) {
383 for ( i
= 0 ; i
<= logdev
; i
++ ) {
384 if ( ( rc
= isapnp_find_tag ( ISAPNP_TAG_LOGDEVID
, logdevid
,
385 sizeof ( *logdevid
) ) ) != 0 )
392 * Try isolating ISAPnP cards at the current read port.
394 * @ret \>0 Number of ISAPnP cards found
395 * @ret 0 There are no ISAPnP cards in the system
396 * @ret \<0 A conflict was detected; try a new read port
399 * The state diagram on page 18 (PDF page 24) of the PnP ISA spec
400 * gives the best overview of what happens here.
402 static int isapnp_try_isolate ( void ) {
403 struct isapnp_identifier identifier
;
405 unsigned int seen_55aa
, seen_life
;
406 unsigned int csn
= 0;
410 DBG ( "ISAPnP attempting isolation at read port %04x\n",
413 /* Place all cards into the Sleep state, whatever state
414 * they're currently in.
416 isapnp_wait_for_key();
419 /* Reset all assigned CSNs */
424 /* Place all cards into the Isolation state */
425 isapnp_wait_for_key ();
427 isapnp_wake ( 0x00 );
429 /* Set the read port */
430 isapnp_set_read_port();
435 /* All cards that do not have assigned CSNs are
436 * currently in the Isolation state, each time we go
440 /* Initiate serial isolation */
441 isapnp_serialisolation();
444 /* Read identifier serially via the ISAPnP read port. */
445 memset ( &identifier
, 0, sizeof ( identifier
) );
446 seen_55aa
= seen_life
= 0;
447 for ( i
= 0 ; i
< 9 ; i
++ ) {
449 for ( j
= 0 ; j
< 8 ; j
++ ) {
450 data
= isapnp_read_data();
452 data
= ( ( data
<< 8 ) | isapnp_read_data() );
455 if ( data
!= 0xffff ) {
457 if ( data
== 0x55aa ) {
463 *( ( ( uint8_t * ) &identifier
) + i
) = byte
;
466 /* If we didn't see any 55aa patterns, stop here */
469 DBG ( "ISAPnP found no more cards\n" );
472 DBG ( "ISAPnP saw life but no cards, "
473 "trying new read port\n" );
476 DBG ( "ISAPnP saw no signs of life, "
477 "abandoning isolation\n" );
483 /* If the checksum was invalid stop here */
484 if ( identifier
.checksum
!= isapnp_checksum ( &identifier
) ) {
485 DBG ( "ISAPnP found malformed card "
486 ISAPNP_CARD_ID_FMT
"\n with checksum %02x "
487 "(should be %02x), trying new read port\n",
488 ISAPNP_CARD_ID_DATA ( &identifier
),
490 isapnp_checksum ( &identifier
) );
495 /* Give the device a CSN */
497 DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT
498 ", assigning CSN %02x\n",
499 ISAPNP_CARD_ID_DATA ( &identifier
), csn
);
501 isapnp_write_csn ( csn
);
504 /* Send this card back to Sleep and force all cards
505 * without a CSN into Isolation state
507 isapnp_wake ( 0x00 );
511 /* Place all cards in Wait for Key state */
512 isapnp_wait_for_key();
514 /* Return number of cards found */
516 DBG ( "ISAPnP found %d cards at read port %04x\n",
517 csn
, isapnp_read_port
);
523 * Find a valid read port and isolate all ISAPnP cards.
526 static void isapnp_isolate ( void ) {
527 for ( isapnp_read_port
= ISAPNP_READ_PORT_START
;
528 isapnp_read_port
<= ISAPNP_READ_PORT_MAX
;
529 isapnp_read_port
+= ISAPNP_READ_PORT_STEP
) {
530 /* Avoid problematic locations such as the NE2000
533 if ( ( isapnp_read_port
>= 0x280 ) &&
534 ( isapnp_read_port
<= 0x380 ) )
537 /* If we detect any ISAPnP cards at this location, stop */
538 if ( isapnp_try_isolate() >= 0 )
544 * Activate or deactivate an ISAPnP device.
546 * @v isapnp ISAPnP device
547 * @v activation True to enable, False to disable the device
551 * This routine simply activates the device in its current
552 * configuration, or deactivates the device. It does not attempt any
553 * kind of resource arbitration.
556 void isapnp_device_activation ( struct isapnp_device
*isapnp
,
558 /* Wake the card and select the logical device */
559 isapnp_wait_for_key ();
561 isapnp_wake ( isapnp
->csn
);
562 isapnp_logicaldevice ( isapnp
->logdev
);
564 /* Activate/deactivate the logical device */
565 isapnp_activate ( activation
);
568 /* Return all cards to Wait for Key state */
569 isapnp_wait_for_key ();
571 DBG ( "ISAPnP %s device %02x:%02x\n",
572 ( activation
? "activated" : "deactivated" ),
573 isapnp
->csn
, isapnp
->logdev
);
577 * Probe an ISAPnP device
579 * @v isapnp ISAPnP device
580 * @ret rc Return status code
582 * Searches for a driver for the ISAPnP device. If a driver is found,
583 * its probe() routine is called.
585 static int isapnp_probe ( struct isapnp_device
*isapnp
) {
586 struct isapnp_driver
*driver
;
587 struct isapnp_device_id
*id
;
591 DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") "
592 "io %x irq %d)\n", isapnp
->csn
, isapnp
->logdev
,
593 isapnp
->vendor_id
, isapnp
->prod_id
,
594 isa_id_string ( isapnp
->vendor_id
, isapnp
->prod_id
),
595 isapnp
->ioaddr
, isapnp
->irqno
);
597 for ( driver
= isapnp_drivers
; driver
< isapnp_drivers_end
; driver
++ ){
598 for ( i
= 0 ; i
< driver
->id_count
; i
++ ) {
599 id
= &driver
->ids
[i
];
600 if ( id
->vendor_id
!= isapnp
->vendor_id
)
602 if ( ISA_PROD_ID ( id
->prod_id
) !=
603 ISA_PROD_ID ( isapnp
->prod_id
) )
605 isapnp
->driver
= driver
;
606 isapnp
->driver_name
= id
->name
;
607 DBG ( "...using driver %s\n", isapnp
->driver_name
);
608 if ( ( rc
= driver
->probe ( isapnp
, id
) ) != 0 ) {
609 DBG ( "......probe failed\n" );
616 DBG ( "...no driver found\n" );
621 * Remove an ISAPnP device
623 * @v isapnp ISAPnP device
625 static void isapnp_remove ( struct isapnp_device
*isapnp
) {
626 isapnp
->driver
->remove ( isapnp
);
627 DBG ( "Removed ISAPnP device %02x:%02x\n",
628 isapnp
->csn
, isapnp
->logdev
);
632 * Probe ISAPnP root bus
634 * @v rootdev ISAPnP bus root device
636 * Scans the ISAPnP bus for devices and registers all devices it can
639 static int isapnpbus_probe ( struct root_device
*rootdev
) {
640 struct isapnp_device
*isapnp
= NULL
;
641 struct isapnp_identifier identifier
;
642 struct isapnp_logdevid logdevid
;
647 /* Perform isolation if it hasn't yet been done */
648 if ( ! isapnp_read_port
)
651 for ( csn
= 1 ; csn
<= 0xff ; csn
++ ) {
652 for ( logdev
= 0 ; logdev
<= 0xff ; logdev
++ ) {
654 /* Allocate struct isapnp_device */
656 isapnp
= malloc ( sizeof ( *isapnp
) );
661 memset ( isapnp
, 0, sizeof ( *isapnp
) );
663 isapnp
->logdev
= logdev
;
666 isapnp_wait_for_key();
670 /* Read the card identifier */
671 isapnp_peek ( &identifier
, sizeof ( identifier
) );
673 /* No card with this CSN; stop here */
674 if ( identifier
.vendor_id
& 0x80 )
677 /* Find the Logical Device ID tag */
678 if ( ( rc
= isapnp_find_logdevid ( logdev
,
680 /* No more logical devices; go to next CSN */
684 /* Select the logical device */
685 isapnp_logicaldevice ( logdev
);
687 /* Populate struct isapnp_device */
688 isapnp
->vendor_id
= logdevid
.vendor_id
;
689 isapnp
->prod_id
= logdevid
.prod_id
;
690 isapnp
->ioaddr
= isapnp_read_iobase ( 0 );
691 isapnp
->irqno
= isapnp_read_irqno ( 0 );
693 /* Return all cards to Wait for Key state */
694 isapnp_wait_for_key();
696 /* Add to device hierarchy */
697 snprintf ( isapnp
->dev
.name
,
698 sizeof ( isapnp
->dev
.name
),
699 "ISAPnP%02x:%02x", csn
, logdev
);
700 isapnp
->dev
.desc
.bus_type
= BUS_TYPE_ISAPNP
;
701 isapnp
->dev
.desc
.vendor
= isapnp
->vendor_id
;
702 isapnp
->dev
.desc
.device
= isapnp
->prod_id
;
703 isapnp
->dev
.desc
.ioaddr
= isapnp
->ioaddr
;
704 isapnp
->dev
.desc
.irq
= isapnp
->irqno
;
705 isapnp
->dev
.parent
= &rootdev
->dev
;
706 list_add ( &isapnp
->dev
.siblings
,
707 &rootdev
->dev
.children
);
708 INIT_LIST_HEAD ( &isapnp
->dev
.children
);
710 /* Look for a driver */
711 if ( isapnp_probe ( isapnp
) == 0 ) {
712 /* isapnpdev registered, we can drop our ref */
715 /* Not registered; re-use struct */
716 list_del ( &isapnp
->dev
.siblings
);
727 isapnpbus_remove ( rootdev
);
732 * Remove ISAPnP root bus
734 * @v rootdev ISAPnP bus root device
736 static void isapnpbus_remove ( struct root_device
*rootdev
) {
737 struct isapnp_device
*isapnp
;
738 struct isapnp_device
*tmp
;
740 list_for_each_entry_safe ( isapnp
, tmp
, &rootdev
->dev
.children
,
742 isapnp_remove ( isapnp
);
743 list_del ( &isapnp
->dev
.siblings
);
748 /** ISAPnP bus root device driver */
749 static struct root_driver isapnp_root_driver
= {
750 .probe
= isapnpbus_probe
,
751 .remove
= isapnpbus_remove
,
754 /** ISAPnP bus root device */
755 struct root_device isapnp_root_device __root_device
= {
756 .dev
= { .name
= "ISAPnP" },
757 .driver
= &isapnp_root_driver
,