iPXE
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.

Macros

#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.

Macro Definition Documentation

◆ ISAPNP_CARD_ID_FMT

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

Definition at line 85 of file isapnp.c.

Referenced by isapnp_try_isolate().

◆ ISAPNP_CARD_ID_DATA

#define ISAPNP_CARD_ID_DATA ( identifier)
Value:
(identifier)->vendor_id, (identifier)->prod_id, \
isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
(identifier)->serial
uint64_t serial
Serial number.
Definition edd.h:1
uint8_t vendor_id[3]
Definition ib_mad.h:11

Definition at line 86 of file isapnp.c.

86#define ISAPNP_CARD_ID_DATA(identifier) \
87 (identifier)->vendor_id, (identifier)->prod_id, \
88 isa_id_string ( (identifier)->vendor_id, (identifier)->prod_id ), \
89 (identifier)->serial

Referenced by isapnp_try_isolate().

◆ ISAPNP_DEV_ID_FMT

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

Definition at line 90 of file isapnp.c.

◆ ISAPNP_DEV_ID_DATA

#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.

91#define ISAPNP_DEV_ID_DATA(isapnp) \
92 (isapnp)->vendor_id, (isapnp)->prod_id, \
93 isa_id_string ( (isapnp)->vendor_id, (isapnp)->prod_id )

Function Documentation

◆ FILE_LICENCE()

FILE_LICENCE ( GPL2_OR_LATER )

◆ isapnpbus_remove()

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.

734 {
735 struct isapnp_device *isapnp;
736 struct isapnp_device *tmp;
737
738 list_for_each_entry_safe ( isapnp, tmp, &rootdev->dev.children,
739 dev.siblings ) {
740 isapnp_remove ( isapnp );
741 list_del ( &isapnp->dev.siblings );
742 free ( isapnp );
743 }
744}
static void isapnp_remove(struct isapnp_device *isapnp)
Remove an ISAPnP device.
Definition isapnp.c:623
unsigned long tmp
Definition linux_pci.h:65
#define list_for_each_entry_safe(pos, tmp, head, member)
Iterate over entries in a list, safe against deletion of the current entry.
Definition list.h:459
#define list_del(list)
Delete an entry from a list.
Definition list.h:120
static void(* free)(struct refcnt *refcnt))
Definition refcnt.h:55
struct list_head children
Devices attached to this device.
Definition device.h:87
struct list_head siblings
Devices on the same bus.
Definition device.h:85
An ISAPnP device.
Definition isapnp.h:173
struct device dev
Generic device.
Definition isapnp.h:175
struct device dev
Device chain.
Definition device.h:103

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

Referenced by isapnpbus_probe().

◆ isapnp_write_address()

void isapnp_write_address ( unsigned int address)
inlinestatic

Definition at line 95 of file isapnp.c.

95 {
97}
uint64_t address
Base address.
Definition ena.h:13
#define outb(data, io_addr)
Definition io.h:310
#define ISAPNP_ADDRESS
Definition isapnp.h:57

References address, ISAPNP_ADDRESS, and outb.

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

◆ isapnp_write_data()

void isapnp_write_data ( unsigned int data)
inlinestatic

Definition at line 99 of file isapnp.c.

99 {
101}
uint8_t data[48]
Additional event data.
Definition ena.h:11
#define ISAPNP_WRITE_DATA
Definition isapnp.h:58

References data, ISAPNP_WRITE_DATA, and outb.

Referenced by isapnp_write_byte().

◆ isapnp_read_data()

unsigned int isapnp_read_data ( void )
inlinestatic

Definition at line 103 of file isapnp.c.

103 {
104 return inb ( isapnp_read_port );
105}
#define inb(io_addr)
Definition io.h:283
uint16_t isapnp_read_port
ISAPnP Read Port address.
Definition isapnp.c:76

References inb, and isapnp_read_port.

Referenced by isapnp_read_byte(), and isapnp_try_isolate().

◆ isapnp_write_byte()

void isapnp_write_byte ( unsigned int address,
unsigned int value )
inlinestatic

Definition at line 107 of file isapnp.c.

108 {
111}
pseudo_bit_t value[0x00020]
Definition arbel.h:2
static void isapnp_write_address(unsigned int address)
Definition isapnp.c:95
static void isapnp_write_data(unsigned int data)
Definition isapnp.c:99

