summaryrefslogtreecommitdiffstats
path: root/sys/pci/uhci_pci.c
diff options
context:
space:
mode:
authorn_hibma <n_hibma@FreeBSD.org>2000-05-07 20:16:25 +0000
committern_hibma <n_hibma@FreeBSD.org>2000-05-07 20:16:25 +0000
commitd9cfc650630464627df346b97c4dd728a95818bb (patch)
tree28f047ab64e7ebf71e144d53d5995d322540d916 /sys/pci/uhci_pci.c
parent0ee0a9878bdb7b86f331fdd3fb15fcc3ccec676d (diff)
downloadFreeBSD-src-d9cfc650630464627df346b97c4dd728a95818bb.zip
FreeBSD-src-d9cfc650630464627df346b97c4dd728a95818bb.tar.gz
Do the attach (and detach) properly. Store the cookies.
This is a first step to make usb unloadable.
Diffstat (limited to 'sys/pci/uhci_pci.c')
-rw-r--r--sys/pci/uhci_pci.c116
1 files changed, 76 insertions, 40 deletions
diff --git a/sys/pci/uhci_pci.c b/sys/pci/uhci_pci.c
index 3ae3e1a..ef716aa 100644
--- a/sys/pci/uhci_pci.c
+++ b/sys/pci/uhci_pci.c
@@ -94,6 +94,13 @@ static const char *uhci_device_generic = "UHCI (generic) USB controller";
#define PCI_UHCI_BASE_REG 0x20
+
+static int uhci_pci_attach(device_t self);
+static int uhci_pci_detach(device_t self);
+static int uhci_pci_suspend(device_t self);
+static int uhci_pci_resume(device_t self);
+
+
static int
uhci_pci_suspend(device_t self)
{
@@ -162,8 +169,6 @@ uhci_pci_attach(device_t self)
{
uhci_softc_t *sc = device_get_softc(self);
int rid;
- void *ih;
- struct resource *io_res, *irq_res;
int intr;
int err;
@@ -176,33 +181,34 @@ uhci_pci_attach(device_t self)
}
rid = PCI_UHCI_BASE_REG;
- io_res = bus_alloc_resource(self, SYS_RES_IOPORT, &rid,
- 0, ~0, 1, RF_ACTIVE);
- if (!io_res) {
- device_printf(self, "could not map ports\n");
+ sc->io_res = bus_alloc_resource(self, SYS_RES_IOPORT, &rid,
+ 0, ~0, 1, RF_ACTIVE);
+ if (!sc->io_res) {
+ device_printf(self, "Could not map ports\n");
return ENXIO;
}
- sc->iot = rman_get_bustag(io_res);
- sc->ioh = rman_get_bushandle(io_res);
+ sc->iot = rman_get_bustag(sc->io_res);
+ sc->ioh = rman_get_bushandle(sc->io_res);
/* disable interrupts */
bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
rid = 0;
- irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1,
- RF_SHAREABLE | RF_ACTIVE);
- if (irq_res == NULL) {
- device_printf(self, "could not allocate irq\n");
- err = ENOMEM;
- goto bad1;
+ sc->irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid,
+ 0, ~0, 1,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ uhci_pci_detach(self);
+ return ENXIO;
}
-
+
sc->sc_bus.bdev = device_add_child(self, "usb", -1);
if (!sc->sc_bus.bdev) {
- device_printf(self, "could not add USB device\n");
- err = ENOMEM;
- goto bad2;
+ device_printf(self, "Could not add USB device\n");
+ uhci_pci_detach(self);
+ return ENOMEM;
}
device_set_ivars(sc->sc_bus.bdev, sc);
@@ -246,11 +252,13 @@ uhci_pci_attach(device_t self)
break;
}
- err = bus_setup_intr(self, irq_res, INTR_TYPE_BIO,
- (driver_intr_t *) uhci_intr, sc, &ih);
+ err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO,
+ (driver_intr_t *) uhci_intr, sc, &sc->ih);
if (err) {
- device_printf(self, "could not setup irq, %d\n", err);
- goto bad3;
+ device_printf(self, "Could not setup irq, %d\n", err);
+ sc->ih = NULL;
+ uhci_pci_detach(self);
+ return ENXIO;
}
/* Set the PIRQD enable bit and switch off all the others. We don't
@@ -271,33 +279,61 @@ uhci_pci_attach(device_t self)
if (err) {
device_printf(self, "USB init failed\n");
- err = EIO;
- goto bad4;
+ uhci_pci_detach(self);
+ return EIO;
}
- return 0;
+ return 0; /* success */
+}
+
+int
+uhci_pci_detach(device_t self)
+{
+ uhci_softc_t *sc = device_get_softc(self);
+
+ /* XXX This function is not yet complete and should not be added
+ * method list.
+ */
+#if 0
+ if uhci_init was successful
+ we should call something like uhci_deinit
+#endif
-bad4:
/* disable interrupts that might have been switched on
* in uhci_init.
*/
- bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
+ if (sc->iot && sc->ioh)
+ bus_space_write_2(sc->iot, sc->ioh, UHCI_INTR, 0);
+
+ if (sc->irq_res && sc->ih) {
+ int err = bus_teardown_intr(self, sc->irq_res, sc->ih);
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->ih = NULL;
+ }
- err = bus_teardown_intr(self, irq_res, ih);
- if (err)
- /* XXX or should we panic? */
- device_printf(self, "could not tear down irq, %d\n",
- err);
-
-bad3:
- device_delete_child(self, sc->sc_bus.bdev);
-bad2:
- bus_release_resource(self, SYS_RES_IRQ, 0, irq_res);
-bad1:
- bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG, io_res);
- return err;
+ if (sc->sc_bus.bdev) {
+ device_delete_child(self, sc->sc_bus.bdev);
+ sc->sc_bus.bdev = NULL;
+ }
+ if (sc->irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
+ sc->irq_res = NULL;
+ }
+ if (sc->io_res) {
+ bus_release_resource(self, SYS_RES_IOPORT, PCI_UHCI_BASE_REG,
+ sc->io_res);
+ sc->io_res = NULL;
+ sc->iot = 0;
+ sc->ioh = 0;
+ }
+
+ return 0;
}
+
static device_method_t uhci_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, uhci_pci_probe),
OpenPOWER on IntegriCloud