[sundance] Add reset completion check
[gpxe.git] / src / drivers / bus / isapnp.c
blob8f812df8e86dc769344c2fcd4d133a8ddb07dede
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)
24 * REVISION HISTORY:
25 * ================
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 ***************************************************************************/
36 /** @file
38 * ISAPnP bus support
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.
58 #include <stdint.h>
59 #include <stdlib.h>
60 #include <string.h>
61 #include <stdio.h>
62 #include <errno.h>
63 #include <gpxe/io.h>
64 #include <unistd.h>
65 #include <gpxe/isapnp.h>
67 /**
68 * ISAPnP Read Port address.
70 * ROM prefix may be able to set this address, which is why this is
71 * non-static.
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 ), \
91 (identifier)->serial
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
135 * command.
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
145 * state.
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
155 * command.
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
165 * @ret None -
166 * @err None -
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
192 * completes.
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 ) {
221 udelay ( 1000 );
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;
244 return lfsr_next;
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 ) {
254 unsigned int i;
255 unsigned int lfsr;
257 isapnp_delay();
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 ) {
275 unsigned int i, j;
276 unsigned int lfsr;
277 unsigned int byte;
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 );
284 byte >>= 1;
287 return lfsr;
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 ) {
296 unsigned int i;
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();
304 isapnp_delay();
306 /* Data never became ready - return 0xff */
307 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 ) {
320 unsigned int i;
321 unsigned int byte;
323 for ( i = 0 ; i < len ; i++) {
324 byte = isapnp_peek_byte();
325 if ( buf )
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 ) {
342 unsigned int tag;
343 unsigned int tag_len;
345 DBG2 ( "ISAPnP read tag" );
346 do {
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 );
351 } else {
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 ) {
358 if ( len > tag_len )
359 len = tag_len;
360 isapnp_peek ( buf, len );
361 DBG2 ( "\n" );
362 return 0;
363 } else {
364 isapnp_peek ( NULL, tag_len );
366 } while ( tag != ISAPNP_TAG_END );
367 DBG2 ( "\n" );
368 return -ENOENT;
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 ) {
380 unsigned int i;
381 int rc;
383 for ( i = 0 ; i <= logdev ; i++ ) {
384 if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid,
385 sizeof ( *logdevid ) ) ) != 0 )
386 return rc;
388 return 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
397 * @err None -
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;
404 unsigned int i, j;
405 unsigned int seen_55aa, seen_life;
406 unsigned int csn = 0;
407 unsigned int data;
408 unsigned int byte;
410 DBG ( "ISAPnP attempting isolation at read port %04x\n",
411 isapnp_read_port );
413 /* Place all cards into the Sleep state, whatever state
414 * they're currently in.
416 isapnp_wait_for_key();
417 isapnp_send_key();
419 /* Reset all assigned CSNs */
420 isapnp_reset_csn();
421 isapnp_delay();
422 isapnp_delay();
424 /* Place all cards into the Isolation state */
425 isapnp_wait_for_key ();
426 isapnp_send_key();
427 isapnp_wake ( 0x00 );
429 /* Set the read port */
430 isapnp_set_read_port();
431 isapnp_delay();
433 while ( 1 ) {
435 /* All cards that do not have assigned CSNs are
436 * currently in the Isolation state, each time we go
437 * through this loop.
440 /* Initiate serial isolation */
441 isapnp_serialisolation();
442 isapnp_delay();
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++ ) {
448 byte = 0;
449 for ( j = 0 ; j < 8 ; j++ ) {
450 data = isapnp_read_data();
451 isapnp_delay();
452 data = ( ( data << 8 ) | isapnp_read_data() );
453 isapnp_delay();
454 byte >>= 1;
455 if ( data != 0xffff ) {
456 seen_life++;
457 if ( data == 0x55aa ) {
458 byte |= 0x80;
459 seen_55aa++;
463 *( ( ( uint8_t * ) &identifier ) + i ) = byte;
466 /* If we didn't see any 55aa patterns, stop here */
467 if ( ! seen_55aa ) {
468 if ( csn ) {
469 DBG ( "ISAPnP found no more cards\n" );
470 } else {
471 if ( seen_life ) {
472 DBG ( "ISAPnP saw life but no cards, "
473 "trying new read port\n" );
474 csn = -1;
475 } else {
476 DBG ( "ISAPnP saw no signs of life, "
477 "abandoning isolation\n" );
480 break;
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 ),
489 identifier.checksum,
490 isapnp_checksum ( &identifier) );
491 csn = -1;
492 break;
495 /* Give the device a CSN */
496 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 );
502 isapnp_delay();
504 /* Send this card back to Sleep and force all cards
505 * without a CSN into Isolation state
507 isapnp_wake ( 0x00 );
508 isapnp_delay();
511 /* Place all cards in Wait for Key state */
512 isapnp_wait_for_key();
514 /* Return number of cards found */
515 if ( csn > 0 ) {
516 DBG ( "ISAPnP found %d cards at read port %04x\n",
517 csn, isapnp_read_port );
519 return csn;
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
531 * probe space
533 if ( ( isapnp_read_port >= 0x280 ) &&
534 ( isapnp_read_port <= 0x380 ) )
535 continue;
537 /* If we detect any ISAPnP cards at this location, stop */
538 if ( isapnp_try_isolate() >= 0 )
539 return;
544 * Activate or deactivate an ISAPnP device.
546 * @v isapnp ISAPnP device
547 * @v activation True to enable, False to disable the device
548 * @ret None -
549 * @err None -
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,
557 int activation ) {
558 /* Wake the card and select the logical device */
559 isapnp_wait_for_key ();
560 isapnp_send_key ();
561 isapnp_wake ( isapnp->csn );
562 isapnp_logicaldevice ( isapnp->logdev );
564 /* Activate/deactivate the logical device */
565 isapnp_activate ( activation );
566 isapnp_delay();
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;
588 unsigned int i;
589 int rc;
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 )
601 continue;
602 if ( ISA_PROD_ID ( id->prod_id ) !=
603 ISA_PROD_ID ( isapnp->prod_id ) )
604 continue;
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" );
610 continue;
612 return 0;
616 DBG ( "...no driver found\n" );
617 return -ENOTTY;
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
637 * find.
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;
643 unsigned int csn;
644 unsigned int logdev;
645 int rc;
647 /* Perform isolation if it hasn't yet been done */
648 if ( ! isapnp_read_port )
649 isapnp_isolate();
651 for ( csn = 1 ; csn <= 0xff ; csn++ ) {
652 for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) {
654 /* Allocate struct isapnp_device */
655 if ( ! isapnp )
656 isapnp = malloc ( sizeof ( *isapnp ) );
657 if ( ! isapnp ) {
658 rc = -ENOMEM;
659 goto err;
661 memset ( isapnp, 0, sizeof ( *isapnp ) );
662 isapnp->csn = csn;
663 isapnp->logdev = logdev;
665 /* Wake the card */
666 isapnp_wait_for_key();
667 isapnp_send_key();
668 isapnp_wake ( csn );
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 )
675 goto done;
677 /* Find the Logical Device ID tag */
678 if ( ( rc = isapnp_find_logdevid ( logdev,
679 &logdevid ) ) != 0){
680 /* No more logical devices; go to next CSN */
681 break;
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 */
713 isapnp = NULL;
714 } else {
715 /* Not registered; re-use struct */
716 list_del ( &isapnp->dev.siblings );
721 done:
722 free ( isapnp );
723 return 0;
725 err:
726 free ( isapnp );
727 isapnpbus_remove ( rootdev );
728 return rc;
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,
741 dev.siblings ) {
742 isapnp_remove ( isapnp );
743 list_del ( &isapnp->dev.siblings );
744 free ( isapnp );
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,