iPXE
Defines | Functions | Variables
isapnp.c File Reference

ISAPnP bus support. More...

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <ipxe/io.h>
#include <unistd.h>
#include <ipxe/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 85 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 86 of file isapnp.c.

Referenced by isapnp_try_isolate().

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

Definition at line 90 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 91 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:
rootdevISAPnP bus root device

Definition at line 734 of file isapnp.c.

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

Referenced by isapnpbus_probe().

                                                             {
        struct isapnp_device *isapnp;
        struct isapnp_device *tmp;

        list_for_each_entry_safe ( isapnp, tmp, &rootdev->dev.children,
                                   dev.siblings ) {
                isapnp_remove ( isapnp );
                list_del ( &isapnp->dev.siblings );
                free ( isapnp );
        }
}
static void isapnp_write_address ( unsigned int  address) [inline, static]

Definition at line 95 of file isapnp.c.

References outb().

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

                                                                 {
        outb ( address, ISAPNP_ADDRESS );
}
static void isapnp_write_data ( unsigned int  data) [inline, static]

Definition at line 99 of file isapnp.c.

References outb().

Referenced by isapnp_write_byte().

                                                           {
        outb ( data, ISAPNP_WRITE_DATA );
}
static unsigned int isapnp_read_data ( void  ) [inline, static]

Definition at line 103 of file isapnp.c.

References inb(), and isapnp_read_port.

Referenced by isapnp_read_byte(), and isapnp_try_isolate().

                                                     {
        return inb ( isapnp_read_port );
}
static void isapnp_write_byte ( unsigned int  address,
unsigned int  value 
) [inline, static]
static unsigned int isapnp_read_byte ( unsigned int  address) [inline, static]
static unsigned int isapnp_read_word ( unsigned int  address) [inline, static]

Definition at line 118 of file isapnp.c.

References isapnp_read_byte().

Referenced by isapnp_read_iobase().

                                                                     {
        /* Yes, they're in big-endian order */
        return ( ( isapnp_read_byte ( address ) << 8 )
                 | isapnp_read_byte ( address + 1 ) );
}
static void isapnp_set_read_port ( void  ) [inline, static]

Inform cards of a new read port address.

Definition at line 125 of file isapnp.c.

References isapnp_read_port, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

                                                 {
        isapnp_write_byte ( ISAPNP_READPORT, ( isapnp_read_port >> 2 ) );
}
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 135 of file isapnp.c.

References isapnp_write_address().

Referenced by isapnp_try_isolate().

                                                   {
        isapnp_write_address ( ISAPNP_SERIALISOLATION );
}
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 145 of file isapnp.c.

References isapnp_write_byte().

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

                                                {
        isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY );
}
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 155 of file isapnp.c.

References isapnp_write_byte().

Referenced by isapnp_try_isolate().

                                             {
        isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN );
}
static void isapnp_wake ( uint8_t  csn) [inline, static]

Place a specified card into the Config state.

Parameters:
csnCard 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 170 of file isapnp.c.

References isapnp_write_byte().

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

                                               {
        isapnp_write_byte ( ISAPNP_WAKE, csn );
}
static unsigned int isapnp_read_resourcedata ( void  ) [inline, static]

Definition at line 174 of file isapnp.c.

References isapnp_read_byte().

Referenced by isapnp_peek_byte().

                                                             {
        return isapnp_read_byte ( ISAPNP_RESOURCEDATA );
}
static unsigned int isapnp_read_status ( void  ) [inline, static]

Definition at line 178 of file isapnp.c.

References isapnp_read_byte().

Referenced by isapnp_peek_byte().

                                                       {
        return isapnp_read_byte ( ISAPNP_STATUS );
}
static void isapnp_write_csn ( unsigned int  csn) [inline, static]

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

Parameters:
csnCard 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 192 of file isapnp.c.

References isapnp_write_byte().

Referenced by isapnp_try_isolate().

                                                         {
        isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
}
static void isapnp_logicaldevice ( unsigned int  logdev) [inline, static]

Definition at line 196 of file isapnp.c.

References isapnp_write_byte().

Referenced by isapnp_activate(), isapnp_deactivate(), isapnp_device_activation(), and isapnpbus_probe().

                                                                {
        isapnp_write_byte ( ISAPNP_LOGICALDEVICENUMBER, logdev );
}
static void isapnp_activate ( unsigned int  logdev) [inline, static]

Definition at line 200 of file isapnp.c.

References isapnp_logicaldevice(), and isapnp_write_byte().

