isapnp.c File Reference

ISAPnP bus support. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <gpxe/io.h>
#include <unistd.h>
#include <gpxe/isapnp.h>

Go to the source code of this file.

Defines

#define ISAPNP_CARD_ID_FMT   "ID %04x:%04x (\"%s\") serial %x"
#define ISAPNP_CARD_ID_DATA(identifier)
#define ISAPNP_DEV_ID_FMT   "ID %04x:%04x (\"%s\")"
#define ISAPNP_DEV_ID_DATA(isapnp)

Functions

 FILE_LICENCE (GPL2_OR_LATER)
static void isapnpbus_remove (struct root_device *rootdev)
 Remove ISAPnP root bus.
static void isapnp_write_address (unsigned int address)
static void isapnp_write_data (unsigned int data)
static unsigned int isapnp_read_data (void)
static void isapnp_write_byte (unsigned int address, unsigned int value)
static unsigned int isapnp_read_byte (unsigned int address)
static unsigned int isapnp_read_word (unsigned int address)
static void isapnp_set_read_port (void)
 Inform cards of a new read port address.
static void isapnp_serialisolation (void)
 Enter the Isolation state.
static void isapnp_wait_for_key (void)
 Enter the Wait for Key state.
static void isapnp_reset_csn (void)
 Reset (i.e.
static void isapnp_wake (uint8_t csn)
 Place a specified card into the Config state.
static unsigned int isapnp_read_resourcedata (void)
static unsigned int isapnp_read_status (void)
static void isapnp_write_csn (unsigned int csn)
 Assign a Card Select Number to a card, and enter the Config state.
static void isapnp_logicaldevice (unsigned int logdev)
static void isapnp_activate (unsigned int logdev)
static void isapnp_deactivate (unsigned int logdev)
static unsigned int isapnp_read_iobase (unsigned int index)
static unsigned int isapnp_read_irqno (unsigned int index)
static void isapnp_delay (void)
static unsigned int isapnp_lfsr_next (unsigned int lfsr, unsigned int input_bit)
 Linear feedback shift register.
static void isapnp_send_key (void)
 Send the ISAPnP initiation key.
static unsigned int isapnp_checksum (struct isapnp_identifier *identifier)
 Compute ISAPnP identifier checksum.
static unsigned int isapnp_peek_byte (void)
static void isapnp_peek (void *buf, size_t len)
 Read resource data.
static int isapnp_find_tag (unsigned int wanted_tag, void *buf, size_t len)
 Find a tag within the resource data.
static int isapnp_find_logdevid (unsigned int logdev, struct isapnp_logdevid *logdevid)
 Find specified Logical Device ID tag.
static int isapnp_try_isolate (void)
 Try isolating ISAPnP cards at the current read port.
static void isapnp_isolate (void)
 Find a valid read port and isolate all ISAPnP cards.
void isapnp_device_activation (struct isapnp_device *isapnp, int activation)
 Activate or deactivate an ISAPnP device.
static int isapnp_probe (struct isapnp_device *isapnp)
 Probe an ISAPnP device.
static void isapnp_remove (struct isapnp_device *isapnp)
 Remove an ISAPnP device.
static int isapnpbus_probe (struct root_device *rootdev)
 Probe ISAPnP root bus.

Variables

uint16_t isapnp_read_port
 ISAPnP Read Port address.
static struct root_driver isapnp_root_driver
 ISAPnP bus root device driver.
struct root_device
isapnp_root_device 
__root_device
 ISAPnP bus root device.


Detailed Description

ISAPnP bus support.

Etherboot orignally gained ISAPnP support in a very limited way for the 3c515 NIC. The current implementation is almost a complete rewrite based on the ISAPnP specification, with passing reference to the Linux ISAPnP code.

There can be only one ISAPnP bus in a system. Once the read port is known and all cards have been allocated CSNs, there's nothing to be gained by re-scanning for cards.

External code (e.g. the ISAPnP ROM prefix) may already know the read port address, in which case it can store it in isapnp_read_port. Note that setting the read port address in this way will prevent further isolation from taking place; you should set the read port address only if you know that devices have already been allocated CSNs.

Definition in file isapnp.c.


Define Documentation

#define ISAPNP_CARD_ID_FMT   "ID %04x:%04x (\"%s\") serial %x"

Definition at line 84 of file isapnp.c.

Referenced by isapnp_try_isolate().

#define ISAPNP_CARD_ID_DATA ( identifier   ) 

Value:

(identifier)->vendor_id, (identifier)->prod_id,                   \
        isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
        (identifier)->serial

Definition at line 85 of file isapnp.c.

Referenced by isapnp_try_isolate().

#define ISAPNP_DEV_ID_FMT   "ID %04x:%04x (\"%s\")"

Definition at line 89 of file isapnp.c.

#define ISAPNP_DEV_ID_DATA ( isapnp   ) 

Value:

(isapnp)->vendor_id, (isapnp)->prod_id,                           \
        isa_id_string ( (isapnp)->vendor_id, (isapnp)->prod_id )

Definition at line 90 of file isapnp.c.


Function Documentation

FILE_LICENCE ( GPL2_OR_LATER   ) 

static void isapnpbus_remove ( struct root_device rootdev  )  [static]

Remove ISAPnP root bus.

Parameters:
rootdev ISAPnP bus root device

Definition at line 733 of file isapnp.c.

References device::children, isapnp_device::dev, root_device::dev, free(), isapnp_remove(), list_del, list_for_each_entry_safe, and device::siblings.

Referenced by isapnpbus_probe().

00733                                                              {
00734         struct isapnp_device *isapnp;
00735         struct isapnp_device *tmp;
00736 
00737         list_for_each_entry_safe ( isapnp, tmp, &rootdev->dev.children,
00738                                    dev.siblings ) {
00739                 isapnp_remove ( isapnp );
00740                 list_del ( &isapnp->dev.siblings );
00741                 free ( isapnp );
00742         }
00743 }

static void isapnp_write_address ( unsigned int  address  )  [inline, static]

Definition at line 94 of file isapnp.c.

References ISAPNP_ADDRESS, and outb.

Referenced by isapnp_read_byte(), isapnp_send_key(), isapnp_serialisolation(), and isapnp_write_byte().

00094                                                                  {
00095         outb ( address, ISAPNP_ADDRESS );
00096 }

static void isapnp_write_data ( unsigned int  data  )  [inline, static]

Definition at line 98 of file isapnp.c.

References ISAPNP_WRITE_DATA, and outb.

Referenced by isapnp_write_byte().

00098                                                            {
00099         outb ( data, ISAPNP_WRITE_DATA );
00100 }

static unsigned int isapnp_read_data ( void   )  [inline, static]

Definition at line 102 of file isapnp.c.

References inb, and isapnp_read_port.

Referenced by isapnp_read_byte(), and isapnp_try_isolate().

00102                                                      {
00103         return inb ( isapnp_read_port );
00104 }

static void isapnp_write_byte ( unsigned int  address,
unsigned int  value 
) [inline, static]

static unsigned int isapnp_read_byte ( unsigned int  address  )  [inline, static]

Definition at line 112 of file isapnp.c.

References isapnp_read_data(), and isapnp_write_address().

Referenced by isapnp_read_irqno(), isapnp_read_resourcedata(), isapnp_read_status(), and isapnp_read_word().

00112                                                                      {
00113         isapnp_write_address ( address );
00114         return isapnp_read_data ();
00115 }

static unsigned int isapnp_read_word ( unsigned int  address  )  [inline, static]

Definition at line 117 of file isapnp.c.

References isapnp_read_byte().

Referenced by isapnp_read_iobase().

00117                                                                      {
00118         /* Yes, they're in big-endian order */
00119         return ( ( isapnp_read_byte ( address ) << 8 )
00120                  | isapnp_read_byte ( address + 1 ) );
00121 }

static void isapnp_set_read_port ( void   )  [inline, static]

Inform cards of a new read port address.

Definition at line 124 of file isapnp.c.

References isapnp_read_port, ISAPNP_READPORT, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

00124                                                  {
00125         isapnp_write_byte ( ISAPNP_READPORT, ( isapnp_read_port >> 2 ) );
00126 }

static void isapnp_serialisolation ( void   )  [inline, static]

Enter the Isolation state.

Only cards currently in the Sleep state will respond to this command.

Definition at line 134 of file isapnp.c.

References ISAPNP_SERIALISOLATION, and isapnp_write_address().

Referenced by isapnp_try_isolate().

00134                                                    {
00135         isapnp_write_address ( ISAPNP_SERIALISOLATION );
00136 }

static void isapnp_wait_for_key ( void   )  [inline, static]

Enter the Wait for Key state.

All cards will respond to this command, regardless of their current state.

Definition at line 144 of file isapnp.c.

References ISAPNP_CONFIG_WAIT_FOR_KEY, ISAPNP_CONFIGCONTROL, and isapnp_write_byte().

Referenced by isapnp_device_activation(), isapnp_try_isolate(), and isapnpbus_probe().

static void isapnp_reset_csn ( void   )  [inline, static]

Reset (i.e.

remove) Card Select Number.

Only cards currently in the Sleep state will respond to this command.

Definition at line 154 of file isapnp.c.

References ISAPNP_CONFIG_RESET_CSN, ISAPNP_CONFIGCONTROL, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

static void isapnp_wake ( uint8_t  csn  )  [inline, static]

Place a specified card into the Config state.

Parameters:
csn Card Select Number
Return values:
None -
Exceptions:
None -
Only cards currently in the Sleep, Isolation, or Config states will respond to this command. The card that has the specified CSN will enter the Config state, all other cards will enter the Sleep state.

Definition at line 169 of file isapnp.c.

References ISAPNP_WAKE, and isapnp_write_byte().

Referenced by isapnp_device_activation(), isapnp_try_isolate(), and isapnpbus_probe().

00169                                                {
00170         isapnp_write_byte ( ISAPNP_WAKE, csn );
00171 }

static unsigned int isapnp_read_resourcedata ( void   )  [inline, static]

Definition at line 173 of file isapnp.c.

References isapnp_read_byte(), and ISAPNP_RESOURCEDATA.

Referenced by isapnp_peek_byte().

00173                                                              {
00174         return isapnp_read_byte ( ISAPNP_RESOURCEDATA );
00175 }

static unsigned int isapnp_read_status ( void   )  [inline, static]

Definition at line 177 of file isapnp.c.

References isapnp_read_byte(), and ISAPNP_STATUS.

Referenced by isapnp_peek_byte().

00177                                                        {
00178         return isapnp_read_byte ( ISAPNP_STATUS );
00179 }

static void isapnp_write_csn ( unsigned int  csn  )  [inline, static]

Assign a Card Select Number to a card, and enter the Config state.

Parameters:
csn Card Select Number
Only cards in the Isolation state will respond to this command. The isolation protocol is designed so that only one card will remain in the Isolation state by the time the isolation protocol completes.

Definition at line 191 of file isapnp.c.

References ISAPNP_CARDSELECTNUMBER, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

00191                                                          {
00192         isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
00193 }

static void isapnp_logicaldevice ( unsigned int  logdev  )  [inline, static]

static void isapnp_activate ( unsigned int  logdev  )  [inline, static]

Definition at line 199 of file isapnp.c.

References ISAPNP_ACTIVATE, isapnp_logicaldevice(), and isapnp_write_byte().

Referenced by isapnp_device_activation().

00199                                                            {
00200         isapnp_logicaldevice ( logdev );
00201         isapnp_write_byte ( ISAPNP_ACTIVATE, 1 );
00202 }

static void isapnp_deactivate ( unsigned int  logdev  )  [inline, static]

Definition at line 204 of file isapnp.c.

References ISAPNP_ACTIVATE, isapnp_logicaldevice(), and isapnp_write_byte().

00204                                                              {
00205         isapnp_logicaldevice ( logdev );
00206         isapnp_write_byte ( ISAPNP_ACTIVATE, 0 );
00207 }

static unsigned int isapnp_read_iobase ( unsigned int  index  )  [inline, static]

Definition at line 209 of file isapnp.c.

References ISAPNP_IOBASE, and isapnp_read_word().

Referenced by isapnpbus_probe().

00209                                                                      {
00210         return isapnp_read_word ( ISAPNP_IOBASE ( index ) );
00211 }

static unsigned int isapnp_read_irqno ( unsigned int  index  )  [inline, static]

Definition at line 213 of file isapnp.c.

References ISAPNP_IRQNO, and isapnp_read_byte().

Referenced by isapnpbus_probe().

00213                                                                     {
00214         return isapnp_read_byte ( ISAPNP_IRQNO ( index ) );
00215 }

static void isapnp_delay ( void   )  [static]

Definition at line 217 of file isapnp.c.

References udelay().

Referenced by isapnp_device_activation(), isapnp_peek_byte(), isapnp_send_key(), and isapnp_try_isolate().

00217                                   {
00218         udelay ( 1000 );
00219 }

static unsigned int isapnp_lfsr_next ( unsigned int  lfsr,
unsigned int  input_bit 
) [inline, static]

Linear feedback shift register.

Parameters:
lfsr Current value of the LFSR
input_bit Current input bit to the LFSR
Return values:
lfsr Next value of the LFSR
This routine implements the linear feedback shift register as described in Appendix B of the PnP ISA spec. The hardware implementation uses eight D-type latches and two XOR gates. I think this is probably the smallest possible implementation in software. Six instructions when input_bit is a constant 0 (for isapnp_send_key). :)

