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