Referenced by isapnp_device_activation().

                                                           {
        isapnp_logicaldevice ( logdev );
        isapnp_write_byte ( ISAPNP_ACTIVATE, 1 );
}
static void isapnp_deactivate ( unsigned int  logdev) [inline, static]

Definition at line 205 of file isapnp.c.

References isapnp_logicaldevice(), and isapnp_write_byte().

                                                             {
        isapnp_logicaldevice ( logdev );
        isapnp_write_byte ( ISAPNP_ACTIVATE, 0 );
}
static unsigned int isapnp_read_iobase ( unsigned int  index) [inline, static]

Definition at line 210 of file isapnp.c.

References isapnp_read_word().

Referenced by isapnpbus_probe().

                                                                     {
        return isapnp_read_word ( ISAPNP_IOBASE ( index ) );
}
static unsigned int isapnp_read_irqno ( unsigned int  index) [inline, static]

Definition at line 214 of file isapnp.c.

References isapnp_read_byte().

Referenced by isapnpbus_probe().

                                                                    {
        return isapnp_read_byte ( ISAPNP_IRQNO ( index ) );
}
static void isapnp_delay ( void  ) [static]

Definition at line 218 of file isapnp.c.

References udelay().

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

                                  {
        udelay ( 1000 );
}
static unsigned int isapnp_lfsr_next ( unsigned int  lfsr,
unsigned int  input_bit 
) [inline, static]

Linear feedback shift register.

Parameters:
lfsrCurrent value of the LFSR
input_bitCurrent input bit to the LFSR
Return values:
lfsrNext 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 236 of file isapnp.c.

Referenced by isapnp_checksum(), and isapnp_send_key().

                                                                       {
        register uint8_t lfsr_next;

        lfsr_next = lfsr >> 1;
        lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
        return lfsr_next;
}
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 251 of file isapnp.c.

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

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

                                     {
        unsigned int i;
        unsigned int lfsr;

        isapnp_delay();
        isapnp_write_address ( 0x00 );
        isapnp_write_address ( 0x00 );

        lfsr = ISAPNP_LFSR_SEED;
        for ( i = 0 ; i < 32 ; i++ ) {
                isapnp_write_address ( lfsr );
                lfsr = isapnp_lfsr_next ( lfsr, 0 );
        }
}
static unsigned int isapnp_checksum ( struct isapnp_identifier *  identifier) [static]

Compute ISAPnP identifier checksum.

Parameters:
identifierISAPnP identifier
Return values:
checksumExpected checksum value

Definition at line 272 of file isapnp.c.

References byte, and isapnp_lfsr_next().

Referenced by isapnp_try_isolate().

                                                                             {
        unsigned int i, j;
        unsigned int lfsr;
        unsigned int byte;

        lfsr = ISAPNP_LFSR_SEED;
        for ( i = 0 ; i < 8 ; i++ ) {
                byte = * ( ( ( uint8_t * ) identifier ) + i );
                for ( j = 0 ; j < 8 ; j++ ) {
                        lfsr = isapnp_lfsr_next ( lfsr, byte );
                        byte >>= 1;
                }
        }
        return lfsr;
}
static unsigned int isapnp_peek_byte ( void  ) [inline, static]

Definition at line 293 of file isapnp.c.

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

Referenced by isapnp_find_tag(), and isapnp_peek().

                                                     {
        unsigned int i;

        /* Wait for data to be ready */
        for ( i = 0 ; i < 20 ; i++ ) {
                if ( isapnp_read_status() & 0x01 ) {
                        /* Byte ready - read it */
                        return isapnp_read_resourcedata();
                }
                isapnp_delay();
        }
        /* Data never became ready - return 0xff */
        return 0xff;
}
static void isapnp_peek ( void *  buf,
size_t  len 
) [static]

Read resource data.

Parameters:
bufBuffer in which to store data, or NULL
bytesNumber of bytes to read

Resource data is read from the current location. If #buf is NULL, the data is discarded.

Definition at line 317 of file isapnp.c.

References byte, isapnp_peek_byte(), and len.

Referenced by isapnp_find_tag(), and isapnpbus_probe().

                                                  {
        unsigned int i;
        unsigned int byte;

        for ( i = 0 ; i < len ; i++) {
                byte = isapnp_peek_byte();
                if ( buf )
                        * ( ( uint8_t * ) buf + i ) = byte;
        }
}
static int isapnp_find_tag ( unsigned int  wanted_tag,
void *  buf,
size_t  len 
) [static]

Find a tag within the resource data.