Definition at line 235 of file isapnp.c.

Referenced by isapnp_checksum(), and isapnp_send_key().

00236                                                                        {
00237         register uint8_t lfsr_next;
00238 
00239         lfsr_next = lfsr >> 1;
00240         lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
00241         return lfsr_next;
00242 }

static void isapnp_send_key ( void   )  [static]

Send the ISAPnP initiation key.

Sending the key causes all ISAPnP cards that are currently in the Wait for Key state to transition into the Sleep state.

Definition at line 250 of file isapnp.c.

References isapnp_delay(), isapnp_lfsr_next(), ISAPNP_LFSR_SEED, and isapnp_write_address().

Referenced by isapnp_device_activation(), isapnp_try_isolate(), and isapnpbus_probe().

00250                                      {
00251         unsigned int i;
00252         unsigned int lfsr;
00253 
00254         isapnp_delay();
00255         isapnp_write_address ( 0x00 );
00256         isapnp_write_address ( 0x00 );
00257 
00258         lfsr = ISAPNP_LFSR_SEED;
00259         for ( i = 0 ; i < 32 ; i++ ) {
00260                 isapnp_write_address ( lfsr );
00261                 lfsr = isapnp_lfsr_next ( lfsr, 0 );
00262         }
00263 }

static unsigned int isapnp_checksum ( struct isapnp_identifier identifier  )  [static]