References address, isapnp_write_address(), isapnp_write_data(), and value.

Referenced by isapnp_activate(), isapnp_deactivate(), isapnp_logicaldevice(), isapnp_reset_csn(), isapnp_set_read_port(), isapnp_wait_for_key(), isapnp_wake(), and isapnp_write_csn().

◆ isapnp_read_byte()

unsigned int isapnp_read_byte ( unsigned int address)
inlinestatic

Definition at line 113 of file isapnp.c.

113 {
115 return isapnp_read_data ();
116}
static unsigned int isapnp_read_data(void)
Definition isapnp.c:103

References address, isapnp_read_data(), and isapnp_write_address().

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

◆ isapnp_read_word()

unsigned int isapnp_read_word ( unsigned int address)
inlinestatic

Definition at line 118 of file isapnp.c.

118 {
119 /* Yes, they're in big-endian order */
120 return ( ( isapnp_read_byte ( address ) << 8 )
121 | isapnp_read_byte ( address + 1 ) );
122}
static unsigned int isapnp_read_byte(unsigned int address)
Definition isapnp.c:113

References address, and isapnp_read_byte().

Referenced by isapnp_read_iobase().

◆ isapnp_set_read_port()

void isapnp_set_read_port ( void )
inlinestatic

Inform cards of a new read port address.

Definition at line 125 of file isapnp.c.

125 {
127}
static void isapnp_write_byte(unsigned int address, unsigned int value)
Definition isapnp.c:107
#define ISAPNP_READPORT
Definition isapnp.h:69

References isapnp_read_port, ISAPNP_READPORT, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

◆ isapnp_serialisolation()

void isapnp_serialisolation ( void )
inlinestatic

Enter the Isolation state.

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

Definition at line 135 of file isapnp.c.

135 {
137}
#define ISAPNP_SERIALISOLATION
Definition isapnp.h:70

References ISAPNP_SERIALISOLATION, and isapnp_write_address().

Referenced by isapnp_try_isolate().

◆ isapnp_wait_for_key()

void isapnp_wait_for_key ( void )
inlinestatic

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.

145 {
147}
#define ISAPNP_CONFIG_WAIT_FOR_KEY
Definition isapnp.h:85
#define ISAPNP_CONFIGCONTROL
Definition isapnp.h:71

References ISAPNP_CONFIG_WAIT_FOR_KEY, ISAPNP_CONFIGCONTROL, and isapnp_write_byte().

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

◆ isapnp_reset_csn()

void isapnp_reset_csn ( void )
inlinestatic

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.

155 {
157}
#define ISAPNP_CONFIG_RESET_CSN
Definition isapnp.h:86

References ISAPNP_CONFIG_RESET_CSN, ISAPNP_CONFIGCONTROL, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

◆ isapnp_wake()

void isapnp_wake ( uint8_t csn)
inlinestatic

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.

170 {
172}
#define ISAPNP_WAKE
Definition isapnp.h:72

References ISAPNP_WAKE, and isapnp_write_byte().

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

◆ isapnp_read_resourcedata()

unsigned int isapnp_read_resourcedata ( void )
inlinestatic

Definition at line 174 of file isapnp.c.

174 {
176}
#define ISAPNP_RESOURCEDATA
Definition isapnp.h:73

References isapnp_read_byte(), and ISAPNP_RESOURCEDATA.

Referenced by isapnp_peek_byte().

◆ isapnp_read_status()

unsigned int isapnp_read_status ( void )
inlinestatic

Definition at line 178 of file isapnp.c.

178 {
180}
#define ISAPNP_STATUS
Definition isapnp.h:74

References isapnp_read_byte(), and ISAPNP_STATUS.

Referenced by isapnp_peek_byte().

◆ isapnp_write_csn()

void isapnp_write_csn ( unsigned int csn)
inlinestatic

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.

192 {
194}
#define ISAPNP_CARDSELECTNUMBER
Definition isapnp.h:75

References ISAPNP_CARDSELECTNUMBER, and isapnp_write_byte().

Referenced by isapnp_try_isolate().

◆ isapnp_logicaldevice()

