Connect interrupts and start processing them. We panic on card removal

now, but we're getting interrupts!
o Add pcic_suspend/pcic_resume so we can detach our children on suspention
  and fix the state of the pcic on resume.
o Remove some unused parts of softc.
o Centralize resource activation/deactivation for pcic bridge chip in
  the stylistic pcic_activate/pcic_deactivate.
o Add bus_print_child method so we can see the pccard attachment.
o Add pcic_identify in an attempt to make it possible to automatically id
  the pcic devices.  This works great, but we cannot divine the irq to use
  from this method, nor the memory hole.  For the moment, KLUDGE irq to be
  10 and memory hold to be 0xd0000.
o Loose the pnp probe stuff.  This may be a big mistake, but it is easy
  enough to add back later.  I did this so the identify routines can do their
  thing unmolested by pnp information.  The whole identify thing may be a bad
  idea to be ripped out later.
o change return type of pcic_intr to void, make it static and ripple
  this through the code.
o Add explicit call to bus_generic_attach at the end of pcic_attach to
  get any children probed/attached.
o add some comments about future directions/questionable things being
  done at different layers, etc.
This commit is contained in:
Warner Losh 2000-01-03 06:45:16 +00:00
parent 2fdb1532b4
commit fe98624bbb
4 changed files with 197 additions and 88 deletions

View File

@ -77,12 +77,13 @@ int pccard_card_intr(void *);
int pccard_card_intrdebug(void *);
#endif
/* XXX Shouldn't be touching hardware, that's a layering violation */
/* XXX imp */
int
pccard_ccr_read(pf, ccr)
struct pccard_function *pf;
int ccr;
{
return (bus_space_read_1(pf->pf_ccrt, pf->pf_ccrh,
pf->pf_ccr_offset + ccr));
}
@ -839,7 +840,6 @@ pccard_card_intrdebug(arg)
static int
pccard_add_children(device_t dev, int busno)
{
device_add_child(dev, NULL, -1);
return 0;
}

View File

