1/* 2 * linux/drivers/acorn/scsi/acornscsi.c 3 * 4 * Acorn SCSI 3 driver 5 * By R.M.King. 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License version 2 as 9 * published by the Free Software Foundation. 10 * 11 * Abandoned using the Select and Transfer command since there were 12 * some nasty races between our software and the target devices that 13 * were not easy to solve, and the device errata had a lot of entries 14 * for this command, some of them quite nasty... 15 * 16 * Changelog: 17 * 26-Sep-1997 RMK Re-jigged to use the queue module. 18 * Re-coded state machine to be based on driver 19 * state not scsi state. Should be easier to debug. 20 * Added acornscsi_release to clean up properly. 21 * Updated proc/scsi reporting. 22 * 05-Oct-1997 RMK Implemented writing to SCSI devices. 23 * 06-Oct-1997 RMK Corrected small (non-serious) bug with the connect/ 24 * reconnect race condition causing a warning message. 25 * 12-Oct-1997 RMK Added catch for re-entering interrupt routine. 26 * 15-Oct-1997 RMK Improved handling of commands. 27 * 27-Jun-1998 RMK Changed asm/delay.h to linux/delay.h. 28 * 13-Dec-1998 RMK Better abort code and command handling. Extra state 29 * transitions added to allow dodgy devices to work. 30 */ 31#define DEBUG_NO_WRITE 1 32#define DEBUG_QUEUES 2 33#define DEBUG_DMA 4 34#define DEBUG_ABORT 8 35#define DEBUG_DISCON 16 36#define DEBUG_CONNECT 32 37#define DEBUG_PHASES 64 38#define DEBUG_WRITE 128 39#define DEBUG_LINK 256 40#define DEBUG_MESSAGES 512 41#define DEBUG_RESET 1024 42#define DEBUG_ALL (DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\ 43 DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\ 44 DEBUG_DMA|DEBUG_QUEUES) 45 46/* DRIVER CONFIGURATION 47 * 48 * SCSI-II Tagged queue support. 49 * 50 * I don't have any SCSI devices that support it, so it is totally untested 51 * (except to make sure that it doesn't interfere with any non-tagging 52 * devices). It is not fully implemented either - what happens when a 53 * tagging device reconnects??? 54 * 55 * You can tell if you have a device that supports tagged queueing my 56 * cating (eg) /proc/scsi/acornscsi/0 and see if the SCSI revision is reported 57 * as '2 TAG'. 58 * 59 * Also note that CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE is normally set in the config 60 * scripts, but disabled here. Once debugged, remove the #undef, otherwise to debug, 61 * comment out the undef. 62 */ 63#undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 64/* 65 * SCSI-II Linked command support. 66 * 67 * The higher level code doesn't support linked commands yet, and so the option 68 * is undef'd here. 69 */ 70#undef CONFIG_SCSI_ACORNSCSI_LINK 71/* 72 * SCSI-II Synchronous transfer support. 73 * 74 * Tried and tested... 75 * 76 * SDTR_SIZE - maximum number of un-acknowledged bytes (0 = off, 12 = max) 77 * SDTR_PERIOD - period of REQ signal (min=125, max=1020) 78 * DEFAULT_PERIOD - default REQ period. 79 */ 80#define SDTR_SIZE 12 81#define SDTR_PERIOD 125 82#define DEFAULT_PERIOD 500 83 84/* 85 * Debugging information 86 * 87 * DEBUG - bit mask from list above 88 * DEBUG_TARGET - is defined to the target number if you want to debug 89 * a specific target. [only recon/write/dma]. 90 */ 91#define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE) 92/* only allow writing to SCSI device 0 */ 93#define NO_WRITE 0xFE 94/*#define DEBUG_TARGET 2*/ 95/* 96 * Select timeout time (in 10ms units) 97 * 98 * This is the timeout used between the start of selection and the WD33C93 99 * chip deciding that the device isn't responding. 100 */ 101#define TIMEOUT_TIME 10 102/* 103 * Define this if you want to have verbose explaination of SCSI 104 * status/messages. 105 */ 106#undef CONFIG_ACORNSCSI_CONSTANTS 107/* 108 * Define this if you want to use the on board DMAC [don't remove this option] 109 * If not set, then use PIO mode (not currently supported). 110 */ 111#define USE_DMAC 112/* 113 * List of devices that the driver will recognise 114 */ 115#define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI } 116/* 117 * ==================================================================================== 118 */ 119 120#ifdef DEBUG_TARGET 121#define DBG(cmd,xxx...) \ 122 if (cmd->target == DEBUG_TARGET) { \ 123 xxx; \ 124 } 125#else 126#define DBG(cmd,xxx...) xxx 127#endif 128 129#ifndef STRINGIFY 130#define STRINGIFY(x) #x 131#endif 132#define STRx(x) STRINGIFY(x) 133#define NO_WRITE_STR STRx(NO_WRITE) 134 135#include <linux/config.h> 136#include <linux/module.h> 137#include <linux/kernel.h> 138#include <linux/sched.h> 139#include <linux/string.h> 140#include <linux/signal.h> 141#include <linux/errno.h> 142#include <linux/proc_fs.h> 143#include <linux/stat.h> 144#include <linux/ioport.h> 145#include <linux/blk.h> 146#include <linux/delay.h> 147#include <linux/init.h> 148 149#include <asm/bitops.h> 150#include <asm/system.h> 151#include <asm/io.h> 152#include <asm/irq.h> 153#include <asm/ecard.h> 154 155#include "../../scsi/scsi.h" 156#include "../../scsi/hosts.h" 157#include "../../scsi/constants.h" 158#include "acornscsi.h" 159#include "msgqueue.h" 160 161#include <scsi/scsicam.h> 162 163#define VER_MAJOR 2 164#define VER_MINOR 0 165#define VER_PATCH 6 166 167#ifndef ABORT_TAG 168#define ABORT_TAG 0xd 169#else 170#error "Yippee! ABORT TAG is now defined! Remove this error!" 171#endif 172 173#ifdef CONFIG_SCSI_ACORNSCSI_LINK 174#error SCSI2 LINKed commands not supported (yet)! 175#endif 176 177#ifdef USE_DMAC 178/* 179 * DMAC setup parameters 180 */ 181#define INIT_DEVCON0 (DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP) 182#define INIT_DEVCON1 (DEVCON1_BHLD) 183#define DMAC_READ (MODECON_READ) 184#define DMAC_WRITE (MODECON_WRITE) 185#define INIT_SBICDMA (CTRL_DMABURST) 186 187#define scsi_xferred have_data_in 188 189/* 190 * Size of on-board DMA buffer 191 */ 192#define DMAC_BUFFER_SIZE 65536 193#endif 194 195#define STATUS_BUFFER_TO_PRINT 24 196 197unsigned int sdtr_period = SDTR_PERIOD; 198unsigned int sdtr_size = SDTR_SIZE; 199 200static void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result); 201static int acornscsi_reconnect_finish(AS_Host *host); 202static void acornscsi_dma_cleanup(AS_Host *host); 203static void acornscsi_abortcmd(AS_Host *host, unsigned char tag); 204 205/* ==================================================================================== 206 * Miscellaneous 207 */ 208 209static inline void 210sbic_arm_write(unsigned int io_port, int reg, int value) 211{ 212 __raw_writeb(reg, io_port); 213 __raw_writeb(value, io_port + 4); 214} 215 216#define sbic_arm_writenext(io,val) \ 217 __raw_writeb((val), (io) + 4) 218 219static inline 220int sbic_arm_read(unsigned int io_port, int reg) 221{ 222 if(reg == ASR) 223 return __raw_readl(io_port) & 255; 224 __raw_writeb(reg, io_port); 225 return __raw_readl(io_port + 4) & 255; 226} 227 228#define sbic_arm_readnext(io) \ 229 __raw_readb((io) + 4) 230 231#ifdef USE_DMAC 232#define dmac_read(io_port,reg) \ 233 inb((io_port) + (reg)) 234 235#define dmac_write(io_port,reg,value) \ 236 ({ outb((value), (io_port) + (reg)); }) 237 238#define dmac_clearintr(io_port) \ 239 ({ outb(0, (io_port)); }) 240 241static inline 242unsigned int dmac_address(unsigned int io_port) 243{ 244 return dmac_read(io_port, TXADRHI) << 16 | 245 dmac_read(io_port, TXADRMD) << 8 | 246 dmac_read(io_port, TXADRLO); 247} 248 249static 250void acornscsi_dumpdma(AS_Host *host, char *where) 251{ 252 unsigned int mode, addr, len; 253 254 mode = dmac_read(host->dma.io_port, MODECON); 255 addr = dmac_address(host->dma.io_port); 256 len = dmac_read(host->dma.io_port, TXCNTHI) << 8 | 257 dmac_read(host->dma.io_port, TXCNTLO); 258 259 printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ", 260 host->host->host_no, where, 261 mode, addr, (len + 1) & 0xffff, 262 dmac_read(host->dma.io_port, MASKREG)); 263 264 printk("DMA @%06x, ", host->dma.start_addr); 265 printk("BH @%p +%04x, ", host->scsi.SCp.ptr, 266 host->scsi.SCp.this_residual); 267 printk("DT @+%04x ST @+%04x", host->dma.transferred, 268 host->scsi.SCp.scsi_xferred); 269 printk("\n"); 270} 271#endif 272 273static 274unsigned long acornscsi_sbic_xfcount(AS_Host *host) 275{ 276 unsigned long length; 277 278 length = sbic_arm_read(host->scsi.io_port, TRANSCNTH) << 16; 279 length |= sbic_arm_readnext(host->scsi.io_port) << 8; 280 length |= sbic_arm_readnext(host->scsi.io_port); 281 282 return length; 283} 284 285static int 286acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg) 287{ 288 int asr; 289 290 do { 291 asr = sbic_arm_read(host->scsi.io_port, ASR); 292 293 if ((asr & stat_mask) == stat) 294 return 0; 295 296 udelay(1); 297 } while (--timeout); 298 299 printk("scsi%d: timeout while %s\n", host->host->host_no, msg); 300 301 return -1; 302} 303 304static 305int acornscsi_sbic_issuecmd(AS_Host *host, int command) 306{ 307 if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) 308 return -1; 309 310 sbic_arm_write(host->scsi.io_port, CMND, command); 311 312 return 0; 313} 314 315static void 316acornscsi_csdelay(unsigned int cs) 317{ 318 unsigned long target_jiffies, flags; 319 320 target_jiffies = jiffies + 1 + cs * HZ / 100; 321 322 save_flags(flags); 323 sti(); 324 325 while (time_before(jiffies, target_jiffies)) barrier(); 326 327 restore_flags(flags); 328} 329 330static 331void acornscsi_resetcard(AS_Host *host) 332{ 333 unsigned int i, timeout; 334 335 /* assert reset line */ 336 host->card.page_reg = 0x80; 337 outb(host->card.page_reg, host->card.io_page); 338 339 /* wait 3 cs. SCSI standard says 25ms. */ 340 acornscsi_csdelay(3); 341 342 host->card.page_reg = 0; 343 outb(host->card.page_reg, host->card.io_page); 344 345 /* 346 * Should get a reset from the card 347 */ 348 timeout = 1000; 349 do { 350 if (inb(host->card.io_intr) & 8) 351 break; 352 udelay(1); 353 } while (--timeout); 354 355 if (timeout == 0) 356 printk("scsi%d: timeout while resetting card\n", 357 host->host->host_no); 358 359 sbic_arm_read(host->scsi.io_port, ASR); 360 sbic_arm_read(host->scsi.io_port, SSR); 361 362 /* setup sbic - WD33C93A */ 363 sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); 364 sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); 365 366 /* 367 * Command should cause a reset interrupt 368 */ 369 timeout = 1000; 370 do { 371 if (inb(host->card.io_intr) & 8) 372 break; 373 udelay(1); 374 } while (--timeout); 375 376 if (timeout == 0) 377 printk("scsi%d: timeout while resetting card\n", 378 host->host->host_no); 379 380 sbic_arm_read(host->scsi.io_port, ASR); 381 if (sbic_arm_read(host->scsi.io_port, SSR) != 0x01) 382 printk(KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n", 383 host->host->host_no); 384 385 sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); 386 sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); 387 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); 388 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); 389 390 host->card.page_reg = 0x40; 391 outb(host->card.page_reg, host->card.io_page); 392 393 /* setup dmac - uPC71071 */ 394 dmac_write(host->dma.io_port, INIT, 0); 395#ifdef USE_DMAC 396 dmac_write(host->dma.io_port, INIT, INIT_8BIT); 397 dmac_write(host->dma.io_port, CHANNEL, CHANNEL_0); 398 dmac_write(host->dma.io_port, DEVCON0, INIT_DEVCON0); 399 dmac_write(host->dma.io_port, DEVCON1, INIT_DEVCON1); 400#endif 401 402 host->SCpnt = NULL; 403 host->scsi.phase = PHASE_IDLE; 404 host->scsi.disconnectable = 0; 405 406 for (i = 0; i < 8; i++) { 407 host->busyluns[i] = 0; 408 host->device[i].sync_state = SYNC_NEGOCIATE; 409 host->device[i].disconnect_ok = 1; 410 } 411 412 /* wait 25 cs. SCSI standard says 250ms. */ 413 acornscsi_csdelay(25); 414} 415 416/*============================================================================================= 417 * Utility routines (eg. debug) 418 */ 419#ifdef CONFIG_ACORNSCSI_CONSTANTS 420static char *acornscsi_interrupttype[] = { 421 "rst", "suc", "p/a", "3", 422 "term", "5", "6", "7", 423 "serv", "9", "a", "b", 424 "c", "d", "e", "f" 425}; 426 427static signed char acornscsi_map[] = { 428 0, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 429 -1, 2, -1, -1, -1, -1, 3, -1, 4, 5, 6, 7, 8, 9, 10, 11, 430 12, 13, 14, -1, -1, -1, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11, 431 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 432 15, 16, 17, 18, 19, -1, -1, 20, 4, 5, 6, 7, 8, 9, 10, 11, 433 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 434 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 435 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 436 21, 22, -1, -1, -1, 23, -1, -1, 4, 5, 6, 7, 8, 9, 10, 11, 437 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 438 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 439 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 440 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 441 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 442 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 443 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 444}; 445 446static char *acornscsi_interruptcode[] = { 447 /* 0 */ 448 "reset - normal mode", /* 00 */ 449 "reset - advanced mode", /* 01 */ 450 451 /* 2 */ 452 "sel", /* 11 */ 453 "sel+xfer", /* 16 */ 454 "data-out", /* 18 */ 455 "data-in", /* 19 */ 456 "cmd", /* 1A */ 457 "stat", /* 1B */ 458 "??-out", /* 1C */ 459 "??-in", /* 1D */ 460 "msg-out", /* 1E */ 461 "msg-in", /* 1F */ 462 463 /* 12 */ 464 "/ACK asserted", /* 20 */ 465 "save-data-ptr", /* 21 */ 466 "{re}sel", /* 22 */ 467 468 /* 15 */ 469 "inv cmd", /* 40 */ 470 "unexpected disconnect", /* 41 */ 471 "sel timeout", /* 42 */ 472 "P err", /* 43 */ 473 "P err+ATN", /* 44 */ 474 "bad status byte", /* 47 */ 475 476 /* 21 */ 477 "resel, no id", /* 80 */ 478 "resel", /* 81 */ 479 "discon", /* 85 */ 480}; 481 482static 483void print_scsi_status(unsigned int ssr) 484{ 485 if (acornscsi_map[ssr] != -1) 486 printk("%s:%s", 487 acornscsi_interrupttype[(ssr >> 4)], 488 acornscsi_interruptcode[acornscsi_map[ssr]]); 489 else 490 printk("%X:%X", ssr >> 4, ssr & 0x0f); 491} 492#endif 493 494static 495void print_sbic_status(int asr, int ssr, int cmdphase) 496{ 497#ifdef CONFIG_ACORNSCSI_CONSTANTS 498 printk("sbic: %c%c%c%c%c%c ", 499 asr & ASR_INT ? 'I' : 'i', 500 asr & ASR_LCI ? 'L' : 'l', 501 asr & ASR_BSY ? 'B' : 'b', 502 asr & ASR_CIP ? 'C' : 'c', 503 asr & ASR_PE ? 'P' : 'p', 504 asr & ASR_DBR ? 'D' : 'd'); 505 printk("scsi: "); 506 print_scsi_status(ssr); 507 printk(" ph %02X\n", cmdphase); 508#else 509 printk("sbic: %02X scsi: %X:%X ph: %02X\n", 510 asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase); 511#endif 512} 513 514static void 515acornscsi_dumplogline(AS_Host *host, int target, int line) 516{ 517 unsigned long prev; 518 signed int ptr; 519 520 ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT; 521 if (ptr < 0) 522 ptr += STATUS_BUFFER_SIZE; 523 524 printk("%c: %3s:", target == 8 ? 'H' : '0' + target, 525 line == 0 ? "ph" : line == 1 ? "ssr" : "int"); 526 527 prev = host->status[target][ptr].when; 528 529 for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) { 530 unsigned long time_diff; 531 532 if (!host->status[target][ptr].when) 533 continue; 534 535 switch (line) { 536 case 0: 537 printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ', 538 host->status[target][ptr].ph); 539 break; 540 541 case 1: 542 printk(" %02X", host->status[target][ptr].ssr); 543 break; 544 545 case 2: 546 time_diff = host->status[target][ptr].when - prev; 547 prev = host->status[target][ptr].when; 548 if (time_diff == 0) 549 printk("==^"); 550 else if (time_diff >= 100) 551 printk(" "); 552 else 553 printk(" %02ld", time_diff); 554 break; 555 } 556 } 557 558 printk("\n"); 559} 560 561static 562void acornscsi_dumplog(AS_Host *host, int target) 563{ 564 do { 565 acornscsi_dumplogline(host, target, 0); 566 acornscsi_dumplogline(host, target, 1); 567 acornscsi_dumplogline(host, target, 2); 568 569 if (target == 8) 570 break; 571 572 target = 8; 573 } while (1); 574} 575 576static 577char acornscsi_target(AS_Host *host) 578{ 579 if (host->SCpnt) 580 return '0' + host->SCpnt->target; 581 return 'H'; 582} 583 584/* 585 * Prototype: cmdtype_t acornscsi_cmdtype(int command) 586 * Purpose : differentiate READ from WRITE from other commands 587 * Params : command - command to interpret 588 * Returns : CMD_READ - command reads data, 589 * CMD_WRITE - command writes data, 590 * CMD_MISC - everything else 591 */ 592static inline 593cmdtype_t acornscsi_cmdtype(int command) 594{ 595 switch (command) { 596 case WRITE_6: case WRITE_10: case WRITE_12: 597 return CMD_WRITE; 598 case READ_6: case READ_10: case READ_12: 599 return CMD_READ; 600 default: 601 return CMD_MISC; 602 } 603} 604 605/* 606 * Prototype: int acornscsi_datadirection(int command) 607 * Purpose : differentiate between commands that have a DATA IN phase 608 * and a DATA OUT phase 609 * Params : command - command to interpret 610 * Returns : DATADIR_OUT - data out phase expected 611 * DATADIR_IN - data in phase expected 612 */ 613static 614datadir_t acornscsi_datadirection(int command) 615{ 616 switch (command) { 617 case CHANGE_DEFINITION: case COMPARE: case COPY: 618 case COPY_VERIFY: case LOG_SELECT: case MODE_SELECT: 619 case MODE_SELECT_10: case SEND_DIAGNOSTIC: case WRITE_BUFFER: 620 case FORMAT_UNIT: case REASSIGN_BLOCKS: case RESERVE: 621 case SEARCH_EQUAL: case SEARCH_HIGH: case SEARCH_LOW: 622 case WRITE_6: case WRITE_10: case WRITE_VERIFY: 623 case UPDATE_BLOCK: case WRITE_LONG: case WRITE_SAME: 624 case SEARCH_HIGH_12: case SEARCH_EQUAL_12: case SEARCH_LOW_12: 625 case WRITE_12: case WRITE_VERIFY_12: case SET_WINDOW: 626 case MEDIUM_SCAN: case SEND_VOLUME_TAG: case 0xea: 627 return DATADIR_OUT; 628 default: 629 return DATADIR_IN; 630 } 631} 632 633/* 634 * Purpose : provide values for synchronous transfers with 33C93. 635 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting 636 * Modified by Russell King for 8MHz WD33C93A 637 */ 638static struct sync_xfer_tbl { 639 unsigned int period_ns; 640 unsigned char reg_value; 641} sync_xfer_table[] = { 642 { 1, 0x20 }, { 249, 0x20 }, { 374, 0x30 }, 643 { 499, 0x40 }, { 624, 0x50 }, { 749, 0x60 }, 644 { 874, 0x70 }, { 999, 0x00 }, { 0, 0 } 645}; 646 647/* 648 * Prototype: int acornscsi_getperiod(unsigned char syncxfer) 649 * Purpose : period for the synchronous transfer setting 650 * Params : syncxfer SYNCXFER register value 651 * Returns : period in ns. 652 */ 653static 654int acornscsi_getperiod(unsigned char syncxfer) 655{ 656 int i; 657 658 syncxfer &= 0xf0; 659 if (syncxfer == 0x10) 660 syncxfer = 0; 661 662 for (i = 1; sync_xfer_table[i].period_ns; i++) 663 if (syncxfer == sync_xfer_table[i].reg_value) 664 return sync_xfer_table[i].period_ns; 665 return 0; 666} 667 668/* 669 * Prototype: int round_period(unsigned int period) 670 * Purpose : return index into above table for a required REQ period 671 * Params : period - time (ns) for REQ 672 * Returns : table index 673 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting 674 */ 675static inline 676int round_period(unsigned int period) 677{ 678 int i; 679 680 for (i = 1; sync_xfer_table[i].period_ns; i++) { 681 if ((period <= sync_xfer_table[i].period_ns) && 682 (period > sync_xfer_table[i - 1].period_ns)) 683 return i; 684 } 685 return 7; 686} 687 688/* 689 * Prototype: unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) 690 * Purpose : calculate value for 33c93s SYNC register 691 * Params : period - time (ns) for REQ 692 * offset - offset in bytes between REQ/ACK 693 * Returns : value for SYNC register 694 * Copyright: Copyright (c) 1996 John Shifflett, GeoLog Consulting 695 */ 696static 697unsigned char calc_sync_xfer(unsigned int period, unsigned int offset) 698{ 699 return sync_xfer_table[round_period(period)].reg_value | 700 ((offset < SDTR_SIZE) ? offset : SDTR_SIZE); 701} 702 703/* ==================================================================================== 704 * Command functions 705 */ 706/* 707 * Function: acornscsi_kick(AS_Host *host) 708 * Purpose : kick next command to interface 709 * Params : host - host to send command to 710 * Returns : INTR_IDLE if idle, otherwise INTR_PROCESSING 711 * Notes : interrupts are always disabled! 712 */ 713static 714intr_ret_t acornscsi_kick(AS_Host *host) 715{ 716 int from_queue = 0; 717 Scsi_Cmnd *SCpnt; 718 719 /* first check to see if a command is waiting to be executed */ 720 SCpnt = host->origSCpnt; 721 host->origSCpnt = NULL; 722 723 /* retrieve next command */ 724 if (!SCpnt) { 725 SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns); 726 if (!SCpnt) 727 return INTR_IDLE; 728 729 from_queue = 1; 730 } 731 732 if (host->scsi.disconnectable && host->SCpnt) { 733 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); 734 host->scsi.disconnectable = 0; 735#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 736 DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n", 737 host->host->host_no, acornscsi_target(host))); 738#endif 739 host->SCpnt = NULL; 740 } 741 742 /* 743 * If we have an interrupt pending, then we may have been reselected. 744 * In this case, we don't want to write to the registers 745 */ 746 if (!(sbic_arm_read(host->scsi.io_port, ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { 747 sbic_arm_write(host->scsi.io_port, DESTID, SCpnt->target); 748 sbic_arm_write(host->scsi.io_port, CMND, CMND_SELWITHATN); 749 } 750 751 /* 752 * claim host busy - all of these must happen atomically wrt 753 * our interrupt routine. Failure means command loss. 754 */ 755 host->scsi.phase = PHASE_CONNECTING; 756 host->SCpnt = SCpnt; 757 host->scsi.SCp = SCpnt->SCp; 758 host->dma.xfer_setup = 0; 759 host->dma.xfer_required = 0; 760 host->dma.xfer_done = 0; 761 762#if (DEBUG & (DEBUG_ABORT|DEBUG_CONNECT)) 763 DBG(SCpnt,printk("scsi%d.%c: starting cmd %02X\n", 764 host->host->host_no, '0' + SCpnt->target, 765 SCpnt->cmnd[0])); 766#endif 767 768 if (from_queue) { 769#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 770 /* 771 * tagged queueing - allocate a new tag to this command 772 */ 773 if (SCpnt->device->tagged_queue) { 774 SCpnt->device->current_tag += 1; 775 if (SCpnt->device->current_tag == 0) 776 SCpnt->device->current_tag = 1; 777 SCpnt->tag = SCpnt->device->current_tag; 778 } else 779#endif 780 set_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); 781 782 host->stats.removes += 1; 783 784 switch (acornscsi_cmdtype(SCpnt->cmnd[0])) { 785 case CMD_WRITE: 786 host->stats.writes += 1; 787 break; 788 case CMD_READ: 789 host->stats.reads += 1; 790 break; 791 case CMD_MISC: 792 host->stats.miscs += 1; 793 break; 794 } 795 } 796 797 return INTR_PROCESSING; 798} 799 800/* 801 * Function: void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) 802 * Purpose : complete processing for command 803 * Params : host - interface that completed 804 * result - driver byte of result 805 */ 806static 807void acornscsi_done(AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result) 808{ 809 Scsi_Cmnd *SCpnt = *SCpntp; 810 811 /* clean up */ 812 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); 813 814 host->stats.fins += 1; 815 816 if (SCpnt) { 817 *SCpntp = NULL; 818 819 acornscsi_dma_cleanup(host); 820 821 SCpnt->result = result << 16 | host->scsi.SCp.Message << 8 | host->scsi.SCp.Status; 822 823 /* 824 * In theory, this should not happen. In practice, it seems to. 825 * Only trigger an error if the device attempts to report all happy 826 * but with untransferred buffers... If we don't do something, then 827 * data loss will occur. Should we check SCpnt->underflow here? 828 * It doesn't appear to be set to something meaningful by the higher 829 * levels all the time. 830 */ 831 if (result == DID_OK) { 832 int xfer_warn = 0; 833 834 if (SCpnt->underflow == 0) { 835 if (host->scsi.SCp.ptr && 836 acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC) 837 xfer_warn = 1; 838 } else { 839 if (host->scsi.SCp.scsi_xferred < SCpnt->underflow || 840 host->scsi.SCp.scsi_xferred != host->dma.transferred) 841 xfer_warn = 1; 842 } 843 844 /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6) 845 * Targets which break data transfers into multiple 846 * connections shall end each successful connection 847 * (except possibly the last) with a SAVE DATA 848 * POINTER - DISCONNECT message sequence. 849 * 850 * This makes it difficult to ensure that a transfer has 851 * completed. If we reach the end of a transfer during 852 * the command, then we can only have finished the transfer. 853 * therefore, if we seem to have some data remaining, this 854 * is not a problem. 855 */ 856 if (host->dma.xfer_done) 857 xfer_warn = 0; 858 859 if (xfer_warn) { 860 switch (status_byte(SCpnt->result)) { 861 case CHECK_CONDITION: 862 case COMMAND_TERMINATED: 863 case BUSY: 864 case QUEUE_FULL: 865 case RESERVATION_CONFLICT: 866 break; 867 868 default: 869 printk(KERN_ERR "scsi%d.H: incomplete data transfer detected: result=%08X command=", 870 host->host->host_no, SCpnt->result); 871 print_command(SCpnt->cmnd); 872 acornscsi_dumpdma(host, "done"); 873 acornscsi_dumplog(host, SCpnt->target); 874 SCpnt->result &= 0xffff; 875 SCpnt->result |= DID_ERROR << 16; 876 } 877 } 878 } 879 880 if (!SCpnt->scsi_done) 881 panic("scsi%d.H: null scsi_done function in acornscsi_done", host->host->host_no); 882 883 clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); 884 885 SCpnt->scsi_done(SCpnt); 886 } else 887 printk("scsi%d: null command in acornscsi_done", host->host->host_no); 888 889 host->scsi.phase = PHASE_IDLE; 890} 891 892/* ==================================================================================== 893 * DMA routines 894 */ 895/* 896 * Purpose : update SCSI Data Pointer 897 * Notes : this will only be one SG entry or less 898 */ 899static 900void acornscsi_data_updateptr(AS_Host *host, Scsi_Pointer *SCp, unsigned int length) 901{ 902 SCp->ptr += length; 903 SCp->this_residual -= length; 904 905 if (!SCp->this_residual) { 906 if (SCp->buffers_residual) { 907 SCp->buffer++; 908 SCp->buffers_residual--; 909 SCp->ptr = (char *)SCp->buffer->address; 910 SCp->this_residual = SCp->buffer->length; 911 } else { 912 SCp->ptr = NULL; 913 host->dma.xfer_done = 1; 914 } 915 } 916} 917 918/* 919 * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr, 920 * unsigned int start_addr, unsigned int length) 921 * Purpose : read data from DMA RAM 922 * Params : host - host to transfer from 923 * ptr - DRAM address 924 * start_addr - host mem address 925 * length - number of bytes to transfer 926 * Notes : this will only be one SG entry or less 927 */ 928static 929void acornscsi_data_read(AS_Host *host, char *ptr, 930 unsigned int start_addr, unsigned int length) 931{ 932 extern void __acornscsi_in(int port, char *buf, int len); 933 unsigned int page, offset, len = length; 934 935 page = (start_addr >> 12); 936 offset = start_addr & ((1 << 12) - 1); 937 938 outb((page & 0x3f) | host->card.page_reg, host->card.io_page); 939 940 while (len > 0) { 941 unsigned int this_len; 942 943 if (len + offset > (1 << 12)) 944 this_len = (1 << 12) - offset; 945 else 946 this_len = len; 947 948 __acornscsi_in(host->card.io_ram + (offset << 1), ptr, this_len); 949 950 offset += this_len; 951 ptr += this_len; 952 len -= this_len; 953 954 if (offset == (1 << 12)) { 955 offset = 0; 956 page ++; 957 outb((page & 0x3f) | host->card.page_reg, host->card.io_page); 958 } 959 } 960 outb(host->card.page_reg, host->card.io_page); 961} 962 963/* 964 * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr, 965 * unsigned int start_addr, unsigned int length) 966 * Purpose : write data to DMA RAM 967 * Params : host - host to transfer from 968 * ptr - DRAM address 969 * start_addr - host mem address 970 * length - number of bytes to transfer 971 * Notes : this will only be one SG entry or less 972 */ 973static 974void acornscsi_data_write(AS_Host *host, char *ptr, 975 unsigned int start_addr, unsigned int length) 976{ 977 extern void __acornscsi_out(int port, char *buf, int len); 978 unsigned int page, offset, len = length; 979 980 page = (start_addr >> 12); 981 offset = start_addr & ((1 << 12) - 1); 982 983 outb((page & 0x3f) | host->card.page_reg, host->card.io_page); 984 985 while (len > 0) { 986 unsigned int this_len; 987 988 if (len + offset > (1 << 12)) 989 this_len = (1 << 12) - offset; 990 else 991 this_len = len; 992 993 __acornscsi_out(host->card.io_ram + (offset << 1), ptr, this_len); 994 995 offset += this_len; 996 ptr += this_len; 997 len -= this_len; 998 999 if (offset == (1 << 12)) { 1000 offset = 0; 1001 page ++; 1002 outb((page & 0x3f) | host->card.page_reg, host->card.io_page); 1003 } 1004 } 1005 outb(host->card.page_reg, host->card.io_page); 1006} 1007 1008/* ========================================================================================= 1009 * On-board DMA routines 1010 */ 1011#ifdef USE_DMAC 1012/* 1013 * Prototype: void acornscsi_dmastop(AS_Host *host) 1014 * Purpose : stop all DMA 1015 * Params : host - host on which to stop DMA 1016 * Notes : This is called when leaving DATA IN/OUT phase, 1017 * or when interface is RESET 1018 */ 1019static inline 1020void acornscsi_dma_stop(AS_Host *host) 1021{ 1022 dmac_write(host->dma.io_port, MASKREG, MASK_ON); 1023 dmac_clearintr(host->dma.io_intr_clear); 1024 1025#if (DEBUG & DEBUG_DMA) 1026 DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); 1027#endif 1028} 1029 1030/* 1031 * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) 1032 * Purpose : setup DMA controller for data transfer 1033 * Params : host - host to setup 1034 * direction - data transfer direction 1035 * Notes : This is called when entering DATA I/O phase, not 1036 * while we're in a DATA I/O phase 1037 */ 1038static 1039void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) 1040{ 1041 unsigned int address, length, mode; 1042 1043 host->dma.direction = direction; 1044 1045 dmac_write(host->dma.io_port, MASKREG, MASK_ON); 1046 1047 if (direction == DMA_OUT) { 1048#if (DEBUG & DEBUG_NO_WRITE) 1049 if (NO_WRITE & (1 << host->SCpnt->target)) { 1050 printk(KERN_CRIT "scsi%d.%c: I can't handle DMA_OUT!\n", 1051 host->host->host_no, acornscsi_target(host)); 1052 return; 1053 } 1054#endif 1055 mode = DMAC_WRITE; 1056 } else 1057 mode = DMAC_READ; 1058 1059 /* 1060 * Allocate some buffer space, limited to half the buffer size 1061 */ 1062 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); 1063 if (length) { 1064 host->dma.start_addr = address = host->dma.free_addr; 1065 host->dma.free_addr = (host->dma.free_addr + length) & 1066 (DMAC_BUFFER_SIZE - 1); 1067 1068 /* 1069 * Transfer data to DMA memory 1070 */ 1071 if (direction == DMA_OUT) 1072 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, 1073 length); 1074 1075 length -= 1; 1076 dmac_write(host->dma.io_port, TXCNTLO, length); 1077 dmac_write(host->dma.io_port, TXCNTHI, length >> 8); 1078 dmac_write(host->dma.io_port, TXADRLO, address); 1079 dmac_write(host->dma.io_port, TXADRMD, address >> 8); 1080 dmac_write(host->dma.io_port, TXADRHI, 0); 1081 dmac_write(host->dma.io_port, MODECON, mode); 1082 dmac_write(host->dma.io_port, MASKREG, MASK_OFF); 1083 1084#if (DEBUG & DEBUG_DMA) 1085 DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); 1086#endif 1087 host->dma.xfer_setup = 1; 1088 } 1089} 1090 1091/* 1092 * Function: void acornscsi_dma_cleanup(AS_Host *host) 1093 * Purpose : ensure that all DMA transfers are up-to-date & host->scsi.SCp is correct 1094 * Params : host - host to finish 1095 * Notes : This is called when a command is: 1096 * terminating, RESTORE_POINTERS, SAVE_POINTERS, DISCONECT 1097 * : This must not return until all transfers are completed. 1098 */ 1099static 1100void acornscsi_dma_cleanup(AS_Host *host) 1101{ 1102 dmac_write(host->dma.io_port, MASKREG, MASK_ON); 1103 dmac_clearintr(host->dma.io_intr_clear); 1104 1105 /* 1106 * Check for a pending transfer 1107 */ 1108 if (host->dma.xfer_required) { 1109 host->dma.xfer_required = 0; 1110 if (host->dma.direction == DMA_IN) 1111 acornscsi_data_read(host, host->dma.xfer_ptr, 1112 host->dma.xfer_start, host->dma.xfer_length); 1113 } 1114 1115 /* 1116 * Has a transfer been setup? 1117 */ 1118 if (host->dma.xfer_setup) { 1119 unsigned int transferred; 1120 1121 host->dma.xfer_setup = 0; 1122 1123#if (DEBUG & DEBUG_DMA) 1124 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi")); 1125#endif 1126 1127 /* 1128 * Calculate number of bytes transferred from DMA. 1129 */ 1130 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; 1131 host->dma.transferred += transferred; 1132 1133 if (host->dma.direction == DMA_IN) 1134 acornscsi_data_read(host, host->scsi.SCp.ptr, 1135 host->dma.start_addr, transferred); 1136 1137 /* 1138 * Update SCSI pointers 1139 */ 1140 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); 1141#if (DEBUG & DEBUG_DMA) 1142 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo")); 1143#endif 1144 } 1145} 1146 1147/* 1148 * Function: void acornscsi_dmacintr(AS_Host *host) 1149 * Purpose : handle interrupts from DMAC device 1150 * Params : host - host to process 1151 * Notes : If reading, we schedule the read to main memory & 1152 * allow the transfer to continue. 1153 * : If writing, we fill the onboard DMA memory from main 1154 * memory. 1155 * : Called whenever DMAC finished it's current transfer. 1156 */ 1157static 1158void acornscsi_dma_intr(AS_Host *host) 1159{ 1160 unsigned int address, length, transferred; 1161 1162#if (DEBUG & DEBUG_DMA) 1163 DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); 1164#endif 1165 1166 dmac_write(host->dma.io_port, MASKREG, MASK_ON); 1167 dmac_clearintr(host->dma.io_intr_clear); 1168 1169 /* 1170 * Calculate amount transferred via DMA 1171 */ 1172 transferred = dmac_address(host->dma.io_port) - host->dma.start_addr; 1173 host->dma.transferred += transferred; 1174 1175 /* 1176 * Schedule DMA transfer off board 1177 */ 1178 if (host->dma.direction == DMA_IN) { 1179 host->dma.xfer_start = host->dma.start_addr; 1180 host->dma.xfer_length = transferred; 1181 host->dma.xfer_ptr = host->scsi.SCp.ptr; 1182 host->dma.xfer_required = 1; 1183 } 1184 1185 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); 1186 1187 /* 1188 * Allocate some buffer space, limited to half the on-board RAM size 1189 */ 1190 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); 1191 if (length) { 1192 host->dma.start_addr = address = host->dma.free_addr; 1193 host->dma.free_addr = (host->dma.free_addr + length) & 1194 (DMAC_BUFFER_SIZE - 1); 1195 1196 /* 1197 * Transfer data to DMA memory 1198 */ 1199 if (host->dma.direction == DMA_OUT) 1200 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, 1201 length); 1202 1203 length -= 1; 1204 dmac_write(host->dma.io_port, TXCNTLO, length); 1205 dmac_write(host->dma.io_port, TXCNTHI, length >> 8); 1206 dmac_write(host->dma.io_port, TXADRLO, address); 1207 dmac_write(host->dma.io_port, TXADRMD, address >> 8); 1208 dmac_write(host->dma.io_port, TXADRHI, 0); 1209 dmac_write(host->dma.io_port, MASKREG, MASK_OFF); 1210 1211#if (DEBUG & DEBUG_DMA) 1212 DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); 1213#endif 1214 } else { 1215 host->dma.xfer_setup = 0; 1216 } 1217} 1218 1219/* 1220 * Function: void acornscsi_dma_xfer(AS_Host *host) 1221 * Purpose : transfer data between AcornSCSI and memory 1222 * Params : host - host to process 1223 */ 1224static 1225void acornscsi_dma_xfer(AS_Host *host) 1226{ 1227 host->dma.xfer_required = 0; 1228 1229 if (host->dma.direction == DMA_IN) 1230 acornscsi_data_read(host, host->dma.xfer_ptr, 1231 host->dma.xfer_start, host->dma.xfer_length); 1232} 1233 1234/* 1235 * Function: void acornscsi_dma_adjust(AS_Host *host) 1236 * Purpose : adjust DMA pointers & count for bytes transferred to 1237 * SBIC but not SCSI bus. 1238 * Params : host - host to adjust DMA count for 1239 */ 1240static 1241void acornscsi_dma_adjust(AS_Host *host) 1242{ 1243 if (host->dma.xfer_setup) { 1244 signed long transferred; 1245#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) 1246 DBG(host->SCpnt, acornscsi_dumpdma(host, "adji")); 1247#endif 1248 /* 1249 * Calculate correct DMA address - DMA is ahead of SCSI bus while 1250 * writing. 1251 * host->scsi.SCp.scsi_xferred is the number of bytes 1252 * actually transferred to/from the SCSI bus. 1253 * host->dma.transferred is the number of bytes transferred 1254 * over DMA since host->dma.start_addr was last set. 1255 * 1256 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred 1257 * - host->dma.transferred 1258 */ 1259 transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred; 1260 if (transferred < 0) 1261 printk("scsi%d.%c: Ack! DMA write correction %ld < 0!\n", 1262 host->host->host_no, acornscsi_target(host), transferred); 1263 else if (transferred == 0) 1264 host->dma.xfer_setup = 0; 1265 else { 1266 transferred += host->dma.start_addr; 1267 dmac_write(host->dma.io_port, TXADRLO, transferred); 1268 dmac_write(host->dma.io_port, TXADRMD, transferred >> 8); 1269 dmac_write(host->dma.io_port, TXADRHI, transferred >> 16); 1270#if (DEBUG & (DEBUG_DMA|DEBUG_WRITE)) 1271 DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); 1272#endif 1273 } 1274 } 1275} 1276#endif 1277 1278/* ========================================================================================= 1279 * Data I/O 1280 */ 1281static int 1282acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout) 1283{ 1284 unsigned int asr, timeout = max_timeout; 1285 int my_ptr = *ptr; 1286 1287 while (my_ptr < len) { 1288 asr = sbic_arm_read(host->scsi.io_port, ASR); 1289 1290 if (asr & ASR_DBR) { 1291 timeout = max_timeout; 1292 1293 sbic_arm_write(host->scsi.io_port, DATA, bytes[my_ptr++]); 1294 } else if (asr & ASR_INT) 1295 break; 1296 else if (--timeout == 0) 1297 break; 1298 udelay(1); 1299 } 1300 1301 *ptr = my_ptr; 1302 1303 return (timeout == 0) ? -1 : 0; 1304} 1305 1306/* 1307 * Function: void acornscsi_sendcommand(AS_Host *host) 1308 * Purpose : send a command to a target 1309 * Params : host - host which is connected to target 1310 */ 1311static void 1312acornscsi_sendcommand(AS_Host *host) 1313{ 1314 Scsi_Cmnd *SCpnt = host->SCpnt; 1315 1316 sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); 1317 sbic_arm_writenext(host->scsi.io_port, 0); 1318 sbic_arm_writenext(host->scsi.io_port, SCpnt->cmd_len - host->scsi.SCp.sent_command); 1319 1320 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); 1321 1322 if (acornscsi_write_pio(host, SCpnt->cmnd, 1323 (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000)) 1324 printk("scsi%d: timeout while sending command\n", host->host->host_no); 1325 1326 host->scsi.phase = PHASE_COMMAND; 1327} 1328 1329static 1330void acornscsi_sendmessage(AS_Host *host) 1331{ 1332 unsigned int message_length = msgqueue_msglength(&host->scsi.msgs); 1333 unsigned int msgnr; 1334 struct message *msg; 1335 1336#if (DEBUG & DEBUG_MESSAGES) 1337 printk("scsi%d.%c: sending message ", 1338 host->host->host_no, acornscsi_target(host)); 1339#endif 1340 1341 switch (message_length) { 1342 case 0: 1343 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); 1344 1345 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); 1346 1347 sbic_arm_write(host->scsi.io_port, DATA, NOP); 1348 1349 host->scsi.last_message = NOP; 1350#if (DEBUG & DEBUG_MESSAGES) 1351 printk("NOP"); 1352#endif 1353 break; 1354 1355 case 1: 1356 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); 1357 msg = msgqueue_getmsg(&host->scsi.msgs, 0); 1358 1359 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); 1360 1361 sbic_arm_write(host->scsi.io_port, DATA, msg->msg[0]); 1362 1363 host->scsi.last_message = msg->msg[0]; 1364#if (DEBUG & DEBUG_MESSAGES) 1365 print_msg(msg->msg); 1366#endif 1367 break; 1368 1369 default: 1370 /* 1371 * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14) 1372 * 'When a target sends this (MESSAGE_REJECT) message, it 1373 * shall change to MESSAGE IN phase and send this message 1374 * prior to requesting additional message bytes from the 1375 * initiator. This provides an interlock so that the 1376 * initiator can determine which message byte is rejected. 1377 */ 1378 sbic_arm_write(host->scsi.io_port, TRANSCNTH, 0); 1379 sbic_arm_writenext(host->scsi.io_port, 0); 1380 sbic_arm_writenext(host->scsi.io_port, message_length); 1381 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); 1382 1383 msgnr = 0; 1384 while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) { 1385 unsigned int i; 1386#if (DEBUG & DEBUG_MESSAGES) 1387 print_msg(msg); 1388#endif 1389 i = 0; 1390 if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000)) 1391 printk("scsi%d: timeout while sending message\n", host->host->host_no); 1392 1393 host->scsi.last_message = msg->msg[0]; 1394 if (msg->msg[0] == EXTENDED_MESSAGE) 1395 host->scsi.last_message |= msg->msg[2] << 8; 1396 1397 if (i != msg->length) 1398 break; 1399 } 1400 break; 1401 } 1402#if (DEBUG & DEBUG_MESSAGES) 1403 printk("\n"); 1404#endif 1405} 1406 1407/* 1408 * Function: void acornscsi_readstatusbyte(AS_Host *host) 1409 * Purpose : Read status byte from connected target 1410 * Params : host - host connected to target 1411 */ 1412static 1413void acornscsi_readstatusbyte(AS_Host *host) 1414{ 1415 acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); 1416 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); 1417 host->scsi.SCp.Status = sbic_arm_read(host->scsi.io_port, DATA); 1418} 1419 1420/* 1421 * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host) 1422 * Purpose : Read one message byte from connected target 1423 * Params : host - host connected to target 1424 */ 1425static 1426unsigned char acornscsi_readmessagebyte(AS_Host *host) 1427{ 1428 unsigned char message; 1429 1430 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); 1431 1432 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); 1433 1434 message = sbic_arm_read(host->scsi.io_port, DATA); 1435 1436 /* wait for MSGIN-XFER-PAUSED */ 1437 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); 1438 1439 sbic_arm_read(host->scsi.io_port, SSR); 1440 1441 return message; 1442} 1443 1444/* 1445 * Function: void acornscsi_message(AS_Host *host) 1446 * Purpose : Read complete message from connected target & action message 1447 * Params : host - host connected to target 1448 */ 1449static 1450void acornscsi_message(AS_Host *host) 1451{ 1452 unsigned char message[16]; 1453 unsigned int msgidx = 0, msglen = 1; 1454 1455 do { 1456 message[msgidx] = acornscsi_readmessagebyte(host); 1457 1458 switch (msgidx) { 1459 case 0: 1460 if (message[0] == EXTENDED_MESSAGE || 1461 (message[0] >= 0x20 && message[0] <= 0x2f)) 1462 msglen = 2; 1463 break; 1464 1465 case 1: 1466 if (message[0] == EXTENDED_MESSAGE) 1467 msglen += message[msgidx]; 1468 break; 1469 } 1470 msgidx += 1; 1471 if (msgidx < msglen) { 1472 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); 1473 1474 /* wait for next msg-in */ 1475 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); 1476 sbic_arm_read(host->scsi.io_port, SSR); 1477 } 1478 } while (msgidx < msglen); 1479 1480#if (DEBUG & DEBUG_MESSAGES) 1481 printk("scsi%d.%c: message in: ", 1482 host->host->host_no, acornscsi_target(host)); 1483 print_msg(message); 1484 printk("\n"); 1485#endif 1486 1487 if (host->scsi.phase == PHASE_RECONNECTED) { 1488 /* 1489 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17) 1490 * 'Whenever a target reconnects to an initiator to continue 1491 * a tagged I/O process, the SIMPLE QUEUE TAG message shall 1492 * be sent immediately following the IDENTIFY message...' 1493 */ 1494 if (message[0] == SIMPLE_QUEUE_TAG) 1495 host->scsi.reconnected.tag = message[1]; 1496 if (acornscsi_reconnect_finish(host)) 1497 host->scsi.phase = PHASE_MSGIN; 1498 } 1499 1500 switch (message[0]) { 1501 case ABORT: 1502 case ABORT_TAG: 1503 case COMMAND_COMPLETE: 1504 if (host->scsi.phase != PHASE_STATUSIN) { 1505 printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", 1506 host->host->host_no, acornscsi_target(host)); 1507 acornscsi_dumplog(host, host->SCpnt->target); 1508 } 1509 host->scsi.phase = PHASE_DONE; 1510 host->scsi.SCp.Message = message[0]; 1511 break; 1512 1513 case SAVE_POINTERS: 1514 /* 1515 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20) 1516 * 'The SAVE DATA POINTER message is sent from a target to 1517 * direct the initiator to copy the active data pointer to 1518 * the saved data pointer for the current I/O process. 1519 */ 1520 acornscsi_dma_cleanup(host); 1521 host->SCpnt->SCp = host->scsi.SCp; 1522 host->SCpnt->SCp.sent_command = 0; 1523 host->scsi.phase = PHASE_MSGIN; 1524 break; 1525 1526 case RESTORE_POINTERS: 1527 /* 1528 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19) 1529 * 'The RESTORE POINTERS message is sent from a target to 1530 * direct the initiator to copy the most recently saved 1531 * command, data, and status pointers for the I/O process 1532 * to the corresponding active pointers. The command and 1533 * status pointers shall be restored to the beginning of 1534 * the present command and status areas.' 1535 */ 1536 acornscsi_dma_cleanup(host); 1537 host->scsi.SCp = host->SCpnt->SCp; 1538 host->scsi.phase = PHASE_MSGIN; 1539 break; 1540 1541 case DISCONNECT: 1542 /* 1543 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2) 1544 * 'On those occasions when an error or exception condition occurs 1545 * and the target elects to repeat the information transfer, the 1546 * target may repeat the transfer either issuing a RESTORE POINTERS 1547 * message or by disconnecting without issuing a SAVE POINTERS 1548 * message. When reconnection is completed, the most recent 1549 * saved pointer values are restored.' 1550 */ 1551 acornscsi_dma_cleanup(host); 1552 host->scsi.phase = PHASE_DISCONNECT; 1553 break; 1554 1555 case MESSAGE_REJECT: 1556 1557 /* 1558 * If we have any messages waiting to go out, then assert ATN now 1559 */ 1560 if (msgqueue_msglength(&host->scsi.msgs)) 1561 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); 1562 1563 switch (host->scsi.last_message) { 1564#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 1565 case HEAD_OF_QUEUE_TAG: 1566 case ORDERED_QUEUE_TAG: 1567 case SIMPLE_QUEUE_TAG: 1568 /* 1569 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17) 1570 * If a target does not implement tagged queuing and a queue tag 1571 * message is received, it shall respond with a MESSAGE REJECT 1572 * message and accept the I/O process as if it were untagged. 1573 */ 1574 printk(KERN_NOTICE "scsi%d.%c: disabling tagged queueing\n", 1575 host->host->host_no, acornscsi_target(host)); 1576 host->SCpnt->device->tagged_queue = 0; 1577 set_bit(host->SCpnt->target * 8 + host->SCpnt->lun, &host->busyluns); 1578 break; 1579#endif 1580 case EXTENDED_MESSAGE | (EXTENDED_SDTR << 8): 1581 /* 1582 * Target can't handle synchronous transfers 1583 */ 1584 printk(KERN_NOTICE "scsi%d.%c: Using asynchronous transfer\n", 1585 host->host->host_no, acornscsi_target(host)); 1586 host->device[host->SCpnt->target].sync_xfer = SYNCHTRANSFER_2DBA; 1587 host->device[host->SCpnt->target].sync_state = SYNC_ASYNCHRONOUS; 1588 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); 1589 break; 1590 1591 default: 1592 break; 1593 } 1594 break; 1595 1596 case QUEUE_FULL: 1597 /* TODO: target queue is full */ 1598 break; 1599 1600 case SIMPLE_QUEUE_TAG: 1601 /* tag queue reconnect... message[1] = queue tag. Print something to indicate something happened! */ 1602 printk("scsi%d.%c: reconnect queue tag %02X\n", 1603 host->host->host_no, acornscsi_target(host), 1604 message[1]); 1605 break; 1606 1607 case EXTENDED_MESSAGE: 1608 switch (message[2]) { 1609#ifdef CONFIG_SCSI_ACORNSCSI_SYNC 1610 case EXTENDED_SDTR: 1611 if (host->device[host->SCpnt->target].sync_state == SYNC_SENT_REQUEST) { 1612 /* 1613 * We requested synchronous transfers. This isn't quite right... 1614 * We can only say if this succeeded if we proceed on to execute the 1615 * command from this message. If we get a MESSAGE PARITY ERROR, 1616 * and the target retries fail, then we fallback to asynchronous mode 1617 */ 1618 host->device[host->SCpnt->target].sync_state = SYNC_COMPLETED; 1619 printk(KERN_NOTICE "scsi%d.%c: Using synchronous transfer, offset %d, %d ns\n", 1620 host->host->host_no, acornscsi_target(host), 1621 message[4], message[3] * 4); 1622 host->device[host->SCpnt->target].sync_xfer = 1623 calc_sync_xfer(message[3] * 4, message[4]); 1624 } else { 1625 unsigned char period, length; 1626 /* 1627 * Target requested synchronous transfers. The agreement is only 1628 * to be in operation AFTER the target leaves message out phase. 1629 */ 1630 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); 1631 period = max_t(unsigned int, message[3], sdtr_period / 4); 1632 length = min_t(unsigned int, message[4], sdtr_size); 1633 msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, 1634 EXTENDED_SDTR, period, length); 1635 host->device[host->SCpnt->target].sync_xfer = 1636 calc_sync_xfer(period * 4, length); 1637 } 1638 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); 1639 break; 1640#else 1641 /* We do not accept synchronous transfers. Respond with a 1642 * MESSAGE_REJECT. 1643 */ 1644#endif 1645 1646 case EXTENDED_WDTR: 1647 /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT 1648 * to a wide data transfer request. 1649 */ 1650 default: 1651 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); 1652 msgqueue_flush(&host->scsi.msgs); 1653 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); 1654 break; 1655 } 1656 break; 1657 1658#ifdef CONFIG_SCSI_ACORNSCSI_LINK 1659 case LINKED_CMD_COMPLETE: 1660 case LINKED_FLG_CMD_COMPLETE: 1661 /* 1662 * We don't support linked commands yet 1663 */ 1664 if (0) { 1665#if (DEBUG & DEBUG_LINK) 1666 printk("scsi%d.%c: lun %d tag %d linked command complete\n", 1667 host->host->host_no, acornscsi_target(host), host->SCpnt->tag); 1668#endif 1669 /* 1670 * A linked command should only terminate with one of these messages 1671 * if there are more linked commands available. 1672 */ 1673 if (!host->SCpnt->next_link) { 1674 printk(KERN_WARNING "scsi%d.%c: lun %d tag %d linked command complete, but no next_link\n", 1675 instance->host_no, acornscsi_target(host), host->SCpnt->tag); 1676 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); 1677 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); 1678 } else { 1679 Scsi_Cmnd *SCpnt = host->SCpnt; 1680 1681 acornscsi_dma_cleanup(host); 1682 1683 host->SCpnt = host->SCpnt->next_link; 1684 host->SCpnt->tag = SCpnt->tag; 1685 SCpnt->result = DID_OK | host->scsi.SCp.Message << 8 | host->Scsi.SCp.Status; 1686 SCpnt->done(SCpnt); 1687 1688 /* initialise host->SCpnt->SCp */ 1689 } 1690 break; 1691 } 1692#endif 1693 1694 default: /* reject message */ 1695 printk(KERN_ERR "scsi%d.%c: unrecognised message %02X, rejecting\n", 1696 host->host->host_no, acornscsi_target(host), 1697 message[0]); 1698 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); 1699 msgqueue_flush(&host->scsi.msgs); 1700 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); 1701 host->scsi.phase = PHASE_MSGIN; 1702 break; 1703 } 1704 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); 1705} 1706 1707/* 1708 * Function: int acornscsi_buildmessages(AS_Host *host) 1709 * Purpose : build the connection messages for a host 1710 * Params : host - host to add messages to 1711 */ 1712static 1713void acornscsi_buildmessages(AS_Host *host) 1714{ 1715 1716 msgqueue_addmsg(&host->scsi.msgs, 1, 1717 IDENTIFY(host->device[host->SCpnt->target].disconnect_ok, 1718 host->SCpnt->lun)); 1719 1720 1721#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 1722 if (host->SCpnt->tag) { 1723 unsigned int tag_type; 1724 1725 if (host->SCpnt->cmnd[0] == REQUEST_SENSE || 1726 host->SCpnt->cmnd[0] == TEST_UNIT_READY || 1727 host->SCpnt->cmnd[0] == INQUIRY) 1728 tag_type = HEAD_OF_QUEUE_TAG; 1729 else 1730 tag_type = SIMPLE_QUEUE_TAG; 1731 msgqueue_addmsg(&host->scsi.msgs, 2, tag_type, host->SCpnt->tag); 1732 } 1733#endif 1734 1735#ifdef CONFIG_SCSI_ACORNSCSI_SYNC 1736 if (host->device[host->SCpnt->target].sync_state == SYNC_NEGOCIATE) { 1737 host->device[host->SCpnt->target].sync_state = SYNC_SENT_REQUEST; 1738 msgqueue_addmsg(&host->scsi.msgs, 5, 1739 EXTENDED_MESSAGE, 3, EXTENDED_SDTR, 1740 sdtr_period / 4, sdtr_size); 1741 } 1742#endif 1743} 1744 1745/* 1746 * Function: int acornscsi_starttransfer(AS_Host *host) 1747 * Purpose : transfer data to/from connected target 1748 * Params : host - host to which target is connected 1749 * Returns : 0 if failure 1750 */ 1751static 1752int acornscsi_starttransfer(AS_Host *host) 1753{ 1754 int residual; 1755 1756 if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) { 1757 printk(KERN_ERR "scsi%d.%c: null buffer passed to acornscsi_starttransfer\n", 1758 host->host->host_no, acornscsi_target(host)); 1759 return 0; 1760 } 1761 1762 residual = host->SCpnt->request_bufflen - host->scsi.SCp.scsi_xferred; 1763 1764 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, host->device[host->SCpnt->target].sync_xfer); 1765 sbic_arm_writenext(host->scsi.io_port, residual >> 16); 1766 sbic_arm_writenext(host->scsi.io_port, residual >> 8); 1767 sbic_arm_writenext(host->scsi.io_port, residual); 1768 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); 1769 return 1; 1770} 1771 1772/* ========================================================================================= 1773 * Connection & Disconnection 1774 */ 1775/* 1776 * Function : acornscsi_reconnect(AS_Host *host) 1777 * Purpose : reconnect a previously disconnected command 1778 * Params : host - host specific data 1779 * Remarks : SCSI spec says: 1780 * 'The set of active pointers is restored from the set 1781 * of saved pointers upon reconnection of the I/O process' 1782 */ 1783static 1784int acornscsi_reconnect(AS_Host *host) 1785{ 1786 unsigned int target, lun, ok = 0; 1787 1788 target = sbic_arm_read(host->scsi.io_port, SOURCEID); 1789 1790 if (!(target & 8)) 1791 printk(KERN_ERR "scsi%d: invalid source id after reselection " 1792 "- device fault?\n", 1793 host->host->host_no); 1794 1795 target &= 7; 1796 1797 if (host->SCpnt && !host->scsi.disconnectable) { 1798 printk(KERN_ERR "scsi%d.%d: reconnected while command in " 1799 "progress to target %d?\n", 1800 host->host->host_no, target, host->SCpnt->target); 1801 host->SCpnt = NULL; 1802 } 1803 1804 lun = sbic_arm_read(host->scsi.io_port, DATA) & 7; 1805 1806 host->scsi.reconnected.target = target; 1807 host->scsi.reconnected.lun = lun; 1808 host->scsi.reconnected.tag = 0; 1809 1810 if (host->scsi.disconnectable && host->SCpnt && 1811 host->SCpnt->target == target && host->SCpnt->lun == lun) 1812 ok = 1; 1813 1814 if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun)) 1815 ok = 1; 1816 1817 ADD_STATUS(target, 0x81, host->scsi.phase, 0); 1818 1819 if (ok) { 1820 host->scsi.phase = PHASE_RECONNECTED; 1821 } else { 1822 /* this doesn't seem to work */ 1823 printk(KERN_ERR "scsi%d.%c: reselected with no command " 1824 "to reconnect with\n", 1825 host->host->host_no, '0' + target); 1826 acornscsi_dumplog(host, target); 1827 acornscsi_abortcmd(host, 0); 1828 if (host->SCpnt) { 1829 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); 1830 host->SCpnt = NULL; 1831 } 1832 } 1833 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); 1834 return !ok; 1835} 1836 1837/* 1838 * Function: int acornscsi_reconect_finish(AS_Host *host) 1839 * Purpose : finish reconnecting a command 1840 * Params : host - host to complete 1841 * Returns : 0 if failed 1842 */ 1843static 1844int acornscsi_reconnect_finish(AS_Host *host) 1845{ 1846 if (host->scsi.disconnectable && host->SCpnt) { 1847 host->scsi.disconnectable = 0; 1848 if (host->SCpnt->target == host->scsi.reconnected.target && 1849 host->SCpnt->lun == host->scsi.reconnected.lun && 1850 host->SCpnt->tag == host->scsi.reconnected.tag) { 1851#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 1852 DBG(host->SCpnt, printk("scsi%d.%c: reconnected", 1853 host->host->host_no, acornscsi_target(host))); 1854#endif 1855 } else { 1856 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); 1857#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 1858 DBG(host->SCpnt, printk("scsi%d.%c: had to move command " 1859 "to disconnected queue\n", 1860 host->host->host_no, acornscsi_target(host))); 1861#endif 1862 host->SCpnt = NULL; 1863 } 1864 } 1865 if (!host->SCpnt) { 1866 host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected, 1867 host->scsi.reconnected.target, 1868 host->scsi.reconnected.lun, 1869 host->scsi.reconnected.tag); 1870#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 1871 DBG(host->SCpnt, printk("scsi%d.%c: had to get command", 1872 host->host->host_no, acornscsi_target(host))); 1873#endif 1874 } 1875 1876 if (!host->SCpnt) 1877 acornscsi_abortcmd(host, host->scsi.reconnected.tag); 1878 else { 1879 /* 1880 * Restore data pointer from SAVED pointers. 1881 */ 1882 host->scsi.SCp = host->SCpnt->SCp; 1883#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 1884 printk(", data pointers: [%p, %X]", 1885 host->scsi.SCp.ptr, host->scsi.SCp.this_residual); 1886#endif 1887 } 1888#if (DEBUG & (DEBUG_QUEUES|DEBUG_DISCON)) 1889 printk("\n"); 1890#endif 1891 1892 host->dma.transferred = host->scsi.SCp.scsi_xferred; 1893 1894 return host->SCpnt != NULL; 1895} 1896 1897/* 1898 * Function: void acornscsi_disconnect_unexpected(AS_Host *host) 1899 * Purpose : handle an unexpected disconnect 1900 * Params : host - host on which disconnect occurred 1901 */ 1902static 1903void acornscsi_disconnect_unexpected(AS_Host *host) 1904{ 1905 printk(KERN_ERR "scsi%d.%c: unexpected disconnect\n", 1906 host->host->host_no, acornscsi_target(host)); 1907#if (DEBUG & DEBUG_ABORT) 1908 acornscsi_dumplog(host, 8); 1909#endif 1910 1911 acornscsi_done(host, &host->SCpnt, DID_ERROR); 1912} 1913 1914/* 1915 * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag) 1916 * Purpose : abort a currently executing command 1917 * Params : host - host with connected command to abort 1918 * tag - tag to abort 1919 */ 1920static 1921void acornscsi_abortcmd(AS_Host *host, unsigned char tag) 1922{ 1923 host->scsi.phase = PHASE_ABORTED; 1924 sbic_arm_write(host->scsi.io_port, CMND, CMND_ASSERTATN); 1925 1926 msgqueue_flush(&host->scsi.msgs); 1927#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 1928 if (tag) 1929 msgqueue_addmsg(&host->scsi.msgs, 2, ABORT_TAG, tag); 1930 else 1931#endif 1932 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); 1933} 1934 1935/* ========================================================================================== 1936 * Interrupt routines. 1937 */ 1938/* 1939 * Function: int acornscsi_sbicintr(AS_Host *host) 1940 * Purpose : handle interrupts from SCSI device 1941 * Params : host - host to process 1942 * Returns : INTR_PROCESS if expecting another SBIC interrupt 1943 * INTR_IDLE if no interrupt 1944 * INTR_NEXT_COMMAND if we have finished processing the command 1945 */ 1946static 1947intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) 1948{ 1949 unsigned int asr, ssr; 1950 1951 asr = sbic_arm_read(host->scsi.io_port, ASR); 1952 if (!(asr & ASR_INT)) 1953 return INTR_IDLE; 1954 1955 ssr = sbic_arm_read(host->scsi.io_port, SSR); 1956 1957#if (DEBUG & DEBUG_PHASES) 1958 print_sbic_status(asr, ssr, host->scsi.phase); 1959#endif 1960 1961 ADD_STATUS(8, ssr, host->scsi.phase, in_irq); 1962 1963 if (host->SCpnt && !host->scsi.disconnectable) 1964 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq); 1965 1966 switch (ssr) { 1967 case 0x00: /* reset state - not advanced */ 1968 printk(KERN_ERR "scsi%d: reset in standard mode but wanted advanced mode.\n", 1969 host->host->host_no); 1970 /* setup sbic - WD33C93A */ 1971 sbic_arm_write(host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id); 1972 sbic_arm_write(host->scsi.io_port, CMND, CMND_RESET); 1973 return INTR_IDLE; 1974 1975 case 0x01: /* reset state - advanced */ 1976 sbic_arm_write(host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI); 1977 sbic_arm_write(host->scsi.io_port, TIMEOUT, TIMEOUT_TIME); 1978 sbic_arm_write(host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA); 1979 sbic_arm_write(host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP); 1980 msgqueue_flush(&host->scsi.msgs); 1981 return INTR_IDLE; 1982 1983 case 0x41: /* unexpected disconnect aborted command */ 1984 acornscsi_disconnect_unexpected(host); 1985 return INTR_NEXT_COMMAND; 1986 } 1987 1988 switch (host->scsi.phase) { 1989 case PHASE_CONNECTING: /* STATE: command removed from issue queue */ 1990 switch (ssr) { 1991 case 0x11: /* -> PHASE_CONNECTED */ 1992 /* BUS FREE -> SELECTION */ 1993 host->scsi.phase = PHASE_CONNECTED; 1994 msgqueue_flush(&host->scsi.msgs); 1995 host->dma.transferred = host->scsi.SCp.scsi_xferred; 1996 /* 33C93 gives next interrupt indicating bus phase */ 1997 asr = sbic_arm_read(host->scsi.io_port, ASR); 1998 if (!(asr & ASR_INT)) 1999 break; 2000 ssr = sbic_arm_read(host->scsi.io_port, SSR); 2001 ADD_STATUS(8, ssr, host->scsi.phase, 1); 2002 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, 1); 2003 goto connected; 2004 2005 case 0x42: /* select timed out */ 2006 /* -> PHASE_IDLE */ 2007 acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT); 2008 return INTR_NEXT_COMMAND; 2009 2010 case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */ 2011 /* BUS FREE -> RESELECTION */ 2012 host->origSCpnt = host->SCpnt; 2013 host->SCpnt = NULL; 2014 msgqueue_flush(&host->scsi.msgs); 2015 acornscsi_reconnect(host); 2016 break; 2017 2018 default: 2019 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTING, SSR %02X?\n", 2020 host->host->host_no, acornscsi_target(host), ssr); 2021 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2022 acornscsi_abortcmd(host, host->SCpnt->tag); 2023 } 2024 return INTR_PROCESSING; 2025 2026 connected: 2027 case PHASE_CONNECTED: /* STATE: device selected ok */ 2028 switch (ssr) { 2029#ifdef NONSTANDARD 2030 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ 2031 /* SELECTION -> COMMAND */ 2032 acornscsi_sendcommand(host); 2033 break; 2034 2035 case 0x8b: /* -> PHASE_STATUS */ 2036 /* SELECTION -> STATUS */ 2037 acornscsi_readstatusbyte(host); 2038 host->scsi.phase = PHASE_STATUSIN; 2039 break; 2040#endif 2041 2042 case 0x8e: /* -> PHASE_MSGOUT */ 2043 /* SELECTION ->MESSAGE OUT */ 2044 host->scsi.phase = PHASE_MSGOUT; 2045 acornscsi_buildmessages(host); 2046 acornscsi_sendmessage(host); 2047 break; 2048 2049 /* these should not happen */ 2050 case 0x85: /* target disconnected */ 2051 acornscsi_done(host, &host->SCpnt, DID_ERROR); 2052 break; 2053 2054 default: 2055 printk(KERN_ERR "scsi%d.%c: PHASE_CONNECTED, SSR %02X?\n", 2056 host->host->host_no, acornscsi_target(host), ssr); 2057 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2058 acornscsi_abortcmd(host, host->SCpnt->tag); 2059 } 2060 return INTR_PROCESSING; 2061 2062 case PHASE_MSGOUT: /* STATE: connected & sent IDENTIFY message */ 2063 /* 2064 * SCSI standard says that MESSAGE OUT phases can be followed by a 2065 * DATA phase, STATUS phase, MESSAGE IN phase or COMMAND phase 2066 */ 2067 switch (ssr) { 2068 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ 2069 case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ 2070 /* MESSAGE OUT -> COMMAND */ 2071 acornscsi_sendcommand(host); 2072 break; 2073 2074 case 0x8b: /* -> PHASE_STATUS */ 2075 case 0x1b: /* -> PHASE_STATUS */ 2076 /* MESSAGE OUT -> STATUS */ 2077 acornscsi_readstatusbyte(host); 2078 host->scsi.phase = PHASE_STATUSIN; 2079 break; 2080 2081 case 0x8e: /* -> PHASE_MSGOUT */ 2082 /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */ 2083 acornscsi_sendmessage(host); 2084 break; 2085 2086 case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2087 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2088 /* MESSAGE OUT -> MESSAGE IN */ 2089 acornscsi_message(host); 2090 break; 2091 2092 default: 2093 printk(KERN_ERR "scsi%d.%c: PHASE_MSGOUT, SSR %02X?\n", 2094 host->host->host_no, acornscsi_target(host), ssr); 2095 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2096 } 2097 return INTR_PROCESSING; 2098 2099 case PHASE_COMMAND: /* STATE: connected & command sent */ 2100 switch (ssr) { 2101 case 0x18: /* -> PHASE_DATAOUT */ 2102 /* COMMAND -> DATA OUT */ 2103 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) 2104 acornscsi_abortcmd(host, host->SCpnt->tag); 2105 acornscsi_dma_setup(host, DMA_OUT); 2106 if (!acornscsi_starttransfer(host)) 2107 acornscsi_abortcmd(host, host->SCpnt->tag); 2108 host->scsi.phase = PHASE_DATAOUT; 2109 return INTR_IDLE; 2110 2111 case 0x19: /* -> PHASE_DATAIN */ 2112 /* COMMAND -> DATA IN */ 2113 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) 2114 acornscsi_abortcmd(host, host->SCpnt->tag); 2115 acornscsi_dma_setup(host, DMA_IN); 2116 if (!acornscsi_starttransfer(host)) 2117 acornscsi_abortcmd(host, host->SCpnt->tag); 2118 host->scsi.phase = PHASE_DATAIN; 2119 return INTR_IDLE; 2120 2121 case 0x1b: /* -> PHASE_STATUS */ 2122 /* COMMAND -> STATUS */ 2123 acornscsi_readstatusbyte(host); 2124 host->scsi.phase = PHASE_STATUSIN; 2125 break; 2126 2127 case 0x1e: /* -> PHASE_MSGOUT */ 2128 /* COMMAND -> MESSAGE OUT */ 2129 acornscsi_sendmessage(host); 2130 break; 2131 2132 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2133 /* COMMAND -> MESSAGE IN */ 2134 acornscsi_message(host); 2135 break; 2136 2137 default: 2138 printk(KERN_ERR "scsi%d.%c: PHASE_COMMAND, SSR %02X?\n", 2139 host->host->host_no, acornscsi_target(host), ssr); 2140 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2141 } 2142 return INTR_PROCESSING; 2143 2144 case PHASE_DISCONNECT: /* STATE: connected, received DISCONNECT msg */ 2145 if (ssr == 0x85) { /* -> PHASE_IDLE */ 2146 host->scsi.disconnectable = 1; 2147 host->scsi.reconnected.tag = 0; 2148 host->scsi.phase = PHASE_IDLE; 2149 host->stats.disconnects += 1; 2150 } else { 2151 printk(KERN_ERR "scsi%d.%c: PHASE_DISCONNECT, SSR %02X instead of disconnect?\n", 2152 host->host->host_no, acornscsi_target(host), ssr); 2153 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2154 } 2155 return INTR_NEXT_COMMAND; 2156 2157 case PHASE_IDLE: /* STATE: disconnected */ 2158 if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */ 2159 acornscsi_reconnect(host); 2160 else { 2161 printk(KERN_ERR "scsi%d.%c: PHASE_IDLE, SSR %02X while idle?\n", 2162 host->host->host_no, acornscsi_target(host), ssr); 2163 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2164 } 2165 return INTR_PROCESSING; 2166 2167 case PHASE_RECONNECTED: /* STATE: device reconnected to initiator */ 2168 /* 2169 * Command reconnected - if MESGIN, get message - it may be 2170 * the tag. If not, get command out of disconnected queue 2171 */ 2172 /* 2173 * If we reconnected and we're not in MESSAGE IN phase after IDENTIFY, 2174 * reconnect I_T_L command 2175 */ 2176 if (ssr != 0x8f && !acornscsi_reconnect_finish(host)) 2177 return INTR_IDLE; 2178 ADD_STATUS(host->SCpnt->target, ssr, host->scsi.phase, in_irq); 2179 switch (ssr) { 2180 case 0x88: /* data out phase */ 2181 /* -> PHASE_DATAOUT */ 2182 /* MESSAGE IN -> DATA OUT */ 2183 acornscsi_dma_setup(host, DMA_OUT); 2184 if (!acornscsi_starttransfer(host)) 2185 acornscsi_abortcmd(host, host->SCpnt->tag); 2186 host->scsi.phase = PHASE_DATAOUT; 2187 return INTR_IDLE; 2188 2189 case 0x89: /* data in phase */ 2190 /* -> PHASE_DATAIN */ 2191 /* MESSAGE IN -> DATA IN */ 2192 acornscsi_dma_setup(host, DMA_IN); 2193 if (!acornscsi_starttransfer(host)) 2194 acornscsi_abortcmd(host, host->SCpnt->tag); 2195 host->scsi.phase = PHASE_DATAIN; 2196 return INTR_IDLE; 2197 2198 case 0x8a: /* command out */ 2199 /* MESSAGE IN -> COMMAND */ 2200 acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ 2201 break; 2202 2203 case 0x8b: /* status in */ 2204 /* -> PHASE_STATUSIN */ 2205 /* MESSAGE IN -> STATUS */ 2206 acornscsi_readstatusbyte(host); 2207 host->scsi.phase = PHASE_STATUSIN; 2208 break; 2209 2210 case 0x8e: /* message out */ 2211 /* -> PHASE_MSGOUT */ 2212 /* MESSAGE IN -> MESSAGE OUT */ 2213 acornscsi_sendmessage(host); 2214 break; 2215 2216 case 0x8f: /* message in */ 2217 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2218 break; 2219 2220 default: 2221 printk(KERN_ERR "scsi%d.%c: PHASE_RECONNECTED, SSR %02X after reconnect?\n", 2222 host->host->host_no, acornscsi_target(host), ssr); 2223 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2224 } 2225 return INTR_PROCESSING; 2226 2227 case PHASE_DATAIN: /* STATE: transferred data in */ 2228 /* 2229 * This is simple - if we disconnect then the DMA address & count is 2230 * correct. 2231 */ 2232 switch (ssr) { 2233 case 0x19: /* -> PHASE_DATAIN */ 2234 case 0x89: /* -> PHASE_DATAIN */ 2235 acornscsi_abortcmd(host, host->SCpnt->tag); 2236 return INTR_IDLE; 2237 2238 case 0x1b: /* -> PHASE_STATUSIN */ 2239 case 0x4b: /* -> PHASE_STATUSIN */ 2240 case 0x8b: /* -> PHASE_STATUSIN */ 2241 /* DATA IN -> STATUS */ 2242 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2243 acornscsi_sbic_xfcount(host); 2244 acornscsi_dma_stop(host); 2245 acornscsi_readstatusbyte(host); 2246 host->scsi.phase = PHASE_STATUSIN; 2247 break; 2248 2249 case 0x1e: /* -> PHASE_MSGOUT */ 2250 case 0x4e: /* -> PHASE_MSGOUT */ 2251 case 0x8e: /* -> PHASE_MSGOUT */ 2252 /* DATA IN -> MESSAGE OUT */ 2253 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2254 acornscsi_sbic_xfcount(host); 2255 acornscsi_dma_stop(host); 2256 acornscsi_sendmessage(host); 2257 break; 2258 2259 case 0x1f: /* message in */ 2260 case 0x4f: /* message in */ 2261 case 0x8f: /* message in */ 2262 /* DATA IN -> MESSAGE IN */ 2263 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2264 acornscsi_sbic_xfcount(host); 2265 acornscsi_dma_stop(host); 2266 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2267 break; 2268 2269 default: 2270 printk(KERN_ERR "scsi%d.%c: PHASE_DATAIN, SSR %02X?\n", 2271 host->host->host_no, acornscsi_target(host), ssr); 2272 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2273 } 2274 return INTR_PROCESSING; 2275 2276 case PHASE_DATAOUT: /* STATE: transferred data out */ 2277 /* 2278 * This is more complicated - if we disconnect, the DMA could be 12 2279 * bytes ahead of us. We need to correct this. 2280 */ 2281 switch (ssr) { 2282 case 0x18: /* -> PHASE_DATAOUT */ 2283 case 0x88: /* -> PHASE_DATAOUT */ 2284 acornscsi_abortcmd(host, host->SCpnt->tag); 2285 return INTR_IDLE; 2286 2287 case 0x1b: /* -> PHASE_STATUSIN */ 2288 case 0x4b: /* -> PHASE_STATUSIN */ 2289 case 0x8b: /* -> PHASE_STATUSIN */ 2290 /* DATA OUT -> STATUS */ 2291 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2292 acornscsi_sbic_xfcount(host); 2293 acornscsi_dma_stop(host); 2294 acornscsi_dma_adjust(host); 2295 acornscsi_readstatusbyte(host); 2296 host->scsi.phase = PHASE_STATUSIN; 2297 break; 2298 2299 case 0x1e: /* -> PHASE_MSGOUT */ 2300 case 0x4e: /* -> PHASE_MSGOUT */ 2301 case 0x8e: /* -> PHASE_MSGOUT */ 2302 /* DATA OUT -> MESSAGE OUT */ 2303 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2304 acornscsi_sbic_xfcount(host); 2305 acornscsi_dma_stop(host); 2306 acornscsi_dma_adjust(host); 2307 acornscsi_sendmessage(host); 2308 break; 2309 2310 case 0x1f: /* message in */ 2311 case 0x4f: /* message in */ 2312 case 0x8f: /* message in */ 2313 /* DATA OUT -> MESSAGE IN */ 2314 host->scsi.SCp.scsi_xferred = host->SCpnt->request_bufflen - 2315 acornscsi_sbic_xfcount(host); 2316 acornscsi_dma_stop(host); 2317 acornscsi_dma_adjust(host); 2318 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ 2319 break; 2320 2321 default: 2322 printk(KERN_ERR "scsi%d.%c: PHASE_DATAOUT, SSR %02X?\n", 2323 host->host->host_no, acornscsi_target(host), ssr); 2324 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2325 } 2326 return INTR_PROCESSING; 2327 2328 case PHASE_STATUSIN: /* STATE: status in complete */ 2329 switch (ssr) { 2330 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ 2331 case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ 2332 /* STATUS -> MESSAGE IN */ 2333 acornscsi_message(host); 2334 break; 2335 2336 case 0x1e: /* -> PHASE_MSGOUT */ 2337 case 0x8e: /* -> PHASE_MSGOUT */ 2338 /* STATUS -> MESSAGE OUT */ 2339 acornscsi_sendmessage(host); 2340 break; 2341 2342 default: 2343 printk(KERN_ERR "scsi%d.%c: PHASE_STATUSIN, SSR %02X instead of MESSAGE_IN?\n", 2344 host->host->host_no, acornscsi_target(host), ssr); 2345 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2346 } 2347 return INTR_PROCESSING; 2348 2349 case PHASE_MSGIN: /* STATE: message in */ 2350 switch (ssr) { 2351 case 0x1e: /* -> PHASE_MSGOUT */ 2352 case 0x4e: /* -> PHASE_MSGOUT */ 2353 case 0x8e: /* -> PHASE_MSGOUT */ 2354 /* MESSAGE IN -> MESSAGE OUT */ 2355 acornscsi_sendmessage(host); 2356 break; 2357 2358 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ 2359 case 0x2f: 2360 case 0x4f: 2361 case 0x8f: 2362 acornscsi_message(host); 2363 break; 2364 2365 case 0x85: 2366 printk("scsi%d.%c: strange message in disconnection\n", 2367 host->host->host_no, acornscsi_target(host)); 2368 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2369 acornscsi_done(host, &host->SCpnt, DID_ERROR); 2370 break; 2371 2372 default: 2373 printk(KERN_ERR "scsi%d.%c: PHASE_MSGIN, SSR %02X after message in?\n", 2374 host->host->host_no, acornscsi_target(host), ssr); 2375 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2376 } 2377 return INTR_PROCESSING; 2378 2379 case PHASE_DONE: /* STATE: received status & message */ 2380 switch (ssr) { 2381 case 0x85: /* -> PHASE_IDLE */ 2382 acornscsi_done(host, &host->SCpnt, DID_OK); 2383 return INTR_NEXT_COMMAND; 2384 2385 case 0x1e: 2386 case 0x8e: 2387 acornscsi_sendmessage(host); 2388 break; 2389 2390 default: 2391 printk(KERN_ERR "scsi%d.%c: PHASE_DONE, SSR %02X instead of disconnect?\n", 2392 host->host->host_no, acornscsi_target(host), ssr); 2393 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2394 } 2395 return INTR_PROCESSING; 2396 2397 case PHASE_ABORTED: 2398 switch (ssr) { 2399 case 0x85: 2400 if (host->SCpnt) 2401 acornscsi_done(host, &host->SCpnt, DID_ABORT); 2402 else { 2403 clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun, 2404 host->busyluns); 2405 host->scsi.phase = PHASE_IDLE; 2406 } 2407 return INTR_NEXT_COMMAND; 2408 2409 case 0x1e: 2410 case 0x2e: 2411 case 0x4e: 2412 case 0x8e: 2413 acornscsi_sendmessage(host); 2414 break; 2415 2416 default: 2417 printk(KERN_ERR "scsi%d.%c: PHASE_ABORTED, SSR %02X?\n", 2418 host->host->host_no, acornscsi_target(host), ssr); 2419 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2420 } 2421 return INTR_PROCESSING; 2422 2423 default: 2424 printk(KERN_ERR "scsi%d.%c: unknown driver phase %d\n", 2425 host->host->host_no, acornscsi_target(host), ssr); 2426 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->target : 8); 2427 } 2428 return INTR_PROCESSING; 2429} 2430 2431/* 2432 * Prototype: void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) 2433 * Purpose : handle interrupts from Acorn SCSI card 2434 * Params : irq - interrupt number 2435 * dev_id - device specific data (AS_Host structure) 2436 * regs - processor registers when interrupt occurred 2437 */ 2438static 2439void acornscsi_intr(int irq, void *dev_id, struct pt_regs *regs) 2440{ 2441 AS_Host *host = (AS_Host *)dev_id; 2442 intr_ret_t ret; 2443 int iostatus; 2444 int in_irq = 0; 2445 2446 if (host->scsi.interrupt) 2447 printk("scsi%d: interrupt re-entered\n", host->host->host_no); 2448 host->scsi.interrupt = 1; 2449 2450 do { 2451 ret = INTR_IDLE; 2452 2453 iostatus = inb(host->card.io_intr); 2454 2455 if (iostatus & 2) { 2456 acornscsi_dma_intr(host); 2457 iostatus = inb(host->card.io_intr); 2458 } 2459 2460 if (iostatus & 8) 2461 ret = acornscsi_sbicintr(host, in_irq); 2462 2463 /* 2464 * If we have a transfer pending, start it. 2465 * Only start it if the interface has already started transferring 2466 * it's data 2467 */ 2468 if (host->dma.xfer_required) 2469 acornscsi_dma_xfer(host); 2470 2471 if (ret == INTR_NEXT_COMMAND) 2472 ret = acornscsi_kick(host); 2473 2474 in_irq = 1; 2475 } while (ret != INTR_IDLE); 2476 2477 host->scsi.interrupt = 0; 2478} 2479 2480/*============================================================================================= 2481 * Interfaces between interrupt handler and rest of scsi code 2482 */ 2483 2484/* 2485 * Function : acornscsi_queuecmd(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) 2486 * Purpose : queues a SCSI command 2487 * Params : cmd - SCSI command 2488 * done - function called on completion, with pointer to command descriptor 2489 * Returns : 0, or < 0 on error. 2490 */ 2491int acornscsi_queuecmd(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) 2492{ 2493 AS_Host *host = (AS_Host *)SCpnt->host->hostdata; 2494 2495 if (!done) { 2496 /* there should be some way of rejecting errors like this without panicing... */ 2497 panic("scsi%d: queuecommand called with NULL done function [cmd=%p]", 2498 SCpnt->host->host_no, SCpnt); 2499 return -EINVAL; 2500 } 2501 2502#if (DEBUG & DEBUG_NO_WRITE) 2503 if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->target))) { 2504 printk(KERN_CRIT "scsi%d.%c: WRITE attempted with NO_WRITE flag set\n", 2505 SCpnt->host->host_no, '0' + SCpnt->target); 2506 SCpnt->result = DID_NO_CONNECT << 16; 2507 done(SCpnt); 2508 return 0; 2509 } 2510#endif 2511 2512 SCpnt->scsi_done = done; 2513 SCpnt->host_scribble = NULL; 2514 SCpnt->result = 0; 2515 SCpnt->tag = 0; 2516 SCpnt->SCp.phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]); 2517 SCpnt->SCp.sent_command = 0; 2518 SCpnt->SCp.scsi_xferred = 0; 2519 SCpnt->SCp.Status = 0; 2520 SCpnt->SCp.Message = 0; 2521 2522 if (SCpnt->use_sg) { 2523 SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer; 2524 SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1; 2525 SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address; 2526 SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length; 2527 } else { 2528 SCpnt->SCp.buffer = NULL; 2529 SCpnt->SCp.buffers_residual = 0; 2530 SCpnt->SCp.ptr = (char *) SCpnt->request_buffer; 2531 SCpnt->SCp.this_residual = SCpnt->request_bufflen; 2532 } 2533 2534 host->stats.queues += 1; 2535 2536 { 2537 unsigned long flags; 2538 2539 if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) { 2540 SCpnt->result = DID_ERROR << 16; 2541 done(SCpnt); 2542 return 0; 2543 } 2544 save_flags_cli(flags); 2545 if (host->scsi.phase == PHASE_IDLE) 2546 acornscsi_kick(host); 2547 restore_flags(flags); 2548 } 2549 return 0; 2550} 2551 2552/* 2553 * Prototype: void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) 2554 * Purpose : pass a result to *SCpntp1, and check if *SCpntp1 = *SCpntp2 2555 * Params : SCpntp1 - pointer to command to return 2556 * SCpntp2 - pointer to command to check 2557 * result - result to pass back to mid-level done function 2558 * Returns : *SCpntp2 = NULL if *SCpntp1 is the same command structure as *SCpntp2. 2559 */ 2560static inline 2561void acornscsi_reportstatus(Scsi_Cmnd **SCpntp1, Scsi_Cmnd **SCpntp2, int result) 2562{ 2563 Scsi_Cmnd *SCpnt = *SCpntp1; 2564 2565 if (SCpnt) { 2566 *SCpntp1 = NULL; 2567 2568 SCpnt->result = result; 2569 SCpnt->scsi_done(SCpnt); 2570 } 2571 2572 if (SCpnt == *SCpntp2) 2573 *SCpntp2 = NULL; 2574} 2575 2576enum res_abort { res_not_running, res_success, res_success_clear, res_snooze }; 2577 2578/* 2579 * Prototype: enum res acornscsi_do_abort(Scsi_Cmnd *SCpnt) 2580 * Purpose : abort a command on this host 2581 * Params : SCpnt - command to abort 2582 * Returns : our abort status 2583 */ 2584static enum res_abort 2585acornscsi_do_abort(AS_Host *host, Scsi_Cmnd *SCpnt) 2586{ 2587 enum res_abort res = res_not_running; 2588 2589 if (queue_remove_cmd(&host->queues.issue, SCpnt)) { 2590 /* 2591 * The command was on the issue queue, and has not been 2592 * issued yet. We can remove the command from the queue, 2593 * and acknowledge the abort. Neither the devices nor the 2594 * interface know about the command. 2595 */ 2596//#if (DEBUG & DEBUG_ABORT) 2597 printk("on issue queue "); 2598//#endif 2599 res = res_success; 2600 } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) { 2601 /* 2602 * The command was on the disconnected queue. Simply 2603 * acknowledge the abort condition, and when the target 2604 * reconnects, we will give it an ABORT message. The 2605 * target should then disconnect, and we will clear 2606 * the busylun bit. 2607 */ 2608//#if (DEBUG & DEBUG_ABORT) 2609 printk("on disconnected queue "); 2610//#endif 2611 res = res_success; 2612 } else if (host->SCpnt == SCpnt) { 2613 unsigned long flags; 2614 2615//#if (DEBUG & DEBUG_ABORT) 2616 printk("executing "); 2617//#endif 2618 2619 save_flags(flags); 2620 cli(); 2621 switch (host->scsi.phase) { 2622 /* 2623 * If the interface is idle, and the command is 'disconnectable', 2624 * then it is the same as on the disconnected queue. We simply 2625 * remove all traces of the command. When the target reconnects, 2626 * we will give it an ABORT message since the command could not 2627 * be found. When the target finally disconnects, we will clear 2628 * the busylun bit. 2629 */ 2630 case PHASE_IDLE: 2631 if (host->scsi.disconnectable) { 2632 host->scsi.disconnectable = 0; 2633 host->SCpnt = NULL; 2634 res = res_success; 2635 } 2636 break; 2637 2638 /* 2639 * If the command has connected and done nothing further, 2640 * simply force a disconnect. We also need to clear the 2641 * busylun bit. 2642 */ 2643 case PHASE_CONNECTED: 2644 sbic_arm_write(host->scsi.io_port, CMND, CMND_DISCONNECT); 2645 host->SCpnt = NULL; 2646 res = res_success_clear; 2647 break; 2648 2649 default: 2650 acornscsi_abortcmd(host, host->SCpnt->tag); 2651 res = res_snooze; 2652 } 2653 restore_flags(flags); 2654 } else if (host->origSCpnt == SCpnt) { 2655 /* 2656 * The command will be executed next, but a command 2657 * is currently using the interface. This is similar to 2658 * being on the issue queue, except the busylun bit has 2659 * been set. 2660 */ 2661 host->origSCpnt = NULL; 2662//#if (DEBUG & DEBUG_ABORT) 2663 printk("waiting for execution "); 2664//#endif 2665 res = res_success_clear; 2666 } else 2667 printk("unknown "); 2668 2669 return res; 2670} 2671 2672/* 2673 * Prototype: int acornscsi_abort(Scsi_Cmnd *SCpnt) 2674 * Purpose : abort a command on this host 2675 * Params : SCpnt - command to abort 2676 * Returns : one of SCSI_ABORT_ macros 2677 */ 2678int acornscsi_abort(Scsi_Cmnd *SCpnt) 2679{ 2680 AS_Host *host = (AS_Host *) SCpnt->host->hostdata; 2681 int result; 2682 2683 host->stats.aborts += 1; 2684 2685#if (DEBUG & DEBUG_ABORT) 2686 { 2687 int asr, ssr; 2688 asr = sbic_arm_read(host->scsi.io_port, ASR); 2689 ssr = sbic_arm_read(host->scsi.io_port, SSR); 2690 2691 printk(KERN_WARNING "acornscsi_abort: "); 2692 print_sbic_status(asr, ssr, host->scsi.phase); 2693 acornscsi_dumplog(host, SCpnt->target); 2694 } 2695#endif 2696 2697 printk("scsi%d: ", host->host->host_no); 2698 2699 switch (acornscsi_do_abort(host, SCpnt)) { 2700 /* 2701 * We managed to find the command and cleared it out. 2702 * We do not expect the command to be executing on the 2703 * target, but we have set the busylun bit. 2704 */ 2705 case res_success_clear: 2706//#if (DEBUG & DEBUG_ABORT) 2707 printk("clear "); 2708//#endif 2709 clear_bit(SCpnt->target * 8 + SCpnt->lun, host->busyluns); 2710 2711 /* 2712 * We found the command, and cleared it out. Either 2713 * the command is still known to be executing on the 2714 * target, or the busylun bit is not set. 2715 */ 2716 case res_success: 2717//#if (DEBUG & DEBUG_ABORT) 2718 printk("success\n"); 2719//#endif 2720 SCpnt->result = DID_ABORT << 16; 2721 SCpnt->scsi_done(SCpnt); 2722 result = SCSI_ABORT_SUCCESS; 2723 break; 2724 2725 /* 2726 * We did find the command, but unfortunately we couldn't 2727 * unhook it from ourselves. Wait some more, and if it 2728 * still doesn't complete, reset the interface. 2729 */ 2730 case res_snooze: 2731//#if (DEBUG & DEBUG_ABORT) 2732 printk("snooze\n"); 2733//#endif 2734 result = SCSI_ABORT_SNOOZE; 2735 break; 2736 2737 /* 2738 * The command could not be found (either because it completed, 2739 * or it got dropped. 2740 */ 2741 default: 2742 case res_not_running: 2743 acornscsi_dumplog(host, SCpnt->target); 2744#if (DEBUG & DEBUG_ABORT) 2745 result = SCSI_ABORT_SNOOZE; 2746#else 2747 result = SCSI_ABORT_NOT_RUNNING; 2748#endif 2749//#if (DEBUG & DEBUG_ABORT) 2750 printk("not running\n"); 2751//#endif 2752 break; 2753 } 2754 2755 return result; 2756} 2757 2758/* 2759 * Prototype: int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) 2760 * Purpose : reset a command on this host/reset this host 2761 * Params : SCpnt - command causing reset 2762 * result - what type of reset to perform 2763 * Returns : one of SCSI_RESET_ macros 2764 */ 2765int acornscsi_reset(Scsi_Cmnd *SCpnt, unsigned int reset_flags) 2766{ 2767 AS_Host *host = (AS_Host *)SCpnt->host->hostdata; 2768 Scsi_Cmnd *SCptr; 2769 2770 host->stats.resets += 1; 2771 2772#if (DEBUG & DEBUG_RESET) 2773 { 2774 int asr, ssr; 2775 2776 asr = sbic_arm_read(host->scsi.io_port, ASR); 2777 ssr = sbic_arm_read(host->scsi.io_port, SSR); 2778 2779 printk(KERN_WARNING "acornscsi_reset: "); 2780 print_sbic_status(asr, ssr, host->scsi.phase); 2781 acornscsi_dumplog(host, SCpnt->target); 2782 } 2783#endif 2784 2785 acornscsi_dma_stop(host); 2786 2787 SCptr = host->SCpnt; 2788 2789 /* 2790 * do hard reset. This resets all devices on this host, and so we 2791 * must set the reset status on all commands. 2792 */ 2793 acornscsi_resetcard(host); 2794 2795 /* 2796 * report reset on commands current connected/disconnected 2797 */ 2798 acornscsi_reportstatus(&host->SCpnt, &SCptr, DID_RESET); 2799 2800 while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) 2801 acornscsi_reportstatus(&SCptr, &SCpnt, DID_RESET); 2802 2803 if (SCpnt) { 2804 SCpnt->result = DID_RESET << 16; 2805 SCpnt->scsi_done(SCpnt); 2806 } 2807 2808 return SCSI_RESET_BUS_RESET | SCSI_RESET_HOST_RESET | SCSI_RESET_SUCCESS; 2809} 2810 2811/*============================================================================================== 2812 * initialisation & miscellaneous support 2813 */ 2814static struct expansion_card *ecs[MAX_ECARDS]; 2815 2816/* 2817 * Prototype: void acornscsi_init(AS_Host *host) 2818 * Purpose : initialise the AS_Host structure for one interface & setup hardware 2819 * Params : host - host to setup 2820 */ 2821static 2822void acornscsi_host_init(AS_Host *host) 2823{ 2824 memset(&host->stats, 0, sizeof (host->stats)); 2825 queue_initialise(&host->queues.issue); 2826 queue_initialise(&host->queues.disconnected); 2827 msgqueue_initialise(&host->scsi.msgs); 2828 2829 acornscsi_resetcard(host); 2830} 2831 2832int acornscsi_detect(Scsi_Host_Template * tpnt) 2833{ 2834 static const card_ids acornscsi_cids[] = { ACORNSCSI_LIST, { 0xffff, 0xffff } }; 2835 int i, count = 0; 2836 struct Scsi_Host *instance; 2837 AS_Host *host; 2838 2839 tpnt->proc_name = "acornscsi"; 2840 2841 for (i = 0; i < MAX_ECARDS; i++) 2842 ecs[i] = NULL; 2843 2844 ecard_startfind(); 2845 2846 while(1) { 2847 ecs[count] = ecard_find(0, acornscsi_cids); 2848 if (!ecs[count]) 2849 break; 2850 2851 if (ecs[count]->irq == 0xff) { 2852 printk("scsi: WD33C93 does not have IRQ enabled - ignoring\n"); 2853 continue; 2854 } 2855 2856 ecard_claim(ecs[count]); /* Must claim here - card produces irq on reset */ 2857 2858 instance = scsi_register(tpnt, sizeof(AS_Host)); 2859 host = (AS_Host *)instance->hostdata; 2860 2861 instance->io_port = ecard_address(ecs[count], ECARD_MEMC, 0); 2862 instance->irq = ecs[count]->irq; 2863 2864 host->host = instance; 2865 host->scsi.io_port = ioaddr(instance->io_port + 0x800); 2866 host->scsi.irq = instance->irq; 2867 host->card.io_intr = POD_SPACE(instance->io_port) + 0x800; 2868 host->card.io_page = POD_SPACE(instance->io_port) + 0xc00; 2869 host->card.io_ram = ioaddr(instance->io_port); 2870 host->dma.io_port = instance->io_port + 0xc00; 2871 host->dma.io_intr_clear = POD_SPACE(instance->io_port) + 0x800; 2872 2873 ecs[count]->irqaddr = (char *)ioaddr(host->card.io_intr); 2874 ecs[count]->irqmask = 0x0a; 2875 2876 if (!request_region(instance->io_port + 0x800, 2, "acornscsi(sbic)")) 2877 goto err_1; 2878 if (!request_region(host->card.io_intr, 1, "acornscsi(intr)")) 2879 goto err_2; 2880 if (!request_region(host->card.io_page, 1, "acornscsi(page)")) 2881 goto err_3; 2882#ifdef USE_DMAC 2883 if (!request_region(host->dma.io_port, 256, "acornscsi(dmac)")) 2884 goto err_4; 2885#endif 2886 if (!request_region(instance->io_port, 2048, "acornscsi(ram)")) 2887 goto err_5; 2888 2889 if (request_irq(host->scsi.irq, acornscsi_intr, SA_INTERRUPT, "acornscsi", host)) { 2890 printk(KERN_CRIT "scsi%d: IRQ%d not free, interrupts disabled\n", 2891 instance->host_no, host->scsi.irq); 2892 host->scsi.irq = NO_IRQ; 2893 } 2894 2895 acornscsi_host_init(host); 2896 2897 ++count; 2898 } 2899 return count; 2900 2901err_5: 2902#ifdef USE_DMAC 2903 release_region(host->dma.io_port, 256); 2904#endif 2905err_4: 2906 release_region(host->card.io_page, 1); 2907err_3: 2908 release_region(host->card.io_intr, 1); 2909err_2: 2910 release_region(instance->io_port + 0x800, 2); 2911err_1: 2912 scsi_unregister(instance); 2913 return 0; 2914} 2915 2916/* 2917 * Function: int acornscsi_release(struct Scsi_Host *host) 2918 * Purpose : release all resources used by this adapter 2919 * Params : host - driver structure to release 2920 * Returns : nothing of any consequence 2921 */ 2922int acornscsi_release(struct Scsi_Host *instance) 2923{ 2924 AS_Host *host = (AS_Host *)instance->hostdata; 2925 int i; 2926 2927 /* 2928 * Put card into RESET state 2929 */ 2930 outb(0x80, host->card.io_page); 2931 2932 if (host->scsi.irq != NO_IRQ) 2933 free_irq(host->scsi.irq, host); 2934 2935 release_region(instance->io_port + 0x800, 2); 2936 release_region(host->card.io_intr, 1); 2937 release_region(host->card.io_page, 1); 2938 release_region(host->dma.io_port, 256); 2939 release_region(instance->io_port, 2048); 2940 2941 for (i = 0; i < MAX_ECARDS; i++) 2942 if (ecs[i] && instance->io_port == ecard_address(ecs[i], ECARD_MEMC, 0)) 2943 ecard_release(ecs[i]); 2944 2945 msgqueue_free(&host->scsi.msgs); 2946 queue_free(&host->queues.disconnected); 2947 queue_free(&host->queues.issue); 2948 2949 return 0; 2950} 2951 2952/* 2953 * Function: char *acornscsi_info(struct Scsi_Host *host) 2954 * Purpose : return a string describing this interface 2955 * Params : host - host to give information on 2956 * Returns : a constant string 2957 */ 2958const 2959char *acornscsi_info(struct Scsi_Host *host) 2960{ 2961 static char string[100], *p; 2962 2963 p = string; 2964 2965 p += sprintf(string, "%s at port %08lX irq %d v%d.%d.%d" 2966#ifdef CONFIG_SCSI_ACORNSCSI_SYNC 2967 " SYNC" 2968#endif 2969#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 2970 " TAG" 2971#endif 2972#ifdef CONFIG_SCSI_ACORNSCSI_LINK 2973 " LINK" 2974#endif 2975#if (DEBUG & DEBUG_NO_WRITE) 2976 " NOWRITE ("NO_WRITE_STR")" 2977#endif 2978 , host->hostt->name, host->io_port, host->irq, 2979 VER_MAJOR, VER_MINOR, VER_PATCH); 2980 return string; 2981} 2982 2983int acornscsi_proc_info(char *buffer, char **start, off_t offset, 2984 int length, int host_no, int inout) 2985{ 2986 int pos, begin = 0, devidx; 2987 struct Scsi_Host *instance = scsi_hostlist; 2988 Scsi_Device *scd; 2989 AS_Host *host; 2990 char *p = buffer; 2991 2992 for (instance = scsi_hostlist; 2993 instance && instance->host_no != host_no; 2994 instance = instance->next); 2995 2996 if (inout == 1 || !instance) 2997 return -EINVAL; 2998 2999 host = (AS_Host *)instance->hostdata; 3000 3001 p += sprintf(p, "AcornSCSI driver v%d.%d.%d" 3002#ifdef CONFIG_SCSI_ACORNSCSI_SYNC 3003 " SYNC" 3004#endif 3005#ifdef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE 3006 " TAG" 3007#endif 3008#ifdef CONFIG_SCSI_ACORNSCSI_LINK 3009 " LINK" 3010#endif 3011#if (DEBUG & DEBUG_NO_WRITE) 3012 " NOWRITE ("NO_WRITE_STR")" 3013#endif 3014 "\n\n", VER_MAJOR, VER_MINOR, VER_PATCH); 3015 3016 p += sprintf(p, "SBIC: WD33C93A Address: %08X IRQ : %d\n", 3017 host->scsi.io_port, host->scsi.irq); 3018#ifdef USE_DMAC 3019 p += sprintf(p, "DMAC: uPC71071 Address: %08X IRQ : %d\n\n", 3020 host->dma.io_port, host->scsi.irq); 3021#endif 3022 3023 p += sprintf(p, "Statistics:\n" 3024 "Queued commands: %-10u Issued commands: %-10u\n" 3025 "Done commands : %-10u Reads : %-10u\n" 3026 "Writes : %-10u Others : %-10u\n" 3027 "Disconnects : %-10u Aborts : %-10u\n" 3028 "Resets : %-10u\n\nLast phases:", 3029 host->stats.queues, host->stats.removes, 3030 host->stats.fins, host->stats.reads, 3031 host->stats.writes, host->stats.miscs, 3032 host->stats.disconnects, host->stats.aborts, 3033 host->stats.resets); 3034 3035 for (devidx = 0; devidx < 9; devidx ++) { 3036 unsigned int statptr, prev; 3037 3038 p += sprintf(p, "\n%c:", devidx == 8 ? 'H' : ('0' + devidx)); 3039 statptr = host->status_ptr[devidx] - 10; 3040 3041 if ((signed int)statptr < 0) 3042 statptr += STATUS_BUFFER_SIZE; 3043 3044 prev = host->status[devidx][statptr].when; 3045 3046 for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) { 3047 if (host->status[devidx][statptr].when) { 3048 p += sprintf(p, "%c%02X:%02X+%2ld", 3049 host->status[devidx][statptr].irq ? '-' : ' ', 3050 host->status[devidx][statptr].ph, 3051 host->status[devidx][statptr].ssr, 3052 (host->status[devidx][statptr].when - prev) < 100 ? 3053 (host->status[devidx][statptr].when - prev) : 99); 3054 prev = host->status[devidx][statptr].when; 3055 } 3056 } 3057 } 3058 3059 p += sprintf(p, "\nAttached devices:%s\n", instance->host_queue ? "" : " none"); 3060 3061 for (scd = instance->host_queue; scd; scd = scd->next) { 3062 int len; 3063 3064 proc_print_scsidevice(scd, p, &len, 0); 3065 p += len; 3066 3067 p += sprintf(p, "Extensions: "); 3068 3069 if (scd->tagged_supported) 3070 p += sprintf(p, "TAG %sabled [%d] ", 3071 scd->tagged_queue ? "en" : "dis", scd->current_tag); 3072 p += sprintf(p, "\nTransfers: "); 3073 if (host->device[scd->id].sync_xfer & 15) 3074 p += sprintf(p, "sync, offset %d, %d ns\n", 3075 host->device[scd->id].sync_xfer & 15, 3076 acornscsi_getperiod(host->device[scd->id].sync_xfer)); 3077 else 3078 p += sprintf(p, "async\n"); 3079 3080 pos = p - buffer; 3081 if (pos + begin < offset) { 3082 begin += pos; 3083 p = buffer; 3084 } 3085 pos = p - buffer; 3086 if (pos + begin > offset + length) 3087 break; 3088 } 3089 3090 pos = p - buffer; 3091 3092 *start = buffer + (offset - begin); 3093 pos -= offset - begin; 3094 3095 if (pos > length) 3096 pos = length; 3097 3098 return pos; 3099} 3100 3101static Scsi_Host_Template acornscsi_template = { 3102 module: THIS_MODULE, 3103 proc_info: acornscsi_proc_info, 3104 name: "AcornSCSI", 3105 detect: acornscsi_detect, 3106 release: acornscsi_release, 3107 info: acornscsi_info, 3108 queuecommand: acornscsi_queuecmd, 3109 abort: acornscsi_abort, 3110 reset: acornscsi_reset, 3111 bios_param: scsicam_bios_param, 3112 can_queue: 16, 3113 this_id: 7, 3114 sg_tablesize: SG_ALL, 3115 cmd_per_lun: 2, 3116 unchecked_isa_dma: 0, 3117 use_clustering: DISABLE_CLUSTERING 3118}; 3119 3120static int __init acornscsi_init(void) 3121{ 3122 acornscsi_template.module = THIS_MODULE; 3123 scsi_register_module(MODULE_SCSI_HA, &acornscsi_template); 3124 if (acornscsi_template.present) 3125 return 0; 3126 3127 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template); 3128 return -ENODEV; 3129} 3130 3131static void __exit acornscsi_exit(void) 3132{ 3133 scsi_unregister_module(MODULE_SCSI_HA, &acornscsi_template); 3134} 3135 3136module_init(acornscsi_init); 3137module_exit(acornscsi_exit); 3138 3139MODULE_AUTHOR("Russell King"); 3140MODULE_DESCRIPTION("AcornSCSI driver"); 3141MODULE_LICENSE("GPL"); 3142EXPORT_NO_SYMBOLS; 3143