1 2#define PSEUDO_DMA 3#define DONT_USE_INTR 4#define UNSAFE /* Leave interrupts enabled during pseudo-dma I/O */ 5#define DMA_WORKS_RIGHT 6 7 8/* 9 * DTC 3180/3280 driver, by 10 * Ray Van Tassle rayvt@comm.mot.com 11 * 12 * taken from ... 13 * Trantor T128/T128F/T228 driver by... 14 * 15 * Drew Eckhardt 16 * Visionary Computing 17 * (Unix and Linux consulting and custom programming) 18 * drew@colorado.edu 19 * +1 (303) 440-4894 20 */ 21 22/* 23 * The card is detected and initialized in one of several ways : 24 * 1. Autoprobe (default) - since the board is memory mapped, 25 * a BIOS signature is scanned for to locate the registers. 26 * An interrupt is triggered to autoprobe for the interrupt 27 * line. 28 * 29 * 2. With command line overrides - dtc=address,irq may be 30 * used on the LILO command line to override the defaults. 31 * 32*/ 33 34/*----------------------------------------------------------------*/ 35/* the following will set the monitor border color (useful to find 36 where something crashed or gets stuck at */ 37/* 1 = blue 38 2 = green 39 3 = cyan 40 4 = red 41 5 = magenta 42 6 = yellow 43 7 = white 44*/ 45#if 0 46#define rtrc(i) {inb(0x3da); outb(0x31, 0x3c0); outb((i), 0x3c0);} 47#else 48#define rtrc(i) {} 49#endif 50 51 52#include <linux/module.h> 53#include <linux/signal.h> 54#include <linux/blkdev.h> 55#include <linux/delay.h> 56#include <linux/stat.h> 57#include <linux/string.h> 58#include <linux/init.h> 59#include <linux/interrupt.h> 60#include <linux/io.h> 61#include <scsi/scsi_host.h> 62#include "dtc.h" 63#define AUTOPROBE_IRQ 64#include "NCR5380.h" 65 66/* 67 * The DTC3180 & 3280 boards are memory mapped. 68 * 69 */ 70 71/* 72 */ 73/* Offset from DTC_5380_OFFSET */ 74#define DTC_CONTROL_REG 0x100 /* rw */ 75#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ 76#define CSR_DIR_READ 0x40 /* rw direction, 1 = read 0 = write */ 77 78#define CSR_RESET 0x80 /* wo Resets 53c400 */ 79#define CSR_5380_REG 0x80 /* ro 5380 registers can be accessed */ 80#define CSR_TRANS_DIR 0x40 /* rw Data transfer direction */ 81#define CSR_SCSI_BUFF_INTR 0x20 /* rw Enable int on transfer ready */ 82#define CSR_5380_INTR 0x10 /* rw Enable 5380 interrupts */ 83#define CSR_SHARED_INTR 0x08 /* rw Interrupt sharing */ 84#define CSR_HOST_BUF_NOT_RDY 0x04 /* ro Host buffer not ready */ 85#define CSR_SCSI_BUF_RDY 0x02 /* ro SCSI buffer ready */ 86#define CSR_GATED_5380_IRQ 0x01 /* ro Last block xferred */ 87#define CSR_INT_BASE (CSR_SCSI_BUFF_INTR | CSR_5380_INTR) 88 89 90#define DTC_BLK_CNT 0x101 /* rw 91 * # of 128-byte blocks to transfer */ 92 93 94#define D_CR_ACCESS 0x80 /* ro set=can access 3280 registers */ 95 96#define DTC_SWITCH_REG 0x3982 /* ro - DIP switches */ 97#define DTC_RESUME_XFER 0x3982 /* wo - resume data xfer 98 * after disconnect/reconnect*/ 99 100#define DTC_5380_OFFSET 0x3880 /* 8 registers here, see NCR5380.h */ 101 102/*!!!! for dtc, it's a 128 byte buffer at 3900 !!! */ 103#define DTC_DATA_BUF 0x3900 /* rw 128 bytes long */ 104 105static struct override { 106 unsigned int address; 107 int irq; 108} overrides 109#ifdef OVERRIDE 110[] __initdata = OVERRIDE; 111#else 112[4] __initdata = { 113 { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO }, { 0, IRQ_AUTO } 114}; 115#endif 116 117#define NO_OVERRIDES ARRAY_SIZE(overrides) 118 119static struct base { 120 unsigned long address; 121 int noauto; 122} bases[] __initdata = { 123 { 0xcc000, 0 }, 124 { 0xc8000, 0 }, 125 { 0xdc000, 0 }, 126 { 0xd8000, 0 } 127}; 128 129#define NO_BASES ARRAY_SIZE(bases) 130 131static const struct signature { 132 const char *string; 133 int offset; 134} signatures[] = { 135 {"DATA TECHNOLOGY CORPORATION BIOS", 0x25}, 136}; 137 138#define NO_SIGNATURES ARRAY_SIZE(signatures) 139 140#ifndef MODULE 141/* 142 * Function : dtc_setup(char *str, int *ints) 143 * 144 * Purpose : LILO command line initialization of the overrides array, 145 * 146 * Inputs : str - unused, ints - array of integer parameters with ints[0] 147 * equal to the number of ints. 148 * 149 */ 150 151static int __init dtc_setup(char *str) 152{ 153 static int commandline_current = 0; 154 int i; 155 int ints[10]; 156 157 get_options(str, ARRAY_SIZE(ints), ints); 158 if (ints[0] != 2) 159 printk("dtc_setup: usage dtc=address,irq\n"); 160 else if (commandline_current < NO_OVERRIDES) { 161 overrides[commandline_current].address = ints[1]; 162 overrides[commandline_current].irq = ints[2]; 163 for (i = 0; i < NO_BASES; ++i) 164 if (bases[i].address == ints[1]) { 165 bases[i].noauto = 1; 166 break; 167 } 168 ++commandline_current; 169 } 170 return 1; 171} 172 173__setup("dtc=", dtc_setup); 174#endif 175 176/* 177 * Function : int dtc_detect(struct scsi_host_template * tpnt) 178 * 179 * Purpose : detects and initializes DTC 3180/3280 controllers 180 * that were autoprobed, overridden on the LILO command line, 181 * or specified at compile time. 182 * 183 * Inputs : tpnt - template for this SCSI adapter. 184 * 185 * Returns : 1 if a host adapter was found, 0 if not. 186 * 187*/ 188 189static int __init dtc_detect(struct scsi_host_template * tpnt) 190{ 191 static int current_override = 0, current_base = 0; 192 struct Scsi_Host *instance; 193 unsigned int addr; 194 void __iomem *base; 195 int sig, count; 196 197 for (count = 0; current_override < NO_OVERRIDES; ++current_override) { 198 addr = 0; 199 base = NULL; 200 201 if (overrides[current_override].address) { 202 addr = overrides[current_override].address; 203 base = ioremap(addr, 0x2000); 204 if (!base) 205 addr = 0; 206 } else 207 for (; !addr && (current_base < NO_BASES); ++current_base) { 208#if (DTCDEBUG & DTCDEBUG_INIT) 209 printk(KERN_DEBUG "scsi-dtc : probing address %08x\n", bases[current_base].address); 210#endif 211 if (bases[current_base].noauto) 212 continue; 213 base = ioremap(bases[current_base].address, 0x2000); 214 if (!base) 215 continue; 216 for (sig = 0; sig < NO_SIGNATURES; ++sig) { 217 if (check_signature(base + signatures[sig].offset, signatures[sig].string, strlen(signatures[sig].string))) { 218 addr = bases[current_base].address; 219#if (DTCDEBUG & DTCDEBUG_INIT) 220 printk(KERN_DEBUG "scsi-dtc : detected board.\n"); 221#endif 222 goto found; 223 } 224 } 225 iounmap(base); 226 } 227 228#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) 229 printk(KERN_DEBUG "scsi-dtc : base = %08x\n", addr); 230#endif 231 232 if (!addr) 233 break; 234 235found: 236 instance = scsi_register(tpnt, sizeof(struct NCR5380_hostdata)); 237 if (instance == NULL) 238 break; 239 240 instance->base = addr; 241 ((struct NCR5380_hostdata *)(instance)->hostdata)->base = base; 242 243 NCR5380_init(instance, 0); 244 245 NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); /* Enable int's */ 246 if (overrides[current_override].irq != IRQ_AUTO) 247 instance->irq = overrides[current_override].irq; 248 else 249 instance->irq = NCR5380_probe_irq(instance, DTC_IRQS); 250 251 /* Compatibility with documented NCR5380 kernel parameters */ 252 if (instance->irq == 255) 253 instance->irq = NO_IRQ; 254 255#ifndef DONT_USE_INTR 256 /* With interrupts enabled, it will sometimes hang when doing heavy 257 * reads. So better not enable them until I finger it out. */ 258 if (instance->irq != NO_IRQ) 259 if (request_irq(instance->irq, dtc_intr, 0, 260 "dtc", instance)) { 261 printk(KERN_ERR "scsi%d : IRQ%d not free, interrupts disabled\n", instance->host_no, instance->irq); 262 instance->irq = NO_IRQ; 263 } 264 265 if (instance->irq == NO_IRQ) { 266 printk(KERN_WARNING "scsi%d : interrupts not enabled. for better interactive performance,\n", instance->host_no); 267 printk(KERN_WARNING "scsi%d : please jumper the board for a free IRQ.\n", instance->host_no); 268 } 269#else 270 if (instance->irq != NO_IRQ) 271 printk(KERN_WARNING "scsi%d : interrupts not used. Might as well not jumper it.\n", instance->host_no); 272 instance->irq = NO_IRQ; 273#endif 274#if defined(DTCDEBUG) && (DTCDEBUG & DTCDEBUG_INIT) 275 printk("scsi%d : irq = %d\n", instance->host_no, instance->irq); 276#endif 277 278 ++current_override; 279 ++count; 280 } 281 return count; 282} 283 284/* 285 * Function : int dtc_biosparam(Disk * disk, struct block_device *dev, int *ip) 286 * 287 * Purpose : Generates a BIOS / DOS compatible H-C-S mapping for 288 * the specified device / size. 289 * 290 * Inputs : size = size of device in sectors (512 bytes), dev = block device 291 * major / minor, ip[] = {heads, sectors, cylinders} 292 * 293 * Returns : always 0 (success), initializes ip 294 * 295*/ 296 297/* 298 * XXX Most SCSI boards use this mapping, I could be incorrect. Some one 299 * using hard disks on a trantor should verify that this mapping corresponds 300 * to that used by the BIOS / ASPI driver by running the linux fdisk program 301 * and matching the H_C_S coordinates to what DOS uses. 302*/ 303 304static int dtc_biosparam(struct scsi_device *sdev, struct block_device *dev, 305 sector_t capacity, int *ip) 306{ 307 int size = capacity; 308 309 ip[0] = 64; 310 ip[1] = 32; 311 ip[2] = size >> 11; 312 return 0; 313} 314 315 316/**************************************************************** 317 * Function : int NCR5380_pread (struct Scsi_Host *instance, 318 * unsigned char *dst, int len) 319 * 320 * Purpose : Fast 5380 pseudo-dma read function, reads len bytes to 321 * dst 322 * 323 * Inputs : dst = destination, len = length in bytes 324 * 325 * Returns : 0 on success, non zero on a failure such as a watchdog 326 * timeout. 327*/ 328 329static inline int NCR5380_pread(struct Scsi_Host *instance, unsigned char *dst, int len) 330{ 331 unsigned char *d = dst; 332 int i; /* For counting time spent in the poll-loop */ 333 struct NCR5380_hostdata *hostdata = shost_priv(instance); 334 NCR5380_local_declare(); 335 NCR5380_setup(instance); 336 337 i = 0; 338 NCR5380_read(RESET_PARITY_INTERRUPT_REG); 339 NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); 340 if (instance->irq == NO_IRQ) 341 NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ); 342 else 343 NCR5380_write(DTC_CONTROL_REG, CSR_DIR_READ | CSR_INT_BASE); 344 NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ 345 rtrc(1); 346 while (len > 0) { 347 rtrc(2); 348 while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) 349 ++i; 350 rtrc(3); 351 memcpy_fromio(d, base + DTC_DATA_BUF, 128); 352 d += 128; 353 len -= 128; 354 rtrc(7); 355 /*** with int's on, it sometimes hangs after here. 356 * Looks like something makes HBNR go away. */ 357 } 358 rtrc(4); 359 while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) 360 ++i; 361 NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ 362 rtrc(0); 363 NCR5380_read(RESET_PARITY_INTERRUPT_REG); 364 if (i > hostdata->spin_max_r) 365 hostdata->spin_max_r = i; 366 return (0); 367} 368 369/**************************************************************** 370 * Function : int NCR5380_pwrite (struct Scsi_Host *instance, 371 * unsigned char *src, int len) 372 * 373 * Purpose : Fast 5380 pseudo-dma write function, transfers len bytes from 374 * src 375 * 376 * Inputs : src = source, len = length in bytes 377 * 378 * Returns : 0 on success, non zero on a failure such as a watchdog 379 * timeout. 380*/ 381 382static inline int NCR5380_pwrite(struct Scsi_Host *instance, unsigned char *src, int len) 383{ 384 int i; 385 struct NCR5380_hostdata *hostdata = shost_priv(instance); 386 NCR5380_local_declare(); 387 NCR5380_setup(instance); 388 389 NCR5380_read(RESET_PARITY_INTERRUPT_REG); 390 NCR5380_write(MODE_REG, MR_ENABLE_EOP_INTR | MR_DMA_MODE); 391 /* set direction (write) */ 392 if (instance->irq == NO_IRQ) 393 NCR5380_write(DTC_CONTROL_REG, 0); 394 else 395 NCR5380_write(DTC_CONTROL_REG, CSR_5380_INTR); 396 NCR5380_write(DTC_BLK_CNT, len >> 7); /* Block count */ 397 for (i = 0; len > 0; ++i) { 398 rtrc(5); 399 /* Poll until the host buffer can accept data. */ 400 while (NCR5380_read(DTC_CONTROL_REG) & CSR_HOST_BUF_NOT_RDY) 401 ++i; 402 rtrc(3); 403 memcpy_toio(base + DTC_DATA_BUF, src, 128); 404 src += 128; 405 len -= 128; 406 } 407 rtrc(4); 408 while (!(NCR5380_read(DTC_CONTROL_REG) & D_CR_ACCESS)) 409 ++i; 410 rtrc(6); 411 /* Wait until the last byte has been sent to the disk */ 412 while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT)) 413 ++i; 414 rtrc(7); 415 /* Check for parity error here. fixme. */ 416 NCR5380_write(MODE_REG, 0); /* Clear the operating mode */ 417 rtrc(0); 418 if (i > hostdata->spin_max_w) 419 hostdata->spin_max_w = i; 420 return (0); 421} 422 423MODULE_LICENSE("GPL"); 424 425#include "NCR5380.c" 426 427static int dtc_release(struct Scsi_Host *shost) 428{ 429 NCR5380_local_declare(); 430 NCR5380_setup(shost); 431 if (shost->irq != NO_IRQ) 432 free_irq(shost->irq, shost); 433 NCR5380_exit(shost); 434 if (shost->io_port && shost->n_io_port) 435 release_region(shost->io_port, shost->n_io_port); 436 scsi_unregister(shost); 437 iounmap(base); 438 return 0; 439} 440 441static struct scsi_host_template driver_template = { 442 .name = "DTC 3180/3280 ", 443 .detect = dtc_detect, 444 .release = dtc_release, 445 .proc_name = "dtc3x80", 446 .show_info = dtc_show_info, 447 .write_info = dtc_write_info, 448 .info = dtc_info, 449 .queuecommand = dtc_queue_command, 450 .eh_abort_handler = dtc_abort, 451 .eh_bus_reset_handler = dtc_bus_reset, 452 .bios_param = dtc_biosparam, 453 .can_queue = CAN_QUEUE, 454 .this_id = 7, 455 .sg_tablesize = SG_ALL, 456 .cmd_per_lun = CMD_PER_LUN, 457 .use_clustering = DISABLE_CLUSTERING, 458}; 459#include "scsi_module.c" 460