1/*- 2 * Copyright (c) 1998 - 2008 Søren Schmidt <sos@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer, 10 * without modification, immediately at the beginning of the file. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD$"); 29 30#include <sys/param.h> 31#include <sys/systm.h> 32#include <sys/ata.h> 33#include <sys/kernel.h> 34#include <sys/module.h> 35#include <sys/bus.h> 36#include <sys/malloc.h> 37#include <sys/sema.h> 38#include <sys/taskqueue.h> 39#include <vm/uma.h> 40#include <machine/stdarg.h> 41#include <machine/resource.h> 42#include <machine/bus.h> 43#include <sys/rman.h> 44#include <dev/ata/ata-all.h> 45#include <dev/pccard/pccard_cis.h> 46#include <dev/pccard/pccardreg.h> 47#include <dev/pccard/pccardvar.h> 48#include <ata_if.h> 49 50#include "pccarddevs.h" 51 52static const struct pccard_product ata_pccard_products[] = { 53 PCMCIA_CARD(FREECOM, PCCARDIDE), 54 PCMCIA_CARD(EXP, EXPMULTIMEDIA), 55 PCMCIA_CARD(IODATA3, CBIDE2), 56 PCMCIA_CARD(OEM2, CDROM1), 57 PCMCIA_CARD(OEM2, IDE), 58 PCMCIA_CARD(PANASONIC, KXLC005), 59 PCMCIA_CARD(TEAC, IDECARDII), 60 {NULL} 61}; 62 63static int 64ata_pccard_probe(device_t dev) 65{ 66 const struct pccard_product *pp; 67 u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; 68 int error = 0; 69 70 if ((error = pccard_get_function(dev, &fcn))) 71 return error; 72 73 /* if it says its a disk we should register it */ 74 if (fcn == PCCARD_FUNCTION_DISK) 75 return 0; 76 77 /* match other devices here, primarily cdrom/dvd rom */ 78 if ((pp = pccard_product_lookup(dev, ata_pccard_products, 79 sizeof(ata_pccard_products[0]), NULL))) { 80 if (pp->pp_name) 81 device_set_desc(dev, pp->pp_name); 82 return 0; 83 } 84 return ENXIO; 85} 86 87static int 88ata_pccard_attach(device_t dev) 89{ 90 struct ata_channel *ch = device_get_softc(dev); 91 struct resource *io, *ctlio; 92 int i, rid, err; 93 uint16_t funce; 94 95 if (ch->attached) 96 return (0); 97 ch->attached = 1; 98 99 /* allocate the io range to get start and length */ 100 rid = ATA_IOADDR_RID; 101 if (!(io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 102 ATA_IOSIZE, RF_ACTIVE))) 103 return (ENXIO); 104 105 /* setup the resource vectors */ 106 for (i = ATA_DATA; i <= ATA_COMMAND; i++) { 107 ch->r_io[i].res = io; 108 ch->r_io[i].offset = i; 109 } 110 ch->r_io[ATA_IDX_ADDR].res = io; 111 112 /* 113 * if we got more than the default ATA_IOSIZE ports, this is a device 114 * where ctlio is located at offset 14 into "normal" io space. 115 */ 116 if (rman_get_size(io) > ATA_IOSIZE) { 117 ch->r_io[ATA_CONTROL].res = io; 118 ch->r_io[ATA_CONTROL].offset = 14; 119 } 120 else { 121 rid = ATA_CTLADDR_RID; 122 if (!(ctlio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 123 ATA_CTLIOSIZE, RF_ACTIVE))) { 124 bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 125 for (i = ATA_DATA; i < ATA_MAX_RES; i++) 126 ch->r_io[i].res = NULL; 127 return (ENXIO); 128 } 129 ch->r_io[ATA_CONTROL].res = ctlio; 130 ch->r_io[ATA_CONTROL].offset = 0; 131 } 132 ata_default_registers(dev); 133 134 /* initialize softc for this channel */ 135 ch->unit = 0; 136 ch->flags |= ATA_USE_16BIT; 137 funce = 0; /* Default to sane setting of FUNCE */ 138 pccard_get_funce_disk(dev, &funce); 139 if (!(funce & PFD_I_D)) 140 ch-> flags |= ATA_NO_SLAVE; 141 ata_generic_hw(dev); 142 err = ata_probe(dev); 143 if (err > 0) 144 return (err); 145 return (ata_attach(dev)); 146} 147 148static int 149ata_pccard_detach(device_t dev) 150{ 151 struct ata_channel *ch = device_get_softc(dev); 152 int i; 153 154 if (!ch->attached) 155 return (0); 156 ch->attached = 0; 157 158 ata_detach(dev); 159 if (ch->r_io[ATA_CONTROL].res != ch->r_io[ATA_DATA].res) 160 bus_release_resource(dev, SYS_RES_IOPORT, ATA_CTLADDR_RID, 161 ch->r_io[ATA_CONTROL].res); 162 bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, 163 ch->r_io[ATA_DATA].res); 164 for (i = ATA_DATA; i < ATA_MAX_RES; i++) 165 ch->r_io[i].res = NULL; 166 return 0; 167} 168 169static device_method_t ata_pccard_methods[] = { 170 /* device interface */ 171 DEVMETHOD(device_probe, ata_pccard_probe), 172 DEVMETHOD(device_attach, ata_pccard_attach), 173 DEVMETHOD(device_detach, ata_pccard_detach), 174 175 DEVMETHOD_END 176}; 177 178static driver_t ata_pccard_driver = { 179 "ata", 180 ata_pccard_methods, 181 sizeof(struct ata_channel), 182}; 183 184DRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, NULL, NULL); 185MODULE_DEPEND(ata, ata, 1, 1, 1); 186