Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v3.6-rc7 446 lines 12 kB view raw
1#define AUTOSENSE 2#define PSEUDO_DMA 3 4/* 5 * Trantor T128/T128F/T228 driver 6 * Note : architecturally, the T100 and T130 are different and won't 7 * work 8 * 9 * Copyright 1993, Drew Eckhardt 10 * Visionary Computing 11 * (Unix and Linux consulting and custom programming) 12 * drew@colorado.edu 13 * +1 (303) 440-4894 14 * 15 * DISTRIBUTION RELEASE 3. 16 * 17 * For more information, please consult 18 * 19 * Trantor Systems, Ltd. 20 * T128/T128F/T228 SCSI Host Adapter 21 * Hardware Specifications 22 * 23 * Trantor Systems, Ltd. 24 * 5415 Randall Place 25 * Fremont, CA 94538 26 * 1+ (415) 770-1400, FAX 1+ (415) 770-9910 27 * 28 * and 29 * 30 * NCR 5380 Family 31 * SCSI Protocol Controller 32 * Databook 33 * 34 * NCR Microelectronics 35 * 1635 Aeroplaza Drive 36 * Colorado Springs, CO 80916 37 * 1+ (719) 578-3400 38 * 1+ (800) 334-5454 39 */ 40 41/* 42 * Options : 43 * AUTOSENSE - if defined, REQUEST SENSE will be performed automatically 44 * for commands that return with a CHECK CONDITION status. 45 * 46 * PSEUDO_DMA - enables PSEUDO-DMA hardware, should give a 3-4X performance 47 * increase compared to polled I/O. 48 * 49 * PARITY - enable parity checking. Not supported. 50 * 51 * SCSI2 - enable support for SCSI-II tagged queueing. Untested. 52 * 53 * 54 * UNSAFE - leave interrupts enabled during pseudo-DMA transfers. You 55 * only really want to use this if you're having a problem with 56 * dropped characters during high speed communications, and even 57 * then, you're going to be better off twiddling with transfersize. 58 * 59 * USLEEP - enable support for devices that don't disconnect. Untested. 60 * 61 * The card is detected and initialized in one of several ways : 62 * 1. Autoprobe (default) - since the board is memory mapped, 63 * a BIOS signature is scanned for to locate the registers. 64 * An interrupt is triggered to autoprobe for the interrupt 65 * line. 66 * 67 * 2. With command line overrides - t128=address,irq may be 68 * used on the LILO command line to override the defaults. 69 * 70 * 3. With the T128_OVERRIDE compile time define. This is 71 * specified as an array of address, irq tuples. Ie, for 72 * one board at the default 0xcc000 address, IRQ5, I could say 73 * -DT128_OVERRIDE={{0xcc000, 5}} 74 * 75 * Note that if the override methods are used, place holders must 76 * be specified for other boards in the system. 77 * 78 * T128/T128F jumper/dipswitch settings (note : on my sample, the switches 79 * were epoxy'd shut, meaning I couldn't change the 0xcc000 base address) : 80 * 81 * T128 Sw7 Sw8 Sw6 = 0ws Sw5 = boot 82 * T128F Sw6 Sw7 Sw5 = 0ws Sw4 = boot Sw8 = floppy disable 83 * cc000 off off 84 * c8000 off on 85 * dc000 on off 86 * d8000 on on 87 * 88 * 89 * Interrupts 90 * There is a 12 pin jumper block, jp1, numbered as follows : 91 * T128 (JP1) T128F (J5) 92 * 2 4 6 8 10 12 11 9 7 5 3 1 93 * 1 3 5 7 9 11 12 10 8 6 4 2 94 * 95 * 3 2-4 96 * 5 1-3 97 * 7 3-5 98 * T128F only 99 * 10 8-10 100 * 12 7-9 101 * 14 10-12 102 * 15 9-11 103 */ 104 105/* 106 * $Log: t128.c,v $ 107 */ 108 109#include <linux/signal.h> 110#include <linux/io.h> 111#include <linux/blkdev.h> 112#include <linux/interrupt.h> 113#include <linux/stat.h> 114#include <linux/init.h> 115#include <linux/module.h> 116#include <linux/delay.h> 117 118#include "scsi.h" 119#include <scsi/scsi_host.h> 120#include "t128.h" 121#define AUTOPROBE_IRQ 122#include "NCR5380.h" 123 124static struct override { 125 unsigned long address; 126 int irq; 127} overrides 128#ifdef T128_OVERRIDE 129 [] __initdata = T128_OVERRIDE; 130#else 131 [4] __initdata = {{0, IRQ_AUTO}, {0, IRQ_AUTO}, 132 {0 ,IRQ_AUTO}, {0, IRQ_AUTO}}; 133#endif 134 135#define NO_OVERRIDES ARRAY_SIZE(overrides) 136 137static struct base { 138 unsigned int address; 139 int noauto; 140} bases[] __initdata = { 141 { 0xcc000, 0}, { 0xc8000, 0}, { 0xdc000, 0}, { 0xd8000, 0} 142}; 143 144#define NO_BASES ARRAY_SIZE(bases) 145 146static struct signature { 147 const char *string; 148 int offset; 149} signatures[] __initdata = { 150{"TSROM: SCSI BIOS, Version 1.12", 0x36}, 151}; 152 153#define NO_SIGNATURES ARRAY_SIZE(signatures) 154 155/* 156 * Function : t128_setup(char *str, int *ints) 157 * 158 * Purpose : LILO command line initialization of the overrides array, 159 * 160 * Inputs : str - unused, ints - array of integer parameters with ints[0] 161 * equal to the number of ints. 162 * 163 */ 164 165void __init t128_setup(char *str, int *ints){ 166 static int commandline_current = 0; 167 int i; 168 if (ints[0] != 2) 169 printk("t128_setup : usage t128=address,irq\n"); 170 else 171 if (commandline_current < NO_OVERRIDES) { 172 overrides[commandline_current].address = ints[1]; 173 overrides[commandline_current].irq = ints[2]; 174 for (i = 0; i < NO_BASES; ++i) 175 if (bases[i].address == ints[1]) { 176 bases[i].noauto = 1; 177 break; 178 } 179 ++commandline_current; 180 } 181} 182 183/* 184 * Function : int t128_detect(struct scsi_host_template * tpnt) 185 * 186 * Purpose : detects and initializes T128,T128F, or T228 controllers 187 * that were autoprobed, overridden on the LILO command line, 188 * or specified at compile time. 189 * 190 * Inputs : tpnt - template for this SCSI adapter. 191 * 192 * Returns : 1 if a host adapter was found, 0 if not. 193 * 194 */ 195 196int __init t128_detect(struct scsi_host_template * tpnt){ 197 static int current_override = 0, current_base = 0; 198 struct Scsi_Host *instance; 199 unsigned long base; 200 void __iomem *p; 201 int sig, count; 202 203 tpnt->proc_name = "t128"; 204 tpnt->proc_info = &t128_proc_info; 205 206 for (count = 0; current_override < NO_OVERRIDES; ++current_override) { 207 base = 0; 208 p = NULL; 209 210 if (overrides[current_override].address) { 211 base = overrides[current_override].address; 212 p = ioremap(bases[current_base].address, 0x2000); 213 if (!p) 214 base = 0; 215 } else 216 for (; !base && (current_base < NO_BASES); ++current_base) { 217#if (TDEBUG & TDEBUG_INIT) 218 printk("scsi-t128 : probing address %08x\n", bases[current_base].address); 219#endif 220 if (bases[current_base].noauto) 221 continue; 222 p = ioremap(bases[current_base].address, 0x2000); 223 if (!p) 224 continue; 225 for (sig = 0; sig < NO_SIGNATURES; ++sig) 226 if (check_signature(p + signatures[sig].offset, 227 signatures[sig].string, 228 strlen(signatures[sig].string))) { 229 base = bases[current_base].address; 230#if (TDEBUG & TDEBUG_INIT) 231 printk("scsi-t128 : detected board.\n"); 232#endif 233 goto found; 234 } 235 iounmap(p); 236 } 237 238#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) 239 printk("scsi-t128 : base = %08x\n", (unsigned int) base); 240#endif 241 242 if (!base) 243 break; 244 245found: 246 instance = scsi_register (tpnt, sizeof(struct NCR5380_hostdata)); 247 if(instance == NULL) 248 break; 249 250 instance->base = base; 251 ((struct NCR5380_hostdata *)instance->hostdata)->base = p; 252 253 NCR5380_init(instance, 0); 254 255 if (overrides[current_override].irq != IRQ_AUTO) 256 instance->irq = overrides[current_override].irq; 257 else 258 instance->irq = NCR5380_probe_irq(instance, T128_IRQS); 259 260 if (instance->irq != SCSI_IRQ_NONE) 261 if (request_irq(instance->irq, t128_intr, IRQF_DISABLED, "t128", 262 instance)) { 263 printk("scsi%d : IRQ%d not free, interrupts disabled\n", 264 instance->host_no, instance->irq); 265 instance->irq = SCSI_IRQ_NONE; 266 } 267 268 if (instance->irq == SCSI_IRQ_NONE) { 269 printk("scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); 270 printk("scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); 271 } 272 273#if defined(TDEBUG) && (TDEBUG & TDEBUG_INIT) 274 printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); 275#endif 276 277 printk("scsi%d : at 0x%08lx", instance->host_no, instance->base); 278 if (instance->irq == SCSI_IRQ_NONE) 279 printk (" interrupts disabled"); 280 else 281 printk (" irq %d", instance->irq); 282 printk(" options CAN_QUEUE=%d CMD_PER_LUN=%d release=%d", 283 CAN_QUEUE, CMD_PER_LUN, T128_PUBLIC_RELEASE); 284 NCR5380_print_options(instance); 285 printk("\n"); 286 287 ++current_override; 288 ++count; 289 } 290 return count; 291} 292 293static int t128_release(struct Scsi_Host *shost) 294{ 295 NCR5380_local_declare(); 296 NCR5380_setup(shost); 297 if (shost->irq) 298 free_irq(shost->irq, shost); 299 NCR5380_exit(shost); 300 if (shost->io_port && shost->n_io_port) 301 release_region(shost->io_port, shost->n_io_port); 302 scsi_unregister(shost); 303 iounmap(base); 304 return 0; 305} 306 307/* 308 * Function : int t128_biosparam(Disk * disk, struct block_device *dev, int *ip) 309 * 310 * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 311 * the specified device / size. 312 * 313 * Inputs : size = size of device in sectors (512 bytes), dev = block device 314 * major / minor, ip[] = {heads, sectors, cylinders} 315 * 316 * Returns : always 0 (success), initializes ip 317 * 318 */ 319 320/* 321 * XXX Most SCSI boards use this mapping, I could be incorrect. Some one 322 * using hard disks on a trantor should verify that this mapping corresponds 323 * to that used by the BIOS / ASPI driver by running the linux fdisk program 324 * and matching the H_C_S coordinates to what DOS uses. 325 */ 326 327int t128_biosparam(struct scsi_device *sdev, struct block_device *bdev, 328 sector_t capacity, int * ip) 329{ 330 ip[0] = 64; 331 ip[1] = 32; 332 ip[2] = capacity >> 11; 333 return 0; 334} 335 336/* 337 * Function : int NCR5380_pread (struct Scsi_Host *instance, 338 * unsigned char *dst, int len) 339 * 340 * Purpose : Fast 5380 pseudo-dma read function, transfers len bytes to 341 * dst 342 * 343 * Inputs : dst = destination, len = length in bytes 344 * 345 * Returns : 0 on success, non zero on a failure such as a watchdog 346 * timeout. 347 */ 348 349static inline int NCR5380_pread (struct Scsi_Host *instance, unsigned char *dst, 350 int len) { 351 NCR5380_local_declare(); 352 void __iomem *reg; 353 unsigned char *d = dst; 354 register int i = len; 355 356 NCR5380_setup(instance); 357 reg = base + T_DATA_REG_OFFSET; 358 359#if 0 360 for (; i; --i) { 361 while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); 362#else 363 while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); 364 for (; i; --i) { 365#endif 366 *d++ = readb(reg); 367 } 368 369 if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { 370 unsigned char tmp; 371 void __iomem *foo = base + T_CONTROL_REG_OFFSET; 372 tmp = readb(foo); 373 writeb(tmp | T_CR_CT, foo); 374 writeb(tmp, foo); 375 printk("scsi%d : watchdog timer fired in NCR5380_pread()\n", 376 instance->host_no); 377 return -1; 378 } else 379 return 0; 380} 381 382/* 383 * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 384 * unsigned char *src, int len) 385 * 386 * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from 387 * src 388 * 389 * Inputs : src = source, len = length in bytes 390 * 391 * Returns : 0 on success, non zero on a failure such as a watchdog 392 * timeout. 393 */ 394 395static inline int NCR5380_pwrite (struct Scsi_Host *instance, unsigned char *src, 396 int len) { 397 NCR5380_local_declare(); 398 void __iomem *reg; 399 unsigned char *s = src; 400 register int i = len; 401 402 NCR5380_setup(instance); 403 reg = base + T_DATA_REG_OFFSET; 404 405#if 0 406 for (; i; --i) { 407 while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); 408#else 409 while (!(readb(base+T_STATUS_REG_OFFSET) & T_ST_RDY)) barrier(); 410 for (; i; --i) { 411#endif 412 writeb(*s++, reg); 413 } 414 415 if (readb(base + T_STATUS_REG_OFFSET) & T_ST_TIM) { 416 unsigned char tmp; 417 void __iomem *foo = base + T_CONTROL_REG_OFFSET; 418 tmp = readb(foo); 419 writeb(tmp | T_CR_CT, foo); 420 writeb(tmp, foo); 421 printk("scsi%d : watchdog timer fired in NCR5380_pwrite()\n", 422 instance->host_no); 423 return -1; 424 } else 425 return 0; 426} 427 428MODULE_LICENSE("GPL"); 429 430#include "NCR5380.c" 431 432static struct scsi_host_template driver_template = { 433 .name = "Trantor T128/T128F/T228", 434 .detect = t128_detect, 435 .release = t128_release, 436 .queuecommand = t128_queue_command, 437 .eh_abort_handler = t128_abort, 438 .eh_bus_reset_handler = t128_bus_reset, 439 .bios_param = t128_biosparam, 440 .can_queue = CAN_QUEUE, 441 .this_id = 7, 442 .sg_tablesize = SG_ALL, 443 .cmd_per_lun = CMD_PER_LUN, 444 .use_clustering = DISABLE_CLUSTERING, 445}; 446#include "scsi_module.c"