Compute ISAPnP identifier checksum.

Parameters:
identifier ISAPnP identifier
Return values:
checksum Expected checksum value

Definition at line 271 of file isapnp.c.

References isapnp_lfsr_next(), and ISAPNP_LFSR_SEED.

Referenced by isapnp_try_isolate().

00271                                                                              {
00272         unsigned int i, j;
00273         unsigned int lfsr;
00274         unsigned int byte;
00275 
00276         lfsr = ISAPNP_LFSR_SEED;
00277         for ( i = 0 ; i < 8 ; i++ ) {
00278                 byte = * ( ( ( uint8_t * ) identifier ) + i );
00279                 for ( j = 0 ; j < 8 ; j++ ) {
00280                         lfsr = isapnp_lfsr_next ( lfsr, byte );
00281                         byte >>= 1;
00282                 }
00283         }
00284         return lfsr;
00285 }

static unsigned int isapnp_peek_byte ( void   )  [inline, static]

Definition at line 292 of file isapnp.c.

References isapnp_delay(), isapnp_read_resourcedata(), and isapnp_read_status().

Referenced by isapnp_find_tag(), and isapnp_peek().

00292                                                      {
00293         unsigned int i;
00294 
00295         /* Wait for data to be ready */
00296         for ( i = 0 ; i < 20 ; i++ ) {
00297                 if ( isapnp_read_status() & 0x01 ) {
00298                         /* Byte ready - read it */
00299                         return isapnp_read_resourcedata();
00300                 }
00301                 isapnp_delay();
00302         }
00303         /* Data never became ready - return 0xff */
00304         return 0xff;
00305 }

