From 68754c496b16c6416ee601d6d9cc634e91e3b9f1 Mon Sep 17 00:00:00 2001 From: Thomas Schwinge Date: Mon, 20 Feb 2006 19:42:29 +0000 Subject: 2006-02-20 Thomas Schwinge Remove unused and unsupported code. Consult the file `DEVELOPMENT' for details. Partly based on suggestions by Gianluca Guida . * i386/bogus/asc.h: Remove file. * i386/bogus/aha.h: Likewise. * i386/bogus/eaha.h: Likewise. * i386/bogus/sbic.h: Likewise. * i386/bogus/sci.h: Likewise. * i386/bogus/sii.h: Likewise. * i386/bogus/siop.h: Likewise. * i386/i386at/eisa.h: Likewise. * scsi/adapters/README: Likewise. * scsi/adapters/scsi_33C93.h: Likewise. * scsi/adapters/scsi_33C93_hdw.c: Likewise. * scsi/adapters/scsi_5380.h: Likewise. * scsi/adapters/scsi_5380_hdw.c: Likewise. * scsi/adapters/scsi_53C700.h: Likewise. * scsi/adapters/scsi_53C700_hdw.c: Likewise. * scsi/adapters/scsi_53C94.h: Likewise. * scsi/adapters/scsi_53C94_hdw.c: Likewise. * scsi/adapters/scsi_7061.h: Likewise. * scsi/adapters/scsi_7061_hdw.c: Likewise. * scsi/adapters/scsi_89352.h: Likewise. * scsi/adapters/scsi_89352_hdw.c: Likewise. * scsi/adapters/scsi_aha15.h: Likewise. * scsi/adapters/scsi_aha15_hdw.c: Likewise. * scsi/adapters/scsi_aha17_hdw.c: Likewise. * scsi/adapters/scsi_dma.h: Likewise. * scsi/adapters/scsi_user_dma.c: Likewise. * scsi/adapters/scsi_user_dma.h: Likewise. * scsi/compat_30.h: Likewise. * scsi/disk_label.c: Likewise. * scsi/mapped_scsi.c: Likewise. * scsi/mapped_scsi.h: Likewise. * scsi/pc_scsi_label.c: Likewise. * scsi/rz.c: Likewise. * scsi/rz.h: Likewise. * scsi/rz_audio.c: Likewise. * scsi/rz_cpu.c: Likewise. * scsi/rz_disk.c: Likewise. * scsi/rz_disk_bbr.c: Likewise. * scsi/rz_host.c: Likewise. * scsi/rz_labels.h: Likewise. * scsi/rz_tape.c: Likewise. * scsi/scsi.c: Likewise. * scsi/scsi.h: Likewise. * scsi/scsi2.h: Likewise. * scsi/scsi_alldevs.c: Likewise. * scsi/scsi_comm.c: Likewise. * scsi/scsi_cpu.c: Likewise. * scsi/scsi_defs.h: Likewise. * scsi/scsi_disk.c: Likewise. * scsi/scsi_endian.h: Likewise. * scsi/scsi_jukebox.c: Likewise. * scsi/scsi_optical.c: Likewise. * scsi/scsi_printer.c: Likewise. * scsi/scsi_rom.c: Likewise. * scsi/scsi_scanner.c: Likewise. * scsi/scsi_tape.c: Likewise. * scsi/scsi_worm.c: Likewise. * i386/i386at/autoconf.c: Don't include and anymore and adopt all users of NAHA and NEAHA as if it were always defined to `0'. * i386/i386at/conf.c: Likewise. * Makefile.in (scsi-files): Remove variable and all users of it. --- scsi/adapters/scsi_5380_hdw.c | 2423 ----------------------------------------- 1 file changed, 2423 deletions(-) delete mode 100644 scsi/adapters/scsi_5380_hdw.c (limited to 'scsi/adapters/scsi_5380_hdw.c') diff --git a/scsi/adapters/scsi_5380_hdw.c b/scsi/adapters/scsi_5380_hdw.c deleted file mode 100644 index 2fc7d89..0000000 --- a/scsi/adapters/scsi_5380_hdw.c +++ /dev/null @@ -1,2423 +0,0 @@ -/* - * Mach Operating System - * Copyright (c) 1991,1990,1989 Carnegie Mellon University - * All Rights Reserved. - * - * Permission to use, copy, modify and distribute this software and its - * documentation is hereby granted, provided that both the copyright - * notice and this permission notice appear in all copies of the - * software, derivative works or modified versions, and any portions - * thereof, and that both notices appear in supporting documentation. - * - * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS - * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR - * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. - * - * Carnegie Mellon requests users of this software to return to - * - * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU - * School of Computer Science - * Carnegie Mellon University - * Pittsburgh PA 15213-3890 - * - * any improvements or extensions that they make and grant Carnegie the - * rights to redistribute these changes. - */ -/* - * File: scsi_5380_hdw.c - * Author: Alessandro Forin, Carnegie Mellon University - * Date: 4/91 - * - * Bottom layer of the SCSI driver: chip-dependent functions - * - * This file contains the code that is specific to the NCR 5380 - * SCSI chip (Host Bus Adapter in SCSI parlance): probing, start - * operation, and interrupt routine. - */ - -/* - * This layer works based on small simple 'scripts' that are installed - * at the start of the command and drive the chip to completion. - * The idea comes from the specs of the NCR 53C700 'script' processor. - * - * There are various reasons for this, mainly - * - Performance: identify the common (successful) path, and follow it; - * at interrupt time no code is needed to find the current status - * - Code size: it should be easy to compact common operations - * - Adaptability: the code skeleton should adapt to different chips without - * terrible complications. - * - Error handling: and it is easy to modify the actions performed - * by the scripts to cope with strange but well identified sequences - * - */ - -#include -#if NSCI > 0 -#include - -#include -#include -#include -#include -#include - -#include - -#include -#include -#include - -#ifdef VAXSTATION -#define PAD(n) char n[3] -#endif - -#include - -#ifdef PAD -typedef struct { - volatile unsigned char sci_data; /* r: Current data */ -/*#define sci_odata sci_data /* w: Out data */ - PAD(pad0); - - volatile unsigned char sci_icmd; /* rw: Initiator command */ - PAD(pad1); - - volatile unsigned char sci_mode; /* rw: Mode */ - PAD(pad2); - - volatile unsigned char sci_tcmd; /* rw: Target command */ - PAD(pad3); - - volatile unsigned char sci_bus_csr; /* r: Bus Status */ -/*#define sci_sel_enb sci_bus_csr /* w: Select enable */ - PAD(pad4); - - volatile unsigned char sci_csr; /* r: Status */ -/*#define sci_dma_send sci_csr /* w: Start dma send data */ - PAD(pad5); - - volatile unsigned char sci_idata; /* r: Input data */ -/*#define sci_trecv sci_idata /* w: Start dma receive, target */ - PAD(pad6); - - volatile unsigned char sci_iack; /* r: Interrupt Acknowledge */ -/*#define sci_irecv sci_iack /* w: Start dma receive, initiator */ - PAD(pad7); - -} sci_padded_regmap_t; -#else -typedef sci_regmap_t sci_padded_regmap_t; -#endif - -#ifdef VAXSTATION -#define check_memory(addr,dow) ((dow) ? wbadaddr(addr,4) : badaddr(addr,4)) - -/* vax3100 */ -#include -#define STC_5380_A VAX3100_STC_5380_A -#define STC_5380_B VAX3100_STC_5380_B -#define STC_DMAREG_OFF VAX3100_STC_DMAREG_OFF - -static int mem; /* mem++ seems to take approx 0.34 usecs */ -#define delay_1p2_us() {mem++;mem++;mem++;mem++;} -#define my_scsi_id(ctlr) (ka3100_scsi_id((ctlr))) -#endif /* VAXSTATION */ - - -#ifndef STC_5380_A /* cross compile check */ -typedef struct { - int sci_dma_dir, sci_dma_adr; -} *sci_dmaregs_t; -#define STC_DMAREG_OFF 0 -#define SCI_DMA_DIR_WRITE 0 -#define SCI_DMA_DIR_READ 1 -#define STC_5380_A 0 -#define STC_5380_B 0x100 -#define SCI_RAM_SIZE 0x10000 -#endif - -/* - * The 5380 can't tell you the scsi ID it uses, so - * unless there is another way use the defaults - */ -#ifndef my_scsi_id -#define my_scsi_id(ctlr) (scsi_initiator_id[(ctlr)]) -#endif - -/* - * Statically partition the DMA buffer between targets. - * This way we will eventually be able to attach/detach - * drives on-fly. And 18k/target is enough. - */ -#define PER_TGT_DMA_SIZE ((SCI_RAM_SIZE/7) & ~(sizeof(int)-1)) - -/* - * Round to 4k to make debug easier - */ -#define PER_TGT_BUFF_SIZE ((PER_TGT_DMA_SIZE >> 12) << 12) -#define PER_TGT_BURST_SIZE (PER_TGT_BUFF_SIZE>>1) - -/* - * Macros to make certain things a little more readable - */ - -#define SCI_ACK(ptr,phase) (ptr)->sci_tcmd = (phase) -#define SCI_CLR_INTR(regs) {register int temp = regs->sci_iack;} - - -/* - * A script has a two parts: a pre-condition and an action. - * The first triggers error handling if not satisfied and in - * our case it is formed by the current bus phase and connected - * condition as per bus status bits. The action part is just a - * function pointer, invoked in a standard way. The script - * pointer is advanced only if the action routine returns TRUE. - * See sci_intr() for how and where this is all done. - */ - -typedef struct script { - int condition; /* expected state at interrupt */ - int (*action)(); /* action routine */ -} *script_t; - -#define SCRIPT_MATCH(cs,bs) (((bs)&SCI_BUS_BSY)|SCI_CUR_PHASE((bs))) - -#define SCI_PHASE_DISC 0x0 /* sort of .. */ - - -/* forward decls of script actions */ -boolean_t - sci_dosynch(), /* negotiate synch xfer */ - sci_dma_in(), /* get data from target via dma */ - sci_dma_out(), /* send data to target via dma */ - sci_get_status(), /* get status from target */ - sci_end_transaction(), /* all come to an end */ - sci_msg_in(), /* get disconnect message(s) */ - sci_disconnected(); /* current target disconnected */ -/* forward decls of error handlers */ -boolean_t - sci_err_generic(), /* generic error handler */ - sci_err_disconn(), /* when a target disconnects */ - gimmeabreak(); /* drop into the debugger */ - -int sci_reset_scsibus(); -boolean_t sci_probe_target(); - -scsi_ret_t sci_select_target(); - -#ifdef VAXSTATION -/* - * This should be somewhere else, and it was a - * mistake to share this buffer across SCSIs. - */ -struct dmabuffer { - volatile char *base; - char *sbrk; -} dmab[1]; - -volatile char * -sci_buffer_base(unit) -{ - return dmab[unit].base; -} - -sci_buffer_init(dmar, ram) - sci_dmaregs_t dmar; - volatile char *ram; -{ - dmar->sci_dma_rammode = SCI_RAM_EXPMODE; - dmab[0].base = dmab[0].sbrk = (char *) ram; - blkclr((char *) ram, SCI_RAM_SIZE); -} -char * -sci_buffer_sbrk(size) -{ - char *ret = dmab[0].sbrk; - - dmab[0].sbrk += size; - if ((dmab[0].sbrk - dmab[0].base) > SCI_RAM_SIZE) - panic("scialloc"); - return ret; -} - -#endif /* VAXSTATION */ - -/* - * State descriptor for this layer. There is one such structure - * per (enabled) 5380 interface - */ -struct sci_softc { - watchdog_t wd; - sci_padded_regmap_t *regs; /* 5380 registers */ - sci_dmaregs_t dmar; /* DMA controller registers */ - volatile char *buff; /* DMA buffer memory (I/O space) */ - script_t script; - int (*error_handler)(); - int in_count; /* amnt we expect to receive */ - int out_count; /* amnt we are going to ship */ - - volatile char state; -#define SCI_STATE_BUSY 0x01 /* selecting or currently connected */ -#define SCI_STATE_TARGET 0x04 /* currently selected as target */ -#define SCI_STATE_COLLISION 0x08 /* lost selection attempt */ -#define SCI_STATE_DMA_IN 0x10 /* tgt --> initiator xfer */ - - unsigned char ntargets; /* how many alive on this scsibus */ - unsigned char done; - unsigned char extra_byte; - - scsi_softc_t *sc; - target_info_t *active_target; - - target_info_t *next_target; /* trying to seize bus */ - queue_head_t waiting_targets;/* other targets competing for bus */ - -} sci_softc_data[NSCI]; - -typedef struct sci_softc *sci_softc_t; - -sci_softc_t sci_softc[NSCI]; - -/* - * Definition of the controller for the auto-configuration program. - */ - -int sci_probe(), scsi_slave(), sci_go(), sci_intr(); -void scsi_attach(); - -vm_offset_t sci_std[NSCI] = { 0 }; -struct bus_device *sci_dinfo[NSCI*8]; -struct bus_ctlr *sci_minfo[NSCI]; -struct bus_driver sci_driver = - { sci_probe, scsi_slave, scsi_attach, sci_go, sci_std, "rz", sci_dinfo, - "sci", sci_minfo, BUS_INTR_B4_PROBE}; - -/* - * Scripts - */ -struct script -sci_script_data_in[] = { - { SCSI_PHASE_DATAI|SCI_BUS_BSY, sci_dma_in}, - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -sci_script_data_out[] = { - { SCSI_PHASE_DATAO|SCI_BUS_BSY, sci_dma_out}, - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -sci_script_cmd[] = { - { SCSI_PHASE_STATUS|SCI_BUS_BSY, sci_get_status}, - { SCSI_PHASE_MSG_IN|SCI_BUS_BSY, sci_end_transaction} -}, - -/* Synchronous transfer neg(oti)ation */ - -sci_script_try_synch[] = { - { SCSI_PHASE_MSG_OUT|SCI_BUS_BSY, sci_dosynch} -}, - -/* Disconnect sequence */ - -sci_script_disconnect[] = { - { SCI_PHASE_DISC, sci_disconnected} -}; - - - -#define u_min(a,b) (((a) < (b)) ? (a) : (b)) - - -#define DEBUG -#ifdef DEBUG - -sci_state(base) - vm_offset_t base; -{ - sci_padded_regmap_t *regs; - sci_dmaregs_t dmar; - extern char *sci; - unsigned dmadr; - int cnt, i; - - if (base == 0) - base = (vm_offset_t)sci; - - for (i = 0; i < 2; i++) { - regs = (sci_padded_regmap_t*) (base + - (i ? STC_5380_B : STC_5380_A)); - dmar = (sci_dmaregs_t) ((char*)regs + STC_DMAREG_OFF); - SCI_DMADR_GET(dmar,dmadr); - SCI_TC_GET(dmar,cnt); - - db_printf("scsi%d: ph %x (sb %x), mode %x, tph %x, csr %x, cmd %x, ", - i, - (unsigned) SCI_CUR_PHASE(regs->sci_bus_csr), - (unsigned) regs->sci_bus_csr, - (unsigned) regs->sci_mode, - (unsigned) regs->sci_tcmd, - (unsigned) regs->sci_csr, - (unsigned) regs->sci_icmd); - db_printf("dma%c %x @ %x\n", - (dmar->sci_dma_dir) ? 'I' : 'O', cnt, dmadr); - } - return 0; -} -sci_target_state(tgt) - target_info_t *tgt; -{ - if (tgt == 0) - tgt = sci_softc[0]->active_target; - if (tgt == 0) - return 0; - db_printf("fl %x dma %x+%x cmd %x id %x per %x off %x ior %x ret %x\n", - tgt->flags, tgt->dma_ptr, tgt->transient_state.dma_offset, - tgt->cmd_ptr, tgt->target_id, tgt->sync_period, tgt->sync_offset, - tgt->ior, tgt->done); - if (tgt->flags & TGT_DISCONNECTED){ - script_t spt; - - spt = tgt->transient_state.script; - db_printf("disconnected at "); - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(tgt->transient_state.handler, 1); - db_printf("\n"); - } - - return 0; -} - -sci_all_targets(unit) -{ - int i; - target_info_t *tgt; - for (i = 0; i < 8; i++) { - tgt = sci_softc[unit]->sc->target[i]; - if (tgt) - sci_target_state(tgt); - } -} - -sci_script_state(unit) -{ - script_t spt = sci_softc[unit]->script; - - if (spt == 0) return 0; - db_printsym(spt,1); - db_printf(": %x ", spt->condition); - db_printsym(spt->action,1); - db_printf(", "); - db_printsym(sci_softc[unit]->error_handler, 1); - return 0; - -} - -#define PRINT(x) if (scsi_debug) printf x - -#define TRMAX 200 -int tr[TRMAX+3]; -int trpt, trpthi; -#define TR(x) tr[trpt++] = x -#define TRWRAP trpthi = trpt; trpt = 0; -#define TRCHECK if (trpt > TRMAX) {TRWRAP} - -#define TRACE - -#ifdef TRACE - -#define LOGSIZE 256 -int sci_logpt; -char sci_log[LOGSIZE]; - -#define MAXLOG_VALUE 0x24 -struct { - char *name; - unsigned int count; -} logtbl[MAXLOG_VALUE]; - -static LOG(e,f) - char *f; -{ - sci_log[sci_logpt++] = (e); - if (sci_logpt == LOGSIZE) sci_logpt = 0; - if ((e) < MAXLOG_VALUE) { - logtbl[(e)].name = (f); - logtbl[(e)].count++; - } -} - -sci_print_log(skip) - int skip; -{ - register int i, j; - register unsigned char c; - - for (i = 0, j = sci_logpt; i < LOGSIZE; i++) { - c = sci_log[j]; - if (++j == LOGSIZE) j = 0; - if (skip-- > 0) - continue; - if (c < MAXLOG_VALUE) - db_printf(" %s", logtbl[c].name); - else - db_printf("-%d", c & 0x7f); - } - db_printf("\n"); - return 0; -} - -sci_print_stat() -{ - register int i; - register char *p; - for (i = 0; i < MAXLOG_VALUE; i++) { - if (p = logtbl[i].name) - printf("%d %s\n", logtbl[i].count, p); - } -} - -#else /* TRACE */ -#define LOG(e,f) -#endif /* TRACE */ - -#else /* DEBUG */ -#define PRINT(x) -#define LOG(e,f) -#define TR(x) -#define TRCHECK -#define TRWRAP -#endif /* DEBUG */ - - -/* - * Probe/Slave/Attach functions - */ - -/* - * Probe routine: - * Should find out (a) if the controller is - * present and (b) which/where slaves are present. - * - * Implementation: - * Send an identify msg to each possible target on the bus - * except of course ourselves. - */ -sci_probe(reg, ui) - char *reg; - struct bus_ctlr *ui; -{ - int unit = ui->unit; - sci_softc_t sci = &sci_softc_data[unit]; - int target_id, i; - scsi_softc_t *sc; - register sci_padded_regmap_t *regs; - spl_t s; - boolean_t did_banner = FALSE; - char *cmd_ptr; - static char *here = "sci_probe"; - - /* - * We are only called if the chip is there, - * but make sure anyways.. - */ - regs = (sci_padded_regmap_t *) (reg); - if (check_memory(regs, 0)) - return 0; - -#if notyet - /* Mappable version side */ - SCI_probe(reg, ui); -#endif - - /* - * Initialize hw descriptor - */ - sci_softc[unit] = sci; - sci->regs = regs; - sci->dmar = (sci_dmaregs_t)(reg + STC_DMAREG_OFF); - sci->buff = sci_buffer_base(0); - - queue_init(&sci->waiting_targets); - - sc = scsi_master_alloc(unit, sci); - sci->sc = sc; - - sc->go = sci_go; - sc->probe = sci_probe_target; - sc->watchdog = scsi_watchdog; - sci->wd.reset = sci_reset_scsibus; - -#ifdef MACH_KERNEL - sc->max_dma_data = -1; /* unlimited */ -#else - sc->max_dma_data = scsi_per_target_virtual; -#endif - - scsi_might_disconnect[unit] = 0; /* still true */ - - /* - * Reset chip - */ - s = splbio(); - sci_reset(sci, TRUE); - SCI_CLR_INTR(regs); - - /* - * Our SCSI id on the bus. - */ - - sc->initiator_id = my_scsi_id(unit); - printf("%s%d: my SCSI id is %d", ui->name, unit, sc->initiator_id); - - /* - * For all possible targets, see if there is one and allocate - * a descriptor for it if it is there. - */ - cmd_ptr = sci_buffer_sbrk(0); - for (target_id = 0; target_id < 8; target_id++) { - - register unsigned csr, dsr; - scsi_status_byte_t status; - - /* except of course ourselves */ - if (target_id == sc->initiator_id) - continue; - - if (sci_select_target( regs, sc->initiator_id, target_id, FALSE) == SCSI_RET_DEVICE_DOWN) { - SCI_CLR_INTR(regs); - continue; - } - - printf(",%s%d", did_banner++ ? " " : " target(s) at ", - target_id); - - /* should be command phase here: we selected wo ATN! */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_CMD) - ; - - SCI_ACK(regs,SCSI_PHASE_CMD); - - /* build command in dma area */ - { - unsigned char *p = (unsigned char*) cmd_ptr; - - p[0] = SCSI_CMD_TEST_UNIT_READY; - p[1] = - p[2] = - p[3] = - p[4] = - p[5] = 0; - } - - sci_data_out(regs, SCSI_PHASE_CMD, 6, cmd_ptr); - - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_STATUS) - ; - - SCI_ACK(regs,SCSI_PHASE_STATUS); - - sci_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) - scsi_error( 0, SCSI_ERR_STATUS, status.bits, 0); - - /* get cmd_complete message */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_IN) - ; - - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &i); - - /* check disconnected, clear all intr bits */ - while (regs->sci_bus_csr & SCI_BUS_BSY) - ; - SCI_ACK(regs,SCI_PHASE_DISC); - - SCI_CLR_INTR(regs); - - /* ... */ - - /* - * Found a target - */ - sci->ntargets++; - { - register target_info_t *tgt; - - tgt = scsi_slave_alloc(unit, target_id, sci); - - /* "virtual" address for our use */ - tgt->cmd_ptr = sci_buffer_sbrk(PER_TGT_DMA_SIZE); - /* "physical" address for dma engine */ - tgt->dma_ptr = (char*)(tgt->cmd_ptr - sci->buff); -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - } - } - printf(".\n"); - - splx(s); - return 1; -} - -boolean_t -sci_probe_target(tgt, ior) - target_info_t *tgt; - io_req_t ior; -{ - sci_softc_t sci = sci_softc[tgt->masterno]; - boolean_t newlywed; - - newlywed = (tgt->cmd_ptr == 0); - if (newlywed) { - /* desc was allocated afresh */ - - /* "virtual" address for our use */ - tgt->cmd_ptr = sci_buffer_sbrk(PER_TGT_DMA_SIZE); - /* "physical" address for dma engine */ - tgt->dma_ptr = (char*)(tgt->cmd_ptr - sci->buff); -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_init(&tgt->fdma, scsi_per_target_virtual); -#endif /*MACH_KERNEL*/ - - } - - if (scsi_inquiry(tgt, SCSI_INQ_STD_DATA) == SCSI_RET_DEVICE_DOWN) - return FALSE; - - tgt->flags = TGT_ALIVE; - return TRUE; -} - - -static sci_wait(preg, until) - volatile unsigned char *preg; -{ - int timeo = 1000000; - /* read it over to avoid bus glitches */ - while ( ((*preg & until) != until) || - ((*preg & until) != until) || - ((*preg & until) != until)) { - delay(1); - if (!timeo--) { - printf("sci_wait TIMEO with x%x\n", *preg); - break; - } - } - return *preg; -} - -scsi_ret_t -sci_select_target(regs, myid, id, with_atn) - register sci_padded_regmap_t *regs; - unsigned char myid, id; - boolean_t with_atn; -{ - register unsigned char bid, icmd; - scsi_ret_t ret = SCSI_RET_RETRY; - - if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) - return ret; - - /* for our purposes.. */ - myid = 1 << myid; - id = 1 << id; - - regs->sci_sel_enb = myid; /* if not there already */ - - regs->sci_odata = myid; - regs->sci_mode |= SCI_MODE_ARB; - /* AIP might not set if BSY went true after we checked */ - for (bid = 0; bid < 20; bid++) /* 20usec circa */ - if (regs->sci_icmd & SCI_ICMD_AIP) - break; - if ((regs->sci_icmd & SCI_ICMD_AIP) == 0) { - goto lost; - } - - delay(2); /* 2.2us arb delay */ - - if (regs->sci_icmd & SCI_ICMD_LST) { - goto lost; - } - - regs->sci_mode &= ~SCI_MODE_PAR_CHK; - bid = regs->sci_data; - - if ((bid & ~myid) > myid) { - goto lost; - } - if (regs->sci_icmd & SCI_ICMD_LST) { - goto lost; - } - - /* Won arbitration, enter selection phase now */ - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd |= (with_atn ? (SCI_ICMD_SEL|SCI_ICMD_ATN) : SCI_ICMD_SEL); - regs->sci_icmd = icmd; - - if (regs->sci_icmd & SCI_ICMD_LST) { - goto nosel; - } - - /* XXX a target that violates specs might still drive the bus XXX */ - /* XXX should put our id out, and after the delay check nothi XXX */ - /* XXX ng else is out there. XXX */ - - delay_1p2_us(); - - regs->sci_sel_enb = 0; - - regs->sci_odata = myid | id; - - icmd |= SCI_ICMD_BSY|SCI_ICMD_DATA; - regs->sci_icmd = icmd; - - regs->sci_mode &= ~SCI_MODE_ARB; /* 2 deskew delays, too */ - - icmd &= ~SCI_ICMD_BSY; - regs->sci_icmd = icmd; - - /* bus settle delay, 400ns */ - delay(0); /* too much ? */ - - regs->sci_mode |= SCI_MODE_PAR_CHK; - - { - register int timeo = 2500;/* 250 msecs in 100 usecs chunks */ - while ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) - if (--timeo > 0) - delay(100); - else { - goto nodev; - } - } - - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL); - regs->sci_icmd = icmd; -/* regs->sci_sel_enb = myid;*/ /* looks like we should NOT have it */ - return SCSI_RET_SUCCESS; -nodev: - ret = SCSI_RET_DEVICE_DOWN; - regs->sci_sel_enb = myid; -nosel: - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_SEL|SCI_ICMD_ATN); - regs->sci_icmd = icmd; -lost: - bid = regs->sci_mode; - bid &= ~SCI_MODE_ARB; - bid |= SCI_MODE_PAR_CHK; - regs->sci_mode = bid; - - return ret; -} - -sci_data_out(regs, phase, count, data) - register sci_padded_regmap_t *regs; - unsigned char *data; -{ - register unsigned char icmd; - - /* ..checks.. */ - - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); -loop: - if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) - return count; - - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - icmd |= SCI_ICMD_DATA; - regs->sci_icmd = icmd; - regs->sci_odata = *data++; - icmd |= SCI_ICMD_ACK; - regs->sci_icmd = icmd; - - icmd &= ~(SCI_ICMD_DATA|SCI_ICMD_ACK); - while ( (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ)) - ; - regs->sci_icmd = icmd; - if (--count > 0) - goto loop; - return 0; -} - -sci_data_in(regs, phase, count, data) - register sci_padded_regmap_t *regs; - unsigned char *data; -{ - register unsigned char icmd; - - /* ..checks.. */ - - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); -loop: - if (SCI_CUR_PHASE(regs->sci_bus_csr) != phase) - return count; - - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - *data++ = regs->sci_data; - icmd |= SCI_ICMD_ACK; - regs->sci_icmd = icmd; - - icmd &= ~SCI_ICMD_ACK; - while ( (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ) && - (regs->sci_bus_csr & SCI_BUS_REQ)) - ; - regs->sci_icmd = icmd; - if (--count > 0) - goto loop; - return 0; - -} - -sci_reset(sci, quickly) - sci_softc_t sci; - boolean_t quickly; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dma = sci->dmar; - int dummy; - - regs->sci_icmd = SCI_ICMD_TEST; /* don't drive outputs */ - regs->sci_icmd = SCI_ICMD_TEST|SCI_ICMD_RST; - delay(25); - regs->sci_icmd = 0; - - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_PERR_IE; - regs->sci_tcmd = SCI_PHASE_DISC; /* make sure we do not miss transition */ - regs->sci_sel_enb = 0; - - /* idle the dma controller */ - dma->sci_dma_adr = 0; - dma->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_TC_PUT(dma,0); - - /* clear interrupt (two might be queued?) */ - SCI_CLR_INTR(regs); - SCI_CLR_INTR(regs); - - if (quickly) - return; - - /* - * reset the scsi bus, the interrupt routine does the rest - * or you can call sci_bus_reset(). - */ - regs->sci_icmd = SCI_ICMD_RST; - -} - -/* - * Operational functions - */ - -/* - * Start a SCSI command on a target - */ -sci_go(tgt, cmd_count, in_count, cmd_only) - target_info_t *tgt; - boolean_t cmd_only; -{ - sci_softc_t sci; - register spl_t s; - boolean_t disconn; - script_t scp; - boolean_t (*handler)(); - - LOG(1,"go"); - - sci = (sci_softc_t)tgt->hw_state; - - /* - * We cannot do real DMA. - */ -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - if (tgt->ior) - fdma_map(&tgt->fdma, tgt->ior); -#endif /*MACH_KERNEL*/ - - if ((tgt->cur_cmd == SCSI_CMD_WRITE) || - (tgt->cur_cmd == SCSI_CMD_LONG_WRITE)){ - io_req_t ior = tgt->ior; - register int len = ior->io_count; - - tgt->transient_state.out_count = len; - - if (len > PER_TGT_BUFF_SIZE) - len = PER_TGT_BUFF_SIZE; - bcopy( ior->io_data, - tgt->cmd_ptr + cmd_count, - len); - tgt->transient_state.copy_count = len; - - /* avoid leaks */ - if (len < tgt->block_size) { - bzero( tgt->cmd_ptr + cmd_count + len, - tgt->block_size - len); - tgt->transient_state.out_count = tgt->block_size; - } - } else { - tgt->transient_state.out_count = 0; - tgt->transient_state.copy_count = 0; - } - - tgt->transient_state.cmd_count = cmd_count; - - disconn = BGET(scsi_might_disconnect,tgt->masterno,tgt->target_id); - disconn = disconn && (sci->ntargets > 1); - disconn |= BGET(scsi_should_disconnect,tgt->masterno,tgt->target_id); - - /* - * Setup target state - */ - tgt->done = SCSI_RET_IN_PROGRESS; - - handler = (disconn) ? sci_err_disconn : sci_err_generic; - - switch (tgt->cur_cmd) { - case SCSI_CMD_READ: - case SCSI_CMD_LONG_READ: - LOG(0x13,"readop"); - scp = sci_script_data_in; - break; - case SCSI_CMD_WRITE: - case SCSI_CMD_LONG_WRITE: - LOG(0x14,"writeop"); - scp = sci_script_data_out; - break; - case SCSI_CMD_INQUIRY: - /* This is likely the first thing out: - do the synch neg if so */ - if (!cmd_only && ((tgt->flags&TGT_DID_SYNCH)==0)) { - scp = sci_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - break; - } - case SCSI_CMD_REQUEST_SENSE: - case SCSI_CMD_MODE_SENSE: - case SCSI_CMD_RECEIVE_DIAG_RESULTS: - case SCSI_CMD_READ_CAPACITY: - case SCSI_CMD_READ_BLOCK_LIMITS: - case SCSI_CMD_READ_TOC: - case SCSI_CMD_READ_SUBCH: - case SCSI_CMD_READ_HEADER: - case 0xc4: /* despised: SCSI_CMD_DEC_PLAYBACK_STATUS */ - case 0xdd: /* despised: SCSI_CMD_NEC_READ_SUBCH_Q */ - case 0xde: /* despised: SCSI_CMD_NEC_READ_TOC */ - scp = sci_script_data_in; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_MODE_SELECT: - case SCSI_CMD_REASSIGN_BLOCKS: - case SCSI_CMD_FORMAT_UNIT: - case 0xc9: /* vendor-spec: SCSI_CMD_DEC_PLAYBACK_CONTROL */ - tgt->transient_state.cmd_count = sizeof_scsi_command(tgt->cur_cmd); - tgt->transient_state.out_count = - cmd_count - tgt->transient_state.cmd_count; - scp = sci_script_data_out; - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - case SCSI_CMD_TEST_UNIT_READY: - /* - * Do the synch negotiation here, unless prohibited - * or done already - */ - if (tgt->flags & TGT_DID_SYNCH) { - scp = sci_script_cmd; - } else { - scp = sci_script_try_synch; - tgt->flags |= TGT_TRY_SYNCH; - cmd_only = FALSE; - } - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - break; - default: - LOG(0x1c,"cmdop"); - LOG(0x80+tgt->cur_cmd,0); - scp = sci_script_cmd; - } - - tgt->transient_state.script = scp; - tgt->transient_state.handler = handler; - tgt->transient_state.identify = (cmd_only) ? 0xff : - (disconn ? SCSI_IDENTIFY|SCSI_IFY_ENABLE_DISCONNECT : - SCSI_IDENTIFY); - - if (in_count) - tgt->transient_state.in_count = - (in_count < tgt->block_size) ? tgt->block_size : in_count; - else - tgt->transient_state.in_count = 0; - tgt->transient_state.dma_offset = 0; - - /* - * See if another target is currently selected on - * this SCSI bus, e.g. lock the sci structure. - * Note that it is the strategy routine's job - * to serialize ops on the same target as appropriate. - * XXX here and everywhere, locks! - */ - /* - * Protection viz reconnections makes it tricky. - */ -/* s = splbio();*/ - s = splhigh(); - - if (sci->wd.nactive++ == 0) - sci->wd.watchdog_state = SCSI_WD_ACTIVE; - - if (sci->state & SCI_STATE_BUSY) { - /* - * Queue up this target, note that this takes care - * of proper FIFO scheduling of the scsi-bus. - */ - LOG(3,"enqueue"); - enqueue_tail(&sci->waiting_targets, (queue_entry_t) tgt); - } else { - /* - * It is down to at most two contenders now, - * we will treat reconnections same as selections - * and let the scsi-bus arbitration process decide. - */ - sci->state |= SCI_STATE_BUSY; - sci->next_target = tgt; - sci_attempt_selection(sci); - /* - * Note that we might still lose arbitration.. - */ - } - splx(s); -} - -sci_attempt_selection(sci) - sci_softc_t sci; -{ - target_info_t *tgt; - register int out_count; - sci_padded_regmap_t *regs; - sci_dmaregs_t dmar; - register int cmd; - boolean_t ok; - scsi_ret_t ret; - - regs = sci->regs; - dmar = sci->dmar; - tgt = sci->next_target; - - LOG(4,"select"); - LOG(0x80+tgt->target_id,0); - - /* - * Init bus state variables and set registers. - */ - sci->active_target = tgt; - - /* reselection pending ? */ - if ((regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL)) && - (regs->sci_bus_csr & (SCI_BUS_BSY|SCI_BUS_SEL))) - return; - - sci->script = tgt->transient_state.script; - sci->error_handler = tgt->transient_state.handler; - sci->done = SCSI_RET_IN_PROGRESS; - - sci->in_count = 0; - sci->out_count = 0; - sci->extra_byte = 0; - - /* - * This is a bit involved, but the bottom line is we want to - * know after we selected with or w/o ATN if the selection - * went well (ret) and if it is (ok) to send the command. - */ - ok = TRUE; - if (tgt->flags & TGT_DID_SYNCH) { - if (tgt->transient_state.identify == 0xff) { - /* Select w/o ATN */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, FALSE); - } else { - /* Select with ATN */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, TRUE); - if (ret == SCSI_RET_SUCCESS) { - register unsigned char icmd; - - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_OUT) - ; - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd &= ~SCI_ICMD_ATN; - regs->sci_icmd = icmd; - SCI_ACK(regs,SCSI_PHASE_MSG_OUT); - ok = (sci_data_out(regs, SCSI_PHASE_MSG_OUT, - 1, &tgt->transient_state.identify) == 0); - } - } - } else if (tgt->flags & TGT_TRY_SYNCH) { - /* Select with ATN, do the synch xfer neg */ - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, TRUE); - if (ret == SCSI_RET_SUCCESS) { - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_MSG_OUT) - ; - ok = sci_dosynch( sci, regs->sci_csr, regs->sci_bus_csr); - } - } else { - ret = sci_select_target(regs, sci->sc->initiator_id, - tgt->target_id, FALSE); - } - - if (ret == SCSI_RET_DEVICE_DOWN) { - sci->done = ret; - sci_end(sci, regs->sci_csr, regs->sci_bus_csr); - return; - } - if ((ret != SCSI_RET_SUCCESS) || !ok) - return; - -/* time this out or do it via dma !! */ - while (SCI_CUR_PHASE(regs->sci_bus_csr) != SCSI_PHASE_CMD) - ; - - /* set dma pointer and counter to xfer command */ - out_count = tgt->transient_state.cmd_count; -#if 0 - SCI_ACK(regs,SCSI_PHASE_CMD); - sci_data_out(regs,SCSI_PHASE_CMD,out_count,tgt->cmd_ptr); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; -#else - SCI_DMADR_PUT(dmar,tgt->dma_ptr); - delay_1p2_us(); - SCI_TC_PUT(dmar,out_count); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_ACK(regs,SCSI_PHASE_CMD); - SCI_CLR_INTR(regs); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; - regs->sci_icmd = SCI_ICMD_DATA; - regs->sci_dma_send = 1; -#endif -} - -/* - * Interrupt routine - * Take interrupts from the chip - * - * Implementation: - * Move along the current command's script if - * all is well, invoke error handler if not. - */ -sci_intr(unit) -{ - register sci_softc_t sci; - register script_t scp; - register unsigned csr, bs, cmd; - register sci_padded_regmap_t *regs; - boolean_t try_match; -#if notyet - extern boolean_t rz_use_mapped_interface; - - if (rz_use_mapped_interface) - return SCI_intr(unit); -#endif - - LOG(5,"\n\tintr"); - - sci = sci_softc[unit]; - regs = sci->regs; - - /* ack interrupt */ - csr = regs->sci_csr; - bs = regs->sci_bus_csr; - cmd = regs->sci_icmd; -TR(regs->sci_mode); - SCI_CLR_INTR(regs); - -TR(csr); -TR(bs); -TR(cmd); -TRCHECK; - - if (cmd & SCI_ICMD_RST){ - sci_bus_reset(sci); - return; - } - - /* we got an interrupt allright */ - if (sci->active_target) - sci->wd.watchdog_state = SCSI_WD_ACTIVE; - - /* drop spurious calls */ - if ((csr & SCI_CSR_INT) == 0) { - LOG(2,"SPURIOUS"); - return; - } - - /* Note: reselect has I/O asserted, select has not */ - if ((sci->state & SCI_STATE_TARGET) || - ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == SCI_BUS_SEL)) { - sci_target_intr(sci,csr,bs); - return; - } - - scp = sci->script; - - /* Race: disconnecting, we get the disconnected notification - (csr sez BSY dropped) at the same time a reselect is active */ - if ((csr & SCI_CSR_DISC) && - scp && (scp->condition == SCI_PHASE_DISC)) { - (void) (*scp->action)(sci, csr, bs); - /* takes care of calling reconnect if necessary */ - return; - } - - /* check who got the bus */ - if ((scp == 0) || (cmd & SCI_ICMD_LST) || - ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == (SCI_BUS_SEL|SCI_BUS_IO))) { - sci_reconnect(sci, csr, bs); - return; - } - - if (SCRIPT_MATCH(csr,bs) != scp->condition) { - if (try_match = (*sci->error_handler)(sci, csr, bs)) { - csr = regs->sci_csr; - bs = regs->sci_bus_csr; - } - } else - try_match = TRUE; - - /* might have been side effected */ - scp = sci->script; - - if (try_match && (SCRIPT_MATCH(csr,bs) == scp->condition)) { - /* - * Perform the appropriate operation, - * then proceed - */ - if ((*scp->action)(sci, csr, bs)) { - /* might have been side effected */ - scp = sci->script; - sci->script = scp + 1; - } - } -} - - -sci_target_intr(sci) - register sci_softc_t sci; -{ - panic("SCI: TARGET MODE !!!\n"); -} - -/* - * All the many little things that the interrupt - * routine might switch to - */ -boolean_t -sci_end_transaction( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - char cmc; - - LOG(0x1f,"end_t"); - - /* Stop dma, no interrupt on disconnect */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_MONBSY|SCI_MODE_DMA_IE); -/* dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - regs->sci_sel_enb = (1 << sci->sc->initiator_id); - - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &cmc); - - if (cmc != SCSI_COMMAND_COMPLETE) - printf("{T%x}", cmc); - - /* check disconnected, clear all intr bits */ - while (regs->sci_bus_csr & SCI_BUS_BSY) - ; - SCI_CLR_INTR(regs); - SCI_ACK(regs,SCI_PHASE_DISC); - - if (!sci_end(sci, csr, bs)) { - SCI_CLR_INTR(regs); - (void) sci_reconnect(sci, csr, bs); - } - return FALSE; -} - -boolean_t -sci_end( sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register io_req_t ior; - register sci_padded_regmap_t *regs = sci->regs; - boolean_t reconn_pending; - - LOG(6,"end"); - - tgt = sci->active_target; - - if ((tgt->done = sci->done) == SCSI_RET_IN_PROGRESS) - tgt->done = SCSI_RET_SUCCESS; - - sci->script = 0; - - if (sci->wd.nactive-- == 1) - sci->wd.watchdog_state = SCSI_WD_INACTIVE; - - /* check reconnection not pending */ - bs = regs->sci_bus_csr; - reconn_pending = ((bs & (SCI_BUS_BSY|SCI_BUS_SEL|SCI_BUS_IO)) == (SCI_BUS_SEL|SCI_BUS_IO)); - if (!reconn_pending) { - sci_release_bus(sci); - } else { - sci->active_target = 0; -/* sci->state &= ~SCI_STATE_BUSY; later */ - } - - if (ior = tgt->ior) { -#ifdef MACH_KERNEL -#else /*MACH_KERNEL*/ - fdma_unmap(&tgt->fdma, ior); -#endif /*MACH_KERNEL*/ - LOG(0xA,"ops->restart"); - (*tgt->dev_ops->restart)( tgt, TRUE); - if (reconn_pending) - sci->state &= ~SCI_STATE_BUSY; - } - - return (!reconn_pending); -} - -boolean_t -sci_release_bus(sci) - register sci_softc_t sci; -{ - boolean_t ret = FALSE; - - LOG(9,"release"); - - sci->script = 0; - - if (sci->state & SCI_STATE_COLLISION) { - - LOG(0xB,"collided"); - sci->state &= ~SCI_STATE_COLLISION; - sci_attempt_selection(sci); - - } else if (queue_empty(&sci->waiting_targets)) { - - sci->state &= ~SCI_STATE_BUSY; - sci->active_target = 0; - ret = TRUE; - - } else { - - LOG(0xC,"dequeue"); - sci->next_target = (target_info_t *) - dequeue_head(&sci->waiting_targets); - sci_attempt_selection(sci); - } - return ret; -} - -boolean_t -sci_get_status( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - scsi2_status_byte_t status; - register target_info_t *tgt; - unsigned int len, mode; - - LOG(0xD,"get_status"); -TRWRAP; - - /* Stop dma */ - regs->sci_icmd = 0; - mode = regs->sci_mode; - regs->sci_mode = (mode & ~(SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - sci->state &= ~SCI_STATE_DMA_IN; - - tgt = sci->active_target; - - if (len = sci->in_count) { - register int count; - SCI_TC_GET(dmar,count); - if ((tgt->cur_cmd != SCSI_CMD_READ) && - (tgt->cur_cmd != SCSI_CMD_LONG_READ)){ - len -= count; - } else { - if (count) { -#if 0 - this is incorrect and besides.. - tgt->ior->io_residual = count; -#endif - len -= count; - } - sci_copyin( tgt, tgt->transient_state.dma_offset, - len, 0, 0); - } - } - - /* to get the phase mismatch intr */ - regs->sci_mode = mode; - - SCI_ACK(regs,SCSI_PHASE_STATUS); - - sci_data_in(regs, SCSI_PHASE_STATUS, 1, &status.bits); - - SCI_TC_PUT(dmar,0); - - if (status.st.scsi_status_code != SCSI_ST_GOOD) { - scsi_error(sci->active_target, SCSI_ERR_STATUS, status.bits, 0); - sci->done = (status.st.scsi_status_code == SCSI_ST_BUSY) ? - SCSI_RET_RETRY : SCSI_RET_NEED_SENSE; - } else - sci->done = SCSI_RET_SUCCESS; - - return TRUE; -} - -boolean_t -sci_dma_in( sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - char *dma_ptr; - register int count; - boolean_t advance_script = TRUE; - - LOG(0xE,"dma_in"); - - /* - * Problem: the 5380 pipelines xfers between the scsibus and - * itself and between itself and the DMA engine --> halting ? - * In the dmaout direction all is ok, except that (see NCR notes) - * the EOP interrupt is generated before the pipe is empty. - * In the dmain direction (here) the interrupt comes when - * one too many bytes have been xferred on chip! - * - * More specifically, IF we asked for count blindly and we had - * more than count bytes coming (double buffering) we would endup - * actually xferring count+1 from the scsibus, but only count - * to memory [hopefully the last byte sits in the sci_datai reg]. - * This could be helped, except most times count is an exact multiple - * of the sector size which is where disks disconnect.... - * - * INSTEAD, we recognize here that we expect more than count bytes - * coming and set the DMA count to count-1 but keep sci->in_count - * above to count. This will be wrong if the target disconnects - * amidst, but we can cure it. - * - * The places where this has an effect are marked by "EXTRA_BYTE" - */ - - tgt = sci->active_target; - sci->state |= SCI_STATE_DMA_IN; - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - regs->sci_icmd = 0; - - if (sci->in_count == 0) { - /* - * Got nothing yet: either just sent the command - * or just reconnected - */ - register int avail; - - count = tgt->transient_state.in_count; - count = u_min(count, (PER_TGT_BURST_SIZE)); - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - - /* common case of 8k-or-less read ? */ - advance_script = (tgt->transient_state.in_count == count); - - } else { - - /* - * We received some data. - */ - register int offset, xferred, eb; - unsigned char extrab = regs->sci_idata; /* EXTRA_BYTE */ - - SCI_TC_GET(dmar,xferred); - assert(xferred == 0); -if (scsi_debug) { -printf("{B %x %x %x (%x)}", - sci->in_count, xferred, sci->extra_byte, extrab); -} - /* ++EXTRA_BYTE */ - xferred = sci->in_count - xferred; - eb = sci->extra_byte; - /* --EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.in_count, (PER_TGT_BURST_SIZE)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int avail; - avail = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, avail); - } - advance_script = (tgt->transient_state.in_count == count); - - /* get some more */ - dma_ptr = tgt->dma_ptr + tgt->transient_state.dma_offset; - sci->in_count = count; - /* ++EXTRA_BYTE */ - if (!advance_script) { - sci->extra_byte = 1; /* that's the cure.. */ - count--; - } else - sci->extra_byte = 0; - /* --EXTRA_BYTE */ - SCI_TC_PUT(dmar,count); -/* regs->sci_icmd = 0;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_DATAI); - SCI_CLR_INTR(regs); - regs->sci_mode |= (advance_script ? SCI_MODE_DMA - : (SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, eb, extrab); - - /* last chunk ? */ - return advance_script; - } - - sci->in_count = count; - dma_ptr = tgt->dma_ptr + tgt->transient_state.dma_offset; - - /* ++EXTRA_BYTE */ - if (!advance_script) { - sci->extra_byte = 1; /* that's the cure.. */ - count--; - } else - sci->extra_byte = 0; - /* --EXTRA_BYTE */ - - SCI_TC_PUT(dmar,count); -/* regs->sci_icmd = 0;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_DATAI); - SCI_CLR_INTR(regs); - regs->sci_mode |= (advance_script ? SCI_MODE_DMA - : (SCI_MODE_DMA|SCI_MODE_DMA_IE)); - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - return advance_script; -} - -/* send data to target. Called in three different ways: - (a) to start transfer (b) to restart a bigger-than-8k - transfer (c) after reconnection - */ -int sci_delay = 1; - -boolean_t -sci_dma_out( sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - register char *dma_ptr; - register target_info_t *tgt; - boolean_t advance_script = TRUE; - int count = sci->out_count; - spl_t s; - register int tmp; - - LOG(0xF,"dma_out"); - - tgt = sci->active_target; - sci->state &= ~SCI_STATE_DMA_IN; - - if (sci->out_count == 0) { - /* - * Nothing committed: either just sent the - * command or reconnected - */ - register int remains; - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/*hold it */ - - regs->sci_icmd = SCI_ICMD_DATA; - - SCI_ACK(regs,SCSI_PHASE_DATAO); - - count = tgt->transient_state.out_count; - count = u_min(count, (PER_TGT_BURST_SIZE)); - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - - /* common case of 8k-or-less write ? */ - advance_script = (tgt->transient_state.out_count == count); - } else { - /* - * We sent some data. - * Also, take care of bogus interrupts - */ - register int offset, xferred; - -if (sci_delay & 1) delay(1000); - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/*hold it */ -/* regs->sci_icmd = SCI_ICMD_DATA; */ - - SCI_TC_GET(dmar,xferred); -if (xferred) printf("{A %x}", xferred); - xferred = sci->out_count - xferred; - assert(xferred > 0); - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - count = u_min(tgt->transient_state.out_count, (PER_TGT_BURST_SIZE)); - if (tgt->transient_state.dma_offset == PER_TGT_BUFF_SIZE) { - tgt->transient_state.dma_offset = 0; - } else { - register int remains; - remains = PER_TGT_BUFF_SIZE - tgt->transient_state.dma_offset; - count = u_min(count, remains); - } - /* last chunk ? */ - if (tgt->transient_state.out_count == count) - goto quickie; - - /* ship some more */ - dma_ptr = tgt->dma_ptr + - tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - sci->out_count = count; - /* - * Mistery: sometimes the first byte - * of an 8k chunk is missing from the tape, it must - * be that somehow touching the 5380 registers - * after the dma engine is ready screws up: false DRQ? - */ -s = splhigh(); - SCI_TC_PUT(dmar,count); -/* SCI_CLR_INTR(regs);*/ - regs->sci_mode = SCI_MODE_PAR_CHK | SCI_MODE_DMA | - SCI_MODE_MONBSY | SCI_MODE_DMA_IE; -/* regs->sci_icmd = SCI_ICMD_DATA;*/ - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - - regs->sci_dma_send = 1; -splx(s); - /* copy some more data */ - sci_copyout(tgt, offset, xferred); - return FALSE; - } - -quickie: - sci->out_count = count; - dma_ptr = tgt->dma_ptr + - tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - tmp = (advance_script ? - SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY: - SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY|SCI_MODE_DMA_IE); -s = splhigh(); - SCI_TC_PUT(dmar,count); -/* SCI_CLR_INTR(regs);*/ - regs->sci_mode = tmp; -/* regs->sci_icmd = SCI_ICMD_DATA;*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE; - regs->sci_dma_send = 1; -splx(s); - - return advance_script; -} - -/* disconnect-reconnect ops */ - -/* get the message in via dma */ -boolean_t -sci_msg_in(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - char *dma_ptr; - register sci_padded_regmap_t *regs = sci->regs; - register sci_dmaregs_t dmar = sci->dmar; - - LOG(0x15,"msg_in"); - - tgt = sci->active_target; - - dma_ptr = tgt->dma_ptr; - /* We would clobber the data for READs */ - if (sci->state & SCI_STATE_DMA_IN) { - register int offset; - offset = tgt->transient_state.cmd_count + tgt->transient_state.dma_offset; - dma_ptr += offset; - } - - /* ought to stop dma to start another */ - regs->sci_mode &= ~ (SCI_MODE_DMA|SCI_MODE_DMA_IE); - regs->sci_icmd = 0; - - /* We only really expect two bytes */ - SCI_TC_PUT(dmar,sizeof(scsi_command_group_0)); -/* regs->sci_icmd = 0*/ - SCI_DMADR_PUT(dmar,dma_ptr); - delay_1p2_us(); - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - SCI_CLR_INTR(regs); - regs->sci_mode |= SCI_MODE_DMA; - dmar->sci_dma_dir = SCI_DMA_DIR_READ; - regs->sci_irecv = 1; - - return TRUE; -} - -/* check the message is indeed a DISCONNECT */ -boolean_t -sci_disconnect(sci, csr, bs) - register sci_softc_t sci; -{ - register int len; - boolean_t ok = FALSE; - register sci_dmaregs_t dmar = sci->dmar; - register char *msgs; - unsigned int offset; - - - SCI_TC_GET(dmar,len); - len = sizeof(scsi_command_group_0) - len; - PRINT(("{G%d}",len)); - - /* wherever it was, take it from there */ - SCI_DMADR_GET(dmar,offset); - msgs = (char*)sci->buff + offset - len; - - if ((len == 0) || (len > 2)) - ok = FALSE; - else { - /* A SDP message preceeds it in non-completed READs */ - ok = ((msgs[0] == SCSI_DISCONNECT) || /* completed op */ - ((msgs[0] == SCSI_SAVE_DATA_POINTER) && /* incomplete */ - (msgs[1] == SCSI_DISCONNECT))); - } - if (!ok) - printf("[tgt %d bad msg (%d): %x]", - sci->active_target->target_id, len, *msgs); - - return TRUE; -} - -/* save all relevant data, free the BUS */ -boolean_t -sci_disconnected(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - sci_padded_regmap_t *regs = sci->regs; - - regs->sci_mode &= ~(SCI_MODE_MONBSY|SCI_MODE_DMA); - SCI_CLR_INTR(regs);/*retriggered by MONBSY cuz intr routine did CLR */ - SCI_ACK(regs,SCI_PHASE_DISC); - - LOG(0x16,"disconnected"); - - sci_disconnect(sci,csr,bs); - - tgt = sci->active_target; - tgt->flags |= TGT_DISCONNECTED; - tgt->transient_state.handler = sci->error_handler; - /* the rest has been saved in sci_err_disconn() */ - - PRINT(("{D%d}", tgt->target_id)); - - sci_release_bus(sci); - - return FALSE; -} - -/* get reconnect message, restore BUS */ -boolean_t -sci_reconnect(sci, csr, bs) - register sci_softc_t sci; -{ - register target_info_t *tgt; - sci_padded_regmap_t *regs; - register int id; - int msg; - - LOG(0x17,"reconnect"); - - if (sci->wd.nactive == 0) { - LOG(2,"SPURIOUS"); - return FALSE; - } - - regs = sci->regs; - - regs->sci_mode &= ~SCI_MODE_PAR_CHK; - id = regs->sci_data;/*parity!*/ - regs->sci_mode |= SCI_MODE_PAR_CHK; - - /* xxx check our id is in there */ - - id &= ~(1 << sci->sc->initiator_id); - { - register int i; - for (i = 0; i < 8; i++) - if (id & (1 << i)) break; -if (i == 8) {printf("{P%x}", id);return;} - id = i; - } - regs->sci_icmd = SCI_ICMD_BSY; - while (regs->sci_bus_csr & SCI_BUS_SEL) - ; - regs->sci_icmd = 0; - delay_1p2_us(); - while ( ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) && - ((regs->sci_bus_csr & SCI_BUS_BSY) == 0) && - ((regs->sci_bus_csr & SCI_BUS_BSY) == 0)) - ; - - regs->sci_mode |= SCI_MODE_MONBSY; - - /* Now should wait for correct phase: REQ signals it */ - while ( ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0) && - ((regs->sci_bus_csr & SCI_BUS_REQ) == 0)) - ; - - /* - * See if this reconnection collided with a selection attempt - */ - if (sci->state & SCI_STATE_BUSY) - sci->state |= SCI_STATE_COLLISION; - - sci->state |= SCI_STATE_BUSY; - - /* Get identify msg */ - bs = regs->sci_bus_csr; -if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) gimmeabreak(); - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - msg = 0; - sci_data_in(regs, SCSI_PHASE_MSG_IN, 1, &msg); - regs->sci_mode = SCI_MODE_PAR_CHK|SCI_MODE_DMA|SCI_MODE_MONBSY; - regs->sci_sel_enb = 0; - - if (msg != SCSI_IDENTIFY) - printf("{I%x %x}", id, msg); - - tgt = sci->sc->target[id]; - if (id > 7 || tgt == 0) panic("sci_reconnect"); - - PRINT(("{R%d}", id)); - if (sci->state & SCI_STATE_COLLISION) - PRINT(("[B %d-%d]", sci->active_target->target_id, id)); - - LOG(0x80+id,0); - - sci->active_target = tgt; - tgt->flags &= ~TGT_DISCONNECTED; - - sci->script = tgt->transient_state.script; - sci->error_handler = tgt->transient_state.handler; - sci->in_count = 0; - sci->out_count = 0; - - /* Should get a phase mismatch when tgt changes phase */ - - return TRUE; -} - - - -/* do the synch negotiation */ -boolean_t -sci_dosynch( sci, csr, bs) - register sci_softc_t sci; -{ - /* - * Phase is MSG_OUT here, cmd has not been xferred - */ - int len; - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - unsigned char off, icmd; - register unsigned char *p; - - regs->sci_mode |= SCI_MODE_MONBSY; - - LOG(0x11,"dosync"); - - /* ATN still asserted */ - SCI_ACK(regs,SCSI_PHASE_MSG_OUT); - - tgt = sci->active_target; - - tgt->flags |= TGT_DID_SYNCH; /* only one chance */ - tgt->flags &= ~TGT_TRY_SYNCH; - - p = (unsigned char *)tgt->cmd_ptr + tgt->transient_state.cmd_count + - tgt->transient_state.dma_offset; - p[0] = SCSI_IDENTIFY; - p[1] = SCSI_EXTENDED_MESSAGE; - p[2] = 3; - p[3] = SCSI_SYNC_XFER_REQUEST; - /* We cannot run synchronous */ -#define sci_to_scsi_period(x) 0xff -#define scsi_period_to_sci(x) (x) - off = 0; - p[4] = sci_to_scsi_period(sci_min_period); - p[5] = off; - - /* xfer all but last byte with ATN set */ - sci_data_out(regs, SCSI_PHASE_MSG_OUT, - sizeof(scsi_synch_xfer_req_t), p); - icmd = regs->sci_icmd & ~(SCI_ICMD_DIFF|SCI_ICMD_TEST); - icmd &= ~SCI_ICMD_ATN; - regs->sci_icmd = icmd; - sci_data_out(regs, SCSI_PHASE_MSG_OUT, 1, - &p[sizeof(scsi_synch_xfer_req_t)]); - - /* wait for phase change */ - while (regs->sci_csr & SCI_CSR_PHASE_MATCH) - ; - bs = regs->sci_bus_csr; - - /* The standard sez there nothing else the target can do but.. */ - if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) - panic("sci_dosync");/* XXX put offline */ - -msgin: - /* ack */ - SCI_ACK(regs,SCSI_PHASE_MSG_IN); - - /* get answer */ - len = sizeof(scsi_synch_xfer_req_t); - len = sci_data_in(regs, SCSI_PHASE_MSG_IN, len, p); - - /* do not cancel the phase mismatch interrupt ! */ - - /* look at the answer and see if we like it */ - if (len || (p[0] != SCSI_EXTENDED_MESSAGE)) { - /* did not like it at all */ - printf(" did not like SYNCH xfer "); - } else { - /* will NOT do synch */ - printf(" but we cannot do SYNCH xfer "); - tgt->sync_period = scsi_period_to_sci(p[3]); - tgt->sync_offset = p[4]; - /* sanity */ - if (tgt->sync_offset != 0) - printf(" ?OFFSET %x? ", tgt->sync_offset); - } - - /* wait for phase change */ - while (regs->sci_csr & SCI_CSR_PHASE_MATCH) - ; - bs = regs->sci_bus_csr; - - /* phase should be command now */ - /* continue with simple command script */ - sci->error_handler = sci_err_generic; - sci->script = sci_script_cmd; - - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_CMD ) - return TRUE; - -/* sci->script++;*/ - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_STATUS ) - return TRUE; /* intr is pending */ - - sci->script++; - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_MSG_IN ) - return TRUE; - - if ((bs & SCI_BUS_BSY) == 0) /* uhu? disconnected */ - return sci_end_transaction(sci, regs->sci_csr, regs->sci_bus_csr); - - panic("sci_dosynch"); - return FALSE; -} - -/* - * The bus was reset - */ -sci_bus_reset(sci) - register sci_softc_t sci; -{ - register target_info_t *tgt; - register sci_padded_regmap_t *regs = sci->regs; - int i; - - LOG(0x21,"bus_reset"); - - /* - * Clear bus descriptor - */ - sci->script = 0; - sci->error_handler = 0; - sci->active_target = 0; - sci->next_target = 0; - sci->state = 0; - queue_init(&sci->waiting_targets); - sci->wd.nactive = 0; - sci_reset(sci, TRUE); - - printf("sci%d: (%d) bus reset ", sci->sc->masterno, ++sci->wd.reset_count); - delay(scsi_delay_after_reset); /* some targets take long to reset */ - - if (sci->sc == 0) /* sanity */ - return; - - scsi_bus_was_reset(sci->sc); -} - -/* - * Error handlers - */ - -/* - * Generic, default handler - */ -boolean_t -sci_err_generic(sci, csr, bs) - register sci_softc_t sci; -{ - register int cond = sci->script->condition; - - LOG(0x10,"err_generic"); - - if (SCI_CUR_PHASE(bs) == SCSI_PHASE_STATUS) - return sci_err_to_status(sci, csr, bs); - gimmeabreak(); - return FALSE; -} - -/* - * Handle generic errors that are reported as - * an unexpected change to STATUS phase - */ -sci_err_to_status(sci, csr, bs) - register sci_softc_t sci; -{ - script_t scp = sci->script; - - LOG(0x20,"err_tostatus"); - while (SCSI_PHASE(scp->condition) != SCSI_PHASE_STATUS) - scp++; - sci->script = scp; -#if 0 - /* - * Normally, we would already be able to say the command - * is in error, e.g. the tape had a filemark or something. - * But in case we do disconnected mode WRITEs, it is quite - * common that the following happens: - * dma_out -> disconnect -> reconnect - * and our script might expect at this point that the dma - * had to be restarted (it didn't know it was completed - * because the tape record is shorter than we asked for). - * And in any event.. it is both correct and cleaner to - * declare error iff the STATUS byte says so. - */ - sci->done = SCSI_RET_NEED_SENSE; -#endif - return TRUE; -} - -/* - * Watch for a disconnection - */ -boolean_t -sci_err_disconn(sci, csr, bs) - register sci_softc_t sci; -{ - register sci_padded_regmap_t *regs; - register sci_dmaregs_t dmar = sci->dmar; - register target_info_t *tgt; - int count; - - LOG(0x18,"err_disconn"); - - if (SCI_CUR_PHASE(bs) != SCSI_PHASE_MSG_IN) - return sci_err_generic(sci, csr, bs); - - regs = sci->regs; - - tgt = sci->active_target; - - switch (SCSI_PHASE(sci->script->condition)) { - case SCSI_PHASE_DATAO: - LOG(0x1b,"+DATAO"); - -if (sci_delay & 1) delay(1000); - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/* make sure we steal not */ - - if (sci->out_count) { - register int xferred, offset; - - SCI_TC_GET(dmar,xferred); -if (scsi_debug) -printf("{O %x %x}", xferred, sci->out_count); - /* 5380 prefetches */ - xferred = sci->out_count - xferred - 1; -/* assert(xferred > 0);*/ - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - sci_copyout( tgt, offset, xferred); - - } - tgt->transient_state.script = sci_script_data_out; - break; - - case SCSI_PHASE_DATAI: - LOG(0x19,"+DATAI"); - - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - if (sci->in_count) { - register int offset, xferred; -/* unsigned char extrab = regs->sci_idata;*/ - - SCI_TC_GET(dmar,xferred); - /* ++EXTRA_BYTE */ -if (scsi_debug) -printf("{A %x %x %x}", xferred, sci->in_count, sci->extra_byte); - xferred = sci->in_count - xferred - sci->extra_byte; - /* ++EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; - assert(tgt->transient_state.in_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, 0, 0/*extrab*/); - } - tgt->transient_state.script = sci_script_data_in; - break; - - case SCSI_PHASE_STATUS: - /* will have to restart dma */ - SCI_TC_GET(dmar,count); - if (sci->state & SCI_STATE_DMA_IN) { - register int offset, xferred; -/* unsigned char extrab = regs->sci_idata;*/ - - LOG(0x1a,"+STATUS+R"); - - - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_WRITE;/* make sure we steal not */ - - /* ++EXTRA_BYTE */ -if (scsi_debug) -printf("{A %x %x %x}", count, sci->in_count, sci->extra_byte); - xferred = sci->in_count - count - sci->extra_byte; - /* ++EXTRA_BYTE */ - assert(xferred > 0); - tgt->transient_state.in_count -= xferred; -/* assert(tgt->transient_state.in_count > 0);*/ - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - /* copy what we got */ - sci_copyin( tgt, offset, xferred, 0, 0/*/extrab*/); - - tgt->transient_state.script = sci_script_data_in; - if (tgt->transient_state.in_count == 0) - tgt->transient_state.script++; - - } else { - - LOG(0x1d,"+STATUS+W"); - -if (sci_delay & 1) delay(1000); - /* Stop dma */ - regs->sci_icmd = 0; - regs->sci_mode &= ~(SCI_MODE_DMA|SCI_MODE_DMA_IE); - dmar->sci_dma_dir = SCI_DMA_DIR_READ;/* make sure we steal not */ - -if (scsi_debug) -printf("{O %x %x}", count, sci->out_count); - if ((count == 0) && (tgt->transient_state.out_count == sci->out_count)) { - /* all done */ - tgt->transient_state.script = &sci_script_data_out[1]; - tgt->transient_state.out_count = 0; - } else { - register int xferred, offset; - - /* how much we xferred */ - xferred = sci->out_count - count - 1;/*prefetch*/ - - tgt->transient_state.out_count -= xferred; - assert(tgt->transient_state.out_count > 0); - offset = tgt->transient_state.dma_offset; - tgt->transient_state.dma_offset += xferred; - if (tgt->transient_state.dma_offset >= PER_TGT_BUFF_SIZE) - tgt->transient_state.dma_offset = 0; - - sci_copyout( tgt, offset, xferred); - - tgt->transient_state.script = sci_script_data_out; - } - sci->out_count = 0; - } - break; - default: - gimmeabreak(); - } - sci->extra_byte = 0; - -/* SCI_ACK(regs,SCSI_PHASE_MSG_IN); later */ - (void) sci_msg_in(sci,csr,bs); - - regs->sci_sel_enb = (1 << sci->sc->initiator_id); - - sci->script = sci_script_disconnect; - - return FALSE; -} - -/* - * Watchdog - * - */ -sci_reset_scsibus(sci) - register sci_softc_t sci; -{ - register target_info_t *tgt = sci->active_target; - if (tgt) { - int cnt; - SCI_TC_GET(sci->dmar,cnt); - log( LOG_KERN, - "Target %d was active, cmd x%x in x%x out x%x Sin x%x Sou x%x dmalen x%x\n", - tgt->target_id, tgt->cur_cmd, - tgt->transient_state.in_count, tgt->transient_state.out_count, - sci->in_count, sci->out_count, cnt); - } - sci->regs->sci_icmd = SCI_ICMD_RST; - delay(25); -} - -/* - * Copy routines - */ -/*static*/ -sci_copyin(tgt, offset, len, isaobb, obb) - register target_info_t *tgt; - unsigned char obb; -{ - register char *from, *to; - register int count; - - count = tgt->transient_state.copy_count; - - from = tgt->cmd_ptr + offset; - to = tgt->ior->io_data + count; - tgt->transient_state.copy_count = count + len; - - bcopy( from, to, len); - /* check for last, poor little odd byte */ - if (isaobb) { - to += len; - to[-1] = obb; - } -} - -/*static*/ -sci_copyout( tgt, offset, len) - register target_info_t *tgt; -{ - register char *from, *to; - register int count, olen; - unsigned char c; - char *p; - - count = tgt->ior->io_count - tgt->transient_state.copy_count; - if (count > 0) { - - len = u_min(count, len); - offset += tgt->transient_state.cmd_count; - - count = tgt->transient_state.copy_count; - tgt->transient_state.copy_count = count + len; - - from = tgt->ior->io_data + count; - to = tgt->cmd_ptr + offset; - - bcopy(from, to, len); - - } -} - -#endif /*NSCI > 0*/ - -- cgit v1.2.3