ata-card.c revision 124403
173897Ssos/*- 2124403Ssos * Copyright (c) 1998 - 2004 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 * 3. The name of the author may not be used to endorse or promote products 1573897Ssos * derived from this software without specific prior written permission. 1673897Ssos * 1773897Ssos * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1873897Ssos * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1973897Ssos * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2073897Ssos * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2173897Ssos * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2273897Ssos * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2373897Ssos * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2473897Ssos * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2573897Ssos * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2673897Ssos * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2773897Ssos */ 2873897Ssos 29119418Sobrien#include <sys/cdefs.h> 30119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/ata/ata-card.c 124403 2004-01-11 22:08:34Z sos $"); 31119418Sobrien 3273897Ssos#include <sys/param.h> 3373897Ssos#include <sys/systm.h> 34111809Ssos#include <sys/ata.h> 3573897Ssos#include <sys/kernel.h> 3673897Ssos#include <sys/module.h> 3773897Ssos#include <sys/bus.h> 3873897Ssos#include <sys/malloc.h> 39124403Ssos#include <sys/sema.h> 40119404Ssos#include <sys/taskqueue.h> 4173897Ssos#include <machine/stdarg.h> 4273897Ssos#include <machine/resource.h> 4373897Ssos#include <machine/bus.h> 4473897Ssos#include <sys/rman.h> 4573897Ssos#include <dev/ata/ata-all.h> 46120871Simp#include <dev/pccard/pccard_cis.h> 47120871Simp#include <dev/pccard/pccarddevs.h> 4889915Ssos#include <dev/pccard/pccardreg.h> 4989915Ssos#include <dev/pccard/pccardvar.h> 5073897Ssos 51114090Simpstatic const struct pccard_product ata_pccard_products[] = { 52116485Simp PCMCIA_CARD(FREECOM, PCCARDIDE, 0), 53114090Simp PCMCIA_CARD(EXP, EXPMULTIMEDIA, 0), 54114090Simp PCMCIA_CARD(IODATA, CBIDE2, 0), 55114090Simp PCMCIA_CARD(OEM2, CDROM1, 0), 56115756Simp PCMCIA_CARD(OEM2, IDE, 0), 57114090Simp PCMCIA_CARD(PANASONIC, KXLC005, 0), 58114090Simp PCMCIA_CARD(TEAC, IDECARDII, 0), 59114090Simp {NULL} 60114090Simp}; 61114090Simp 62123066SsosMALLOC_DECLARE(M_ATA); 63123066Ssos 6473897Ssosstatic int 6589915Ssosata_pccard_match(device_t dev) 6689915Ssos{ 67114090Simp const struct pccard_product *pp; 6890215Ssos u_int32_t fcn = PCCARD_FUNCTION_UNSPEC; 6990215Ssos int error = 0; 7089915Ssos 7189915Ssos error = pccard_get_function(dev, &fcn); 7289915Ssos if (error != 0) 7389915Ssos return (error); 7489915Ssos 7589915Ssos /* if it says its a disk we should register it */ 7689915Ssos if (fcn == PCCARD_FUNCTION_DISK) 7789915Ssos return (0); 7889915Ssos 79119404Ssos /* match other devices here, primarily cdrom/dvd rom */ 80114090Simp if ((pp = pccard_product_lookup(dev, ata_pccard_products, 81119450Ssos sizeof(ata_pccard_products[0]), NULL))) { 82114090Simp if (pp->pp_name) 83114090Simp device_set_desc(dev, pp->pp_name); 84114090Simp return (0); 85114090Simp } 8689915Ssos return(ENXIO); 8789915Ssos} 8889915Ssos 89107660Ssosstatic void 90107660Ssosata_pccard_locknoop(struct ata_channel *ch, int type) 91107660Ssos{ 92107660Ssos} 93107660Ssos 94111809Ssosstatic void 95111809Ssosata_pccard_setmode(struct ata_device *atadev, int mode) 96111809Ssos{ 97111809Ssos atadev->mode = ata_limit_mode(atadev, mode, ATA_PIO_MAX); 98111809Ssos} 99111809Ssos 100107660Ssosstatic int 10173897Ssosata_pccard_probe(device_t dev) 10273897Ssos{ 10390215Ssos struct ata_channel *ch = device_get_softc(dev); 104112791Ssos struct resource *io, *altio; 105123066Ssos int i, rid, len; 10673897Ssos 10773897Ssos /* allocate the io range to get start and length */ 10873897Ssos rid = ATA_IOADDR_RID; 10973897Ssos len = bus_get_resource_count(dev, SYS_RES_IOPORT, rid); 11073897Ssos io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 11173897Ssos ATA_IOSIZE, RF_ACTIVE); 11273897Ssos if (!io) 113112791Ssos return ENXIO; 11473897Ssos 115112791Ssos /* setup the resource vectors */ 116112791Ssos for (i = ATA_DATA; i <= ATA_STATUS; i++) { 117112791Ssos ch->r_io[i].res = io; 118112791Ssos ch->r_io[i].offset = i; 119112791Ssos } 120112791Ssos 121123066Ssos /* 122123066Ssos * if we got more than the default ATA_IOSIZE ports, this is a device 123123066Ssos * where altio is located at offset 14 into "normal" io space. 124123066Ssos */ 125123066Ssos if (len > ATA_IOSIZE) { 126123066Ssos ch->r_io[ATA_ALTSTAT].res = io; 127123066Ssos ch->r_io[ATA_ALTSTAT].offset = 14; 128123066Ssos } 129123066Ssos else { 130123066Ssos rid = ATA_ALTADDR_RID; 131123066Ssos altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 132123066Ssos ATA_ALTIOSIZE, RF_ACTIVE); 133123066Ssos if (!altio) { 134123066Ssos bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 135123066Ssos for (i = ATA_DATA; i < ATA_MAX_RES; i++) 136123066Ssos ch->r_io[i].res = NULL; 137123066Ssos return ENXIO; 138123066Ssos } 139123066Ssos ch->r_io[ATA_ALTSTAT].res = altio; 140123066Ssos ch->r_io[ATA_ALTSTAT].offset = 0; 141123066Ssos } 142123066Ssos 143112791Ssos /* initialize softc for this channel */ 14490215Ssos ch->unit = 0; 14590215Ssos ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE); 146111188Ssos ch->locking = ata_pccard_locknoop; 147111809Ssos ch->device[MASTER].setmode = ata_pccard_setmode; 14873897Ssos return ata_probe(dev); 14973897Ssos} 15073897Ssos 151112791Ssosstatic int 152112791Ssosata_pccard_detach(device_t dev) 153112791Ssos{ 154112791Ssos struct ata_channel *ch = device_get_softc(dev); 155112791Ssos int i; 156112791Ssos 157123066Ssos free(ch->device[MASTER].param, M_ATA); 158123066Ssos ch->device[MASTER].param = NULL; 159112791Ssos ata_detach(dev); 160112791Ssos bus_release_resource(dev, SYS_RES_IOPORT, 161112791Ssos ATA_ALTADDR_RID, ch->r_io[ATA_ALTSTAT].res); 162112791Ssos bus_release_resource(dev, SYS_RES_IOPORT, 163112791Ssos ATA_IOADDR_RID, 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 */ 17189915Ssos DEVMETHOD(device_probe, pccard_compat_probe), 17289915Ssos DEVMETHOD(device_attach, pccard_compat_attach), 173112791Ssos DEVMETHOD(device_detach, ata_pccard_detach), 17489915Ssos 17589915Ssos /* Card interface */ 17689915Ssos DEVMETHOD(card_compat_match, ata_pccard_match), 17789915Ssos DEVMETHOD(card_compat_probe, ata_pccard_probe), 17889915Ssos DEVMETHOD(card_compat_attach, ata_attach), 17973897Ssos { 0, 0 } 18073897Ssos}; 18173897Ssos 18273897Ssosstatic driver_t ata_pccard_driver = { 18373897Ssos "ata", 18473897Ssos ata_pccard_methods, 18590215Ssos sizeof(struct ata_channel), 18673897Ssos}; 18773897Ssos 18873897SsosDRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, 0, 0); 189