static void isapnp_peek ( void *  buf,
size_t  len 
) [static]

Read resource data.

Parameters:
buf Buffer in which to store data, or NULL
bytes Number of bytes to read
Resource data is read from the current location. If buf is NULL, the data is discarded.

Definition at line 316 of file isapnp.c.

References isapnp_peek_byte().

Referenced by isapnp_find_tag(), and isapnpbus_probe().

00316                                                   {
00317         unsigned int i;
00318         unsigned int byte;
00319 
00320         for ( i = 0 ; i < len ; i++) {
00321                 byte = isapnp_peek_byte();
00322                 if ( buf )
00323                         * ( ( uint8_t * ) buf + i ) = byte;
00324         }
00325 }

static int isapnp_find_tag ( unsigned int  wanted_tag,
void *  buf,
size_t  len 
) [static]

Find a tag within the resource data.

Parameters:
wanted_tag The tag that we're looking for
buf Buffer in which to store the tag's contents
len Length of buffer
Return values:
rc Return status code
Scan through the resource data until we find a particular tag, and read its contents into a buffer.

Definition at line 338 of file isapnp.c.

References DBG2, ENOENT, ISAPNP_IS_SMALL_TAG, ISAPNP_LARGE_TAG_NAME, isapnp_peek(), isapnp_peek_byte(), ISAPNP_SMALL_TAG_LEN, ISAPNP_SMALL_TAG_NAME, ISAPNP_TAG_END, and NULL.

Referenced by isapnp_find_logdevid().