Parameters:
wanted_tagThe tag that we're looking for
bufBuffer in which to store the tag's contents
lenLength of buffer
Return values:
rcReturn status code

Scan through the resource data until we find a particular tag, and read its contents into a buffer.

Definition at line 339 of file isapnp.c.

References DBG2, ENOENT, isapnp_peek(), isapnp_peek_byte(), NULL, and tag.

Referenced by isapnp_find_logdevid().

                                                                              {
        unsigned int tag;
        unsigned int tag_len;

        DBG2 ( "ISAPnP read tag" );
        do {
                tag = isapnp_peek_byte();
                if ( ISAPNP_IS_SMALL_TAG ( tag ) ) {
                        tag_len = ISAPNP_SMALL_TAG_LEN ( tag );
                        tag = ISAPNP_SMALL_TAG_NAME ( tag );
                } else {
                        tag_len = ( isapnp_peek_byte() +
                                    ( isapnp_peek_byte() << 8 ) );
                        tag = ISAPNP_LARGE_TAG_NAME ( tag );
                }
                DBG2 ( " %02x (%02x)", tag, tag_len );
                if ( tag == wanted_tag ) {
                        if ( len > tag_len )
                                len = tag_len;
                        isapnp_peek ( buf, len );
                        DBG2 ( "\n" );
                        return 0;
                } else {
                        isapnp_peek ( NULL, tag_len );
                }
        } while ( tag != ISAPNP_TAG_END );
        DBG2 ( "\n" );
        return -ENOENT;
}
static int isapnp_find_logdevid ( unsigned int  logdev,
struct isapnp_logdevid *  logdevid 
) [static]

Find specified Logical Device ID tag.

Parameters:
logdevLogical device ID
logdevidLogical device ID structure to fill in
Return values:
rcReturn status code

Definition at line 376 of file isapnp.c.

References isapnp_find_tag(), and rc.

Referenced by isapnpbus_probe().

                                                                     {
        unsigned int i;
        int rc;

        for ( i = 0 ; i <= logdev ; i++ ) {
                if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid,
                                              sizeof ( *logdevid ) ) ) != 0 )
                        return rc;
        }
        return 0;
}
static int isapnp_try_isolate ( void  ) [static]

Try isolating ISAPnP cards at the current read port.

Return values:
\>0Number of ISAPnP cards found
0There are no ISAPnP cards in the system
\<0A 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 400 of file isapnp.c.

References byte, data, 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().

                                       {
        struct isapnp_identifier identifier;
        unsigned int i, j;
        unsigned int seen_55aa, seen_life;
        unsigned int csn = 0;
        unsigned int data;
        unsigned int byte;

        DBG ( "ISAPnP attempting isolation at read port %04x\n",
              isapnp_read_port );

        /* Place all cards into the Sleep state, whatever state
         * they're currently in.
         */
        isapnp_wait_for_key();
        isapnp_send_key();

        /* Reset all assigned CSNs */
        isapnp_reset_csn();
        isapnp_delay();
        isapnp_delay();
        
        /* Place all cards into the Isolation state */
        isapnp_wait_for_key ();
        isapnp_send_key();
        isapnp_wake ( 0x00 );
        
        /* Set the read port */
        isapnp_set_read_port();
        isapnp_delay();

        while ( 1 ) {

                /* All cards that do not have assigned CSNs are
                 * currently in the Isolation state, each time we go
                 * through this loop.
                 */

                /* Initiate serial isolation */
                isapnp_serialisolation();
                isapnp_delay();

                /* Read identifier serially via the ISAPnP read port. */
                memset ( &identifier, 0, sizeof ( identifier ) );
                seen_55aa = seen_life = 0;
                for ( i = 0 ; i < 9 ; i++ ) {
                        byte = 0;
                        for ( j = 0 ; j < 8 ; j++ ) {
                                data = isapnp_read_data();
                                isapnp_delay();
                                data = ( ( data << 8 ) | isapnp_read_data() );
                                isapnp_delay();
                                byte >>= 1;
                                if (  data != 0xffff ) {
                                        seen_life++;
                                        if ( data == 0x55aa ) {
                                                byte |= 0x80;
                                                seen_55aa++;
                                        }
                                }
                        }
                        *( ( ( uint8_t * ) &identifier ) + i ) = byte;
                }

                /* If we didn't see any 55aa patterns, stop here */
                if ( ! seen_55aa ) {
                        if ( csn ) {
                                DBG ( "ISAPnP found no more cards\n" );
                        } else {
                                if ( seen_life ) {
                                        DBG ( "ISAPnP saw life but no cards, "
                                              "trying new read port\n" );
                                        csn = -1;
                                } else {
                                        DBG ( "ISAPnP saw no signs of life, "
                                              "abandoning isolation\n" );
                                }
                        }
                        break;
                }

                /* If the checksum was invalid stop here */
                if ( identifier.checksum != isapnp_checksum ( &identifier) ) {
                        DBG ( "ISAPnP found malformed card "
                              ISAPNP_CARD_ID_FMT "\n  with checksum %02x "
                              "(should be %02x), trying new read port\n",
                              ISAPNP_CARD_ID_DATA ( &identifier ),
                              identifier.checksum,
                              isapnp_checksum ( &identifier) );
                        csn = -1;
                        break;
                }

                /* Give the device a CSN */
                csn++;
                DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT
                      ", assigning CSN %02x\n",
                      ISAPNP_CARD_ID_DATA ( &identifier ), csn );
                
                isapnp_write_csn ( csn );
                isapnp_delay();

                /* Send this card back to Sleep and force all cards
                 * without a CSN into Isolation state
                 */
                isapnp_wake ( 0x00 );
                isapnp_delay();
        }

        /* Place all cards in Wait for Key state */
        isapnp_wait_for_key();

        /* Return number of cards found */
        if ( csn > 0 ) {
                DBG ( "ISAPnP found %d cards at read port %04x\n",
                      csn, isapnp_read_port );
        }
        return csn;
}
static void isapnp_isolate ( void  ) [static]

