Overhaul of CIS parsing, next step: keep a cached copy of the CIS,
read before we configure the card, so we can implement /dev/cardbus*.cis. Also, do this on a per-child basis, so we now have a different name than before. I think i'll have to fix that for some legacy tools to keep working. I can now do a dumpcis on my running atheros card and have it still work!
This commit is contained in:
parent
30dda99b96
commit
a7de0b74a7
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2003 M. Warner Losh. All Rights Reserved.
|
||||
* Copyright (c) 2003-2008 M. Warner Losh. All Rights Reserved.
|
||||
* Copyright (c) 2000,2001 Jonathan Chen. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -99,20 +99,18 @@ cardbus_probe(device_t cbdev)
|
||||
static int
|
||||
cardbus_attach(device_t cbdev)
|
||||
{
|
||||
struct cardbus_softc *sc = device_get_softc(cbdev);
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = device_get_softc(cbdev);
|
||||
sc->sc_dev = cbdev;
|
||||
cardbus_device_create(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_detach(device_t cbdev)
|
||||
{
|
||||
struct cardbus_softc *sc = device_get_softc(cbdev);
|
||||
|
||||
cardbus_detach_card(cbdev);
|
||||
cardbus_device_destroy(sc);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -165,7 +163,9 @@ cardbus_attach_card(device_t cbdev)
|
||||
int bus, domain, slot, func;
|
||||
int cardattached = 0;
|
||||
int cardbusfunchigh = 0;
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = device_get_softc(cbdev);
|
||||
cardbus_detach_card(cbdev); /* detach existing cards */
|
||||
POWER_ENABLE_SOCKET(brdev, cbdev);
|
||||
domain = pcib_get_domain(cbdev);
|
||||
@ -192,6 +192,7 @@ cardbus_attach_card(device_t cbdev)
|
||||
dinfo->pci.cfg.dev = child;
|
||||
resource_list_init(&dinfo->pci.resources);
|
||||
device_set_ivars(child, dinfo);
|
||||
cardbus_device_create(sc, dinfo, cbdev, child);
|
||||
if (cardbus_do_cis(cbdev, child) != 0)
|
||||
DEVPRINTF((cbdev, "Warning: Bogus CIS ignored\n"));
|
||||
pci_cfg_save(dinfo->pci.cfg.dev, &dinfo->pci, 0);
|
||||
@ -235,6 +236,7 @@ cardbus_detach_card(device_t cbdev)
|
||||
if (status == DS_ATTACHED || status == DS_BUSY)
|
||||
device_detach(devlist[tmp]);
|
||||
cardbus_release_all_resources(cbdev, dinfo);
|
||||
cardbus_device_destroy(dinfo);
|
||||
device_delete_child(cbdev, devlist[tmp]);
|
||||
pci_freecfg((struct pci_devinfo *)dinfo);
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005-2008, M. Warner Losh
|
||||
* Copyright (c) 2000,2001 Jonathan Chen.
|
||||
* All rights reserved.
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2005, M. Warner Losh
|
||||
* Copyright (c) 2005-2008, M. Warner Losh
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -63,26 +63,6 @@ static struct cdevsw cardbus_cdevsw = {
|
||||
.d_name = "cardbus"
|
||||
};
|
||||
|
||||
int
|
||||
cardbus_device_create(struct cardbus_softc *sc)
|
||||
{
|
||||
uint32_t minor;
|
||||
|
||||
minor = device_get_unit(sc->sc_dev) << 16;
|
||||
sc->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
|
||||
"cardbus%u.cis", device_get_unit(sc->sc_dev));
|
||||
sc->sc_cisdev->si_drv1 = sc;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cardbus_device_destroy(struct cardbus_softc *sc)
|
||||
{
|
||||
if (sc->sc_cisdev)
|
||||
destroy_dev(sc->sc_cisdev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_build_cis(device_t cbdev, device_t child, int id,
|
||||
int len, uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
@ -115,7 +95,8 @@ cardbus_build_cis(device_t cbdev, device_t child, int id,
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_device_buffer_cis(device_t parent, device_t child)
|
||||
cardbus_device_buffer_cis(device_t parent, device_t child,
|
||||
struct cis_buffer *cbp)
|
||||
{
|
||||
struct cardbus_softc *sc;
|
||||
struct tuple_callbacks cb[] = {
|
||||
@ -123,46 +104,44 @@ cardbus_device_buffer_cis(device_t parent, device_t child)
|
||||
};
|
||||
|
||||
sc = device_get_softc(parent);
|
||||
return (cardbus_parse_cis(parent, child, cb, &sc->sc_cis));
|
||||
return (cardbus_parse_cis(parent, child, cb, cbp));
|
||||
}
|
||||
|
||||
int
|
||||
cardbus_device_create(struct cardbus_softc *sc, struct cardbus_devinfo *devi,
|
||||
device_t parent, device_t child)
|
||||
{
|
||||
uint32_t minor;
|
||||
|
||||
cardbus_device_buffer_cis(parent, child, &devi->sc_cis);
|
||||
minor = (device_get_unit(sc->sc_dev) << 8) + devi->pci.cfg.func;
|
||||
devi->sc_cisdev = make_dev(&cardbus_cdevsw, minor, 0, 0, 0666,
|
||||
"cardbus%d.%d.cis", device_get_unit(sc->sc_dev),
|
||||
devi->pci.cfg.func);
|
||||
/* XXX need cardbus%d.cis compat layer here ? */
|
||||
devi->sc_cisdev->si_drv1 = devi;
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
cardbus_device_destroy(struct cardbus_devinfo *devi)
|
||||
{
|
||||
if (devi->sc_cisdev)
|
||||
destroy_dev(devi->sc_cisdev);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_open(struct cdev *dev, int oflags, int devtype, struct thread *td)
|
||||
{
|
||||
device_t parent, child;
|
||||
device_t *kids;
|
||||
int cnt, err;
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
if (sc->sc_cis_open)
|
||||
return (EBUSY);
|
||||
parent = sc->sc_dev;
|
||||
err = device_get_children(parent, &kids, &cnt);
|
||||
if (err)
|
||||
return err;
|
||||
sc->sc_cis.len = 0;
|
||||
if (cnt == 0) {
|
||||
free(kids, M_TEMP);
|
||||
sc->sc_cis_open++;
|
||||
return (0);
|
||||
}
|
||||
child = kids[0];
|
||||
free(kids, M_TEMP);
|
||||
err = cardbus_device_buffer_cis(parent, child);
|
||||
if (err)
|
||||
return (err);
|
||||
sc->sc_cis_open++;
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
cardbus_close(struct cdev *dev, int fflags, int devtype, struct thread *td)
|
||||
{
|
||||
struct cardbus_softc *sc;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
sc->sc_cis_open = 0;
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -176,12 +155,12 @@ cardbus_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
|
||||
static int
|
||||
cardbus_read(struct cdev *dev, struct uio *uio, int ioflag)
|
||||
{
|
||||
struct cardbus_softc *sc;
|
||||
struct cardbus_devinfo *devi;
|
||||
|
||||
sc = dev->si_drv1;
|
||||
devi = dev->si_drv1;
|
||||
/* EOF */
|
||||
if (uio->uio_offset >= sc->sc_cis.len)
|
||||
if (uio->uio_offset >= devi->sc_cis.len)
|
||||
return (0);
|
||||
return (uiomove(sc->sc_cis.buffer + uio->uio_offset,
|
||||
MIN(uio->uio_resid, sc->sc_cis.len - uio->uio_offset), uio));
|
||||
return (uiomove(devi->sc_cis.buffer + uio->uio_offset,
|
||||
MIN(uio->uio_resid, devi->sc_cis.len - uio->uio_offset), uio));
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2008, M. Warner Losh
|
||||
* Copyright (c) 2000,2001 Jonathan Chen.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -29,6 +30,21 @@
|
||||
/*
|
||||
* Structure definitions for the Cardbus Bus driver
|
||||
*/
|
||||
|
||||
/*
|
||||
* Static copy of the CIS buffer. Technically, you aren't supposed
|
||||
* to do this. In practice, however, it works well.
|
||||
*/
|
||||
struct cis_buffer
|
||||
{
|
||||
size_t len; /* Actual length of the CIS */
|
||||
uint8_t buffer[2040]; /* small enough to be 2k */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per child information for the PCI device. Cardbus layers on some
|
||||
* additional data.
|
||||
*/
|
||||
struct cardbus_devinfo
|
||||
{
|
||||
struct pci_devinfo pci;
|
||||
@ -43,36 +59,33 @@ struct cardbus_devinfo
|
||||
} lan;
|
||||
} funce;
|
||||
uint32_t fepresent; /* bit mask of funce values present */
|
||||
struct cdev *sc_cisdev;
|
||||
struct cis_buffer sc_cis;
|
||||
};
|
||||
|
||||
struct cis_buffer
|
||||
{
|
||||
size_t len; /* Actual length of the CIS */
|
||||
uint8_t buffer[2040]; /* small enough to be 2k */
|
||||
};
|
||||
|
||||
/*
|
||||
* Per cardbus soft info. Not sure why we even keep this around...
|
||||
*/
|
||||
struct cardbus_softc
|
||||
{
|
||||
device_t sc_dev;
|
||||
/* The following fields should in be in struct cardbus_devinfo */
|
||||
struct cdev *sc_cisdev;
|
||||
struct cis_buffer sc_cis;
|
||||
int sc_cis_open;
|
||||
};
|
||||
|
||||
/*
|
||||
* Per node callback structures.
|
||||
*/
|
||||
struct tuple_callbacks;
|
||||
|
||||
typedef int (tuple_cb) (device_t cbdev, device_t child, int id, int len,
|
||||
uint8_t *tupledata, uint32_t start, uint32_t *off,
|
||||
struct tuple_callbacks *info, void *);
|
||||
|
||||
struct tuple_callbacks {
|
||||
int id;
|
||||
char *name;
|
||||
tuple_cb *func;
|
||||
};
|
||||
|
||||
int cardbus_device_create(struct cardbus_softc *);
|
||||
int cardbus_device_destroy(struct cardbus_softc *);
|
||||
int cardbus_device_create(struct cardbus_softc *sc,
|
||||
struct cardbus_devinfo *devi, device_t parent, device_t child);
|
||||
int cardbus_device_destroy(struct cardbus_devinfo *devi);
|
||||
int cardbus_parse_cis(device_t cbdev, device_t child,
|
||||
struct tuple_callbacks *callbacks, void *);
|
||||
|
Loading…
Reference in New Issue
Block a user