bt_isa.c revision 40265
1/* 2 * Product specific probe and attach routines for: 3 * Buslogic BT-54X and BT-445 cards 4 * 5 * Copyright (c) 1998 Justin T. Gibbs 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions, and the following disclaimer, 13 * without modification, immediately at the beginning of the file. 14 * 2. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * 29 * $Id: bt_isa.c,v 1.3 1998/10/10 00:44:12 imp Exp $ 30 */ 31 32#include <sys/param.h> 33#include <sys/systm.h> 34 35#include <machine/bus_pio.h> 36#include <machine/bus.h> 37 38#include <i386/isa/isa_device.h> 39#include <dev/buslogic/btreg.h> 40 41#include <cam/scsi/scsi_all.h> 42 43static int bt_isa_probe __P((struct isa_device *dev)); 44static int bt_isa_attach __P((struct isa_device *dev)); 45static void bt_isa_intr __P((void *unit)); 46 47static bus_dma_filter_t btvlbouncefilter; 48static bus_dmamap_callback_t btmapsensebuffers; 49 50struct isa_driver btdriver = 51{ 52 bt_isa_probe, 53 bt_isa_attach, 54 "bt" 55}; 56 57/* 58 * Check if the device can be found at the port given 59 * and if so, set it up ready for further work 60 * as an argument, takes the isa_device structure from 61 * autoconf.c 62 */ 63static int 64bt_isa_probe(dev) 65 struct isa_device *dev; 66{ 67 /* 68 * find unit and check we have that many defined 69 */ 70 struct bt_softc *bt; 71 int port_index; 72 int max_port_index; 73 74 /* 75 * We ignore the unit number assigned by config to allow 76 * consistant numbering between PCI/EISA/ISA devices. 77 * This is a total kludge until we have a configuration 78 * manager. 79 */ 80 dev->id_unit = bt_unit; 81 82 bt = NULL; 83 port_index = 0; 84 max_port_index = BT_NUM_ISAPORTS - 1; 85 /* 86 * Bound our board search if the user has 87 * specified an exact port. 88 */ 89 if (dev->id_iobase > 0) { 90 for (;port_index <= max_port_index; port_index++) 91 if (dev->id_iobase >= bt_isa_ports[port_index].addr) 92 break; 93 if ((port_index > max_port_index) 94 || (dev->id_iobase != bt_isa_ports[port_index].addr)) { 95 printf(" 96bt_isa_probe: Invalid baseport of 0x%x specified. 97bt_isa_probe: Nearest valid baseport is 0x%x. 98bt_isa_probe: Failing probe.\n", 99 dev->id_iobase, 100 (port_index <= max_port_index) 101 ? bt_isa_ports[port_index].addr 102 : bt_isa_ports[max_port_index].addr); 103 return 0; 104 } 105 max_port_index = port_index; 106 } 107 108 /* Attempt to find an adapter */ 109 for (;port_index <= max_port_index; port_index++) { 110 config_data_t config_data; 111 u_int ioport; 112 int error; 113 114 ioport = bt_isa_ports[port_index].addr; 115 116 /* 117 * Ensure this port has not already been claimed already 118 * by a PCI, EISA or ISA adapter. 119 */ 120 if (bt_check_probed_iop(ioport) != 0) 121 continue; 122 dev->id_iobase = bt_isa_ports[port_index].addr; 123 if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET)) 124 continue; 125 126 /* Allocate a softc for use during probing */ 127 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 128 129 if (bt == NULL) 130 break; 131 132 /* We're going to attempt to probe it now, so mark it probed */ 133 bt_mark_probed_bio(port_index); 134 135 /* See if there is really a card present */ 136 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) { 137 bt_free(bt); 138 continue; 139 } 140 141 /* 142 * Determine our IRQ, and DMA settings and 143 * export them to the configuration system. 144 */ 145 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 146 (u_int8_t*)&config_data, sizeof(config_data), 147 DEFAULT_CMD_TIMEOUT); 148 if (error != 0) { 149 printf("bt_isa_probe: Could not determine IRQ or DMA " 150 "settings for adapter at 0x%x. Failing probe\n", 151 ioport); 152 bt_free(bt); 153 continue; 154 } 155 156 if (bt->model[0] == '5') { 157 /* DMA settings only make sense for ISA cards */ 158 switch (config_data.dma_chan) { 159 case DMA_CHAN_5: 160 dev->id_drq = 5; 161 break; 162 case DMA_CHAN_6: 163 dev->id_drq = 6; 164 break; 165 case DMA_CHAN_7: 166 dev->id_drq = 7; 167 break; 168 default: 169 printf("bt_isa_probe: Invalid DMA setting " 170 "detected for adapter at 0x%x. " 171 "Failing probe\n", ioport); 172 } 173 } else { 174 /* VL DMA */ 175 dev->id_drq = -1; 176 } 177 dev->id_irq = (config_data.irq << 9); 178 dev->id_intr = bt_isa_intr; 179 180 bt_unit++; 181 return (BT_NREGS); 182 } 183 184 return (0); 185} 186 187/* 188 * Attach all the sub-devices we can find 189 */ 190static int 191bt_isa_attach(dev) 192 struct isa_device *dev; 193{ 194 struct bt_softc *bt; 195 bus_dma_filter_t *filter; 196 void *filter_arg; 197 bus_addr_t lowaddr; 198 199 bt = bt_softcs[dev->id_unit]; 200 if (dev->id_drq != -1) 201 isa_dmacascade(dev->id_drq); 202 203 /* Allocate our parent dmatag */ 204 filter = NULL; 205 filter_arg = NULL; 206 lowaddr = BUS_SPACE_MAXADDR_24BIT; 207 if (bt->model[0] == '4') { 208 /* 209 * This is a VL adapter. Typically, VL devices have access 210 * to the full 32bit address space. On BT-445S adapters 211 * prior to revision E, there is a hardware bug that causes 212 * corruption of transfers to/from addresses in the range of 213 * the BIOS modulo 16MB. The only properly functioning 214 * BT-445S Host Adapters have firmware version 3.37. 215 * If we encounter one of these adapters and the BIOS is 216 * installed, install a filter function for our bus_dma_map 217 * that will catch these accesses and bounce them to a safe 218 * region of memory. 219 */ 220 if (bt->bios_addr != 0 221 && strcmp(bt->model, "445S") == 0 222 && strcmp(bt->firmware_ver, "3.37") < 0) { 223 filter = btvlbouncefilter; 224 filter_arg = bt; 225 } else { 226 lowaddr = BUS_SPACE_MAXADDR_32BIT; 227 } 228 } 229 230 /* XXX Should be a child of the ISA or VL bus dma tag */ 231 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, 232 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 233 filter, filter_arg, 234 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 235 /*nsegments*/BUS_SPACE_UNRESTRICTED, 236 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 237 /*flags*/0, &bt->parent_dmat) != 0) { 238 bt_free(bt); 239 return (-1); 240 } 241 242 if (bt_init(bt)) { 243 bt_free(bt); 244 return (-1); 245 } 246 247 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) { 248 /* DMA tag for our sense buffers */ 249 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, 250 /*boundary*/0, 251 /*lowaddr*/BUS_SPACE_MAXADDR, 252 /*highaddr*/BUS_SPACE_MAXADDR, 253 /*filter*/NULL, /*filterarg*/NULL, 254 bt->max_ccbs 255 * sizeof(struct scsi_sense_data), 256 /*nsegments*/1, 257 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 258 /*flags*/0, &bt->sense_dmat) != 0) { 259 bt_free(bt); 260 return (-1); 261 } 262 263 bt->init_level++; 264 265 /* Allocation of sense buffers */ 266 if (bus_dmamem_alloc(bt->sense_dmat, 267 (void **)&bt->sense_buffers, 268 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 269 bt_free(bt); 270 return (-1); 271 } 272 273 bt->init_level++; 274 275 /* And permanently map them */ 276 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 277 bt->sense_buffers, 278 bt->max_ccbs * sizeof(*bt->sense_buffers), 279 btmapsensebuffers, bt, /*flags*/0); 280 281 bt->init_level++; 282 } 283 284 return (bt_attach(bt)); 285} 286 287/* 288 * Handle an ISA interrupt. 289 * XXX should go away as soon as ISA interrupt handlers 290 * take a (void *) arg. 291 */ 292static void 293bt_isa_intr(void *unit) 294{ 295 struct bt_softc* arg = bt_softcs[(int)unit]; 296 bt_intr((void *)arg); 297} 298 299#define BIOS_MAP_SIZE (16 * 1024) 300 301static int 302btvlbouncefilter(void *arg, bus_addr_t addr) 303{ 304 struct bt_softc *bt; 305 306 bt = (struct bt_softc *)arg; 307 308 addr &= BUS_SPACE_MAXADDR_24BIT; 309 310 if (addr == 0 311 || (addr >= bt->bios_addr 312 && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 313 return (1); 314 return (0); 315} 316 317static void 318btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 319{ 320 struct bt_softc* bt; 321 322 bt = (struct bt_softc*)arg; 323 bt->sense_buffers_physbase = segs->ds_addr; 324} 325