00338                                                                               {
00339         unsigned int tag;
00340         unsigned int tag_len;
00341 
00342         DBG2 ( "ISAPnP read tag" );
00343         do {
00344                 tag = isapnp_peek_byte();
00345                 if ( ISAPNP_IS_SMALL_TAG ( tag ) ) {
00346                         tag_len = ISAPNP_SMALL_TAG_LEN ( tag );
00347                         tag = ISAPNP_SMALL_TAG_NAME ( tag );
00348                 } else {
00349                         tag_len = ( isapnp_peek_byte() +
00350                                     ( isapnp_peek_byte() << 8 ) );
00351                         tag = ISAPNP_LARGE_TAG_NAME ( tag );
00352                 }
00353                 DBG2 ( " %02x (%02x)", tag, tag_len );
00354                 if ( tag == wanted_tag ) {
00355                         if ( len > tag_len )
00356                                 len = tag_len;
00357                         isapnp_peek ( buf, len );
00358                         DBG2 ( "\n" );
00359                         return 0;
00360                 } else {
00361                         isapnp_peek ( NULL, tag_len );
00362                 }
00363         } while ( tag != ISAPNP_TAG_END );
00364         DBG2 ( "\n" );
00365         return -ENOENT;
00366 }

static int isapnp_find_logdevid ( unsigned int  logdev,
struct isapnp_logdevid logdevid 
) [static]

Find specified Logical Device ID tag.

Parameters:
logdev Logical device ID
logdevid Logical device ID structure to fill in
Return values:
rc Return status code

Definition at line 375 of file isapnp.c.

References isapnp_find_tag(), and ISAPNP_TAG_LOGDEVID.

Referenced by isapnpbus_probe().

00376                                                                      {
00377         unsigned int i;
00378         int rc;
00379 
00380         for ( i = 0 ; i <= logdev ; i++ ) {
00381                 if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid,
00382                                               sizeof ( *logdevid ) ) ) != 0 )
00383                         return rc;
00384         }
00385         return 0;
00386 }

static int isapnp_try_isolate ( void   )  [static]

Try isolating ISAPnP cards at the current read port.

Return values:
\>0 Number of ISAPnP cards found
0 There are no ISAPnP cards in the system
\<0 A conflict was detected; try a new read port
Exceptions:
None -
The state diagram on page 18 (PDF page 24) of the PnP ISA spec gives the best overview of what happens here.

Definition at line 399 of file isapnp.c.

References isapnp_identifier::checksum, DBG, ISAPNP_CARD_ID_DATA, ISAPNP_CARD_ID_FMT, isapnp_checksum(), isapnp_delay(), isapnp_read_data(), isapnp_read_port, isapnp_reset_csn(), isapnp_send_key(), isapnp_serialisolation(), isapnp_set_read_port(), isapnp_wait_for_key(), isapnp_wake(), isapnp_write_csn(), and memset().

Referenced by isapnp_isolate().

