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; 99347458c9SSøren Schmidt case ATA_ADAPTEC_ID: 100347458c9SSøren Schmidt if (!ata_adaptec_ident(dev)) 101347458c9SSøren Schmidt return ATA_PROBE_OK; 102347458c9SSøren Schmidt break; 1037ebce023SSøren Schmidt case ATA_ATI_ID: 1047ebce023SSøren Schmidt if (!ata_ati_ident(dev)) 1057af3abd8SSøren Schmidt return ATA_PROBE_OK; 1067ebce023SSøren Schmidt break; 107bb5bdd38SSøren Schmidt case ATA_CYRIX_ID: 10845f13b84SSøren Schmidt if (!ata_cyrix_ident(dev)) 1097af3abd8SSøren Schmidt return ATA_PROBE_OK; 11045f13b84SSøren Schmidt break; 111bb5bdd38SSøren Schmidt case ATA_CYPRESS_ID: 11245f13b84SSøren Schmidt if (!ata_cypress_ident(dev)) 1137af3abd8SSøren Schmidt return ATA_PROBE_OK; 11445f13b84SSøren Schmidt break; 115bb5bdd38SSøren Schmidt case ATA_HIGHPOINT_ID: 11645f13b84SSøren Schmidt if (!ata_highpoint_ident(dev)) 1177af3abd8SSøren Schmidt return ATA_PROBE_OK; 11845f13b84SSøren Schmidt break; 119bb5bdd38SSøren Schmidt case ATA_INTEL_ID: 12045f13b84SSøren Schmidt if (!ata_intel_ident(dev)) 1217af3abd8SSøren Schmidt return ATA_PROBE_OK; 12245f13b84SSøren Schmidt break; 12388bdf804SSøren Schmidt case ATA_ITE_ID: 12488bdf804SSøren Schmidt if (!ata_ite_ident(dev)) 1257af3abd8SSøren Schmidt return ATA_PROBE_OK; 12688bdf804SSøren Schmidt break; 127797c12eeSSøren Schmidt case ATA_JMICRON_ID: 128797c12eeSSøren Schmidt if (!ata_jmicron_ident(dev)) 129797c12eeSSøren Schmidt return ATA_PROBE_OK; 130797c12eeSSøren Schmidt break; 1314b55f0c7SSøren Schmidt case ATA_MARVELL_ID: 1324b55f0c7SSøren Schmidt if (!ata_marvell_ident(dev)) 1337af3abd8SSøren Schmidt return ATA_PROBE_OK; 1344b55f0c7SSøren Schmidt break; 135a5cd71eeSSøren Schmidt case ATA_NATIONAL_ID: 136a5cd71eeSSøren Schmidt if (!ata_national_ident(dev)) 1377af3abd8SSøren Schmidt return ATA_PROBE_OK; 138a5cd71eeSSøren Schmidt break; 139cece26a6SRink Springer case ATA_NETCELL_ID: 140cece26a6SRink Springer if (!ata_netcell_ident(dev)) 141cece26a6SRink Springer return ATA_PROBE_OK; 142cece26a6SRink Springer break; 143bb5bdd38SSøren Schmidt case ATA_NVIDIA_ID: 14445f13b84SSøren Schmidt if (!ata_nvidia_ident(dev)) 1457af3abd8SSøren Schmidt return ATA_PROBE_OK; 14645f13b84SSøren Schmidt break; 147bb5bdd38SSøren Schmidt case ATA_PROMISE_ID: 14845f13b84SSøren Schmidt if (!ata_promise_ident(dev)) 1497af3abd8SSøren Schmidt return ATA_PROBE_OK; 15045f13b84SSøren Schmidt break; 151bb5bdd38SSøren Schmidt case ATA_SERVERWORKS_ID: 15245f13b84SSøren Schmidt if (!ata_serverworks_ident(dev)) 1537af3abd8SSøren Schmidt return ATA_PROBE_OK; 15445f13b84SSøren Schmidt break; 155bb5bdd38SSøren Schmidt case ATA_SILICON_IMAGE_ID: 15645f13b84SSøren Schmidt if (!ata_sii_ident(dev)) 1577af3abd8SSøren Schmidt return ATA_PROBE_OK; 15845f13b84SSøren Schmidt break; 159bb5bdd38SSøren Schmidt case ATA_SIS_ID: 16045f13b84SSøren Schmidt if (!ata_sis_ident(dev)) 1617af3abd8SSøren Schmidt return ATA_PROBE_OK; 16245f13b84SSøren Schmidt break; 163bb5bdd38SSøren Schmidt case ATA_VIA_ID: 16445f13b84SSøren Schmidt if (!ata_via_ident(dev)) 1657af3abd8SSøren Schmidt return ATA_PROBE_OK; 16645f13b84SSøren Schmidt break; 16788bdf804SSøren Schmidt case ATA_CENATEK_ID: 16888bdf804SSøren Schmidt if (pci_get_devid(dev) == ATA_CENATEK_ROCKET) { 169566cf07aSSøren Schmidt ata_generic_ident(dev); 170bb5bdd38SSøren Schmidt device_set_desc(dev, "Cenatek Rocket Drive controller"); 1717af3abd8SSøren Schmidt return ATA_PROBE_OK; 172331c488dSSøren Schmidt } 17345f13b84SSøren Schmidt break; 17488bdf804SSøren Schmidt case ATA_MICRON_ID: 17588bdf804SSøren Schmidt if (pci_get_devid(dev) == ATA_MICRON_RZ1000 || 17688bdf804SSøren Schmidt pci_get_devid(dev) == ATA_MICRON_RZ1001) { 177566cf07aSSøren Schmidt ata_generic_ident(dev); 178bb5bdd38SSøren Schmidt device_set_desc(dev, 17988bdf804SSøren Schmidt "RZ 100? ATA controller !WARNING! data loss/corruption risk"); 1807af3abd8SSøren Schmidt return ATA_PROBE_OK; 181bb5bdd38SSøren Schmidt } 18245f13b84SSøren Schmidt break; 18345f13b84SSøren Schmidt } 184bb5bdd38SSøren Schmidt 185bb5bdd38SSøren Schmidt /* unknown chipset, try generic DMA if it seems possible */ 186200c7605SSøren Schmidt if (pci_get_subclass(dev) == PCIS_STORAGE_IDE) { 1877af3abd8SSøren Schmidt if (!ata_generic_ident(dev)) 1887af3abd8SSøren Schmidt return ATA_PROBE_OK; 1897af3abd8SSøren Schmidt } 190bb5bdd38SSøren Schmidt return ENXIO; 191bb5bdd38SSøren Schmidt } 192331c488dSSøren Schmidt 1938ca4df32SSøren Schmidt int 194331c488dSSøren Schmidt ata_pci_attach(device_t dev) 195331c488dSSøren Schmidt { 196566cf07aSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 197498e5543SSøren Schmidt u_int32_t cmd; 1981b7cfe44SSøren Schmidt int unit; 199331c488dSSøren Schmidt 200566cf07aSSøren Schmidt /* do chipset specific setups only needed once */ 2016230b63cSSøren Schmidt if (ata_legacy(dev) || pci_read_config(dev, PCIR_BAR(2), 4) & IOMASK) 202566cf07aSSøren Schmidt ctlr->channels = 2; 203566cf07aSSøren Schmidt else 204566cf07aSSøren Schmidt ctlr->channels = 1; 205566cf07aSSøren Schmidt ctlr->allocate = ata_pci_allocate; 206566cf07aSSøren Schmidt ctlr->dmainit = ata_pci_dmainit; 2078ca4df32SSøren Schmidt ctlr->dev = dev; 208566cf07aSSøren Schmidt 209498e5543SSøren Schmidt /* if needed try to enable busmastering */ 210498e5543SSøren Schmidt cmd = pci_read_config(dev, PCIR_COMMAND, 2); 2117800211bSSøren Schmidt if (!(cmd & PCIM_CMD_BUSMASTEREN)) { 2127800211bSSøren Schmidt pci_write_config(dev, PCIR_COMMAND, cmd | PCIM_CMD_BUSMASTEREN, 2); 2137800211bSSøren Schmidt cmd = pci_read_config(dev, PCIR_COMMAND, 2); 2147800211bSSøren Schmidt } 215331c488dSSøren Schmidt 216498e5543SSøren Schmidt /* if busmastering mode "stuck" use it */ 217498e5543SSøren Schmidt if ((cmd & PCIM_CMD_BUSMASTEREN) == PCIM_CMD_BUSMASTEREN) { 218498e5543SSøren Schmidt ctlr->r_type1 = SYS_RES_IOPORT; 219498e5543SSøren Schmidt ctlr->r_rid1 = ATA_BMADDR_RID; 2205f96beb9SNate Lawson ctlr->r_res1 = bus_alloc_resource_any(dev, ctlr->r_type1, &ctlr->r_rid1, 2215f96beb9SNate Lawson RF_ACTIVE); 222331c488dSSøren Schmidt } 223331c488dSSøren Schmidt 224f5f55db3SSøren Schmidt if (ctlr->chipinit(dev)) 225f5f55db3SSøren Schmidt return ENXIO; 226c2833977SSøren Schmidt 227566cf07aSSøren Schmidt /* attach all channels on this controller */ 2286230b63cSSøren Schmidt for (unit = 0; unit < ctlr->channels; unit++) { 229cfaed55fSSøren Schmidt if ((unit == 0 || unit == 1) && ata_legacy(dev)) { 2306230b63cSSøren Schmidt device_add_child(dev, "ata", unit); 2316230b63cSSøren Schmidt continue; 2326230b63cSSøren Schmidt } 2336230b63cSSøren Schmidt device_add_child(dev, "ata", devclass_find_free_unit(ata_devclass, 2)); 2346230b63cSSøren Schmidt } 2358ca4df32SSøren Schmidt bus_generic_attach(dev); 2368ca4df32SSøren Schmidt return 0; 237f2972d7eSSøren Schmidt } 238498e5543SSøren Schmidt 2398ca4df32SSøren Schmidt int 240498e5543SSøren Schmidt ata_pci_detach(device_t dev) 241498e5543SSøren Schmidt { 242498e5543SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 2438ca4df32SSøren Schmidt device_t *children; 2448ca4df32SSøren Schmidt int nchildren, i; 245498e5543SSøren Schmidt 2468ca4df32SSøren Schmidt /* detach & delete all children */ 2478ca4df32SSøren Schmidt if (!device_get_children(dev, &children, &nchildren)) { 2488ca4df32SSøren Schmidt for (i = 0; i < nchildren; i++) 2498ca4df32SSøren Schmidt device_delete_child(dev, children[i]); 2508ca4df32SSøren Schmidt free(children, M_TEMP); 251331c488dSSøren Schmidt } 252331c488dSSøren Schmidt 253498e5543SSøren Schmidt if (ctlr->r_irq) { 254498e5543SSøren Schmidt bus_teardown_intr(dev, ctlr->r_irq, ctlr->handle); 255498e5543SSøren Schmidt bus_release_resource(dev, SYS_RES_IRQ, ATA_IRQ_RID, ctlr->r_irq); 256498e5543SSøren Schmidt } 257498e5543SSøren Schmidt if (ctlr->r_res2) 258498e5543SSøren Schmidt bus_release_resource(dev, ctlr->r_type2, ctlr->r_rid2, ctlr->r_res2); 259498e5543SSøren Schmidt if (ctlr->r_res1) 260498e5543SSøren Schmidt bus_release_resource(dev, ctlr->r_type1, ctlr->r_rid1, ctlr->r_res1); 261498e5543SSøren Schmidt 262498e5543SSøren Schmidt return 0; 263498e5543SSøren Schmidt } 264331c488dSSøren Schmidt 2657aab7e05SSøren Schmidt int 2667aab7e05SSøren Schmidt ata_pci_suspend(device_t dev) 2677aab7e05SSøren Schmidt { 2687aab7e05SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 2697aab7e05SSøren Schmidt int error = 0; 2707aab7e05SSøren Schmidt 2717aab7e05SSøren Schmidt bus_generic_suspend(dev); 2727aab7e05SSøren Schmidt if (ctlr->suspend) 2737aab7e05SSøren Schmidt error = ctlr->suspend(dev); 2747aab7e05SSøren Schmidt return error; 2757aab7e05SSøren Schmidt } 2767aab7e05SSøren Schmidt 2777aab7e05SSøren Schmidt int 2787aab7e05SSøren Schmidt ata_pci_resume(device_t dev) 2797aab7e05SSøren Schmidt { 2807aab7e05SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(dev); 2817aab7e05SSøren Schmidt int error = 0; 2827aab7e05SSøren Schmidt 2837aab7e05SSøren Schmidt if (ctlr->resume) 2847aab7e05SSøren Schmidt error = ctlr->resume(dev); 2857aab7e05SSøren Schmidt bus_generic_resume(dev); 2867aab7e05SSøren Schmidt return error; 2877aab7e05SSøren Schmidt } 2887aab7e05SSøren Schmidt 2897aab7e05SSøren Schmidt 2908ca4df32SSøren Schmidt struct resource * 291331c488dSSøren Schmidt ata_pci_alloc_resource(device_t dev, device_t child, int type, int *rid, 292331c488dSSøren Schmidt u_long start, u_long end, u_long count, u_int flags) 293331c488dSSøren Schmidt { 2946ddce903SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 2956ddce903SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 296bb5bdd38SSøren Schmidt struct resource *res = NULL; 297331c488dSSøren Schmidt int myrid; 298331c488dSSøren Schmidt 299331c488dSSøren Schmidt if (type == SYS_RES_IOPORT) { 300331c488dSSøren Schmidt switch (*rid) { 301331c488dSSøren Schmidt case ATA_IOADDR_RID: 3024ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 3036ddce903SSøren Schmidt start = (unit ? ATA_SECONDARY : ATA_PRIMARY); 304331c488dSSøren Schmidt count = ATA_IOSIZE; 305f2972d7eSSøren Schmidt end = start + count - 1; 306331c488dSSøren Schmidt } 3076230b63cSSøren Schmidt myrid = PCIR_BAR(0) + (unit << 3); 308331c488dSSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, 309331c488dSSøren Schmidt SYS_RES_IOPORT, &myrid, 310331c488dSSøren Schmidt start, end, count, flags); 311331c488dSSøren Schmidt break; 312331c488dSSøren Schmidt 3130e1eb682SSøren Schmidt case ATA_CTLADDR_RID: 3144ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 3150e1eb682SSøren Schmidt start = (unit ? ATA_SECONDARY : ATA_PRIMARY) + ATA_CTLOFFSET; 3160e1eb682SSøren Schmidt count = ATA_CTLIOSIZE; 317f2972d7eSSøren Schmidt end = start + count - 1; 318331c488dSSøren Schmidt } 3196230b63cSSøren Schmidt myrid = PCIR_BAR(1) + (unit << 3); 320331c488dSSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, 321331c488dSSøren Schmidt SYS_RES_IOPORT, &myrid, 322331c488dSSøren Schmidt start, end, count, flags); 323331c488dSSøren Schmidt break; 324331c488dSSøren Schmidt } 325331c488dSSøren Schmidt } 326331c488dSSøren Schmidt if (type == SYS_RES_IRQ && *rid == ATA_IRQ_RID) { 3274ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 3286ddce903SSøren Schmidt int irq = (unit == 0 ? 14 : 15); 329331c488dSSøren Schmidt 330bbccd832SSøren Schmidt res = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, 331468fe0fdSSøren Schmidt SYS_RES_IRQ, rid, irq, irq, 1, flags); 332331c488dSSøren Schmidt } 333bbccd832SSøren Schmidt else 334bbccd832SSøren Schmidt res = controller->r_irq; 335331c488dSSøren Schmidt } 336bbccd832SSøren Schmidt return res; 337331c488dSSøren Schmidt } 338331c488dSSøren Schmidt 3398ca4df32SSøren Schmidt int 340331c488dSSøren Schmidt ata_pci_release_resource(device_t dev, device_t child, int type, int rid, 341331c488dSSøren Schmidt struct resource *r) 342331c488dSSøren Schmidt { 3436ddce903SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 344331c488dSSøren Schmidt 345331c488dSSøren Schmidt if (type == SYS_RES_IOPORT) { 346331c488dSSøren Schmidt switch (rid) { 347331c488dSSøren Schmidt case ATA_IOADDR_RID: 348b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, 3496230b63cSSøren Schmidt SYS_RES_IOPORT, 3506230b63cSSøren Schmidt PCIR_BAR(0) + (unit << 3), r); 351331c488dSSøren Schmidt break; 352331c488dSSøren Schmidt 3530e1eb682SSøren Schmidt case ATA_CTLADDR_RID: 354b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, 3556230b63cSSøren Schmidt SYS_RES_IOPORT, 3566230b63cSSøren Schmidt PCIR_BAR(1) + (unit << 3), r); 357331c488dSSøren Schmidt break; 358331c488dSSøren Schmidt default: 359331c488dSSøren Schmidt return ENOENT; 360331c488dSSøren Schmidt } 361331c488dSSøren Schmidt } 362331c488dSSøren Schmidt if (type == SYS_RES_IRQ) { 363331c488dSSøren Schmidt if (rid != ATA_IRQ_RID) 364331c488dSSøren Schmidt return ENOENT; 365331c488dSSøren Schmidt 3664ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 367b5a5e99dSSøren Schmidt return BUS_RELEASE_RESOURCE(device_get_parent(dev), child, 368b5a5e99dSSøren Schmidt SYS_RES_IRQ, rid, r); 369331c488dSSøren Schmidt } 370bb5bdd38SSøren Schmidt else 371331c488dSSøren Schmidt return 0; 372331c488dSSøren Schmidt } 373331c488dSSøren Schmidt return EINVAL; 374331c488dSSøren Schmidt } 375331c488dSSøren Schmidt 3768ca4df32SSøren Schmidt int 377331c488dSSøren Schmidt ata_pci_setup_intr(device_t dev, device_t child, struct resource *irq, 378ef544f63SPaolo Pisati int flags, driver_filter_t *filter, driver_intr_t *function, 379ef544f63SPaolo Pisati void *argument, void **cookiep) 380331c488dSSøren Schmidt { 3814ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 382331c488dSSøren Schmidt return BUS_SETUP_INTR(device_get_parent(dev), child, irq, 383ef544f63SPaolo Pisati flags, filter, function, argument, cookiep); 384331c488dSSøren Schmidt } 385bb5bdd38SSøren Schmidt else { 386bb5bdd38SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 387bb5bdd38SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 388bb5bdd38SSøren Schmidt 389ef544f63SPaolo Pisati if (filter != NULL) { 390ef544f63SPaolo Pisati printf("ata-pci.c: we cannot use a filter here\n"); 391ef544f63SPaolo Pisati return (EINVAL); 392ef544f63SPaolo Pisati } 393bb5bdd38SSøren Schmidt controller->interrupt[unit].function = function; 394bb5bdd38SSøren Schmidt controller->interrupt[unit].argument = argument; 395bb5bdd38SSøren Schmidt *cookiep = controller; 396bb5bdd38SSøren Schmidt return 0; 397bb5bdd38SSøren Schmidt } 398331c488dSSøren Schmidt } 399331c488dSSøren Schmidt 4008ca4df32SSøren Schmidt int 401331c488dSSøren Schmidt ata_pci_teardown_intr(device_t dev, device_t child, struct resource *irq, 402331c488dSSøren Schmidt void *cookie) 403331c488dSSøren Schmidt { 4044ee3fbe8SSøren Schmidt if (ata_legacy(dev)) { 405331c488dSSøren Schmidt return BUS_TEARDOWN_INTR(device_get_parent(dev), child, irq, cookie); 406331c488dSSøren Schmidt } 4072e6c2a10SSøren Schmidt else { 4082e6c2a10SSøren Schmidt struct ata_pci_controller *controller = device_get_softc(dev); 4092e6c2a10SSøren Schmidt int unit = ((struct ata_channel *)device_get_softc(child))->unit; 4102e6c2a10SSøren Schmidt 4112e6c2a10SSøren Schmidt controller->interrupt[unit].function = NULL; 4122e6c2a10SSøren Schmidt controller->interrupt[unit].argument = NULL; 413bb5bdd38SSøren Schmidt return 0; 414331c488dSSøren Schmidt } 4152e6c2a10SSøren Schmidt } 416331c488dSSøren Schmidt 417b0a7e6a5SSøren Schmidt int 418bbccd832SSøren Schmidt ata_pci_allocate(device_t dev) 419566cf07aSSøren Schmidt { 420566cf07aSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 421bbccd832SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 4220e1eb682SSøren Schmidt struct resource *io = NULL, *ctlio = NULL; 423566cf07aSSøren Schmidt int i, rid; 424566cf07aSSøren Schmidt 425566cf07aSSøren Schmidt rid = ATA_IOADDR_RID; 426ecd6c15dSSøren Schmidt if (!(io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE))) 427566cf07aSSøren Schmidt return ENXIO; 428566cf07aSSøren Schmidt 4290e1eb682SSøren Schmidt rid = ATA_CTLADDR_RID; 430ecd6c15dSSøren Schmidt if (!(ctlio = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid,RF_ACTIVE))){ 431566cf07aSSøren Schmidt bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 432566cf07aSSøren Schmidt return ENXIO; 433566cf07aSSøren Schmidt } 434566cf07aSSøren Schmidt 4350e1eb682SSøren Schmidt for (i = ATA_DATA; i <= ATA_COMMAND; i ++) { 436566cf07aSSøren Schmidt ch->r_io[i].res = io; 437566cf07aSSøren Schmidt ch->r_io[i].offset = i; 438566cf07aSSøren Schmidt } 4390e1eb682SSøren Schmidt ch->r_io[ATA_CONTROL].res = ctlio; 4400e1eb682SSøren Schmidt ch->r_io[ATA_CONTROL].offset = ata_legacy(device_get_parent(dev)) ? 0 : 2; 4411b39bd24SSøren Schmidt ch->r_io[ATA_IDX_ADDR].res = io; 4420068f98fSSøren Schmidt ata_default_registers(dev); 443498e5543SSøren Schmidt if (ctlr->r_res1) { 444566cf07aSSøren Schmidt for (i = ATA_BMCMD_PORT; i <= ATA_BMDTP_PORT; i++) { 445498e5543SSøren Schmidt ch->r_io[i].res = ctlr->r_res1; 446566cf07aSSøren Schmidt ch->r_io[i].offset = (i - ATA_BMCMD_PORT) + (ch->unit*ATA_BMIOSIZE); 447566cf07aSSøren Schmidt } 448566cf07aSSøren Schmidt } 449f2972d7eSSøren Schmidt 450f5f55db3SSøren Schmidt ata_pci_hw(dev); 451566cf07aSSøren Schmidt return 0; 452566cf07aSSøren Schmidt } 453566cf07aSSøren Schmidt 454a7c33e78SSøren Schmidt int 455f5f55db3SSøren Schmidt ata_pci_status(device_t dev) 456f5f55db3SSøren Schmidt { 457f5f55db3SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 458f5f55db3SSøren Schmidt 4590a3a1935SSøren Schmidt if ((dumping || !ata_legacy(device_get_parent(dev))) && 4609f82379cSSøren Schmidt ((ch->flags & ATA_ALWAYS_DMASTAT) || 4619f82379cSSøren Schmidt (ch->dma.flags & ATA_DMA_ACTIVE))) { 462f5f55db3SSøren Schmidt int bmstat = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 463f5f55db3SSøren Schmidt 464f5f55db3SSøren Schmidt if ((bmstat & (ATA_BMSTAT_ACTIVE | ATA_BMSTAT_INTERRUPT)) != 465f5f55db3SSøren Schmidt ATA_BMSTAT_INTERRUPT) 466f5f55db3SSøren Schmidt return 0; 467f5f55db3SSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, bmstat & ~ATA_BMSTAT_ERROR); 468f5f55db3SSøren Schmidt DELAY(1); 469f5f55db3SSøren Schmidt } 470f5f55db3SSøren Schmidt if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) { 471f5f55db3SSøren Schmidt DELAY(100); 472f5f55db3SSøren Schmidt if (ATA_IDX_INB(ch, ATA_ALTSTAT) & ATA_S_BUSY) 473f5f55db3SSøren Schmidt return 0; 474f5f55db3SSøren Schmidt } 475f5f55db3SSøren Schmidt return 1; 476f5f55db3SSøren Schmidt } 477f5f55db3SSøren Schmidt 4789f82379cSSøren Schmidt void 4799f82379cSSøren Schmidt ata_pci_hw(device_t dev) 480566cf07aSSøren Schmidt { 4819f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 4829f82379cSSøren Schmidt 4839f82379cSSøren Schmidt ata_generic_hw(dev); 4849f82379cSSøren Schmidt ch->hw.status = ata_pci_status; 4859f82379cSSøren Schmidt } 4869f82379cSSøren Schmidt 4879f82379cSSøren Schmidt static int 4889f82379cSSøren Schmidt ata_pci_dmastart(struct ata_request *request) 4899f82379cSSøren Schmidt { 4909f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(request->parent); 4919f82379cSSøren Schmidt 4929f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmastart"); 4930068f98fSSøren Schmidt 494566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, (ATA_IDX_INB(ch, ATA_BMSTAT_PORT) | 495566cf07aSSøren Schmidt (ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR))); 496104c094eSSøren Schmidt ATA_IDX_OUTL(ch, ATA_BMDTP_PORT, request->dma->sg_bus); 4979f82379cSSøren Schmidt ch->dma.flags |= ATA_DMA_ACTIVE; 498566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 49945bf968aSSøren Schmidt (ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_WRITE_READ) | 5009f82379cSSøren Schmidt ((request->flags & ATA_R_READ) ? ATA_BMCMD_WRITE_READ : 0)| 50180344be5SSøren Schmidt ATA_BMCMD_START_STOP); 502566cf07aSSøren Schmidt return 0; 503566cf07aSSøren Schmidt } 504566cf07aSSøren Schmidt 505566cf07aSSøren Schmidt static int 5069f82379cSSøren Schmidt ata_pci_dmastop(struct ata_request *request) 507566cf07aSSøren Schmidt { 5089f82379cSSøren Schmidt struct ata_channel *ch = device_get_softc(request->parent); 509566cf07aSSøren Schmidt int error; 510566cf07aSSøren Schmidt 5119f82379cSSøren Schmidt ATA_DEBUG_RQ(request, "dmastop"); 5129f82379cSSøren Schmidt 513566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 514566cf07aSSøren Schmidt ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 5159f82379cSSøren Schmidt ch->dma.flags &= ~ATA_DMA_ACTIVE; 516c5b2c44cSSøren Schmidt error = ATA_IDX_INB(ch, ATA_BMSTAT_PORT) & ATA_BMSTAT_MASK; 517566cf07aSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); 5185fdbb0d2SSøren Schmidt return error; 519566cf07aSSøren Schmidt } 520566cf07aSSøren Schmidt 5216419d0b0SSøren Schmidt static void 522eeda55ceSSøren Schmidt ata_pci_dmareset(device_t dev) 523eeda55ceSSøren Schmidt { 524eeda55ceSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 5259f82379cSSøren Schmidt struct ata_request *request; 526eeda55ceSSøren Schmidt 527eeda55ceSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMCMD_PORT, 528eeda55ceSSøren Schmidt ATA_IDX_INB(ch, ATA_BMCMD_PORT) & ~ATA_BMCMD_START_STOP); 5299f82379cSSøren Schmidt ch->dma.flags &= ~ATA_DMA_ACTIVE; 530eeda55ceSSøren Schmidt ATA_IDX_OUTB(ch, ATA_BMSTAT_PORT, ATA_BMSTAT_INTERRUPT | ATA_BMSTAT_ERROR); 5319f82379cSSøren Schmidt if ((request = ch->running)) { 5329f82379cSSøren Schmidt device_printf(request->dev, "DMA reset calling unload\n"); 5339f82379cSSøren Schmidt ch->dma.unload(request); 5349f82379cSSøren Schmidt } 535eeda55ceSSøren Schmidt } 536eeda55ceSSøren Schmidt 537e3989d3eSSøren Schmidt void 5380068f98fSSøren Schmidt ata_pci_dmainit(device_t dev) 539566cf07aSSøren Schmidt { 5400068f98fSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 5410068f98fSSøren Schmidt 5420068f98fSSøren Schmidt ata_dmainit(dev); 5439f82379cSSøren Schmidt ch->dma.start = ata_pci_dmastart; 5449f82379cSSøren Schmidt ch->dma.stop = ata_pci_dmastop; 5459f82379cSSøren Schmidt ch->dma.reset = ata_pci_dmareset; 546566cf07aSSøren Schmidt } 547566cf07aSSøren Schmidt 548200c7605SSøren Schmidt char * 549200c7605SSøren Schmidt ata_pcivendor2str(device_t dev) 550200c7605SSøren Schmidt { 551200c7605SSøren Schmidt switch (pci_get_vendor(dev)) { 552200c7605SSøren Schmidt case ATA_ACARD_ID: return "Acard"; 553200c7605SSøren Schmidt case ATA_ACER_LABS_ID: return "AcerLabs"; 554200c7605SSøren Schmidt case ATA_AMD_ID: return "AMD"; 555347458c9SSøren Schmidt case ATA_ADAPTEC_ID: return "Adaptec"; 556200c7605SSøren Schmidt case ATA_ATI_ID: return "ATI"; 557200c7605SSøren Schmidt case ATA_CYRIX_ID: return "Cyrix"; 558200c7605SSøren Schmidt case ATA_CYPRESS_ID: return "Cypress"; 559200c7605SSøren Schmidt case ATA_HIGHPOINT_ID: return "HighPoint"; 560200c7605SSøren Schmidt case ATA_INTEL_ID: return "Intel"; 561200c7605SSøren Schmidt case ATA_ITE_ID: return "ITE"; 562200c7605SSøren Schmidt case ATA_JMICRON_ID: return "JMicron"; 563200c7605SSøren Schmidt case ATA_MARVELL_ID: return "Marvell"; 564200c7605SSøren Schmidt case ATA_NATIONAL_ID: return "National"; 565200c7605SSøren Schmidt case ATA_NETCELL_ID: return "Netcell"; 566200c7605SSøren Schmidt case ATA_NVIDIA_ID: return "nVidia"; 567200c7605SSøren Schmidt case ATA_PROMISE_ID: return "Promise"; 568200c7605SSøren Schmidt case ATA_SERVERWORKS_ID: return "ServerWorks"; 569200c7605SSøren Schmidt case ATA_SILICON_IMAGE_ID: return "SiI"; 570200c7605SSøren Schmidt case ATA_SIS_ID: return "SiS"; 571200c7605SSøren Schmidt case ATA_VIA_ID: return "VIA"; 572200c7605SSøren Schmidt case ATA_CENATEK_ID: return "Cenatek"; 573200c7605SSøren Schmidt case ATA_MICRON_ID: return "Micron"; 574200c7605SSøren Schmidt default: return "Generic"; 575200c7605SSøren Schmidt } 576200c7605SSøren Schmidt } 577200c7605SSøren Schmidt 578331c488dSSøren Schmidt static device_method_t ata_pci_methods[] = { 579331c488dSSøren Schmidt /* device interface */ 580331c488dSSøren Schmidt DEVMETHOD(device_probe, ata_pci_probe), 581331c488dSSøren Schmidt DEVMETHOD(device_attach, ata_pci_attach), 582498e5543SSøren Schmidt DEVMETHOD(device_detach, ata_pci_detach), 5837aab7e05SSøren Schmidt DEVMETHOD(device_suspend, ata_pci_suspend), 5847aab7e05SSøren Schmidt DEVMETHOD(device_resume, ata_pci_resume), 585331c488dSSøren Schmidt DEVMETHOD(device_shutdown, bus_generic_shutdown), 586331c488dSSøren Schmidt 587331c488dSSøren Schmidt /* bus methods */ 588331c488dSSøren Schmidt DEVMETHOD(bus_alloc_resource, ata_pci_alloc_resource), 589331c488dSSøren Schmidt DEVMETHOD(bus_release_resource, ata_pci_release_resource), 590331c488dSSøren Schmidt DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), 591331c488dSSøren Schmidt DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), 592331c488dSSøren Schmidt DEVMETHOD(bus_setup_intr, ata_pci_setup_intr), 593331c488dSSøren Schmidt DEVMETHOD(bus_teardown_intr, ata_pci_teardown_intr), 5948ca4df32SSøren Schmidt 595331c488dSSøren Schmidt { 0, 0 } 596331c488dSSøren Schmidt }; 597331c488dSSøren Schmidt 5988ca4df32SSøren Schmidt devclass_t atapci_devclass; 5998ca4df32SSøren Schmidt 600331c488dSSøren Schmidt static driver_t ata_pci_driver = { 601331c488dSSøren Schmidt "atapci", 602331c488dSSøren Schmidt ata_pci_methods, 6036ddce903SSøren Schmidt sizeof(struct ata_pci_controller), 604331c488dSSøren Schmidt }; 605331c488dSSøren Schmidt 6068ca4df32SSøren Schmidt DRIVER_MODULE(atapci, pci, ata_pci_driver, atapci_devclass, 0, 0); 6078ca4df32SSøren Schmidt MODULE_VERSION(atapci, 1); 6088ca4df32SSøren Schmidt MODULE_DEPEND(atapci, ata, 1, 1, 1); 609331c488dSSøren Schmidt 610331c488dSSøren Schmidt static int 6115a5b148dSSøren Schmidt ata_pcichannel_probe(device_t dev) 612331c488dSSøren Schmidt { 6136ddce903SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 614331c488dSSøren Schmidt device_t *children; 615d53fc3e4SSøren Schmidt int count, i; 6168ca4df32SSøren Schmidt char buffer[32]; 617331c488dSSøren Schmidt 618498e5543SSøren Schmidt /* take care of green memory */ 619498e5543SSøren Schmidt bzero(ch, sizeof(struct ata_channel)); 620498e5543SSøren Schmidt 621331c488dSSøren Schmidt /* find channel number on this controller */ 622331c488dSSøren Schmidt device_get_children(device_get_parent(dev), &children, &count); 623331c488dSSøren Schmidt for (i = 0; i < count; i++) { 624331c488dSSøren Schmidt if (children[i] == dev) 6256ddce903SSøren Schmidt ch->unit = i; 626331c488dSSøren Schmidt } 627331c488dSSøren Schmidt free(children, M_TEMP); 6288ba4488cSSøren Schmidt 6298ca4df32SSøren Schmidt sprintf(buffer, "ATA channel %d", ch->unit); 6308ca4df32SSøren Schmidt device_set_desc_copy(dev, buffer); 6318ca4df32SSøren Schmidt 632d53fc3e4SSøren Schmidt return ata_probe(dev); 633d53fc3e4SSøren Schmidt } 634d53fc3e4SSøren Schmidt 635d53fc3e4SSøren Schmidt static int 6365a5b148dSSøren Schmidt ata_pcichannel_attach(device_t dev) 637d53fc3e4SSøren Schmidt { 638d53fc3e4SSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 639d53fc3e4SSøren Schmidt int error; 640d53fc3e4SSøren Schmidt 641104c094eSSøren Schmidt if (ctlr->dmainit) 6420068f98fSSøren Schmidt ctlr->dmainit(dev); 643d53fc3e4SSøren Schmidt 644104c094eSSøren Schmidt if ((error = ctlr->allocate(dev))) 645ca5d21e9SSøren Schmidt return error; 646ca5d21e9SSøren Schmidt 647082b99a8SSøren Schmidt return ata_attach(dev); 648331c488dSSøren Schmidt } 649331c488dSSøren Schmidt 650d53fc3e4SSøren Schmidt static int 6515a5b148dSSøren Schmidt ata_pcichannel_detach(device_t dev) 652d53fc3e4SSøren Schmidt { 653d53fc3e4SSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 654d53fc3e4SSøren Schmidt int error; 655d53fc3e4SSøren Schmidt 656d53fc3e4SSøren Schmidt if ((error = ata_detach(dev))) 657d53fc3e4SSøren Schmidt return error; 658d53fc3e4SSøren Schmidt 6599f82379cSSøren Schmidt ch->dma.free(dev); 660d53fc3e4SSøren Schmidt 661265da99cSSøren Schmidt /* XXX SOS free resources for io and ctlio ?? */ 662bbccd832SSøren Schmidt 663d53fc3e4SSøren Schmidt return 0; 664d53fc3e4SSøren Schmidt } 665d53fc3e4SSøren Schmidt 6665a5b148dSSøren Schmidt static int 6675a5b148dSSøren Schmidt ata_pcichannel_locking(device_t dev, int mode) 6685a5b148dSSøren Schmidt { 6695a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 6705a5b148dSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 6715a5b148dSSøren Schmidt 6725a5b148dSSøren Schmidt if (ctlr->locking) 6730068f98fSSøren Schmidt return ctlr->locking(dev, mode); 6745a5b148dSSøren Schmidt else 6755a5b148dSSøren Schmidt return ch->unit; 6765a5b148dSSøren Schmidt } 6775a5b148dSSøren Schmidt 6785a5b148dSSøren Schmidt static void 6795a5b148dSSøren Schmidt ata_pcichannel_reset(device_t dev) 6805a5b148dSSøren Schmidt { 6815a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(device_get_parent(dev)); 6825a5b148dSSøren Schmidt struct ata_channel *ch = device_get_softc(dev); 6835a5b148dSSøren Schmidt 684eeda55ceSSøren Schmidt /* if DMA engine present reset it */ 6859f82379cSSøren Schmidt if (ch->dma.reset) 6869f82379cSSøren Schmidt ch->dma.reset(dev); 687b0a7e6a5SSøren Schmidt 688b0a7e6a5SSøren Schmidt /* reset the controller HW */ 6895a5b148dSSøren Schmidt if (ctlr->reset) 6900068f98fSSøren Schmidt ctlr->reset(dev); 6918dad6b7bSSøren Schmidt else 6920068f98fSSøren Schmidt ata_generic_reset(dev); 6935a5b148dSSøren Schmidt } 6945a5b148dSSøren Schmidt 6955a5b148dSSøren Schmidt static void 6965a5b148dSSøren Schmidt ata_pcichannel_setmode(device_t parent, device_t dev) 6975a5b148dSSøren Schmidt { 6985a5b148dSSøren Schmidt struct ata_pci_controller *ctlr = device_get_softc(GRANDPARENT(dev)); 6995a5b148dSSøren Schmidt struct ata_device *atadev = device_get_softc(dev); 7005a5b148dSSøren Schmidt int mode = atadev->mode; 7015a5b148dSSøren Schmidt 7020068f98fSSøren Schmidt ctlr->setmode(dev, ATA_PIO_MAX); 7035a5b148dSSøren Schmidt if (mode >= ATA_DMA) 7040068f98fSSøren Schmidt ctlr->setmode(dev, mode); 7055a5b148dSSøren Schmidt } 7065a5b148dSSøren Schmidt 7075a5b148dSSøren Schmidt static device_method_t ata_pcichannel_methods[] = { 708331c488dSSøren Schmidt /* device interface */ 7095a5b148dSSøren Schmidt DEVMETHOD(device_probe, ata_pcichannel_probe), 7105a5b148dSSøren Schmidt DEVMETHOD(device_attach, ata_pcichannel_attach), 7115a5b148dSSøren Schmidt DEVMETHOD(device_detach, ata_pcichannel_detach), 7128ca4df32SSøren Schmidt DEVMETHOD(device_shutdown, bus_generic_shutdown), 713186ba2b7SSøren Schmidt DEVMETHOD(device_suspend, ata_suspend), 714186ba2b7SSøren Schmidt DEVMETHOD(device_resume, ata_resume), 7155a5b148dSSøren Schmidt 7165a5b148dSSøren Schmidt /* ATA methods */ 7175a5b148dSSøren Schmidt DEVMETHOD(ata_setmode, ata_pcichannel_setmode), 7185a5b148dSSøren Schmidt DEVMETHOD(ata_locking, ata_pcichannel_locking), 7195a5b148dSSøren Schmidt DEVMETHOD(ata_reset, ata_pcichannel_reset), 7205a5b148dSSøren Schmidt 721331c488dSSøren Schmidt { 0, 0 } 722331c488dSSøren Schmidt }; 723331c488dSSøren Schmidt 7245a5b148dSSøren Schmidt driver_t ata_pcichannel_driver = { 725331c488dSSøren Schmidt "ata", 7265a5b148dSSøren Schmidt ata_pcichannel_methods, 7276ddce903SSøren Schmidt sizeof(struct ata_channel), 728331c488dSSøren Schmidt }; 729331c488dSSøren Schmidt 7305a5b148dSSøren Schmidt DRIVER_MODULE(ata, atapci, ata_pcichannel_driver, ata_devclass, 0, 0); 731