freebsd compat. layer: split device structure to handle for miibus devices, added a new network_device.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21094 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
a300c4e4e1
commit
b650951128
@ -36,8 +36,9 @@ pci_module_info *gPci;
|
||||
uint32_t
|
||||
pci_read_config(device_t dev, int offset, int size)
|
||||
{
|
||||
uint32_t value = gPci->read_pci_config(dev->pci_info.bus,
|
||||
dev->pci_info.device, dev->pci_info.function, offset, size);
|
||||
uint32_t value = gPci->read_pci_config(NETDEV(dev)->pci_info.bus,
|
||||
NETDEV(dev)->pci_info.device, NETDEV(dev)->pci_info.function,
|
||||
offset, size);
|
||||
TRACE_PCI(dev, "pci_read_config(%i, %i) = 0x%lx\n", offset, size, value);
|
||||
return value;
|
||||
}
|
||||
@ -48,8 +49,9 @@ pci_write_config(device_t dev, int offset, uint32_t value, int size)
|
||||
{
|
||||
TRACE_PCI(dev, "pci_write_config(%i, 0x%lx, %i)\n", offset, value, size);
|
||||
|
||||
gPci->write_pci_config(dev->pci_info.bus, dev->pci_info.device,
|
||||
dev->pci_info.function, offset, size, value);
|
||||
gPci->write_pci_config(NETDEV(dev)->pci_info.bus,
|
||||
NETDEV(dev)->pci_info.device, NETDEV(dev)->pci_info.function,
|
||||
offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
@ -164,14 +166,10 @@ driver_vprintf(const char *format, va_list vl)
|
||||
int
|
||||
device_printf(device_t dev, const char *format, ...)
|
||||
{
|
||||
char devDesc[32];
|
||||
va_list vl;
|
||||
|
||||
snprintf(devDesc, sizeof(devDesc), "%i:%i:%i", (int)dev->pci_info.bus,
|
||||
(int)dev->pci_info.device, (int)dev->pci_info.function);
|
||||
|
||||
va_start(vl, format);
|
||||
driver_vprintf_etc(devDesc, format, vl);
|
||||
driver_vprintf_etc(dev->dev_name, format, vl);
|
||||
va_end(vl);
|
||||
return 0;
|
||||
}
|
||||
@ -192,6 +190,23 @@ device_set_desc_copy(device_t dev, const char *desc)
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
device_get_desc(device_t dev)
|
||||
{
|
||||
return dev->description;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
device_sprintf_name(device_t dev, const char *format, ...)
|
||||
{
|
||||
va_list vl;
|
||||
va_start(vl, format);
|
||||
vsnprintf(dev->dev_name, sizeof(dev->dev_name), format, vl);
|
||||
va_end(vl);
|
||||
}
|
||||
|
||||
|
||||
const char *
|
||||
device_get_name(device_t dev)
|
||||
{
|
||||
|
@ -93,6 +93,7 @@ void *device_get_softc(device_t dev);
|
||||
int device_printf(device_t dev, const char *, ...) __printflike(2, 3);
|
||||
void device_set_desc(device_t dev, const char *desc);
|
||||
void device_set_desc_copy(device_t dev, const char *desc);
|
||||
const char *device_get_desc(device_t dev);
|
||||
|
||||
device_t device_add_child(device_t dev, const char *name, int unit);
|
||||
int device_delete_child(device_t dev, device_t child);
|
||||
|
@ -52,32 +52,41 @@ status_t _fbsd_init_driver(driver_t *);
|
||||
void _fbsd_uninit_driver(driver_t *);
|
||||
|
||||
extern const char gDriverName[];
|
||||
driver_t *__haiku_get_miibus_driver(void);
|
||||
|
||||
/* we define the driver methods with HAIKU_FBSD_DRIVER_GLUE to
|
||||
* force the rest of the stuff to be linked back with the driver.
|
||||
* While gcc 2.95 packs everything from the static library onto
|
||||
* the final binary, gcc 4.x rightfuly doesn't. */
|
||||
|
||||
#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \
|
||||
extern char *gDevNameList[]; \
|
||||
extern device_hooks gDeviceHooks; \
|
||||
extern driver_t *DRIVER_MODULE_NAME(name, busname); \
|
||||
const char gDriverName[] = #publicname; \
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION; \
|
||||
status_t init_hardware() \
|
||||
{ \
|
||||
return _fbsd_init_hardware(DRIVER_MODULE_NAME(name, busname)); \
|
||||
} \
|
||||
status_t init_driver() \
|
||||
{ \
|
||||
return _fbsd_init_driver(DRIVER_MODULE_NAME(name, busname)); \
|
||||
} \
|
||||
void uninit_driver() \
|
||||
{ \
|
||||
_fbsd_uninit_driver(DRIVER_MODULE_NAME(name, busname)); \
|
||||
} \
|
||||
const char **publish_devices() { return (const char **)gDevNameList; } \
|
||||
device_hooks *find_device(const char *name) { return &gDeviceHooks; }
|
||||
#define HAIKU_FBSD_DRIVER_GLUE(publicname, name, busname) \
|
||||
extern const char *gDevNameList[]; \
|
||||
extern device_hooks gDeviceHooks; \
|
||||
extern driver_t *DRIVER_MODULE_NAME(name, busname); \
|
||||
const char gDriverName[] = #publicname; \
|
||||
int32 api_version = B_CUR_DRIVER_API_VERSION; \
|
||||
status_t init_hardware() \
|
||||
{ \
|
||||
return _fbsd_init_hardware(DRIVER_MODULE_NAME(name, busname)); \
|
||||
} \
|
||||
status_t init_driver() \
|
||||
{ \
|
||||
return _fbsd_init_driver(DRIVER_MODULE_NAME(name, busname)); \
|
||||
} \
|
||||
void uninit_driver() \
|
||||
{ _fbsd_uninit_driver(DRIVER_MODULE_NAME(name, busname)); } \
|
||||
const char **publish_devices() \
|
||||
{ return gDevNameList; } \
|
||||
device_hooks *find_device(const char *name) \
|
||||
{ return &gDeviceHooks; }
|
||||
|
||||
#define HAIKU_FBSD_MII_DRIVER(name) \
|
||||
driver_t *__haiku_get_miibus_driver(device_t dev) \
|
||||
{ return DRIVER_MODULE_NAME(name, miibus); }
|
||||
|
||||
#define HAIKU_NO_FBSD_MII_DRIVER() \
|
||||
driver_t *__haiku_get_miibus_driver(device_t dev) \
|
||||
{ return NULL; }
|
||||
|
||||
extern spinlock __haiku_intr_spinlock;
|
||||
extern int __haiku_disable_interrupts(device_t dev);
|
||||
|
@ -26,8 +26,8 @@
|
||||
#define MAX_DEVICES 8
|
||||
|
||||
|
||||
device_t gDevices[MAX_DEVICES];
|
||||
char *gDevNameList[MAX_DEVICES + 1];
|
||||
struct network_device *gDevices[MAX_DEVICES];
|
||||
const char *gDevNameList[MAX_DEVICES + 1];
|
||||
|
||||
|
||||
static device_probe_t *sDeviceProbe;
|
||||
@ -36,28 +36,47 @@ static device_detach_t *sDeviceDetach;
|
||||
|
||||
|
||||
static device_t
|
||||
init_device(device_t dev, driver_t *driver)
|
||||
{
|
||||
dev->driver = driver;
|
||||
dev->softc = malloc(driver->softc_size);
|
||||
if (dev->softc == NULL)
|
||||
return NULL;
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
uninit_device(device_t dev)
|
||||
{
|
||||
if (dev->flags & DEVICE_DESC_ALLOCED)
|
||||
free((char *)dev->description);
|
||||
free(dev->softc);
|
||||
}
|
||||
|
||||
|
||||
static struct network_device *
|
||||
allocate_device(driver_t *driver)
|
||||
{
|
||||
char semName[64];
|
||||
|
||||
device_t dev = (device_t)malloc(sizeof(struct device));
|
||||
struct network_device *dev = malloc(sizeof(struct network_device));
|
||||
if (dev == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(dev, 0, sizeof(struct device));
|
||||
|
||||
snprintf(semName, sizeof(semName), "%s rcv", gDriverName);
|
||||
|
||||
dev->softc_size = driver->softc_size;
|
||||
dev->softc = malloc(driver->softc_size);
|
||||
if (dev->softc == NULL) {
|
||||
if (init_device(DEVNET(dev), driver) == NULL) {
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
snprintf(semName, sizeof(semName), "%s rcv", gDriverName);
|
||||
|
||||
dev->receive_sem = create_sem(0, semName);
|
||||
if (dev->receive_sem < 0) {
|
||||
free(dev->softc);
|
||||
uninit_device(DEVNET(dev));
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
@ -71,13 +90,11 @@ allocate_device(driver_t *driver)
|
||||
|
||||
|
||||
static void
|
||||
free_device(device_t dev)
|
||||
free_device(struct network_device *dev)
|
||||
{
|
||||
delete_sem(dev->receive_sem);
|
||||
ifq_uninit(&dev->receive_queue);
|
||||
free(dev->softc);
|
||||
if (dev->flags & DEVICE_DESC_ALLOCED)
|
||||
free((char *)dev->description);
|
||||
uninit_device(DEVNET(dev));
|
||||
free(dev);
|
||||
}
|
||||
|
||||
@ -100,8 +117,8 @@ _resolve_method(driver_t *driver, const char *name)
|
||||
static status_t
|
||||
compat_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
struct network_device *dev;
|
||||
status_t status;
|
||||
device_t dev;
|
||||
int i;
|
||||
|
||||
driver_printf("compat_open(%s, 0x%lx)\n", name, flags);
|
||||
@ -124,11 +141,11 @@ compat_open(const char *name, uint32 flags, void **cookie)
|
||||
return B_BUSY;
|
||||
|
||||
/* some drivers expect the softc to be zero'ed out */
|
||||
memset(dev->softc, 0, dev->softc_size);
|
||||
memset(dev->base.softc, 0, dev->base.driver->softc_size);
|
||||
|
||||
status = sDeviceAttach(dev);
|
||||
status = sDeviceAttach(DEVNET(dev));
|
||||
if (status != 0)
|
||||
dev->flags = 0;
|
||||
atomic_and(&dev->open, 0);
|
||||
|
||||
driver_printf(" ... status = 0x%ld\n", status);
|
||||
|
||||
@ -155,11 +172,11 @@ compat_open(const char *name, uint32 flags, void **cookie)
|
||||
static status_t
|
||||
compat_close(void *cookie)
|
||||
{
|
||||
device_t dev = cookie;
|
||||
struct network_device *dev = cookie;
|
||||
|
||||
device_printf(dev, "compat_close()\n");
|
||||
device_printf(DEVNET(dev), "compat_close()\n");
|
||||
|
||||
atomic_or(&dev->flags, DEVICE_CLOSED);
|
||||
atomic_or(&DEVNET(dev)->flags, DEVICE_CLOSED);
|
||||
|
||||
/* do we need a memory barrier in read() or is the atomic_or
|
||||
* (and the implicit 'lock') enough? */
|
||||
@ -173,11 +190,11 @@ compat_close(void *cookie)
|
||||
static status_t
|
||||
compat_free(void *cookie)
|
||||
{
|
||||
device_t dev = cookie;
|
||||
struct network_device *dev = cookie;
|
||||
|
||||
device_printf(dev, "compat_free()\n");
|
||||
device_printf(DEVNET(dev), "compat_free()\n");
|
||||
|
||||
sDeviceDetach(dev);
|
||||
sDeviceDetach(DEVNET(dev));
|
||||
|
||||
/* XXX empty out the send queue */
|
||||
|
||||
@ -191,24 +208,24 @@ compat_free(void *cookie)
|
||||
static status_t
|
||||
compat_read(void *cookie, off_t position, void *buf, size_t *numBytes)
|
||||
{
|
||||
struct network_device *dev = cookie;
|
||||
uint32 semFlags = B_CAN_INTERRUPT;
|
||||
device_t dev = cookie;
|
||||
status_t status;
|
||||
struct mbuf *mb;
|
||||
size_t len;
|
||||
|
||||
driver_printf("compat_read(%p, %lld, %p, [%lu])\n", cookie, position, buf,
|
||||
device_printf(DEVNET(dev), "compat_read(%lld, %p, [%lu])\n", position, buf,
|
||||
*numBytes);
|
||||
|
||||
if (dev->flags & DEVICE_CLOSED)
|
||||
if (DEVNET(dev)->flags & DEVICE_CLOSED)
|
||||
return B_INTERRUPTED;
|
||||
|
||||
if (dev->flags & DEVICE_NON_BLOCK)
|
||||
if (DEVNET(dev)->flags & DEVICE_NON_BLOCK)
|
||||
semFlags |= B_RELATIVE_TIMEOUT;
|
||||
|
||||
do {
|
||||
status = acquire_sem_etc(dev->receive_sem, 1, semFlags, 0);
|
||||
if (dev->flags & DEVICE_CLOSED)
|
||||
if (DEVNET(dev)->flags & DEVICE_CLOSED)
|
||||
return B_INTERRUPTED;
|
||||
|
||||
if (status == B_WOULD_BLOCK) {
|
||||
@ -242,10 +259,10 @@ static status_t
|
||||
compat_write(void *cookie, off_t position, const void *buffer,
|
||||
size_t *numBytes)
|
||||
{
|
||||
device_t dev = cookie;
|
||||
struct network_device *dev = cookie;
|
||||
struct mbuf *mb;
|
||||
|
||||
driver_printf("compat_write(%p, %lld, %p, [%lu])\n", cookie, position,
|
||||
device_printf(DEVNET(dev), "compat_write(%lld, %p, [%lu])\n", position,
|
||||
buffer, *numBytes);
|
||||
|
||||
mb = m_getcl(0, MT_DATA, 0);
|
||||
@ -264,7 +281,7 @@ compat_write(void *cookie, off_t position, const void *buffer,
|
||||
static status_t
|
||||
compat_control(void *cookie, uint32 op, void *arg, size_t len)
|
||||
{
|
||||
device_t dev = cookie;
|
||||
struct network_device *dev = cookie;
|
||||
struct ifnet *ifp = dev->ifp;
|
||||
|
||||
switch (op) {
|
||||
@ -282,9 +299,9 @@ compat_control(void *cookie, uint32 op, void *arg, size_t len)
|
||||
if (user_memcpy(&value, arg, sizeof(int32)) < B_OK)
|
||||
return B_BAD_ADDRESS;
|
||||
if (value)
|
||||
dev->flags |= DEVICE_NON_BLOCK;
|
||||
DEVNET(dev)->flags |= DEVICE_NON_BLOCK;
|
||||
else
|
||||
dev->flags &= ~DEVICE_NON_BLOCK;
|
||||
DEVNET(dev)->flags &= ~DEVICE_NON_BLOCK;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@ -378,7 +395,7 @@ device_hooks gDeviceHooks = {
|
||||
status_t
|
||||
_fbsd_init_hardware(driver_t *driver)
|
||||
{
|
||||
struct device fakeDevice;
|
||||
struct network_device fakeDevice;
|
||||
device_probe_t *probe;
|
||||
int i;
|
||||
|
||||
@ -397,12 +414,12 @@ _fbsd_init_hardware(driver_t *driver)
|
||||
|
||||
for (i = 0; gPci->get_nth_pci_info(i, &fakeDevice.pci_info) == B_OK; i++) {
|
||||
int result;
|
||||
result = probe(&fakeDevice);
|
||||
result = probe(DEVNET(&fakeDevice));
|
||||
if (result >= 0) {
|
||||
dprintf("%s, found %s at %d\n", gDriverName,
|
||||
fakeDevice.description, i);
|
||||
if (fakeDevice.flags & DEVICE_DESC_ALLOCED)
|
||||
free((char *)fakeDevice.description);
|
||||
device_get_desc(DEVNET(&fakeDevice)), i);
|
||||
if (DEVNET(&fakeDevice)->flags & DEVICE_DESC_ALLOCED)
|
||||
free((char *)DEVNET(&fakeDevice)->description);
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
return B_OK;
|
||||
}
|
||||
@ -420,7 +437,7 @@ _fbsd_init_driver(driver_t *driver)
|
||||
{
|
||||
int i, ncards = 0;
|
||||
status_t status;
|
||||
device_t dev;
|
||||
struct network_device *dev;
|
||||
|
||||
dprintf("%s: init_driver(%p)\n", gDriverName, driver);
|
||||
|
||||
@ -460,14 +477,15 @@ _fbsd_init_driver(driver_t *driver)
|
||||
|
||||
for (i = 0; dev != NULL
|
||||
&& gPci->get_nth_pci_info(i, &dev->pci_info) == B_OK; i++) {
|
||||
if (sDeviceProbe(dev) >= 0) {
|
||||
snprintf(dev->dev_name, sizeof(dev->dev_name), "net/%s/%i",
|
||||
gDriverName, ncards);
|
||||
dprintf("%s, adding %s @%d -> /dev/%s\n", gDriverName, dev->description,
|
||||
i, dev->dev_name);
|
||||
device_t base = DEVNET(dev);
|
||||
|
||||
if (sDeviceProbe(base) >= 0) {
|
||||
device_sprintf_name(base, "net/%s/%i", gDriverName, ncards);
|
||||
dprintf("%s, adding %s @%d -> /dev/%s\n", gDriverName,
|
||||
device_get_desc(base), i, device_get_name(base));
|
||||
|
||||
gDevices[ncards] = dev;
|
||||
gDevNameList[ncards] = dev->dev_name;
|
||||
gDevNameList[ncards] = device_get_name(base);
|
||||
|
||||
ncards++;
|
||||
if (ncards < MAX_DEVICES)
|
||||
|
@ -25,27 +25,39 @@
|
||||
struct ifnet;
|
||||
|
||||
struct device {
|
||||
pci_info pci_info;
|
||||
char dev_name[128];
|
||||
|
||||
int32 open;
|
||||
driver_t *driver;
|
||||
|
||||
int32 flags;
|
||||
|
||||
int unit;
|
||||
char nameunit[64];
|
||||
const char * description;
|
||||
void * softc;
|
||||
};
|
||||
|
||||
|
||||
struct network_device {
|
||||
struct device base;
|
||||
|
||||
pci_info pci_info;
|
||||
|
||||
int32 open;
|
||||
|
||||
struct ifqueue receive_queue;
|
||||
sem_id receive_sem;
|
||||
|
||||
sem_id link_state_sem;
|
||||
|
||||
struct ifnet * ifp;
|
||||
|
||||
int unit;
|
||||
char nameunit[64];
|
||||
const char * description;
|
||||
void * softc;
|
||||
size_t softc_size;
|
||||
};
|
||||
|
||||
|
||||
#define DEVNET(dev) ((device_t)(&(dev)->base))
|
||||
#define NETDEV(base) ((struct network_device *)(base))
|
||||
|
||||
|
||||
enum {
|
||||
DEVICE_OPEN = 1 << 0,
|
||||
DEVICE_CLOSED = 1 << 1,
|
||||
@ -80,16 +92,20 @@ void uninit_taskqueues(void);
|
||||
void init_bounce_pages(void);
|
||||
void uninit_bounce_pages(void);
|
||||
|
||||
void driver_printf(const char *format, ...) __attribute__ ((format (__printf__, 1, 2)));
|
||||
void driver_printf(const char *format, ...)
|
||||
__attribute__ ((format (__printf__, 1, 2)));
|
||||
void driver_vprintf(const char *format, va_list vl);
|
||||
|
||||
void device_sprintf_name(device_t dev, const char *format, ...)
|
||||
__attribute__ ((format (__printf__, 2, 3)));
|
||||
|
||||
void ifq_init(struct ifqueue *ifq, const char *name);
|
||||
void ifq_uninit(struct ifqueue *ifq);
|
||||
|
||||
extern struct net_stack_module_info *gStack;
|
||||
extern pci_module_info *gPci;
|
||||
|
||||
extern char *gDevNameList[];
|
||||
extern struct device *gDevices[];
|
||||
extern const char *gDevNameList[];
|
||||
extern struct network_device *gDevices[];
|
||||
|
||||
#endif
|
||||
|
@ -67,8 +67,8 @@ if_initname(struct ifnet *ifp, const char *name, int unit)
|
||||
if (gDevNameList[i] == NULL)
|
||||
panic("unknown interface");
|
||||
|
||||
ifp->if_dev = gDevices[i];
|
||||
ifp->if_dev->ifp = ifp;
|
||||
ifp->if_dev = DEVNET(gDevices[i]);
|
||||
gDevices[i]->ifp = ifp;
|
||||
}
|
||||
|
||||
|
||||
@ -146,7 +146,8 @@ if_link_state_change(struct ifnet *ifp, int link_state)
|
||||
|
||||
ifp->if_link_state = link_state;
|
||||
|
||||
release_sem_etc(ifp->if_dev->link_state_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
release_sem_etc(NETDEV(ifp->if_dev)->link_state_sem, 1,
|
||||
B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
||||
@ -269,8 +270,8 @@ ether_input(struct ifnet *ifp, struct mbuf *m)
|
||||
{
|
||||
device_t dev = ifp->if_dev;
|
||||
|
||||
IF_ENQUEUE(&dev->receive_queue, m);
|
||||
release_sem_etc(dev->receive_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
IF_ENQUEUE(&NETDEV(dev)->receive_queue, m);
|
||||
release_sem_etc(NETDEV(dev)->receive_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user