david/ipxe
david
/
ipxe
Archived
1
0
Fork 0

Extraced from 3c509.c

This commit is contained in:
Michael Brown 2005-04-13 12:45:38 +00:00
parent a4f1a058a4
commit 200b39a645
2 changed files with 212 additions and 0 deletions

136
src/drivers/bus/eisa.c Normal file
View File

@ -0,0 +1,136 @@
#include "etherboot.h"
#include "dev.h"
#include "io.h"
#include "timer.h"
#include "eisa.h"
#define DEBUG_EISA
#undef DBG
#ifdef DEBUG_EISA
#define DBG(...) printf ( __VA_ARGS__ )
#else
#define DBG(...)
#endif
/*
* Fill in parameters for an EISA device based on slot number
*
* Return 1 if device present, 0 otherwise
*
*/
static int fill_eisa_device ( struct eisa_device *eisa ) {
uint8_t present;
/* Set ioaddr */
eisa->ioaddr = EISA_SLOT_BASE ( eisa->slot );
/* Test for board present */
outb ( 0xff, eisa->ioaddr + EISA_MFG_ID_HI );
present = inb ( eisa->ioaddr + EISA_MFG_ID_HI );
if ( present & 0x80 ) {
/* No board present */
return 0;
}
/* Read mfg and product IDs. Yes, the resulting uint16_ts
* will be upside-down. This appears to be by design.
*/
eisa->mfg_id = ( inb ( eisa->ioaddr + EISA_MFG_ID_LO ) << 8 )
+ present;
eisa->prod_id = ( inb ( eisa->ioaddr + EISA_PROD_ID_LO ) << 8 )
+ inb ( eisa->ioaddr + EISA_PROD_ID_HI );
DBG ( "EISA slot %d (base %#hx) ID %hx:%hx (\"%s\")\n",
eisa->slot, eisa->ioaddr, eisa->mfg_id, eisa->prod_id,
isa_id_string ( eisa->mfg_id, eisa->prod_id ) );
return 1;
}
/*
* Obtain a struct eisa * from a struct dev *
*
* If dev has not previously been used for an EISA device scan, blank
* out dev.eisa
*/
struct eisa_device * eisa_device ( struct dev *dev ) {
struct eisa_device *eisa = &dev->eisa;
if ( dev->devid.bus_type != EISA_BUS_TYPE ) {
memset ( eisa, 0, sizeof ( *eisa ) );
dev->devid.bus_type = EISA_BUS_TYPE;
eisa->slot = EISA_MIN_SLOT;
}
eisa->dev = dev;
return eisa;
}
/*
* Find an EISA device matching the specified driver
*
*/
int find_eisa_device ( struct eisa_device *eisa, struct eisa_driver *driver ) {
unsigned int i;
/* Iterate through all possible EISA slots, starting where we
* left off/
*/
for ( ; eisa->slot <= EISA_MAX_SLOT ; eisa->slot++ ) {
/* If we've already used this device, skip it */
if ( eisa->already_tried ) {
eisa->already_tried = 0;
continue;
}
/* Fill in device parameters */
if ( ! fill_eisa_device ( eisa ) ) {
continue;
}
/* Compare against driver's ID list */
for ( i = 0 ; i < driver->id_count ; i++ ) {
struct eisa_id *id = &driver->ids[i];
if ( ( eisa->mfg_id == id->mfg_id ) &&
( ISA_PROD_ID ( eisa->prod_id ) ==
ISA_PROD_ID ( id->prod_id ) ) ) {
DBG ( "Device %s (driver %s) matches ID %s\n",
id->name, driver->name,
isa_id_string ( eisa->mfg_id,
eisa->prod_id ) );
if ( eisa->dev ) {
eisa->dev->name = driver->name;
eisa->dev->devid.vendor_id
= eisa->mfg_id;
eisa->dev->devid.device_id
= eisa->prod_id;
}
eisa->already_tried = 1;
return 1;
}
}
}
/* No device found */
eisa->slot = EISA_MIN_SLOT;
return 0;
}
/*
* Reset and enable an EISA device
*
*/
void enable_eisa_device ( struct eisa_device *eisa ) {
/* Set reset line high for 1000 µs. Spec says 500 µs, but
* this doesn't work for all cards, so we are conservative.
*/
outb ( EISA_CMD_RESET, eisa->ioaddr + EISA_GLOBAL_CONFIG );
udelay ( 1000 ); /* Must wait 800 */
/* Set reset low and write a 1 to ENABLE. Delay again, in
* case the card takes a while to wake up.
*/
outb ( EISA_CMD_ENABLE, eisa->ioaddr + EISA_GLOBAL_CONFIG );
udelay ( 1000 ); /* Must wait 800 */
}

76
src/include/eisa.h Normal file
View File

@ -0,0 +1,76 @@
#ifndef EISA_H
#define EISA_H
#include "isa_ids.h"
/*
* EISA constants
*
*/
#define EISA_MIN_SLOT (0x1)
#define EISA_MAX_SLOT (0xf)
#define EISA_SLOT_BASE( n ) ( 0x1000 * (n) )
#define EISA_MFG_ID_HI ( 0xc80 )
#define EISA_MFG_ID_LO ( 0xc81 )
#define EISA_PROD_ID_HI ( 0xc82 )
#define EISA_PROD_ID_LO ( 0xc83 )
#define EISA_GLOBAL_CONFIG ( 0xc84 )
#define EISA_CMD_RESET ( 1 << 2 )
#define EISA_CMD_ENABLE ( 1 << 0 )
/*
* A physical EISA device
*
*/
struct dev;
struct eisa_device {
struct dev *dev;
unsigned int slot;
uint16_t ioaddr;
uint16_t mfg_id;
uint16_t prod_id;
int already_tried;
};
/*
* An individual EISA device identified by ID
*
*/
struct eisa_id {
const char *name;
uint16_t mfg_id, prod_id;
};
/*
* An EISA driver, with a device ID (struct eisa_id) table.
*
*/
struct eisa_driver {
const char *name;
struct eisa_id *ids;
unsigned int id_count;
};
/*
* Define an EISA driver
*
*/
#define EISA_DRIVER( driver_name, eisa_ids ) { \
.name = driver_name, \
.ids = eisa_ids, \
.id_count = sizeof ( eisa_ids ) / sizeof ( eisa_ids[0] ), \
}
/*
* Functions in eisa.c
*
*/
extern struct eisa_device * eisa_device ( struct dev *dev );
extern int find_eisa_device ( struct eisa_device *eisa,
struct eisa_driver *driver );
extern void enable_eisa_device ( struct eisa_device *eisa );
#endif /* EISA_H */