void isapnp_logicaldevice ( unsigned int logdev)
inlinestatic

Definition at line 196 of file isapnp.c.

196 {
198}
#define ISAPNP_LOGICALDEVICENUMBER
Definition isapnp.h:76

References ISAPNP_LOGICALDEVICENUMBER, and isapnp_write_byte().

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

◆ isapnp_activate()

void isapnp_activate ( unsigned int logdev)
inlinestatic

Definition at line 200 of file isapnp.c.

200 {
201 isapnp_logicaldevice ( logdev );
203}
static void isapnp_logicaldevice(unsigned int logdev)
Definition isapnp.c:196
#define ISAPNP_ACTIVATE
Definition isapnp.h:77

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

Referenced by isapnp_device_activation().

◆ isapnp_deactivate()

void isapnp_deactivate ( unsigned int logdev)
inlinestatic

Definition at line 205 of file isapnp.c.

205 {
206 isapnp_logicaldevice ( logdev );
208}

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

◆ isapnp_read_iobase()

unsigned int isapnp_read_iobase ( unsigned int index)
inlinestatic

Definition at line 210 of file isapnp.c.

210 {
211 return isapnp_read_word ( ISAPNP_IOBASE ( index ) );
212}
long index
Definition bigint.h:65
static unsigned int isapnp_read_word(unsigned int address)
Definition isapnp.c:118
#define ISAPNP_IOBASE(n)
Definition isapnp.h:79

References index, ISAPNP_IOBASE, and isapnp_read_word().

Referenced by isapnpbus_probe().

◆ isapnp_read_irqno()

unsigned int isapnp_read_irqno ( unsigned int index)
inlinestatic

Definition at line 214 of file isapnp.c.

214 {
215 return isapnp_read_byte ( ISAPNP_IRQNO ( index ) );
216}
#define ISAPNP_IRQNO(n)
Definition isapnp.h:80

References index, ISAPNP_IRQNO, and isapnp_read_byte().

Referenced by isapnpbus_probe().

◆ isapnp_delay()

void isapnp_delay ( void )
static

Definition at line 218 of file isapnp.c.

218 {
219 udelay ( 1000 );
220}
void udelay(unsigned long usecs)
Delay for a fixed number of microseconds.
Definition timer.c:61

References udelay().

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

◆ isapnp_lfsr_next()

unsigned int isapnp_lfsr_next ( unsigned int lfsr,
unsigned int input_bit )
inlinestatic

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.

237 {
238 register uint8_t lfsr_next;
239
240 lfsr_next = lfsr >> 1;
241 lfsr_next |= ( ( ( lfsr ^ lfsr_next ) ^ input_bit ) ) << 7;
242 return lfsr_next;
243}
unsigned char uint8_t
Definition stdint.h:10

Referenced by isapnp_checksum(), and isapnp_send_key().

◆ isapnp_send_key()

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.

251 {
252 unsigned int i;
253 unsigned int lfsr;
254
255 isapnp_delay();
256 isapnp_write_address ( 0x00 );
257 isapnp_write_address ( 0x00 );
258
259 lfsr = ISAPNP_LFSR_SEED;
260 for ( i = 0 ; i < 32 ; i++ ) {
261 isapnp_write_address ( lfsr );
262 lfsr = isapnp_lfsr_next ( lfsr, 0 );
263 }
264}
static unsigned int isapnp_lfsr_next(unsigned int lfsr, unsigned int input_bit)
Linear feedback shift register.
Definition isapnp.c:236
static void isapnp_delay(void)
Definition isapnp.c:218
#define ISAPNP_LFSR_SEED
Definition isapnp.h:92

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

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

◆ isapnp_checksum()

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.

272 {
273 unsigned int i, j;
274 unsigned int lfsr;
275 unsigned int byte;
276
277 lfsr = ISAPNP_LFSR_SEED;
278 for ( i = 0 ; i < 8 ; i++ ) {
279 byte = * ( ( ( uint8_t * ) identifier ) + i );
280 for ( j = 0 ; j < 8 ; j++ ) {
281 lfsr = isapnp_lfsr_next ( lfsr, byte );
282 byte >>= 1;
283 }
284 }
285 return lfsr;
286}
unsigned char byte
Definition smc9000.h:38

