173897Ssos/*- 2230132Suqs * Copyright (c) 1998 - 2008 S��ren Schmidt <sos@FreeBSD.org> 373897Ssos * All rights reserved. 473897Ssos * 573897Ssos * Redistribution and use in source and binary forms, with or without 673897Ssos * modification, are permitted provided that the following conditions 773897Ssos * are met: 873897Ssos * 1. Redistributions of source code must retain the above copyright 973897Ssos * notice, this list of conditions and the following disclaimer, 1073897Ssos * without modification, immediately at the beginning of the file. 1173897Ssos * 2. Redistributions in binary form must reproduce the above copyright 1273897Ssos * notice, this list of conditions and the following disclaimer in the 1373897Ssos * documentation and/or other materials provided with the distribution. 1473897Ssos * 1573897Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1673897Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1773897Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1873897Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1973897Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2073897Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2173897Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2273897Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2373897Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2473897Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2573897Ssos */ 2673897Ssos 27119418Sobrien#include <sys/cdefs.h> 28119418Sobrien__FBSDID("$FreeBSD$"); 29119418Sobrien 3073897Ssos#include <sys/param.h> 3173897Ssos#include <sys/systm.h> 32111809Ssos#include <sys/ata.h> 3373897Ssos#include <sys/kernel.h> 3473897Ssos#include <sys/module.h> 3573897Ssos#include <sys/bus.h> 3673897Ssos#include <sys/malloc.h> 37124403Ssos#include <sys/sema.h> 38119404Ssos#include <sys/taskqueue.h> 39124534Ssos#include <vm/uma.h> 4073897Ssos#include <machine/stdarg.h> 4173897Ssos#include <machine/resource.h> 4273897Ssos#include <machine/bus.h> 4373897Ssos#include <sys/rman.h> 4473897Ssos#include <dev/ata/ata-all.h> 45120871Simp#include <dev/pccard/pccard_cis.h> 4689915Ssos#include <dev/pccard/pccardreg.h> 4789915Ssos#include <dev/pccard/pccardvar.h> 48145000Ssos#include <ata_if.h> 4973897Ssos 50129764Simp#include "pccarddevs.h" 51129764Simp 52242625Sdimstatic const struct pccard_product ata_pccard_products[] = { 53147580Simp PCMCIA_CARD(FREECOM, PCCARDIDE), 54147580Simp PCMCIA_CARD(EXP, EXPMULTIMEDIA), 55147580Simp PCMCIA_CARD(IODATA3, CBIDE2), 56147580Simp PCMCIA_CARD(OEM2, CDROM1), 57147580Simp PCMCIA_CARD(OEM2, IDE), 58147580Simp PCMCIA_CARD(PANASONIC, KXLC005), 59147580Simp PCMCIA_CARD(TEAC, IDECARDII), 60114090Simp {NULL} 61114090Simp}; 62114090Simp 6373897Ssosstatic int 64150480Sglebiusata_pccard_probe(device_t dev) 6589915Ssos{ 66114090Simp const struct pccard_product *pp; 6790215Ssos u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; 6890215Ssos int error = 0; 6989915Ssos 70145499Ssos if ((error = pccard_get_function(dev, &fcn))) 71145499Ssos return error; 7289915Ssos 7389915Ssos /* if it says its a disk we should register it */ 7489915Ssos if (fcn == PCCARD_FUNCTION_DISK) 75145499Ssos return 0; 7689915Ssos 77119404Ssos /* match other devices here, primarily cdrom/dvd rom */ 78114090Simp if ((pp = pccard_product_lookup(dev, ata_pccard_products, 79119450Ssos sizeof(ata_pccard_products[0]), NULL))) { 80114090Simp if (pp->pp_name) 81114090Simp device_set_desc(dev, pp->pp_name); 82145499Ssos return 0; 83114090Simp } 84145499Ssos return ENXIO; 8589915Ssos} 8689915Ssos 87136198Ssosstatic int 88150480Sglebiusata_pccard_attach(device_t dev) 8973897Ssos{ 9090215Ssos struct ata_channel *ch = device_get_softc(dev); 91144707Ssos struct resource *io, *ctlio; 92150481Simp int i, rid, err; 93189724Simp uint16_t funce; 9473897Ssos 95188812Smav if (ch->attached) 96188812Smav return (0); 97188812Smav ch->attached = 1; 98188812Smav 9973897Ssos /* allocate the io range to get start and length */ 10073897Ssos rid = ATA_IOADDR_RID; 101145499Ssos if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 102145499Ssos ATA_IOSIZE, RF_ACTIVE))) 103150481Simp return (ENXIO); 10473897Ssos 105112791Ssos /* setup the resource vectors */ 106144707Ssos for (i = ATA_DATA; i <= ATA_COMMAND; i++) { 107112791Ssos ch->r_io[i].res = io; 108112791Ssos ch->r_io[i].offset = i; 109112791Ssos } 110144707Ssos ch->r_io[ATA_IDX_ADDR].res = io; 111112791Ssos 112123066Ssos /* 113123066Ssos * if we got more than the default ATA_IOSIZE ports, this is a device 114144707Ssos * where ctlio is located at offset 14 into "normal" io space. 115123066Ssos */ 116137493Simp if (rman_get_size(io) > ATA_IOSIZE) { 117144707Ssos ch->r_io[ATA_CONTROL].res = io; 118144707Ssos ch->r_io[ATA_CONTROL].offset = 14; 119123066Ssos } 120123066Ssos else { 121144707Ssos rid = ATA_CTLADDR_RID; 122145499Ssos if (!(ctlio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 123145499Ssos ATA_CTLIOSIZE, RF_ACTIVE))) { 124123066Ssos bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 125123066Ssos for (i = ATA_DATA; i < ATA_MAX_RES; i++) 126123066Ssos ch->r_io[i].res = NULL; 127150481Simp return (ENXIO); 128123066Ssos } 129144707Ssos ch->r_io[ATA_CONTROL].res = ctlio; 130144707Ssos ch->r_io[ATA_CONTROL].offset = 0; 131123066Ssos } 132145713Ssos ata_default_registers(dev); 133123066Ssos 134112791Ssos /* initialize softc for this channel */ 13590215Ssos ch->unit = 0; 136189724Simp ch->flags |= ATA_USE_16BIT; 137189724Simp funce = 0; /* Default to sane setting of FUNCE */ 138209682Simp pccard_get_funce_disk(dev, &funce); 139189724Simp if (!(funce & PFD_I_D)) 140209682Simp ch-> flags |= ATA_NO_SLAVE; 141145713Ssos ata_generic_hw(dev); 142150481Simp err = ata_probe(dev); 143256326Sgrehan if (err > 0) 144150481Simp return (err); 145150481Simp return (ata_attach(dev)); 14673897Ssos} 14773897Ssos 148112791Ssosstatic int 149112791Ssosata_pccard_detach(device_t dev) 150112791Ssos{ 151112791Ssos struct ata_channel *ch = device_get_softc(dev); 152112791Ssos int i; 153112791Ssos 154188812Smav if (!ch->attached) 155188812Smav return (0); 156188812Smav ch->attached = 0; 157188812Smav 158112791Ssos ata_detach(dev); 159144707Ssos if (ch->r_io[ATA_CONTROL].res != ch->r_io[ATA_DATA].res) 160144707Ssos bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, 161144707Ssos ch->r_io[ATA_CONTROL].res); 162137493Simp bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, 163137493Simp ch->r_io[ATA_DATA].res); 164114947Sphk for (i = ATA_DATA; i < ATA_MAX_RES; i++) 165112791Ssos ch->r_io[i].res = NULL; 166112791Ssos return 0; 167112791Ssos} 168112791Ssos 16973897Ssosstatic device_method_t ata_pccard_methods[] = { 17073897Ssos /* device interface */ 171150480Sglebius DEVMETHOD(device_probe, ata_pccard_probe), 172150480Sglebius DEVMETHOD(device_attach, ata_pccard_attach), 173145000Ssos DEVMETHOD(device_detach, ata_pccard_detach), 17489915Ssos 175233282Smarius DEVMETHOD_END 17673897Ssos}; 17773897Ssos 17873897Ssosstatic driver_t ata_pccard_driver = { 17973897Ssos "ata", 18073897Ssos ata_pccard_methods, 18190215Ssos sizeof(struct ata_channel), 18273897Ssos}; 18373897Ssos 184233282SmariusDRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, NULL, NULL); 185144330SsosMODULE_DEPEND(ata, ata, 1, 1, 1); 186