00399                                        {
00400         struct isapnp_identifier identifier;
00401         unsigned int i, j;
00402         unsigned int seen_55aa, seen_life;
00403         unsigned int csn = 0;
00404         unsigned int data;
00405         unsigned int byte;
00406 
00407         DBG ( "ISAPnP attempting isolation at read port %04x\n",
00408               isapnp_read_port );
00409 
00410         /* Place all cards into the Sleep state, whatever state
00411          * they're currently in.
00412          */
00413         isapnp_wait_for_key();
00414         isapnp_send_key();
00415 
00416         /* Reset all assigned CSNs */
00417         isapnp_reset_csn();
00418         isapnp_delay();
00419         isapnp_delay();
00420         
00421         /* Place all cards into the Isolation state */
00422         isapnp_wait_for_key ();
00423         isapnp_send_key();
00424         isapnp_wake ( 0x00 );
00425         
00426         /* Set the read port */
00427         isapnp_set_read_port();
00428         isapnp_delay();
00429 
00430         while ( 1 ) {
00431 
00432                 /* All cards that do not have assigned CSNs are
00433                  * currently in the Isolation state, each time we go
00434                  * through this loop.
00435                  */
00436 
00437                 /* Initiate serial isolation */
00438                 isapnp_serialisolation();
00439                 isapnp_delay();
00440 
00441                 /* Read identifier serially via the ISAPnP read port. */
00442                 memset ( &identifier, 0, sizeof ( identifier ) );
00443                 seen_55aa = seen_life = 0;
00444                 for ( i = 0 ; i < 9 ; i++ ) {
00445                         byte = 0;
00446                         for ( j = 0 ; j < 8 ; j++ ) {
00447                                 data = isapnp_read_data();
00448                                 isapnp_delay();
00449                                 data = ( ( data << 8 ) | isapnp_read_data() );
00450                                 isapnp_delay();
00451                                 byte >>= 1;
00452                                 if (  data != 0xffff ) {
00453                                         seen_life++;
00454                                         if ( data == 0x55aa ) {
00455                                                 byte |= 0x80;
00456                                                 seen_55aa++;
00457                                         }
00458                                 }
00459                         }
00460                         *( ( ( uint8_t * ) &identifier ) + i ) = byte;
00461                 }
00462 
00463                 /* If we didn't see any 55aa patterns, stop here */
00464                 if ( ! seen_55aa ) {
00465                         if ( csn ) {
00466                                 DBG ( "ISAPnP found no more cards\n" );
00467                         } else {
00468                                 if ( seen_life ) {
00469                                         DBG ( "ISAPnP saw life but no cards, "
00470                                               "trying new read port\n" );
00471                                         csn = -1;
00472                                 } else {
00473                                         DBG ( "ISAPnP saw no signs of life, "
00474                                               "abandoning isolation\n" );
00475                                 }
00476                         }
00477                         break;
00478                 }
00479 
00480                 /* If the checksum was invalid stop here */
00481                 if ( identifier.checksum != isapnp_checksum ( &identifier) ) {
00482                         DBG ( "ISAPnP found malformed card "
00483                               ISAPNP_CARD_ID_FMT "\n  with checksum %02x "
00484                               "(should be %02x), trying new read port\n",
00485                               ISAPNP_CARD_ID_DATA ( &identifier ),
00486                               identifier.checksum,
00487                               isapnp_checksum ( &identifier) );
00488                         csn = -1;
00489                         break;
00490                 }
00491 
00492                 /* Give the device a CSN */
00493                 csn++;
00494                 DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT
00495                       ", assigning CSN %02x\n",
00496                       ISAPNP_CARD_ID_DATA ( &identifier ), csn );
00497                 
00498                 isapnp_write_csn ( csn );
00499                 isapnp_delay();
00500 
00501                 /* Send this card back to Sleep and force all cards
00502                  * without a CSN into Isolation state
00503                  */
00504                 isapnp_wake ( 0x00 );
00505                 isapnp_delay();
00506         }
00507 
00508         /* Place all cards in Wait for Key state */
00509         isapnp_wait_for_key();
00510 
00511         /* Return number of cards found */
00512         if ( csn > 0 ) {
00513                 DBG ( "ISAPnP found %d cards at read port %04x\n",
00514                       csn, isapnp_read_port );
00515         }
00516         return csn;
00517 }

static void isapnp_isolate ( void   )  [static]

Find a valid read port and isolate all ISAPnP cards.

Definition at line 523 of file isapnp.c.

References isapnp_read_port, ISAPNP_READ_PORT_MAX, ISAPNP_READ_PORT_START, ISAPNP_READ_PORT_STEP, and isapnp_try_isolate().

Referenced by isapnpbus_probe().

00523                                     {
00524         for ( isapnp_read_port = ISAPNP_READ_PORT_START ;
00525               isapnp_read_port <= ISAPNP_READ_PORT_MAX ;
00526               isapnp_read_port += ISAPNP_READ_PORT_STEP ) {
00527                 /* Avoid problematic locations such as the NE2000
00528                  * probe space
00529                  */
00530                 if ( ( isapnp_read_port >= 0x280 ) &&
00531                      ( isapnp_read_port <= 0x380 ) )
00532                         continue;
00533                 
00534                 /* If we detect any ISAPnP cards at this location, stop */
00535                 if ( isapnp_try_isolate() >= 0 )
00536                         return;
00537         }
00538 }

void isapnp_device_activation ( struct isapnp_device isapnp,
int  activation 
)

Activate or deactivate an ISAPnP device.

Parameters:
isapnp ISAPnP device
activation True to enable, False to disable the device
Return values:
None -
Exceptions:
None -
This routine simply activates the device in its current configuration, or deactivates the device. It does not attempt any kind of resource arbitration.

Definition at line 553 of file isapnp.c.

References isapnp_device::csn, DBG, isapnp_activate(), isapnp_delay(), isapnp_logicaldevice(), isapnp_send_key(), isapnp_wait_for_key(), isapnp_wake(), and isapnp_device::logdev.

Referenced by activate_isapnp_device(), and deactivate_isapnp_device().

