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 *
| 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 $
| 29 * $Id: bt_isa.c,v 1.4 1998/10/12 18:53:33 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 */
| 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 }
| 89 bt_find_probe_range(dev->id_iobase, &port_index, &max_port_index);
|
107
| 90
|
| 91 if (port_index < 0) 92 return 0; 93
|
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
| 94 /* Attempt to find an adapter */ 95 for (;port_index <= max_port_index; port_index++) { 96 config_data_t config_data; 97 u_int ioport; 98 int error; 99
|
114 ioport = bt_isa_ports[port_index].addr;
| 100 ioport = bt_iop_from_bio(port_index);
|
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;
| 101 102 /* 103 * Ensure this port has not already been claimed already 104 * by a PCI, EISA or ISA adapter. 105 */ 106 if (bt_check_probed_iop(ioport) != 0) 107 continue;
|
122 dev->id_iobase = bt_isa_ports[port_index].addr;
| 108 dev->id_iobase = ioport;
|
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);
| 109 if (haveseen_isadev(dev, CC_IOADDR | CC_QUIET)) 110 continue; 111 112 /* Allocate a softc for use during probing */ 113 bt = bt_alloc(dev->id_unit, I386_BUS_SPACE_IO, ioport); 114 115 if (bt == NULL) 116 break; 117 118 /* We're going to attempt to probe it now, so mark it probed */ 119 bt_mark_probed_bio(port_index); 120 121 /* See if there is really a card present */ 122 if (bt_probe(bt) || bt_fetch_adapter_info(bt)) { 123 bt_free(bt); 124 continue; 125 } 126 127 /* 128 * Determine our IRQ, and DMA settings and 129 * export them to the configuration system. 130 */ 131 error = bt_cmd(bt, BOP_INQUIRE_CONFIG, NULL, /*parmlen*/0, 132 (u_int8_t*)&config_data, sizeof(config_data), 133 DEFAULT_CMD_TIMEOUT); 134 if (error != 0) { 135 printf("bt_isa_probe: Could not determine IRQ or DMA " 136 "settings for adapter at 0x%x. Failing probe\n", 137 ioport); 138 bt_free(bt); 139 continue; 140 } 141 142 if (bt->model[0] == '5') { 143 /* DMA settings only make sense for ISA cards */ 144 switch (config_data.dma_chan) { 145 case DMA_CHAN_5: 146 dev->id_drq = 5; 147 break; 148 case DMA_CHAN_6: 149 dev->id_drq = 6; 150 break; 151 case DMA_CHAN_7: 152 dev->id_drq = 7; 153 break; 154 default: 155 printf("bt_isa_probe: Invalid DMA setting " 156 "detected for adapter at 0x%x. " 157 "Failing probe\n", ioport);
|
| 158 return (0);
|
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}
| 159 } 160 } else { 161 /* VL DMA */ 162 dev->id_drq = -1; 163 } 164 dev->id_irq = (config_data.irq << 9); 165 dev->id_intr = bt_isa_intr; 166 167 bt_unit++; 168 return (BT_NREGS); 169 } 170 171 return (0); 172} 173 174/* 175 * Attach all the sub-devices we can find 176 */ 177static int 178bt_isa_attach(dev) 179 struct isa_device *dev; 180{ 181 struct bt_softc *bt; 182 bus_dma_filter_t *filter; 183 void *filter_arg; 184 bus_addr_t lowaddr; 185 186 bt = bt_softcs[dev->id_unit]; 187 if (dev->id_drq != -1) 188 isa_dmacascade(dev->id_drq); 189 190 /* Allocate our parent dmatag */ 191 filter = NULL; 192 filter_arg = NULL; 193 lowaddr = BUS_SPACE_MAXADDR_24BIT; 194 if (bt->model[0] == '4') { 195 /* 196 * This is a VL adapter. Typically, VL devices have access 197 * to the full 32bit address space. On BT-445S adapters 198 * prior to revision E, there is a hardware bug that causes 199 * corruption of transfers to/from addresses in the range of 200 * the BIOS modulo 16MB. The only properly functioning 201 * BT-445S Host Adapters have firmware version 3.37. 202 * If we encounter one of these adapters and the BIOS is 203 * installed, install a filter function for our bus_dma_map 204 * that will catch these accesses and bounce them to a safe 205 * region of memory. 206 */ 207 if (bt->bios_addr != 0 208 && strcmp(bt->model, "445S") == 0 209 && strcmp(bt->firmware_ver, "3.37") < 0) { 210 filter = btvlbouncefilter; 211 filter_arg = bt; 212 } else { 213 lowaddr = BUS_SPACE_MAXADDR_32BIT; 214 } 215 } 216 217 /* XXX Should be a child of the ISA or VL bus dma tag */ 218 if (bus_dma_tag_create(/*parent*/NULL, /*alignemnt*/0, /*boundary*/0, 219 lowaddr, /*highaddr*/BUS_SPACE_MAXADDR, 220 filter, filter_arg, 221 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 222 /*nsegments*/BUS_SPACE_UNRESTRICTED, 223 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 224 /*flags*/0, &bt->parent_dmat) != 0) { 225 bt_free(bt); 226 return (-1); 227 } 228 229 if (bt_init(bt)) { 230 bt_free(bt); 231 return (-1); 232 } 233 234 if (lowaddr != BUS_SPACE_MAXADDR_32BIT) { 235 /* DMA tag for our sense buffers */ 236 if (bus_dma_tag_create(bt->parent_dmat, /*alignment*/0, 237 /*boundary*/0, 238 /*lowaddr*/BUS_SPACE_MAXADDR, 239 /*highaddr*/BUS_SPACE_MAXADDR, 240 /*filter*/NULL, /*filterarg*/NULL, 241 bt->max_ccbs 242 * sizeof(struct scsi_sense_data), 243 /*nsegments*/1, 244 /*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT, 245 /*flags*/0, &bt->sense_dmat) != 0) { 246 bt_free(bt); 247 return (-1); 248 } 249 250 bt->init_level++; 251 252 /* Allocation of sense buffers */ 253 if (bus_dmamem_alloc(bt->sense_dmat, 254 (void **)&bt->sense_buffers, 255 BUS_DMA_NOWAIT, &bt->sense_dmamap) != 0) { 256 bt_free(bt); 257 return (-1); 258 } 259 260 bt->init_level++; 261 262 /* And permanently map them */ 263 bus_dmamap_load(bt->sense_dmat, bt->sense_dmamap, 264 bt->sense_buffers, 265 bt->max_ccbs * sizeof(*bt->sense_buffers), 266 btmapsensebuffers, bt, /*flags*/0); 267 268 bt->init_level++; 269 } 270 271 return (bt_attach(bt)); 272} 273 274/* 275 * Handle an ISA interrupt. 276 * XXX should go away as soon as ISA interrupt handlers 277 * take a (void *) arg. 278 */ 279static void 280bt_isa_intr(void *unit) 281{ 282 struct bt_softc* arg = bt_softcs[(int)unit]; 283 bt_intr((void *)arg); 284} 285 286#define BIOS_MAP_SIZE (16 * 1024) 287 288static int 289btvlbouncefilter(void *arg, bus_addr_t addr) 290{ 291 struct bt_softc *bt; 292 293 bt = (struct bt_softc *)arg; 294 295 addr &= BUS_SPACE_MAXADDR_24BIT; 296 297 if (addr == 0 298 || (addr >= bt->bios_addr 299 && addr < (bt->bios_addr + BIOS_MAP_SIZE))) 300 return (1); 301 return (0); 302} 303 304static void 305btmapsensebuffers(void *arg, bus_dma_segment_t *segs, int nseg, int error) 306{ 307 struct bt_softc* bt; 308 309 bt = (struct bt_softc*)arg; 310 bt->sense_buffers_physbase = segs->ds_addr; 311}
|