References isapnp_lfsr_next(), and ISAPNP_LFSR_SEED.

Referenced by isapnp_try_isolate().

◆ isapnp_peek_byte()

unsigned int isapnp_peek_byte ( void )
inlinestatic

Definition at line 293 of file isapnp.c.

293 {
294 unsigned int i;
295
296 /* Wait for data to be ready */
297 for ( i = 0 ; i < 20 ; i++ ) {
298 if ( isapnp_read_status() & 0x01 ) {
299 /* Byte ready - read it */
301 }
302 isapnp_delay();
303 }
304 /* Data never became ready - return 0xff */
305 return 0xff;
306}
static unsigned int isapnp_read_status(void)
Definition isapnp.c:178
static unsigned int isapnp_read_resourcedata(void)
Definition isapnp.c:174

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

Referenced by isapnp_find_tag(), and isapnp_peek().

◆ isapnp_peek()

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.

317 {
318 unsigned int i;
319 unsigned int byte;
320
321 for ( i = 0 ; i < len ; i++) {
322 byte = isapnp_peek_byte();
323 if ( buf )
324 * ( ( uint8_t * ) buf + i ) = byte;
325 }
326}
ring len
Length.
Definition dwmac.h:226
static unsigned int isapnp_peek_byte(void)
Definition isapnp.c:293

References isapnp_peek_byte(), and len.

Referenced by isapnp_find_tag(), and isapnpbus_probe().

◆ isapnp_find_tag()

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.

339 {
340 unsigned int tag;
341 unsigned int tag_len;
342
343 DBG2 ( "ISAPnP read tag" );
344 do {
346 if ( ISAPNP_IS_SMALL_TAG ( tag ) ) {
347 tag_len = ISAPNP_SMALL_TAG_LEN ( tag );
349 } else {
350 tag_len = ( isapnp_peek_byte() +
351 ( isapnp_peek_byte() << 8 ) );
353 }
354 DBG2 ( " %02x (%02x)", tag, tag_len );
355 if ( tag == wanted_tag ) {
356 if ( len > tag_len )
357 len = tag_len;
358 isapnp_peek ( buf, len );
359 DBG2 ( "\n" );
360 return 0;
361 } else {
362 isapnp_peek ( NULL, tag_len );
363 }
364 } while ( tag != ISAPNP_TAG_END );
365 DBG2 ( "\n" );
366 return -ENOENT;
367}
#define NULL
NULL pointer (VOID *)
Definition Base.h:322
uint64_t tag
Identity tag.
Definition edd.h:1
#define DBG2(...)
Definition compiler.h:515
#define ENOENT
No such file or directory.
Definition errno.h:515
static void isapnp_peek(void *buf, size_t len)
Read resource data.
Definition isapnp.c:317
#define ISAPNP_SMALL_TAG_LEN(tag)
Definition isapnp.h:97
#define ISAPNP_IS_SMALL_TAG(tag)
Definition isapnp.h:95
#define ISAPNP_SMALL_TAG_NAME(tag)
Definition isapnp.h:96
#define ISAPNP_TAG_END
Definition isapnp.h:112
#define ISAPNP_LARGE_TAG_NAME(tag)
Definition isapnp.h:115

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, len, NULL, and tag.

Referenced by isapnp_find_logdevid().

◆ isapnp_find_logdevid()

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.

377 {
378 unsigned int i;
379 int rc;
380
381 for ( i = 0 ; i <= logdev ; i++ ) {
382 if ( ( rc = isapnp_find_tag ( ISAPNP_TAG_LOGDEVID, logdevid,
383 sizeof ( *logdevid ) ) ) != 0 )
384 return rc;
385 }
386 return 0;
387}
struct arbelprm_rc_send_wqe rc
Definition arbel.h:3
static int isapnp_find_tag(unsigned int wanted_tag, void *buf, size_t len)
Find a tag within the resource data.
Definition isapnp.c:339
#define ISAPNP_TAG_LOGDEVID
Definition isapnp.h:99

References isapnp_find_tag(), ISAPNP_TAG_LOGDEVID, and rc.

Referenced by isapnpbus_probe().

◆ isapnp_try_isolate()

int isapnp_try_isolate ( void )
static

Try isolating ISAPnP cards at the current read port.

