adv_eisa.c revision 73280
1/* 2 * Device probe and attach routines for the following 3 * Advanced Systems Inc. SCSI controllers: 4 * 5 * Single Channel Products: 6 * ABP742 - Bus-Master EISA (240 CDB) 7 * 8 * Dual Channel Products: 9 * ABP752 - Dual Channel Bus-Master EISA (240 CDB Per Channel) 10 * 11 * Copyright (c) 1997 Justin Gibbs. 12 * All rights reserved. 13 * 14 * Redistribution and use in source and binary forms, with or without 15 * modification, are permitted provided that the following conditions 16 * are met: 17 * 1. Redistributions of source code must retain the above copyright 18 * notice, this list of conditions, and the following disclaimer, 19 * without modification, immediately at the beginning of the file. 20 * 2. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 27 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $FreeBSD: head/sys/dev/advansys/adv_eisa.c 73280 2001-03-01 17:09:09Z markm $ 36 */ 37 38#include <sys/param.h> 39#include <sys/systm.h> 40#include <sys/kernel.h> 41#include <sys/module.h> 42#include <sys/bus.h> 43 44#include <machine/bus_pio.h> 45#include <machine/bus.h> 46#include <machine/resource.h> 47#include <sys/rman.h> 48 49#include <dev/eisa/eisaconf.h> 50 51#include <dev/advansys/advansys.h> 52 53#define EISA_DEVICE_ID_ADVANSYS_740 0x04507400 54#define EISA_DEVICE_ID_ADVANSYS_750 0x04507500 55 56#define ADV_EISA_SLOT_OFFSET 0xc00 57#define ADV_EISA_OFFSET_CHAN1 0x30 58#define ADV_EISA_OFFSET_CHAN2 0x50 59#define ADV_EISA_IOSIZE 0x100 60 61#define ADV_EISA_ROM_BIOS_ADDR_REG 0x86 62#define ADV_EISA_IRQ_BURST_LEN_REG 0x87 63#define ADV_EISA_IRQ_MASK 0x07 64#define ADV_EISA_IRQ_10 0x00 65#define ADV_EISA_IRQ_11 0x01 66#define ADV_EISA_IRQ_12 0x02 67#define ADV_EISA_IRQ_14 0x04 68#define ADV_EISA_IRQ_15 0x05 69 70#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL) 71#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL) 72 73/* 74 * The overrun buffer shared amongst all EISA adapters. 75 */ 76static u_int8_t* overrun_buf; 77static bus_dma_tag_t overrun_dmat; 78static bus_dmamap_t overrun_dmamap; 79static bus_addr_t overrun_physbase; 80 81static const char* 82adv_eisa_match(eisa_id_t type) 83{ 84 switch (type & ~0xF) { 85 case EISA_DEVICE_ID_ADVANSYS_740: 86 return ("AdvanSys ABP-740/742 SCSI adapter"); 87 break; 88 case EISA_DEVICE_ID_ADVANSYS_750: 89 return ("AdvanSys ABP-750/752 SCSI adapter"); 90 break; 91 default: 92 break; 93 } 94 return (NULL); 95} 96 97static int 98adv_eisa_probe(device_t dev) 99{ 100 const char *desc; 101 u_int32_t iobase; 102 u_int8_t irq; 103 104 desc = adv_eisa_match(eisa_get_id(dev)); 105 if (!desc) 106 return (ENXIO); 107 device_set_desc(dev, desc); 108 109 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + ADV_EISA_SLOT_OFFSET; 110 111 eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE); 112 irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG); 113 irq &= ADV_EISA_IRQ_MASK; 114 switch (irq) { 115 case 0: 116 case 1: 117 case 2: 118 case 4: 119 case 5: 120 break; 121 default: 122 printf("adv at slot %d: illegal " 123 "irq setting %d\n", eisa_get_slot(dev), 124 irq); 125 return ENXIO; 126 } 127 eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL); 128 129 return 0; 130} 131 132static int 133adv_eisa_attach(device_t dev) 134{ 135 struct adv_softc *adv; 136 struct adv_softc *adv_b; 137 struct resource *io; 138 struct resource *irq; 139 int rid, error; 140 void *ih; 141 142 adv_b = NULL; 143 144 rid = 0; 145 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 146 0, ~0, 1, RF_ACTIVE); 147 if (!io) { 148 device_printf(dev, "No I/O space?!\n"); 149 return ENOMEM; 150 } 151 152 rid = 0; 153 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 154 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 155 if (!irq) { 156 device_printf(dev, "No irq?!\n"); 157 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 158 return ENOMEM; 159 160 } 161 162 switch (eisa_get_id(dev) & ~0xF) { 163 case EISA_DEVICE_ID_ADVANSYS_750: 164 adv_b = adv_alloc(dev, rman_get_bustag(io), 165 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2); 166 if (adv_b == NULL) 167 goto bad; 168 169 /* 170 * Allocate a parent dmatag for all tags created 171 * by the MI portions of the advansys driver 172 */ 173 /* XXX Should be a child of the PCI bus dma tag */ 174 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 175 /*boundary*/0, 176 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR, 177 /*highaddr*/BUS_SPACE_MAXADDR, 178 /*filter*/NULL, /*filterarg*/NULL, 179 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 180 /*nsegments*/BUS_SPACE_UNRESTRICTED, 181 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT, 182 /*flags*/0, 183 &adv_b->parent_dmat); 184 185 if (error != 0) { 186 printf("%s: Could not allocate DMA tag - error %d\n", 187 adv_name(adv_b), error); 188 adv_free(adv_b); 189 goto bad; 190 } 191 192 adv_b->init_level++; 193 194 /* FALLTHROUGH */ 195 case EISA_DEVICE_ID_ADVANSYS_740: 196 adv = adv_alloc(dev, rman_get_bustag(io), 197 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1); 198 if (adv == NULL) { 199 if (adv_b != NULL) 200 adv_free(adv_b); 201 goto bad; 202 } 203 204 /* 205 * Allocate a parent dmatag for all tags created 206 * by the MI portions of the advansys driver 207 */ 208 /* XXX Should be a child of the PCI bus dma tag */ 209 error = bus_dma_tag_create(/*parent*/NULL, /*alignment*/1, 210 /*boundary*/0, 211 /*lowaddr*/ADV_EISA_MAX_DMA_ADDR, 212 /*highaddr*/BUS_SPACE_MAXADDR, 213 /*filter*/NULL, /*filterarg*/NULL, 214 /*maxsize*/BUS_SPACE_MAXSIZE_32BIT, 215 /*nsegments*/BUS_SPACE_UNRESTRICTED, 216 /*maxsegsz*/ADV_EISA_MAX_DMA_COUNT, 217 /*flags*/0, 218 &adv->parent_dmat); 219 220 if (error != 0) { 221 printf("%s: Could not allocate DMA tag - error %d\n", 222 adv_name(adv), error); 223 adv_free(adv); 224 goto bad; 225 } 226 227 adv->init_level++; 228 break; 229 default: 230 printf("adveisaattach: Unknown device type!\n"); 231 goto bad; 232 break; 233 } 234 235 if (overrun_buf == NULL) { 236 /* Need to allocate our overrun buffer */ 237 if (bus_dma_tag_create(adv->parent_dmat, 238 /*alignment*/8, 239 /*boundary*/0, 240 ADV_EISA_MAX_DMA_ADDR, 241 BUS_SPACE_MAXADDR, 242 /*filter*/NULL, 243 /*filterarg*/NULL, 244 ADV_OVERRUN_BSIZE, 245 /*nsegments*/1, 246 BUS_SPACE_MAXSIZE_32BIT, 247 /*flags*/0, 248 &overrun_dmat) != 0) { 249 adv_free(adv); 250 goto bad; 251 } 252 if (bus_dmamem_alloc(overrun_dmat, 253 (void **)&overrun_buf, 254 BUS_DMA_NOWAIT, 255 &overrun_dmamap) != 0) { 256 bus_dma_tag_destroy(overrun_dmat); 257 adv_free(adv); 258 goto bad; 259 } 260 /* And permanently map it in */ 261 bus_dmamap_load(overrun_dmat, overrun_dmamap, 262 overrun_buf, ADV_OVERRUN_BSIZE, 263 adv_map, &overrun_physbase, 264 /*flags*/0); 265 } 266 267 /* 268 * Now that we know we own the resources we need, do the 269 * card initialization. 270 */ 271 272 /* 273 * Stop the chip. 274 */ 275 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 276 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 277 278 adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 279 + ADV_CHIP_MIN_VER_EISA - 1; 280 281 if (adv_init(adv) != 0) { 282 adv_free(adv); 283 if (adv_b != NULL) 284 adv_free(adv_b); 285 return(-1); 286 } 287 288 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 289 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 290 291 if (adv_b != NULL) { 292 /* 293 * Stop the chip. 294 */ 295 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT); 296 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0); 297 298 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 299 + ADV_CHIP_MIN_VER_EISA - 1; 300 301 if (adv_init(adv_b) != 0) { 302 adv_free(adv_b); 303 } else { 304 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 305 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 306 } 307 } 308 309 /* 310 * Enable our interrupt handler. 311 */ 312 bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih); 313 314 /* Attach sub-devices - always succeeds */ 315 adv_attach(adv); 316 if (adv_b != NULL) 317 adv_attach(adv_b); 318 319 return 0; 320 321 bad: 322 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 323 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 324 return -1; 325} 326 327static device_method_t adv_eisa_methods[] = { 328 /* Device interface */ 329 DEVMETHOD(device_probe, adv_eisa_probe), 330 DEVMETHOD(device_attach, adv_eisa_attach), 331 { 0, 0 } 332}; 333 334static driver_t adv_eisa_driver = { 335 "adv", adv_eisa_methods, sizeof(struct adv_softc) 336}; 337 338static devclass_t adv_eisa_devclass; 339DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0); 340