|
|
1.1 ! root 1: /* ! 2: * NCR53c406.c ! 3: * Low-level SCSI driver for NCR53c406a chip. ! 4: * Copyright (C) 1994, 1995, 1996 Normunds Saumanis ([email protected]) ! 5: * ! 6: * LILO command line usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]] ! 7: * Specify IRQ = 0 for non-interrupt driven mode. ! 8: * FASTPIO = 1 for fast pio mode, 0 for slow mode. ! 9: * ! 10: * This program is free software; you can redistribute it and/or modify it ! 11: * under the terms of the GNU General Public License as published by the ! 12: * Free Software Foundation; either version 2, or (at your option) any ! 13: * later version. ! 14: * ! 15: * This program is distributed in the hope that it will be useful, but ! 16: * WITHOUT ANY WARRANTY; without even the implied warranty of ! 17: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 18: * General Public License for more details. ! 19: * ! 20: */ ! 21: ! 22: #define NCR53C406A_DEBUG 0 ! 23: #define VERBOSE_NCR53C406A_DEBUG 0 ! 24: ! 25: /* Set this to 1 for PIO mode (recommended) or to 0 for DMA mode */ ! 26: #define USE_PIO 1 ! 27: ! 28: #define USE_BIOS 0 ! 29: /* #define BIOS_ADDR 0xD8000 */ /* define this if autoprobe fails */ ! 30: /* #define PORT_BASE 0x330 */ /* define this if autoprobe fails */ ! 31: /* #define IRQ_LEV 0 */ /* define this if autoprobe fails */ ! 32: #define DMA_CHAN 5 /* this is ignored if DMA is disabled */ ! 33: ! 34: /* Set this to 0 if you encounter kernel lockups while transferring ! 35: * data in PIO mode */ ! 36: #define USE_FAST_PIO 1 ! 37: ! 38: /* ============= End of user configurable parameters ============= */ ! 39: ! 40: #include <linux/module.h> ! 41: ! 42: #include <linux/errno.h> ! 43: #include <linux/ioport.h> ! 44: #include <linux/sched.h> ! 45: #include <linux/interrupt.h> ! 46: #include <linux/proc_fs.h> ! 47: #include <linux/stat.h> ! 48: #include <asm/io.h> ! 49: #include <asm/dma.h> ! 50: #include <asm/bitops.h> ! 51: #include <asm/irq.h> ! 52: ! 53: #include <linux/blk.h> ! 54: #include "scsi.h" ! 55: #include "hosts.h" ! 56: #include "sd.h" ! 57: ! 58: #include "NCR53c406a.h" ! 59: ! 60: /* ============================================================= */ ! 61: ! 62: #define WATCHDOG 5000000 ! 63: ! 64: #define SYNC_MODE 0 /* Synchronous transfer mode */ ! 65: ! 66: #if DEBUG ! 67: #undef NCR53C406A_DEBUG ! 68: #define NCR53C406A_DEBUG 1 ! 69: #endif ! 70: ! 71: #if USE_PIO ! 72: #define USE_DMA 0 ! 73: #else ! 74: #define USE_DMA 1 ! 75: #endif ! 76: ! 77: /* Default configuration */ ! 78: #define C1_IMG 0x07 /* ID=7 */ ! 79: #define C2_IMG 0x48 /* FE SCSI2 */ ! 80: #if USE_DMA ! 81: #define C3_IMG 0x21 /* CDB TE */ ! 82: #else ! 83: #define C3_IMG 0x20 /* CDB */ ! 84: #endif ! 85: #define C4_IMG 0x04 /* ANE */ ! 86: #define C5_IMG 0xb6 /* AA PI SIE POL */ ! 87: ! 88: #define REG0 (outb(C4_IMG, CONFIG4)) ! 89: #define REG1 (outb(C5_IMG, CONFIG5)) ! 90: ! 91: #if NCR53C406A_DEBUG ! 92: #define DEB(x) x ! 93: #else ! 94: #define DEB(x) ! 95: #endif ! 96: ! 97: #if VERBOSE_NCR53C406A_DEBUG ! 98: #define VDEB(x) x ! 99: #else ! 100: #define VDEB(x) ! 101: #endif ! 102: ! 103: #define LOAD_DMA_COUNT(count) \ ! 104: outb(count & 0xff, TC_LSB); \ ! 105: outb((count >> 8) & 0xff, TC_MSB); \ ! 106: outb((count >> 16) & 0xff, TC_HIGH); ! 107: ! 108: /* Chip commands */ ! 109: #define DMA_OP 0x80 ! 110: ! 111: #define SCSI_NOP 0x00 ! 112: #define FLUSH_FIFO 0x01 ! 113: #define CHIP_RESET 0x02 ! 114: #define SCSI_RESET 0x03 ! 115: #define RESELECT 0x40 ! 116: #define SELECT_NO_ATN 0x41 ! 117: #define SELECT_ATN 0x42 ! 118: #define SELECT_ATN_STOP 0x43 ! 119: #define ENABLE_SEL 0x44 ! 120: #define DISABLE_SEL 0x45 ! 121: #define SELECT_ATN3 0x46 ! 122: #define RESELECT3 0x47 ! 123: #define TRANSFER_INFO 0x10 ! 124: #define INIT_CMD_COMPLETE 0x11 ! 125: #define MSG_ACCEPT 0x12 ! 126: #define TRANSFER_PAD 0x18 ! 127: #define SET_ATN 0x1a ! 128: #define RESET_ATN 0x1b ! 129: #define SEND_MSG 0x20 ! 130: #define SEND_STATUS 0x21 ! 131: #define SEND_DATA 0x22 ! 132: #define DISCONN_SEQ 0x23 ! 133: #define TERMINATE_SEQ 0x24 ! 134: #define TARG_CMD_COMPLETE 0x25 ! 135: #define DISCONN 0x27 ! 136: #define RECV_MSG 0x28 ! 137: #define RECV_CMD 0x29 ! 138: #define RECV_DATA 0x2a ! 139: #define RECV_CMD_SEQ 0x2b ! 140: #define TARGET_ABORT_DMA 0x04 ! 141: ! 142: /*----------------------------------------------------------------*/ ! 143: /* the following will set the monitor border color (useful to find ! 144: where something crashed or gets stuck at */ ! 145: /* 1 = blue ! 146: 2 = green ! 147: 3 = cyan ! 148: 4 = red ! 149: 5 = magenta ! 150: 6 = yellow ! 151: 7 = white ! 152: */ ! 153: ! 154: #if NCR53C406A_DEBUG ! 155: #define rtrc(i) {inb(0x3da);outb(0x31,0x3c0);outb((i),0x3c0);} ! 156: #else ! 157: #define rtrc(i) {} ! 158: #endif ! 159: /*----------------------------------------------------------------*/ ! 160: ! 161: enum Phase { ! 162: idle, ! 163: data_out, ! 164: data_in, ! 165: command_ph, ! 166: status_ph, ! 167: message_out, ! 168: message_in ! 169: }; ! 170: ! 171: /* Static function prototypes */ ! 172: static void NCR53c406a_intr(int, void *, struct pt_regs *); ! 173: static void internal_done(Scsi_Cmnd *); ! 174: static void wait_intr(void); ! 175: static void chip_init(void); ! 176: static void calc_port_addr(void); ! 177: #ifndef IRQ_LEV ! 178: static int irq_probe(void); ! 179: #endif ! 180: ! 181: /* ================================================================= */ ! 182: ! 183: #if USE_BIOS ! 184: static void *bios_base = (void *)0; ! 185: #endif ! 186: ! 187: #if PORT_BASE ! 188: static int port_base = PORT_BASE; ! 189: #else ! 190: static int port_base = 0; ! 191: #endif ! 192: ! 193: #if IRQ_LEV ! 194: static int irq_level = IRQ_LEV; ! 195: #else ! 196: static int irq_level = -1; /* 0 is 'no irq', so use -1 for 'uninitialized'*/ ! 197: #endif ! 198: ! 199: #if USE_DMA ! 200: static int dma_chan = 0; ! 201: #endif ! 202: ! 203: #if USE_PIO ! 204: static int fast_pio = USE_FAST_PIO; ! 205: #endif ! 206: ! 207: static Scsi_Cmnd *current_SC = NULL; ! 208: static volatile int internal_done_flag = 0; ! 209: static volatile int internal_done_errcode = 0; ! 210: static char info_msg[256]; ! 211: ! 212: struct proc_dir_entry proc_scsi_NCR53c406a = { ! 213: PROC_SCSI_NCR53C406A, 7, "NCR53c406a", ! 214: S_IFDIR | S_IRUGO | S_IXUGO, 2 ! 215: }; ! 216: /* ================================================================= */ ! 217: ! 218: /* possible BIOS locations */ ! 219: #if USE_BIOS ! 220: static void *addresses[] = { ! 221: (void *)0xd8000, ! 222: (void *)0xc8000 ! 223: }; ! 224: #define ADDRESS_COUNT (sizeof( addresses ) / sizeof( unsigned )) ! 225: #endif USE_BIOS ! 226: ! 227: /* possible i/o port addresses */ ! 228: static unsigned short ports[] = { 0x230, 0x330 }; ! 229: #define PORT_COUNT (sizeof( ports ) / sizeof( unsigned short )) ! 230: ! 231: /* possible interrupt channels */ ! 232: static unsigned short intrs[] = { 10, 11, 12, 15 }; ! 233: #define INTR_COUNT (sizeof( intrs ) / sizeof( unsigned short )) ! 234: ! 235: /* signatures for NCR 53c406a based controllers */ ! 236: #if USE_BIOS ! 237: struct signature { ! 238: char *signature; ! 239: int sig_offset; ! 240: int sig_length; ! 241: } signatures[] = { ! 242: /* 1 2 3 4 5 6 */ ! 243: /* 123456789012345678901234567890123456789012345678901234567890 */ ! 244: { "Copyright (C) Acculogic, Inc.\r\n2.8M Diskette Extension Bios ver 4.04.03 03/01/1993", 61, 82 }, ! 245: }; ! 246: #define SIGNATURE_COUNT (sizeof( signatures ) / sizeof( struct signature )) ! 247: #endif USE_BIOS ! 248: ! 249: /* ============================================================ */ ! 250: ! 251: /* Control Register Set 0 */ ! 252: static int TC_LSB; /* transfer counter lsb */ ! 253: static int TC_MSB; /* transfer counter msb */ ! 254: static int SCSI_FIFO; /* scsi fifo register */ ! 255: static int CMD_REG; /* command register */ ! 256: static int STAT_REG; /* status register */ ! 257: static int DEST_ID; /* selection/reselection bus id */ ! 258: static int INT_REG; /* interrupt status register */ ! 259: static int SRTIMOUT; /* select/reselect timeout reg */ ! 260: static int SEQ_REG; /* sequence step register */ ! 261: static int SYNCPRD; /* synchronous transfer period */ ! 262: static int FIFO_FLAGS; /* indicates # of bytes in fifo */ ! 263: static int SYNCOFF; /* synchronous offset register */ ! 264: static int CONFIG1; /* configuration register */ ! 265: static int CLKCONV; /* clock conversion reg */ ! 266: /*static int TESTREG;*/ /* test mode register */ ! 267: static int CONFIG2; /* Configuration 2 Register */ ! 268: static int CONFIG3; /* Configuration 3 Register */ ! 269: static int CONFIG4; /* Configuration 4 Register */ ! 270: static int TC_HIGH; /* Transfer Counter High */ ! 271: /*static int FIFO_BOTTOM;*/ /* Reserve FIFO byte register */ ! 272: ! 273: /* Control Register Set 1 */ ! 274: /*static int JUMPER_SENSE;*/ /* Jumper sense port reg (r/w) */ ! 275: /*static int SRAM_PTR;*/ /* SRAM address pointer reg (r/w) */ ! 276: /*static int SRAM_DATA;*/ /* SRAM data register (r/w) */ ! 277: static int PIO_FIFO; /* PIO FIFO registers (r/w) */ ! 278: /*static int PIO_FIFO1;*/ /* */ ! 279: /*static int PIO_FIFO2;*/ /* */ ! 280: /*static int PIO_FIFO3;*/ /* */ ! 281: static int PIO_STATUS; /* PIO status (r/w) */ ! 282: /*static int ATA_CMD;*/ /* ATA command/status reg (r/w) */ ! 283: /*static int ATA_ERR;*/ /* ATA features/error register (r/w)*/ ! 284: static int PIO_FLAG; /* PIO flag interrupt enable (r/w) */ ! 285: static int CONFIG5; /* Configuration 5 register (r/w) */ ! 286: /*static int SIGNATURE;*/ /* Signature Register (r) */ ! 287: /*static int CONFIG6;*/ /* Configuration 6 register (r) */ ! 288: ! 289: /* ============================================================== */ ! 290: ! 291: #if USE_DMA ! 292: static __inline__ int ! 293: NCR53c406a_dma_setup (unsigned char *ptr, ! 294: unsigned int count, ! 295: unsigned char mode) { ! 296: unsigned limit; ! 297: unsigned long flags = 0; ! 298: ! 299: VDEB(printk("dma: before count=%d ", count)); ! 300: if (dma_chan <=3) { ! 301: if (count > 65536) ! 302: count = 65536; ! 303: limit = 65536 - (((unsigned) ptr) & 0xFFFF); ! 304: } else { ! 305: if (count > (65536<<1)) ! 306: count = (65536<<1); ! 307: limit = (65536<<1) - (((unsigned) ptr) & 0x1FFFF); ! 308: } ! 309: ! 310: if (count > limit) count = limit; ! 311: ! 312: VDEB(printk("after count=%d\n", count)); ! 313: if ((count & 1) || (((unsigned) ptr) & 1)) ! 314: panic ("NCR53c406a: attempted unaligned DMA transfer\n"); ! 315: ! 316: save_flags(flags); ! 317: cli(); ! 318: disable_dma(dma_chan); ! 319: clear_dma_ff(dma_chan); ! 320: set_dma_addr(dma_chan, (long) ptr); ! 321: set_dma_count(dma_chan, count); ! 322: set_dma_mode(dma_chan, mode); ! 323: enable_dma(dma_chan); ! 324: restore_flags(flags); ! 325: ! 326: return count; ! 327: } ! 328: ! 329: static __inline__ int ! 330: NCR53c406a_dma_write(unsigned char *src, unsigned int count) { ! 331: return NCR53c406a_dma_setup (src, count, DMA_MODE_WRITE); ! 332: } ! 333: ! 334: static __inline__ int ! 335: NCR53c406a_dma_read(unsigned char *src, unsigned int count) { ! 336: return NCR53c406a_dma_setup (src, count, DMA_MODE_READ); ! 337: } ! 338: ! 339: static __inline__ int ! 340: NCR53c406a_dma_residual (void) { ! 341: register int tmp; ! 342: unsigned long flags = 0; ! 343: save_flags(flags); ! 344: cli(); ! 345: clear_dma_ff(dma_chan); ! 346: tmp = get_dma_residue(dma_chan); ! 347: restore_flags(flags); ! 348: ! 349: return tmp; ! 350: } ! 351: #endif USE_DMA ! 352: ! 353: #if USE_PIO ! 354: static __inline__ int NCR53c406a_pio_read(unsigned char *request, ! 355: unsigned int reqlen) ! 356: { ! 357: int i; ! 358: int len; /* current scsi fifo size */ ! 359: unsigned long flags = 0; ! 360: ! 361: REG1; ! 362: while (reqlen) { ! 363: i = inb(PIO_STATUS); ! 364: /* VDEB(printk("pio_status=%x\n", i)); */ ! 365: if (i & 0x80) ! 366: return 0; ! 367: ! 368: switch( i & 0x1e ) { ! 369: default: ! 370: case 0x10: ! 371: len=0; break; ! 372: case 0x0: ! 373: len=1; break; ! 374: case 0x8: ! 375: len=42; break; ! 376: case 0xc: ! 377: len=84; break; ! 378: case 0xe: ! 379: len=128; break; ! 380: } ! 381: ! 382: if ((i & 0x40) && len == 0) { /* fifo empty and interrupt occurred */ ! 383: return 0; ! 384: } ! 385: ! 386: if (len) { ! 387: if( len > reqlen ) ! 388: len = reqlen; ! 389: ! 390: save_flags(flags); ! 391: cli(); ! 392: if( fast_pio && len > 3 ) { ! 393: insl(PIO_FIFO,request,len>>2); ! 394: request += len & 0xfc; ! 395: reqlen -= len & 0xfc; ! 396: } ! 397: else { ! 398: while(len--) { ! 399: *request++ = inb(PIO_FIFO); ! 400: reqlen--; ! 401: } ! 402: } ! 403: restore_flags(flags); ! 404: } ! 405: } ! 406: return 0; ! 407: } ! 408: ! 409: static __inline__ int NCR53c406a_pio_write(unsigned char *request, ! 410: unsigned int reqlen) ! 411: { ! 412: int i = 0; ! 413: int len; /* current scsi fifo size */ ! 414: unsigned long flags = 0; ! 415: ! 416: REG1; ! 417: while (reqlen && !(i&0x40)) { ! 418: i = inb(PIO_STATUS); ! 419: /* VDEB(printk("pio_status=%x\n", i)); */ ! 420: if (i & 0x80) /* error */ ! 421: return 0; ! 422: ! 423: switch( i & 0x1e ) { ! 424: case 0x10: ! 425: len=128; break; ! 426: case 0x0: ! 427: len=84; break; ! 428: case 0x8: ! 429: len=42; break; ! 430: case 0xc: ! 431: len=1; break; ! 432: default: ! 433: case 0xe: ! 434: len=0; break; ! 435: } ! 436: ! 437: if (len) { ! 438: if( len > reqlen ) ! 439: len = reqlen; ! 440: ! 441: save_flags(flags); ! 442: cli(); ! 443: if( fast_pio && len > 3 ) { ! 444: outsl(PIO_FIFO,request,len>>2); ! 445: request += len & 0xfc; ! 446: reqlen -= len & 0xfc; ! 447: } ! 448: else { ! 449: while(len--) { ! 450: outb(*request++, PIO_FIFO); ! 451: reqlen--; ! 452: } ! 453: } ! 454: restore_flags(flags); ! 455: } ! 456: } ! 457: return 0; ! 458: } ! 459: #endif USE_PIO ! 460: ! 461: int ! 462: NCR53c406a_detect(Scsi_Host_Template * tpnt){ ! 463: struct Scsi_Host *shpnt; ! 464: #ifndef PORT_BASE ! 465: int i; ! 466: #endif ! 467: ! 468: #if USE_BIOS ! 469: int ii, jj; ! 470: bios_base = 0; ! 471: /* look for a valid signature */ ! 472: for( ii=0; ii < ADDRESS_COUNT && !bios_base; ii++) ! 473: for( jj=0; (jj < SIGNATURE_COUNT) && !bios_base; jj++) ! 474: if(!memcmp((void *) addresses[ii]+signatures[jj].sig_offset, ! 475: (void *) signatures[jj].signature, ! 476: (int) signatures[jj].sig_length)) ! 477: bios_base=addresses[ii]; ! 478: ! 479: if(!bios_base){ ! 480: printk("NCR53c406a: BIOS signature not found\n"); ! 481: return 0; ! 482: } ! 483: ! 484: DEB(printk("NCR53c406a BIOS found at %X\n", (unsigned int) bios_base);); ! 485: #endif USE_BIOS ! 486: ! 487: #ifdef PORT_BASE ! 488: if (check_region(port_base, 0x10)) /* ports already snatched */ ! 489: port_base = 0; ! 490: ! 491: #else /* autodetect */ ! 492: if (port_base) { /* LILO override */ ! 493: if (check_region(port_base, 0x10)) ! 494: port_base = 0; ! 495: } ! 496: else { ! 497: for(i=0; i<PORT_COUNT && !port_base; i++){ ! 498: if(check_region(ports[i], 0x10)){ ! 499: DEB(printk("NCR53c406a: port %x in use\n", ports[i])); ! 500: } ! 501: else { ! 502: VDEB(printk("NCR53c406a: port %x available\n", ports[i])); ! 503: outb(C5_IMG, ports[i] + 0x0d); /* reg set 1 */ ! 504: if( (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 ! 505: && (inb(ports[i] + 0x0e) ^ inb(ports[i] + 0x0e)) == 7 ! 506: && (inb(ports[i] + 0x0e) & 0xf8) == 0x58 ) { ! 507: VDEB(printk("NCR53c406a: Sig register valid\n")); ! 508: VDEB(printk("port_base=%x\n", port_base)); ! 509: port_base = ports[i]; ! 510: } ! 511: } ! 512: } ! 513: } ! 514: #endif PORT_BASE ! 515: ! 516: if(!port_base){ /* no ports found */ ! 517: printk("NCR53c406a: no available ports found\n"); ! 518: return 0; ! 519: } ! 520: ! 521: DEB(printk("NCR53c406a detected\n")); ! 522: ! 523: calc_port_addr(); ! 524: chip_init(); ! 525: ! 526: #ifndef IRQ_LEV ! 527: if (irq_level < 0) { /* LILO override if >= 0*/ ! 528: irq_level=irq_probe(); ! 529: if (irq_level < 0) { /* Trouble */ ! 530: printk("NCR53c406a: IRQ problem, irq_level=%d, giving up\n", irq_level); ! 531: return 0; ! 532: } ! 533: } ! 534: #endif ! 535: ! 536: DEB(printk("NCR53c406a: using port_base %x\n", port_base)); ! 537: request_region(port_base, 0x10, "NCR53c406a"); ! 538: ! 539: if(irq_level > 0) { ! 540: if(request_irq(irq_level, NCR53c406a_intr, 0, "NCR53c406a", NULL)){ ! 541: printk("NCR53c406a: unable to allocate IRQ %d\n", irq_level); ! 542: return 0; ! 543: } ! 544: tpnt->can_queue = 1; ! 545: DEB(printk("NCR53c406a: allocated IRQ %d\n", irq_level)); ! 546: } ! 547: else if (irq_level == 0) { ! 548: tpnt->can_queue = 0; ! 549: DEB(printk("NCR53c406a: No interrupts detected\n")); ! 550: #if USE_DMA ! 551: printk("NCR53c406a: No interrupts found and DMA mode defined. Giving up.\n"); ! 552: return 0; ! 553: #endif USE_DMA ! 554: } ! 555: else { ! 556: DEB(printk("NCR53c406a: Shouldn't get here!\n")); ! 557: return 0; ! 558: } ! 559: ! 560: #if USE_DMA ! 561: dma_chan = DMA_CHAN; ! 562: if(request_dma(dma_chan, "NCR53c406a") != 0){ ! 563: printk("NCR53c406a: unable to allocate DMA channel %d\n", dma_chan); ! 564: return 0; ! 565: } ! 566: ! 567: DEB(printk("Allocated DMA channel %d\n", dma_chan)); ! 568: #endif USE_DMA ! 569: ! 570: tpnt->present = 1; ! 571: tpnt->proc_dir = &proc_scsi_NCR53c406a; ! 572: ! 573: shpnt = scsi_register(tpnt, 0); ! 574: shpnt->irq = irq_level; ! 575: shpnt->io_port = port_base; ! 576: shpnt->n_io_port = 0x10; ! 577: #if USE_DMA ! 578: shpnt->dma = dma_chan; ! 579: #endif ! 580: ! 581: #if USE_DMA ! 582: sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, DMA channel %d.", ! 583: port_base, irq_level, dma_chan); ! 584: #else ! 585: sprintf(info_msg, "NCR53c406a at 0x%x, IRQ %d, %s PIO mode.", ! 586: port_base, irq_level, fast_pio ? "fast" : "slow"); ! 587: #endif ! 588: ! 589: return (tpnt->present); ! 590: } ! 591: ! 592: /* called from init/main.c */ ! 593: void NCR53c406a_setup(char *str, int *ints) ! 594: { ! 595: static size_t setup_idx = 0; ! 596: size_t i; ! 597: ! 598: DEB(printk("NCR53c406a: Setup called\n");); ! 599: ! 600: if (setup_idx >= PORT_COUNT - 1) { ! 601: printk("NCR53c406a: Setup called too many times. Bad LILO params?\n"); ! 602: return; ! 603: } ! 604: if (ints[0] < 1 || ints[0] > 3) { ! 605: printk("NCR53c406a: Malformed command line\n"); ! 606: printk("NCR53c406a: Usage: ncr53c406a=<PORTBASE>[,<IRQ>[,<FASTPIO>]]\n"); ! 607: return; ! 608: } ! 609: for (i = 0; i < PORT_COUNT && !port_base; i++) ! 610: if (ports[i] == ints[1]) { ! 611: port_base = ints[1]; ! 612: DEB(printk("NCR53c406a: Specified port_base 0x%X\n", port_base);) ! 613: } ! 614: if (!port_base) { ! 615: printk("NCR53c406a: Invalid PORTBASE 0x%X specified\n", ints[1]); ! 616: return; ! 617: } ! 618: ! 619: if (ints[0] > 1) { ! 620: if (ints[2] == 0) { ! 621: irq_level = 0; ! 622: DEB(printk("NCR53c406a: Specified irq %d\n", irq_level);) ! 623: } ! 624: else ! 625: for (i = 0; i < INTR_COUNT && irq_level < 0; i++) ! 626: if (intrs[i] == ints[2]) { ! 627: irq_level = ints[2]; ! 628: DEB(printk("NCR53c406a: Specified irq %d\n", port_base);) ! 629: } ! 630: if (irq_level < 0) ! 631: printk("NCR53c406a: Invalid IRQ %d specified\n", ints[2]); ! 632: } ! 633: ! 634: if (ints[0] > 2) ! 635: fast_pio = ints[3]; ! 636: ! 637: DEB(printk("NCR53c406a: port_base=0x%X, irq=%d, fast_pio=%d\n", ! 638: port_base, irq_level, fast_pio);) ! 639: } ! 640: ! 641: const char* ! 642: NCR53c406a_info(struct Scsi_Host *SChost){ ! 643: DEB(printk("NCR53c406a_info called\n")); ! 644: return (info_msg); ! 645: } ! 646: ! 647: static void internal_done(Scsi_Cmnd *SCpnt) { ! 648: internal_done_errcode = SCpnt->result; ! 649: ++internal_done_flag; ! 650: } ! 651: ! 652: ! 653: static void wait_intr() { ! 654: int i = jiffies + WATCHDOG; ! 655: ! 656: while(i>jiffies && !(inb(STAT_REG)&0xe0)) /* wait for a pseudo-interrupt */ ! 657: barrier(); ! 658: ! 659: if (i <= jiffies) { /* Timed out */ ! 660: rtrc(0); ! 661: current_SC->result = DID_TIME_OUT << 16; ! 662: current_SC->SCp.phase = idle; ! 663: current_SC->scsi_done(current_SC); ! 664: return; ! 665: } ! 666: ! 667: NCR53c406a_intr(0, NULL, NULL); ! 668: } ! 669: ! 670: int NCR53c406a_command(Scsi_Cmnd *SCpnt){ ! 671: DEB(printk("NCR53c406a_command called\n")); ! 672: NCR53c406a_queue(SCpnt, internal_done); ! 673: if(irq_level) ! 674: while (!internal_done_flag); ! 675: else /* interrupts not supported */ ! 676: while (!internal_done_flag) ! 677: wait_intr(); ! 678: ! 679: internal_done_flag = 0; ! 680: return internal_done_errcode; ! 681: } ! 682: ! 683: ! 684: int ! 685: NCR53c406a_queue(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){ ! 686: int i; ! 687: unsigned long flags = 0; ! 688: ! 689: VDEB(printk("NCR53c406a_queue called\n")); ! 690: DEB(printk("cmd=%02x, cmd_len=%02x, target=%02x, lun=%02x, bufflen=%d\n", ! 691: SCpnt->cmnd[0], ! 692: SCpnt->cmd_len, ! 693: SCpnt->target, ! 694: SCpnt->lun, ! 695: SCpnt->request_bufflen)); ! 696: ! 697: #if 0 ! 698: VDEB(for(i=0; i<SCpnt->cmd_len; i++) ! 699: printk("cmd[%d]=%02x ", i, SCpnt->cmnd[i])); ! 700: VDEB(printk("\n")); ! 701: #endif ! 702: ! 703: current_SC = SCpnt; ! 704: current_SC->scsi_done = done; ! 705: current_SC->SCp.phase = command_ph; ! 706: current_SC->SCp.Status = 0; ! 707: current_SC->SCp.Message = 0; ! 708: ! 709: save_flags(flags); ! 710: cli(); ! 711: REG0; ! 712: outb(SCpnt->target, DEST_ID); /* set destination */ ! 713: outb(FLUSH_FIFO, CMD_REG); /* reset the fifos */ ! 714: ! 715: for(i=0; i<SCpnt->cmd_len; i++){ ! 716: outb(SCpnt->cmnd[i], SCSI_FIFO); ! 717: } ! 718: outb(SELECT_NO_ATN, CMD_REG); ! 719: restore_flags(flags); ! 720: ! 721: rtrc(1); ! 722: return 0; ! 723: } ! 724: ! 725: int ! 726: NCR53c406a_abort(Scsi_Cmnd *SCpnt){ ! 727: DEB(printk("NCR53c406a_abort called\n")); ! 728: return SCSI_ABORT_SNOOZE; /* Don't know how to abort */ ! 729: } ! 730: ! 731: int ! 732: NCR53c406a_reset(Scsi_Cmnd *SCpnt, unsigned int flags){ ! 733: DEB(printk("NCR53c406a_reset called\n")); ! 734: outb(C4_IMG, CONFIG4); /* Select reg set 0 */ ! 735: outb(CHIP_RESET, CMD_REG); ! 736: outb(SCSI_NOP, CMD_REG); /* required after reset */ ! 737: outb(SCSI_RESET, CMD_REG); ! 738: chip_init(); ! 739: ! 740: rtrc(2); ! 741: if (irq_level) ! 742: return SCSI_RESET_PENDING; /* should get an interrupt */ ! 743: else ! 744: return SCSI_RESET_WAKEUP; /* won't get any interrupts */ ! 745: } ! 746: ! 747: int ! 748: NCR53c406a_biosparm(Scsi_Disk *disk, kdev_t dev, int* info_array){ ! 749: int size; ! 750: ! 751: DEB(printk("NCR53c406a_biosparm called\n")); ! 752: ! 753: size = disk->capacity; ! 754: info_array[0] = 64; /* heads */ ! 755: info_array[1] = 32; /* sectors */ ! 756: info_array[2] = size>>11; /* cylinders */ ! 757: if (info_array[2] > 1024) { /* big disk */ ! 758: info_array[0] = 255; ! 759: info_array[1] = 63; ! 760: info_array[2] = size / (255*63); ! 761: } ! 762: return 0; ! 763: } ! 764: ! 765: static void ! 766: NCR53c406a_intr(int unused, void *dev_id, struct pt_regs *regs){ ! 767: DEB(unsigned char fifo_size;) ! 768: DEB(unsigned char seq_reg;) ! 769: unsigned char status, int_reg; ! 770: unsigned long flags = 0; ! 771: #if USE_PIO ! 772: unsigned char pio_status; ! 773: struct scatterlist *sglist; ! 774: unsigned int sgcount; ! 775: #endif ! 776: ! 777: VDEB(printk("NCR53c406a_intr called\n")); ! 778: ! 779: save_flags(flags); ! 780: cli(); ! 781: #if USE_PIO ! 782: REG1; ! 783: pio_status = inb(PIO_STATUS); ! 784: #endif ! 785: REG0; ! 786: status = inb(STAT_REG); ! 787: DEB(seq_reg = inb(SEQ_REG)); ! 788: int_reg = inb(INT_REG); ! 789: DEB(fifo_size = inb(FIFO_FLAGS) & 0x1f); ! 790: restore_flags(flags); ! 791: ! 792: #if NCR53C406A_DEBUG ! 793: printk("status=%02x, seq_reg=%02x, int_reg=%02x, fifo_size=%02x", ! 794: status, seq_reg, int_reg, fifo_size); ! 795: #if (USE_DMA) ! 796: printk("\n"); ! 797: #else ! 798: printk(", pio=%02x\n", pio_status); ! 799: #endif USE_DMA ! 800: #endif NCR53C406A_DEBUG ! 801: ! 802: if(int_reg & 0x80){ /* SCSI reset intr */ ! 803: rtrc(3); ! 804: DEB(printk("NCR53c406a: reset intr received\n")); ! 805: current_SC->SCp.phase = idle; ! 806: current_SC->result = DID_RESET << 16; ! 807: current_SC->scsi_done(current_SC); ! 808: return; ! 809: } ! 810: ! 811: #if USE_PIO ! 812: if(pio_status & 0x80) { ! 813: printk("NCR53C406A: Warning: PIO error!\n"); ! 814: current_SC->SCp.phase = idle; ! 815: current_SC->result = DID_ERROR << 16; ! 816: current_SC->scsi_done(current_SC); ! 817: return; ! 818: } ! 819: #endif USE_PIO ! 820: ! 821: if(status & 0x20) { /* Parity error */ ! 822: printk("NCR53c406a: Warning: parity error!\n"); ! 823: current_SC->SCp.phase = idle; ! 824: current_SC->result = DID_PARITY << 16; ! 825: current_SC->scsi_done(current_SC); ! 826: return; ! 827: } ! 828: ! 829: if(status & 0x40) { /* Gross error */ ! 830: printk("NCR53c406a: Warning: gross error!\n"); ! 831: current_SC->SCp.phase = idle; ! 832: current_SC->result = DID_ERROR << 16; ! 833: current_SC->scsi_done(current_SC); ! 834: return; ! 835: } ! 836: ! 837: if(int_reg & 0x20){ /* Disconnect */ ! 838: DEB(printk("NCR53c406a: disconnect intr received\n")); ! 839: if(current_SC->SCp.phase != message_in){ /* Unexpected disconnect */ ! 840: current_SC->result = DID_NO_CONNECT << 16; ! 841: } ! 842: else{ /* Command complete, return status and message */ ! 843: current_SC->result = (current_SC->SCp.Status & 0xff) ! 844: | ((current_SC->SCp.Message & 0xff) << 8) | (DID_OK << 16); ! 845: } ! 846: ! 847: rtrc(0); ! 848: current_SC->SCp.phase = idle; ! 849: current_SC->scsi_done( current_SC ); ! 850: return; ! 851: } ! 852: ! 853: switch(status & 0x07){ /* scsi phase */ ! 854: case 0x00: /* DATA-OUT */ ! 855: if(int_reg & 0x10){ /* Target requesting info transfer */ ! 856: rtrc(5); ! 857: current_SC->SCp.phase = data_out; ! 858: VDEB(printk("NCR53c406a: Data-Out phase\n")); ! 859: outb(FLUSH_FIFO, CMD_REG); ! 860: LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ ! 861: #if USE_DMA /* No s/g support for DMA */ ! 862: NCR53c406a_dma_write(current_SC->request_buffer, ! 863: current_SC->request_bufflen); ! 864: #endif USE_DMA ! 865: outb(TRANSFER_INFO | DMA_OP, CMD_REG); ! 866: #if USE_PIO ! 867: if (!current_SC->use_sg) /* Don't use scatter-gather */ ! 868: NCR53c406a_pio_write(current_SC->request_buffer, ! 869: current_SC->request_bufflen); ! 870: else { /* use scatter-gather */ ! 871: sgcount = current_SC->use_sg; ! 872: sglist = current_SC->request_buffer; ! 873: while( sgcount-- ) { ! 874: NCR53c406a_pio_write(sglist->address, sglist->length); ! 875: sglist++; ! 876: } ! 877: } ! 878: REG0; ! 879: #endif USE_PIO ! 880: } ! 881: break; ! 882: ! 883: case 0x01: /* DATA-IN */ ! 884: if(int_reg & 0x10){ /* Target requesting info transfer */ ! 885: rtrc(6); ! 886: current_SC->SCp.phase = data_in; ! 887: VDEB(printk("NCR53c406a: Data-In phase\n")); ! 888: outb(FLUSH_FIFO, CMD_REG); ! 889: LOAD_DMA_COUNT(current_SC->request_bufflen); /* Max transfer size */ ! 890: #if USE_DMA /* No s/g support for DMA */ ! 891: NCR53c406a_dma_read(current_SC->request_buffer, ! 892: current_SC->request_bufflen); ! 893: #endif USE_DMA ! 894: outb(TRANSFER_INFO | DMA_OP, CMD_REG); ! 895: #if USE_PIO ! 896: if (!current_SC->use_sg) /* Don't use scatter-gather */ ! 897: NCR53c406a_pio_read(current_SC->request_buffer, ! 898: current_SC->request_bufflen); ! 899: else { /* Use scatter-gather */ ! 900: sgcount = current_SC->use_sg; ! 901: sglist = current_SC->request_buffer; ! 902: while( sgcount-- ) { ! 903: NCR53c406a_pio_read(sglist->address, sglist->length); ! 904: sglist++; ! 905: } ! 906: } ! 907: REG0; ! 908: #endif USE_PIO ! 909: } ! 910: break; ! 911: ! 912: case 0x02: /* COMMAND */ ! 913: current_SC->SCp.phase = command_ph; ! 914: printk("NCR53c406a: Warning: Unknown interrupt occurred in command phase!\n"); ! 915: break; ! 916: ! 917: case 0x03: /* STATUS */ ! 918: rtrc(7); ! 919: current_SC->SCp.phase = status_ph; ! 920: VDEB(printk("NCR53c406a: Status phase\n")); ! 921: outb(FLUSH_FIFO, CMD_REG); ! 922: outb(INIT_CMD_COMPLETE, CMD_REG); ! 923: break; ! 924: ! 925: case 0x04: /* Reserved */ ! 926: case 0x05: /* Reserved */ ! 927: printk("NCR53c406a: WARNING: Reserved phase!!!\n"); ! 928: break; ! 929: ! 930: case 0x06: /* MESSAGE-OUT */ ! 931: DEB(printk("NCR53c406a: Message-Out phase\n")); ! 932: current_SC->SCp.phase = message_out; ! 933: outb(SET_ATN, CMD_REG); /* Reject the message */ ! 934: outb(MSG_ACCEPT, CMD_REG); ! 935: break; ! 936: ! 937: case 0x07: /* MESSAGE-IN */ ! 938: rtrc(4); ! 939: VDEB(printk("NCR53c406a: Message-In phase\n")); ! 940: current_SC->SCp.phase = message_in; ! 941: ! 942: current_SC->SCp.Status = inb(SCSI_FIFO); ! 943: current_SC->SCp.Message = inb(SCSI_FIFO); ! 944: ! 945: VDEB(printk("SCSI FIFO size=%d\n", inb(FIFO_FLAGS) & 0x1f)); ! 946: DEB(printk("Status = %02x Message = %02x\n", ! 947: current_SC->SCp.Status, current_SC->SCp.Message)); ! 948: ! 949: if(current_SC->SCp.Message == SAVE_POINTERS || ! 950: current_SC->SCp.Message == DISCONNECT) { ! 951: outb(SET_ATN, CMD_REG); /* Reject message */ ! 952: DEB(printk("Discarding SAVE_POINTERS message\n")); ! 953: } ! 954: outb(MSG_ACCEPT, CMD_REG); ! 955: break; ! 956: } ! 957: } ! 958: ! 959: #ifndef IRQ_LEV ! 960: static int irq_probe() ! 961: { ! 962: int irqs, irq; ! 963: int i; ! 964: ! 965: inb(INT_REG); /* clear the interrupt register */ ! 966: sti(); ! 967: irqs = probe_irq_on(); ! 968: ! 969: /* Invalid command will cause an interrupt */ ! 970: REG0; ! 971: outb(0xff, CMD_REG); ! 972: ! 973: /* Wait for the interrupt to occur */ ! 974: i = jiffies + WATCHDOG; ! 975: while(i > jiffies && !(inb(STAT_REG) & 0x80)) ! 976: barrier(); ! 977: if (i <= jiffies) { /* Timed out, must be hardware trouble */ ! 978: probe_irq_off(irqs); ! 979: return -1; ! 980: } ! 981: ! 982: irq = probe_irq_off(irqs); ! 983: ! 984: /* Kick the chip */ ! 985: outb(CHIP_RESET, CMD_REG); ! 986: outb(SCSI_NOP, CMD_REG); ! 987: chip_init(); ! 988: ! 989: return irq; ! 990: } ! 991: #endif IRQ_LEV ! 992: ! 993: static void chip_init() ! 994: { ! 995: REG1; ! 996: #if USE_DMA ! 997: outb(0x00, PIO_STATUS); ! 998: #else /* USE_PIO */ ! 999: outb(0x01, PIO_STATUS); ! 1000: #endif ! 1001: outb(0x00, PIO_FLAG); ! 1002: ! 1003: outb(C4_IMG, CONFIG4); /* REG0; */ ! 1004: outb(C3_IMG, CONFIG3); ! 1005: outb(C2_IMG, CONFIG2); ! 1006: outb(C1_IMG, CONFIG1); ! 1007: ! 1008: outb(0x05, CLKCONV); /* clock conversion factor */ ! 1009: outb(0x9C, SRTIMOUT); /* Selection timeout */ ! 1010: outb(0x05, SYNCPRD); /* Synchronous transfer period */ ! 1011: outb(SYNC_MODE, SYNCOFF); /* synchronous mode */ ! 1012: } ! 1013: ! 1014: void calc_port_addr() ! 1015: { ! 1016: /* Control Register Set 0 */ ! 1017: TC_LSB = (port_base+0x00); ! 1018: TC_MSB = (port_base+0x01); ! 1019: SCSI_FIFO = (port_base+0x02); ! 1020: CMD_REG = (port_base+0x03); ! 1021: STAT_REG = (port_base+0x04); ! 1022: DEST_ID = (port_base+0x04); ! 1023: INT_REG = (port_base+0x05); ! 1024: SRTIMOUT = (port_base+0x05); ! 1025: SEQ_REG = (port_base+0x06); ! 1026: SYNCPRD = (port_base+0x06); ! 1027: FIFO_FLAGS = (port_base+0x07); ! 1028: SYNCOFF = (port_base+0x07); ! 1029: CONFIG1 = (port_base+0x08); ! 1030: CLKCONV = (port_base+0x09); ! 1031: /* TESTREG = (port_base+0x0A); */ ! 1032: CONFIG2 = (port_base+0x0B); ! 1033: CONFIG3 = (port_base+0x0C); ! 1034: CONFIG4 = (port_base+0x0D); ! 1035: TC_HIGH = (port_base+0x0E); ! 1036: /* FIFO_BOTTOM = (port_base+0x0F); */ ! 1037: ! 1038: /* Control Register Set 1 */ ! 1039: /* JUMPER_SENSE = (port_base+0x00);*/ ! 1040: /* SRAM_PTR = (port_base+0x01);*/ ! 1041: /* SRAM_DATA = (port_base+0x02);*/ ! 1042: PIO_FIFO = (port_base+0x04); ! 1043: /* PIO_FIFO1 = (port_base+0x05);*/ ! 1044: /* PIO_FIFO2 = (port_base+0x06);*/ ! 1045: /* PIO_FIFO3 = (port_base+0x07);*/ ! 1046: PIO_STATUS = (port_base+0x08); ! 1047: /* ATA_CMD = (port_base+0x09);*/ ! 1048: /* ATA_ERR = (port_base+0x0A);*/ ! 1049: PIO_FLAG = (port_base+0x0B); ! 1050: CONFIG5 = (port_base+0x0D); ! 1051: /* SIGNATURE = (port_base+0x0E);*/ ! 1052: /* CONFIG6 = (port_base+0x0F);*/ ! 1053: } ! 1054: ! 1055: #ifdef MODULE ! 1056: /* Eventually this will go into an include file, but this will be later */ ! 1057: Scsi_Host_Template driver_template = NCR53c406a; ! 1058: ! 1059: #include "scsi_module.c" ! 1060: #endif ! 1061: ! 1062: /* ! 1063: * Overrides for Emacs so that we get a uniform tabbing style. ! 1064: * Emacs will notice this stuff at the end of the file and automatically ! 1065: * adjust the settings for this buffer only. This must remain at the end ! 1066: * of the file. ! 1067: * --------------------------------------------------------------------------- ! 1068: * Local variables: ! 1069: * c-indent-level: 4 ! 1070: * c-brace-imaginary-offset: 0 ! 1071: * c-brace-offset: -4 ! 1072: * c-argdecl-indent: 4 ! 1073: * c-label-offset: -4 ! 1074: * c-continued-statement-offset: 4 ! 1075: * c-continued-brace-offset: 0 ! 1076: * indent-tabs-mode: nil ! 1077: * tab-width: 8 ! 1078: * End: ! 1079: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.