Return values

>0 Number of ISAPnP cards found

Return values
0There 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 400 of file isapnp.c.

400 {
401 struct isapnp_identifier identifier;
402 unsigned int i, j;
403 unsigned int seen_55aa, seen_life;
404 unsigned int csn = 0;
405 unsigned int data;
406 unsigned int byte;
407
408 DBG ( "ISAPnP attempting isolation at read port %04x\n",
410
411 /* Place all cards into the Sleep state, whatever state
412 * they're currently in.
413 */
416
417 /* Reset all assigned CSNs */
419 isapnp_delay();
420 isapnp_delay();
421
422 /* Place all cards into the Isolation state */
425 isapnp_wake ( 0x00 );
426
427 /* Set the read port */
429 isapnp_delay();
430
431 while ( 1 ) {
432
433 /* All cards that do not have assigned CSNs are
434 * currently in the Isolation state, each time we go
435 * through this loop.
436 */
437
438 /* Initiate serial isolation */
440 isapnp_delay();
441
442 /* Read identifier serially via the ISAPnP read port. */
443 memset ( &identifier, 0, sizeof ( identifier ) );
444 seen_55aa = seen_life = 0;
445 for ( i = 0 ; i < 9 ; i++ ) {
446 byte = 0;
447 for ( j = 0 ; j < 8 ; j++ ) {
449 isapnp_delay();
450 data = ( ( data << 8 ) | isapnp_read_data() );
451 isapnp_delay();
452 byte >>= 1;
453 if ( data != 0xffff ) {
454 seen_life++;
455 if ( data == 0x55aa ) {
456 byte |= 0x80;
457 seen_55aa++;
458 }
459 }
460 }
461 *( ( ( uint8_t * ) &identifier ) + i ) = byte;
462 }
463
464 /* If we didn't see any 55aa patterns, stop here */
465 if ( ! seen_55aa ) {
466 if ( csn ) {
467 DBG ( "ISAPnP found no more cards\n" );
468 } else {
469 if ( seen_life ) {
470 DBG ( "ISAPnP saw life but no cards, "
471 "trying new read port\n" );
472 csn = -1;
473 } else {
474 DBG ( "ISAPnP saw no signs of life, "
475 "abandoning isolation\n" );
476 }
477 }
478 break;
479 }
480
481 /* If the checksum was invalid stop here */
482 if ( identifier.checksum != isapnp_checksum ( &identifier) ) {
483 DBG ( "ISAPnP found malformed card "
484 ISAPNP_CARD_ID_FMT "\n with checksum %02x "
485 "(should be %02x), trying new read port\n",
486 ISAPNP_CARD_ID_DATA ( &identifier ),
487 identifier.checksum,
488 isapnp_checksum ( &identifier) );
489 csn = -1;
490 break;
491 }
492
493 /* Give the device a CSN */
494 csn++;
495 DBG ( "ISAPnP found card " ISAPNP_CARD_ID_FMT
496 ", assigning CSN %02x\n",
497 ISAPNP_CARD_ID_DATA ( &identifier ), csn );
498
499 isapnp_write_csn ( csn );
500 isapnp_delay();
501
502 /* Send this card back to Sleep and force all cards
503 * without a CSN into Isolation state
504 */
505 isapnp_wake ( 0x00 );
506 isapnp_delay();
507 }
508
509 /* Place all cards in Wait for Key state */
511
512 /* Return number of cards found */
513 if ( csn > 0 ) {
514 DBG ( "ISAPnP found %d cards at read port %04x\n",
515 csn, isapnp_read_port );
516 }
517 return csn;
518}
#define DBG(...)
Print a debugging message.
Definition compiler.h:498
void * memset(void *dest, int character, size_t len) __nonnull
#define ISAPNP_CARD_ID_FMT
Definition isapnp.c:85
static void isapnp_wake(uint8_t csn)
Place a specified card into the Config state.
Definition isapnp.c:170
static void isapnp_wait_for_key(void)
Enter the Wait for Key state.
Definition isapnp.c:145
#define ISAPNP_CARD_ID_DATA(identifier)
Definition isapnp.c:86
static void isapnp_reset_csn(void)
Reset (i.e.
Definition isapnp.c:155
static void isapnp_write_csn(unsigned int csn)
Assign a Card Select Number to a card, and enter the Config state.
Definition isapnp.c:192
static void isapnp_serialisolation(void)
Enter the Isolation state.
Definition isapnp.c:135
static void isapnp_send_key(void)
Send the ISAPnP initiation key.
Definition isapnp.c:251
static void isapnp_set_read_port(void)
Inform cards of a new read port address.
Definition isapnp.c:125
static unsigned int isapnp_checksum(struct isapnp_identifier *identifier)
Compute ISAPnP identifier checksum.
Definition isapnp.c:272
An ISAPnP serial identifier.
Definition isapnp.h:141

References isapnp_identifier::checksum, 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().

◆ isapnp_isolate()

void isapnp_isolate ( void )
static

Find a valid read port and isolate all ISAPnP cards.

Definition at line 524 of file isapnp.c.

524 {
528 /* Avoid problematic locations such as the NE2000
529 * probe space
530 */
531 if ( ( isapnp_read_port >= 0x280 ) &&
532 ( isapnp_read_port <= 0x380 ) )
533 continue;
534
535 /* If we detect any ISAPnP cards at this location, stop */
536 if ( isapnp_try_isolate() >= 0 )
537 return;
538 }
539}
static int isapnp_try_isolate(void)
Try isolating ISAPnP cards at the current read port.
Definition isapnp.c:400
#define ISAPNP_READ_PORT_START
Definition isapnp.h:60
#define ISAPNP_READ_PORT_MAX
Definition isapnp.h:61
#define ISAPNP_READ_PORT_STEP
Definition isapnp.h:62

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

Referenced by isapnpbus_probe().

◆ isapnp_device_activation()

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.

555 {
556 /* Wake the card and select the logical device */
559 isapnp_wake ( isapnp->csn );
560 isapnp_logicaldevice ( isapnp->logdev );
561
562 /* Activate/deactivate the logical device */
563 isapnp_activate ( activation );
564 isapnp_delay();
565
566 /* Return all cards to Wait for Key state */
568
569 DBG ( "ISAPnP %s device %02x:%02x\n",
570 ( activation ? "activated" : "deactivated" ),
571 isapnp->csn, isapnp->logdev );
572}
static void isapnp_activate(unsigned int logdev)
Definition isapnp.c:200
uint8_t csn
Card Select Number.
Definition isapnp.h:185
uint8_t logdev
Logical Device ID.
Definition isapnp.h:187

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 deactivate_isapnp_device(), and isapnp_set_drvdata().

◆ isapnp_probe()

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.

583 {
584 struct isapnp_driver *driver;
585 struct isapnp_device_id *id;
586 unsigned int i;
587 int rc;
588
589 DBG ( "Adding ISAPnP device %02x:%02x (%04x:%04x (\"%s\") "
590 "io %x irq %d)\n", isapnp->csn, isapnp->logdev,
591 isapnp->vendor_id, isapnp->prod_id,
592 isa_id_string ( isapnp->vendor_id, isapnp->prod_id ),
593 isapnp->ioaddr, isapnp->irqno );
594
596 for ( i = 0 ; i < driver->id_count ; i++ ) {
597 id = &driver->ids[i];
598 if ( id->vendor_id != isapnp->vendor_id )
599 continue;
600 if ( ISA_PROD_ID ( id->prod_id ) !=
601 ISA_PROD_ID ( isapnp->prod_id ) )
602 continue;
603 isapnp->driver = driver;
604 isapnp->dev.driver_name = id->name;
605 DBG ( "...using driver %s\n", isapnp->dev.driver_name );
606 if ( ( rc = driver->probe ( isapnp, id ) ) != 0 ) {
607 DBG ( "......probe failed\n" );
608 continue;
609 }
610 return 0;
611 }
612 }
613
614 DBG ( "...no driver found\n" );
615 return -ENOTTY;
616}
uint8_t id
Request identifier.
Definition ena.h:1
#define ENOTTY
Inappropriate I/O control operation.
Definition errno.h:595
char * isa_id_string(unsigned int vendor, unsigned int product)
Definition isa_ids.c:11
#define ISA_PROD_ID(product)
Definition isa_ids.h:45
#define ISAPNP_DRIVERS
ISAPnP driver table.
Definition isapnp.h:222
const char * driver_name
Driver name.
Definition device.h:81
An ISAPnP device ID list entry.
Definition isapnp.h:163
uint16_t ioaddr
I/O address.
Definition isapnp.h:181
uint16_t prod_id
Product ID.
Definition isapnp.h:179
uint8_t irqno
Interrupt number.
Definition isapnp.h:183
struct isapnp_driver * driver
Driver for this device.
Definition isapnp.h:189
uint16_t vendor_id
Vendor ID.
Definition isapnp.h:177
An ISAPnP driver.
Definition isapnp.h:199
int(* probe)(struct isapnp_device *isapnp, const struct isapnp_device_id *id)
Probe device.
Definition isapnp.h:211
struct isapnp_device_id * ids
ISAPnP ID table.
Definition isapnp.h:201
unsigned int id_count
Number of entries in ISAPnP ID table.
Definition isapnp.h:203
#define for_each_table_entry(pointer, table)
Iterate through all entries within a linker table.
Definition tables.h:386