Find a valid read port and isolate all ISAPnP cards.

Definition at line 524 of file isapnp.c.

References isapnp_read_port, and isapnp_try_isolate().

Referenced by isapnpbus_probe().

                                    {
        for ( isapnp_read_port = ISAPNP_READ_PORT_START ;
              isapnp_read_port <= ISAPNP_READ_PORT_MAX ;
              isapnp_read_port += ISAPNP_READ_PORT_STEP ) {
                /* Avoid problematic locations such as the NE2000
                 * probe space
                 */
                if ( ( isapnp_read_port >= 0x280 ) &&
                     ( isapnp_read_port <= 0x380 ) )
                        continue;
                
                /* If we detect any ISAPnP cards at this location, stop */
                if ( isapnp_try_isolate() >= 0 )
                        return;
        }
}
void isapnp_device_activation ( struct isapnp_device *  isapnp,
int  activation 
)

Activate or deactivate an ISAPnP device.

Parameters:
isapnpISAPnP device
activationTrue 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 554 of file isapnp.c.

References DBG, isapnp_activate(), isapnp_delay(), isapnp_logicaldevice(), isapnp_send_key(), isapnp_wait_for_key(), and isapnp_wake().

                                                 {
        /* Wake the card and select the logical device */
        isapnp_wait_for_key ();
        isapnp_send_key ();
        isapnp_wake ( isapnp->csn );
        isapnp_logicaldevice ( isapnp->logdev );

        /* Activate/deactivate the logical device */
        isapnp_activate ( activation );
        isapnp_delay();

        /* Return all cards to Wait for Key state */
        isapnp_wait_for_key ();

        DBG ( "ISAPnP %s device %02x:%02x\n",
              ( activation ? "activated" : "deactivated" ),
              isapnp->csn, isapnp->logdev );
}
static int isapnp_probe ( struct isapnp_device *  isapnp) [static]

Probe an ISAPnP device.

Parameters:
isapnpISAPnP device
Return values:
rcReturn status code

Searches for a driver for the ISAPnP device. If a driver is found, its probe() routine is called.

Definition at line 583 of file isapnp.c.

References DBG, driver, ENOTTY, for_each_table_entry, id, isa_id_string(), ISA_PROD_ID, and rc.

Referenced by isapnpbus_probe().

                                                         {
        struct isapnp_driver *driver;
        struct isapnp_device_id *id;
        unsigned int i;
        int rc;

        DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") "
              "io %x irq %d)\n", isapnp->csn, isapnp->logdev,
              isapnp->vendor_id, isapnp->prod_id,
              isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
              isapnp->ioaddr, isapnp->irqno );

        for_each_table_entry ( driver, ISAPNP_DRIVERS ) {
                for ( i = 0 ; i < driver->id_count ; i++ ) {
                        id = &driver->ids[i];
                        if ( id->vendor_id != isapnp->vendor_id )
                                continue;
                        if ( ISA_PROD_ID ( id->prod_id ) !=
                             ISA_PROD_ID ( isapnp->prod_id ) )
                                continue;
                        isapnp->driver = driver;
                        isapnp->dev.driver_name = id->name;
                        DBG ( "...using driver %s\n", isapnp->dev.driver_name );
                        if ( ( rc = driver->probe ( isapnp, id ) ) != 0 ) {
                                DBG ( "......probe failed\n" );
                                continue;
                        }
                        return 0;
                }
        }

        DBG ( "...no driver found\n" );
        return -ENOTTY;
}
static void isapnp_remove ( struct isapnp_device *  isapnp) [static]

