1331c488dSSøren Schmidt /*- 29f82379cSSøren Schmidt * Copyright (c) 1998 - 2008 S�ren Schmidt <sos@FreeBSD.org> 3331c488dSSøren Schmidt * All rights reserved. 4331c488dSSøren Schmidt * 5331c488dSSøren Schmidt * Redistribution and use in source and binary forms, with or without 6331c488dSSøren Schmidt * modification, are permitted provided that the following conditions 7331c488dSSøren Schmidt * are met: 8331c488dSSøren Schmidt * 1. Redistributions of source code must retain the above copyright 9331c488dSSøren Schmidt * notice, this list of conditions and the following disclaimer, 10331c488dSSøren Schmidt * without modification, immediately at the beginning of the file. 11331c488dSSøren Schmidt * 2. Redistributions in binary form must reproduce the above copyright 12331c488dSSøren Schmidt * notice, this list of conditions and the following disclaimer in the 13331c488dSSøren Schmidt * documentation and/or other materials provided with the distribution. 14331c488dSSøren Schmidt * 15331c488dSSøren Schmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16331c488dSSøren Schmidt * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17331c488dSSøren Schmidt * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18331c488dSSøren Schmidt * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19331c488dSSøren Schmidt * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20331c488dSSøren Schmidt * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21331c488dSSøren Schmidt * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22331c488dSSøren Schmidt * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23331c488dSSøren Schmidt * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24331c488dSSøren Schmidt * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25331c488dSSøren Schmidt */ 26331c488dSSøren Schmidt 27aad970f1SDavid E. O'Brien #include <sys/cdefs.h> 28aad970f1SDavid E. O'Brien __FBSDID("$FreeBSD$"); 29aad970f1SDavid E. O'Brien 307800211bSSøren Schmidt #include "opt_ata.h" 31331c488dSSøren Schmidt #include <sys/param.h> 32331c488dSSøren Schmidt #include <sys/systm.h> 33331c488dSSøren Schmidt #include <sys/kernel.h> 34331c488dSSøren Schmidt #include <sys/module.h> 358ca4df32SSøren Schmidt #include <sys/ata.h> 36331c488dSSøren Schmidt #include <sys/bus.h> 370a3a1935SSøren Schmidt #include <sys/conf.h> 38331c488dSSøren Schmidt #include <sys/malloc.h> 39a7a120f6SSøren Schmidt #include <sys/sema.h> 405fdbb0d2SSøren Schmidt #include <sys/taskqueue.h> 415df3ca78SSøren Schmidt #include <vm/uma.h> 42331c488dSSøren Schmidt #include <machine/stdarg.h> 43331c488dSSøren Schmidt #include <machine/resource.h> 44331c488dSSøren Schmidt #include <machine/bus.h> 45331c488dSSøren Schmidt #include <sys/rman.h> 464fbd232cSWarner Losh #include <dev/pci/pcivar.h> 474fbd232cSWarner Losh #include <dev/pci/pcireg.h> 48331c488dSSøren Schmidt #include <dev/ata/ata-all.h> 49bb5bdd38SSøren Schmidt #include <dev/ata/ata-pci.h> 508ca4df32SSøren Schmidt #include <ata_if.h> 51331c488dSSøren Schmidt 52bb5bdd38SSøren Schmidt /* local vars */ 535bb84bc8SRobert Watson static MALLOC_DEFINE(M_ATAPCI, "ata_pci", "ATA driver PCI"); 54331c488dSSøren Schmidt 5572c2f499SSøren Schmidt /* misc defines */ 5672c2f499SSøren Schmidt #define IOMASK 0xfffffffc 577af3abd8SSøren Schmidt #define ATA_PROBE_OK -10 5872c2f499SSøren Schmidt 594ee3fbe8SSøren Schmidt int 604ee3fbe8SSøren Schmidt ata_legacy(device_t dev) 614ee3fbe8SSøren Schmidt { 62cfaed55fSSøren Schmidt return (((pci_read_config(dev, PCIR_PROGIF, 1)&PCIP_STORAGE_IDE_MASTERDEV)&& 634ee3fbe8SSøren Schmidt ((pci_read_config(dev, PCIR_PROGIF, 1) & 644ee3fbe8SSøren Schmidt (PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC)) != 65cfaed55fSSøren Schmidt (PCIP_STORAGE_IDE_MODEPRIM | PCIP_STORAGE_IDE_MODESEC))) || 66cfaed55fSSøren Schmidt (!pci_read_config(dev, PCIR_BAR(0), 4) && 67cfaed55fSSøren Schmidt !pci_read_config(dev, PCIR_BAR(1), 4) && 68cfaed55fSSøren Schmidt !pci_read_config(dev, PCIR_BAR(2), 4) && 69f31e86f5SSøren Schmidt !pci_read_config(dev, PCIR_BAR(3), 4) && 70f31e86f5SSøren Schmidt !pci_read_config(dev, PCIR_BAR(5), 4))); 714ee3fbe8SSøren Schmidt } 724ee3fbe8SSøren Schmidt 738ca4df32SSøren Schmidt int 74331c488dSSøren Schmidt ata_pci_probe(device_t dev) 75331c488dSSøren Schmidt { 76bb5bdd38SSøren Schmidt if (pci_get_class(dev) != PCIC_STORAGE) 77331c488dSSøren Schmidt return ENXIO; 78331c488dSSøren Schmidt 79200c7605SSøren Schmidt /* if this is an AHCI chipset grab it */ 80200c7605SSøren Schmidt if (pci_get_subclass(dev) == PCIS_STORAGE_SATA) { 81200c7605SSøren Schmidt if (!ata_ahci_ident(dev)) 82200c7605SSøren Schmidt return ATA_PROBE_OK; 83200c7605SSøren Schmidt } 84200c7605SSøren Schmidt 85200c7605SSøren Schmidt /* run through the vendor specific drivers */ 86bb5bdd38SSøren Schmidt switch (pci_get_vendor(dev)) { 87bb5bdd38SSøren Schmidt case ATA_ACARD_ID: 8845f13b84SSøren Schmidt if (!ata_acard_ident(dev)) 897af3abd8SSøren Schmidt return ATA_PROBE_OK; 9045f13b84SSøren Schmidt break; 91bb5bdd38SSøren Schmidt case ATA_ACER_LABS_ID: 9245f13b84SSøren Schmidt if (!ata_ali_ident(dev)) 937af3abd8SSøren Schmidt return ATA_PROBE_OK; 9445f13b84SSøren Schmidt break; 95bb5bdd38SSøren Schmidt case ATA_AMD_ID: 9645f13b84SSøren Schmidt if (!ata_amd_ident(dev)) 977af3abd8SSøren Schmidt return ATA_PROBE_OK; 9845f13b84SSøren Schmidt break; 997ebce023SSøren Schmidt case ATA_ATI_ID: 1007ebce023SSøren Schmidt if (!ata_ati_ident(dev)) 1017af3abd8SSøren Schmidt return ATA_PROBE_OK; 1027ebce023SSøren Schmidt break; 103bb5bdd38SSøren Schmidt case ATA_CYRIX_ID: 10445f13b84SSøren Schmidt if (!ata_cyrix_ident(dev)) 1057af3abd8SSøren Schmidt return ATA_PROBE_OK; 10645f13b84SSøren Schmidt break; 107bb5bdd38SSøren Schmidt case ATA_CYPRESS_ID: 10845f13b84SSøren Schmidt if (!ata_cypress_ident(dev)) 1097af3abd8SSøren Schmidt return ATA_PROBE_OK; 11045f13b84SSøren Schmidt break; 111bb5bdd38SSøren Schmidt case ATA_HIGHPOINT_ID: 11245f13b84SSøren Schmidt if (!ata_highpoint_ident(dev)) 1137af3abd8SSøren Schmidt return ATA_PROBE_OK; 11445f13b84SSøren Schmidt break; 115bb5bdd38SSøren Schmidt case ATA_INTEL_ID: 11645f13b84SSøren Schmidt if (!ata_intel_ident(dev)) 1177af3abd8SSøren Schmidt return ATA_PROBE_OK; 11845f13b84SSøren Schmidt break; 11988bdf804SSøren Schmidt case ATA_ITE_ID: 12088bdf804SSøren Schmidt if (!ata_ite_ident(dev)) 1217af3abd8SSøren Schmidt return ATA_PROBE_OK; 12288bdf804SSøren Schmidt break; 123797c12eeSSøren Schmidt case ATA_JMICRON_ID: 124797c12eeSSøren Schmidt if (!ata_jmicron_ident(dev)) 125797c12eeSSøren Schmidt return ATA_PROBE_OK; 126797c12eeSSøren Schmidt break; 1274b55f0c7SSøren Schmidt case ATA_MARVELL_ID: 1284b55f0c7SSøren Schmidt if (!ata_marvell_ident(dev)) 1297af3abd8SSøren Schmidt return ATA_PROBE_OK; 1304b55f0c7SSøren Schmidt break; 131a5cd71eeSSøren Schmidt case ATA_NATIONAL_ID: 132a5cd71eeSSøren Schmidt if (!ata_national_ident(dev)) 1337af3abd8SSøren Schmidt return ATA_PROBE_OK; 134a5cd71eeSSøren Schmidt break; 135cece26a6SRink Springer case ATA_NETCELL_ID: 136cece26a6SRink Springer if (!ata_netcell_ident(dev)) 137cece26a6SRink Springer return ATA_PROBE_OK; 138cece26a6SRink Springer break; 139bb5bdd38SSøren Schmidt case ATA_NVIDIA_ID: 14045f13b84SSøren Schmidt if (!ata_nvidia_ident(dev)) 1417af3abd8SSøren Schmidt return ATA_PROBE_OK; 14245f13b84SSøren Schmidt break; 143bb5bdd38SSøren Schmidt case ATA_PROMISE_ID: 14445f13b84SSøren Schmidt if (!ata_promise_ident(dev)) 1457af3abd8SSøren Schmidt return ATA_PROBE_OK; 14645f13b84SSøren Schmidt break; 147bb5bdd38SSøren Schmidt case ATA_SERVERWORKS_ID: 14845f13b84SSøren Schmidt if (!ata_serverworks_ident(dev)) 1497af3abd8SSøren Schmidt return ATA_PROBE_OK; 15045f13b84SSøren Schmidt break; 151bb5bdd38SSøren Schmidt case ATA_SILICON_IMAGE_ID: 15245f13b84SSøren Schmidt if (!ata_sii_ident(dev)) 1537af3abd8SSøren Schmidt return ATA_PROBE_OK; 15445f13b84SSøren Schmidt break; 155bb5bdd38SSøren Schmidt case ATA_SIS_ID: 15645f13b84SSøren Schmidt if (!ata_sis_ident(dev)) 1577af3abd8SSøren Schmidt return ATA_PROBE_OK; 15845f13b84SSøren Schmidt break; 159bb5bdd38SSøren Schmidt case ATA_VIA_ID: 16045f13b84SSøren Schmidt if (!ata_via_ident(dev)) 1617af3abd8SSøren Schmidt return ATA_PROBE_OK; 16245f13b84SSøren Schmidt break; 16388bdf804SSøren Schmidt case ATA_CENATEK_ID: 16488bdf804SSøren Schmidt if (pci_get_devid(dev) == ATA_CENATEK_ROCKET) { 165566cf07aSSøren Schmidt ata_generic_ident(dev); 166bb5bdd38SSøren Schmidt device_set_desc(dev, "Cenatek Rocket Drive controller"); 1677af3abd8SSøren Schmidt return ATA_PROBE_OK; 168331c488dSSøren Schmidt } 16945f13b84SSøren Schmidt break; 17088bdf804SSøren Schmidt case ATA_MICRON_ID: 17188bdf804SSøren Schmidt if (pci_get_devid(dev) == ATA_MICRON_RZ1000 || 17288bdf804SSøren Schmidt pci_get_devid(dev) == ATA_MICRON_RZ1001) { 173566cf07aSSøren Schmidt ata_generic_ident(dev); 174bb5bdd38SSøren Schmidt device_set_desc(dev, 17588bdf804SSøren Schmidt "RZ 100? ATA controller !WARNING! data loss/corruption risk"); 1767af3abd8SSøren Schmidt return ATA_PROBE_OK; 177bb5bdd38SSøren Schmidt } 17845f13b84SSøren Schmidt break; 17945f13b84SSøren Schmidt } 180bb5bdd38SSøren Schmidt 181bb5bdd38SSøren Schmidt /* unknown chipset, try generic DMA if it seems possible */ 182200c7605SSøren Schmidt if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) { 1837af3abd8SSøren Schmidt if (!ata_generic_ident(dev)) 1847af3abd8SSøren Schmidt return ATA_PROBE_OK; 1857af3abd8SSøren Schmidt } 186bb5bdd38SSøren Schmidt return ENXIO; 187bb5bdd38SSøren Schmidt } 188331c488dSSøren Schmidt 1898ca4df32SSøren Schmidt int 190331c488dSSøren Schmidt ata_pci_attach(device_t dev) 191331c488dSSøren Schmidt { 192566cf07aSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 193498e5543SSøren Schmidt u_int32_t cmd; 1941b7cfe44SSøren Schmidt int unit; 195331c488dSSøren Schmidt 196566cf07aSSøren Schmidt /* do chipset specific setups only needed once */ 1976230b63cSSøren Schmidt if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK) 198566cf07aSSøren Schmidt ctlr->channels = 2; 199566cf07aSSøren Schmidt else 200566cf07aSSøren Schmidt ctlr->channels = 1; 201566cf07aSSøren Schmidt ctlr->allocate = ata_pci_allocate; 202566cf07aSSøren Schmidt ctlr->dmainit = ata_pci_dmainit; 2038ca4df32SSøren Schmidt ctlr->dev = dev; 204566cf07aSSøren Schmidt 205498e5543SSøren Schmidt /* if needed try to enable busmastering */ 206498e5543SSøren Schmidt cmd = pci_read_config(dev, PCIR_COMMAND, 2); 2077800211bSSøren Schmidt if (!(cmd & PCIM_CMD_BUSMASTEREN)) { 2087800211bSSøren Schmidt pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); 2097800211bSSøren Schmidt cmd = pci_read_config(dev, PCIR_COMMAND, 2); 2107800211bSSøren Schmidt } 211331c488dSSøren Schmidt 212498e5543SSøren Schmidt /* if busmastering mode "stuck" use it */ 213498e5543SSøren Schmidt if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { 214498e5543SSøren Schmidt ctlr->r_type1 = SYS_RES_IOPORT; 215498e5543SSøren Schmidt ctlr->r_rid1 = ATA_BMADDR_RID; 2165f96beb9SNate Lawson ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, 2175f96beb9SNate Lawson RF_ACTIVE); 218331c488dSSøren Schmidt } 219331c488dSSøren Schmidt 220f5f55db3SSøren Schmidt if (ctlr->chipinit(dev)) 221f5f55db3SSøren Schmidt return ENXIO; 222c2833977SSøren Schmidt 223566cf07aSSøren Schmidt /* attach all channels on this controller */ 2246230b63cSSøren Schmidt for (unit = 0; unit < ctlr->channels; unit++) { 225cfaed55fSSøren Schmidt if ((unit == 0 || unit == 1) && ata_legacy(dev)) { 2266230b63cSSøren Schmidt device_add_child(dev, "ata", unit); 2276230b63cSSøren Schmidt continue; 2286230b63cSSøren Schmidt } 2296230b63cSSøren Schmidt device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 2)); 2306230b63cSSøren Schmidt } 2318ca4df32SSøren Schmidt bus_generic_attach(dev); 2328ca4df32SSøren Schmidt return 0; 233f2972d7eSSøren Schmidt } 234498e5543SSøren Schmidt 2358ca4df32SSøren Schmidt int 236498e5543SSøren Schmidt ata_pci_detach(device_t dev) 237498e5543SSøren Schmidt { 238498e5543SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 2398ca4df32SSøren Schmidt device_t *children; 2408ca4df32SSøren Schmidt int nchildren, i; 241498e5543SSøren Schmidt 2428ca4df32SSøren Schmidt /* detach & delete all children */ 2438ca4df32SSøren Schmidt if (!device_get_children(dev, &children, &nchildren)) { 2448ca4df32SSøren Schmidt for (i = 0; i < nchildren; i++) 2458ca4df32SSøren Schmidt device_delete_child(dev, children[i]); 2468ca4df32SSøren Schmidt free(children, M_TEMP); 247331c488dSSøren Schmidt } 248331c488dSSøren Schmidt 249498e5543SSøren Schmidt if (ctlr->r_irq) { 250498e5543SSøren Schmidt bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle); 251498e5543SSøren Schmidt bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ctlr->r_irq); 252498e5543SSøren Schmidt } 253498e5543SSøren Schmidt if (ctlr->r_res2) 254498e5543SSøren Schmidt bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 255498e5543SSøren Schmidt if (ctlr->r_res1) 256498e5543SSøren Schmidt bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1, ctlr->r_res1); 257498e5543SSøren Schmidt 258498e5543SSøren Schmidt return 0; 259498e5543SSøren Schmidt } 260331c488dSSøren Schmidt 2618ca4df32SSøren Schmidt struct resource * 262331c488dSSøren Schmidt ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 263331c488dSSøren Schmidt u_long start, u_long end, u_long count, u_int flags) 264331c488dSSøren Schmidt { 2656ddce903SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 2666ddce903SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 267bb5bdd38SSøren Schmidt struct resource *res = NULL; 268331c488dSSøren Schmidt int myrid; 269331c488dSSøren Schmidt 270331c488dSSøren Schmidt if (type == SYS_RES_IOPORT) { 271331c488dSSøren Schmidt switch (*rid) { 272331c488dSSøren Schmidt case ATA_IOADDR_RID: 2734ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 2746ddce903SSøren Schmidt start = (unit ? ATA_SECONDARY : ATA_PRIMARY); 275331c488dSSøren Schmidt count = ATA_IOSIZE; 276f2972d7eSSøren Schmidt end = start + count - 1; 277331c488dSSøren Schmidt } 2786230b63cSSøren Schmidt myrid = PCIR_BAR(0) + (unit << 3); 279331c488dSSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, 280331c488dSSøren Schmidt SYS_RES_IOPORT, &myrid, 281331c488dSSøren Schmidt start, end, count, flags); 282331c488dSSøren Schmidt break; 283331c488dSSøren Schmidt 2840e1eb682SSøren Schmidt case ATA_CTLADDR_RID: 2854ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 2860e1eb682SSøren Schmidt start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET; 2870e1eb682SSøren Schmidt count = ATA_CTLIOSIZE; 288f2972d7eSSøren Schmidt end = start + count - 1; 289331c488dSSøren Schmidt } 2906230b63cSSøren Schmidt myrid = PCIR_BAR(1) + (unit << 3); 291331c488dSSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, 292331c488dSSøren Schmidt SYS_RES_IOPORT, &myrid, 293331c488dSSøren Schmidt start, end, count, flags); 294331c488dSSøren Schmidt break; 295331c488dSSøren Schmidt } 296331c488dSSøren Schmidt } 297331c488dSSøren Schmidt if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { 2984ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 2996ddce903SSøren Schmidt int irq = (unit == 0 ? 14 : 15); 300331c488dSSøren Schmidt 301bbccd832SSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 302468fe0fdSSøren Schmidt SYS_RES_IRQ, rid, irq, irq, 1, flags); 303331c488dSSøren Schmidt } 304bbccd832SSøren Schmidt else 305bbccd832SSøren Schmidt res = controller->r_irq; 306331c488dSSøren Schmidt } 307bbccd832SSøren Schmidt return res; 308331c488dSSøren Schmidt } 309331c488dSSøren Schmidt 3108ca4df32SSøren Schmidt int 311331c488dSSøren Schmidt ata_pci_release_resource(device_t dev, device_t child, int type, int rid, 312331c488dSSøren Schmidt struct resource *r) 313331c488dSSøren Schmidt { 3146ddce903SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 315331c488dSSøren Schmidt 316331c488dSSøren Schmidt if (type == SYS_RES_IOPORT) { 317331c488dSSøren Schmidt switch (rid) { 318331c488dSSøren Schmidt case ATA_IOADDR_RID: 319b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, 3206230b63cSSøren Schmidt SYS_RES_IOPORT, 3216230b63cSSøren Schmidt PCIR_BAR(0) + (unit << 3), r); 322331c488dSSøren Schmidt break; 323331c488dSSøren Schmidt 3240e1eb682SSøren Schmidt case ATA_CTLADDR_RID: 325b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, 3266230b63cSSøren Schmidt SYS_RES_IOPORT, 3276230b63cSSøren Schmidt PCIR_BAR(1) + (unit << 3), r); 328331c488dSSøren Schmidt break; 329331c488dSSøren Schmidt default: 330331c488dSSøren Schmidt return ENOENT; 331331c488dSSøren Schmidt } 332331c488dSSøren Schmidt } 333331c488dSSøren Schmidt if (type == SYS_RES_IRQ) { 334331c488dSSøren Schmidt if (rid != ATA_IRQ_RID) 335331c488dSSøren Schmidt return ENOENT; 336331c488dSSøren Schmidt 3374ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 338b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, 339b5a5e99dSSøren Schmidt SYS_RES_IRQ, rid, r); 340331c488dSSøren Schmidt } 341bb5bdd38SSøren Schmidt else 342331c488dSSøren Schmidt return 0; 343331c488dSSøren Schmidt } 344331c488dSSøren Schmidt return EINVAL; 345331c488dSSøren Schmidt } 346331c488dSSøren Schmidt 3478ca4df32SSøren Schmidt int 348331c488dSSøren Schmidt ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 349ef544f63SPaolo Pisati int flags, driver_filter_t *filter, driver_intr_t *function, 350ef544f63SPaolo Pisati void *argument, void **cookiep) 351331c488dSSøren Schmidt { 3524ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 353331c488dSSøren Schmidt return BUS_SETUP_INTR(device_get_parent(dev), child, irq, 354ef544f63SPaolo Pisati flags, filter, function, argument, cookiep); 355331c488dSSøren Schmidt } 356bb5bdd38SSøren Schmidt else { 357bb5bdd38SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 358bb5bdd38SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 359bb5bdd38SSøren Schmidt 360ef544f63SPaolo Pisati if (filter != NULL) { 361ef544f63SPaolo Pisati printf("ata-pci.c: we cannot use a filter here\n"); 362ef544f63SPaolo Pisati return (EINVAL); 363ef544f63SPaolo Pisati } 364bb5bdd38SSøren Schmidt controller->interrupt[unit].function = function; 365bb5bdd38SSøren Schmidt controller->interrupt[unit].argument = argument; 366bb5bdd38SSøren Schmidt *cookiep = controller; 367bb5bdd38SSøren Schmidt return 0; 368bb5bdd38SSøren Schmidt } 369331c488dSSøren Schmidt } 370331c488dSSøren Schmidt 3718ca4df32SSøren Schmidt int 372331c488dSSøren Schmidt ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, 373331c488dSSøren Schmidt void *cookie) 374331c488dSSøren Schmidt { 3754ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 376331c488dSSøren Schmidt return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); 377331c488dSSøren Schmidt } 3782e6c2a10SSøren Schmidt else { 3792e6c2a10SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 3802e6c2a10SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 3812e6c2a10SSøren Schmidt 3822e6c2a10SSøren Schmidt controller->interrupt[unit].function = NULL; 3832e6c2a10SSøren Schmidt controller->interrupt[unit].argument = NULL; 384bb5bdd38SSøren Schmidt return 0; 385331c488dSSøren Schmidt } 3862e6c2a10SSøren Schmidt } 387331c488dSSøren Schmidt 388b0a7e6a5SSøren Schmidt int 389bbccd832SSøren Schmidt ata_pci_allocate(device_t dev) 390566cf07aSSøren Schmidt { 391566cf07aSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 392bbccd832SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 3930e1eb682SSøren Schmidt struct resource *io = NULL, *ctlio = NULL; 394566cf07aSSøren Schmidt int i, rid; 395566cf07aSSøren Schmidt 396566cf07aSSøren Schmidt rid = ATA_IOADDR_RID; 397ecd6c15dSSøren Schmidt if (!(io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE))) 398566cf07aSSøren Schmidt return ENXIO; 399566cf07aSSøren Schmidt 4000e1eb682SSøren Schmidt rid = ATA_CTLADDR_RID; 401ecd6c15dSSøren Schmidt if (!(ctlio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,RF_ACTIVE))){ 402566cf07aSSøren Schmidt bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 403566cf07aSSøren Schmidt return ENXIO; 404566cf07aSSøren Schmidt } 405566cf07aSSøren Schmidt 4060e1eb682SSøren Schmidt for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { 407566cf07aSSøren Schmidt ch->r_io[i].res = io; 408566cf07aSSøren Schmidt ch->r_io[i].offset = i; 409566cf07aSSøren Schmidt } 4100e1eb682SSøren Schmidt ch->r_io[ATA_CONTROL].res = ctlio; 4110e1eb682SSøren Schmidt ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2; 4121b39bd24SSøren Schmidt ch->r_io[ATA_IDX_ADDR].res = io; 4130068f98fSSøren Schmidt ata_default_registers(dev); 414498e5543SSøren Schmidt if (ctlr->r_res1) { 415566cf07aSSøren Schmidt for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { 416498e5543SSøren Schmidt ch->r_io[i].res = ctlr->r_res1; 417566cf07aSSøren Schmidt ch->r_io[i].offset = (i - ATA_BMCMD_PORT) + (ch->unit*ATA_BMIOSIZE); 418566cf07aSSøren Schmidt } 419566cf07aSSøren Schmidt } 420f2972d7eSSøren Schmidt 421f5f55db3SSøren Schmidt ata_pci_hw(dev); 422566cf07aSSøren Schmidt return 0; 423566cf07aSSøren Schmidt } 424566cf07aSSøren Schmidt 4259f82379cSSøren Schmidt static int 426f5f55db3SSøren Schmidt ata_pci_status(device_t dev) 427f5f55db3SSøren Schmidt { 428f5f55db3SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 429f5f55db3SSøren Schmidt 4300a3a1935SSøren Schmidt if ((dumping || !ata_legacy(device_get_parent(dev))) && 4319f82379cSSøren Schmidt ((ch->flags & ATA_ALWAYS_DMASTAT) || 4329f82379cSSøren Schmidt (ch->dma.flags & ATA_DMA_ACTIVE))) { 433f5f55db3SSøren Schmidt int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 434f5f55db3SSøren Schmidt 435f5f55db3SSøren Schmidt if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != 436f5f55db3SSøren Schmidt ATA_BMSTAT_INTERRUPT) 437f5f55db3SSøren Schmidt return 0; 438f5f55db3SSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR); 439f5f55db3SSøren Schmidt DELAY(1); 440f5f55db3SSøren Schmidt } 441f5f55db3SSøren Schmidt if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { 442f5f55db3SSøren Schmidt DELAY(100); 443f5f55db3SSøren Schmidt if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) 444f5f55db3SSøren Schmidt return 0; 445f5f55db3SSøren Schmidt } 446f5f55db3SSøren Schmidt return 1; 447f5f55db3SSøren Schmidt } 448f5f55db3SSøren Schmidt 4499f82379cSSøren Schmidt void 4509f82379cSSøren Schmidt ata_pci_hw(device_t dev) 451566cf07aSSøren Schmidt { 4529f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 4539f82379cSSøren Schmidt 4549f82379cSSøren Schmidt ata_generic_hw(dev); 4559f82379cSSøren Schmidt ch->hw.status = ata_pci_status; 4569f82379cSSøren Schmidt } 4579f82379cSSøren Schmidt 4589f82379cSSøren Schmidt static int 4599f82379cSSøren Schmidt ata_pci_dmastart(struct ata_request *request) 4609f82379cSSøren Schmidt { 4619f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(request->parent); 4629f82379cSSøren Schmidt 4639f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmastart"); 4640068f98fSSøren Schmidt 465566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | 466566cf07aSSøren Schmidt (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 4679f82379cSSøren Schmidt ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma.sg_bus); 4689f82379cSSøren Schmidt ch->dma.flags |= ATA_DMA_ACTIVE; 469566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 47045bf968aSSøren Schmidt (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) | 4719f82379cSSøren Schmidt ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)| 47280344be5SSøren Schmidt ATA_BMCMD_START_STOP); 473566cf07aSSøren Schmidt return 0; 474566cf07aSSøren Schmidt } 475566cf07aSSøren Schmidt 476566cf07aSSøren Schmidt static int 4779f82379cSSøren Schmidt ata_pci_dmastop(struct ata_request *request) 478566cf07aSSøren Schmidt { 4799f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(request->parent); 480566cf07aSSøren Schmidt int error; 481566cf07aSSøren Schmidt 4829f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmastop"); 4839f82379cSSøren Schmidt 484566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 485566cf07aSSøren Schmidt ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 4869f82379cSSøren Schmidt ch->dma.flags &= ~ATA_DMA_ACTIVE; 487c5b2c44cSSøren Schmidt error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 488566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); 4895fdbb0d2SSøren Schmidt return error; 490566cf07aSSøren Schmidt } 491566cf07aSSøren Schmidt 4926419d0b0SSøren Schmidt static void 493eeda55ceSSøren Schmidt ata_pci_dmareset(device_t dev) 494eeda55ceSSøren Schmidt { 495eeda55ceSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 4969f82379cSSøren Schmidt struct ata_request *request; 497eeda55ceSSøren Schmidt 498eeda55ceSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 499eeda55ceSSøren Schmidt ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 5009f82379cSSøren Schmidt ch->dma.flags &= ~ATA_DMA_ACTIVE; 501eeda55ceSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); 5029f82379cSSøren Schmidt if ((request = ch->running)) { 5039f82379cSSøren Schmidt device_printf(request->dev, "DMA reset calling unload\n"); 5049f82379cSSøren Schmidt ch->dma.unload(request); 5059f82379cSSøren Schmidt } 506eeda55ceSSøren Schmidt } 507eeda55ceSSøren Schmidt 508e3989d3eSSøren Schmidt void 5090068f98fSSøren Schmidt ata_pci_dmainit(device_t dev) 510566cf07aSSøren Schmidt { 5110068f98fSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 5120068f98fSSøren Schmidt 5130068f98fSSøren Schmidt ata_dmainit(dev); 5149f82379cSSøren Schmidt ch->dma.start = ata_pci_dmastart; 5159f82379cSSøren Schmidt ch->dma.stop = ata_pci_dmastop; 5169f82379cSSøren Schmidt ch->dma.reset = ata_pci_dmareset; 517566cf07aSSøren Schmidt } 518566cf07aSSøren Schmidt 519200c7605SSøren Schmidt char * 520200c7605SSøren Schmidt ata_pcivendor2str(device_t dev) 521200c7605SSøren Schmidt { 522200c7605SSøren Schmidt switch (pci_get_vendor(dev)) { 523200c7605SSøren Schmidt case ATA_ACARD_ID: return "Acard"; 524200c7605SSøren Schmidt case ATA_ACER_LABS_ID: return "AcerLabs"; 525200c7605SSøren Schmidt case ATA_AMD_ID: return "AMD"; 526200c7605SSøren Schmidt case ATA_ATI_ID: return "ATI"; 527200c7605SSøren Schmidt case ATA_CYRIX_ID: return "Cyrix"; 528200c7605SSøren Schmidt case ATA_CYPRESS_ID: return "Cypress"; 529200c7605SSøren Schmidt case ATA_HIGHPOINT_ID: return "HighPoint"; 530200c7605SSøren Schmidt case ATA_INTEL_ID: return "Intel"; 531200c7605SSøren Schmidt case ATA_ITE_ID: return "ITE"; 532200c7605SSøren Schmidt case ATA_JMICRON_ID: return "JMicron"; 533200c7605SSøren Schmidt case ATA_MARVELL_ID: return "Marvell"; 534200c7605SSøren Schmidt case ATA_NATIONAL_ID: return "National"; 535200c7605SSøren Schmidt case ATA_NETCELL_ID: return "Netcell"; 536200c7605SSøren Schmidt case ATA_NVIDIA_ID: return "nVidia"; 537200c7605SSøren Schmidt case ATA_PROMISE_ID: return "Promise"; 538200c7605SSøren Schmidt case ATA_SERVERWORKS_ID: return "ServerWorks"; 539200c7605SSøren Schmidt case ATA_SILICON_IMAGE_ID: return "SiI"; 540200c7605SSøren Schmidt case ATA_SIS_ID: return "SiS"; 541200c7605SSøren Schmidt case ATA_VIA_ID: return "VIA"; 542200c7605SSøren Schmidt case ATA_CENATEK_ID: return "Cenatek"; 543200c7605SSøren Schmidt case ATA_MICRON_ID: return "Micron"; 544200c7605SSøren Schmidt default: return "Generic"; 545200c7605SSøren Schmidt } 546200c7605SSøren Schmidt } 547200c7605SSøren Schmidt 548331c488dSSøren Schmidt static device_method_t ata_pci_methods[] = { 549331c488dSSøren Schmidt /* device interface */ 550331c488dSSøren Schmidt DEVMETHOD(device_probe, ata_pci_probe), 551331c488dSSøren Schmidt DEVMETHOD(device_attach, ata_pci_attach), 552498e5543SSøren Schmidt DEVMETHOD(device_detach, ata_pci_detach), 553331c488dSSøren Schmidt DEVMETHOD(device_shutdown, bus_generic_shutdown), 554331c488dSSøren Schmidt DEVMETHOD(device_suspend, bus_generic_suspend), 555331c488dSSøren Schmidt DEVMETHOD(device_resume, bus_generic_resume), 556331c488dSSøren Schmidt 557331c488dSSøren Schmidt /* bus methods */ 558331c488dSSøren Schmidt DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), 559331c488dSSøren Schmidt DEVMETHOD(bus_release_resource, ata_pci_release_resource), 560331c488dSSøren Schmidt DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 561331c488dSSøren Schmidt DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 562331c488dSSøren Schmidt DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), 563331c488dSSøren Schmidt DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), 5648ca4df32SSøren Schmidt 565331c488dSSøren Schmidt { 0, 0 } 566331c488dSSøren Schmidt }; 567331c488dSSøren Schmidt 5688ca4df32SSøren Schmidt devclass_t atapci_devclass; 5698ca4df32SSøren Schmidt 570331c488dSSøren Schmidt static driver_t ata_pci_driver = { 571331c488dSSøren Schmidt "atapci", 572331c488dSSøren Schmidt ata_pci_methods, 5736ddce903SSøren Schmidt sizeof(struct ata_pci_controller), 574331c488dSSøren Schmidt }; 575331c488dSSøren Schmidt 5768ca4df32SSøren Schmidt DRIVER_MODULE(atapci, pci, ata_pci_driver, atapci_devclass, 0, 0); 5778ca4df32SSøren Schmidt MODULE_VERSION(atapci, 1); 5788ca4df32SSøren Schmidt MODULE_DEPEND(atapci, ata, 1, 1, 1); 579331c488dSSøren Schmidt 580331c488dSSøren Schmidt static int 5815a5b148dSSøren Schmidt ata_pcichannel_probe(device_t dev) 582331c488dSSøren Schmidt { 5836ddce903SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 584331c488dSSøren Schmidt device_t *children; 585d53fc3e4SSøren Schmidt int count, i; 5868ca4df32SSøren Schmidt char buffer[32]; 587331c488dSSøren Schmidt 588498e5543SSøren Schmidt /* take care of green memory */ 589498e5543SSøren Schmidt bzero(ch, sizeof(struct ata_channel)); 590498e5543SSøren Schmidt 591331c488dSSøren Schmidt /* find channel number on this controller */ 592331c488dSSøren Schmidt device_get_children(device_get_parent(dev), &children, &count); 593331c488dSSøren Schmidt for (i = 0; i < count; i++) { 594331c488dSSøren Schmidt if (children[i] == dev) 5956ddce903SSøren Schmidt ch->unit = i; 596331c488dSSøren Schmidt } 597331c488dSSøren Schmidt free(children, M_TEMP); 5988ba4488cSSøren Schmidt 5998ca4df32SSøren Schmidt sprintf(buffer, "ATA channel %d", ch->unit); 6008ca4df32SSøren Schmidt device_set_desc_copy(dev, buffer); 6018ca4df32SSøren Schmidt 602d53fc3e4SSøren Schmidt return ata_probe(dev); 603d53fc3e4SSøren Schmidt } 604d53fc3e4SSøren Schmidt 605d53fc3e4SSøren Schmidt static int 6065a5b148dSSøren Schmidt ata_pcichannel_attach(device_t dev) 607d53fc3e4SSøren Schmidt { 608d53fc3e4SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 609d53fc3e4SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 610d53fc3e4SSøren Schmidt int error; 611d53fc3e4SSøren Schmidt 6129f82379cSSøren Schmidt if (ctlr->dmainit) { 6130068f98fSSøren Schmidt ctlr->dmainit(dev); 6149f82379cSSøren Schmidt ch->dma.alloc(dev); 6159f82379cSSøren Schmidt } 616d53fc3e4SSøren Schmidt 6174471f79eSSøren Schmidt if ((error = ctlr->allocate(dev))) { 6189f82379cSSøren Schmidt ch->dma.free(dev); 619ca5d21e9SSøren Schmidt return error; 6204471f79eSSøren Schmidt } 621ca5d21e9SSøren Schmidt 622d53fc3e4SSøren Schmidt return ata_attach(dev); 623331c488dSSøren Schmidt } 624331c488dSSøren Schmidt 625d53fc3e4SSøren Schmidt static int 6265a5b148dSSøren Schmidt ata_pcichannel_detach(device_t dev) 627d53fc3e4SSøren Schmidt { 628d53fc3e4SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 629d53fc3e4SSøren Schmidt int error; 630d53fc3e4SSøren Schmidt 631d53fc3e4SSøren Schmidt if ((error = ata_detach(dev))) 632d53fc3e4SSøren Schmidt return error; 633d53fc3e4SSøren Schmidt 6349f82379cSSøren Schmidt ch->dma.free(dev); 635d53fc3e4SSøren Schmidt 636265da99cSSøren Schmidt /* XXX SOS free resources for io and ctlio ?? */ 637bbccd832SSøren Schmidt 638d53fc3e4SSøren Schmidt return 0; 639d53fc3e4SSøren Schmidt } 640d53fc3e4SSøren Schmidt 6415a5b148dSSøren Schmidt static int 6425a5b148dSSøren Schmidt ata_pcichannel_locking(device_t dev, int mode) 6435a5b148dSSøren Schmidt { 6445a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 6455a5b148dSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 6465a5b148dSSøren Schmidt 6475a5b148dSSøren Schmidt if (ctlr->locking) 6480068f98fSSøren Schmidt return ctlr->locking(dev, mode); 6495a5b148dSSøren Schmidt else 6505a5b148dSSøren Schmidt return ch->unit; 6515a5b148dSSøren Schmidt } 6525a5b148dSSøren Schmidt 6535a5b148dSSøren Schmidt static void 6545a5b148dSSøren Schmidt ata_pcichannel_reset(device_t dev) 6555a5b148dSSøren Schmidt { 6565a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 6575a5b148dSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 6585a5b148dSSøren Schmidt 659eeda55ceSSøren Schmidt /* if DMA engine present reset it */ 6609f82379cSSøren Schmidt if (ch->dma.reset) 6619f82379cSSøren Schmidt ch->dma.reset(dev); 662b0a7e6a5SSøren Schmidt 663b0a7e6a5SSøren Schmidt /* reset the controller HW */ 6645a5b148dSSøren Schmidt if (ctlr->reset) 6650068f98fSSøren Schmidt ctlr->reset(dev); 6668dad6b7bSSøren Schmidt else 6670068f98fSSøren Schmidt ata_generic_reset(dev); 6685a5b148dSSøren Schmidt } 6695a5b148dSSøren Schmidt 6705a5b148dSSøren Schmidt static void 6715a5b148dSSøren Schmidt ata_pcichannel_setmode(device_t parent, device_t dev) 6725a5b148dSSøren Schmidt { 6735a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); 6745a5b148dSSøren Schmidt struct ata_device *atadev = device_get_softc(dev); 6755a5b148dSSøren Schmidt int mode = atadev->mode; 6765a5b148dSSøren Schmidt 6770068f98fSSøren Schmidt ctlr->setmode(dev, ATA_PIO_MAX); 6785a5b148dSSøren Schmidt if (mode >= ATA_DMA) 6790068f98fSSøren Schmidt ctlr->setmode(dev, mode); 6805a5b148dSSøren Schmidt } 6815a5b148dSSøren Schmidt 6825a5b148dSSøren Schmidt static device_method_t ata_pcichannel_methods[] = { 683331c488dSSøren Schmidt /* device interface */ 6845a5b148dSSøren Schmidt DEVMETHOD(device_probe, ata_pcichannel_probe), 6855a5b148dSSøren Schmidt DEVMETHOD(device_attach, ata_pcichannel_attach), 6865a5b148dSSøren Schmidt DEVMETHOD(device_detach, ata_pcichannel_detach), 6878ca4df32SSøren Schmidt DEVMETHOD(device_shutdown, bus_generic_shutdown), 688186ba2b7SSøren Schmidt DEVMETHOD(device_suspend, ata_suspend), 689186ba2b7SSøren Schmidt DEVMETHOD(device_resume, ata_resume), 6905a5b148dSSøren Schmidt 6915a5b148dSSøren Schmidt /* ATA methods */ 6925a5b148dSSøren Schmidt DEVMETHOD(ata_setmode, ata_pcichannel_setmode), 6935a5b148dSSøren Schmidt DEVMETHOD(ata_locking, ata_pcichannel_locking), 6945a5b148dSSøren Schmidt DEVMETHOD(ata_reset, ata_pcichannel_reset), 6955a5b148dSSøren Schmidt 696331c488dSSøren Schmidt { 0, 0 } 697331c488dSSøren Schmidt }; 698331c488dSSøren Schmidt 6995a5b148dSSøren Schmidt driver_t ata_pcichannel_driver = { 700331c488dSSøren Schmidt "ata", 7015a5b148dSSøren Schmidt ata_pcichannel_methods, 7026ddce903SSøren Schmidt sizeof(struct ata_channel), 703331c488dSSøren Schmidt }; 704331c488dSSøren Schmidt 7055a5b148dSSøren Schmidt DRIVER_MODULE(ata, atapci, ata_pcichannel_driver, ata_devclass, 0, 0); 706