pcii.c revision 141398
119370Spst/*- 298944Sobrien * Copyright (c) 2005 Poul-Henning Kamp <phk@FreeBSD.org> 3130803Smarcel * All rights reserved. 446283Sdfr * 519370Spst * Redistribution and use in source and binary forms, with or without 698944Sobrien * modification, are permitted provided that the following conditions 719370Spst * are met: 898944Sobrien * 1. Redistributions of source code must retain the above copyright 998944Sobrien * notice, this list of conditions and the following disclaimer. 1098944Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1198944Sobrien * notice, this list of conditions and the following disclaimer in the 1219370Spst * documentation and/or other materials provided with the distribution. 1398944Sobrien * 1498944Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1598944Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1698944Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719370Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1898944Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1998944Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2098944Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2198944Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2419370Spst * SUCH DAMAGE. 2519370Spst * 2619370Spst * Driver for GPIB cards based on NEC �PD7210 and compatibles. 2719370Spst * 2819370Spst * This driver just hooks up to the hardware and leaves all the interesting 2919370Spst * stuff to upd7210.c. 3019370Spst * 3119370Spst * Supported hardware: 3219370Spst * PCIIA compatible cards. 3398944Sobrien * 3419370Spst * Tested and known working: 3519370Spst * "B&C Microsystems PC488A-0" 3619370Spst * 3746283Sdfr */ 3846283Sdfr 3998944Sobrien#include <sys/cdefs.h> 4098944Sobrien__FBSDID("$FreeBSD: head/sys/dev/ieee488/pcii.c 141398 2005-02-06 15:22:23Z phk $"); 4198944Sobrien 4298944Sobrien#include <sys/param.h> 43130803Smarcel#include <sys/systm.h> 44130803Smarcel#include <sys/lock.h> 45130803Smarcel#include <sys/mutex.h> 46130803Smarcel#include <sys/kernel.h> 47130803Smarcel#include <sys/module.h> 4819370Spst#include <sys/bus.h> 49130803Smarcel#include <machine/bus.h> 5019370Spst#include <machine/resource.h> 5198944Sobrien#include <sys/rman.h> 5246283Sdfr#include <isa/isavar.h> 5398944Sobrien 5446283Sdfr#include <dev/ieee488/upd7210.h> 55130803Smarcel 5646283Sdfrstruct pcii_softc { 57130803Smarcel int foo; 58130803Smarcel struct resource *port[8]; 5998944Sobrien struct resource *irq; 6046283Sdfr struct resource *dma; 61130803Smarcel void *intr_handler; 62130803Smarcel struct upd7210 upd7210; 63130803Smarcel}; 64130803Smarcel 65130803Smarcelstatic devclass_t pcii_devclass; 66130803Smarcel 6798944Sobrienstatic int pcii_probe(device_t dev); 6819370Spststatic int pcii_attach(device_t dev); 6998944Sobrien 7019370Spststatic device_method_t pcii_methods[] = { 7198944Sobrien DEVMETHOD(device_probe, pcii_probe), 7219370Spst DEVMETHOD(device_attach, pcii_attach), 7398944Sobrien DEVMETHOD(device_suspend, bus_generic_suspend), 7419370Spst DEVMETHOD(device_resume, bus_generic_resume), 7598944Sobrien 7619370Spst { 0, 0 } 7798944Sobrien}; 7819370Spst 7998944Sobrienstatic driver_t pcii_driver = { 8019370Spst "pcii", 8198944Sobrien pcii_methods, 8219370Spst sizeof(struct pcii_softc *), 8398944Sobrien}; 8419370Spst 85130803Smarcelstatic int 8619370Spstpcii_probe(device_t dev) 8798944Sobrien{ 8819370Spst struct resource *port; 8998944Sobrien int rid; 9019370Spst u_long start, count; 9198944Sobrien int i, j, error = 0; 9219370Spst 9398944Sobrien device_set_desc(dev, "PCII IEEE-4888 controller"); 9419370Spst 9598944Sobrien rid = 0; 9619370Spst if (bus_get_resource(dev, SYS_RES_IOPORT, rid, &start, &count) != 0) 9798944Sobrien return ENXIO; 9819370Spst if ((start & 0x3ff) != 0x2e1) 9998944Sobrien return (ENXIO); 10019370Spst count = 1; 10198944Sobrien if (bus_set_resource(dev, SYS_RES_IOPORT, rid, start, count) != 0) 10298944Sobrien return ENXIO; 10398944Sobrien for (i = 0; i < 8; i++) { 10419370Spst j = bus_set_resource(dev, SYS_RES_IOPORT, i, 10598944Sobrien start + 0x400 * i, 1); 10619370Spst if (j) { 10798944Sobrien error = ENXIO; 10846283Sdfr break; 10998944Sobrien } 11098944Sobrien rid = i; 11198944Sobrien port = bus_alloc_resource_any(dev, SYS_RES_IOPORT, 11298944Sobrien &rid, RF_ACTIVE); 11398944Sobrien if (port == NULL) 11498944Sobrien return (ENXIO); 11598944Sobrien else 11698944Sobrien bus_release_resource(dev, SYS_RES_IOPORT, i, port); 11798944Sobrien } 11898944Sobrien 11946283Sdfr rid = 0; 12046283Sdfr port = bus_alloc_resource_any(dev, 12119370Spst SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 12219370Spst if (port == NULL) 12319370Spst return (ENXIO); 12419370Spst bus_release_resource(dev, SYS_RES_IRQ, rid, port); 12519370Spst 12619370Spst return (error); 12719370Spst} 12819370Spst 12998944Sobrienstatic int 13098944Sobrienpcii_attach(device_t dev) 13198944Sobrien{ 13298944Sobrien struct pcii_softc *sc; 13398944Sobrien int unit; 13498944Sobrien int rid; 13519370Spst int i, error = 0; 13619370Spst 13719370Spst unit = device_get_unit(dev); 13819370Spst sc = device_get_softc(dev); 13919370Spst memset(sc, 0, sizeof *sc); 14019370Spst 14119370Spst device_set_desc(dev, "PCII IEEE-4888 controller"); 14219370Spst 14319370Spst for (rid = 0; rid < 8; rid++) { 14498944Sobrien sc->port[rid] = bus_alloc_resource_any(dev, 14519370Spst SYS_RES_IOPORT, &rid, RF_ACTIVE); 14619370Spst if (sc->port[rid] == NULL) { 14719370Spst error = ENXIO; 14819370Spst break; 14919370Spst } 15019370Spst sc->upd7210.reg_tag[rid] = rman_get_bustag(sc->port[rid]); 15119370Spst sc->upd7210.reg_handle[rid] = rman_get_bushandle(sc->port[rid]); 15219370Spst } 15319370Spst if (!error) { 15419370Spst rid = 0; 15519370Spst sc->irq = bus_alloc_resource_any(dev, 15619370Spst SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); 15719370Spst if (sc->irq == NULL) { 15819370Spst error = ENXIO; 15919370Spst } else { 16019370Spst error = bus_setup_intr(dev, sc->irq, 16119370Spst INTR_TYPE_MISC | INTR_MPSAFE, 16219370Spst upd7210intr, &sc->upd7210, &sc->intr_handler); 16319370Spst } 16419370Spst } 16519370Spst if (!error) { 16619370Spst rid = 0; 16719370Spst sc->dma = bus_alloc_resource_any(dev, 16819370Spst SYS_RES_DRQ, &rid, RF_ACTIVE | RF_SHAREABLE); 16919370Spst if (sc->dma == NULL) 17019370Spst sc->upd7210.dmachan = -1; 17119370Spst else 17219370Spst sc->upd7210.dmachan = rman_get_start(sc->dma); 17319370Spst } 17419370Spst if (error) { 17519370Spst for (i = 0; i < 8; i++) { 17619370Spst if (sc->port[i] == NULL) 17719370Spst break; 17819370Spst bus_release_resource(dev, SYS_RES_IOPORT, 17919370Spst 0, sc->port[i]); 18098944Sobrien } 18198944Sobrien if (sc->intr_handler != NULL) 18219370Spst bus_teardown_intr(dev, sc->irq, sc->intr_handler); 18319370Spst if (sc->irq != NULL) 18419370Spst bus_release_resource(dev, SYS_RES_IRQ, i, sc->irq); 18519370Spst } 18619370Spst upd7210attach(&sc->upd7210); 187130803Smarcel return (error); 18819370Spst} 18919370Spst 19019370SpstDRIVER_MODULE(pcii, isa, pcii_driver, pcii_devclass, 0, 0); 19119370SpstDRIVER_MODULE(pcii, acpi, pcii_driver, pcii_devclass, 0, 0); 19219370Spst