Remove an ISAPnP device.

Parameters:
isapnpISAPnP device

Definition at line 623 of file isapnp.c.

References DBG.

Referenced by isapnpbus_remove().

                                                           {
        isapnp->driver->remove ( isapnp );
        DBG ( "Removed ISAPnP device %02x:%02x\n",
              isapnp->csn, isapnp->logdev );
}
static int isapnpbus_probe ( struct root_device rootdev) [static]

Probe ISAPnP root bus.

Parameters:
rootdevISAPnP bus root device

Scans the ISAPnP bus for devices and registers all devices it can find.

Definition at line 637 of file isapnp.c.

References BUS_TYPE_ISAPNP, device::children, root_device::dev, done, ENOMEM, free, INIT_LIST_HEAD, 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, malloc(), memset(), NULL, rc, and snprintf().

                                                           {
        struct isapnp_device *isapnp = NULL;
        struct isapnp_identifier identifier;
        struct isapnp_logdevid logdevid;
        unsigned int csn;
        unsigned int logdev;
        int rc;

        /* Perform isolation if it hasn't yet been done */
        if ( ! isapnp_read_port )
                isapnp_isolate();

        for ( csn = 1 ; csn <= 0xff ; csn++ ) {
                for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) {

                        /* Allocate struct isapnp_device */
                        if ( ! isapnp )
                                isapnp = malloc ( sizeof ( *isapnp ) );
                        if ( ! isapnp ) {
                                rc = -ENOMEM;
                                goto err;
                        }
                        memset ( isapnp, 0, sizeof ( *isapnp ) );
                        isapnp->csn = csn;
                        isapnp->logdev = logdev;

                        /* Wake the card */
                        isapnp_wait_for_key();
                        isapnp_send_key();
                        isapnp_wake ( csn );

                        /* Read the card identifier */
                        isapnp_peek ( &identifier, sizeof ( identifier ) );
                        
                        /* No card with this CSN; stop here */
                        if ( identifier.vendor_id & 0x80 )
                                goto done;

                        /* Find the Logical Device ID tag */
                        if ( ( rc = isapnp_find_logdevid ( logdev,
                                                           &logdevid ) ) != 0){
                                /* No more logical devices; go to next CSN */
                                break;
                        }
                        
                        /* Select the logical device */
                        isapnp_logicaldevice ( logdev );

                        /* Populate struct isapnp_device */
                        isapnp->vendor_id = logdevid.vendor_id;
                        isapnp->prod_id = logdevid.prod_id;
                        isapnp->ioaddr = isapnp_read_iobase ( 0 );
                        isapnp->irqno = isapnp_read_irqno ( 0 );

                        /* Return all cards to Wait for Key state */
                        isapnp_wait_for_key();

                        /* Add to device hierarchy */
                        snprintf ( isapnp->dev.name,
                                   sizeof ( isapnp->dev.name ),
                                   "ISAPnP%02x:%02x", csn, logdev );
                        isapnp->dev.desc.bus_type = BUS_TYPE_ISAPNP;
                        isapnp->dev.desc.vendor = isapnp->vendor_id;
                        isapnp->dev.desc.device = isapnp->prod_id;
                        isapnp->dev.desc.ioaddr = isapnp->ioaddr;
                        isapnp->dev.desc.irq = isapnp->irqno;
                        isapnp->dev.parent = &rootdev->dev;
                        list_add ( &isapnp->dev.siblings,
                                   &rootdev->dev.children );
                        INIT_LIST_HEAD ( &isapnp->dev.children );
                        
                        /* Look for a driver */
                        if ( isapnp_probe ( isapnp ) == 0 ) {
                                /* isapnpdev registered, we can drop our ref */
                                isapnp = NULL;
                        } else {
                                /* Not registered; re-use struct */
                                list_del ( &isapnp->dev.siblings );
                        }
                }
        }

 done:
        free ( isapnp );
        return 0;

 err:
        free ( isapnp );
        isapnpbus_remove ( rootdev );
        return rc;
}

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 76 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 747 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 753 of file isapnp.c.