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$"); 32119418Sobrien 3376195Sbrian#include <sys/param.h> 3476195Sbrian 3576195Sbrian#include <sys/systm.h> 3676195Sbrian#include <sys/kernel.h> 37129879Sphk#include <sys/module.h> 3876195Sbrian#include <sys/tty.h> 3976195Sbrian#include <sys/bus.h> 4076195Sbrian#include <machine/bus.h> 4176195Sbrian#include <sys/rman.h> 4276195Sbrian#include <machine/resource.h> 4376195Sbrian#include <vm/vm.h> 4476195Sbrian#include <vm/pmap.h> 45119277Simp#include <dev/pci/pcivar.h> 4676195Sbrian 4776848Sbrian#include <sys/digiio.h> 4876853Sbrian#include <dev/digi/digireg.h> 4976853Sbrian#include <dev/digi/digi.h> 5076853Sbrian#include <dev/digi/digi_pci.h> 5176195Sbrian 5276195Sbrianstatic u_char * 5376195Sbriandigi_pci_setwin(struct digi_softc *sc, unsigned int addr) 5476195Sbrian{ 5576195Sbrian return (sc->vmem + addr); 5676195Sbrian} 5776195Sbrian 5876195Sbrianstatic void 5976195Sbriandigi_pci_hidewin(struct digi_softc *sc) 6076195Sbrian{ 6176195Sbrian return; 6276195Sbrian} 6376195Sbrian 6476195Sbrianstatic void 6576195Sbriandigi_pci_towin(struct digi_softc *sc, int win) 6676195Sbrian{ 6776195Sbrian return; 6876195Sbrian} 6976195Sbrian 7076195Sbrianstatic int 7176195Sbriandigi_pci_probe(device_t dev) 7276195Sbrian{ 7376195Sbrian unsigned int device_id = pci_get_devid(dev); 7476195Sbrian 7576195Sbrian if (device_get_unit(dev) >= 16) { 7676195Sbrian /* Don't overflow our control mask */ 7776195Sbrian device_printf(dev, "At most 16 digiboards may be used\n"); 7876195Sbrian return (ENXIO); 7976195Sbrian } 8076195Sbrian 8176195Sbrian if ((device_id & 0xffff) != PCI_VENDOR_DIGI) 8276195Sbrian return (ENXIO); 8376195Sbrian 8476195Sbrian switch (device_id >> 16) { 8576195Sbrian case PCI_DEVICE_EPC: 8676195Sbrian case PCI_DEVICE_XEM: 8776195Sbrian case PCI_DEVICE_XR: 8876195Sbrian case PCI_DEVICE_CX: 8976195Sbrian case PCI_DEVICE_XRJ: 9076195Sbrian case PCI_DEVICE_EPCJ: 9176195Sbrian case PCI_DEVICE_920_4: 9276195Sbrian case PCI_DEVICE_920_8: 9376195Sbrian case PCI_DEVICE_920_2: 94143161Simp return (BUS_PROBE_DEFAULT); 9576195Sbrian } 9676195Sbrian 9776358Sbrian return (ENXIO); 9876195Sbrian} 9976195Sbrian 10076195Sbrianstatic int 10176195Sbriandigi_pci_attach(device_t dev) 10276195Sbrian{ 10376195Sbrian struct digi_softc *sc; 10476195Sbrian u_int32_t device_id; 10576195Sbrian#ifdef DIGI_INTERRUPT 10676195Sbrian int retVal = 0; 10776195Sbrian#endif 10876195Sbrian 10976195Sbrian sc = device_get_softc(dev); 11076195Sbrian KASSERT(sc, ("digi%d: softc not allocated in digi_pci_attach\n", 11176195Sbrian device_get_unit(dev))); 11276195Sbrian 11376195Sbrian bzero(sc, sizeof(*sc)); 11476195Sbrian sc->dev = dev; 11576195Sbrian sc->res.unit = device_get_unit(dev); 11676195Sbrian 11776195Sbrian device_id = pci_get_devid(dev); 11876195Sbrian switch (device_id >> 16) { 11976195Sbrian case PCI_DEVICE_EPC: 12076195Sbrian sc->name = "Digiboard PCI EPC/X ASIC"; 12176195Sbrian sc->res.mrid = 0x10; 12276195Sbrian sc->model = PCIEPCX; 12376195Sbrian sc->module = "EPCX_PCI"; 12476195Sbrian break; 12576195Sbrian case PCI_DEVICE_XEM: 12676195Sbrian sc->name = "Digiboard PCI PC/Xem ASIC"; 12776195Sbrian sc->res.mrid = 0x10; 12876195Sbrian sc->model = PCXEM; 12976195Sbrian sc->module = "Xem"; 13076195Sbrian break; 13176195Sbrian case PCI_DEVICE_XR: 13276195Sbrian sc->name = "Digiboard PCI PC/Xr ASIC"; 13376195Sbrian sc->res.mrid = 0x10; 13476195Sbrian sc->model = PCIXR; 13576195Sbrian sc->module = "Xr"; 13676195Sbrian break; 13776195Sbrian case PCI_DEVICE_CX: 13876195Sbrian sc->name = "Digiboard PCI C/X ASIC"; 13976195Sbrian sc->res.mrid = 0x10; 14076195Sbrian sc->model = PCCX; 14176195Sbrian sc->module = "CX_PCI"; 14276195Sbrian break; 14376195Sbrian case PCI_DEVICE_XRJ: 14476195Sbrian sc->name = "Digiboard PCI PC/Xr PLX"; 14576195Sbrian sc->res.mrid = 0x18; 14676195Sbrian sc->model = PCIXR; 14776195Sbrian sc->module = "Xr"; 14876195Sbrian break; 14976195Sbrian case PCI_DEVICE_EPCJ: 15076195Sbrian sc->name = "Digiboard PCI EPC/X PLX"; 15176195Sbrian sc->res.mrid = 0x18; 15276195Sbrian sc->model = PCIEPCX; 15376195Sbrian sc->module = "EPCX_PCI"; 15476195Sbrian break; 15576195Sbrian case PCI_DEVICE_920_4: /* Digi PCI4r 920 */ 15676195Sbrian sc->name = "Digiboard PCI4r 920"; 15776195Sbrian sc->res.mrid = 0x10; 15876195Sbrian sc->model = PCIXR; 15976195Sbrian sc->module = "Xr"; 16076195Sbrian break; 16176195Sbrian case PCI_DEVICE_920_8: /* Digi PCI8r 920 */ 16276195Sbrian sc->name = "Digiboard PCI8r 920"; 16376195Sbrian sc->res.mrid = 0x10; 16476195Sbrian sc->model = PCIXR; 16576195Sbrian sc->module = "Xr"; 16676195Sbrian break; 16776195Sbrian case PCI_DEVICE_920_2: /* Digi PCI2r 920 */ 16876195Sbrian sc->name = "Digiboard PCI2r 920"; 16976195Sbrian sc->res.mrid = 0x10; 17076195Sbrian sc->model = PCIXR; 17176195Sbrian sc->module = "Xr"; 17276195Sbrian break; 17376195Sbrian default: 17476195Sbrian device_printf(dev, "Unknown device id = %08x\n", device_id); 17576195Sbrian return (ENXIO); 17676195Sbrian } 17776195Sbrian 17876195Sbrian pci_write_config(dev, 0x40, 0, 4); 17976195Sbrian pci_write_config(dev, 0x46, 0, 4); 18076195Sbrian 181127135Snjl sc->res.mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->res.mrid, 182127135Snjl RF_ACTIVE); 18376195Sbrian 18476195Sbrian#ifdef DIGI_INTERRUPT 18576195Sbrian sc->res.irqrid = 0; 186127135Snjl sc->res.irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->res.irqrid, 187127135Snjl RF_SHAREABLE | RF_ACTIVE); 18876195Sbrian if (sc->res.irq == NULL) { 18976195Sbrian device_printf(dev, "couldn't map interrupt\n"); 19076358Sbrian return (ENXIO); 19176195Sbrian } 19276195Sbrian retVal = bus_setup_intr(dev, sc->res.irq, INTR_TYPE_TTY, 19376195Sbrian digiintr, sc, &sc->res.irqHandler); 19476195Sbrian#else 19576195Sbrian DLOG(DIGIDB_IRQ, (sc->dev, "Interrupt support compiled out\n")); 19676195Sbrian#endif 19776195Sbrian 19876195Sbrian sc->vmem = rman_get_virtual(sc->res.mem); 19976195Sbrian sc->pmem = vtophys(sc->vmem); 20076195Sbrian sc->pcibus = 1; 20176195Sbrian sc->win_size = 0x200000; 20276195Sbrian sc->win_bits = 21; 20376195Sbrian sc->csigs = &digi_normal_signals; 20476195Sbrian sc->status = DIGI_STATUS_NOTINIT; 20576195Sbrian callout_handle_init(&sc->callout); 20676195Sbrian callout_handle_init(&sc->inttest); 20776195Sbrian sc->setwin = digi_pci_setwin; 20876195Sbrian sc->hidewin = digi_pci_hidewin; 20976195Sbrian sc->towin = digi_pci_towin; 21076195Sbrian 21176195Sbrian PCIPORT = FEPRST; 21276195Sbrian 21376195Sbrian return (digi_attach(sc)); 21476195Sbrian} 21576195Sbrian 21676195Sbrianstatic device_method_t digi_pci_methods[] = { 21776195Sbrian /* Device interface */ 21876195Sbrian DEVMETHOD(device_probe, digi_pci_probe), 21976195Sbrian DEVMETHOD(device_attach, digi_pci_attach), 22076195Sbrian DEVMETHOD(device_detach, digi_detach), 22176195Sbrian DEVMETHOD(device_shutdown, digi_shutdown), 222246128Ssbz 223246128Ssbz DEVMETHOD_END 22476195Sbrian}; 22576195Sbrian 22676195Sbrianstatic driver_t digi_pci_drv = { 22776195Sbrian "digi", 22876195Sbrian digi_pci_methods, 22976195Sbrian sizeof(struct digi_softc), 23076195Sbrian}; 23191445SpeterDRIVER_MODULE(digi, pci, digi_pci_drv, digi_devclass, 0, 0); 232