mirror of
https://github.com/xcat2/xNBA.git
synced 2024-12-16 08:11:31 +00:00
520d9c36af
ISA 3c509 is currently non-functional, although the EISA (3c509-eisa) and MCA (3c529) variants should build OK. None of this code is yet tested.
305 lines
9.8 KiB
C
305 lines
9.8 KiB
C
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License as
|
|
* published by the Free Software Foundation; either version 2, or (at
|
|
* your option) any later version.
|
|
*/
|
|
|
|
#ifndef NIC_H
|
|
#define NIC_H
|
|
|
|
#include <stdint.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <byteswap.h>
|
|
#include <gpxe/pci.h>
|
|
#include <gpxe/isapnp.h>
|
|
#include <gpxe/isa.h>
|
|
#include <gpxe/eisa.h>
|
|
#include <gpxe/mca.h>
|
|
#include "dhcp.h"
|
|
|
|
typedef enum {
|
|
DISABLE = 0,
|
|
ENABLE,
|
|
FORCE
|
|
} irq_action_t;
|
|
|
|
typedef enum duplex {
|
|
HALF_DUPLEX = 1,
|
|
FULL_DUPLEX
|
|
} duplex_t;
|
|
|
|
/*
|
|
* Structure returned from eth_probe and passed to other driver
|
|
* functions.
|
|
*/
|
|
struct nic {
|
|
struct nic_operations *nic_op;
|
|
int flags; /* driver specific flags */
|
|
unsigned char *node_addr;
|
|
unsigned char *packet;
|
|
unsigned int packetlen;
|
|
unsigned int ioaddr;
|
|
unsigned char irqno;
|
|
unsigned int mbps;
|
|
duplex_t duplex;
|
|
struct dhcp_dev_id dhcp_dev_id;
|
|
void *priv_data; /* driver private data */
|
|
};
|
|
|
|
struct nic_operations {
|
|
int ( *connect ) ( struct nic * );
|
|
int ( *poll ) ( struct nic *, int retrieve );
|
|
void ( *transmit ) ( struct nic *, const char *,
|
|
unsigned int, unsigned int, const char * );
|
|
void ( *irq ) ( struct nic *, irq_action_t );
|
|
};
|
|
|
|
extern struct nic nic;
|
|
|
|
static inline int eth_poll ( int retrieve ) {
|
|
return nic.nic_op->poll ( &nic, retrieve );
|
|
}
|
|
|
|
static inline void eth_transmit ( const char *dest, unsigned int type,
|
|
unsigned int size, const void *packet ) {
|
|
nic.nic_op->transmit ( &nic, dest, type, size, packet );
|
|
}
|
|
|
|
/*
|
|
* Function prototypes
|
|
*
|
|
*/
|
|
extern int dummy_connect ( struct nic *nic );
|
|
extern void dummy_irq ( struct nic *nic, irq_action_t irq_action );
|
|
extern int legacy_probe ( void *hwdev,
|
|
void ( * set_drvdata ) ( void *hwdev, void *priv ),
|
|
struct device *dev,
|
|
int ( * probe ) ( struct nic *nic, void *hwdev ),
|
|
void ( * disable ) ( struct nic *nic, void *hwdev ));
|
|
void legacy_remove ( void *hwdev,
|
|
void * ( * get_drvdata ) ( void *hwdev ),
|
|
void ( * disable ) ( struct nic *nic, void *hwdev ) );
|
|
|
|
#define PCI_DRIVER(_name,_ids,_class) \
|
|
static inline int \
|
|
_name ## _pci_legacy_probe ( struct pci_device *pci, \
|
|
const struct pci_device_id *id ); \
|
|
static inline void \
|
|
_name ## _pci_legacy_remove ( struct pci_device *pci ); \
|
|
struct pci_driver _name __pci_driver = { \
|
|
.ids = _ids, \
|
|
.id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
|
|
.probe = _name ## _pci_legacy_probe, \
|
|
.remove = _name ## _pci_legacy_remove, \
|
|
}; \
|
|
REQUIRE_OBJECT ( pci );
|
|
|
|
static inline void legacy_pci_set_drvdata ( void *hwdev, void *priv ) {
|
|
pci_set_drvdata ( hwdev, priv );
|
|
}
|
|
static inline void * legacy_pci_get_drvdata ( void *hwdev ) {
|
|
return pci_get_drvdata ( hwdev );
|
|
}
|
|
|
|
#define ISAPNP_DRIVER(_name,_ids) \
|
|
static inline int \
|
|
_name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
|
|
const struct isapnp_device_id *id ); \
|
|
static inline void \
|
|
_name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ); \
|
|
struct isapnp_driver _name __isapnp_driver = { \
|
|
.ids = _ids, \
|
|
.id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
|
|
.probe = _name ## _isapnp_legacy_probe, \
|
|
.remove = _name ## _isapnp_legacy_remove, \
|
|
}; \
|
|
REQUIRE_OBJECT ( isapnp );
|
|
|
|
static inline void legacy_isapnp_set_drvdata ( void *hwdev, void *priv ) {
|
|
isapnp_set_drvdata ( hwdev, priv );
|
|
}
|
|
static inline void * legacy_isapnp_get_drvdata ( void *hwdev ) {
|
|
return isapnp_get_drvdata ( hwdev );
|
|
}
|
|
|
|
#define EISA_DRIVER(_name,_ids) \
|
|
static inline int \
|
|
_name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
|
|
const struct eisa_device_id *id ); \
|
|
static inline void \
|
|
_name ## _eisa_legacy_remove ( struct eisa_device *eisa ); \
|
|
struct eisa_driver _name __eisa_driver = { \
|
|
.ids = _ids, \
|
|
.id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
|
|
.probe = _name ## _eisa_legacy_probe, \
|
|
.remove = _name ## _eisa_legacy_remove, \
|
|
}; \
|
|
REQUIRE_OBJECT ( eisa );
|
|
|
|
static inline void legacy_eisa_set_drvdata ( void *hwdev, void *priv ) {
|
|
eisa_set_drvdata ( hwdev, priv );
|
|
}
|
|
static inline void * legacy_eisa_get_drvdata ( void *hwdev ) {
|
|
return eisa_get_drvdata ( hwdev );
|
|
}
|
|
|
|
#define MCA_DRIVER(_name,_ids) \
|
|
static inline int \
|
|
_name ## _mca_legacy_probe ( struct mca_device *mca, \
|
|
const struct mca_device_id *id ); \
|
|
static inline void \
|
|
_name ## _mca_legacy_remove ( struct mca_device *mca ); \
|
|
struct mca_driver _name __mca_driver = { \
|
|
.ids = _ids, \
|
|
.id_count = sizeof ( _ids ) / sizeof ( _ids[0] ), \
|
|
.probe = _name ## _mca_legacy_probe, \
|
|
.remove = _name ## _mca_legacy_remove, \
|
|
}; \
|
|
REQUIRE_OBJECT ( mca );
|
|
|
|
static inline void legacy_mca_set_drvdata ( void *hwdev, void *priv ) {
|
|
mca_set_drvdata ( hwdev, priv );
|
|
}
|
|
static inline void * legacy_mca_get_drvdata ( void *hwdev ) {
|
|
return mca_get_drvdata ( hwdev );
|
|
}
|
|
|
|
#define ISA_DRIVER(_name,_probe_addrs,_probe_addr,_vendor_id,_prod_id) \
|
|
static inline int \
|
|
_name ## _isa_legacy_probe ( struct isa_device *isa ); \
|
|
static inline int \
|
|
_name ## _isa_legacy_probe_at_addr ( struct isa_device *isa ) { \
|
|
if ( ! _probe_addr ( isa->ioaddr ) ) \
|
|
return -ENODEV; \
|
|
return _name ## _isa_legacy_probe ( isa ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _isa_legacy_remove ( struct isa_device *isa ); \
|
|
static const char _name ## _text[]; \
|
|
struct isa_driver _name __isa_driver = { \
|
|
.name = _name ## _text, \
|
|
.probe_addrs = _probe_addrs, \
|
|
.addr_count = ( sizeof ( _probe_addrs ) / \
|
|
sizeof ( _probe_addrs[0] ) ), \
|
|
.vendor_id = _vendor_id, \
|
|
.prod_id = _prod_id, \
|
|
.probe = _name ## _isa_legacy_probe_at_addr, \
|
|
.remove = _name ## _isa_legacy_remove, \
|
|
}; \
|
|
REQUIRE_OBJECT ( isa );
|
|
|
|
static inline void legacy_isa_set_drvdata ( void *hwdev, void *priv ) {
|
|
isa_set_drvdata ( hwdev, priv );
|
|
}
|
|
static inline void * legacy_isa_get_drvdata ( void *hwdev ) {
|
|
return isa_get_drvdata ( hwdev );
|
|
}
|
|
|
|
#undef DRIVER
|
|
#define DRIVER(_name_text,_unused2,_unused3,_name,_probe,_disable) \
|
|
static const char _name ## _text[] = _name_text; \
|
|
static inline int \
|
|
_name ## _probe ( struct nic *nic, void *hwdev ) { \
|
|
return _probe ( nic, hwdev ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _disable ( struct nic *nic, void *hwdev ) { \
|
|
void ( * _unsafe_disable ) () = _disable; \
|
|
_unsafe_disable ( nic, hwdev ); \
|
|
} \
|
|
static inline int \
|
|
_name ## _pci_legacy_probe ( struct pci_device *pci, \
|
|
const struct pci_device_id *id __unused ) { \
|
|
return legacy_probe ( pci, legacy_pci_set_drvdata, \
|
|
&pci->dev, _name ## _probe, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _pci_legacy_remove ( struct pci_device *pci ) { \
|
|
return legacy_remove ( pci, legacy_pci_get_drvdata, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline int \
|
|
_name ## _isapnp_legacy_probe ( struct isapnp_device *isapnp, \
|
|
const struct isapnp_device_id *id __unused ) { \
|
|
return legacy_probe ( isapnp, legacy_isapnp_set_drvdata, \
|
|
&isapnp->dev, _name ## _probe, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _isapnp_legacy_remove ( struct isapnp_device *isapnp ) { \
|
|
return legacy_remove ( isapnp, legacy_isapnp_get_drvdata, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline int \
|
|
_name ## _eisa_legacy_probe ( struct eisa_device *eisa, \
|
|
const struct eisa_device_id *id __unused ) { \
|
|
return legacy_probe ( eisa, legacy_eisa_set_drvdata, \
|
|
&eisa->dev, _name ## _probe, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _eisa_legacy_remove ( struct eisa_device *eisa ) { \
|
|
return legacy_remove ( eisa, legacy_eisa_get_drvdata, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline int \
|
|
_name ## _mca_legacy_probe ( struct mca_device *mca, \
|
|
const struct mca_device_id *id __unused ) { \
|
|
return legacy_probe ( mca, legacy_mca_set_drvdata, \
|
|
&mca->dev, _name ## _probe, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _mca_legacy_remove ( struct mca_device *mca ) { \
|
|
return legacy_remove ( mca, legacy_mca_get_drvdata, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline int \
|
|
_name ## _isa_legacy_probe ( struct isa_device *isa ) { \
|
|
return legacy_probe ( isa, legacy_isa_set_drvdata, \
|
|
&isa->dev, _name ## _probe, \
|
|
_name ## _disable ); \
|
|
} \
|
|
static inline void \
|
|
_name ## _isa_legacy_remove ( struct isa_device *isa ) { \
|
|
return legacy_remove ( isa, legacy_isa_get_drvdata, \
|
|
_name ## _disable ); \
|
|
}
|
|
|
|
static inline void pci_fill_nic ( struct nic *nic, struct pci_device *pci ) {
|
|
nic->ioaddr = pci->ioaddr;
|
|
nic->irqno = pci->irq;
|
|
}
|
|
|
|
static inline void isapnp_fill_nic ( struct nic *nic,
|
|
struct isapnp_device *isapnp ) {
|
|
nic->ioaddr = isapnp->ioaddr;
|
|
nic->irqno = isapnp->irqno;
|
|
}
|
|
|
|
static inline void eisa_fill_nic ( struct nic *nic,
|
|
struct eisa_device *eisa ) {
|
|
nic->ioaddr = eisa->ioaddr;
|
|
nic->irqno = 0;
|
|
}
|
|
|
|
static inline void mca_fill_nic ( struct nic *nic,
|
|
struct mca_device *mca __unused ) {
|
|
/* ioaddr and irqno must be read in a device-dependent way
|
|
* from the POS registers
|
|
*/
|
|
nic->ioaddr = 0;
|
|
nic->irqno = 0;
|
|
}
|
|
|
|
static inline void isa_fill_nic ( struct nic *nic, struct isa_device *isa ) {
|
|
nic->ioaddr = isa->ioaddr;
|
|
nic->irqno = 0;
|
|
}
|
|
|
|
#endif /* NIC_H */
|