Lines Matching +full:host +full:- +full:id
1 // SPDX-License-Identifier: GPL-2.0-only
14 * 26-Sep-1997 RMK Re-jigged to use the queue module.
15 * Re-coded state machine to be based on driver
19 * 05-Oct-1997 RMK Implemented writing to SCSI devices.
20 * 06-Oct-1997 RMK Corrected small (non-serious) bug with the connect/
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
45 * SCSI-II Tagged queue support.
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
58 * SCSI-II Synchronous transfer support.
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.
73 * DEBUG - bit mask from list above
74 * DEBUG_TARGET - is defined to the target number if you want to debug
105 if (cmd->device->id == DEBUG_TARGET) { \
160 * Size of on-board DMA buffer
170 static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp,
172 static int acornscsi_reconnect_finish(AS_Host *host);
173 static void acornscsi_dma_cleanup(AS_Host *host);
174 static void acornscsi_abortcmd(AS_Host *host);
189 static inline void sbic_arm_write(AS_Host *host, unsigned int reg, unsigned int value) in sbic_arm_write() argument
191 writeb(reg, host->base + SBIC_REGIDX); in sbic_arm_write()
192 writeb(value, host->base + SBIC_REGVAL); in sbic_arm_write()
195 static inline int sbic_arm_read(AS_Host *host, unsigned int reg) in sbic_arm_read() argument
198 return readl(host->base + SBIC_REGIDX) & 255; in sbic_arm_read()
199 writeb(reg, host->base + SBIC_REGIDX); in sbic_arm_read()
200 return readl(host->base + SBIC_REGVAL) & 255; in sbic_arm_read()
203 #define sbic_arm_writenext(host, val) writeb((val), (host)->base + SBIC_REGVAL) argument
204 #define sbic_arm_readnext(host) readb((host)->base + SBIC_REGVAL) argument
207 #define dmac_read(host,reg) \ argument
208 readb((host)->base + DMAC_OFFSET + ((reg) << 2))
210 #define dmac_write(host,reg,value) \ argument
211 ({ writeb((value), (host)->base + DMAC_OFFSET + ((reg) << 2)); })
213 #define dmac_clearintr(host) writeb(0, (host)->fast + INT_REG) argument
215 static inline unsigned int dmac_address(AS_Host *host) in dmac_address() argument
217 return dmac_read(host, DMAC_TXADRHI) << 16 | in dmac_address()
218 dmac_read(host, DMAC_TXADRMD) << 8 | in dmac_address()
219 dmac_read(host, DMAC_TXADRLO); in dmac_address()
223 void acornscsi_dumpdma(AS_Host *host, char *where) in acornscsi_dumpdma() argument
227 mode = dmac_read(host, DMAC_MODECON); in acornscsi_dumpdma()
228 addr = dmac_address(host); in acornscsi_dumpdma()
229 len = dmac_read(host, DMAC_TXCNTHI) << 8 | in acornscsi_dumpdma()
230 dmac_read(host, DMAC_TXCNTLO); in acornscsi_dumpdma()
233 host->host->host_no, where, in acornscsi_dumpdma()
235 dmac_read(host, DMAC_MASKREG)); in acornscsi_dumpdma()
237 printk("DMA @%06x, ", host->dma.start_addr); in acornscsi_dumpdma()
238 printk("BH @%p +%04x, ", host->scsi.SCp.ptr, in acornscsi_dumpdma()
239 host->scsi.SCp.this_residual); in acornscsi_dumpdma()
240 printk("DT @+%04x ST @+%04x", host->dma.transferred, in acornscsi_dumpdma()
241 host->scsi.SCp.scsi_xferred); in acornscsi_dumpdma()
247 unsigned long acornscsi_sbic_xfcount(AS_Host *host) in acornscsi_sbic_xfcount() argument
251 length = sbic_arm_read(host, SBIC_TRANSCNTH) << 16; in acornscsi_sbic_xfcount()
252 length |= sbic_arm_readnext(host) << 8; in acornscsi_sbic_xfcount()
253 length |= sbic_arm_readnext(host); in acornscsi_sbic_xfcount()
259 acornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg) in acornscsi_sbic_wait() argument
264 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_sbic_wait()
270 } while (--timeout); in acornscsi_sbic_wait()
272 printk("scsi%d: timeout while %s\n", host->host->host_no, msg); in acornscsi_sbic_wait()
274 return -1; in acornscsi_sbic_wait()
278 int acornscsi_sbic_issuecmd(AS_Host *host, int command) in acornscsi_sbic_issuecmd() argument
280 if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command")) in acornscsi_sbic_issuecmd()
281 return -1; in acornscsi_sbic_issuecmd()
283 sbic_arm_write(host, SBIC_CMND, command); in acornscsi_sbic_issuecmd()
304 void acornscsi_resetcard(AS_Host *host) in acornscsi_resetcard() argument
309 host->card.page_reg = 0x80; in acornscsi_resetcard()
310 writeb(host->card.page_reg, host->fast + PAGE_REG); in acornscsi_resetcard()
315 host->card.page_reg = 0; in acornscsi_resetcard()
316 writeb(host->card.page_reg, host->fast + PAGE_REG); in acornscsi_resetcard()
323 if (readb(host->fast + INT_REG) & 8) in acornscsi_resetcard()
326 } while (--timeout); in acornscsi_resetcard()
330 host->host->host_no); in acornscsi_resetcard()
332 sbic_arm_read(host, SBIC_ASR); in acornscsi_resetcard()
333 sbic_arm_read(host, SBIC_SSR); in acornscsi_resetcard()
335 /* setup sbic - WD33C93A */ in acornscsi_resetcard()
336 sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); in acornscsi_resetcard()
337 sbic_arm_write(host, SBIC_CMND, CMND_RESET); in acornscsi_resetcard()
344 if (readb(host->fast + INT_REG) & 8) in acornscsi_resetcard()
347 } while (--timeout); in acornscsi_resetcard()
351 host->host->host_no); in acornscsi_resetcard()
353 sbic_arm_read(host, SBIC_ASR); in acornscsi_resetcard()
354 if (sbic_arm_read(host, SBIC_SSR) != 0x01) in acornscsi_resetcard()
356 host->host->host_no); in acornscsi_resetcard()
358 sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); in acornscsi_resetcard()
359 sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); in acornscsi_resetcard()
360 sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); in acornscsi_resetcard()
361 sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); in acornscsi_resetcard()
363 host->card.page_reg = 0x40; in acornscsi_resetcard()
364 writeb(host->card.page_reg, host->fast + PAGE_REG); in acornscsi_resetcard()
366 /* setup dmac - uPC71071 */ in acornscsi_resetcard()
367 dmac_write(host, DMAC_INIT, 0); in acornscsi_resetcard()
369 dmac_write(host, DMAC_INIT, INIT_8BIT); in acornscsi_resetcard()
370 dmac_write(host, DMAC_CHANNEL, CHANNEL_0); in acornscsi_resetcard()
371 dmac_write(host, DMAC_DEVCON0, INIT_DEVCON0); in acornscsi_resetcard()
372 dmac_write(host, DMAC_DEVCON1, INIT_DEVCON1); in acornscsi_resetcard()
375 host->SCpnt = NULL; in acornscsi_resetcard()
376 host->scsi.phase = PHASE_IDLE; in acornscsi_resetcard()
377 host->scsi.disconnectable = 0; in acornscsi_resetcard()
379 memset(host->busyluns, 0, sizeof(host->busyluns)); in acornscsi_resetcard()
382 host->device[i].sync_state = SYNC_NEGOCIATE; in acornscsi_resetcard()
383 host->device[i].disconnect_ok = 1; in acornscsi_resetcard()
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
422 "reset - normal mode", /* 00 */
423 "reset - advanced mode", /* 01 */
428 "data-out", /* 18 */
429 "data-in", /* 19 */
432 "??-out", /* 1C */
433 "??-in", /* 1D */
434 "msg-out", /* 1E */
435 "msg-in", /* 1F */
439 "save-data-ptr", /* 21 */
451 "resel, no id", /* 80 */
459 if (acornscsi_map[ssr] != -1) in print_scsi_status()
489 acornscsi_dumplogline(AS_Host *host, int target, int line) in acornscsi_dumplogline() argument
494 ptr = host->status_ptr[target] - STATUS_BUFFER_TO_PRINT; in acornscsi_dumplogline()
501 prev = host->status[target][ptr].when; in acornscsi_dumplogline()
503 for (; ptr != host->status_ptr[target]; ptr = (ptr + 1) & (STATUS_BUFFER_SIZE - 1)) { in acornscsi_dumplogline()
506 if (!host->status[target][ptr].when) in acornscsi_dumplogline()
511 printk("%c%02X", host->status[target][ptr].irq ? '-' : ' ', in acornscsi_dumplogline()
512 host->status[target][ptr].ph); in acornscsi_dumplogline()
516 printk(" %02X", host->status[target][ptr].ssr); in acornscsi_dumplogline()
520 time_diff = host->status[target][ptr].when - prev; in acornscsi_dumplogline()
521 prev = host->status[target][ptr].when; in acornscsi_dumplogline()
536 void acornscsi_dumplog(AS_Host *host, int target) in acornscsi_dumplog() argument
539 acornscsi_dumplogline(host, target, 0); in acornscsi_dumplog()
540 acornscsi_dumplogline(host, target, 1); in acornscsi_dumplog()
541 acornscsi_dumplogline(host, target, 2); in acornscsi_dumplog()
551 char acornscsi_target(AS_Host *host) in acornscsi_target() argument
553 if (host->SCpnt) in acornscsi_target()
554 return '0' + host->SCpnt->device->id; in acornscsi_target()
561 * Params : command - command to interpret
562 * Returns : CMD_READ - command reads data,
563 * CMD_WRITE - command writes data,
564 * CMD_MISC - everything else
583 * Params : command - command to interpret
584 * Returns : DATADIR_OUT - data out phase expected
585 * DATADIR_IN - data in phase expected
645 * Params : period - time (ns) for REQ
656 (period > sync_xfer_table[i - 1].period_ns)) in round_period()
665 * Params : period - time (ns) for REQ
666 * offset - offset in bytes between REQ/ACK
682 * Function: acornscsi_kick(AS_Host *host)
684 * Params : host - host to send command to
689 intr_ret_t acornscsi_kick(AS_Host *host) in acornscsi_kick() argument
695 SCpnt = host->origSCpnt; in acornscsi_kick()
696 host->origSCpnt = NULL; in acornscsi_kick()
700 SCpnt = queue_remove_exclude(&host->queues.issue, host->busyluns); in acornscsi_kick()
707 if (host->scsi.disconnectable && host->SCpnt) { in acornscsi_kick()
708 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); in acornscsi_kick()
709 host->scsi.disconnectable = 0; in acornscsi_kick()
711 DBG(host->SCpnt, printk("scsi%d.%c: moved command to disconnected queue\n", in acornscsi_kick()
712 host->host->host_no, acornscsi_target(host))); in acornscsi_kick()
714 host->SCpnt = NULL; in acornscsi_kick()
721 if (!(sbic_arm_read(host, SBIC_ASR) & (ASR_INT|ASR_BSY|ASR_CIP))) { in acornscsi_kick()
722 sbic_arm_write(host, SBIC_DESTID, SCpnt->device->id); in acornscsi_kick()
723 sbic_arm_write(host, SBIC_CMND, CMND_SELWITHATN); in acornscsi_kick()
727 * claim host busy - all of these must happen atomically wrt in acornscsi_kick()
730 host->scsi.phase = PHASE_CONNECTING; in acornscsi_kick()
731 host->SCpnt = SCpnt; in acornscsi_kick()
732 host->scsi.SCp = *arm_scsi_pointer(SCpnt); in acornscsi_kick()
733 host->dma.xfer_setup = 0; in acornscsi_kick()
734 host->dma.xfer_required = 0; in acornscsi_kick()
735 host->dma.xfer_done = 0; in acornscsi_kick()
739 host->host->host_no, '0' + SCpnt->device->id, in acornscsi_kick()
740 SCpnt->cmnd[0])); in acornscsi_kick()
744 set_bit(SCpnt->device->id * 8 + in acornscsi_kick()
745 (u8)(SCpnt->device->lun & 0x07), host->busyluns); in acornscsi_kick()
747 host->stats.removes += 1; in acornscsi_kick()
749 switch (acornscsi_cmdtype(SCpnt->cmnd[0])) { in acornscsi_kick()
751 host->stats.writes += 1; in acornscsi_kick()
754 host->stats.reads += 1; in acornscsi_kick()
757 host->stats.miscs += 1; in acornscsi_kick()
766 * Function: void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, unsigned int result)
768 * Params : host - interface that completed
769 * result - driver byte of result
771 static void acornscsi_done(AS_Host *host, struct scsi_cmnd **SCpntp, in acornscsi_done() argument
777 sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); in acornscsi_done()
779 host->stats.fins += 1; in acornscsi_done()
784 acornscsi_dma_cleanup(host); in acornscsi_done()
788 scsi_msg_to_host_byte(SCpnt, host->scsi.SCp.Message); in acornscsi_done()
789 set_status_byte(SCpnt, host->scsi.SCp.Status); in acornscsi_done()
795 * data loss will occur. Should we check SCpnt->underflow here? in acornscsi_done()
802 if (SCpnt->underflow == 0) { in acornscsi_done()
803 if (host->scsi.SCp.ptr && in acornscsi_done()
804 acornscsi_cmdtype(SCpnt->cmnd[0]) != CMD_MISC) in acornscsi_done()
807 if (host->scsi.SCp.scsi_xferred < SCpnt->underflow || in acornscsi_done()
808 host->scsi.SCp.scsi_xferred != host->dma.transferred) in acornscsi_done()
812 /* ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.6) in acornscsi_done()
816 * POINTER - DISCONNECT message sequence. in acornscsi_done()
824 if (host->dma.xfer_done) in acornscsi_done()
839 "result=%08X", SCpnt->result); in acornscsi_done()
841 acornscsi_dumpdma(host, "done"); in acornscsi_done()
842 acornscsi_dumplog(host, SCpnt->device->id); in acornscsi_done()
848 clear_bit(SCpnt->device->id * 8 + in acornscsi_done()
849 (u8)(SCpnt->device->lun & 0x7), host->busyluns); in acornscsi_done()
853 printk("scsi%d: null command in acornscsi_done", host->host->host_no); in acornscsi_done()
855 host->scsi.phase = PHASE_IDLE; in acornscsi_done()
866 void acornscsi_data_updateptr(AS_Host *host, struct scsi_pointer *SCp, unsigned int length) in acornscsi_data_updateptr() argument
868 SCp->ptr += length; in acornscsi_data_updateptr()
869 SCp->this_residual -= length; in acornscsi_data_updateptr()
871 if (SCp->this_residual == 0 && next_SCp(SCp) == 0) in acornscsi_data_updateptr()
872 host->dma.xfer_done = 1; in acornscsi_data_updateptr()
876 * Prototype: void acornscsi_data_read(AS_Host *host, char *ptr,
879 * Params : host - host to transfer from
880 * ptr - DRAM address
881 * start_addr - host mem address
882 * length - number of bytes to transfer
886 void acornscsi_data_read(AS_Host *host, char *ptr, in acornscsi_data_read() argument
893 offset = start_addr & ((1 << 12) - 1); in acornscsi_data_read()
895 writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_read()
901 this_len = (1 << 12) - offset; in acornscsi_data_read()
905 __acornscsi_in(host->base + (offset << 1), ptr, this_len); in acornscsi_data_read()
909 len -= this_len; in acornscsi_data_read()
914 writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_read()
917 writeb(host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_read()
921 * Prototype: void acornscsi_data_write(AS_Host *host, char *ptr,
924 * Params : host - host to transfer from
925 * ptr - DRAM address
926 * start_addr - host mem address
927 * length - number of bytes to transfer
931 void acornscsi_data_write(AS_Host *host, char *ptr, in acornscsi_data_write() argument
938 offset = start_addr & ((1 << 12) - 1); in acornscsi_data_write()
940 writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_write()
946 this_len = (1 << 12) - offset; in acornscsi_data_write()
950 __acornscsi_out(host->base + (offset << 1), ptr, this_len); in acornscsi_data_write()
954 len -= this_len; in acornscsi_data_write()
959 writeb((page & 0x3f) | host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_write()
962 writeb(host->card.page_reg, host->fast + PAGE_REG); in acornscsi_data_write()
966 * On-board DMA routines
970 * Prototype: void acornscsi_dmastop(AS_Host *host)
972 * Params : host - host on which to stop DMA
977 void acornscsi_dma_stop(AS_Host *host) in acornscsi_dma_stop() argument
979 dmac_write(host, DMAC_MASKREG, MASK_ON); in acornscsi_dma_stop()
980 dmac_clearintr(host); in acornscsi_dma_stop()
983 DBG(host->SCpnt, acornscsi_dumpdma(host, "stop")); in acornscsi_dma_stop()
988 * Function: void acornscsi_dma_setup(AS_Host *host, dmadir_t direction)
990 * Params : host - host to setup
991 * direction - data transfer direction
996 void acornscsi_dma_setup(AS_Host *host, dmadir_t direction) in acornscsi_dma_setup() argument
1000 host->dma.direction = direction; in acornscsi_dma_setup()
1002 dmac_write(host, DMAC_MASKREG, MASK_ON); in acornscsi_dma_setup()
1006 if (NO_WRITE & (1 << host->SCpnt->device->id)) { in acornscsi_dma_setup()
1008 host->host->host_no, acornscsi_target(host)); in acornscsi_dma_setup()
1019 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); in acornscsi_dma_setup()
1021 host->dma.start_addr = address = host->dma.free_addr; in acornscsi_dma_setup()
1022 host->dma.free_addr = (host->dma.free_addr + length) & in acornscsi_dma_setup()
1023 (DMAC_BUFFER_SIZE - 1); in acornscsi_dma_setup()
1029 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, in acornscsi_dma_setup()
1032 length -= 1; in acornscsi_dma_setup()
1033 dmac_write(host, DMAC_TXCNTLO, length); in acornscsi_dma_setup()
1034 dmac_write(host, DMAC_TXCNTHI, length >> 8); in acornscsi_dma_setup()
1035 dmac_write(host, DMAC_TXADRLO, address); in acornscsi_dma_setup()
1036 dmac_write(host, DMAC_TXADRMD, address >> 8); in acornscsi_dma_setup()
1037 dmac_write(host, DMAC_TXADRHI, 0); in acornscsi_dma_setup()
1038 dmac_write(host, DMAC_MODECON, mode); in acornscsi_dma_setup()
1039 dmac_write(host, DMAC_MASKREG, MASK_OFF); in acornscsi_dma_setup()
1042 DBG(host->SCpnt, acornscsi_dumpdma(host, "strt")); in acornscsi_dma_setup()
1044 host->dma.xfer_setup = 1; in acornscsi_dma_setup()
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
1057 void acornscsi_dma_cleanup(AS_Host *host) in acornscsi_dma_cleanup() argument
1059 dmac_write(host, DMAC_MASKREG, MASK_ON); in acornscsi_dma_cleanup()
1060 dmac_clearintr(host); in acornscsi_dma_cleanup()
1065 if (host->dma.xfer_required) { in acornscsi_dma_cleanup()
1066 host->dma.xfer_required = 0; in acornscsi_dma_cleanup()
1067 if (host->dma.direction == DMA_IN) in acornscsi_dma_cleanup()
1068 acornscsi_data_read(host, host->dma.xfer_ptr, in acornscsi_dma_cleanup()
1069 host->dma.xfer_start, host->dma.xfer_length); in acornscsi_dma_cleanup()
1075 if (host->dma.xfer_setup) { in acornscsi_dma_cleanup()
1078 host->dma.xfer_setup = 0; in acornscsi_dma_cleanup()
1081 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupi")); in acornscsi_dma_cleanup()
1087 transferred = dmac_address(host) - host->dma.start_addr; in acornscsi_dma_cleanup()
1088 host->dma.transferred += transferred; in acornscsi_dma_cleanup()
1090 if (host->dma.direction == DMA_IN) in acornscsi_dma_cleanup()
1091 acornscsi_data_read(host, host->scsi.SCp.ptr, in acornscsi_dma_cleanup()
1092 host->dma.start_addr, transferred); in acornscsi_dma_cleanup()
1097 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); in acornscsi_dma_cleanup()
1099 DBG(host->SCpnt, acornscsi_dumpdma(host, "cupo")); in acornscsi_dma_cleanup()
1105 * Function: void acornscsi_dmacintr(AS_Host *host)
1107 * Params : host - host to process
1115 void acornscsi_dma_intr(AS_Host *host) in acornscsi_dma_intr() argument
1120 DBG(host->SCpnt, acornscsi_dumpdma(host, "inti")); in acornscsi_dma_intr()
1123 dmac_write(host, DMAC_MASKREG, MASK_ON); in acornscsi_dma_intr()
1124 dmac_clearintr(host); in acornscsi_dma_intr()
1129 transferred = dmac_address(host) - host->dma.start_addr; in acornscsi_dma_intr()
1130 host->dma.transferred += transferred; in acornscsi_dma_intr()
1135 if (host->dma.direction == DMA_IN) { in acornscsi_dma_intr()
1136 host->dma.xfer_start = host->dma.start_addr; in acornscsi_dma_intr()
1137 host->dma.xfer_length = transferred; in acornscsi_dma_intr()
1138 host->dma.xfer_ptr = host->scsi.SCp.ptr; in acornscsi_dma_intr()
1139 host->dma.xfer_required = 1; in acornscsi_dma_intr()
1142 acornscsi_data_updateptr(host, &host->scsi.SCp, transferred); in acornscsi_dma_intr()
1145 * Allocate some buffer space, limited to half the on-board RAM size in acornscsi_dma_intr()
1147 length = min_t(unsigned int, host->scsi.SCp.this_residual, DMAC_BUFFER_SIZE / 2); in acornscsi_dma_intr()
1149 host->dma.start_addr = address = host->dma.free_addr; in acornscsi_dma_intr()
1150 host->dma.free_addr = (host->dma.free_addr + length) & in acornscsi_dma_intr()
1151 (DMAC_BUFFER_SIZE - 1); in acornscsi_dma_intr()
1156 if (host->dma.direction == DMA_OUT) in acornscsi_dma_intr()
1157 acornscsi_data_write(host, host->scsi.SCp.ptr, host->dma.start_addr, in acornscsi_dma_intr()
1160 length -= 1; in acornscsi_dma_intr()
1161 dmac_write(host, DMAC_TXCNTLO, length); in acornscsi_dma_intr()
1162 dmac_write(host, DMAC_TXCNTHI, length >> 8); in acornscsi_dma_intr()
1163 dmac_write(host, DMAC_TXADRLO, address); in acornscsi_dma_intr()
1164 dmac_write(host, DMAC_TXADRMD, address >> 8); in acornscsi_dma_intr()
1165 dmac_write(host, DMAC_TXADRHI, 0); in acornscsi_dma_intr()
1166 dmac_write(host, DMAC_MASKREG, MASK_OFF); in acornscsi_dma_intr()
1169 DBG(host->SCpnt, acornscsi_dumpdma(host, "into")); in acornscsi_dma_intr()
1172 host->dma.xfer_setup = 0; in acornscsi_dma_intr()
1180 if (dmac_read(host, DMAC_STATUS) & STATUS_RQ0) { in acornscsi_dma_intr()
1181 acornscsi_abortcmd(host); in acornscsi_dma_intr()
1183 dmac_write(host, DMAC_TXCNTLO, 0); in acornscsi_dma_intr()
1184 dmac_write(host, DMAC_TXCNTHI, 0); in acornscsi_dma_intr()
1185 dmac_write(host, DMAC_TXADRLO, 0); in acornscsi_dma_intr()
1186 dmac_write(host, DMAC_TXADRMD, 0); in acornscsi_dma_intr()
1187 dmac_write(host, DMAC_TXADRHI, 0); in acornscsi_dma_intr()
1188 dmac_write(host, DMAC_MASKREG, MASK_OFF); in acornscsi_dma_intr()
1195 * Function: void acornscsi_dma_xfer(AS_Host *host)
1197 * Params : host - host to process
1200 void acornscsi_dma_xfer(AS_Host *host) in acornscsi_dma_xfer() argument
1202 host->dma.xfer_required = 0; in acornscsi_dma_xfer()
1204 if (host->dma.direction == DMA_IN) in acornscsi_dma_xfer()
1205 acornscsi_data_read(host, host->dma.xfer_ptr, in acornscsi_dma_xfer()
1206 host->dma.xfer_start, host->dma.xfer_length); in acornscsi_dma_xfer()
1210 * Function: void acornscsi_dma_adjust(AS_Host *host)
1213 * Params : host - host to adjust DMA count for
1216 void acornscsi_dma_adjust(AS_Host *host) in acornscsi_dma_adjust() argument
1218 if (host->dma.xfer_setup) { in acornscsi_dma_adjust()
1221 DBG(host->SCpnt, acornscsi_dumpdma(host, "adji")); in acornscsi_dma_adjust()
1224 * Calculate correct DMA address - DMA is ahead of SCSI bus while in acornscsi_dma_adjust()
1226 * host->scsi.SCp.scsi_xferred is the number of bytes in acornscsi_dma_adjust()
1228 * host->dma.transferred is the number of bytes transferred in acornscsi_dma_adjust()
1229 * over DMA since host->dma.start_addr was last set. in acornscsi_dma_adjust()
1231 * real_dma_addr = host->dma.start_addr + host->scsi.SCp.scsi_xferred in acornscsi_dma_adjust()
1232 * - host->dma.transferred in acornscsi_dma_adjust()
1234 transferred = host->scsi.SCp.scsi_xferred - host->dma.transferred; in acornscsi_dma_adjust()
1237 host->host->host_no, acornscsi_target(host), transferred); in acornscsi_dma_adjust()
1239 host->dma.xfer_setup = 0; in acornscsi_dma_adjust()
1241 transferred += host->dma.start_addr; in acornscsi_dma_adjust()
1242 dmac_write(host, DMAC_TXADRLO, transferred); in acornscsi_dma_adjust()
1243 dmac_write(host, DMAC_TXADRMD, transferred >> 8); in acornscsi_dma_adjust()
1244 dmac_write(host, DMAC_TXADRHI, transferred >> 16); in acornscsi_dma_adjust()
1246 DBG(host->SCpnt, acornscsi_dumpdma(host, "adjo")); in acornscsi_dma_adjust()
1257 acornscsi_write_pio(AS_Host *host, char *bytes, int *ptr, int len, unsigned int max_timeout) in acornscsi_write_pio() argument
1263 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_write_pio()
1268 sbic_arm_write(host, SBIC_DATA, bytes[my_ptr++]); in acornscsi_write_pio()
1271 else if (--timeout == 0) in acornscsi_write_pio()
1278 return (timeout == 0) ? -1 : 0; in acornscsi_write_pio()
1282 * Function: void acornscsi_sendcommand(AS_Host *host)
1284 * Params : host - host which is connected to target
1287 acornscsi_sendcommand(AS_Host *host) in acornscsi_sendcommand() argument
1289 struct scsi_cmnd *SCpnt = host->SCpnt; in acornscsi_sendcommand()
1291 sbic_arm_write(host, SBIC_TRANSCNTH, 0); in acornscsi_sendcommand()
1292 sbic_arm_writenext(host, 0); in acornscsi_sendcommand()
1293 sbic_arm_writenext(host, SCpnt->cmd_len - host->scsi.SCp.sent_command); in acornscsi_sendcommand()
1295 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); in acornscsi_sendcommand()
1297 if (acornscsi_write_pio(host, SCpnt->cmnd, in acornscsi_sendcommand()
1298 (int *)&host->scsi.SCp.sent_command, SCpnt->cmd_len, 1000000)) in acornscsi_sendcommand()
1299 printk("scsi%d: timeout while sending command\n", host->host->host_no); in acornscsi_sendcommand()
1301 host->scsi.phase = PHASE_COMMAND; in acornscsi_sendcommand()
1305 void acornscsi_sendmessage(AS_Host *host) in acornscsi_sendmessage() argument
1307 unsigned int message_length = msgqueue_msglength(&host->scsi.msgs); in acornscsi_sendmessage()
1313 host->host->host_no, acornscsi_target(host)); in acornscsi_sendmessage()
1318 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); in acornscsi_sendmessage()
1320 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 1"); in acornscsi_sendmessage()
1322 sbic_arm_write(host, SBIC_DATA, NOP); in acornscsi_sendmessage()
1324 host->scsi.last_message = NOP; in acornscsi_sendmessage()
1331 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); in acornscsi_sendmessage()
1332 msg = msgqueue_getmsg(&host->scsi.msgs, 0); in acornscsi_sendmessage()
1334 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "sending message 2"); in acornscsi_sendmessage()
1336 sbic_arm_write(host, SBIC_DATA, msg->msg[0]); in acornscsi_sendmessage()
1338 host->scsi.last_message = msg->msg[0]; in acornscsi_sendmessage()
1340 spi_print_msg(msg->msg); in acornscsi_sendmessage()
1346 * ANSI standard says: (SCSI-2 Rev 10c Sect 5.6.14) in acornscsi_sendmessage()
1353 sbic_arm_write(host, SBIC_TRANSCNTH, 0); in acornscsi_sendmessage()
1354 sbic_arm_writenext(host, 0); in acornscsi_sendmessage()
1355 sbic_arm_writenext(host, message_length); in acornscsi_sendmessage()
1356 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); in acornscsi_sendmessage()
1359 while ((msg = msgqueue_getmsg(&host->scsi.msgs, msgnr++)) != NULL) { in acornscsi_sendmessage()
1365 if (acornscsi_write_pio(host, msg->msg, &i, msg->length, 1000000)) in acornscsi_sendmessage()
1366 printk("scsi%d: timeout while sending message\n", host->host->host_no); in acornscsi_sendmessage()
1368 host->scsi.last_message = msg->msg[0]; in acornscsi_sendmessage()
1369 if (msg->msg[0] == EXTENDED_MESSAGE) in acornscsi_sendmessage()
1370 host->scsi.last_message |= msg->msg[2] << 8; in acornscsi_sendmessage()
1372 if (i != msg->length) in acornscsi_sendmessage()
1383 * Function: void acornscsi_readstatusbyte(AS_Host *host)
1385 * Params : host - host connected to target
1388 void acornscsi_readstatusbyte(AS_Host *host) in acornscsi_readstatusbyte() argument
1390 acornscsi_sbic_issuecmd(host, CMND_XFERINFO|CMND_SBT); in acornscsi_readstatusbyte()
1391 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "reading status byte"); in acornscsi_readstatusbyte()
1392 host->scsi.SCp.Status = sbic_arm_read(host, SBIC_DATA); in acornscsi_readstatusbyte()
1396 * Function: unsigned char acornscsi_readmessagebyte(AS_Host *host)
1398 * Params : host - host connected to target
1401 unsigned char acornscsi_readmessagebyte(AS_Host *host) in acornscsi_readmessagebyte() argument
1405 acornscsi_sbic_issuecmd(host, CMND_XFERINFO | CMND_SBT); in acornscsi_readmessagebyte()
1407 acornscsi_sbic_wait(host, ASR_DBR, ASR_DBR, 1000, "for message byte"); in acornscsi_readmessagebyte()
1409 message = sbic_arm_read(host, SBIC_DATA); in acornscsi_readmessagebyte()
1411 /* wait for MSGIN-XFER-PAUSED */ in acornscsi_readmessagebyte()
1412 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after message byte"); in acornscsi_readmessagebyte()
1414 sbic_arm_read(host, SBIC_SSR); in acornscsi_readmessagebyte()
1420 * Function: void acornscsi_message(AS_Host *host)
1422 * Params : host - host connected to target
1425 void acornscsi_message(AS_Host *host) in acornscsi_message() argument
1432 message[msgidx] = acornscsi_readmessagebyte(host); in acornscsi_message()
1448 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); in acornscsi_message()
1450 /* wait for next msg-in */ in acornscsi_message()
1451 acornscsi_sbic_wait(host, ASR_INT, ASR_INT, 1000, "for interrupt after negate ack"); in acornscsi_message()
1452 sbic_arm_read(host, SBIC_SSR); in acornscsi_message()
1458 host->host->host_no, acornscsi_target(host)); in acornscsi_message()
1463 if (host->scsi.phase == PHASE_RECONNECTED) { in acornscsi_message()
1465 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.17) in acornscsi_message()
1471 host->scsi.reconnected.tag = message[1]; in acornscsi_message()
1472 if (acornscsi_reconnect_finish(host)) in acornscsi_message()
1473 host->scsi.phase = PHASE_MSGIN; in acornscsi_message()
1480 if (host->scsi.phase != PHASE_STATUSIN) { in acornscsi_message()
1481 printk(KERN_ERR "scsi%d.%c: command complete following non-status in phase?\n", in acornscsi_message()
1482 host->host->host_no, acornscsi_target(host)); in acornscsi_message()
1483 acornscsi_dumplog(host, host->SCpnt->device->id); in acornscsi_message()
1485 host->scsi.phase = PHASE_DONE; in acornscsi_message()
1486 host->scsi.SCp.Message = message[0]; in acornscsi_message()
1491 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.20) in acornscsi_message()
1496 acornscsi_dma_cleanup(host); in acornscsi_message()
1497 scsi_pointer = arm_scsi_pointer(host->SCpnt); in acornscsi_message()
1498 *scsi_pointer = host->scsi.SCp; in acornscsi_message()
1499 scsi_pointer->sent_command = 0; in acornscsi_message()
1500 host->scsi.phase = PHASE_MSGIN; in acornscsi_message()
1505 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 5.6.19) in acornscsi_message()
1513 acornscsi_dma_cleanup(host); in acornscsi_message()
1514 host->scsi.SCp = *arm_scsi_pointer(host->SCpnt); in acornscsi_message()
1515 host->scsi.phase = PHASE_MSGIN; in acornscsi_message()
1520 * ANSI standard says: (Section SCSI-2 Rev. 10c Sect 6.4.2) in acornscsi_message()
1528 acornscsi_dma_cleanup(host); in acornscsi_message()
1529 host->scsi.phase = PHASE_DISCONNECT; in acornscsi_message()
1537 * transfer. Re-initiate sync transfer negotiation now, and if in acornscsi_message()
1540 if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) in acornscsi_message()
1541 host->device[host->SCpnt->device->id].sync_state = SYNC_NEGOCIATE; in acornscsi_message()
1547 if (msgqueue_msglength(&host->scsi.msgs)) in acornscsi_message()
1548 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); in acornscsi_message()
1550 switch (host->scsi.last_message) { in acornscsi_message()
1556 host->host->host_no, acornscsi_target(host)); in acornscsi_message()
1557 host->device[host->SCpnt->device->id].sync_xfer = SYNCHTRANSFER_2DBA; in acornscsi_message()
1558 host->device[host->SCpnt->device->id].sync_state = SYNC_ASYNCHRONOUS; in acornscsi_message()
1559 sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); in acornscsi_message()
1570 host->host->host_no, acornscsi_target(host), in acornscsi_message()
1578 if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST) { in acornscsi_message()
1585 host->device[host->SCpnt->device->id].sync_state = SYNC_COMPLETED; in acornscsi_message()
1587 host->host->host_no, acornscsi_target(host), in acornscsi_message()
1589 host->device[host->SCpnt->device->id].sync_xfer = in acornscsi_message()
1597 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); in acornscsi_message()
1600 msgqueue_addmsg(&host->scsi.msgs, 5, EXTENDED_MESSAGE, 3, in acornscsi_message()
1602 host->device[host->SCpnt->device->id].sync_xfer = in acornscsi_message()
1605 sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); in acornscsi_message()
1614 /* The WD33C93A is only 8-bit. We respond with a MESSAGE_REJECT in acornscsi_message()
1618 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); in acornscsi_message()
1619 msgqueue_flush(&host->scsi.msgs); in acornscsi_message()
1620 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); in acornscsi_message()
1627 host->host->host_no, acornscsi_target(host), in acornscsi_message()
1629 acornscsi_sbic_issuecmd(host, CMND_ASSERTATN); in acornscsi_message()
1630 msgqueue_flush(&host->scsi.msgs); in acornscsi_message()
1631 msgqueue_addmsg(&host->scsi.msgs, 1, MESSAGE_REJECT); in acornscsi_message()
1632 host->scsi.phase = PHASE_MSGIN; in acornscsi_message()
1635 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); in acornscsi_message()
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
1644 void acornscsi_buildmessages(AS_Host *host) in acornscsi_buildmessages() argument
1649 msgqueue_addmsg(&host->scsi.msgs, 1, BUS_DEVICE_RESET); in acornscsi_buildmessages()
1654 msgqueue_addmsg(&host->scsi.msgs, 1, in acornscsi_buildmessages()
1655 IDENTIFY(host->device[host->SCpnt->device->id].disconnect_ok, in acornscsi_buildmessages()
1656 host->SCpnt->device->lun)); in acornscsi_buildmessages()
1661 acornscsi_abortcmd(host); in acornscsi_buildmessages()
1668 if (host->device[host->SCpnt->device->id].sync_state == SYNC_NEGOCIATE) { in acornscsi_buildmessages()
1669 host->device[host->SCpnt->device->id].sync_state = SYNC_SENT_REQUEST; in acornscsi_buildmessages()
1670 msgqueue_addmsg(&host->scsi.msgs, 5, in acornscsi_buildmessages()
1678 * Function: int acornscsi_starttransfer(AS_Host *host)
1680 * Params : host - host to which target is connected
1684 int acornscsi_starttransfer(AS_Host *host) in acornscsi_starttransfer() argument
1688 if (!host->scsi.SCp.ptr /*&& host->scsi.SCp.this_residual*/) { in acornscsi_starttransfer()
1690 host->host->host_no, acornscsi_target(host)); in acornscsi_starttransfer()
1694 residual = scsi_bufflen(host->SCpnt) - host->scsi.SCp.scsi_xferred; in acornscsi_starttransfer()
1696 sbic_arm_write(host, SBIC_SYNCHTRANSFER, host->device[host->SCpnt->device->id].sync_xfer); in acornscsi_starttransfer()
1697 sbic_arm_writenext(host, residual >> 16); in acornscsi_starttransfer()
1698 sbic_arm_writenext(host, residual >> 8); in acornscsi_starttransfer()
1699 sbic_arm_writenext(host, residual); in acornscsi_starttransfer()
1700 acornscsi_sbic_issuecmd(host, CMND_XFERINFO); in acornscsi_starttransfer()
1708 * Function : acornscsi_reconnect(AS_Host *host)
1710 * Params : host - host specific data
1716 int acornscsi_reconnect(AS_Host *host) in acornscsi_reconnect() argument
1720 target = sbic_arm_read(host, SBIC_SOURCEID); in acornscsi_reconnect()
1723 printk(KERN_ERR "scsi%d: invalid source id after reselection " in acornscsi_reconnect()
1724 "- device fault?\n", in acornscsi_reconnect()
1725 host->host->host_no); in acornscsi_reconnect()
1729 if (host->SCpnt && !host->scsi.disconnectable) { in acornscsi_reconnect()
1732 host->host->host_no, target, host->SCpnt->device->id); in acornscsi_reconnect()
1733 host->SCpnt = NULL; in acornscsi_reconnect()
1736 lun = sbic_arm_read(host, SBIC_DATA) & 7; in acornscsi_reconnect()
1738 host->scsi.reconnected.target = target; in acornscsi_reconnect()
1739 host->scsi.reconnected.lun = lun; in acornscsi_reconnect()
1740 host->scsi.reconnected.tag = 0; in acornscsi_reconnect()
1742 if (host->scsi.disconnectable && host->SCpnt && in acornscsi_reconnect()
1743 host->SCpnt->device->id == target && host->SCpnt->device->lun == lun) in acornscsi_reconnect()
1746 if (!ok && queue_probetgtlun(&host->queues.disconnected, target, lun)) in acornscsi_reconnect()
1749 ADD_STATUS(target, 0x81, host->scsi.phase, 0); in acornscsi_reconnect()
1752 host->scsi.phase = PHASE_RECONNECTED; in acornscsi_reconnect()
1757 host->host->host_no, '0' + target); in acornscsi_reconnect()
1758 acornscsi_dumplog(host, target); in acornscsi_reconnect()
1759 acornscsi_abortcmd(host); in acornscsi_reconnect()
1760 if (host->SCpnt) { in acornscsi_reconnect()
1761 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); in acornscsi_reconnect()
1762 host->SCpnt = NULL; in acornscsi_reconnect()
1765 acornscsi_sbic_issuecmd(host, CMND_NEGATEACK); in acornscsi_reconnect()
1770 * Function: int acornscsi_reconnect_finish(AS_Host *host)
1772 * Params : host - host to complete
1776 int acornscsi_reconnect_finish(AS_Host *host) in acornscsi_reconnect_finish() argument
1778 if (host->scsi.disconnectable && host->SCpnt) { in acornscsi_reconnect_finish()
1779 host->scsi.disconnectable = 0; in acornscsi_reconnect_finish()
1780 if (host->SCpnt->device->id == host->scsi.reconnected.target && in acornscsi_reconnect_finish()
1781 host->SCpnt->device->lun == host->scsi.reconnected.lun && in acornscsi_reconnect_finish()
1782 scsi_cmd_to_rq(host->SCpnt)->tag == host->scsi.reconnected.tag) { in acornscsi_reconnect_finish()
1784 DBG(host->SCpnt, printk("scsi%d.%c: reconnected", in acornscsi_reconnect_finish()
1785 host->host->host_no, acornscsi_target(host))); in acornscsi_reconnect_finish()
1788 queue_add_cmd_tail(&host->queues.disconnected, host->SCpnt); in acornscsi_reconnect_finish()
1790 DBG(host->SCpnt, printk("scsi%d.%c: had to move command " in acornscsi_reconnect_finish()
1792 host->host->host_no, acornscsi_target(host))); in acornscsi_reconnect_finish()
1794 host->SCpnt = NULL; in acornscsi_reconnect_finish()
1797 if (!host->SCpnt) { in acornscsi_reconnect_finish()
1798 host->SCpnt = queue_remove_tgtluntag(&host->queues.disconnected, in acornscsi_reconnect_finish()
1799 host->scsi.reconnected.target, in acornscsi_reconnect_finish()
1800 host->scsi.reconnected.lun, in acornscsi_reconnect_finish()
1801 host->scsi.reconnected.tag); in acornscsi_reconnect_finish()
1803 DBG(host->SCpnt, printk("scsi%d.%c: had to get command", in acornscsi_reconnect_finish()
1804 host->host->host_no, acornscsi_target(host))); in acornscsi_reconnect_finish()
1808 if (!host->SCpnt) in acornscsi_reconnect_finish()
1809 acornscsi_abortcmd(host); in acornscsi_reconnect_finish()
1814 host->scsi.SCp = *arm_scsi_pointer(host->SCpnt); in acornscsi_reconnect_finish()
1817 host->scsi.SCp.ptr, host->scsi.SCp.this_residual); in acornscsi_reconnect_finish()
1824 host->dma.transferred = host->scsi.SCp.scsi_xferred; in acornscsi_reconnect_finish()
1826 return host->SCpnt != NULL; in acornscsi_reconnect_finish()
1830 * Function: void acornscsi_disconnect_unexpected(AS_Host *host)
1832 * Params : host - host on which disconnect occurred
1835 void acornscsi_disconnect_unexpected(AS_Host *host) in acornscsi_disconnect_unexpected() argument
1838 host->host->host_no, acornscsi_target(host)); in acornscsi_disconnect_unexpected()
1840 acornscsi_dumplog(host, 8); in acornscsi_disconnect_unexpected()
1843 acornscsi_done(host, &host->SCpnt, DID_ERROR); in acornscsi_disconnect_unexpected()
1847 * Function: void acornscsi_abortcmd(AS_host *host, unsigned char tag)
1849 * Params : host - host with connected command to abort
1852 void acornscsi_abortcmd(AS_Host *host) in acornscsi_abortcmd() argument
1854 host->scsi.phase = PHASE_ABORTED; in acornscsi_abortcmd()
1855 sbic_arm_write(host, SBIC_CMND, CMND_ASSERTATN); in acornscsi_abortcmd()
1857 msgqueue_flush(&host->scsi.msgs); in acornscsi_abortcmd()
1858 msgqueue_addmsg(&host->scsi.msgs, 1, ABORT); in acornscsi_abortcmd()
1865 * Function: int acornscsi_sbicintr(AS_Host *host)
1867 * Params : host - host to process
1873 intr_ret_t acornscsi_sbicintr(AS_Host *host, int in_irq) in acornscsi_sbicintr() argument
1877 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_sbicintr()
1881 ssr = sbic_arm_read(host, SBIC_SSR); in acornscsi_sbicintr()
1884 print_sbic_status(asr, ssr, host->scsi.phase); in acornscsi_sbicintr()
1887 ADD_STATUS(8, ssr, host->scsi.phase, in_irq); in acornscsi_sbicintr()
1889 if (host->SCpnt && !host->scsi.disconnectable) in acornscsi_sbicintr()
1890 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); in acornscsi_sbicintr()
1893 case 0x00: /* reset state - not advanced */ in acornscsi_sbicintr()
1895 host->host->host_no); in acornscsi_sbicintr()
1896 /* setup sbic - WD33C93A */ in acornscsi_sbicintr()
1897 sbic_arm_write(host, SBIC_OWNID, OWNID_EAF | host->host->this_id); in acornscsi_sbicintr()
1898 sbic_arm_write(host, SBIC_CMND, CMND_RESET); in acornscsi_sbicintr()
1901 case 0x01: /* reset state - advanced */ in acornscsi_sbicintr()
1902 sbic_arm_write(host, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI); in acornscsi_sbicintr()
1903 sbic_arm_write(host, SBIC_TIMEOUT, TIMEOUT_TIME); in acornscsi_sbicintr()
1904 sbic_arm_write(host, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA); in acornscsi_sbicintr()
1905 sbic_arm_write(host, SBIC_SOURCEID, SOURCEID_ER | SOURCEID_DSP); in acornscsi_sbicintr()
1906 msgqueue_flush(&host->scsi.msgs); in acornscsi_sbicintr()
1910 acornscsi_disconnect_unexpected(host); in acornscsi_sbicintr()
1914 switch (host->scsi.phase) { in acornscsi_sbicintr()
1917 case 0x11: /* -> PHASE_CONNECTED */ in acornscsi_sbicintr()
1918 /* BUS FREE -> SELECTION */ in acornscsi_sbicintr()
1919 host->scsi.phase = PHASE_CONNECTED; in acornscsi_sbicintr()
1920 msgqueue_flush(&host->scsi.msgs); in acornscsi_sbicintr()
1921 host->dma.transferred = host->scsi.SCp.scsi_xferred; in acornscsi_sbicintr()
1923 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_sbicintr()
1926 ssr = sbic_arm_read(host, SBIC_SSR); in acornscsi_sbicintr()
1927 ADD_STATUS(8, ssr, host->scsi.phase, 1); in acornscsi_sbicintr()
1928 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, 1); in acornscsi_sbicintr()
1932 /* -> PHASE_IDLE */ in acornscsi_sbicintr()
1933 acornscsi_done(host, &host->SCpnt, DID_NO_CONNECT); in acornscsi_sbicintr()
1936 case 0x81: /* -> PHASE_RECONNECTED or PHASE_ABORTED */ in acornscsi_sbicintr()
1937 /* BUS FREE -> RESELECTION */ in acornscsi_sbicintr()
1938 host->origSCpnt = host->SCpnt; in acornscsi_sbicintr()
1939 host->SCpnt = NULL; in acornscsi_sbicintr()
1940 msgqueue_flush(&host->scsi.msgs); in acornscsi_sbicintr()
1941 acornscsi_reconnect(host); in acornscsi_sbicintr()
1946 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
1947 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
1948 acornscsi_abortcmd(host); in acornscsi_sbicintr()
1956 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ in acornscsi_sbicintr()
1957 /* SELECTION -> COMMAND */ in acornscsi_sbicintr()
1958 acornscsi_sendcommand(host); in acornscsi_sbicintr()
1961 case 0x8b: /* -> PHASE_STATUS */ in acornscsi_sbicintr()
1962 /* SELECTION -> STATUS */ in acornscsi_sbicintr()
1963 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
1964 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
1968 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
1969 /* SELECTION ->MESSAGE OUT */ in acornscsi_sbicintr()
1970 host->scsi.phase = PHASE_MSGOUT; in acornscsi_sbicintr()
1971 acornscsi_buildmessages(host); in acornscsi_sbicintr()
1972 acornscsi_sendmessage(host); in acornscsi_sbicintr()
1977 acornscsi_done(host, &host->SCpnt, DID_ERROR); in acornscsi_sbicintr()
1982 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
1983 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
1984 acornscsi_abortcmd(host); in acornscsi_sbicintr()
1994 case 0x8a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ in acornscsi_sbicintr()
1995 case 0x1a: /* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ in acornscsi_sbicintr()
1996 /* MESSAGE OUT -> COMMAND */ in acornscsi_sbicintr()
1997 acornscsi_sendcommand(host); in acornscsi_sbicintr()
2000 case 0x8b: /* -> PHASE_STATUS */ in acornscsi_sbicintr()
2001 case 0x1b: /* -> PHASE_STATUS */ in acornscsi_sbicintr()
2002 /* MESSAGE OUT -> STATUS */ in acornscsi_sbicintr()
2003 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
2004 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
2007 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2008 /* MESSAGE_OUT(MESSAGE_IN) ->MESSAGE OUT */ in acornscsi_sbicintr()
2009 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2012 case 0x4f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2013 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2014 /* MESSAGE OUT -> MESSAGE IN */ in acornscsi_sbicintr()
2015 acornscsi_message(host); in acornscsi_sbicintr()
2020 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2021 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2027 case 0x18: /* -> PHASE_DATAOUT */ in acornscsi_sbicintr()
2028 /* COMMAND -> DATA OUT */ in acornscsi_sbicintr()
2029 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) in acornscsi_sbicintr()
2030 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2031 acornscsi_dma_setup(host, DMA_OUT); in acornscsi_sbicintr()
2032 if (!acornscsi_starttransfer(host)) in acornscsi_sbicintr()
2033 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2034 host->scsi.phase = PHASE_DATAOUT; in acornscsi_sbicintr()
2037 case 0x19: /* -> PHASE_DATAIN */ in acornscsi_sbicintr()
2038 /* COMMAND -> DATA IN */ in acornscsi_sbicintr()
2039 if (host->scsi.SCp.sent_command != host->SCpnt->cmd_len) in acornscsi_sbicintr()
2040 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2041 acornscsi_dma_setup(host, DMA_IN); in acornscsi_sbicintr()
2042 if (!acornscsi_starttransfer(host)) in acornscsi_sbicintr()
2043 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2044 host->scsi.phase = PHASE_DATAIN; in acornscsi_sbicintr()
2047 case 0x1b: /* -> PHASE_STATUS */ in acornscsi_sbicintr()
2048 /* COMMAND -> STATUS */ in acornscsi_sbicintr()
2049 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
2050 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
2053 case 0x1e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2054 /* COMMAND -> MESSAGE OUT */ in acornscsi_sbicintr()
2055 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2058 case 0x1f: /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2059 /* COMMAND -> MESSAGE IN */ in acornscsi_sbicintr()
2060 acornscsi_message(host); in acornscsi_sbicintr()
2065 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2066 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2071 if (ssr == 0x85) { /* -> PHASE_IDLE */ in acornscsi_sbicintr()
2072 host->scsi.disconnectable = 1; in acornscsi_sbicintr()
2073 host->scsi.reconnected.tag = 0; in acornscsi_sbicintr()
2074 host->scsi.phase = PHASE_IDLE; in acornscsi_sbicintr()
2075 host->stats.disconnects += 1; in acornscsi_sbicintr()
2078 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2079 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2084 if (ssr == 0x81) /* -> PHASE_RECONNECTED or PHASE_ABORTED */ in acornscsi_sbicintr()
2085 acornscsi_reconnect(host); in acornscsi_sbicintr()
2088 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2089 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2095 * Command reconnected - if MESGIN, get message - it may be in acornscsi_sbicintr()
2102 if (ssr != 0x8f && !acornscsi_reconnect_finish(host)) in acornscsi_sbicintr()
2104 ADD_STATUS(host->SCpnt->device->id, ssr, host->scsi.phase, in_irq); in acornscsi_sbicintr()
2107 /* -> PHASE_DATAOUT */ in acornscsi_sbicintr()
2108 /* MESSAGE IN -> DATA OUT */ in acornscsi_sbicintr()
2109 acornscsi_dma_setup(host, DMA_OUT); in acornscsi_sbicintr()
2110 if (!acornscsi_starttransfer(host)) in acornscsi_sbicintr()
2111 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2112 host->scsi.phase = PHASE_DATAOUT; in acornscsi_sbicintr()
2116 /* -> PHASE_DATAIN */ in acornscsi_sbicintr()
2117 /* MESSAGE IN -> DATA IN */ in acornscsi_sbicintr()
2118 acornscsi_dma_setup(host, DMA_IN); in acornscsi_sbicintr()
2119 if (!acornscsi_starttransfer(host)) in acornscsi_sbicintr()
2120 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2121 host->scsi.phase = PHASE_DATAIN; in acornscsi_sbicintr()
2125 /* MESSAGE IN -> COMMAND */ in acornscsi_sbicintr()
2126 acornscsi_sendcommand(host);/* -> PHASE_COMMAND, PHASE_COMMANDPAUSED */ in acornscsi_sbicintr()
2130 /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2131 /* MESSAGE IN -> STATUS */ in acornscsi_sbicintr()
2132 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
2133 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
2137 /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2138 /* MESSAGE IN -> MESSAGE OUT */ in acornscsi_sbicintr()
2139 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2143 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2148 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2149 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2155 * This is simple - if we disconnect then the DMA address & count is in acornscsi_sbicintr()
2159 case 0x19: /* -> PHASE_DATAIN */ in acornscsi_sbicintr()
2160 case 0x89: /* -> PHASE_DATAIN */ in acornscsi_sbicintr()
2161 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2164 case 0x1b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2165 case 0x4b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2166 case 0x8b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2167 /* DATA IN -> STATUS */ in acornscsi_sbicintr()
2168 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2169 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2170 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2171 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
2172 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
2175 case 0x1e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2176 case 0x4e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2177 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2178 /* DATA IN -> MESSAGE OUT */ in acornscsi_sbicintr()
2179 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2180 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2181 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2182 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2188 /* DATA IN -> MESSAGE IN */ in acornscsi_sbicintr()
2189 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2190 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2191 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2192 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2197 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2198 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2204 * This is more complicated - if we disconnect, the DMA could be 12 in acornscsi_sbicintr()
2208 case 0x18: /* -> PHASE_DATAOUT */ in acornscsi_sbicintr()
2209 case 0x88: /* -> PHASE_DATAOUT */ in acornscsi_sbicintr()
2210 acornscsi_abortcmd(host); in acornscsi_sbicintr()
2213 case 0x1b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2214 case 0x4b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2215 case 0x8b: /* -> PHASE_STATUSIN */ in acornscsi_sbicintr()
2216 /* DATA OUT -> STATUS */ in acornscsi_sbicintr()
2217 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2218 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2219 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2220 acornscsi_dma_adjust(host); in acornscsi_sbicintr()
2221 acornscsi_readstatusbyte(host); in acornscsi_sbicintr()
2222 host->scsi.phase = PHASE_STATUSIN; in acornscsi_sbicintr()
2225 case 0x1e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2226 case 0x4e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2227 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2228 /* DATA OUT -> MESSAGE OUT */ in acornscsi_sbicintr()
2229 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2230 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2231 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2232 acornscsi_dma_adjust(host); in acornscsi_sbicintr()
2233 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2239 /* DATA OUT -> MESSAGE IN */ in acornscsi_sbicintr()
2240 host->scsi.SCp.scsi_xferred = scsi_bufflen(host->SCpnt) - in acornscsi_sbicintr()
2241 acornscsi_sbic_xfcount(host); in acornscsi_sbicintr()
2242 acornscsi_dma_stop(host); in acornscsi_sbicintr()
2243 acornscsi_dma_adjust(host); in acornscsi_sbicintr()
2244 acornscsi_message(host); /* -> PHASE_MSGIN, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2249 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2250 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2256 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2257 case 0x8f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2258 /* STATUS -> MESSAGE IN */ in acornscsi_sbicintr()
2259 acornscsi_message(host); in acornscsi_sbicintr()
2262 case 0x1e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2263 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2264 /* STATUS -> MESSAGE OUT */ in acornscsi_sbicintr()
2265 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2270 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2271 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2277 case 0x1e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2278 case 0x4e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2279 case 0x8e: /* -> PHASE_MSGOUT */ in acornscsi_sbicintr()
2280 /* MESSAGE IN -> MESSAGE OUT */ in acornscsi_sbicintr()
2281 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2284 case 0x1f: /* -> PHASE_MSGIN, PHASE_DONE, PHASE_DISCONNECT */ in acornscsi_sbicintr()
2288 acornscsi_message(host); in acornscsi_sbicintr()
2293 host->host->host_no, acornscsi_target(host)); in acornscsi_sbicintr()
2294 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2295 acornscsi_done(host, &host->SCpnt, DID_ERROR); in acornscsi_sbicintr()
2300 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2301 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2307 case 0x85: /* -> PHASE_IDLE */ in acornscsi_sbicintr()
2308 acornscsi_done(host, &host->SCpnt, DID_OK); in acornscsi_sbicintr()
2313 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2318 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2319 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2326 if (host->SCpnt) in acornscsi_sbicintr()
2327 acornscsi_done(host, &host->SCpnt, DID_ABORT); in acornscsi_sbicintr()
2329 clear_bit(host->scsi.reconnected.target * 8 + host->scsi.reconnected.lun, in acornscsi_sbicintr()
2330 host->busyluns); in acornscsi_sbicintr()
2331 host->scsi.phase = PHASE_IDLE; in acornscsi_sbicintr()
2339 acornscsi_sendmessage(host); in acornscsi_sbicintr()
2344 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2345 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2351 host->host->host_no, acornscsi_target(host), ssr); in acornscsi_sbicintr()
2352 acornscsi_dumplog(host, host->SCpnt ? host->SCpnt->device->id : 8); in acornscsi_sbicintr()
2360 * Params : irq - interrupt number
2361 * dev_id - device specific data (AS_Host structure)
2366 AS_Host *host = (AS_Host *)dev_id; in acornscsi_intr() local
2374 iostatus = readb(host->fast + INT_REG); in acornscsi_intr()
2377 acornscsi_dma_intr(host); in acornscsi_intr()
2378 iostatus = readb(host->fast + INT_REG); in acornscsi_intr()
2382 ret = acornscsi_sbicintr(host, in_irq); in acornscsi_intr()
2389 if (host->dma.xfer_required) in acornscsi_intr()
2390 acornscsi_dma_xfer(host); in acornscsi_intr()
2393 ret = acornscsi_kick(host); in acornscsi_intr()
2408 * Params : cmd - SCSI command
2415 AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; in acornscsi_queuecmd_lck() local
2418 if (acornscsi_cmdtype(SCpnt->cmnd[0]) == CMD_WRITE && (NO_WRITE & (1 << SCpnt->device->id))) { in acornscsi_queuecmd_lck()
2420 host->host->host_no, '0' + SCpnt->device->id); in acornscsi_queuecmd_lck()
2427 SCpnt->host_scribble = NULL; in acornscsi_queuecmd_lck()
2428 SCpnt->result = 0; in acornscsi_queuecmd_lck()
2429 scsi_pointer->phase = (int)acornscsi_datadirection(SCpnt->cmnd[0]); in acornscsi_queuecmd_lck()
2430 scsi_pointer->sent_command = 0; in acornscsi_queuecmd_lck()
2431 scsi_pointer->scsi_xferred = 0; in acornscsi_queuecmd_lck()
2435 host->stats.queues += 1; in acornscsi_queuecmd_lck()
2440 if (!queue_add_cmd_ordered(&host->queues.issue, SCpnt)) { in acornscsi_queuecmd_lck()
2446 if (host->scsi.phase == PHASE_IDLE) in acornscsi_queuecmd_lck()
2447 acornscsi_kick(host); in acornscsi_queuecmd_lck()
2459 * Purpose : abort a command on this host
2460 * Params : SCpnt - command to abort
2463 static enum res_abort acornscsi_do_abort(AS_Host *host, struct scsi_cmnd *SCpnt) in acornscsi_do_abort() argument
2467 if (queue_remove_cmd(&host->queues.issue, SCpnt)) { in acornscsi_do_abort()
2478 } else if (queue_remove_cmd(&host->queues.disconnected, SCpnt)) { in acornscsi_do_abort()
2490 } else if (host->SCpnt == SCpnt) { in acornscsi_do_abort()
2498 switch (host->scsi.phase) { in acornscsi_do_abort()
2508 if (host->scsi.disconnectable) { in acornscsi_do_abort()
2509 host->scsi.disconnectable = 0; in acornscsi_do_abort()
2510 host->SCpnt = NULL; in acornscsi_do_abort()
2521 sbic_arm_write(host, SBIC_CMND, CMND_DISCONNECT); in acornscsi_do_abort()
2522 host->SCpnt = NULL; in acornscsi_do_abort()
2527 acornscsi_abortcmd(host); in acornscsi_do_abort()
2531 } else if (host->origSCpnt == SCpnt) { in acornscsi_do_abort()
2538 host->origSCpnt = NULL; in acornscsi_do_abort()
2551 * Purpose : abort a command on this host
2552 * Params : SCpnt - command to abort
2557 AS_Host *host = (AS_Host *) SCpnt->device->host->hostdata; in acornscsi_abort() local
2560 host->stats.aborts += 1; in acornscsi_abort()
2565 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_abort()
2566 ssr = sbic_arm_read(host, SBIC_SSR); in acornscsi_abort()
2569 print_sbic_status(asr, ssr, host->scsi.phase); in acornscsi_abort()
2570 acornscsi_dumplog(host, SCpnt->device->id); in acornscsi_abort()
2574 printk("scsi%d: ", host->host->host_no); in acornscsi_abort()
2576 switch (acornscsi_do_abort(host, SCpnt)) { in acornscsi_abort()
2586 clear_bit(SCpnt->device->id * 8 + in acornscsi_abort()
2587 (u8)(SCpnt->device->lun & 0x7), host->busyluns); in acornscsi_abort()
2620 acornscsi_dumplog(host, SCpnt->device->id); in acornscsi_abort()
2633 * Purpose : reset a command on this host/reset this host
2634 * Params : SCpnt - command causing reset
2639 AS_Host *host = (AS_Host *)SCpnt->device->host->hostdata; in acornscsi_host_reset() local
2642 host->stats.resets += 1; in acornscsi_host_reset()
2648 asr = sbic_arm_read(host, SBIC_ASR); in acornscsi_host_reset()
2649 ssr = sbic_arm_read(host, SBIC_SSR); in acornscsi_host_reset()
2652 print_sbic_status(asr, ssr, host->scsi.phase); in acornscsi_host_reset()
2654 acornscsi_dumplog(host, devidx); in acornscsi_host_reset()
2658 acornscsi_dma_stop(host); in acornscsi_host_reset()
2661 * do hard reset. This resets all devices on this host, and so we in acornscsi_host_reset()
2664 acornscsi_resetcard(host); in acornscsi_host_reset()
2666 while ((SCptr = queue_remove(&host->queues.disconnected)) != NULL) in acornscsi_host_reset()
2677 * Function: char *acornscsi_info(struct Scsi_Host *host)
2679 * Params : host - host to give information on
2682 static const char *acornscsi_info(struct Scsi_Host *host) in acornscsi_info() argument
2695 , host->hostt->name, host->io_port, host->irq, in acornscsi_info()
2704 AS_Host *host; in acornscsi_show_info() local
2706 host = (AS_Host *)instance->hostdata; in acornscsi_show_info()
2718 host->base + SBIC_REGIDX, host->scsi.irq); in acornscsi_show_info()
2721 host->base + DMAC_OFFSET, host->scsi.irq); in acornscsi_show_info()
2725 "Queued commands: %-10u Issued commands: %-10u\n" in acornscsi_show_info()
2726 "Done commands : %-10u Reads : %-10u\n" in acornscsi_show_info()
2727 "Writes : %-10u Others : %-10u\n" in acornscsi_show_info()
2728 "Disconnects : %-10u Aborts : %-10u\n" in acornscsi_show_info()
2729 "Resets : %-10u\n\nLast phases:", in acornscsi_show_info()
2730 host->stats.queues, host->stats.removes, in acornscsi_show_info()
2731 host->stats.fins, host->stats.reads, in acornscsi_show_info()
2732 host->stats.writes, host->stats.miscs, in acornscsi_show_info()
2733 host->stats.disconnects, host->stats.aborts, in acornscsi_show_info()
2734 host->stats.resets); in acornscsi_show_info()
2740 statptr = host->status_ptr[devidx] - 10; in acornscsi_show_info()
2745 prev = host->status[devidx][statptr].when; in acornscsi_show_info()
2747 for (; statptr != host->status_ptr[devidx]; statptr = (statptr + 1) & (STATUS_BUFFER_SIZE - 1)) { in acornscsi_show_info()
2748 if (host->status[devidx][statptr].when) { in acornscsi_show_info()
2750 host->status[devidx][statptr].irq ? '-' : ' ', in acornscsi_show_info()
2751 host->status[devidx][statptr].ph, in acornscsi_show_info()
2752 host->status[devidx][statptr].ssr, in acornscsi_show_info()
2753 (host->status[devidx][statptr].when - prev) < 100 ? in acornscsi_show_info()
2754 (host->status[devidx][statptr].when - prev) : 99); in acornscsi_show_info()
2755 prev = host->status[devidx][statptr].when; in acornscsi_show_info()
2764 seq_printf(m, " %d/%llu ", scd->id, scd->lun); in acornscsi_show_info()
2765 if (scd->tagged_supported) in acornscsi_show_info()
2767 scd->simple_tags ? "en" : "dis"); in acornscsi_show_info()
2771 if (host->device[scd->id].sync_xfer & 15) in acornscsi_show_info()
2773 host->device[scd->id].sync_xfer & 15, in acornscsi_show_info()
2774 acornscsi_getperiod(host->device[scd->id].sync_xfer)); in acornscsi_show_info()
2794 .dma_boundary = PAGE_SIZE - 1,
2799 static int acornscsi_probe(struct expansion_card *ec, const struct ecard_id *id) in acornscsi_probe() argument
2801 struct Scsi_Host *host; in acornscsi_probe() local
2809 host = scsi_host_alloc(&acornscsi_template, sizeof(AS_Host)); in acornscsi_probe()
2810 if (!host) { in acornscsi_probe()
2811 ret = -ENOMEM; in acornscsi_probe()
2815 ashost = (AS_Host *)host->hostdata; in acornscsi_probe()
2817 ashost->base = ecardm_iomap(ec, ECARD_RES_MEMC, 0, 0); in acornscsi_probe()
2818 ashost->fast = ecardm_iomap(ec, ECARD_RES_IOCFAST, 0, 0); in acornscsi_probe()
2819 if (!ashost->base || !ashost->fast) { in acornscsi_probe()
2820 ret = -ENOMEM; in acornscsi_probe()
2824 host->irq = ec->irq; in acornscsi_probe()
2825 ashost->host = host; in acornscsi_probe()
2826 ashost->scsi.irq = host->irq; in acornscsi_probe()
2828 ec->irqaddr = ashost->fast + INT_REG; in acornscsi_probe()
2829 ec->irqmask = 0x0a; in acornscsi_probe()
2831 ret = request_irq(host->irq, acornscsi_intr, 0, "acornscsi", ashost); in acornscsi_probe()
2834 host->host_no, ashost->scsi.irq, ret); in acornscsi_probe()
2838 memset(&ashost->stats, 0, sizeof (ashost->stats)); in acornscsi_probe()
2839 queue_initialise(&ashost->queues.issue); in acornscsi_probe()
2840 queue_initialise(&ashost->queues.disconnected); in acornscsi_probe()
2841 msgqueue_initialise(&ashost->scsi.msgs); in acornscsi_probe()
2845 ret = scsi_add_host(host, &ec->dev); in acornscsi_probe()
2849 scsi_scan_host(host); in acornscsi_probe()
2853 free_irq(host->irq, ashost); in acornscsi_probe()
2854 msgqueue_free(&ashost->scsi.msgs); in acornscsi_probe()
2855 queue_free(&ashost->queues.disconnected); in acornscsi_probe()
2856 queue_free(&ashost->queues.issue); in acornscsi_probe()
2858 ecardm_iounmap(ec, ashost->fast); in acornscsi_probe()
2859 ecardm_iounmap(ec, ashost->base); in acornscsi_probe()
2860 scsi_host_put(host); in acornscsi_probe()
2869 struct Scsi_Host *host = ecard_get_drvdata(ec); in acornscsi_remove() local
2870 AS_Host *ashost = (AS_Host *)host->hostdata; in acornscsi_remove()
2873 scsi_remove_host(host); in acornscsi_remove()
2878 writeb(0x80, ashost->fast + PAGE_REG); in acornscsi_remove()
2880 free_irq(host->irq, ashost); in acornscsi_remove()
2882 msgqueue_free(&ashost->scsi.msgs); in acornscsi_remove()
2883 queue_free(&ashost->queues.disconnected); in acornscsi_remove()
2884 queue_free(&ashost->queues.issue); in acornscsi_remove()
2885 ecardm_iounmap(ec, ashost->fast); in acornscsi_remove()
2886 ecardm_iounmap(ec, ashost->base); in acornscsi_remove()
2887 scsi_host_put(host); in acornscsi_remove()