📄 scsi_1185.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: $Hdr: scsi_1185.c,v 4.300 91/06/09 06:22:20 root Rel41 $ SONY * * @(#)scsi_1185.c 8.1 (Berkeley) 6/11/93 *//* * Copyright (c) 1989- by SONY Corporation. *//* * scsi_1185.c * * CXD1185Q * SCSI bus low level common routines * for one cpu machine *//* * MODIFY HISTORY: * * DMAC_WAIT --- DMAC_0266 wo tukau-baai, DMAC mata-wa SCSI-chip ni * tuzukete access suru-baai, * kanarazu wait wo ireru-beshi ! * */#include <sys/types.h>#include <machine/pte.h>#include <machine/cpu.h>#include <sys/param.h>#include <sys/systm.h>#include <sys/map.h>#include <sys/buf.h>#include <vm/vm.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/conf.h>#include <sys/dkstat.h>#include <sys/kernel.h>#include <news3400/hbdev/hbvar.h>#include <news3400/hbdev/screg_1185.h>#include <news3400/hbdev/scsic.h>#ifdef news3400# include <news3400/hbdev/dmac_0448.h># ifndef NDMACMAP# define NDMACMAP 144# endif#endif#include <news3400/iodev/scsireg.h>#ifdef mips#define VOLATILE volatile#else#define VOLATILE#endif#define ABORT_SYNCTR_MES_FROM_TARGET#define SCSI_1185AQ#define RESET_RECOVER#define DMAC_MAP_INIT /* for nws-3700 parity error */#define APAD_ALWAYS_ON# define CHECK_LOOP_CNT 60# define RSL_LOOP_CNT 60#ifndef DMAC_MAP_INIT# define MAP_OVER_ACCESS /* for nws-3700 parity error */#endif#undef CHECK_MRQ#ifdef NOT_SUPPORT_SYNCTR# define MAX_OFFSET_BYTES 0#else# define MAX_OFFSET_BYTES MAX_OFFSET#endif#define NTARGET 8#define act_point spoint#define act_trcnt stcnt#define act_tag stag#define act_offset soffset#define splscsi splsc#if defined(mips) && defined(CPU_SINGLE)#define nops(x) { int i; for (i = 0; i < (x); i++) ; }#define vtophys(v) MACH_UNMAPPED_TO_PHYS(v)#define DMAC_WAIT0 ;#else#define DMAC_WAIT0 DMAC_WAIT#endifint perr_flag[NTARGET];#ifndef NOT_SUPPORT_SYNCTRVOLATILE char sync_tr[NTARGET];#endif#ifdef DMAC_MAP_INITint dmac_map_init = 0;#endif#ifdef SCSI_1185AQint scsi_1185AQ = 0;#endifstruct sc_chan_stat chan_stat[NTARGET]; /* SCSI channel status */int sel_stat[NTARGET]; /* target select status */#define SEL_WAIT 0#define SEL_START 1#define SEL_TIMEOUT 2#define SEL_ARBF 3#define SEL_SUCCESS 4#define SEL_RSLD 5#define SEL_RSL_WAIT 6/* * command flag status */#define CF_SET 1#define CF_SEND 2#define CF_ENOUGH 3#define CF_EXEC 4#define SEL_TIMEOUT_VALUE 0x7aVOLATILE int int_stat1;VOLATILE int int_stat2;VOLATILE int min_flag;VOLATILE char mout_flag[NTARGET];#define MOUT_IDENTIFY 1#define MOUT_SYNC_TR 2VOLATILE int last_cmd;VOLATILE char min_cnt[NTARGET];VOLATILE u_char *min_point[NTARGET];VOLATILE int pad_cnt[NTARGET];VOLATILE static u_char *act_cmd_pointer;static VOLATILE struct sc_chan_stat *wbq_actf = 0; /* forword active pointer */static VOLATILE struct sc_chan_stat *wbq_actl = 0; /* last active pointer */static char ScsiSoftError[] = "SCSI soft error";static int pad_start;#if defined(mips) && defined(CPU_SINGLE)#define dma_reset(x) { \ int s = splscsi(); \ dmac_gsel = (x); dmac_cctl = DM_RST; dmac_cctl = 0; \ splx(s); \}#endifWAIT_STATR_BITCLR(bitmask) register int bitmask;{ register int iloop; register VOLATILE int dummy; iloop = 0; do { dummy = sc_statr; DMAC_WAIT0; if (iloop++ > CHECK_LOOP_CNT) return (-1); } while (dummy & bitmask); return (0);}WAIT_STATR_BITSET(bitmask) register int bitmask;{ register int iloop; register VOLATILE int dummy; iloop = 0; do { dummy = sc_statr; DMAC_WAIT0; if (iloop++ > CHECK_LOOP_CNT) return (-1); } while ((dummy & bitmask) == 0); return (0);}SET_CMD(CMD) register int CMD;{ (void) WAIT_STATR_BITCLR(R0_CIP); last_cmd = (CMD); sc_comr = (CMD); DMAC_WAIT0;}SET_CNT(COUNT) register int COUNT;{ sc_tclow = (COUNT) & 0xff; DMAC_WAIT0; sc_tcmid = ((COUNT) >> 8) & 0xff; DMAC_WAIT0; sc_tchi = ((COUNT) >> 16) & 0xff; DMAC_WAIT0;}GET_CNT(){ register VOLATILE int COUNT; COUNT = sc_tclow; DMAC_WAIT0; COUNT += (sc_tcmid << 8) & 0xff00; DMAC_WAIT0; COUNT += (sc_tchi << 16) & 0xff0000; DMAC_WAIT0; return (COUNT);}GET_INTR(DATA1, DATA2) register VOLATILE int *DATA1; register VOLATILE int *DATA2;{ register VOLATILE int dummy; (void) WAIT_STATR_BITCLR(R0_CIP); while (sc_statr & R0_MIRQ) { DMAC_WAIT0; *DATA1 |= sc_intrq1; DMAC_WAIT0; *DATA2 |= sc_intrq2; DMAC_WAIT0; }}sc_send(chan, ie, sc) register int chan; register int ie; register struct scsi *sc;{ register VOLATILE struct sc_chan_stat *cs; register struct scsi_stat *ss; register int i; cs = &chan_stat[chan]; ss = &scsi_stat; if (sc == NULL || cs->sc != NULL) { printf("SCSI%d:sc_send() NULL sc or NOT NULL cs->sc\n", chan); printf("ie=0x%x sc=0x%x cs->sc=0x%x\n", ie, sc, cs->sc); if (sc) { printf("cdb="); for (i = 0; i < 6; i++) printf("0x%x ", sc->sc_cdb.un_reserved[i]); printf("\n"); } panic(ScsiSoftError); /*NOTREACHED*/ } if ((sc->sc_cdb.un_reserved[0] == SCOP_RESET) && (sc->sc_cdb.un_reserved[1] == SCOP_RESET)) { /* * SCSI bus reset command procedure * (vender unique by Sony Corp.) */#ifdef SCSI_1185AQ if (sc_idenr & 0x08) { scsi_1185AQ = 1; }#endif cs->sc = sc; scsi_hardreset(); sc->sc_istatus = INST_EP; cs->sc = NULL; return; } if (sc->sc_map && (sc->sc_map->mp_pages > 0)) { /* * use map table */ sc->sc_coffset = sc->sc_map->mp_offset & PGOFSET; if (sc->sc_map->mp_pages > NSCMAP) { printf("SCSI%d: map table overflow\n", chan); sc->sc_istatus = INST_EP|INST_LB|INST_PRE; return; } } else { /* * no use map table */ sc->sc_coffset = (u_int)sc->sc_cpoint & PGOFSET; } sc->sc_ctag = 0; cs->sc = sc; cs->comflg = OFF; cs->intr_flg = ie; cs->chan_num = chan; perr_flag[chan] = 0; mout_flag[chan] = 0; min_cnt[chan] = 0; sel_stat[chan] = SEL_WAIT; append_wb(cs); sc_start();}/* * SCSI start up routine */sc_start(){ register VOLATILE struct sc_chan_stat *cs; register struct scsi_stat *ss; register int s; register VOLATILE int chan; register VOLATILE int dummy; ss = &scsi_stat; s = splclock(); chan = get_wb_chan(); if ((chan < 0) || (ss->ipc >= 0)) goto sc_start_exit; if (sel_stat[chan] != SEL_WAIT) { /* * already started */ goto sc_start_exit; } sel_stat[chan] = SEL_START; (void) splscsi(); cs = &chan_stat[chan]; dummy = sc_cmonr; DMAC_WAIT0; if (dummy & (R4_MBSY|R4_MSEL)) { sel_stat[chan] = SEL_WAIT; goto sc_start_exit; } /* * send SELECT with ATN command */ ss->dma_stat = OFF; pad_start = 0; dummy = sc_statr; DMAC_WAIT0; if (dummy & R0_CIP) { sel_stat[chan] = SEL_WAIT; goto sc_start_exit; } sc_idenr = (chan << SC_TG_SHIFT) | SC_OWNID; DMAC_WAIT0;#ifdef SCSI_1185AQ if (scsi_1185AQ) sc_intok1 = Ra_STO|Ra_ARBF; else sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;#else sc_intok1 = Ra_STO|Ra_RSL|Ra_ARBF;#endif DMAC_WAIT0; /* * BUGFIX for signal reflection on BSY * !Rb_DCNT */ sc_intok2 = Rb_FNC|Rb_SRST|Rb_PHC|Rb_SPE; DMAC_WAIT0; dummy = sc_cmonr; DMAC_WAIT0; if (dummy & (R4_MBSY|R4_MSEL)) { sel_stat[chan] = SEL_WAIT; goto sc_start_exit; } SET_CMD(SCMD_SEL_ATN);sc_start_exit: splx(s);}/* * SCSI interrupt service routine */scintr(){ register struct scsi_stat *ss; register int iloop; register VOLATILE int chan; register VOLATILE int dummy; int s_int1, s_int2;scintr_loop:#if defined(CHECK_MRQ) && defined(news3400) while (dmac_gstat & CH_MRQ(CH_SCSI)) DMAC_WAIT;#endif for (iloop = 0; iloop < 100; iloop++) { dummy = sc_statr; DMAC_WAIT; if ((dummy & R0_CIP) == 0) break; } /* * get SCSI interrupt request */ while (sc_statr & R0_MIRQ) { DMAC_WAIT0; s_int1 = sc_intrq1; DMAC_WAIT0; s_int2 = sc_intrq2; DMAC_WAIT0; int_stat1 |= s_int1; int_stat2 |= s_int2; } if (int_stat2 & R3_SRST) { /* * RST signal is drived */ int_stat2 &= ~R3_SRST; scsi_softreset(); goto scintr_exit; } ss = &scsi_stat; if ((ss->ipc < 0) && (ss->wrc <= 0) && (ss->wbc <= 0)) { int_stat1 = 0; int_stat2 = 0; goto scintr_exit; } chan = get_wb_chan(); if ((chan >= 0) && (sel_stat[chan] == SEL_START) && (last_cmd == SCMD_SEL_ATN)) { /* * Check the result of SELECTION command */ if (int_stat1 & R2_RSL) { /* * RESELECTION occur */ if (ss->wrc > 0) { sel_stat[chan] = SEL_RSLD; } else { /* * Ghost RESELECTION ??? */ int_stat1 &= ~R2_RSL; } } if (int_stat1 & R2_ARBF) { /* * ARBITRATION fault */ int_stat1 &= ~R2_ARBF; sel_stat[chan] = SEL_ARBF; } if (int_stat1 & R2_STO) { /* * SELECTION timeout */ int_stat1 &= ~R2_STO; if ((int_stat2&(R3_PHC|R3_RMSG)) != (R3_PHC|R3_RMSG)) { ss->ipc = chan; ss->ip = &chan_stat[chan]; sel_stat[chan] = SEL_TIMEOUT; chan_stat[chan].sc->sc_istatus = INST_EP|INST_TO; release_wb(); } } /* * SELECTION command done */ switch (sel_stat[chan]) { case SEL_START: if ((int_stat2 & R3_FNC) == 0) break; /* * SELECTION success */ sc_intok2 = Rb_FNC|Rb_DCNT|Rb_SRST|Rb_PHC|Rb_SPE; ss->ipc = chan; ss->ip = &chan_stat[chan]; ss->ip->sc->sc_istatus |= INST_IP; ss->dma_stat = OFF; pad_start = 0; sel_stat[chan] = SEL_SUCCESS; release_wb();#ifndef NOT_SUPPORT_SYNCTR sc_syncr = sync_tr[chan]; DMAC_WAIT0;#endif DMAC_WAIT0; break; case SEL_TIMEOUT: /* * SELECTION time out */ sc_discon(); goto scintr_exit; /* case SEL_RSLD: */ /* case SEL_ARBF: */ default: /* * SELECTION failed */ sel_stat[chan] = SEL_WAIT; break; } if ((int_stat1 & R2_RSL) == 0) int_stat2 &= ~R3_FNC; } if (ss->ip != NULL) { /* * check In Process channel's request */ if (ss->dma_stat != OFF) { /* * adjust pointer & counter */ adjust_transfer(ss->ip); } if (int_stat2 & R3_SPE) { register int VOLATILE statr; register int VOLATILE cmonr; statr = sc_statr; DMAC_WAIT0; cmonr = sc_cmonr; int_stat2 &= ~R3_SPE; perr_flag[ss->ip->chan_num] = 1; } } if (int_stat2 & R3_DCNT) { /* * Bus Free */ sc_discon(); int_stat2 &= ~R3_DCNT; } if ((ss->ipc >= 0) && (sel_stat[ss->ipc] == SEL_RSL_WAIT)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -