bt_isa.c revision 40160
139223Sgibbs/* 239223Sgibbs * Product specific probe and attach routines for: 339223Sgibbs * Buslogic BT-54X and BT-445 cards 439223Sgibbs * 539223Sgibbs * Copyright (c) 1998 Justin T. Gibbs 639223Sgibbs * All rights reserved. 739223Sgibbs * 839223Sgibbs * Redistribution and use in source and binary forms, with or without 939223Sgibbs * modification, are permitted provided that the following conditions 1039223Sgibbs * are met: 1139223Sgibbs * 1. Redistributions of source code must retain the above copyright 1239223Sgibbs * notice, this list of conditions, and the following disclaimer, 1339223Sgibbs * without modification, immediately at the beginning of the file. 1439223Sgibbs * 2. The name of the author may not be used to endorse or promote products 1539223Sgibbs * derived from this software without specific prior written permission. 1639223Sgibbs * 1739223Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1839223Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1939223Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2039223Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2139223Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2239223Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2339223Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2439223Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2539223Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2639223Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2739223Sgibbs * SUCH DAMAGE. 2839223Sgibbs * 2940160Simp * $Id: bt_isa.c,v 1.2 1998/09/24 10:43:42 bde Exp $ 3039223Sgibbs */ 3139223Sgibbs 3239223Sgibbs#include <sys/param.h> 3339223Sgibbs#include <sys/systm.h> 3439223Sgibbs 3539223Sgibbs#include <machine/bus_pio.h> 3639223Sgibbs#include <machine/bus.h> 3739223Sgibbs 3839223Sgibbs#include <i386/isa/isa_device.h> 3939223Sgibbs#include <dev/buslogic/btreg.h> 4039223Sgibbs 4139223Sgibbs#include <cam/scsi/scsi_all.h> 4239223Sgibbs 4339223Sgibbsstatic int bt_isa_probe __P((struct isa_device *dev)); 4439223Sgibbsstatic int bt_isa_attach __P((struct isa_device *dev)); 4539223Sgibbsstatic void bt_isa_intr __P((void *unit)); 4639223Sgibbs 4739223Sgibbsstatic bus_dma_filter_t btvlbouncefilter; 4839223Sgibbsstatic bus_dmamap_callback_t btmapsensebuffers; 4939223Sgibbs 5039223Sgibbsstruct isa_driver btdriver = 5139223Sgibbs{ 5239223Sgibbs bt_isa_probe, 5339223Sgibbs bt_isa_attach, 5439223Sgibbs "bt" 5539223Sgibbs}; 5639223Sgibbs 5739223Sgibbs/* 5839223Sgibbs * Check if the device can be found at the port given 5939223Sgibbs * and if so, set it up ready for further work 6039223Sgibbs * as an argument, takes the isa_device structure from 6139223Sgibbs * autoconf.c 6239223Sgibbs */ 6339223Sgibbsstatic int 6439223Sgibbsbt_isa_probe(dev) 6539223Sgibbs struct isa_device *dev; 6639223Sgibbs{ 6739223Sgibbs /* 6839223Sgibbs * find unit and check we have that many defined 6939223Sgibbs */ 7039223Sgibbs struct bt_softc *bt; 7139223Sgibbs int port_index; 7239223Sgibbs int max_port_index; 7339223Sgibbs 7439223Sgibbs /* 7539223Sgibbs * We ignore the unit number assigned by config to allow 7639223Sgibbs * consistant numbering between PCI/EISA/ISA devices. 7739223Sgibbs * This is a total kludge until we have a configuration 7839223Sgibbs * manager. 7939223Sgibbs */ 8039223Sgibbs dev->id_unit = bt_unit; 8139223Sgibbs 8239223Sgibbs bt = NULL; 8339223Sgibbs port_index = 0; 8439223Sgibbs max_port_index = BT_NUM_ISAPORTS - 1; 8539223Sgibbs /* 8639223Sgibbs * Bound our board search if the user has 8739223Sgibbs * specified an exact port. 8839223Sgibbs */ 8939223Sgibbs if (dev->id_iobase > 0) { 9039223Sgibbs for (;port_index <= max_port_index; port_index++) 9139223Sgibbs if (dev->id_iobase >= bt_isa_ports[port_index].addr) 9239223Sgibbs break; 9339223Sgibbs if ((port_index > max_port_index) 9439223Sgibbs || (dev->id_iobase != bt_isa_ports[port_index].addr)) { 9539223Sgibbs printf(" 9639223Sgibbsbt_isa_probe: Invalid baseport of 0x%x specified. 9739223Sgibbsbt_isa_probe: Nearest valid baseport is 0x%x. 9839223Sgibbsbt_isa_probe: Failing probe.\n", 9939223Sgibbs dev->id_iobase, 10039223Sgibbs (port_index <= max_port_index) 10139223Sgibbs ? bt_isa_ports[port_index].addr 10239223Sgibbs : bt_isa_ports[max_port_index].addr); 10339223Sgibbs return 0; 10439223Sgibbs } 10540160Simp max_port_index = port_index; 10639223Sgibbs } 10739223Sgibbs 10839223Sgibbs /* Attempt to find an adapter */ 10939223Sgibbs for (;port_index <= max_port_index; port_index++) { 11039223Sgibbs config_data_t config_data; 11139223Sgibbs u_int ioport; 11239223Sgibbs int error; 11339223Sgibbs 11439223Sgibbs ioport = bt_isa_ports[port_index].addr; 11539223Sgibbs 11639223Sgibbs /* 11739223Sgibbs * Ensure this port has not already been claimed already 11839223Sgibbs * by a PCI or EISA adapter. 11939223Sgibbs */ 12039223Sgibbs if (bt_check_probed_iop(ioport) != 0) 12139223Sgibbs continue; 12239223Sgibbs 12340160Simp /* 12440160Simp * Make sure that we do not conflict with another device's 12540160Simp * I/O address. 12640160Simp */ 12740160Simp if (haveseen_isadev(dev, CC_IOADDR)) 12840160Simp continue; 12940160Simp 13039223Sgibbs /* Allocate a softc for use during probing */ 13139223Sgibbs bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 13239223Sgibbs 13339223Sgibbs if (bt == NULL) 13439223Sgibbs break; 13539223Sgibbs 13639223Sgibbs /* We're going to attempt to probe it now, so mark it probed */ 13739223Sgibbs bt_mark_probed_bio(port_index); 13839223Sgibbs 13939223Sgibbs /* See if there is really a card present */ 14039223Sgibbs if (bt_probe(bt) || bt_fetch_adapter_info(bt)) { 14139223Sgibbs bt_free(bt); 14239223Sgibbs continue; 14339223Sgibbs } 14439223Sgibbs 14539223Sgibbs /* 14639223Sgibbs * Determine our IRQ, and DMA settings and 14739223Sgibbs * export them to the configuration system. 14839223Sgibbs */ 14939223Sgibbs error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 15039223Sgibbs (u_int8_t*)&config_data, sizeof(config_data), 15139223Sgibbs DEFAULT_CMD_TIMEOUT); 15239223Sgibbs if (error != 0) { 15339223Sgibbs printf("bt_isa_probe: Could not determine IRQ or DMA " 15439223Sgibbs "settings for adapter at 0x%x. Failing probe\n", 15539223Sgibbs ioport); 15639223Sgibbs bt_free(bt); 15739223Sgibbs continue; 15839223Sgibbs } 15939223Sgibbs 16039223Sgibbs if (bt->model[0] == '5') { 16139223Sgibbs /* DMA settings only make sense for ISA cards */ 16239223Sgibbs switch (config_data.dma_chan) { 16339223Sgibbs case DMA_CHAN_5: 16439223Sgibbs dev->id_drq = 5; 16539223Sgibbs break; 16639223Sgibbs case DMA_CHAN_6: 16739223Sgibbs dev->id_drq = 6; 16839223Sgibbs break; 16939223Sgibbs case DMA_CHAN_7: 17039223Sgibbs dev->id_drq = 7; 17139223Sgibbs break; 17239223Sgibbs default: 17339223Sgibbs printf("bt_isa_probe: Invalid DMA setting " 17439223Sgibbs "detected for adapter at 0x%x. " 17539223Sgibbs "Failing probe\n", ioport); 17639223Sgibbs } 17739223Sgibbs } else { 17839223Sgibbs /* VL DMA */ 17939223Sgibbs dev->id_drq = -1; 18039223Sgibbs } 18139223Sgibbs dev->id_iobase = bt_isa_ports[port_index].addr; 18239223Sgibbs dev->id_irq = (config_data.irq << 9); 18339223Sgibbs dev->id_intr = bt_isa_intr; 18440160Simp 18540160Simp /* 18640160Simp * OK, check to make sure that we're not stepping on 18740160Simp * someone else's IRQ or DRQ 18840160Simp */ 18940160Simp if (haveseen_isadev(dev, CC_DRQ)) { 19040160Simp printf("bt_isa_probe: Bt card at I/O 0x%x's drq %d " 19140160Simp "conflicts, ignoring card.\n", dev->id_iobase, 19240160Simp dev->id_drq); 19340160Simp bt_free(bt); 19440160Simp return 0; 19540160Simp } 19640160Simp if (haveseen_isadev(dev, CC_IRQ)) { 19740160Simp printf("bt_isa_probe: Bt card at I/O 0x%x's irq %d " 19840160Simp "conflicts, ignoring card.\n", dev->id_iobase, 19940160Simp config_data.irq + 9); 20040160Simp bt_free(bt); 20140160Simp return 0; 20240160Simp } 20339223Sgibbs bt_unit++; 20439223Sgibbs return (BT_NREGS); 20539223Sgibbs } 20639223Sgibbs 20739223Sgibbs return (0); 20839223Sgibbs} 20939223Sgibbs 21039223Sgibbs/* 21139223Sgibbs * Attach all the sub-devices we can find 21239223Sgibbs */ 21339223Sgibbsstatic int 21439223Sgibbsbt_isa_attach(dev) 21539223Sgibbs struct isa_device *dev; 21639223Sgibbs{ 21739223Sgibbs struct bt_softc *bt; 21839223Sgibbs bus_dma_filter_t *filter; 21939223Sgibbs void *filter_arg; 22039223Sgibbs bus_addr_t lowaddr; 22139223Sgibbs 22239223Sgibbs bt = bt_softcs[dev->id_unit]; 22339223Sgibbs if (dev->id_drq != -1) 22439223Sgibbs isa_dmacascade(dev->id_drq); 22539223Sgibbs 22639223Sgibbs /* Allocate our parent dmatag */ 22739223Sgibbs filter = NULL; 22839223Sgibbs filter_arg = NULL; 22939223Sgibbs lowaddr = BUS_SPACE_MAXADDR_24BIT; 23039223Sgibbs if (bt->model[0] == '4') { 23139223Sgibbs /* 23239223Sgibbs * This is a VL adapter. Typically, VL devices have access 23339223Sgibbs * to the full 32bit address space. On BT-445S adapters 23439223Sgibbs * prior to revision E, there is a hardware bug that causes 23539223Sgibbs * corruption of transfers to/from addresses in the range of 23639223Sgibbs * the BIOS modulo 16MB. The only properly functioning 23739223Sgibbs * BT-445S Host Adapters have firmware version 3.37. 23839223Sgibbs * If we encounter one of these adapters and the BIOS is 23939223Sgibbs * installed, install a filter function for our bus_dma_map 24039223Sgibbs * that will catch these accesses and bounce them to a safe 24139223Sgibbs * region of memory. 24239223Sgibbs */ 24339223Sgibbs if (bt->bios_addr != 0 24439223Sgibbs && strcmp(bt->model, "445S") == 0 24539223Sgibbs && strcmp(bt->firmware_ver, "3.37") < 0) { 24639223Sgibbs filter = btvlbouncefilter; 24739223Sgibbs filter_arg = bt; 24839223Sgibbs } else { 24939223Sgibbs lowaddr = BUS_SPACE_MAXADDR_32BIT; 25039223Sgibbs } 25139223Sgibbs } 25239223Sgibbs 25339223Sgibbs /* XXX Should be a child of the ISA or VL bus dma tag */ 25439223Sgibbs if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, 25539223Sgibbs lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 25639223Sgibbs filter, filter_arg, 25739223Sgibbs /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 25839223Sgibbs /*nsegments*/BUS_SPACE_UNRESTRICTED, 25939223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 26039223Sgibbs /*flags*/0, &bt->parent_dmat) != 0) { 26139223Sgibbs bt_free(bt); 26239223Sgibbs return (-1); 26339223Sgibbs } 26439223Sgibbs 26539223Sgibbs if (bt_init(bt)) { 26639223Sgibbs bt_free(bt); 26739223Sgibbs return (-1); 26839223Sgibbs } 26939223Sgibbs 27039223Sgibbs if (lowaddr != BUS_SPACE_MAXADDR_32BIT) { 27139223Sgibbs /* DMA tag for our sense buffers */ 27239223Sgibbs if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, 27339223Sgibbs /*boundary*/0, 27439223Sgibbs /*lowaddr*/BUS_SPACE_MAXADDR, 27539223Sgibbs /*highaddr*/BUS_SPACE_MAXADDR, 27639223Sgibbs /*filter*/NULL, /*filterarg*/NULL, 27739223Sgibbs bt->max_ccbs 27839223Sgibbs * sizeof(struct scsi_sense_data), 27939223Sgibbs /*nsegments*/1, 28039223Sgibbs /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 28139223Sgibbs /*flags*/0, &bt->sense_dmat) != 0) { 28239223Sgibbs bt_free(bt); 28339223Sgibbs return (-1); 28439223Sgibbs } 28539223Sgibbs 28639223Sgibbs bt->init_level++; 28739223Sgibbs 28839223Sgibbs /* Allocation of sense buffers */ 28939223Sgibbs if (bus_dmamem_alloc(bt->sense_dmat, 29039223Sgibbs (void **)&bt->sense_buffers, 29139223Sgibbs BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 29239223Sgibbs bt_free(bt); 29339223Sgibbs return (-1); 29439223Sgibbs } 29539223Sgibbs 29639223Sgibbs bt->init_level++; 29739223Sgibbs 29839223Sgibbs /* And permanently map them */ 29939223Sgibbs bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 30039223Sgibbs bt->sense_buffers, 30139223Sgibbs bt->max_ccbs * sizeof(*bt->sense_buffers), 30239223Sgibbs btmapsensebuffers, bt, /*flags*/0); 30339223Sgibbs 30439223Sgibbs bt->init_level++; 30539223Sgibbs } 30639223Sgibbs 30739223Sgibbs return (bt_attach(bt)); 30839223Sgibbs} 30939223Sgibbs 31039223Sgibbs/* 31139223Sgibbs * Handle an ISA interrupt. 31239223Sgibbs * XXX should go away as soon as ISA interrupt handlers 31339223Sgibbs * take a (void *) arg. 31439223Sgibbs */ 31539223Sgibbsstatic void 31639223Sgibbsbt_isa_intr(void *unit) 31739223Sgibbs{ 31839223Sgibbs struct bt_softc* arg = bt_softcs[(int)unit]; 31939223Sgibbs bt_intr((void *)arg); 32039223Sgibbs} 32139223Sgibbs 32239223Sgibbs#define BIOS_MAP_SIZE (16 * 1024) 32339223Sgibbs 32439223Sgibbsstatic int 32539223Sgibbsbtvlbouncefilter(void *arg, bus_addr_t addr) 32639223Sgibbs{ 32739223Sgibbs struct bt_softc *bt; 32839223Sgibbs 32939223Sgibbs bt = (struct bt_softc *)arg; 33039223Sgibbs 33139223Sgibbs addr &= BUS_SPACE_MAXADDR_24BIT; 33239223Sgibbs 33339223Sgibbs if (addr == 0 33439223Sgibbs || (addr >= bt->bios_addr 33539223Sgibbs && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 33639223Sgibbs return (1); 33739223Sgibbs return (0); 33839223Sgibbs} 33939223Sgibbs 34039223Sgibbsstatic void 34139223Sgibbsbtmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 34239223Sgibbs{ 34339223Sgibbs struct bt_softc* bt; 34439223Sgibbs 34539223Sgibbs bt = (struct bt_softc*)arg; 34639223Sgibbs bt->sense_buffers_physbase = segs->ds_addr; 34739223Sgibbs} 348