diff -druN /mnt/sys/dev/acpica/acpi_pci.c dev/acpica/acpi_pci.c --- /mnt/sys/dev/acpica/acpi_pci.c Wed Sep 4 12:13:15 2002 +++ dev/acpica/acpi_pci.c Wed Jan 22 12:07:00 2003 @@ -79,7 +79,7 @@ DEVMETHOD(device_attach, acpi_pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, pci_resume), /* Bus interface */ DEVMETHOD(bus_print_child, pci_print_child), diff -druN /mnt/sys/dev/ata/ata-all.c dev/ata/ata-all.c --- /mnt/sys/dev/ata/ata-all.c Sat Dec 7 04:29:52 2002 +++ dev/ata/ata-all.c Wed Jan 22 12:14:53 2003 @@ -92,6 +92,7 @@ /* local vars */ static MALLOC_DEFINE(M_ATA, "ATA generic", "ATA driver generic layer"); +static int ata_cold = 1; /* misc defines */ #define DEV_ATAPIALL defined(DEV_ATAPICD) || defined(DEV_ATAPIFD) || \ @@ -187,7 +188,7 @@ * when interrupts are enabled by a hook into the boot process. * otherwise attach what the probe has found in ch->devices. */ - if (!ata_delayed_attach) { + if (!ata_cold) { ch->lock_func(ch, ATA_LF_LOCK); if (ch->devices & ATA_ATA_SLAVE) if (ata_getparam(&ch->device[SLAVE], ATA_C_ATA_IDENTIFY)) @@ -284,6 +285,31 @@ } int +ata_suspend(device_t dev) +{ + struct ata_channel *ch; + + ch = device_get_softc(dev); + +#ifdef DEV_ATADISK + if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) { + ch->device[MASTER].suspended = 1; + if (ch->device[MASTER].mode >= ATA_DMA) { + ata_waitdmadone(&ch->device[MASTER]); + } + } + if (ch->devices & ATA_ATA_SLAVE && ch->device[SLAVE].driver) { + ch->device[SLAVE].suspended = 1; + if (ch->device[SLAVE].mode >= ATA_DMA) { + ata_waitdmadone(&ch->device[SLAVE]); + } + } +#endif + + return 0; +} + +int ata_resume(device_t dev) { struct ata_channel *ch; @@ -292,6 +318,15 @@ if (!dev || !(ch = device_get_softc(dev))) return ENXIO; +#ifdef DEV_ATADISK + if (ch->devices & ATA_ATA_MASTER && ch->device[MASTER].driver) { + ch->device[MASTER].suspended = 0; + } + if (ch->devices & ATA_ATA_SLAVE && ch->device[SLAVE].driver) { + ch->device[SLAVE].suspended = 0; + } +#endif + ch->lock_func(ch, ATA_LF_LOCK); error = ata_reinit(ch); ch->lock_func(ch, ATA_LF_UNLOCK); @@ -606,6 +641,7 @@ #endif ch->lock_func(ch, ATA_LF_UNLOCK); } + ata_cold = 0; if (ata_delayed_attach) { config_intrhook_disestablish(ata_delayed_attach); free(ata_delayed_attach, M_TEMP); @@ -707,6 +743,20 @@ if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) ad_start(&ch->device[SLAVE]); } + if (ch->devices & (ATA_ATA_MASTER) && ch->device[MASTER].driver) { + if (ch->device[MASTER].suspended && ch->device[MASTER].mode >= ATA_DMA) { + printf("%s: going to suspend, ignoring.\n", __func__); + splx(s); + return; + } + } + if (ch->devices & (ATA_ATA_SLAVE) && ch->device[SLAVE].driver) { + if (ch->device[SLAVE].suspended && ch->device[SLAVE].mode >= ATA_DMA) { + printf("%s: going to suspend, ignoring.\n", __func__); + splx(s); + return; + } + } if ((ad_request = TAILQ_FIRST(&ch->ata_queue))) { TAILQ_REMOVE(&ch->ata_queue, ad_request, chain); ch->active = ATA_ACTIVE_ATA; @@ -1397,6 +1447,7 @@ case ATA_UDMA6: return "UDMA133"; default: return "???"; } + ata_cold = 0; } int diff -druN /mnt/sys/dev/ata/ata-all.h dev/ata/ata-all.h --- /mnt/sys/dev/ata/ata-all.h Wed Dec 18 05:46:56 2002 +++ dev/ata/ata-all.h Wed Jan 22 12:00:40 2003 @@ -195,6 +195,7 @@ int cmd; /* last cmd executed */ void *result; /* misc data */ struct ata_dmastate dmastate; /* dma state */ + int suspended; /* 0 = normal 1 = suspended */ }; /* structure describing an ATA channel */ @@ -264,6 +265,7 @@ int ata_probe(device_t); int ata_attach(device_t); int ata_detach(device_t); +int ata_suspend(device_t); int ata_resume(device_t); void ata_start(struct ata_channel *); void ata_reset(struct ata_channel *); @@ -291,6 +293,7 @@ int ata_dmasetup(struct ata_device *, caddr_t, int32_t); int ata_dmastart(struct ata_device *, caddr_t, int32_t, int); int ata_dmastatus(struct ata_channel *); +void ata_waitdmadone(struct ata_device *); int ata_dmadone(struct ata_device *); /* macros for locking a channel */ diff -druN /mnt/sys/dev/ata/ata-dma.c dev/ata/ata-dma.c --- /mnt/sys/dev/ata/ata-dma.c Fri Jan 10 15:56:37 2003 +++ dev/ata/ata-dma.c Wed Jan 22 12:00:40 2003 @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1519,8 +1520,11 @@ struct ata_dmastate *ds = &atadev->dmastate; struct ata_dmasetup_data_cb_args cba; - if (ds->flags & ATA_DS_ACTIVE) - panic("ata_dmasetup: transfer active on this device!"); + if (ds->flags & ATA_DS_ACTIVE) { + printf("ata_dmastart: transfer active on this device!\n"); + Debugger("ata_dmastart"); + return -1; + } switch(ch->chiptype) { case 0x0d38105a: /* Promise Fasttrak 66 */ @@ -1558,6 +1562,16 @@ return 0; } +void +ata_waitdmadone(struct ata_device *atadev) +{ + if (atadev->dmastate.flags & ATA_DS_ACTIVE) { + printf("%s: waiting for ata_dmadone()\n", __func__); + tsleep(ata_dmadone, PRIBIO, "atawdma", 10 * hz); + printf("%s: done\n", __func__); + } +} + int ata_dmadone(struct ata_device *atadev) { @@ -1587,6 +1601,7 @@ error | ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); ch->flags &= ~ATA_DMA_ACTIVE; ds->flags = 0; + wakeup((caddr_t)ata_dmadone); return (error & ATA_BMSTAT_MASK); } diff -druN /mnt/sys/dev/ata/ata-pci.c dev/ata/ata-pci.c --- /mnt/sys/dev/ata/ata-pci.c Fri Jan 10 15:56:37 2003 +++ dev/ata/ata-pci.c Wed Jan 22 12:00:40 2003 @@ -967,6 +967,7 @@ DEVMETHOD(device_probe, ata_pcisub_probe), DEVMETHOD(device_attach, ata_attach), DEVMETHOD(device_detach, ata_detach), + DEVMETHOD(device_suspend, ata_suspend), DEVMETHOD(device_resume, ata_resume), { 0, 0 } }; diff -druN /mnt/sys/dev/pccard/pccard.c dev/pccard/pccard.c --- /mnt/sys/dev/pccard/pccard.c Thu Nov 14 23:02:32 2002 +++ dev/pccard/pccard.c Wed Jan 22 12:06:48 2003 @@ -1184,12 +1184,15 @@ * interrupt storm from happening. Of course this won't * help in the non-MFC case. */ + reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS); if (pccard_mfc(pf->sc)) { - reg = pccard_ccr_read(pf, PCCARD_CCR_STATUS); if (reg & PCCARD_CCR_STATUS_INTR) pccard_ccr_write(pf, PCCARD_CCR_STATUS, reg & ~PCCARD_CCR_STATUS_INTR); else + doisr = 0; + } else { + if (reg == 0xff) /* card was removed */ doisr = 0; } if (pf->intr_handler != NULL && doisr) diff -druN /mnt/sys/dev/pci/pci.c dev/pci/pci.c --- /mnt/sys/dev/pci/pci.c Wed Nov 27 15:41:28 2002 +++ dev/pci/pci.c Wed Jan 22 12:07:02 2003 @@ -88,7 +88,7 @@ DEVMETHOD(device_attach, pci_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, pci_resume), /* Bus interface */ DEVMETHOD(bus_print_child, pci_print_child), @@ -744,7 +744,7 @@ pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; struct pci_quirk *q; - int b, i, f, s; + int b, i, irq, f, s; b = cfg->bus; s = cfg->slot; @@ -760,14 +760,16 @@ } if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) { -#ifdef __ia64__ /* - * Re-route interrupts on ia64 so that we can get the - * I/O SAPIC interrupt numbers (the BIOS leaves legacy - * PIC interrupt numbers in the intline registers). + * Try to re-route interrupts. Sometimes the BIOS or + * firmware may leave bogus values in these registers. + * If the re-route fails, then just stick with what we + * have. */ - cfg->intline = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); -#endif + irq = PCIB_ROUTE_INTERRUPT(pcib, dev, cfg->intpin); + if (PCI_INTERRUPT_VALID(irq)) { + cfg->intline = irq; + } resource_list_add(rl, SYS_RES_IRQ, 0, cfg->intline, cfg->intline, 1); } @@ -1412,3 +1414,36 @@ return (0); } + +int +pci_resume(device_t dev) +{ + int numdevs; + int i; + device_t *children; + device_t child; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + device_get_children(dev, &children, &numdevs); + + for (i = 0; i < numdevs; i++) { + child = children[i]; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + if (cfg->intpin > 0 && PCI_INTERRUPT_VALID(cfg->intline)) { + cfg->intline = PCIB_ROUTE_INTERRUPT(device_get_parent(dev), + child, cfg->intpin); + if (PCI_INTERRUPT_VALID(cfg->intline)) { + pci_write_config(child, PCIR_INTLINE, + cfg->intline, 1); + } + } + } + + free(children, M_TEMP); + + return (bus_generic_resume(dev)); +} + diff -druN /mnt/sys/dev/pci/pci_private.h dev/pci/pci_private.h --- /mnt/sys/dev/pci/pci_private.h Wed Sep 4 12:13:16 2002 +++ dev/pci/pci_private.h Wed Jan 22 12:07:02 2003 @@ -68,5 +68,6 @@ size_t size); void pci_print_verbose(struct pci_devinfo *dinfo); int pci_freecfg(struct pci_devinfo *dinfo); +int pci_resume(device_t dev); #endif /* _PCI_PRIVATE_H_ */ diff -druN /mnt/sys/dev/usb/ohci.c dev/usb/ohci.c --- /mnt/sys/dev/usb/ohci.c Mon Dec 9 10:41:24 2002 +++ dev/usb/ohci.c Wed Jan 22 12:05:58 2003 @@ -982,7 +982,6 @@ /* * Shut down the controller when the system is going down. */ -#if defined(__NetBSD__) || defined(__OpenBSD__) void ohci_shutdown(void *v) { @@ -1014,7 +1013,9 @@ s = splhardusb(); switch (why) { case PWR_SUSPEND: +#if 0 case PWR_STANDBY: +#endif sc->sc_bus.use_polling++; ctl = OREAD4(sc, OHCI_CONTROL) & ~OHCI_HCFS_MASK; if (sc->sc_control == 0) { @@ -1052,14 +1053,15 @@ sc->sc_control = sc->sc_intre = 0; sc->sc_bus.use_polling--; break; +#if 0 case PWR_SOFTSUSPEND: case PWR_SOFTSTANDBY: case PWR_SOFTRESUME: break; +#endif } splx(s); } -#endif #ifdef USB_DEBUG void diff -druN /mnt/sys/dev/usb/ohcivar.h dev/usb/ohcivar.h --- /mnt/sys/dev/usb/ohcivar.h Tue Oct 1 02:50:16 2002 +++ dev/usb/ohcivar.h Wed Jan 22 12:05:58 2003 @@ -160,4 +160,9 @@ int ohci_activate(device_ptr_t, enum devact); #endif +#if defined(__FreeBSD__) +void ohci_power(int state, void *); +void ohci_shutdown(void *); +#endif + #define MS_TO_TICKS(ms) ((ms) * hz / 1000) diff -druN /mnt/sys/dev/wi/if_wi.c dev/wi/if_wi.c --- /mnt/sys/dev/wi/if_wi.c Fri Nov 15 08:54:55 2002 +++ dev/wi/if_wi.c Wed Jan 22 12:06:54 2003 @@ -851,6 +851,17 @@ int s; sc = xsc; + + if (sc == NULL) { + printf("%s: wrong argument\n", __func__); + return; + } + + if (sc->wi_gone) { + printf("%s: already detached\n", __func__); + return; + } + ifp = &sc->arpcom.ac_if; sc->wi_stat_ch = timeout(wi_inquire, sc, hz * 60);