References isapnp_device::csn, DBG, isapnp_device::dev, isapnp_device::driver, 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::prod_id, rc, and isapnp_device::vendor_id.

Referenced by isapnpbus_probe().

◆ isapnp_remove()

void isapnp_remove ( struct isapnp_device * isapnp)
static

Remove an ISAPnP device.

Parameters
isapnpISAPnP device

Definition at line 623 of file isapnp.c.

623 {
624 isapnp->driver->remove ( isapnp );
625 DBG ( "Removed ISAPnP device %02x:%02x\n",
626 isapnp->csn, isapnp->logdev );
627}
void(* remove)(struct isapnp_device *isapnp)
Remove device.
Definition isapnp.h:218

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

Referenced by isapnpbus_remove().

◆ isapnpbus_probe()

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.

637 {
638 struct isapnp_device *isapnp = NULL;
639 struct isapnp_identifier identifier;
640 struct isapnp_logdevid logdevid;
641 unsigned int csn;
642 unsigned int logdev;
643 int rc;
644
645 /* Perform isolation if it hasn't yet been done */
646 if ( ! isapnp_read_port )
648
649 for ( csn = 1 ; csn <= 0xff ; csn++ ) {
650 for ( logdev = 0 ; logdev <= 0xff ; logdev++ ) {
651
652 /* Allocate struct isapnp_device */
653 if ( ! isapnp )
654 isapnp = malloc ( sizeof ( *isapnp ) );
655 if ( ! isapnp ) {
656 rc = -ENOMEM;
657 goto err;
658 }
659 memset ( isapnp, 0, sizeof ( *isapnp ) );
660 isapnp->csn = csn;
661 isapnp->logdev = logdev;
662
663 /* Wake the card */
666 isapnp_wake ( csn );
667
668 /* Read the card identifier */
669 isapnp_peek ( &identifier, sizeof ( identifier ) );
670
671 /* No card with this CSN; stop here */
672 if ( identifier.vendor_id & 0x80 )
673 goto done;
674
675 /* Find the Logical Device ID tag */
676 if ( ( rc = isapnp_find_logdevid ( logdev,
677 &logdevid ) ) != 0){
678 /* No more logical devices; go to next CSN */
679 break;
680 }
681
682 /* Select the logical device */
683 isapnp_logicaldevice ( logdev );
684
685 /* Populate struct isapnp_device */
686 isapnp->vendor_id = logdevid.vendor_id;
687 isapnp->prod_id = logdevid.prod_id;
688 isapnp->ioaddr = isapnp_read_iobase ( 0 );
689 isapnp->irqno = isapnp_read_irqno ( 0 );
690
691 /* Return all cards to Wait for Key state */
693
694 /* Add to device hierarchy */
695 snprintf ( isapnp->dev.name,
696 sizeof ( isapnp->dev.name ),
697 "ISAPnP%02x:%02x", csn, logdev );
699 isapnp->dev.desc.vendor = isapnp->vendor_id;
700 isapnp->dev.desc.device = isapnp->prod_id;
701 isapnp->dev.desc.ioaddr = isapnp->ioaddr;
702 isapnp->dev.desc.irq = isapnp->irqno;
703 isapnp->dev.parent = &rootdev->dev;
704 list_add ( &isapnp->dev.siblings,
705 &rootdev->dev.children );
706 INIT_LIST_HEAD ( &isapnp->dev.children );
707
708 /* Look for a driver */
709 if ( isapnp_probe ( isapnp ) == 0 ) {
710 /* isapnpdev registered, we can drop our ref */
711 isapnp = NULL;
712 } else {
713 /* Not registered; re-use struct */
714 list_del ( &isapnp->dev.siblings );
715 }
716 }
717 }
718
719 done:
720 free ( isapnp );
721 return 0;
722
723 err:
724 free ( isapnp );
725 isapnpbus_remove ( rootdev );
726 return rc;
727}
struct bofm_section_header done
Definition bofm_test.c:46
#define BUS_TYPE_ISAPNP
ISAPnP bus type.
Definition device.h:47
#define ENOMEM
Not enough space.
Definition errno.h:535
static int isapnp_find_logdevid(unsigned int logdev, struct isapnp_logdevid *logdevid)
Find specified Logical Device ID tag.
Definition isapnp.c:376
static unsigned int isapnp_read_irqno(unsigned int index)
Definition isapnp.c:214
static int isapnp_probe(struct isapnp_device *isapnp)
Probe an ISAPnP device.
Definition isapnp.c:583
static void isapnpbus_remove(struct root_device *rootdev)
Remove ISAPnP root bus.
Definition isapnp.c:734
static unsigned int isapnp_read_iobase(unsigned int index)
Definition isapnp.c:210
static void isapnp_isolate(void)
Find a valid read port and isolate all ISAPnP cards.
Definition isapnp.c:524
#define INIT_LIST_HEAD(list)
Initialise a list head.
Definition list.h:46
#define list_add(new, head)
Add a new entry to the head of a list.
Definition list.h:70
void * malloc(size_t size)
Allocate memory.
Definition malloc.c:621
unsigned int bus_type
Bus type.
Definition device.h:25
unsigned int device
Device ID.
Definition device.h:34
unsigned int vendor
Vendor ID.
Definition device.h:32
unsigned int irq
IRQ.
Definition device.h:40
unsigned long ioaddr
I/O address.
Definition device.h:38
struct device_description desc
Device description.
Definition device.h:83
struct device * parent
Bus device.
Definition device.h:89
char name[40]
Name.
Definition device.h:79
An ISAPnP logical device ID structure.
Definition isapnp.h:153
int snprintf(char *buf, size_t size, const char *fmt,...)
Write a formatted string to a buffer.
Definition vsprintf.c:383