@ -62,6 +62,8 @@ int pcic_debug = 0;
#else
#define DPRINTF(arg)
#endif
/* To later turn into debug */
#define DEVPRINTF(arg) device_printf arg;
#define DETACH_FORCE 0x1
@ -80,11 +82,15 @@ int pcic_debug = 0;
static void pcic_init_socket(struct pcic_handle *);
int pcic_intr_socket(struct pcic_handle *);
static void pcic_intr_socket(struct pcic_handle *);
void pcic_attach_card(struct pcic_handle *);
void pcic_detach_card(struct pcic_handle *, int);
void pcic_deactivate_card(struct pcic_handle *);
static void pcic_deactivate(device_t dev);
static int pcic_activate(device_t dev);
static void pcic_intr(void *arg);
void pcic_attach_card(struct pcic_handle *);
void pcic_detach_card(struct pcic_handle *, int);
void pcic_deactivate_card(struct pcic_handle *);
static void pcic_chip_do_mem_map(struct pcic_handle *, int);
static void pcic_chip_do_io_map(struct pcic_handle *, int);
@ -172,21 +178,104 @@ pcic_vendor_to_string(int vendor)
return ("Unknown controller");
}
void
static int
pcic_activate(device_t dev)
{
struct pcic_softc *sc = (struct pcic_softc *)
device_get_softc(dev);
int err;
sc->port_rid = 0;
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
0, ~0, PCIC_IOSIZE, RF_ACTIVE);
if (!sc->port_res) {
#ifdef PCIC_DEBUG
device_printf(dev, "Cannot allocate ioport\n");
#endif
return ENOMEM;
}
sc->irq_rid = 0;
sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
0, ~0, 1, RF_ACTIVE);
if (!sc->irq_res) {
#ifdef PCIC_DEBUG
device_printf(dev, "Cannot allocate irq\n");
#endif
pcic_deactivate(dev);
return ENOMEM;
}
sc->irq = rman_get_start(sc->irq_res);
if ((err = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET, pcic_intr,
sc, &sc->intrhand)) != 0) {
pcic_deactivate(dev);
return err;
}
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid,
0, ~0, 1 << 13, RF_ACTIVE);
if (!sc->mem_res) {
#ifdef PCIC_DEBUG
device_printf(dev, "Cannot allocate mem\n");
#endif
pcic_deactivate(dev);
return ENOMEM;
}
sc->subregionmask = (1 <<
((rman_get_end(sc->mem_res) - rman_get_start(sc->mem_res) + 1) /
PCIC_MEM_PAGESIZE)) - 1;
sc->iot = rman_get_bustag(sc->port_res);
sc->ioh = rman_get_bushandle(sc->port_res);;
sc->memt = rman_get_bustag(sc->mem_res);
sc->memh = rman_get_bushandle(sc->mem_res);;
return (0);
}
static void
pcic_deactivate(device_t dev)
{
struct pcic_softc *sc = device_get_softc(dev);
if (sc->intrhand)
bus_teardown_intr(dev, sc->irq_res, sc->intrhand);
sc->intrhand = 0;
if (sc->port_res)
bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
sc->port_res);
sc->port_res = 0;
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
sc->irq_res);
sc->irq_res = 0;
if (sc->mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
sc->mem_res);
sc->mem_res = 0;
return;
}
int
pcic_attach(device_t dev)
{
struct pcic_softc *sc = (struct pcic_softc *)
device_get_softc(dev);
struct pcic_handle *h;
int vendor, count, i, reg;
int vendor, count, i, reg, error;
sc->dev = dev;
/* Activate our resources */
if ((error = pcic_activate(dev)) != 0)
return error;
/* now check for each controller/socket */
/*
* this could be done with a loop, but it would violate the
* abstraction
* abstraction... so? --imp
*/
count = 0;
@ -349,6 +438,14 @@ pcic_attach(device_t dev)
device_set_ivars(h->dev, h);
pcic_init_socket(h);
}
/*
* Probe and attach any children as were configured above.
*/
error = bus_generic_attach(dev);
if (error)
pcic_deactivate(dev);
return error;
}
void
@ -512,22 +609,20 @@ pcic_init_socket(struct pcic_handle *h)
}
}
int
static void
pcic_intr(void *arg)
{
struct pcic_softc *sc = arg;
int i, ret = 0;
int i;
DPRINTF(("%s: intr\n", sc->dev.dv_xname));
DEVPRINTF((sc->dev, "intr\n"));
for (i = 0; i < PCIC_NSLOTS; i++)
if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
ret += pcic_intr_socket(&sc->handle[i]);
return (ret ? 1 : 0);
pcic_intr_socket(&sc->handle[i]);
}
int
static void
pcic_intr_socket(struct pcic_handle *h)
{
int cscreg;
@ -581,7 +676,6 @@ pcic_intr_socket(struct pcic_handle *h)
if (cscreg & PCIC_CSC_BATTDEAD) {
DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname, h->sock));
}
return (cscreg ? 1 : 0);
}
void
@ -1377,6 +1471,27 @@ pcic_release_resource(device_t dev, device_t child, int type, int rid,
return bus_generic_release_resource(dev, child, type, rid, r);
}
int
pcic_suspend(device_t dev)
{
/*
* Do nothing for now, maybe in time do what FreeBSD's current
* pccard code does and detach my children. That's the safest thing
* to do since we don't want to wake up and have different hardware
* in the slots.
*/
return 0;
}
int
pcic_resume(device_t dev)
{
/* Need to port pcic_power from newer netbsd versions of this file */
return 0;
}
static void
pcic_start_threads(void *arg)
{

View File

@ -225,7 +225,7 @@ pcic_isa_bus_width_probe (device_t dev)
}
static int
pcic_isa_probe(device_t dev)
pcic_isa_check(device_t dev, u_int16_t addr)
{
bus_space_tag_t iot;
bus_space_handle_t ioh;
@ -233,13 +233,9 @@ pcic_isa_probe(device_t dev)
int rid;
struct resource *res;
/* Check isapnp ids */
if (ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids) == ENXIO)
return (ENXIO);
rid = 0;
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, PCIC_IOSIZE,
RF_ACTIVE);
res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, addr, addr,
PCIC_IOSIZE, RF_ACTIVE);
if (!res)
return(ENXIO);
iot = rman_get_bustag(res);
@ -272,67 +268,65 @@ pcic_isa_probe(device_t dev)
bus_release_resource(dev, SYS_RES_IOPORT, rid, res);
/* XXX DO I NEED TO WORRY ABOUT the IRQ? XXX */
return (found);
}
if (!found)
static void
pcic_isa_identify(driver_t *driver, device_t parent)
{
device_t child;
u_int16_t ioaddrs[] = { 0x3e0, 0x3e2, 0x3e4, 0x3e6, 0 };
u_int16_t ioaddr;
int i;
for (i = 0; ioaddrs[i]; i++) {
ioaddr = ioaddrs[i];
if (pcic_isa_check(parent, ioaddr)) {
child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE,
"pcic", -1);
device_set_driver(child, driver);
/* XXX */
bus_set_resource(child, SYS_RES_IRQ, 0, 10, 1);
bus_set_resource(child, SYS_RES_MEMORY, 0, 0xd0000, 1 << 12);
bus_set_resource(child, SYS_RES_IOPORT, 0, ioaddr,
PCIC_IOSIZE);
}
}
}
static int
pcic_isa_probe(device_t dev)
{
int error;
/* Check isapnp ids */
error = ISA_PNP_PROBE(device_get_parent(dev), dev, pcic_ids);
if (error == ENXIO)
return (ENXIO);
return (0);
/* If we had some other problem. */
if (!(error == 0 || error == ENOENT)) {
return (error);
}
/* If we have the resources we need then we're good to go. */
if ((bus_get_resource_start(dev, SYS_RES_IOPORT, 0) != 0) &&
(bus_get_resource_start(dev, SYS_RES_IRQ, 0) != 0)) {
return (0);
}
return (ENXIO);
}
static int
pcic_isa_attach(device_t dev)
{
struct pcic_softc *sc = (struct pcic_softc *) device_get_softc(dev);
int err = 0;
sc->port_rid = 0;
sc->port_res = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->port_rid,
0, ~0, PCIC_IOSIZE, RF_ACTIVE);
if (!sc->port_res) {
device_printf(dev, "Unable to allocate I/O ports\n");
goto error;
}
sc->mem_rid = 0;
sc->mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->mem_rid,
0, ~0, 1 << 13, RF_ACTIVE);
if (!sc->mem_res) {
device_printf(dev, "Unable to allocate memory range\n");
goto error;
}
sc->subregionmask = (1 <<
((rman_get_end(sc->mem_res) - rman_get_start(sc->mem_res) + 1) /
PCIC_MEM_PAGESIZE)) - 1;
if ((err = pcic_attach(dev)) == 0)
pcic_isa_bus_width_probe (dev);
sc->irq_rid = 0;
sc->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->irq_rid,
0, ~0, 1, RF_ACTIVE);
if (!sc->irq_res) {
device_printf(dev, "Unable to allocate irq\n");
goto error;
}
sc->iot = rman_get_bustag(sc->port_res);
sc->ioh = rman_get_bushandle(sc->port_res);;
sc->memt = rman_get_bustag(sc->mem_res);
sc->memh = rman_get_bushandle(sc->mem_res);;
pcic_attach(dev);
pcic_isa_bus_width_probe (dev);
return 0;
error:
if (sc->port_res)
bus_release_resource(dev, SYS_RES_IOPORT, sc->port_rid,
sc->port_res);
if (sc->mem_res)
bus_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid,
sc->mem_res);
if (sc->irq_res)
bus_release_resource(dev, SYS_RES_IRQ, sc->irq_rid,
sc->irq_res);
return ENOMEM;
return err;
}
static int
@ -343,15 +337,17 @@ pcic_isa_detach(device_t dev)
static device_method_t pcic_isa_methods[] = {
/* Device interface */
DEVMETHOD(device_identify, pcic_isa_identify),
DEVMETHOD(device_probe, pcic_isa_probe),
DEVMETHOD(device_attach, pcic_isa_attach),
DEVMETHOD(device_detach, pcic_isa_detach),
DEVMETHOD(device_shutdown, bus_generic_shutdown),
DEVMETHOD(device_suspend, bus_generic_suspend),
DEVMETHOD(device_resume, bus_generic_resume),
DEVMETHOD(device_suspend, pcic_suspend),
DEVMETHOD(device_resume, pcic_resume),
/* Bus Interface */
DEVMETHOD(bus_driver_added, bus_generic_driver_added),
DEVMETHOD(bus_print_child, bus_generic_print_child),
DEVMETHOD(bus_alloc_resource, pcic_alloc_resource),
DEVMETHOD(bus_release_resource, pcic_release_resource),
DEVMETHOD(bus_activate_resource, pcic_activate_resource),

View File

@ -101,16 +101,13 @@ struct pcic_softc {
bus_space_tag_t iot;
bus_space_handle_t ioh;
struct resource *port_res;
int port_rid;
struct resource *mem_res;
int mem_rid;
void *intrhand;
struct resource *irq_res;
int irq_rid;
/* XXX isa_chipset_tag_t, pci_chipset_tag_t, etc. */
void *intr_est;
int irq_rid;
struct resource *mem_res;
int mem_rid;
struct resource *port_res;
int port_rid;
/* this needs to be large enough to hold PCIC_MEM_PAGES bits */
int subregionmask;
@ -140,8 +137,7 @@ int pcic_ident_ok(int);
int pcic_vendor(struct pcic_handle *);
char *pcic_vendor_to_string(int);
void pcic_attach(device_t dev);
int pcic_intr(void *arg);
int pcic_attach(device_t dev);
#if 0
@ -193,3 +189,5 @@ int pcic_setup_intr(device_t dev, device_t child, struct resource *irq,
int flags, driver_intr_t intr, void *arg, void **cookiep);
int pcic_teardown_intr(device_t dev, device_t child, struct resource *irq,
void *cookiep);
int pcic_suspend(device_t dev);
int pcic_resume(device_t dev);