00554                                                  {
00555         /* Wake the card and select the logical device */
00556         isapnp_wait_for_key ();
00557         isapnp_send_key ();
00558         isapnp_wake ( isapnp->csn );
00559         isapnp_logicaldevice ( isapnp->logdev );
00560 
00561         /* Activate/deactivate the logical device */
00562         isapnp_activate ( activation );
00563         isapnp_delay();
00564 
00565         /* Return all cards to Wait for Key state */
00566         isapnp_wait_for_key ();
00567 
00568         DBG ( "ISAPnP %s device %02x:%02x\n",
00569               ( activation ? "activated" : "deactivated" ),
00570               isapnp->csn, isapnp->logdev );
00571 }

static int isapnp_probe ( struct isapnp_device isapnp  )  [static]

Probe an ISAPnP device.

Parameters:
isapnp ISAPnP device
Return values:
rc Return status code
Searches for a driver for the ISAPnP device. If a driver is found, its probe() routine is called.

Definition at line 582 of file isapnp.c.

References isapnp_device::csn, DBG, isapnp_device::driver, isapnp_device::driver_name, ENOTTY, for_each_table_entry, id, isapnp_driver::id_count, isapnp_driver::ids, isapnp_device::ioaddr, isapnp_device::irqno, isa_id_string(), ISA_PROD_ID, ISAPNP_DRIVERS, isapnp_device::logdev, isapnp_driver::probe, isapnp_device_id::prod_id, isapnp_device::prod_id, isapnp_device_id::vendor_id, and isapnp_device::vendor_id.

Referenced by isapnpbus_probe().

00582                                                          {
00583         struct isapnp_driver *driver;
00584         struct isapnp_device_id *id;
00585         unsigned int i;
00586         int rc;
00587 
00588         DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") "
00589               "io %x irq %d)\n", isapnp->csn, isapnp->logdev,
00590               isapnp->vendor_id, isapnp->prod_id,
00591               isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
00592               isapnp->ioaddr, isapnp->irqno );
00593 
00594         for_each_table_entry ( driver, ISAPNP_DRIVERS ) {
00595                 for ( i = 0 ; i < driver->id_count ; i++ ) {
00596                         id = &driver->ids[i];
00597                         if ( id->vendor_id != isapnp->vendor_id )
00598                                 continue;
00599                         if ( ISA_PROD_ID ( id->prod_id ) !=
00600                              ISA_PROD_ID ( isapnp->prod_id ) )
00601                                 continue;
00602                         isapnp->driver = driver;
00603                         isapnp->driver_name = id->name;
00604                         DBG ( "...using driver %s\n", isapnp->driver_name );
00605                         if ( ( rc = driver->probe ( isapnp, id ) ) != 0 ) {
00606                                 DBG ( "......probe failed\n" );
00607                                 continue;
00608                         }
00609                         return 0;
00610                 }
00611         }
00612 
00613         DBG ( "...no driver found\n" );
00614         return -ENOTTY;
00615 }

static void isapnp_remove ( struct isapnp_device isapnp  )  [static]

Remove an ISAPnP device.

Parameters:
isapnp ISAPnP device

Definition at line 622 of file isapnp.c.

References isapnp_device::csn, DBG, isapnp_device::driver, isapnp_device::logdev, and isapnp_driver::remove.

Referenced by isapnpbus_remove().

00622                                                            {
00623         isapnp->driver->remove ( isapnp );
00624         DBG ( "Removed ISAPnP device %02x:%02x\n",
00625               isapnp->csn, isapnp->logdev );
00626 }

static int isapnpbus_probe ( struct root_device rootdev  )  [static]

Probe ISAPnP root bus.

Parameters:
rootdev ISAPnP bus root device
Scans the ISAPnP bus for devices and registers all devices it can find.

Definition at line 636 of file isapnp.c.

References device_description::bus_type, BUS_TYPE_ISAPNP, device::children, isapnp_device::csn, device::desc, root_device::dev, isapnp_device::dev, device_description::device, ENOMEM, free(), INIT_LIST_HEAD, device_description::ioaddr, isapnp_device::ioaddr, device_description::irq, isapnp_device::irqno, isapnp_find_logdevid(), isapnp_isolate(), isapnp_logicaldevice(), isapnp_peek(), isapnp_probe(), isapnp_read_iobase(), isapnp_read_irqno(), isapnp_read_port, isapnp_send_key(), isapnp_wait_for_key(), isapnp_wake(), isapnpbus_remove(), list_add, list_del, isapnp_device::logdev, malloc(), memset(), device::name, NULL, device::parent, isapnp_logdevid::prod_id, isapnp_device::prod_id, device::siblings, snprintf(), device_description::vendor, isapnp_logdevid::vendor_id, isapnp_device::vendor_id, and isapnp_identifier::vendor_id.

