pcii.c revision 150525
1234353Sdim/*- 2203954Srdivacky * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3203954Srdivacky * All rights reserved. 4203954Srdivacky * 5203954Srdivacky * Redistribution and use in source and binary forms, with or without 6203954Srdivacky * modification, are permitted provided that the following conditions 7234353Sdim * are met: 8203954Srdivacky * 1. Redistributions of source code must retain the above copyright 9203954Srdivacky * notice, this list of conditions and the following disclaimer. 10203954Srdivacky * 2. Redistributions in binary form must reproduce the above copyright 11203954Srdivacky * notice, this list of conditions and the following disclaimer in the 12203954Srdivacky * documentation and/or other materials provided with the distribution. 13203954Srdivacky * 14203954Srdivacky * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15203954Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16203954Srdivacky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17203954Srdivacky * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18218893Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19218893Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20203954Srdivacky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21203954Srdivacky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22210299Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23210299Sed * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24210299Sed * SUCH DAMAGE. 25210299Sed * 26210299Sed * Driver for GPIB cards based on NEC �PD7210 and compatibles. 27210299Sed * 28210299Sed * This driver just hooks up to the hardware and leaves all the interesting 29210299Sed * stuff to upd7210.c. 30210299Sed * 31210299Sed * Supported hardware: 32210299Sed * PCIIA compatible cards. 33210299Sed * 34210299Sed * Tested and known working: 35210299Sed * "B&C Microsystems PC488A-0" 36210299Sed * 37210299Sed */ 38210299Sed 39210299Sed#include <sys/cdefs.h> 40210299Sed__FBSDID("$FreeBSD: head/sys/dev/ieee488/pcii.c 150525 2005-09-24 20:44:55Z phk $"); 41223017Sdim 42226633Sdim#include <sys/param.h> 43226633Sdim#include <sys/systm.h> 44234353Sdim#include <sys/lock.h> 45234353Sdim#include <sys/mutex.h> 46210299Sed#include <sys/kernel.h> 47210299Sed#include <sys/module.h> 48223017Sdim#include <sys/bus.h> 49223017Sdim#include <machine/bus.h> 50210299Sed#include <machine/resource.h> 51234353Sdim#include <sys/rman.h> 52210299Sed#include <isa/isavar.h> 53224145Sdim 54224145Sdim#define UPD7210_HW_DRIVER 55218893Sdim#include <dev/ieee488/upd7210.h> 56234353Sdim 57234353Sdimstruct pcii_softc { 58218893Sdim int foo; 59210299Sed struct resource *res[2]; 60210299Sed struct resource *dma; 61210299Sed void *intr_handler; 62210299Sed struct upd7210 upd7210; 63210299Sed}; 64210299Sed 65210299Sedstatic devclass_t pcii_devclass; 66210299Sed 67210299Sedstatic int pcii_probe(device_t dev); 68210299Sedstatic int pcii_attach(device_t dev); 69210299Sed 70210299Sedstatic device_method_t pcii_methods[] = { 71210299Sed DEVMETHOD(device_probe, pcii_probe), 72210299Sed DEVMETHOD(device_attach, pcii_attach), 73210299Sed DEVMETHOD(device_suspend, bus_generic_suspend), 74234353Sdim DEVMETHOD(device_resume, bus_generic_resume), 75234353Sdim 76234353Sdim { 0, 0 } 77210299Sed}; 78218893Sdim 79234353Sdimstatic struct resource_spec pcii_res_spec[] = { 80234353Sdim { SYS_RES_IRQ, 0, RF_ACTIVE | RF_SHAREABLE}, 81234353Sdim { SYS_RES_DRQ, 0, RF_ACTIVE | RF_SHAREABLE | RF_OPTIONAL}, 82234353Sdim { SYS_RES_IOPORT, 0, RF_ACTIVE}, 83234353Sdim { -1, 0, 0 } 84210299Sed}; 85234353Sdim 86234353Sdimstatic driver_t pcii_driver = { 87234353Sdim "pcii", 88234353Sdim pcii_methods, 89234353Sdim sizeof(struct pcii_softc), 90234353Sdim}; 91234353Sdim 92234353Sdimstatic int 93234353Sdimpcii_probe(device_t dev) 94234353Sdim{ 95234353Sdim int rid, i, j; 96234353Sdim u_long start, count; 97234353Sdim int error = 0; 98234353Sdim struct pcii_softc *sc; 99210299Sed 100212904Sdim device_set_desc(dev, "PCII IEEE-4888 controller"); 101212904Sdim sc = device_get_softc(dev); 102210299Sed 103212904Sdim rid = 0; 104210299Sed if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0) 105234353Sdim return ENXIO; 106234353Sdim if ((start & 0x3ff) != 0x2e1) 107234353Sdim return (ENXIO); 108234353Sdim count = 1; 109234353Sdim if (bus_set_resource(dev, SYS_RES_IOPORT, rid, start, count) != 0) 110234353Sdim return ENXIO; 111234353Sdim error = bus_alloc_resources(dev, pcii_res_spec, sc->res); 112234353Sdim if (error) 113234353Sdim return (error); 114234353Sdim error = ENXIO; 115234353Sdim for (i = 0; i < 8; i++) { 116212904Sdim j = bus_read_1(sc->res[2], i * 0x400); 117212904Sdim if (j != 0x00 && j != 0xff) 118212904Sdim error = 0; 119212904Sdim } 120212904Sdim if (!error) { 121212904Sdim bus_write_1(sc->res[2], 3 * 0x400, 0x55); 122212904Sdim if (bus_read_1(sc->res[2], 3 * 0x400) != 0x55) 123212904Sdim error = ENXIO; 124212904Sdim } 125212904Sdim if (!error) { 126212904Sdim bus_write_1(sc->res[2], 3 * 0x400, 0xaa); 127212904Sdim if (bus_read_1(sc->res[2], 3 * 0x400) != 0xaa) 128226633Sdim error = ENXIO; 129234353Sdim } 130234353Sdim bus_release_resources(dev, pcii_res_spec, sc->res); 131226633Sdim return (error); 132212904Sdim} 133212904Sdim 134212904Sdimstatic int 135212904Sdimpcii_attach(device_t dev) 136212904Sdim{ 137212904Sdim struct pcii_softc *sc; 138234353Sdim int unit; 139212904Sdim int rid; 140212904Sdim int error = 0; 141212904Sdim 142212904Sdim unit = device_get_unit(dev); 143212904Sdim sc = device_get_softc(dev); 144212904Sdim memset(sc, 0, sizeof *sc); 145212904Sdim 146212904Sdim device_set_desc(dev, "PCII IEEE-4888 controller"); 147212904Sdim 148212904Sdim error = bus_alloc_resources(dev, pcii_res_spec, sc->res); 149212904Sdim if (error) 150212904Sdim return (error); 151212904Sdim 152212904Sdim error = bus_setup_intr(dev, sc->res[0], 153212904Sdim INTR_TYPE_MISC | INTR_MPSAFE, 154234353Sdim upd7210intr, &sc->upd7210, &sc->intr_handler); 155234353Sdim if (error) { 156212904Sdim bus_release_resources(dev, pcii_res_spec, sc->res); 157234353Sdim return (error); 158226633Sdim } 159234353Sdim 160212904Sdim for (rid = 0; rid < 8; rid++) { 161234353Sdim sc->upd7210.reg_res[rid] = sc->res[2]; 162212904Sdim sc->upd7210.reg_offset[rid] = 0x400 * rid; 163234353Sdim } 164234353Sdim 165234353Sdim if (sc->res[1] == NULL) 166226633Sdim sc->upd7210.dmachan = -1; 167210299Sed else 168210299Sed sc->upd7210.dmachan = rman_get_start(sc->res[1]); 169210299Sed 170210299Sed upd7210attach(&sc->upd7210); 171210299Sed return (error); 172210299Sed} 173210299Sed 174210299SedDRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0); 175218893SdimDRIVER_MODULE(pcii, acpi, pcii_driver, pcii_devclass, 0, 0); 176218893Sdim