digi_pci.c revision 119418
176195Sbrian/*- 276195Sbrian * Copyright (c) 2001 Brian Somers <brian@Awfulhak.org> 376358Sbrian * based on work by Slawa Olhovchenkov 476358Sbrian * John Prince <johnp@knight-trosoft.com> 576358Sbrian * Eric Hernes 676195Sbrian * All rights reserved. 776195Sbrian * 876195Sbrian * Redistribution and use in source and binary forms, with or without 976195Sbrian * modification, are permitted provided that the following conditions 1076195Sbrian * are met: 1176195Sbrian * 1. Redistributions of source code must retain the above copyright 1276195Sbrian * notice, this list of conditions and the following disclaimer. 1376195Sbrian * 2. Redistributions in binary form must reproduce the above copyright 1476195Sbrian * notice, this list of conditions and the following disclaimer in the 1576195Sbrian * documentation and/or other materials provided with the distribution. 1676195Sbrian * 1776195Sbrian * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1876195Sbrian * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1976195Sbrian * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2076195Sbrian * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 2176195Sbrian * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2276195Sbrian * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2376195Sbrian * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2476195Sbrian * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2576195Sbrian * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2676195Sbrian * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2776195Sbrian * SUCH DAMAGE. 2876195Sbrian */ 2976195Sbrian 30119418Sobrien#include <sys/cdefs.h> 31119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/digi/digi_pci.c 119418 2003-08-24 17:55:58Z obrien $"); 32119418Sobrien 3376195Sbrian#include <sys/param.h> 3476195Sbrian 3576195Sbrian#include <sys/systm.h> 3676195Sbrian#include <sys/kernel.h> 3776195Sbrian#include <sys/tty.h> 3876195Sbrian#include <sys/bus.h> 3976195Sbrian#include <machine/bus.h> 4076195Sbrian#include <sys/rman.h> 4176195Sbrian#include <machine/resource.h> 4276195Sbrian#include <vm/vm.h> 4376195Sbrian#include <vm/pmap.h> 44119277Simp#include <dev/pci/pcivar.h> 4576195Sbrian 4676848Sbrian#include <sys/digiio.h> 4776853Sbrian#include <dev/digi/digireg.h> 4876853Sbrian#include <dev/digi/digi.h> 4976853Sbrian#include <dev/digi/digi_pci.h> 5076195Sbrian 5176195Sbrianstatic u_char * 5276195Sbriandigi_pci_setwin(struct digi_softc *sc, unsigned int addr) 5376195Sbrian{ 5476195Sbrian return (sc->vmem + addr); 5576195Sbrian} 5676195Sbrian 5776195Sbrianstatic void 5876195Sbriandigi_pci_hidewin(struct digi_softc *sc) 5976195Sbrian{ 6076195Sbrian return; 6176195Sbrian} 6276195Sbrian 6376195Sbrianstatic void 6476195Sbriandigi_pci_towin(struct digi_softc *sc, int win) 6576195Sbrian{ 6676195Sbrian return; 6776195Sbrian} 6876195Sbrian 6976195Sbrianstatic int 7076195Sbriandigi_pci_probe(device_t dev) 7176195Sbrian{ 7276195Sbrian unsigned int device_id = pci_get_devid(dev); 7376195Sbrian 7476195Sbrian if (device_get_unit(dev) >= 16) { 7576195Sbrian /* Don't overflow our control mask */ 7676195Sbrian device_printf(dev, "At most 16 digiboards may be used\n"); 7776195Sbrian return (ENXIO); 7876195Sbrian } 7976195Sbrian 8076195Sbrian if ((device_id & 0xffff) != PCI_VENDOR_DIGI) 8176195Sbrian return (ENXIO); 8276195Sbrian 8376195Sbrian switch (device_id >> 16) { 8476195Sbrian case PCI_DEVICE_EPC: 8576195Sbrian case PCI_DEVICE_XEM: 8676195Sbrian case PCI_DEVICE_XR: 8776195Sbrian case PCI_DEVICE_CX: 8876195Sbrian case PCI_DEVICE_XRJ: 8976195Sbrian case PCI_DEVICE_EPCJ: 9076195Sbrian case PCI_DEVICE_920_4: 9176195Sbrian case PCI_DEVICE_920_8: 9276195Sbrian case PCI_DEVICE_920_2: 9376358Sbrian return (0); 9476195Sbrian } 9576195Sbrian 9676358Sbrian return (ENXIO); 9776195Sbrian} 9876195Sbrian 9976195Sbrianstatic int 10076195Sbriandigi_pci_attach(device_t dev) 10176195Sbrian{ 10276195Sbrian struct digi_softc *sc; 10376195Sbrian u_int32_t device_id; 10476195Sbrian#ifdef DIGI_INTERRUPT 10576195Sbrian int retVal = 0; 10676195Sbrian#endif 10776195Sbrian 10876195Sbrian sc = device_get_softc(dev); 10976195Sbrian KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n", 11076195Sbrian device_get_unit(dev))); 11176195Sbrian 11276195Sbrian bzero(sc, sizeof(*sc)); 11376195Sbrian sc->dev = dev; 11476195Sbrian sc->res.unit = device_get_unit(dev); 11576195Sbrian 11676195Sbrian device_id = pci_get_devid(dev); 11776195Sbrian switch (device_id >> 16) { 11876195Sbrian case PCI_DEVICE_EPC: 11976195Sbrian sc->name = "Digiboard PCI EPC/X ASIC"; 12076195Sbrian sc->res.mrid = 0x10; 12176195Sbrian sc->model = PCIEPCX; 12276195Sbrian sc->module = "EPCX_PCI"; 12376195Sbrian break; 12476195Sbrian case PCI_DEVICE_XEM: 12576195Sbrian sc->name = "Digiboard PCI PC/Xem ASIC"; 12676195Sbrian sc->res.mrid = 0x10; 12776195Sbrian sc->model = PCXEM; 12876195Sbrian sc->module = "Xem"; 12976195Sbrian break; 13076195Sbrian case PCI_DEVICE_XR: 13176195Sbrian sc->name = "Digiboard PCI PC/Xr ASIC"; 13276195Sbrian sc->res.mrid = 0x10; 13376195Sbrian sc->model = PCIXR; 13476195Sbrian sc->module = "Xr"; 13576195Sbrian break; 13676195Sbrian case PCI_DEVICE_CX: 13776195Sbrian sc->name = "Digiboard PCI C/X ASIC"; 13876195Sbrian sc->res.mrid = 0x10; 13976195Sbrian sc->model = PCCX; 14076195Sbrian sc->module = "CX_PCI"; 14176195Sbrian break; 14276195Sbrian case PCI_DEVICE_XRJ: 14376195Sbrian sc->name = "Digiboard PCI PC/Xr PLX"; 14476195Sbrian sc->res.mrid = 0x18; 14576195Sbrian sc->model = PCIXR; 14676195Sbrian sc->module = "Xr"; 14776195Sbrian break; 14876195Sbrian case PCI_DEVICE_EPCJ: 14976195Sbrian sc->name = "Digiboard PCI EPC/X PLX"; 15076195Sbrian sc->res.mrid = 0x18; 15176195Sbrian sc->model = PCIEPCX; 15276195Sbrian sc->module = "EPCX_PCI"; 15376195Sbrian break; 15476195Sbrian case PCI_DEVICE_920_4: /* Digi PCI4r 920 */ 15576195Sbrian sc->name = "Digiboard PCI4r 920"; 15676195Sbrian sc->res.mrid = 0x10; 15776195Sbrian sc->model = PCIXR; 15876195Sbrian sc->module = "Xr"; 15976195Sbrian break; 16076195Sbrian case PCI_DEVICE_920_8: /* Digi PCI8r 920 */ 16176195Sbrian sc->name = "Digiboard PCI8r 920"; 16276195Sbrian sc->res.mrid = 0x10; 16376195Sbrian sc->model = PCIXR; 16476195Sbrian sc->module = "Xr"; 16576195Sbrian break; 16676195Sbrian case PCI_DEVICE_920_2: /* Digi PCI2r 920 */ 16776195Sbrian sc->name = "Digiboard PCI2r 920"; 16876195Sbrian sc->res.mrid = 0x10; 16976195Sbrian sc->model = PCIXR; 17076195Sbrian sc->module = "Xr"; 17176195Sbrian break; 17276195Sbrian default: 17376195Sbrian device_printf(dev, "Unknown device id = %08x\n", device_id); 17476195Sbrian return (ENXIO); 17576195Sbrian } 17676195Sbrian 17776195Sbrian pci_write_config(dev, 0x40, 0, 4); 17876195Sbrian pci_write_config(dev, 0x46, 0, 4); 17976195Sbrian 18076195Sbrian sc->res.mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->res.mrid, 18176195Sbrian 0, ~0, 1, RF_ACTIVE); 18276195Sbrian 18376195Sbrian#ifdef DIGI_INTERRUPT 18476195Sbrian sc->res.irqrid = 0; 18576195Sbrian sc->res.irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->res.irqrid, 18676195Sbrian 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 18776195Sbrian if (sc->res.irq == NULL) { 18876195Sbrian device_printf(dev, "couldn't map interrupt\n"); 18976358Sbrian return (ENXIO); 19076195Sbrian } 19176195Sbrian retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY, 19276195Sbrian digiintr, sc, &sc->res.irqHandler); 19376195Sbrian#else 19476195Sbrian DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n")); 19576195Sbrian#endif 19676195Sbrian 19776195Sbrian sc->vmem = rman_get_virtual(sc->res.mem); 19876195Sbrian sc->pmem = vtophys(sc->vmem); 19976195Sbrian sc->pcibus = 1; 20076195Sbrian sc->win_size = 0x200000; 20176195Sbrian sc->win_bits = 21; 20276195Sbrian sc->csigs = &digi_normal_signals; 20376195Sbrian sc->status = DIGI_STATUS_NOTINIT; 20476195Sbrian callout_handle_init(&sc->callout); 20576195Sbrian callout_handle_init(&sc->inttest); 20676195Sbrian sc->setwin = digi_pci_setwin; 20776195Sbrian sc->hidewin = digi_pci_hidewin; 20876195Sbrian sc->towin = digi_pci_towin; 20976195Sbrian 21076195Sbrian PCIPORT = FEPRST; 21176195Sbrian 21276195Sbrian return (digi_attach(sc)); 21376195Sbrian} 21476195Sbrian 21576195Sbrianstatic device_method_t digi_pci_methods[] = { 21676195Sbrian /* Device interface */ 21776195Sbrian DEVMETHOD(device_probe, digi_pci_probe), 21876195Sbrian DEVMETHOD(device_attach, digi_pci_attach), 21976195Sbrian DEVMETHOD(device_detach, digi_detach), 22076195Sbrian DEVMETHOD(device_shutdown, digi_shutdown), 22176195Sbrian {0, 0} 22276195Sbrian}; 22376195Sbrian 22476195Sbrianstatic driver_t digi_pci_drv = { 22576195Sbrian "digi", 22676195Sbrian digi_pci_methods, 22776195Sbrian sizeof(struct digi_softc), 22876195Sbrian}; 22991445SpeterDRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0); 230