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