ata-card.c revision 144330
173897Ssos/*- 2144330Ssos * Copyright (c) 1998 - 2005 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 144330 2005-03-30 12:03:40Z 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> 41124534Ssos#include <vm/uma.h> 4273897Ssos#include <machine/stdarg.h> 4373897Ssos#include <machine/resource.h> 4473897Ssos#include <machine/bus.h> 4573897Ssos#include <sys/rman.h> 4673897Ssos#include <dev/ata/ata-all.h> 47120871Simp#include <dev/pccard/pccard_cis.h> 4889915Ssos#include <dev/pccard/pccardreg.h> 4989915Ssos#include <dev/pccard/pccardvar.h> 5073897Ssos 51129764Simp#include "pccarddevs.h" 52129764Simp 53114090Simpstatic const struct pccard_product ata_pccard_products[] = { 54116485Simp PCMCIA_CARD(FREECOM, PCCARDIDE, 0), 55114090Simp PCMCIA_CARD(EXP, EXPMULTIMEDIA, 0), 56140846Simp PCMCIA_CARD(IODATA3, CBIDE2, 0), 57114090Simp PCMCIA_CARD(OEM2, CDROM1, 0), 58115756Simp PCMCIA_CARD(OEM2, IDE, 0), 59114090Simp PCMCIA_CARD(PANASONIC, KXLC005, 0), 60114090Simp PCMCIA_CARD(TEAC, IDECARDII, 0), 61114090Simp {NULL} 62114090Simp}; 63114090Simp 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 89136198Ssosstatic int 9073897Ssosata_pccard_probe(device_t dev) 9173897Ssos{ 9290215Ssos struct ata_channel *ch = device_get_softc(dev); 93112791Ssos struct resource *io, *altio; 94137493Simp int i, rid; 9573897Ssos 9673897Ssos /* allocate the io range to get start and length */ 9773897Ssos rid = ATA_IOADDR_RID; 9873897Ssos io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 9973897Ssos ATA_IOSIZE, RF_ACTIVE); 10073897Ssos if (!io) 101112791Ssos return ENXIO; 10273897Ssos 103112791Ssos /* setup the resource vectors */ 104112791Ssos for (i = ATA_DATA; i <= ATA_STATUS; i++) { 105112791Ssos ch->r_io[i].res = io; 106112791Ssos ch->r_io[i].offset = i; 107112791Ssos } 108112791Ssos 109123066Ssos /* 110123066Ssos * if we got more than the default ATA_IOSIZE ports, this is a device 111123066Ssos * where altio is located at offset 14 into "normal" io space. 112123066Ssos */ 113137493Simp if (rman_get_size(io) > ATA_IOSIZE) { 114123066Ssos ch->r_io[ATA_ALTSTAT].res = io; 115123066Ssos ch->r_io[ATA_ALTSTAT].offset = 14; 116123066Ssos } 117123066Ssos else { 118123066Ssos rid = ATA_ALTADDR_RID; 119123066Ssos altio = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 0, ~0, 120123066Ssos ATA_ALTIOSIZE, RF_ACTIVE); 121123066Ssos if (!altio) { 122123066Ssos bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, io); 123123066Ssos for (i = ATA_DATA; i < ATA_MAX_RES; i++) 124123066Ssos ch->r_io[i].res = NULL; 125123066Ssos return ENXIO; 126123066Ssos } 127123066Ssos ch->r_io[ATA_ALTSTAT].res = altio; 128123066Ssos ch->r_io[ATA_ALTSTAT].offset = 0; 129123066Ssos } 130123066Ssos 131112791Ssos /* initialize softc for this channel */ 13290215Ssos ch->unit = 0; 13390215Ssos ch->flags |= (ATA_USE_16BIT | ATA_NO_SLAVE); 134128183Ssos ata_generic_hw(ch); 13573897Ssos return ata_probe(dev); 13673897Ssos} 13773897Ssos 138112791Ssosstatic int 139112791Ssosata_pccard_detach(device_t dev) 140112791Ssos{ 141112791Ssos struct ata_channel *ch = device_get_softc(dev); 142112791Ssos int i; 143112791Ssos 144112791Ssos ata_detach(dev); 145137493Simp if (ch->r_io[ATA_ALTSTAT].res != ch->r_io[ATA_DATA].res) 146137493Simp bus_release_resource(dev, SYS_RES_IOPORT, ATA_ALTADDR_RID, 147137493Simp ch->r_io[ATA_ALTSTAT].res); 148137493Simp bus_release_resource(dev, SYS_RES_IOPORT, ATA_IOADDR_RID, 149137493Simp ch->r_io[ATA_DATA].res); 150114947Sphk for (i = ATA_DATA; i < ATA_MAX_RES; i++) 151112791Ssos ch->r_io[i].res = NULL; 152112791Ssos return 0; 153112791Ssos} 154112791Ssos 15573897Ssosstatic device_method_t ata_pccard_methods[] = { 15673897Ssos /* device interface */ 157144330Ssos DEVMETHOD(device_probe, pccard_compat_probe), 158144330Ssos DEVMETHOD(device_attach, pccard_compat_attach), 159144330Ssos DEVMETHOD(device_detach, ata_pccard_detach), 16089915Ssos 161144330Ssos /* card interface */ 162144330Ssos DEVMETHOD(card_compat_match, ata_pccard_match), 163144330Ssos DEVMETHOD(card_compat_probe, ata_pccard_probe), 164144330Ssos DEVMETHOD(card_compat_attach, ata_attach), 16573897Ssos { 0, 0 } 16673897Ssos}; 16773897Ssos 16873897Ssosstatic driver_t ata_pccard_driver = { 16973897Ssos "ata", 17073897Ssos ata_pccard_methods, 17190215Ssos sizeof(struct ata_channel), 17273897Ssos}; 17373897Ssos 17473897SsosDRIVER_MODULE(ata, pccard, ata_pccard_driver, ata_devclass, 0, 0); 175144330SsosMODULE_DEPEND(ata, ata, 1, 1, 1); 176