00636                                                            {
00637         struct isapnp_device *isapnp = NULL;
00638         struct isapnp_identifier identifier;
00639         struct isapnp_logdevid logdevid;
00640         unsigned int csn;
00641         unsigned int logdev;
00642         int rc;
00643 
00644         /* Perform isolation if it hasn't yet been done */
00645         if ( ! isapnp_read_port )
00646                 isapnp_isolate();
00647 
00648         for ( csn = 1 ; csn <= 0xff ; csn++ ) {
00649                 for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) {
00650 
00651                         /* Allocate struct isapnp_device */
00652                         if ( ! isapnp )
00653                                 isapnp = malloc ( sizeof ( *isapnp ) );
00654                         if ( ! isapnp ) {
00655                                 rc = -ENOMEM;
00656                                 goto err;
00657                         }
00658                         memset ( isapnp, 0, sizeof ( *isapnp ) );
00659                         isapnp->csn = csn;
00660                         isapnp->logdev = logdev;
00661 
00662                         /* Wake the card */
00663                         isapnp_wait_for_key();
00664                         isapnp_send_key();
00665                         isapnp_wake ( csn );
00666 
00667                         /* Read the card identifier */
00668                         isapnp_peek ( &identifier, sizeof ( identifier ) );
00669                         
00670                         /* No card with this CSN; stop here */
00671                         if ( identifier.vendor_id & 0x80 )
00672                                 goto done;
00673 
00674                         /* Find the Logical Device ID tag */
00675                         if ( ( rc = isapnp_find_logdevid ( logdev,
00676                                                            &logdevid ) ) != 0){
00677                                 /* No more logical devices; go to next CSN */
00678                                 break;
00679                         }
00680                         
00681                         /* Select the logical device */
00682                         isapnp_logicaldevice ( logdev );
00683 
00684                         /* Populate struct isapnp_device */
00685                         isapnp->vendor_id = logdevid.vendor_id;
00686                         isapnp->prod_id = logdevid.prod_id;
00687                         isapnp->ioaddr = isapnp_read_iobase ( 0 );
00688                         isapnp->irqno = isapnp_read_irqno ( 0 );
00689 
00690                         /* Return all cards to Wait for Key state */
00691                         isapnp_wait_for_key();
00692 
00693                         /* Add to device hierarchy */
00694                         snprintf ( isapnp->dev.name,
00695                                    sizeof ( isapnp->dev.name ),
00696                                    "ISAPnP%02x:%02x", csn, logdev );
00697                         isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
00698                         isapnp->dev.desc.vendor = isapnp->vendor_id;
00699                         isapnp->dev.desc.device = isapnp->prod_id;
00700                         isapnp->dev.desc.ioaddr = isapnp->ioaddr;
00701                         isapnp->dev.desc.irq = isapnp->irqno;
00702                         isapnp->dev.parent = &rootdev->dev;
00703                         list_add ( &isapnp->dev.siblings,
00704                                    &rootdev->dev.children );
00705                         INIT_LIST_HEAD ( &isapnp->dev.children );
00706                         
00707                         /* Look for a driver */
00708                         if ( isapnp_probe ( isapnp ) == 0 ) {
00709                                 /* isapnpdev registered, we can drop our ref */
00710                                 isapnp = NULL;
00711                         } else {
00712                                 /* Not registered; re-use struct */
00713                                 list_del ( &isapnp->dev.siblings );
00714                         }
00715                 }
00716         }
00717 
00718  done:
00719         free ( isapnp );
00720         return 0;
00721 
00722  err:
00723         free ( isapnp );
00724         isapnpbus_remove ( rootdev );
00725         return rc;
00726 }


Variable Documentation

ISAPnP Read Port address.

ROM prefix may be able to set this address, which is why this is non-static.

Definition at line 75 of file isapnp.c.

Referenced by isapnp_isolate(), isapnp_read_data(), isapnp_set_read_port(), isapnp_try_isolate(), isapnpbus_probe(), and pxenv_start_undi().

Initial value:

 {
        .probe = isapnpbus_probe,
        .remove = isapnpbus_remove,
}
ISAPnP bus root device driver.

Definition at line 746 of file isapnp.c.

struct root_device isapnp_root_device __root_device

Initial value:

 {
        .dev = { .name = "ISAPnP" },
        .driver = &isapnp_root_driver,
}
ISAPnP bus root device.

Definition at line 752 of file isapnp.c.


Generated on Tue Apr 6 20:01:16 2010 for gPXE by  doxygen 1.5.7.1