summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/bus/isapnp.c526
-rw-r--r--src/include/isapnp.h159
2 files changed, 441 insertions, 244 deletions
diff --git a/src/drivers/bus/isapnp.c b/src/drivers/bus/isapnp.c
index b03da92c..b0e64568 100644
--- a/src/drivers/bus/isapnp.c
+++ b/src/drivers/bus/isapnp.c
@@ -1,4 +1,3 @@
-#ifdef CONFIG_ISA
/**************************************************************************
*
* isapnp.c -- Etherboot isapnp support for the 3Com 3c515
@@ -24,161 +23,266 @@
*
* REVISION HISTORY:
* ================
-* Version 0.1 April 26, 2002 TJL
-* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
+* Version 0.1 April 26, 2002 TJL
+* Version 0.2 01/08/2003 TJL Moved outside the 3c515.c driver file
* Version 0.3 Sept 23, 2003 timlegge Change delay to currticks
*
*
-* Indent Options: indent -kr -i8
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
+*
***************************************************************************/
-/* to get some global routines like printf */
#include "etherboot.h"
#include "timer.h"
#include "isapnp.h"
-static int pnp_card_csn = 0;
+/*
+ * We can have 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.
+ *
+ * However, we shouldn't make scanning the ISAPnP bus an INIT_FN(),
+ * because even ISAPnP probing can still screw up other devices on the
+ * ISA bus. We therefore probe only when we are first asked to find
+ * an ISAPnP device.
+ *
+ */
+static uint16_t isapnp_read_port;
+static uint16_t isapnp_max_csn;
-void isapnp_wait(unsigned int nticks)
-{
- unsigned int to = currticks() + nticks;
- while (currticks() < to)
- /* Wait */ ;
+static const char initdata[] = INITDATA;
+
+/*
+ * ISAPnP utility functions
+ *
+ */
+
+static inline void isapnp_write_address ( uint8_t address ) {
+ outb ( address, ISAPNP_ADDRESS );
}
-/* The following code is the ISA PNP logic required to activate the 3c515 */
-/* PNP Defines */
-#define IDENT_LEN 9
-#define NUM_CARDS 128
-
-/* PNP declares */
-static unsigned char serial_identifier[NUM_CARDS + 1][IDENT_LEN];
-static unsigned char isapnp_checksum_value;
-static char initdata[INIT_LENGTH] = INITDATA;
-int read_port = 0;
-
-
-/* PNP Prototypes */
-static int Isolate(void);
-static int do_isapnp_isolate(void);
-static int isapnp_build_device_list(void);
-static int isapnp_isolate_rdp_select(void);
-static int isapnp_next_rdp(void);
-static void isapnp_peek(unsigned char *data, int bytes);
-static void send_key(void);
-static unsigned char isapnp_checksum(unsigned char *data);
-int Config(int csn);
-
-void config_pnp_device(void)
-{
- /* PNP Configuration */
- printf("Probing/Configuring ISAPNP devices\n");
- if (!read_port) {
- Isolate();
- if (pnp_card_csn)
- Config(pnp_card_csn);
+static inline void isapnp_write_data ( uint8_t data ) {
+ outb ( data, ISAPNP_WRITE_DATA );
+}
+
+static inline void isapnp_write_byte ( uint8_t address, uint8_t value ) {
+ isapnp_write_address ( address );
+ isapnp_write_data ( value );
+}
+
+static inline uint8_t isapnp_read_data ( void ) {
+ return inb ( isapnp_read_port );
+}
+
+static inline void isapnp_set_read_port ( void ) {
+ isapnp_write_byte ( ISAPNP_READPORT, isapnp_read_port >> 2 );
+}
+
+static inline void isapnp_serialisolation ( void ) {
+ isapnp_write_address ( ISAPNP_SERIALISOLATION );
+}
+
+static inline void isapnp_wait_for_key ( void ) {
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_WAIT_FOR_KEY );
+}
+
+static inline void isapnp_reset_csn ( void ) {
+ isapnp_write_byte ( ISAPNP_CONFIGCONTROL, ISAPNP_CONFIG_RESET_CSN );
+}
+
+static inline void isapnp_wake ( uint8_t csn ) {
+ isapnp_write_byte ( ISAPNP_WAKE, csn );
+}
+
+static inline void isapnp_write_csn ( uint8_t csn ) {
+ isapnp_write_byte ( ISAPNP_CARDSELECTNUMBER, csn );
+}
+
+/*
+ * 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. :)
+ *
+ */
+static inline uint8_t isapnp_lfsr_next ( uint8_t lfsr, int input_bit ) {
+ register uint8_t lfsr_next;
+
+ lfsr_next = lfsr >> 1;
+ lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
+ return lfsr_next;
+}
+
+/*
+ * Send the ISAPnP initiation key
+ *
+ */
+static void isapnp_send_key ( void ) {
+ unsigned int i;
+ uint8_t lfsr;
+
+ udelay ( 1000 );
+ 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 );
}
}
-/* Isolate all the PNP Boards on the ISA BUS */
-static int Isolate(void)
-{
- int cards = 0;
- if (read_port < 0x203 || read_port > 0x3ff) {
- cards = do_isapnp_isolate();
- if (cards < 0 || (read_port < 0x203 || read_port > 0x3ff)) {
- printf("No Plug & Play device found\n");
- return 0;
+/*
+ * Compute ISAPnP identifier checksum
+ *
+ */
+static uint8_t isapnp_checksum ( union isapnp_identifier *identifier ) {
+ int i, j;
+ uint8_t lfsr;
+ uint8_t byte;
+
+ lfsr = ISAPNP_LFSR_SEED;
+ for ( i = 0 ; i < 8 ; i++ ) {
+ byte = identifier->bytes[i];
+ for ( j = 0 ; j < 8 ; j++ ) {
+ lfsr = isapnp_lfsr_next ( lfsr, byte );
+ byte >>= 1;
}
}
- isapnp_build_device_list();
-#ifdef EDEBUG
- printf("%d Plug & Play device found\n", cards);
-#endif
- return 0;
+ return lfsr;
}
-static int do_isapnp_isolate(void)
-{
- unsigned char checksum = 0x6a;
- unsigned char chksum = 0x00;
- unsigned char bit = 0x00;
- unsigned char c1, c2;
- int csn = 0;
- int i;
- int iteration = 1;
-
- read_port = 0x213;
- if (isapnp_isolate_rdp_select() < 0)
- return -1;
-
- while (1) {
- for (i = 1; i <= 64; i++) {
- c1 = READ_DATA;
- isapnp_wait(1);
- c2 = READ_DATA;
- isapnp_wait(1);
- if (c1 == 0x55) {
- if (c2 == 0xAA) {
- bit = 0x01;
+/*
+ * Try isolating ISAPnP cards at the current read port. Return the
+ * number of ISAPnP cards found.
+ *
+ * The state diagram on page 18 (PDF page 24) of the PnP ISA spec
+ * gives the best overview of what happens here.
+ *
+ */
+static int isapnp_try_isolate ( void ) {
+ union isapnp_identifier identifier;
+ int i, j, seen55aa;
+ uint16_t data;
+ uint8_t byte;
+
+ DBG ( "ISAPnP attempting isolation at read port %hx\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_max_csn = 0;
+ udelay ( 2000 );
+
+ /* 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 ();
+ udelay ( 1000 );
+
+ 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 ();
+ udelay ( 1000 );
+
+ /* Read identifier serially via the ISAPnP read port. */
+ memset ( &identifier, 0, sizeof ( identifier ) );
+ seen55aa = 0;
+ for ( i = 0 ; i < 9 ; i++ ) {
+ byte = 0;
+ for ( j = 0 ; j < 8 ; j++ ) {
+ data = isapnp_read_data ();
+ udelay ( 1000 );
+ data = ( data << 8 ) | isapnp_read_data ();
+ udelay ( 1000 );
+ if ( data == 0x55aa ) {
+ byte |= 1;
}
+ byte <<= 1;
}
- checksum =
- ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
- << 7) | (checksum >> 1);
- bit = 0x00;
- }
-#ifdef EDEBUG
- printf("Calc checksum %d", checksum);
-#endif
- for (i = 65; i <= 72; i++) {
- c1 = READ_DATA;
- udelay(250);
- c2 = READ_DATA;
- udelay(250);
- if (c1 == 0x55) {
- if (c2 == 0xAA)
- chksum |= (1 << (i - 65));
+ identifier.bytes[i] = byte;
+ if ( byte ) {
+ seen55aa = 1;
}
}
-#ifdef EDEBUG
- printf("Actual checksum %d", chksum);
-#endif
- if (checksum != 0x00 && checksum == chksum) {
- csn++;
- serial_identifier[csn][iteration] >>= 1;
- serial_identifier[csn][iteration] |= bit;
- CARDSELECTNUMBER;
-#ifdef EDEBUG
- printf("Writing csn: %d", csn);
-#endif
- WRITE_DATA(csn);
- udelay(250);
- iteration++;
- /* Force all cards without a CSN into Isolation state */
- Wake(0);
- SetRdPort(read_port);
- udelay(1000);
- SERIALISOLATION;
- udelay(1000);
- goto __next;
- }
- if (iteration == 1) {
- read_port += READ_ADDR_STEP;
- if (isapnp_isolate_rdp_select() < 0)
- return -1;
- } else if (iteration > 1) {
+
+ /* If we didn't see a valid ISAPnP device, stop here */
+ if ( ( ! seen55aa ) ||
+ ( identifier.checksum != isapnp_checksum (&identifier) ) )
break;
- }
- __next:
- checksum = 0x6a;
- chksum = 0x00;
- bit = 0x00;
+
+ /* Give the device a CSN */
+ isapnp_max_csn++;
+ DBG ( "ISAPnP isolation found device "
+ "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx:%hhx "
+ "(checksum %hhx), assigning CSN %hhx\n",
+ identifier.bytes[0], identifier.bytes[1],
+ identifier.bytes[2], identifier.bytes[3],
+ identifier.bytes[4], identifier.bytes[5],
+ identifier.bytes[6], identifier.bytes[7],
+ identifier.checksum, isapnp_max_csn );
+
+ isapnp_write_csn ( isapnp_max_csn );
+ udelay ( 1000 );
+
+ /* Send this card back to Sleep and force all cards
+ * without a CSN into Isolation state
+ */
+ isapnp_wake ( 0x00 );
+ udelay ( 1000 );
}
- return csn;
+
+ /* Place all cards in Wait for Key state */
+ isapnp_wait_for_key ();
+
+ /* Return number of cards found */
+ DBG ( "ISAPnP found %d devices at read port %hx\n", isapnp_read_port );
+ return isapnp_max_csn;
}
/*
+ * Isolate all ISAPnP cards, locating a valid read port in the process.
+ *
+ */
+static void isapnp_isolate ( void ) {
+ for ( isapnp_read_port = ISAPNP_READ_PORT_MIN ;
+ 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 () )
+ return;
+ }
+}
+
+
+
+
+
+
+/*
* Build device list for all present ISA PnP devices.
*/
static int isapnp_build_device_list(void)
@@ -277,20 +381,6 @@ int Config(int csn)
return 1;
}
-static void send_key(void)
-{
- int i;
- /* Ask for access to the Wait for Key command - ConfigControl register */
- CONFIGCONTROL;
- /* Write the Wait for Key Command to the ConfigControl Register */
- WRITE_DATA(CONFIG_WAIT_FOR_KEY);
- /* As per doc. Two Write cycles of 0x00 required befor the Initialization key is sent */
- ADDRESS(0);
- ADDRESS(0);
- /* 32 writes of the initiation key to the card */
- for (i = 0; i < INIT_LENGTH; i++)
- ADDRESS(initdata[i]);
-}
static void isapnp_peek(unsigned char *data, int bytes)
{
@@ -316,67 +406,111 @@ static void isapnp_peek(unsigned char *data, int bytes)
}
}
+
+
+
/*
- * Compute ISA PnP checksum for first eight bytes.
+ * Ensure that there is sufficient space in the shared dev_bus
+ * structure for a struct isapnp_device.
+ *
*/
-static unsigned char isapnp_checksum(unsigned char *data)
-{
- int i, j;
- unsigned char checksum = 0x6a, bit, b;
-
- for (i = 0; i < 8; i++) {
- b = data[i];
- for (j = 0; j < 8; j++) {
- bit = 0;
- if (b & (1 << j))
- bit = 1;
- checksum =
- ((((checksum ^ (checksum >> 1)) & 0x01) ^ bit)
- << 7) | (checksum >> 1);
- }
+DEV_BUS( struct isapnp_device, isapnp_dev );
+static char isapnp_magic[0]; /* guaranteed unique symbol */
+
+/*
+ * Fill in parameters for an ISAPnP device based on CSN
+ *
+ * Return 1 if device present, 0 otherwise
+ *
+ */
+static int fill_isapnp_device ( struct isapnp_device *isapnp ) {
+
+ /*
+ * Ensure that all ISAPnP cards have CSNs allocated to them,
+ * if we haven't already done so.
+ *
+ */
+ if ( ! isapnp_read_port ) {
+ isapnp_isolate();
}
- return checksum;
+
+ /* wake csn, read config, send card to sleep */
+
+ DBG ( "ISAPnP found CSN %hhx ID %hx:%hx (\"%s\")\n",
+ isapnp->csn, isapnp->vendor_id, isapnp->prod_id,
+ isa_id_string ( isapnp->vendor_id, isapnp->prod_id ) );
+
+ return 0;
}
-static int isapnp_next_rdp(void)
-{
- int rdp = read_port;
- while (rdp <= 0x3ff) {
- /*
- * We cannot use NE2000 probe spaces for ISAPnP or we
- * will lock up machines.
- */
- if ((rdp < 0x280 || rdp > 0x380)) {
- read_port = rdp;
- return 0;
- }
- rdp += READ_ADDR_STEP;
+
+/*
+ * Find an ISAPnP device matching the specified driver
+ *
+ */
+int find_isapnp_device ( struct isapnp_device *isapnp,
+ struct isapnp_driver *driver ) {
+ unsigned int i;
+
+ /* Initialise struct isapnp if it's the first time it's been used. */
+ if ( isapnp->magic != isapnp_magic ) {
+ memset ( isapnp, 0, sizeof ( *isapnp ) );
+ isapnp->magic = isapnp_magic;
+ isapnp->csn = 1;
}
- return -1;
-}
-static int isapnp_isolate_rdp_select(void)
-{
- send_key();
- /* Control: reset CSN and conditionally everything else too */
- CONFIGCONTROL;
- WRITE_DATA((CONFIG_RESET_CSN | CONFIG_WAIT_FOR_KEY));
- mdelay(2);
-
- send_key();
- Wake(0);
-
- if (isapnp_next_rdp() < 0) {
- /* Ask for access to the Wait for Key command - ConfigControl register */
- CONFIGCONTROL;
- /* Write the Wait for Key Command to the ConfigControl Register */
- WRITE_DATA(CONFIG_WAIT_FOR_KEY);
- return -1;
+ /* Iterate through all possible ISAPNP CSNs, starting where we
+ * left off.
+ */
+ for ( ; isapnp->csn <= isapnp_max_csn ; isapnp->csn++ ) {
+ /* If we've already used this device, skip it */
+ if ( isapnp->already_tried ) {
+ isapnp->already_tried = 0;
+ continue;
+ }
+
+ /* Fill in device parameters */
+ if ( ! fill_isapnp_device ( isapnp ) ) {
+ continue;
+ }
+
+ /* Compare against driver's ID list */
+ for ( i = 0 ; i < driver->id_count ; i++ ) {
+ struct isapnp_id *id = &driver->ids[i];
+
+ if ( ( isapnp->vendor_id == id->vendor_id ) &&
+ ( ISA_PROD_ID ( isapnp->prod_id ) ==
+ ISA_PROD_ID ( id->prod_id ) ) ) {
+ DBG ( "Device %s (driver %s) matches ID %s\n",
+ id->name, driver->name,
+ isa_id_string ( isapnp->vendor_id,
+ isapnp->prod_id ) );
+ isapnp->name = id->name;
+ isapnp->already_tried = 1;
+ return 1;
+ }
+ }
}
- SetRdPort(read_port);
- udelay(1000);
- SERIALISOLATION;
- udelay(1000);
+ /* No device found */
+ isapnp->csn = 1;
return 0;
}
-#endif /* CONFIG_ISA */
+
+/*
+ * Find the next ISAPNP device that can be used to boot using the
+ * specified driver.
+ *
+ */
+int find_isapnp_boot_device ( struct dev *dev, struct isapnp_driver *driver ) {
+ struct isapnp_device *isapnp = ( struct isapnp_device * ) dev->bus;
+
+ if ( ! find_isapnp_device ( isapnp, driver ) )
+ return 0;
+
+ dev->name = isapnp->name;
+ dev->devid.bus_type = ISA_BUS_TYPE;
+ dev->devid.vendor_id = isapnp->vendor_id;
+ dev->devid.device_id = isapnp->prod_id;
+
+ return 1;
+}
diff --git a/src/include/isapnp.h b/src/include/isapnp.h
index 228823b2..c490e1ec 100644
--- a/src/include/isapnp.h
+++ b/src/include/isapnp.h
@@ -18,69 +18,65 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* Portions of this code:
-* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
+* Copyright (C) 2001 P.J.H.Fox (fox@roestock.demon.co.uk)
*
*
*
* REVISION HISTORY:
* ================
* Version 0.1 April 26, 2002 TJL
-* Version 0.2 01/08/2003 TJL Renamed from 3c515_isapnp.h
+* Version 0.2 01/08/2003 TJL Renamed from 3c515_isapnp.h
+*
+*
+* Generalised into an ISAPnP bus that can be used by more than just
+* the 3c515 by Michael Brown <mbrown@fensystems.co.uk>
*
***************************************************************************/
-/*extern int read_port;*/
-/*#define DEBUG*/
-#define ADDRESS_ADDR 0x0279
-#define WRITEDATA_ADDR 0x0a79
-/* MIN and MAX READ_ADDR must have the bottom two bits set */
-#define MIN_READ_ADDR 0x0203
-#define START_READ_ADDR 0x203
-#define MAX_READ_ADDR 0x03ff
-/* READ_ADDR_STEP must be a multiple of 4 */
-#ifndef READ_ADDR_STEP
-#define READ_ADDR_STEP 8
-#endif
-
-#ifdef EDEBUG
-static int x;
-#define ADDRESS(x) (outb(x, ADDRESS_ADDR), printf("\nAddress: %hX", x))
-#define WRITE_DATA(x) (outb(x, WRITEDATA_ADDR), printf(" WR(%hX)", x & 0xff))
-#define READ_DATA (x = inb(read_port), printf(" RD(%hX)", x & 0xff), x)
-#define READ_IOPORT(p) (x = inb(p), printf(" [%hX](%hX)", p, x & 0xff), x)
-#else /* !DEBUG */
-#define ADDRESS(x) outb(x, ADDRESS_ADDR)
-#define WRITE_DATA(x) outb(x, WRITEDATA_ADDR)
-#define READ_DATA inb(read_port)
-#define READ_IOPORT(p) inb(p)
-#endif /* !DEBUG */
+#ifndef ISAPNP_H
+#define ISAPNP_H
+#include "isa_ids.h"
+#include "dev.h"
+/*
+ * ISAPnP constants
+ *
+ */
-#define INIT_LENGTH 32
-
-#define INITDATA { 0x6a, 0xb5, 0xda, 0xed, 0xf6, 0xfb, 0x7d, 0xbe,\
- 0xdf, 0x6f, 0x37, 0x1b, 0x0d, 0x86, 0xc3, 0x61,\
- 0xb0, 0x58, 0x2c, 0x16, 0x8b, 0x45, 0xa2, 0xd1,\
- 0xe8, 0x74, 0x3a, 0x9d, 0xce, 0xe7, 0x73, 0x39 }
+/* Port addresses */
+#define ISAPNP_ADDRESS 0x279
+#define ISAPNP_WRITE_DATA 0xa79
+#define ISAPNP_READ_PORT_MIN 0x213 /* ISAPnP spec says 0x203, but
+ * Linux ISAPnP starts at
+ * 0x213 with no explanatory
+ * comment. 0x203 probably
+ * clashes with something. */
+#define ISAPNP_READ_PORT_MAX 0x3ff
+#define ISAPNP_READ_PORT_STEP 0x08 /* Can be any multiple of 4 */
/* Registers */
-#define SetRdPort(x) (ADDRESS(0x00),WRITE_DATA((x)>>2),read_port=((x)|3))
-#define SERIALISOLATION ADDRESS(0x01)
-#define CONFIGCONTROL ADDRESS(0x02)
-#define Wake(x) (ADDRESS(0x03),WRITE_DATA(x))
-#define RESOURCEDATA (ADDRESS(0x04),READ_DATA)
-#define STATUS (ADDRESS(0x05),READ_DATA)
-#define CARDSELECTNUMBER ADDRESS(0x06)
-#define LOGICALDEVICENUMBER ADDRESS(0x07)
-#define ACTIVATE ADDRESS(0x30)
-#define IORANGECHECK ADDRESS(0x31)
+#define ISAPNP_READPORT 0x00
+#define ISAPNP_SERIALISOLATION 0x01
+#define ISAPNP_CONFIGCONTROL 0x02
+#define ISAPNP_WAKE 0x03
+#define ISAPNP_RESOURCEDATA 0x04
+#define ISAPNP_STATUS 0x05
+#define ISAPNP_CARDSELECTNUMBER 0x06
+#define ISAPNP_LOGICALDEVICENUMBER 0x07
+#define ISAPNP_ACTIVATE 0x30
+#define ISAPNP_IORANGECHECK 0x31
+
+/* Bits in the CONFIGCONTROL register */
+#define ISAPNP_CONFIG_RESET ( 1 << 0 )
+#define ISAPNP_CONFIG_WAIT_FOR_KEY ( 1 << 1 )
+#define ISAPNP_CONFIG_RESET_CSN ( 1 << 2 )
+#define ISAPNP_CONFIG_RESET_DRV ( ISAPNP_CONFIG_RESET | \
+ ISAPNP_CONFIG_WAIT_FOR_KEY | \
+ ISAPNP_CONFIG_RESET_CSN )
-/* Bits */
-#define CONFIG_RESET 0x01
-#define CONFIG_WAIT_FOR_KEY 0x02
-#define CONFIG_RESET_CSN 0x04
-#define CONFIG_RESET_DRV 0x07
+/* The LFSR used for the initiation key and for checksumming */
+#define ISAPNP_LFSR_SEED 0x6a
/* Short Tags */
#define PnPVerNo_TAG 0x01
@@ -122,3 +118,70 @@ static int x;
#define RsvdLongE_TAG 0xFE
#define RsvdLongF_TAG 0xFF
#define NewBoard_PSEUDOTAG 0x100
+
+/*
+ * An ISAPnP serial identifier
+ *
+ */
+union isapnp_identifier {
+ char bytes[9];
+ struct {
+ uint16_t vendor_id;
+ uint16_t product_id;
+ uint32_t serial;
+ uint8_t checksum;
+ } __attribute__ (( packed ));
+} __attribute__ (( packed ));
+
+/*
+ * A physical ISAPnP device
+ *
+ */
+struct isapnp_device {
+ char *magic; /* must be first */
+ const char *name;
+ unsigned char csn;
+ uint16_t vendor_id;
+ uint16_t prod_id;
+ int already_tried;
+};
+
+/*
+ * An individual ISAPnP device identified by ID
+ *
+ */
+struct isapnp_id {
+ const char *name;
+ uint16_t vendor_id, prod_id;
+};
+
+/*
+ * An ISAPnP driver, with a device ID (struct isapnp_id) table.
+ *
+ */
+struct isapnp_driver {
+ const char *name;
+ struct isapnp_id *ids;
+ unsigned int id_count;
+};
+
+/*
+ * Define an ISAPnP driver
+ *
+ */
+#define ISAPNP_DRIVER( driver_name, isapnp_ids ) { \
+ .name = driver_name, \
+ .ids = isapnp_ids, \
+ .id_count = sizeof ( isapnp_ids ) / sizeof ( isapnp_ids[0] ), \
+}
+
+/*
+ * Functions in isapnp.c
+ *
+ */
+extern int find_isapnp_device ( struct isapnp_device *isapnp,
+ struct isapnp_driver *driver );
+extern int find_isapnp_boot_device ( struct dev *dev,
+ struct isapnp_driver *driver );
+
+#endif /* ISAPNP_H */