159078Smdodd/*- 259078Smdodd * Copyright (c) 2000 Matthew N. Dodd <winter@jurai.net> 359078Smdodd * All rights reserved. 459078Smdodd * 559078Smdodd * Redistribution and use in source and binary forms, with or without 659078Smdodd * modification, are permitted provided that the following conditions 759078Smdodd * are met: 859078Smdodd * 1. Redistributions of source code must retain the above copyright 959078Smdodd * notice, this list of conditions and the following disclaimer. 1059078Smdodd * 2. Redistributions in binary form must reproduce the above copyright 1159078Smdodd * notice, this list of conditions and the following disclaimer in the 1259078Smdodd * documentation and/or other materials provided with the distribution. 1359078Smdodd * 1459078Smdodd * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1559078Smdodd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1659078Smdodd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1759078Smdodd * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1859078Smdodd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1959078Smdodd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2059078Smdodd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2159078Smdodd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2259078Smdodd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2359078Smdodd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2459078Smdodd * SUCH DAMAGE. 2559078Smdodd * 2659078Smdodd */ 2759078Smdodd 28119418Sobrien#include <sys/cdefs.h> 29119418Sobrien__FBSDID("$FreeBSD$"); 30119418Sobrien 3159078Smdodd#include <sys/param.h> 3259078Smdodd#include <sys/systm.h> 3359078Smdodd#include <sys/kernel.h> 34241593Sjhb#include <sys/lock.h> 3559078Smdodd#include <sys/module.h> 36241593Sjhb#include <sys/mutex.h> 3759078Smdodd#include <sys/bus.h> 3859078Smdodd 3959078Smdodd#include <machine/bus.h> 4059078Smdodd#include <machine/resource.h> 4159078Smdodd#include <sys/rman.h> 4259078Smdodd 4359078Smdodd#include <isa/isavar.h> 4459078Smdodd 4559078Smdodd#include <cam/scsi/scsi_all.h> 4659078Smdodd 4759078Smdodd#include <dev/dpt/dpt.h> 4859078Smdodd 49112795Smdodd#ifdef notyet 50112780Smdoddstatic void dpt_isa_identify (driver_t *, device_t); 51112795Smdodd#endif 5259078Smdoddstatic int dpt_isa_probe (device_t); 5359078Smdoddstatic int dpt_isa_attach (device_t); 54112780Smdoddstatic int dpt_isa_detach (device_t); 5559078Smdodd 56112780Smdoddstatic int dpt_isa_valid_irq (int); 57112780Smdoddstatic int dpt_isa_valid_ioport (int); 58112780Smdodd 5959078Smdoddstatic int 60112780Smdodddpt_isa_valid_irq (int irq) 61112780Smdodd{ 62112780Smdodd switch (irq) { 63112780Smdodd case 11: 64112780Smdodd case 12: 65112780Smdodd case 14: 66112780Smdodd case 15: 67112780Smdodd return (0); 68112780Smdodd default: 69112780Smdodd return (1); 70112780Smdodd }; 71112780Smdodd return (1); 72112780Smdodd} 73112780Smdodd 74112780Smdoddstatic int 75112780Smdodddpt_isa_valid_ioport (int ioport) 76112780Smdodd{ 77112780Smdodd switch (ioport) { 78112780Smdodd case 0x170: 79112780Smdodd case 0x1f0: 80112780Smdodd case 0x230: 81112780Smdodd case 0x330: 82112780Smdodd return (0); 83112780Smdodd default: 84112780Smdodd return (1); 85112780Smdodd }; 86112780Smdodd return (1); 87112780Smdodd} 88112780Smdodd 89112795Smdodd#ifdef notyet 90112780Smdoddstatic void 91112780Smdodddpt_isa_identify (driver_t *driver, device_t parent) 92112780Smdodd{ 93112780Smdodd device_t child; 94112780Smdodd dpt_conf_t * conf; 95112780Smdodd int isa_bases[] = { 0x1f0, 0x170, 0x330, 0x230, 0 }; 96112780Smdodd int i; 97112780Smdodd 98112780Smdodd for (i = 0; isa_bases[i]; i++) { 99112780Smdodd conf = dpt_pio_get_conf(isa_bases[i]); 100112780Smdodd if (!conf) { 101112780Smdodd if (bootverbose) 102112780Smdodd device_printf(parent, "dpt: dpt_pio_get_conf(%x) failed.\n", 103112780Smdodd isa_bases[i]); 104112780Smdodd continue; 105112780Smdodd } 106112780Smdodd 107112780Smdodd child = BUS_ADD_CHILD(parent, ISA_ORDER_SPECULATIVE, "dpt", -1); 108112780Smdodd if (child == 0) { 109112780Smdodd device_printf(parent, "dpt: BUS_ADD_CHILD() failed!\n"); 110112780Smdodd continue; 111112780Smdodd } 112112780Smdodd device_set_driver(child, driver); 113112780Smdodd bus_set_resource(child, SYS_RES_IOPORT, 0, isa_bases[i], 0x9); 114112780Smdodd } 115112780Smdodd return; 116112780Smdodd} 117112795Smdodd#endif 118112780Smdodd 119112780Smdoddstatic int 12059078Smdodddpt_isa_probe (device_t dev) 12159078Smdodd{ 12259078Smdodd dpt_conf_t * conf; 12359078Smdodd u_int32_t io_base; 12459078Smdodd 12559078Smdodd /* No pnp support */ 12659078Smdodd if (isa_get_vendorid(dev)) 12759078Smdodd return (ENXIO); 12859078Smdodd 12959078Smdodd if ((io_base = bus_get_resource_start(dev, SYS_RES_IOPORT, 0)) == 0) 13059078Smdodd return (ENXIO); 13159078Smdodd 132112780Smdodd if (dpt_isa_valid_ioport(io_base)) 133112780Smdodd ; 134112780Smdodd 13559078Smdodd conf = dpt_pio_get_conf(io_base); 136112780Smdodd if (!conf) { 137112780Smdodd printf("dpt: dpt_pio_get_conf() failed.\n"); 138112780Smdodd return (ENXIO); 139112780Smdodd } 14059078Smdodd 141112780Smdodd if (dpt_isa_valid_irq(conf->IRQ)) 142112780Smdodd ; 143112780Smdodd 14459078Smdodd device_set_desc(dev, "ISA DPT SCSI controller"); 14559078Smdodd bus_set_resource(dev, SYS_RES_IRQ, 0, conf->IRQ, 1); 14659078Smdodd bus_set_resource(dev, SYS_RES_DRQ, 0, ((8 - conf->DMA_channel) & 7), 1); 14759078Smdodd 14859078Smdodd return 0; 14959078Smdodd} 15059078Smdodd 15159078Smdoddstatic int 15259078Smdodddpt_isa_attach (device_t dev) 15359078Smdodd{ 154112780Smdodd dpt_softc_t * dpt; 15559078Smdodd int error = 0; 15659078Smdodd 157112780Smdodd dpt = device_get_softc(dev); 158170872Sscottl dpt->dev = dev; 159241593Sjhb dpt_alloc(dev); 16059078Smdodd 161112780Smdodd dpt->io_rid = 0; 162112780Smdodd dpt->io_type = SYS_RES_IOPORT; 163112780Smdodd dpt->irq_rid = 0; 164112780Smdodd 165112780Smdodd error = dpt_alloc_resources(dev); 166112780Smdodd if (error) { 16759078Smdodd goto bad; 16859078Smdodd } 16959078Smdodd 170112780Smdodd dpt->drq_rid = 0; 171127135Snjl dpt->drq_res = bus_alloc_resource_any(dev, SYS_RES_DRQ, &dpt->drq_rid, 172127135Snjl RF_ACTIVE); 173112780Smdodd if (!dpt->drq_res) { 174112780Smdodd device_printf(dev, "No DRQ!\n"); 17559078Smdodd error = ENOMEM; 17659078Smdodd goto bad; 17759078Smdodd } 178112780Smdodd isa_dma_acquire(rman_get_start(dpt->drq_res)); 179112780Smdodd isa_dmacascade(rman_get_start(dpt->drq_res)); 18059078Smdodd 18159078Smdodd /* Allocate a dmatag representing the capabilities of this attachment */ 182241593Sjhb if (bus_dma_tag_create( /* parent */ bus_get_dma_tag(dev), 18359078Smdodd /* alignemnt */ 1, 18459078Smdodd /* boundary */ 0, 185112780Smdodd /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 18659078Smdodd /* highaddr */ BUS_SPACE_MAXADDR, 18759078Smdodd /* filter */ NULL, 18859078Smdodd /* filterarg */ NULL, 18959078Smdodd /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 190104710Speter /* nsegments */ ~0, 19159078Smdodd /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 19259078Smdodd /* flags */ 0, 193241593Sjhb /* lockfunc */ NULL, 194241593Sjhb /* lockarg */ NULL, 19559078Smdodd &dpt->parent_dmat) != 0) { 19659078Smdodd error = ENXIO; 19759078Smdodd goto bad; 19859078Smdodd } 19959078Smdodd 20059078Smdodd if (dpt_init(dpt) != 0) { 20159078Smdodd error = ENXIO; 20259078Smdodd goto bad; 20359078Smdodd } 20459078Smdodd 20559078Smdodd /* Register with the XPT */ 20659078Smdodd dpt_attach(dpt); 20759078Smdodd 208241593Sjhb if (bus_setup_intr(dev, dpt->irq_res, INTR_TYPE_CAM | INTR_ENTROPY | 209241593Sjhb INTR_MPSAFE, NULL, dpt_intr, dpt, &dpt->ih)) { 21059078Smdodd device_printf(dev, "Unable to register interrupt handler\n"); 21159078Smdodd error = ENXIO; 21259078Smdodd goto bad; 21359078Smdodd } 21459078Smdodd 21559078Smdodd return (error); 21659078Smdodd 21759078Smdodd bad: 218112780Smdodd if (dpt->drq_res) { 219112780Smdodd isa_dma_release(rman_get_start(dpt->drq_res)); 220112780Smdodd } 221112780Smdodd 222112780Smdodd dpt_release_resources(dev); 223112780Smdodd 22459078Smdodd if (dpt) 22559078Smdodd dpt_free(dpt); 22659078Smdodd 22759078Smdodd return (error); 22859078Smdodd} 22959078Smdodd 230112780Smdoddstatic int 231112780Smdodddpt_isa_detach (device_t dev) 232112780Smdodd{ 233112780Smdodd dpt_softc_t * dpt; 234112780Smdodd int dma; 235112780Smdodd int error; 236112780Smdodd 237112780Smdodd dpt = device_get_softc(dev); 238112780Smdodd 239112780Smdodd dma = rman_get_start(dpt->drq_res); 240112780Smdodd error = dpt_detach(dev); 241112780Smdodd isa_dma_release(dma); 242112780Smdodd 243112780Smdodd return (error); 244112780Smdodd} 245112780Smdodd 246112780Smdodd 24759078Smdoddstatic device_method_t dpt_isa_methods[] = { 24859078Smdodd /* Device interface */ 249112780Smdodd#ifdef notyet 250112780Smdodd DEVMETHOD(device_identify, dpt_isa_identify), 251112780Smdodd#endif 25259078Smdodd DEVMETHOD(device_probe, dpt_isa_probe), 25359078Smdodd DEVMETHOD(device_attach, dpt_isa_attach), 254112780Smdodd DEVMETHOD(device_detach, dpt_isa_detach), 25559078Smdodd 25659078Smdodd { 0, 0 } 25759078Smdodd}; 25859078Smdodd 25959078Smdoddstatic driver_t dpt_isa_driver = { 26059078Smdodd "dpt", 26159078Smdodd dpt_isa_methods, 26259078Smdodd sizeof(dpt_softc_t), 26359078Smdodd}; 26459078Smdodd 26559078SmdoddDRIVER_MODULE(dpt, isa, dpt_isa_driver, dpt_devclass, 0, 0); 266165102SmjacobMODULE_DEPEND(dpt, isa, 1, 1, 1); 267165102SmjacobMODULE_DEPEND(dpt, cam, 1, 1, 1); 268