adv_eisa.c revision 117126
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 117126 2003-07-01 15:52:06Z scottl $ 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/lock.h> 43#include <sys/mutex.h> 44#include <sys/bus.h> 45 46#include <machine/bus_pio.h> 47#include <machine/bus.h> 48#include <machine/resource.h> 49#include <sys/rman.h> 50 51#include <dev/eisa/eisaconf.h> 52 53#include <dev/advansys/advansys.h> 54 55#define EISA_DEVICE_ID_ADVANSYS_740 0x04507400 56#define EISA_DEVICE_ID_ADVANSYS_750 0x04507500 57 58#define ADV_EISA_SLOT_OFFSET 0xc00 59#define ADV_EISA_OFFSET_CHAN1 0x30 60#define ADV_EISA_OFFSET_CHAN2 0x50 61#define ADV_EISA_IOSIZE 0x100 62 63#define ADV_EISA_ROM_BIOS_ADDR_REG 0x86 64#define ADV_EISA_IRQ_BURST_LEN_REG 0x87 65#define ADV_EISA_IRQ_MASK 0x07 66#define ADV_EISA_IRQ_10 0x00 67#define ADV_EISA_IRQ_11 0x01 68#define ADV_EISA_IRQ_12 0x02 69#define ADV_EISA_IRQ_14 0x04 70#define ADV_EISA_IRQ_15 0x05 71 72#define ADV_EISA_MAX_DMA_ADDR (0x07FFFFFFL) 73#define ADV_EISA_MAX_DMA_COUNT (0x07FFFFFFL) 74 75/* 76 * The overrun buffer shared amongst all EISA adapters. 77 */ 78static u_int8_t* overrun_buf; 79static bus_dma_tag_t overrun_dmat; 80static bus_dmamap_t overrun_dmamap; 81static bus_addr_t overrun_physbase; 82 83static const char* 84adv_eisa_match(eisa_id_t type) 85{ 86 switch (type & ~0xF) { 87 case EISA_DEVICE_ID_ADVANSYS_740: 88 return ("AdvanSys ABP-740/742 SCSI adapter"); 89 break; 90 case EISA_DEVICE_ID_ADVANSYS_750: 91 return ("AdvanSys ABP-750/752 SCSI adapter"); 92 break; 93 default: 94 break; 95 } 96 return (NULL); 97} 98 99static int 100adv_eisa_probe(device_t dev) 101{ 102 const char *desc; 103 u_int32_t iobase; 104 u_int8_t irq; 105 106 desc = adv_eisa_match(eisa_get_id(dev)); 107 if (!desc) 108 return (ENXIO); 109 device_set_desc(dev, desc); 110 111 iobase = (eisa_get_slot(dev) * EISA_SLOT_SIZE) + ADV_EISA_SLOT_OFFSET; 112 113 eisa_add_iospace(dev, iobase, ADV_EISA_IOSIZE, RESVADDR_NONE); 114 irq = inb(iobase + ADV_EISA_IRQ_BURST_LEN_REG); 115 irq &= ADV_EISA_IRQ_MASK; 116 switch (irq) { 117 case 0: 118 case 1: 119 case 2: 120 case 4: 121 case 5: 122 break; 123 default: 124 printf("adv at slot %d: illegal " 125 "irq setting %d\n", eisa_get_slot(dev), 126 irq); 127 return ENXIO; 128 } 129 eisa_add_intr(dev, irq + 10, EISA_TRIGGER_LEVEL); 130 131 return 0; 132} 133 134static int 135adv_eisa_attach(device_t dev) 136{ 137 struct adv_softc *adv; 138 struct adv_softc *adv_b; 139 struct resource *io; 140 struct resource *irq; 141 int rid, error; 142 void *ih; 143 144 adv_b = NULL; 145 146 rid = 0; 147 io = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, 148 0, ~0, 1, RF_ACTIVE); 149 if (!io) { 150 device_printf(dev, "No I/O space?!\n"); 151 return ENOMEM; 152 } 153 154 rid = 0; 155 irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 156 0, ~0, 1, RF_SHAREABLE | RF_ACTIVE); 157 if (!irq) { 158 device_printf(dev, "No irq?!\n"); 159 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 160 return ENOMEM; 161 162 } 163 164 switch (eisa_get_id(dev) & ~0xF) { 165 case EISA_DEVICE_ID_ADVANSYS_750: 166 adv_b = adv_alloc(dev, rman_get_bustag(io), 167 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN2); 168 if (adv_b == NULL) 169 goto bad; 170 171 /* 172 * Allocate a parent dmatag for all tags created 173 * by the MI portions of the advansys driver 174 */ 175 /* XXX Should be a child of the PCI bus dma tag */ 176 error = bus_dma_tag_create( 177 /* parent */ NULL, 178 /* alignment */ 1, 179 /* boundary */ 0, 180 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 181 /* highaddr */ BUS_SPACE_MAXADDR, 182 /* filter */ NULL, 183 /* filterarg */ NULL, 184 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 185 /* nsegments */ ~0, 186 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 187 /* flags */ 0, 188 /* lockfunc */ busdma_lock_mutex, 189 /* lockarg */ &Giant, 190 &adv_b->parent_dmat); 191 192 if (error != 0) { 193 printf("%s: Could not allocate DMA tag - error %d\n", 194 adv_name(adv_b), error); 195 adv_free(adv_b); 196 goto bad; 197 } 198 199 adv_b->init_level++; 200 201 /* FALLTHROUGH */ 202 case EISA_DEVICE_ID_ADVANSYS_740: 203 adv = adv_alloc(dev, rman_get_bustag(io), 204 rman_get_bushandle(io) + ADV_EISA_OFFSET_CHAN1); 205 if (adv == NULL) { 206 if (adv_b != NULL) 207 adv_free(adv_b); 208 goto bad; 209 } 210 211 /* 212 * Allocate a parent dmatag for all tags created 213 * by the MI portions of the advansys driver 214 */ 215 /* XXX Should be a child of the PCI bus dma tag */ 216 error = bus_dma_tag_create( 217 /* parent */ NULL, 218 /* alignment */ 1, 219 /* boundary */ 0, 220 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 221 /* highaddr */ BUS_SPACE_MAXADDR, 222 /* filter */ NULL, 223 /* filterarg */ NULL, 224 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 225 /* nsegments */ ~0, 226 /* maxsegsz */ ADV_EISA_MAX_DMA_COUNT, 227 /* flags */ 0, 228 /* lockfunc */ busdma_lock_mutex, 229 /* lockarg */ &Giant, 230 &adv->parent_dmat); 231 232 if (error != 0) { 233 printf("%s: Could not allocate DMA tag - error %d\n", 234 adv_name(adv), error); 235 adv_free(adv); 236 goto bad; 237 } 238 239 adv->init_level++; 240 break; 241 default: 242 printf("adveisaattach: Unknown device type!\n"); 243 goto bad; 244 break; 245 } 246 247 if (overrun_buf == NULL) { 248 /* Need to allocate our overrun buffer */ 249 if (bus_dma_tag_create( 250 /* parent */ adv->parent_dmat, 251 /* alignment */ 8, 252 /* boundary */ 0, 253 /* lowaddr */ ADV_EISA_MAX_DMA_ADDR, 254 /* highaddr */ BUS_SPACE_MAXADDR, 255 /* filter */ NULL, 256 /* filterarg */ NULL, 257 /* maxsize */ ADV_OVERRUN_BSIZE, 258 /* nsegments */ 1, 259 /* maxsegsz */ BUS_SPACE_MAXSIZE_32BIT, 260 /* flags */ 0, 261 /* lockfunc */ busdma_lock_mutex, 262 /* lockarg */ &Giant, 263 &overrun_dmat) != 0) { 264 adv_free(adv); 265 goto bad; 266 } 267 if (bus_dmamem_alloc(overrun_dmat, 268 (void **)&overrun_buf, 269 BUS_DMA_NOWAIT, 270 &overrun_dmamap) != 0) { 271 bus_dma_tag_destroy(overrun_dmat); 272 adv_free(adv); 273 goto bad; 274 } 275 /* And permanently map it in */ 276 bus_dmamap_load(overrun_dmat, overrun_dmamap, 277 overrun_buf, ADV_OVERRUN_BSIZE, 278 adv_map, &overrun_physbase, 279 /*flags*/0); 280 } 281 282 /* 283 * Now that we know we own the resources we need, do the 284 * card initialization. 285 */ 286 287 /* 288 * Stop the chip. 289 */ 290 ADV_OUTB(adv, ADV_CHIP_CTRL, ADV_CC_HALT); 291 ADV_OUTW(adv, ADV_CHIP_STATUS, 0); 292 293 adv->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 294 + ADV_CHIP_MIN_VER_EISA - 1; 295 296 if (adv_init(adv) != 0) { 297 adv_free(adv); 298 if (adv_b != NULL) 299 adv_free(adv_b); 300 return(-1); 301 } 302 303 adv->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 304 adv->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 305 306 if (adv_b != NULL) { 307 /* 308 * Stop the chip. 309 */ 310 ADV_OUTB(adv_b, ADV_CHIP_CTRL, ADV_CC_HALT); 311 ADV_OUTW(adv_b, ADV_CHIP_STATUS, 0); 312 313 adv_b->chip_version = EISA_REVISION_ID(eisa_get_id(dev)) 314 + ADV_CHIP_MIN_VER_EISA - 1; 315 316 if (adv_init(adv_b) != 0) { 317 adv_free(adv_b); 318 } else { 319 adv_b->max_dma_count = ADV_EISA_MAX_DMA_COUNT; 320 adv_b->max_dma_addr = ADV_EISA_MAX_DMA_ADDR; 321 } 322 } 323 324 /* 325 * Enable our interrupt handler. 326 */ 327 bus_setup_intr(dev, irq, INTR_TYPE_CAM|INTR_ENTROPY, adv_intr, adv, &ih); 328 329 /* Attach sub-devices - always succeeds */ 330 adv_attach(adv); 331 if (adv_b != NULL) 332 adv_attach(adv_b); 333 334 return 0; 335 336 bad: 337 bus_release_resource(dev, SYS_RES_IOPORT, 0, io); 338 bus_release_resource(dev, SYS_RES_IRQ, 0, irq); 339 return -1; 340} 341 342static device_method_t adv_eisa_methods[] = { 343 /* Device interface */ 344 DEVMETHOD(device_probe, adv_eisa_probe), 345 DEVMETHOD(device_attach, adv_eisa_attach), 346 { 0, 0 } 347}; 348 349static driver_t adv_eisa_driver = { 350 "adv", adv_eisa_methods, sizeof(struct adv_softc) 351}; 352 353static devclass_t adv_eisa_devclass; 354DRIVER_MODULE(adv, eisa, adv_eisa_driver, adv_eisa_devclass, 0, 0); 355