References device_description::bus_type, BUS_TYPE_ISAPNP, device::children, isapnp_device::csn, device::desc, isapnp_device::dev, root_device::dev, device_description::device, done, 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_device::prod_id, isapnp_logdevid::prod_id, rc, device::siblings, snprintf(), device_description::vendor, isapnp_device::vendor_id, isapnp_identifier::vendor_id, and isapnp_logdevid::vendor_id.

Variable Documentation

◆ isapnp_read_port

uint16_t isapnp_read_port

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 activate_isapnp_device(), isapnp_isolate(), isapnp_read_data(), isapnp_set_read_port(), isapnp_try_isolate(), isapnpbus_probe(), and pxenv_start_undi().

◆ isapnp_root_driver

struct root_driver isapnp_root_driver
static
Initial value:
= {
.probe = isapnpbus_probe,
.remove = isapnpbus_remove,
}
static int isapnpbus_probe(struct root_device *rootdev)
Probe ISAPnP root bus.
Definition isapnp.c:637

ISAPnP bus root device driver.

Definition at line 747 of file isapnp.c.

747 {
748 .probe = isapnpbus_probe,
749 .remove = isapnpbus_remove,
750};

◆ __root_device

struct root_device isapnp_root_device __root_device
Initial value:
= {
.dev = { .name = "ISAPnP" },
.driver = &isapnp_root_driver,
}
static struct root_driver isapnp_root_driver
ISAPnP bus root device driver.
Definition isapnp.c:747

ISAPnP bus root device.

Definition at line 753 of file isapnp.c.

753 {
754 .dev = { .name = "ISAPnP" },
755 .driver = &isapnp_root_driver,
756};