From e91272502526170cc4f62c2357a8b7d3ee9b2c27 Mon Sep 17 00:00:00 2001 From: non Date: Sat, 14 Jul 2001 00:38:51 +0000 Subject: Catch up with NetBSD/pc98. o Much cleanly separate NetBSD(XS) / FreeBSD(CAM) codes. o Improve tagged queing support (full QTAG). o Improve quirk support. o Improve parity error retry. o Impliment wide negotheation. o Cmd link support. o Add copyright of CAM part. o Change for CAM_NEW_TRAN_CODE. o Work around for buggy KME UJDCD450. o stg: add disconnet condition. o nsp: use suspend I/O. and more. I thank Honda-san. conf/options.pc98: add CT_USE_RELOCATE_OFFSET and CT_BUS_WEIGHT dev/{ct,ncv,nsp,stg}/*_{pccard,isa}.c: add splcam() before calling attach/detach functions. Tested by: bsd-nomads Obtained from: NetBSD/pc98 --- sys/dev/nsp/nsp.c | 1348 ++++++++++++++++++++++++++++++++++------------ sys/dev/nsp/nsp_pccard.c | 8 +- sys/dev/nsp/nspreg.h | 22 +- sys/dev/nsp/nspvar.h | 54 +- 4 files changed, 1056 insertions(+), 376 deletions(-) (limited to 'sys/dev/nsp') diff --git a/sys/dev/nsp/nsp.c b/sys/dev/nsp/nsp.c index b10bdb3..a78dd34 100644 --- a/sys/dev/nsp/nsp.c +++ b/sys/dev/nsp/nsp.c @@ -1,13 +1,20 @@ /* $FreeBSD$ */ -/* $NecBSD: nsp.c,v 1.21 1999/07/23 21:00:05 honda Exp $ */ +/* $NecBSD: nsp.c,v 1.21.12.6 2001/06/29 06:27:52 honda Exp $ */ /* $NetBSD$ */ #define NSP_DEBUG #define NSP_STATICS +#define NSP_IO_CONTROL_FLAGS \ + (NSP_READ_SUSPEND_IO | NSP_WRITE_SUSPEND_IO | \ + NSP_READ_FIFO_INTERRUPTS | NSP_WRITE_FIFO_INTERRUPTS | \ + NSP_USE_MEMIO | NSP_WAIT_FOR_SELECT) /* - * Copyright (c) 1998 + * Copyright (c) 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. + * + * Copyright (c) 1998, 1999, 2000, 2001 + * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -37,19 +44,16 @@ #include #include #include -#include #if defined(__FreeBSD__) && __FreeBSD_version > 500001 #include -#endif +#endif /* __ FreeBSD__ */ #include #include #include -#include #include -#include - #ifdef __NetBSD__ +#include #include #include @@ -68,8 +72,6 @@ #ifdef __FreeBSD__ #include -#define delay(time) DELAY(time) - #include #include #include @@ -105,76 +107,101 @@ struct nsp_softc *nspdata[NNSP]; #define NSP_NTARGETS 8 #define NSP_NLUNS 8 -#define NSP_SELTIMEOUT 200 +#define NSP_MAX_DATA_SIZE (64 * 1024) +#define NSP_SELTIMEOUT (200) +#define NSP_DELAY_MAX (2 * 1000 * 1000) +#define NSP_DELAY_INTERVAL (1) +#define NSP_TIMER_1MS (1000 / 51) /*************************************************** * DEBUG ***************************************************/ -#ifndef DDB -#define Debugger() panic("should call debugger here (nsp.c)") -#else /* ! DDB */ -#ifdef __FreeBSD__ -#define Debugger() Debugger("nsp") -#endif /* __FreeBSD__ */ -#endif - #ifdef NSP_DEBUG int nsp_debug; #endif /* NSP_DEBUG */ #ifdef NSP_STATICS struct nsp_statics { + int arbit_conflict_1; + int arbit_conflict_2; + int device_data_write; + int device_busy; int disconnect; int reselect; int data_phase_bypass; -} nsp_statics[NSP_NTARGETS]; +} nsp_statics; #endif /* NSP_STATICS */ /*************************************************** - * ISA DEVICE STRUCTURE + * IO control + ***************************************************/ +#define NSP_READ_SUSPEND_IO 0x0001 +#define NSP_WRITE_SUSPEND_IO 0x0002 +#define NSP_USE_MEMIO 0x0004 +#define NSP_READ_FIFO_INTERRUPTS 0x0010 +#define NSP_WRITE_FIFO_INTERRUPTS 0x0020 +#define NSP_WAIT_FOR_SELECT 0x0100 + +u_int nsp_io_control = NSP_IO_CONTROL_FLAGS; +int nsp_read_suspend_bytes = DEV_BSIZE; +int nsp_write_suspend_bytes = DEV_BSIZE; +int nsp_read_interrupt_bytes = 4096; +int nsp_write_interrupt_bytes = 4096; + +/*************************************************** + * DEVICE STRUCTURE ***************************************************/ extern struct cfdriver nsp_cd; /************************************************************** * DECLARE **************************************************************/ -#ifdef __NetBSD__ -extern int delaycount; -#endif - -/* static */ -static void nsp_pio_read __P((struct nsp_softc *, struct targ_info *)); -static void nsp_pio_write __P((struct nsp_softc *, struct targ_info *)); -static int nsp_xfer __P((struct nsp_softc *, u_int8_t *, int, int)); +#define NSP_FIFO_ON 1 +#define NSP_FIFO_OFF 0 +static void nsp_pio_read __P((struct nsp_softc *, int)); +static void nsp_pio_write __P((struct nsp_softc *, int)); +static int nsp_xfer __P((struct nsp_softc *, u_int8_t *, int, int, int)); static int nsp_msg __P((struct nsp_softc *, struct targ_info *, u_int)); static int nsp_reselected __P((struct nsp_softc *)); -static __inline int nsp_disconnected __P((struct nsp_softc *, struct targ_info *)); -static __inline void nsp_pdma_end __P((struct nsp_softc *, struct targ_info *)); +static int nsp_disconnected __P((struct nsp_softc *, struct targ_info *)); +static void nsp_pdma_end __P((struct nsp_softc *, struct targ_info *)); static void nsphw_init __P((struct nsp_softc *)); -static int nsp_nexus __P((struct nsp_softc *, struct targ_info *)); +static int nsp_target_nexus_establish __P((struct nsp_softc *)); +static int nsp_lun_nexus_establish __P((struct nsp_softc *)); +static int nsp_ccb_nexus_establish __P((struct nsp_softc *)); static int nsp_world_start __P((struct nsp_softc *, int)); static int nsphw_start_selection __P((struct nsp_softc *sc, struct slccb *)); static void nsphw_bus_reset __P((struct nsp_softc *)); static void nsphw_attention __P((struct nsp_softc *)); static u_int nsp_fifo_count __P((struct nsp_softc *)); +static u_int nsp_request_count __P((struct nsp_softc *)); static int nsp_negate_signal __P((struct nsp_softc *, u_int8_t, u_char *)); static int nsp_expect_signal __P((struct nsp_softc *, u_int8_t, u_int8_t)); -static __inline void nsp_start_timer __P((struct nsp_softc *, int)); -static int nsp_dataphase_bypass __P((struct nsp_softc *, struct targ_info *)); -static void nsp_setup_fifo __P((struct nsp_softc *, int)); -static int nsp_targ_init __P((struct nsp_softc *, struct targ_info *)); +static void nsp_start_timer __P((struct nsp_softc *, int)); +static void nsp_setup_fifo __P((struct nsp_softc *, int, int, int)); +static int nsp_targ_init __P((struct nsp_softc *, struct targ_info *, int)); +static void nsphw_selection_done_and_expect_msgout __P((struct nsp_softc *)); +static void nsp_data_padding __P((struct nsp_softc *, int, u_int)); +static int nsp_timeout __P((struct nsp_softc *)); +static int nsp_read_fifo __P((struct nsp_softc *, int)); +static int nsp_write_fifo __P((struct nsp_softc *, int)); +static int nsp_phase_match __P((struct nsp_softc *, u_int8_t, u_int8_t)); +static int nsp_wait_interrupt __P((struct nsp_softc *)); struct scsi_low_funcs nspfuncs = { SC_LOW_INIT_T nsp_world_start, SC_LOW_BUSRST_T nsphw_bus_reset, SC_LOW_TARG_INIT_T nsp_targ_init, + SC_LOW_LUN_INIT_T NULL, SC_LOW_SELECT_T nsphw_start_selection, - SC_LOW_NEXUS_T nsp_nexus, + SC_LOW_NEXUS_T nsp_lun_nexus_establish, + SC_LOW_NEXUS_T nsp_ccb_nexus_establish, SC_LOW_ATTEN_T nsphw_attention, SC_LOW_MSG_T nsp_msg, + SC_LOW_TIMEOUT_T nsp_timeout, SC_LOW_POLL_T nspintr, NULL, @@ -217,35 +244,27 @@ nsp_expect_signal(sc, curphase, mask) struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - int wc = (sc->sc_wc >> 2); + int wc; u_int8_t ph, isrc; - int rv = -1; - do + for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) { ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); - if (ph == 0xff) { - rv = -1; - break; - } + if (ph == (u_int8_t) -1) + return -1; + isrc = bus_space_read_1(bst, bsh, nsp_irqsr); - if (isrc & IRQSR_SCSI) { - rv = 0; - break; - } - if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase) { - rv = 1; - break; - } - } - while (wc -- > 0); + if (isrc & IRQSR_SCSI) + return 0; + + if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase) + return 1; - if (wc <= 0) { - printf("%s: nsp_expect_signal timeout\n", slp->sl_xname); - rv = -1; + SCSI_LOW_DELAY(NSP_DELAY_INTERVAL); } - return rv; + printf("%s: nsp_expect_signal timeout\n", slp->sl_xname); + return -1; } static void @@ -267,7 +286,7 @@ nsphw_init(sc) nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_iclkdiv); nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); - nsp_cr_write_1(bst, bsh, NSPR_PARITYR, 0); + nsp_cr_write_1(bst, bsh, NSPR_PARITYR, sc->sc_parr); nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS); @@ -286,10 +305,10 @@ nsphw_init(sc) nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, 0); /* enable interrupts and ack them */ - nsp_cr_write_1(bst, bsh, NSPR_SCIENR, SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST); + nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); - nsp_setup_fifo(sc, 0); + nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); } /**************************************************** @@ -305,6 +324,7 @@ nsphw_attention(sc) cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR)/* & ~SCBUSCR_ACK */; nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ATN); + SCSI_LOW_DELAY(10); } static void @@ -318,7 +338,7 @@ nsphw_bus_reset(sc) bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK); nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_RST); - delay(100 * 1000); /* 100ms */ + SCSI_LOW_DELAY(100 * 1000); /* 100ms */ nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0); for (i = 0; i < 5; i ++) (void) nsp_cr_read_1(bst, bsh, NSPR_IRQPHS); @@ -326,16 +346,26 @@ nsphw_bus_reset(sc) bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); } -static __inline void -nsp_start_timer(sc, time) +static void +nsphw_selection_done_and_expect_msgout(sc) struct nsp_softc *sc; - int time; { + struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - sc->sc_timer = time; - nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time); + /* clear ack counter */ + sc->sc_cnt = 0; + nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | + PTCLRR_REQ | PTCLRR_HOST); + + /* deassert sel and assert atten */ + sc->sc_seltout = 0; + nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc); + SCSI_LOW_DELAY(1); + nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, + sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN); + SCSI_LOW_ASSERT_ATN(slp); } static int @@ -348,58 +378,97 @@ nsphw_start_selection(sc, cb) bus_space_handle_t bsh = sc->sc_ioh; struct targ_info *ti = cb->ti; register u_int8_t arbs, ph; - int s, wc = sc->sc_wc; + int s, wc; + + wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; + sc->sc_dataout_timeout = 0; /* check bus free */ - if (slp->sl_disc > 0) + s = splhigh(); + ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); + if (ph != SCBUSMON_FREE) { - s = splhigh(); - ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); - if (ph != SCBUSMON_FREE) - { - splx(s); - return SCSI_LOW_START_FAIL; - } splx(s); +#ifdef NSP_STATICS + nsp_statics.arbit_conflict_1 ++; +#endif /* NSP_STATICS */ + return SCSI_LOW_START_FAIL; } /* start arbitration */ - SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_EXEC); + splx(s); + + SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); do { /* XXX: what a stupid chip! */ arbs = nsp_cr_read_1(bst, bsh, NSPR_ARBITS); - delay(1); + SCSI_LOW_DELAY(1); } while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0); if ((arbs & ARBITS_WIN) == 0) { nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); +#ifdef NSP_STATICS + nsp_statics.arbit_conflict_2 ++; +#endif /* NSP_STATICS */ return SCSI_LOW_START_FAIL; } /* assert select line */ SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); - scsi_low_arbit_win(slp, ti); - delay(3); + scsi_low_arbit_win(slp); + + s = splhigh(); + SCSI_LOW_DELAY(3); nsp_cr_write_1(bst, bsh, NSPR_DATA, sc->sc_idbit | (1 << ti->ti_id)); nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc); - delay(3); + SCSI_LOW_DELAY(3); nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL | SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc); nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); - delay(3); + SCSI_LOW_DELAY(3); nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc); + SCSI_LOW_DELAY(1); - /* check selection timeout */ - nsp_start_timer(sc, 1000 / 51); - sc->sc_seltout = 1; + if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0) + { +#define NSP_FIRST_SEL_WAIT 300 +#define NSP_SEL_CHECK_INTERVAL 10 + + /* wait for a selection response */ + for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL; + wc ++) + { + ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); + if ((ph & SCBUSMON_BSY) == 0) + { + SCSI_LOW_DELAY(NSP_SEL_CHECK_INTERVAL); + continue; + } + + SCSI_LOW_DELAY(1); + ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); + if ((ph & SCBUSMON_BSY) != 0) + { + nsphw_selection_done_and_expect_msgout(sc); + splx(s); + + SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); + return SCSI_LOW_START_OK; + } + } + } + splx(s); + /* check a selection timeout */ + nsp_start_timer(sc, NSP_TIMER_1MS); + sc->sc_seltout = 1; return SCSI_LOW_START_OK; } @@ -409,24 +478,24 @@ nsp_world_start(sc, fdone) int fdone; { struct scsi_low_softc *slp = &sc->sc_sclow; -#ifdef __FreeBSD__ - intrmask_t s; - s = splcam(); -#endif sc->sc_cnt = 0; sc->sc_seltout = 0; + if ((slp->sl_cfgflags & CFG_NOATTEN) == 0) sc->sc_busc = SCBUSCR_ATN; else sc->sc_busc = 0; + + if ((slp->sl_cfgflags & CFG_NOPARITY) == 0) + sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR; + else + sc->sc_parr = 0; + sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST); nsphw_init(sc); scsi_low_bus_reset(slp); -#ifdef __FreeBSD__ - splx(s); -#endif SOFT_INTR_REQUIRED(slp); return 0; @@ -460,10 +529,22 @@ nsp_msg(sc, ti, msg) struct targ_info *ti; u_int msg; { + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; struct ncp_synch_data *sdp; struct nsp_targ_info *nti = (void *) ti; u_int period, offset; - int i; + int i, error; + + if ((msg & SCSI_LOW_MSG_WIDE) != 0) + { + if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) + { + ti->ti_width = SCSI_LOW_BUS_WIDTH_8; + return EINVAL; + } + return 0; + } if ((msg & SCSI_LOW_MSG_SYNCH) == 0) return 0; @@ -491,29 +572,52 @@ nsp_msg(sc, ti, msg) ti->ti_maxsynch.offset = 0; nti->nti_reg_syncr = 0; nti->nti_reg_ackwidth = 0; - return EINVAL; + error = EINVAL; + } + else + { + nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) | + (offset & SYNCR_OFFM); + nti->nti_reg_ackwidth = sdp->ack_width; + error = 0; } - nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) | - (offset & SYNCR_OFFM); - nti->nti_reg_ackwidth = sdp->ack_width; - return 0; + nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); + nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); + return error; } static int -nsp_targ_init(sc, ti) +nsp_targ_init(sc, ti, action) struct nsp_softc *sc; struct targ_info *ti; + int action; { struct nsp_targ_info *nti = (void *) ti; - ti->ti_maxsynch.period = 200 / 4; - ti->ti_maxsynch.offset = 15; - nti->nti_reg_syncr = 0; - nti->nti_reg_ackwidth = 0; + if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) + { + ti->ti_width = SCSI_LOW_BUS_WIDTH_8; + ti->ti_maxsynch.period = 100 / 4; + ti->ti_maxsynch.offset = 15; + nti->nti_reg_syncr = 0; + nti->nti_reg_ackwidth = 0; + } return 0; } +static void +nsp_start_timer(sc, time) + struct nsp_softc *sc; + int time; +{ + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + + sc->sc_timer = time; + nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time); +} + /************************************************************** * General probe attach **************************************************************/ @@ -550,20 +654,13 @@ nspattachsubr(sc) printf("\n"); -#ifdef __FreeBSD__ - sc->sc_wc = 0x2000 * 2000; /* XXX need calibration */ -#else - sc->sc_wc = delaycount * 2000; /* 2 sec */ -#endif sc->sc_idbit = (1 << slp->sl_hostid); + slp->sl_flags |= HW_READ_PADDING; slp->sl_funcs = &nspfuncs; - if (sc->sc_memh != NULL) - sc->sc_xmode = NSP_MID_SMIT; - else - sc->sc_xmode = NSP_PIO; + sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ - (void) scsi_low_attach(slp, 2, NSP_NTARGETS, NSP_NLUNS, - sizeof(struct nsp_targ_info)); + (void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS, + sizeof(struct nsp_targ_info), 0); } /************************************************************** @@ -577,57 +674,110 @@ nsp_fifo_count(sc) bus_space_handle_t bsh = sc->sc_ioh; u_int count; - nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT); + nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT); count = bus_space_read_1(bst, bsh, nsp_datar); count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); return count; } -static void -nsp_setup_fifo(sc, on) +static u_int +nsp_request_count(sc) struct nsp_softc *sc; - int on; { - struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; + u_int count; + + nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT); + count = bus_space_read_1(bst, bsh, nsp_datar); + count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); + count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); + return count; +} + +static void +nsp_setup_fifo(sc, on, direction, datalen) + struct nsp_softc *sc; + int on; + int direction; + int datalen; +{ u_int8_t xfermode; - if (on != 0) - xfermode = XFERMR_XEN | XFERMR_FIFOEN; - else - xfermode = 0; + sc->sc_suspendio = 0; + if (on == NSP_FIFO_OFF) + { + xfermode = XFERMR_IO8; + goto out; + } + + /* check if suspend io OK ? */ + if (datalen > 0) + { + if (direction == SCSI_LOW_READ) + { + if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 && + (datalen % nsp_read_suspend_bytes) == 0) + sc->sc_suspendio = nsp_read_suspend_bytes; + } + else + { + if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 && + (datalen % nsp_write_suspend_bytes) == 0) + sc->sc_suspendio = nsp_write_suspend_bytes; + } + } - if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0) + /* determine a transfer type */ + if (datalen < DEV_BSIZE || (datalen & 3) != 0) { - sc->sc_mask = 0; - xfermode |= XFERMR_IO8; + if (sc->sc_memh != NULL && + (nsp_io_control & NSP_USE_MEMIO) != 0) + xfermode = XFERMR_XEN | XFERMR_MEM8; + else + xfermode = XFERMR_XEN | XFERMR_IO8; } else { - sc->sc_mask = 3; - if (sc->sc_xmode == NSP_MID_SMIT) - xfermode |= XFERMR_MEM32; + if (sc->sc_memh != NULL && + (nsp_io_control & NSP_USE_MEMIO) != 0) + xfermode = XFERMR_XEN | XFERMR_MEM32; else - xfermode |= XFERMR_IO32; + xfermode = XFERMR_XEN | XFERMR_IO32; + + if (sc->sc_suspendio > 0) + xfermode |= XFERMR_FIFOEN; } +out: sc->sc_xfermr = xfermode; - nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr); + nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_XFERMR, sc->sc_xfermr); } -static __inline void +static void nsp_pdma_end(sc, ti) struct nsp_softc *sc; struct targ_info *ti; { struct scsi_low_softc *slp = &sc->sc_sclow; - struct slccb *cb = ti->ti_nexus; + struct slccb *cb = slp->sl_Qnexus; u_int len = 0, cnt; + sc->sc_dataout_timeout = 0; slp->sl_flags &= ~HW_PDMASTART; - nsp_setup_fifo(sc, 0); + nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); + if ((sc->sc_icr & SCIENR_FIFO) != 0) + { + sc->sc_icr &= ~SCIENR_FIFO; + nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_SCIENR, sc->sc_icr); + } + + if (cb == NULL) + { + slp->sl_error |= PDMAERR; + return; + } if (ti->ti_phase == PH_DATA) { @@ -635,7 +785,8 @@ nsp_pdma_end(sc, ti) if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) { len = sc->sc_cnt - cnt; - if (slp->sl_scp.scp_datalen + len <= + if (sc->sc_cnt >= cnt && + slp->sl_scp.scp_datalen + len <= cb->ccb_scp.scp_datalen) { slp->sl_scp.scp_data -= len; @@ -651,14 +802,17 @@ nsp_pdma_end(sc, ti) } else if (slp->sl_scp.scp_direction == SCSI_LOW_READ) { - if (sc->sc_cnt != cnt) + if (sc->sc_cnt != cnt || + sc->sc_cnt > cb->ccb_scp.scp_datalen) { slp->sl_error |= PDMAERR; - printf("%s: data read count error %x != %x\n", - slp->sl_xname, sc->sc_cnt, cnt); + printf("%s: data read count error %x != %x (%x)\n", + slp->sl_xname, sc->sc_cnt, cnt, + cb->ccb_scp.scp_datalen); } } sc->sc_cnt = cnt; + scsi_low_data_finish(slp); } else { @@ -669,182 +823,448 @@ nsp_pdma_end(sc, ti) } #define RFIFO_CRIT 64 -#define WFIFO_CRIT 64 +#define WFIFO_CRIT 32 static void -nsp_pio_read(sc, ti) +nsp_data_padding(sc, direction, count) struct nsp_softc *sc; - struct targ_info *ti; + int direction; + u_int count; +{ + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + + if (count > NSP_MAX_DATA_SIZE) + count = NSP_MAX_DATA_SIZE; + + nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8); + if (direction == SCSI_LOW_READ) + { + while (count -- > 0) + (void) bus_space_read_1(bst, bsh, nsp_fifodr); + } + else + { + while (count -- > 0) + (void) bus_space_write_1(bst, bsh, nsp_fifodr, 0); + } + nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr); +} + +static int +nsp_read_fifo(sc, suspendio) + struct nsp_softc *sc; + int suspendio; { struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - int tout = sc->sc_wc; - u_int res, ocount, mask = sc->sc_mask; - u_int8_t stat, fstat; + u_int res; - slp->sl_flags |= HW_PDMASTART; - ocount = sc->sc_cnt; + res = nsp_fifo_count(sc); + if (res == sc->sc_cnt) + return 0; - while (slp->sl_scp.scp_datalen > 0 && tout -- > 0) +#ifdef NSP_DEBUG + if (res < sc->sc_cnt || res == (u_int) -1) { - stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); - stat &= SCBUSMON_PHMASK; - res = nsp_fifo_count(sc) - ocount; - if (res == 0) + printf("%s: strange fifo ack count 0x%x < 0x%x\n", + slp->sl_xname, res, sc->sc_cnt); + return 0; + } +#endif /* NSP_DEBUG */ + + res = res - sc->sc_cnt; + if (res > slp->sl_scp.scp_datalen) + { + if ((slp->sl_error & PDMAERR) == 0) { - if (stat == PHASE_DATAIN) - continue; - break; + printf("%s: data overrun 0x%x > 0x%x\n", + slp->sl_xname, res, slp->sl_scp.scp_datalen); } - fstat = bus_space_read_1(bst, bsh, nsp_fifosr); - if ((fstat & FIFOSR_FULLEMP) == 0 && stat == PHASE_DATAIN) - continue; + slp->sl_error |= PDMAERR; + slp->sl_scp.scp_datalen = 0; - if (res > slp->sl_scp.scp_datalen) - break; + if ((slp->sl_flags & HW_READ_PADDING) == 0) + { + printf("%s: read padding required\n", slp->sl_xname); + return 0; + } - if (res >= NSP_BUFFER_SIZE) - res = NSP_BUFFER_SIZE; - else - res &= ~mask; + nsp_data_padding(sc, SCSI_LOW_READ, res); + sc->sc_cnt += res; + return 1; /* padding start */ + } + + if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio) + res = suspendio; - if (sc->sc_xfermr & XFERMR_MEM32) + if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) + { + if ((sc->sc_xfermr & XFERMR_MEM32) != 0) { - bus_space_read_region_4(sc->sc_memt, - sc->sc_memh, - 0, - (u_int32_t *) slp->sl_scp.scp_data, - res >> 2); + res &= ~3; + bus_space_read_region_4(sc->sc_memt, sc->sc_memh, 0, + (u_int32_t *) slp->sl_scp.scp_data, res >> 2); } else { - if (mask != 0) - bus_space_read_multi_4(bst, bsh, nsp_fifodr, - (u_int32_t *) slp->sl_scp.scp_data, - res >> 2); - else - bus_space_read_multi_1(bst, bsh, nsp_fifodr, - (u_int8_t *) slp->sl_scp.scp_data, - res); + bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 0, + (u_int8_t *) slp->sl_scp.scp_data, res); + } + } + else + { + if ((sc->sc_xfermr & XFERMR_IO32) != 0) + { + res &= ~3; + bus_space_read_multi_4(bst, bsh, nsp_fifodr, + (u_int32_t *) slp->sl_scp.scp_data, res >> 2); + } + else + { + bus_space_read_multi_1(bst, bsh, nsp_fifodr, + (u_int8_t *) slp->sl_scp.scp_data, res); } + } - slp->sl_scp.scp_data += res; - slp->sl_scp.scp_datalen -= res; - ocount += res; + if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) + { + nsp_cr_write_1(bst, bsh, NSPR_PARITYR, + PARITYR_ENABLE | PARITYR_CLEAR); + scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1); } - sc->sc_cnt = ocount; - if (tout <= 0) - printf("%s pio read timeout\n", slp->sl_xname); + slp->sl_scp.scp_data += res; + slp->sl_scp.scp_datalen -= res; + sc->sc_cnt += res; + return 0; } -static void -nsp_pio_write(sc, ti) +static int +nsp_write_fifo(sc, suspendio) struct nsp_softc *sc; - struct targ_info *ti; + int suspendio; { struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - u_int res, ocount, mask = sc->sc_mask; - int tout = sc->sc_wc; + u_int res; register u_int8_t stat; - ocount = sc->sc_cnt; - slp->sl_flags |= HW_PDMASTART; - while (slp->sl_scp.scp_datalen > 0 && tout -- > 0) + if (suspendio > 0) { - stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); - stat &= SCBUSMON_PHMASK; - if (stat != PHASE_DATAOUT) - break; +#ifdef NSP_DEBUG + if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0) + { + printf("%s: strange write length 0x%x\n", + slp->sl_xname, slp->sl_scp.scp_datalen); + } +#endif /* NSP_DEBUG */ + res = slp->sl_scp.scp_datalen % suspendio; + if (res == 0) + { + res = suspendio; + } + } + else + { + res = WFIFO_CRIT; + } - res = ocount - nsp_fifo_count(sc); - if (res > 0) - continue; + if (res > slp->sl_scp.scp_datalen) + res = slp->sl_scp.scp_datalen; - res = (slp->sl_scp.scp_datalen > WFIFO_CRIT) ? WFIFO_CRIT : - slp->sl_scp.scp_datalen; + /* XXX: reconfirm! */ + stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; + if (stat != PHASE_DATAOUT) + return 0; - if (sc->sc_xfermr & XFERMR_MEM32) + if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) + { + if ((sc->sc_xfermr & XFERMR_MEM32) != 0) { - bus_space_write_region_4(sc->sc_memt, - sc->sc_memh, - 0, - (u_int32_t *) slp->sl_scp.scp_data, - res >> 2); + bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 0, + (u_int32_t *) slp->sl_scp.scp_data, res >> 2); } else { - if (mask != 0) - bus_space_write_multi_4(bst, bsh, nsp_fifodr, + bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 0, + (u_int8_t *) slp->sl_scp.scp_data, res); + } + } + else + { + if ((sc->sc_xfermr & XFERMR_IO32) != 0) + { + bus_space_write_multi_4(bst, bsh, nsp_fifodr, (u_int32_t *) slp->sl_scp.scp_data, res >> 2); - else - bus_space_write_multi_1(bst, bsh, nsp_fifodr, + } + else + { + bus_space_write_multi_1(bst, bsh, nsp_fifodr, (u_int8_t *) slp->sl_scp.scp_data, res); } - - slp->sl_scp.scp_datalen -= res; - slp->sl_scp.scp_data += res; - ocount += res; } - sc->sc_cnt = ocount; - if (tout <= 0) - printf("%s pio write timeout\n", slp->sl_xname); + slp->sl_scp.scp_datalen -= res; + slp->sl_scp.scp_data += res; + sc->sc_cnt += res; + return 0; } static int -nsp_negate_signal(sc, mask, s) +nsp_wait_interrupt(sc) struct nsp_softc *sc; - u_int8_t mask; - u_char *s; { - struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - int wc = (sc->sc_wc >> 2); - u_int8_t regv; + int tout; + register u_int8_t isrc; - do + for (tout = 0; tout < DEV_BSIZE / 10; tout ++) { - regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); - if (regv == 0xff) - break; + isrc = bus_space_read_1(bst, bsh, nsp_irqsr); + if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0) + { + if ((isrc & IRQSR_FIFO) != 0) + { + bus_space_write_1(bst, bsh, + nsp_irqcr, IRQCR_FIFOCL); + } + return 1; + } + SCSI_LOW_DELAY(1); } - while ((regv & mask) != 0 && (-- wc) > 0); - - if (wc <= 0) - printf("%s: %s singla off timeout \n", slp->sl_xname, s); - return 0; } -static int -nsp_xfer(sc, buf, len, phase) +static void +nsp_pio_read(sc, suspendio) struct nsp_softc *sc; - u_int8_t *buf; - int len; - int phase; + int suspendio; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + int tout, padding, datalen; + register u_int8_t stat, fstat; + + padding = 0; + tout = sc->sc_tmaxcnt; + slp->sl_flags |= HW_PDMASTART; + datalen = slp->sl_scp.scp_datalen; + +ReadLoop: + while (1) + { + stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); + if (stat == (u_int8_t) -1) + return; + + /* out of data phase */ + if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN) + { + nsp_read_fifo(sc, 0); + return; + } + + /* data phase */ + fstat = bus_space_read_1(bst, bsh, nsp_fifosr); + if ((fstat & FIFOSR_FULLEMP) != 0) + { + if ((sc->sc_icr & SCIENR_FIFO) != 0) + { + bus_space_write_1(bst, bsh, nsp_irqcr, + IRQCR_FIFOCL); + } + + if (suspendio > 0) + { + padding |= nsp_read_fifo(sc, suspendio); + } + else + { + padding |= nsp_read_fifo(sc, 0); + } + + if ((sc->sc_icr & SCIENR_FIFO) != 0) + break; + } + else + { + if (padding == 0 && slp->sl_scp.scp_datalen <= 0) + return; + + if ((sc->sc_icr & SCIENR_FIFO) != 0) + break; + + SCSI_LOW_DELAY(1); + } + + if ((-- tout) <= 0) + { + printf("%s: nsp_pio_read: timeout\n", slp->sl_xname); + return; + } + } + + + if (slp->sl_scp.scp_datalen > 0 && + slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes) + { + if (nsp_wait_interrupt(sc) != 0) + goto ReadLoop; + } +} + +static void +nsp_pio_write(sc, suspendio) + struct nsp_softc *sc; + int suspendio; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + u_int rcount, acount; + int tout, datalen; + register u_int8_t stat, fstat; + + tout = sc->sc_tmaxcnt; + slp->sl_flags |= HW_PDMASTART; + datalen = slp->sl_scp.scp_datalen; + +WriteLoop: + while (1) + { + stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; + if (stat != PHASE_DATAOUT) + return; + + if (slp->sl_scp.scp_datalen <= 0) + { + if (sc->sc_dataout_timeout == 0) + sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; + return; + } + + fstat = bus_space_read_1(bst, bsh, nsp_fifosr); + if ((fstat & FIFOSR_FULLEMP) != 0) + { + if ((sc->sc_icr & SCIENR_FIFO) != 0) + { + bus_space_write_1(bst, bsh, nsp_irqcr, + IRQCR_FIFOCL); + } + + if (suspendio > 0) + { + /* XXX:IMPORTANT: + * To avoid timeout of pcmcia bus + * (not scsi bus!), we should check + * the scsi device sends us request + * signals, which means the scsi device + * is ready to recieve data without + * heavy delays. + */ + acount = nsp_fifo_count(sc); + rcount = nsp_request_count(sc); + if (rcount <= acount) + { + nsp_write_fifo(sc, 0); +#ifdef NSP_STATICS + nsp_statics.device_busy ++; +#endif /* NSP_STATICS */ + } + else + { + nsp_write_fifo(sc, suspendio); +#ifdef NSP_STATICS + nsp_statics.device_data_write ++; +#endif /* NSP_STATICS */ + } + } + else + { + nsp_write_fifo(sc, 0); + } + + if ((sc->sc_icr & SCIENR_FIFO) != 0) + break; + } + else + { + if ((sc->sc_icr & SCIENR_FIFO) != 0) + break; + + SCSI_LOW_DELAY(1); + } + + if ((-- tout) <= 0) + { + printf("%s: nsp_pio_write: timeout\n", slp->sl_xname); + return; + } + } + + if (slp->sl_scp.scp_datalen > 0 && + slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes) + { + if (nsp_wait_interrupt(sc) != 0) + goto WriteLoop; + } +} + +static int +nsp_negate_signal(sc, mask, s) + struct nsp_softc *sc; + u_int8_t mask; + u_char *s; { struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; - int ptr, rv, atn; + int wc; + u_int8_t regv; + + for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) + { + regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); + if (regv == (u_int8_t) -1) + return -1; + if ((regv & mask) == 0) + return 1; + SCSI_LOW_DELAY(NSP_DELAY_INTERVAL); + } + + printf("%s: %s nsp_negate_signal timeout\n", slp->sl_xname, s); + return -1; +} + +static int +nsp_xfer(sc, buf, len, phase, clear_atn) + struct nsp_softc *sc; + u_int8_t *buf; + int len; + int phase; + int clear_atn; +{ + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + int ptr, rv; - atn = (scsi_low_is_msgout_continue(slp->sl_nexus) != 0); for (ptr = 0; len > 0; len --, ptr ++) { rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ); if (rv <= 0) goto out; - if (len == 1 && atn == 0) + if (len == 1 && clear_atn != 0) { nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_ADIR | SCBUSCR_ACKEN); + SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow); } if (phase & SCBUSMON_IO) @@ -862,41 +1282,6 @@ out: return len; } -static int -nsp_dataphase_bypass(sc, ti) - struct nsp_softc *sc; - struct targ_info *ti; -{ - struct scsi_low_softc *slp = &sc->sc_sclow; - struct slccb *cb = ti->ti_nexus; - u_int cnt; - - if (slp->sl_scp.scp_direction != SCSI_LOW_READ || - (slp->sl_scp.scp_datalen % DEV_BSIZE) == 0) - return 0; - - cnt = nsp_fifo_count(sc); - if (sc->sc_cnt == cnt) - return 0; - if (cnt >= DEV_BSIZE) - return EINVAL; - - if (cb == NULL) - return 0; - - /* - * XXX: NSP_QUIRK - * Data phase skip only occures in case of SCSI_LOW_READ. - */ - SCSI_LOW_SETUP_PHASE(ti, PH_DATA); - nsp_pio_read(sc, ti); - nsp_pdma_end(sc, ti); -#ifdef NSP_STATICS - nsp_statics[ti->ti_id].data_phase_bypass ++; -#endif /* NSP_STATICS */ - return 0; -} - /************************************************************** * disconnect & reselect (HW low) **************************************************************/ @@ -919,28 +1304,39 @@ nsp_reselected(sc) nsp_negate_signal(sc, SCBUSMON_SEL, "reselect"); - cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & ~(SCBUSCR_BSY | SCBUSCR_ATN); + cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); + cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN); + nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); + cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN; nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); - nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ADIR | SCBUSCR_ACKEN); #ifdef NSP_STATICS - nsp_statics[sid].reselect ++; + nsp_statics.reselect ++; #endif /* NSP_STATCIS */ return EJUSTRETURN; } -static __inline int +static int nsp_disconnected(sc, ti) struct nsp_softc *sc; struct targ_info *ti; { struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t bst = sc->sc_iot; + bus_space_handle_t bsh = sc->sc_ioh; + nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | + PTCLRR_REQ | PTCLRR_HOST); + if ((sc->sc_icr & SCIENR_FIFO) != 0) + { + sc->sc_icr &= ~SCIENR_FIFO; + nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); + } + sc->sc_cnt = 0; + sc->sc_dataout_timeout = 0; #ifdef NSP_STATICS - if (slp->sl_msgphase == MSGPH_DISC) - nsp_statics[ti->ti_id].disconnect ++; + nsp_statics.disconnect ++; #endif /* NSP_STATICS */ - scsi_low_disconnected(slp, ti); return 1; } @@ -948,10 +1344,10 @@ nsp_disconnected(sc, ti) /************************************************************** * SEQUENCER **************************************************************/ -static void nspmsg __P((struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t)); +static void nsp_error __P((struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t)); static void -nspmsg(sc, s, isrc, ph, irqphs) +nsp_error(sc, s, isrc, ph, irqphs) struct nsp_softc *sc; u_char *s; u_int8_t isrc, ph, irqphs; @@ -964,25 +1360,86 @@ nspmsg(sc, s, isrc, ph, irqphs) } static int -nsp_nexus(sc, ti) +nsp_target_nexus_establish(sc) struct nsp_softc *sc; - struct targ_info *ti; { + struct scsi_low_softc *slp = &sc->sc_sclow; bus_space_tag_t bst = sc->sc_iot; bus_space_handle_t bsh = sc->sc_ioh; + struct targ_info *ti = slp->sl_Tnexus; struct nsp_targ_info *nti = (void *) ti; /* setup synch transfer registers */ nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); + /* setup pdma fifo (minimum) */ + nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0); + return 0; +} + +static int +nsp_lun_nexus_establish(sc) + struct nsp_softc *sc; +{ + + return 0; +} + +static int +nsp_ccb_nexus_establish(sc) + struct nsp_softc *sc; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + struct slccb *cb = slp->sl_Qnexus; + + sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; + /* setup pdma fifo */ - nsp_setup_fifo(sc, 1); + nsp_setup_fifo(sc, NSP_FIFO_ON, + slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen); + + if (slp->sl_scp.scp_direction == SCSI_LOW_READ) + { + if (sc->sc_suspendio > 0 && + (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0) + { + sc->sc_icr |= SCIENR_FIFO; + nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, + NSPR_SCIENR, sc->sc_icr); + } + } + else + { + if (sc->sc_suspendio > 0 && + (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0) + { + sc->sc_icr |= SCIENR_FIFO; + nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, + NSPR_SCIENR, sc->sc_icr); + } + } + return 0; +} + +static int +nsp_phase_match(sc, phase, stat) + struct nsp_softc *sc; + u_int8_t phase; + u_int8_t stat; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + + if ((stat & SCBUSMON_PHMASK) != phase) + { + printf("%s: phase mismatch 0x%x != 0x%x\n", + slp->sl_xname, (u_int) phase, (u_int) stat); + return EINVAL; + } + + if ((stat & SCBUSMON_REQ) == 0) + return EINVAL; - /* clear ack counter */ - sc->sc_cnt = 0; - nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | - PTCLRR_REQ | PTCLRR_HOST); return 0; } @@ -997,6 +1454,7 @@ nspintr(arg) struct targ_info *ti; struct physio_proc *pp; struct buf *bp; + u_int derror, flags; int len, rv; u_int8_t isrc, ph, irqphs, cr, regv; @@ -1008,7 +1466,7 @@ nspintr(arg) bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_IRQDIS); isrc = bus_space_read_1(bst, bsh, nsp_irqsr); - if (isrc == 0xff || (isrc & IRQSR_MASK) == 0) + if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0) { bus_space_write_1(bst, bsh, nsp_irqcr, 0); return 0; @@ -1036,13 +1494,26 @@ nspintr(arg) sc->sc_timer = 0; } - if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0) + /* check a timer interrupt */ + regv = 0; + if ((isrc & IRQSR_TIMER) != 0) { - bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL); - return 1; + if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0) + { + bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL); + return 1; + } + regv |= IRQCR_TIMERCL; } - bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL | IRQCR_FIFOCL); + /* check a fifo interrupt */ + if ((isrc & IRQSR_FIFO) != 0) + { + regv |= IRQCR_FIFOCL; + } + + /* OK. enable all interrupts */ + bus_space_write_1(bst, bsh, nsp_irqcr, regv); /******************************************* * debug section @@ -1050,10 +1521,12 @@ nspintr(arg) #ifdef NSP_DEBUG if (nsp_debug) { - nspmsg(sc, "current status", isrc, ph, irqphs); + nsp_error(sc, "current status", isrc, ph, irqphs); scsi_low_print(slp, NULL); +#ifdef DDB if (nsp_debug > 1) - Debugger(); + SCSI_LOW_DEBUGGER("nsp"); +#endif /* DDB */ } #endif /* NSP_DEBUG */ @@ -1083,10 +1556,10 @@ nspintr(arg) /******************************************* * nexus check *******************************************/ - if ((ti = slp->sl_nexus) == NULL) + if ((ti = slp->sl_Tnexus) == NULL) { /* unknown scsi phase changes */ - nspmsg(sc, "unknown scsi phase changes", isrc, ph, irqphs); + nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs); return 0; } @@ -1105,63 +1578,93 @@ nspintr(arg) return nsp_disconnected(sc, ti); } sc->sc_seltout ++; - nsp_start_timer(sc, 1000 / 51); + nsp_start_timer(sc, NSP_TIMER_1MS); return 1; } - /* attention assert */ - sc->sc_seltout = 0; SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); - nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc); - delay(1); - nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, - sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN); - - SCSI_LOW_TARGET_ASSERT_ATN(ti); - scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); + nsphw_selection_done_and_expect_msgout(sc); return 1; + case PH_SELECTED: + if ((isrc & IRQSR_SCSI) == 0) + return 1; + + nsp_target_nexus_establish(sc); + break; + case PH_RESEL: + if ((isrc & IRQSR_SCSI) == 0) + return 1; + + nsp_target_nexus_establish(sc); if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN) { + printf("%s: unexpected phase after reselect\n", + slp->sl_xname); + slp->sl_error |= FATALIO; scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); return 1; } - /* fall */ + break; + + case PH_DATA: + if ((isrc & IRQSR_SCSI) != 0) + break; + if ((isrc & IRQSR_FIFO) != 0) + { + if (NSP_IS_PHASE_DATA(ph) == 0) + return 1; + irqphs = (ph & IRQPHS_PHMASK); + break; + } + return 1; default: - if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) == 0) + if ((isrc & IRQSR_SCSI) == 0) return 1; break; } /******************************************* - * scsi seq + * data phase control *******************************************/ if (slp->sl_flags & HW_PDMASTART) - nsp_pdma_end(sc, ti); + { + if ((isrc & IRQSR_SCSI) != 0 && + NSP_IS_IRQPHS_DATA(irqphs) == 0) + { + if (slp->sl_scp.scp_direction == SCSI_LOW_READ) + nsp_pio_read(sc, 0); + nsp_pdma_end(sc, ti); + } + } - /* normal disconnect */ + /******************************************* + * scsi seq + *******************************************/ if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0) return nsp_disconnected(sc, ti); /* check unexpected bus free state */ if (ph == 0) { - nspmsg(sc, "unexpected bus free", isrc, ph, irqphs); + nsp_error(sc, "unexpected bus free", isrc, ph, irqphs); return nsp_disconnected(sc, ti); } /* check normal scsi phase */ - switch (ph & SCBUSMON_PHMASK) + switch (irqphs & IRQPHS_PHMASK) { - case PHASE_CMD: - if ((ph & SCBUSMON_REQ) == 0) + case IRQPHS_CMD: + if (nsp_phase_match(sc, PHASE_CMD, ph) != 0) return 1; SCSI_LOW_SETUP_PHASE(ti, PH_CMD); if (scsi_low_cmd(slp, ti) != 0) - break; + { + scsi_low_attention(slp); + } nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR); for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++) @@ -1171,39 +1674,67 @@ nspintr(arg) nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC); break; - case PHASE_DATAOUT: + case IRQPHS_DATAOUT: SCSI_LOW_SETUP_PHASE(ti, PH_DATA); if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) - break; + { + scsi_low_attention(slp); + } pp = physio_proc_enter(bp); - nsp_pio_write(sc, ti); + nsp_pio_write(sc, sc->sc_suspendio); physio_proc_leave(pp); break; - case PHASE_DATAIN: + case IRQPHS_DATAIN: SCSI_LOW_SETUP_PHASE(ti, PH_DATA); if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) - break; + { + scsi_low_attention(slp); + } pp = physio_proc_enter(bp); - nsp_pio_read(sc, ti); + nsp_pio_read(sc, sc->sc_suspendio); physio_proc_leave(pp); break; - case PHASE_STATUS: - nsp_dataphase_bypass(sc, ti); - if ((ph & SCBUSMON_REQ) == 0) + case IRQPHS_STATUS: + if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0) return 1; SCSI_LOW_SETUP_PHASE(ti, PH_STAT); - ti->ti_status = nsp_cr_read_1(bst, bsh, NSPR_DATAACK); + regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); + if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) + { + nsp_cr_write_1(bst, bsh, NSPR_PARITYR, + PARITYR_ENABLE | PARITYR_CLEAR); + derror = SCSI_LOW_DATA_PE; + } + else + derror = 0; + + /* assert ACK */ + cr = SCBUSCR_ACK | nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); + nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); + + if (scsi_low_statusin(slp, ti, derror | regv) != 0) + { + scsi_low_attention(slp); + } + + /* check REQ nagated */ + nsp_negate_signal(sc, SCBUSMON_REQ, "statin"); + + /* deassert ACK */ + cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); + nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); break; - case PHASE_MSGOUT: - if ((ph & SCBUSMON_REQ) == 0) - goto timerout; + case IRQPHS_MSGOUT: + if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0) + return 1; +#ifdef NSP_MSGOUT_SERIALIZE /* * XXX: NSP QUIRK * NSP invoke interrupts only in the case of scsi phase changes, @@ -1213,13 +1744,20 @@ nspintr(arg) rv = len = 16; do { SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); + flags = (ti->ti_ophase != ti->ti_phase) ? + SCSI_LOW_MSGOUT_INIT : 0; + len = scsi_low_msgout(slp, ti, flags); - len = scsi_low_msgout(slp, ti); - if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT)) + if (len > 1 && slp->sl_atten == 0) { - scsi_low_assert_msg(slp, ti, - SCSI_LOW_MSG_RESET, 0); - nspmsg(sc, "MSGOUT: xfer short", + scsi_low_attention(slp); + } + + if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, + slp->sl_clear_atten) != 0) + { + slp->sl_error |= FATALIO; + nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs); } @@ -1227,14 +1765,31 @@ nspintr(arg) rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ); } while (rv > 0 && len -- > 0); - break; - case PHASE_MSGIN: - nsp_dataphase_bypass(sc, ti); - if ((ph & SCBUSMON_REQ) == 0) - goto timerout; +#else /* !NSP_MSGOUT_SERIALIZE */ + SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); + flags = SCSI_LOW_MSGOUT_UNIFY; + if (ti->ti_ophase != ti->ti_phase) + flags |= SCSI_LOW_MSGOUT_INIT; + len = scsi_low_msgout(slp, ti, flags); - SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); + if (len > 1 && slp->sl_atten == 0) + { + scsi_low_attention(slp); + } + + if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, + slp->sl_clear_atten) != 0) + { + nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs); + } + +#endif /* !NSP_MSGOUT_SERIALIZE */ + break; + + case IRQPHS_MSGIN: + if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0) + return 1; /* * XXX: NSP QUIRK @@ -1244,20 +1799,39 @@ nspintr(arg) */ rv = len = 16; do { + SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); + /* read a data */ regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); + if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) + { + nsp_cr_write_1(bst, bsh, + NSPR_PARITYR, + PARITYR_ENABLE | PARITYR_CLEAR); + derror = SCSI_LOW_DATA_PE; + } + else + { + derror = 0; + } /* assert ack */ - cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); - cr |= SCBUSCR_ACK; + cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) | SCBUSCR_ACK; nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); - nsp_negate_signal(sc, SCBUSMON_REQ, "msgin"); - scsi_low_msgin(slp, ti, regv); + if (scsi_low_msgin(slp, ti, regv | derror) == 0) + { + if (scsi_low_is_msgout_continue(ti, 0) != 0) + { + scsi_low_attention(slp); + } + } + + /* check REQ nagated */ + nsp_negate_signal(sc, SCBUSMON_REQ, "msgin"); /* deassert ack */ - cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); - cr &= ~SCBUSCR_ACK; + cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); /* catch a next signal */ @@ -1266,15 +1840,85 @@ nspintr(arg) while (rv > 0 && len -- > 0); break; - case PHASE_SEL: default: - nspmsg(sc, "unknown scsi phase", isrc, ph, irqphs); + slp->sl_error |= FATALIO; + nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs); break; } return 1; +#if 0 timerout: - nsp_start_timer(sc, 1000 / 102); + nsp_start_timer(sc, NSP_TIMER_1MS); + return 0; +#endif +} + +static int +nsp_timeout(sc) + struct nsp_softc *sc; +{ + struct scsi_low_softc *slp = &sc->sc_sclow; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int tout; + u_int8_t ph, regv; + + if (slp->sl_Tnexus == NULL) + return 0; + + ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); + switch (ph & SCBUSMON_PHMASK) + { + case PHASE_DATAOUT: + if (sc->sc_dataout_timeout == 0) + break; + + /* check a fifo empty */ + regv = bus_space_read_1(iot, ioh, nsp_fifosr); + if ((regv & FIFOSR_FULLEMP) == 0) + break; + bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); + + /* check still requested */ + ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); + if ((ph & SCBUSMON_REQ) == 0) + break; + /* check timeout */ + if ((-- sc->sc_dataout_timeout) > 0) + break; + + slp->sl_error |= PDMAERR; + if ((slp->sl_flags & HW_WRITE_PADDING) == 0) + { + printf("%s: write padding required\n", slp->sl_xname); + break; + } + + tout = NSP_DELAY_MAX; + while (tout -- > 0) + { + ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); + if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT) + break; + regv = bus_space_read_1(iot, ioh, nsp_fifosr); + if ((regv & FIFOSR_FULLEMP) == 0) + { + SCSI_LOW_DELAY(1); + continue; + } + + bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); + nsp_data_padding(sc, SCSI_LOW_WRITE, 32); + } + ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); + if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT) + sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; + break; + + default: + break; + } return 0; } diff --git a/sys/dev/nsp/nsp_pccard.c b/sys/dev/nsp/nsp_pccard.c index 3bc2428..a0b4556 100644 --- a/sys/dev/nsp/nsp_pccard.c +++ b/sys/dev/nsp/nsp_pccard.c @@ -318,10 +318,13 @@ static void nsp_card_unload(DEVPORT_PDEVICE devi) { struct nsp_softc *sc = DEVPORT_PDEVGET_SOFTC(devi); + intrmask_t s; printf("%s: unload\n",sc->sc_sclow.sl_xname); + s = splcam(); scsi_low_deactivate((struct scsi_low_softc *)sc); scsi_low_dettach(&sc->sc_sclow); + splx(s); } static int @@ -352,6 +355,7 @@ nspattach(DEVPORT_PDEVICE devi) struct scsi_low_softc *slp; u_int32_t flags = DEVPORT_PDEVFLAGS(devi); u_int iobase = DEVPORT_PDEVIOBASE(devi); + intrmask_t s; char dvname[16]; strcpy(dvname,"nsp"); @@ -406,9 +410,9 @@ nspattach(DEVPORT_PDEVICE devi) slp->sl_hostid = NSP_HOSTID; slp->sl_cfgflags = flags; + s = splcam(); nspattachsubr(sc); - - sc->sc_ih = nspintr; + splx(s); return(NSP_IOSIZE); } diff --git a/sys/dev/nsp/nspreg.h b/sys/dev/nsp/nspreg.h index 9912a13..3bfcd96 100644 --- a/sys/dev/nsp/nspreg.h +++ b/sys/dev/nsp/nspreg.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $NecBSD: nspreg.h,v 1.4 1999/04/15 01:35:55 kmatsuda Exp $ */ +/* $NecBSD: nspreg.h,v 1.4.14.3 2001/06/29 06:27:53 honda Exp $ */ /* $NetBSD$ */ /* @@ -92,6 +92,7 @@ #define IRQPHS_RSEL 0x20 #define IRQPHS_FIFO 0x40 #define IRQPHS_RST 0x80 +#define IRQPHS_PHMASK (IRQPHS_LCD | IRQPHS_LMSG | IRQPHS_LIO) #define NSPR_TIMERCNT 0x17 @@ -125,6 +126,9 @@ #define ARBITS_RESEL 0x08 #define NSPR_PARITYR 0x1B /* (W/R) */ +#define PARITYR_ENABLE 0x01 +#define PARITYR_CLEAR 0x02 +#define PARITYR_PE 0x02 #define NSPR_CMDCR 0x1C /* (W) */ #define CMDCR_PTCLR 0x01 @@ -139,6 +143,9 @@ #define PTCLRR_REQ 0x04 #define PTCLRR_HOST 0x08 #define PTCLRR_RSS 0x30 +#define PTCLRR_RSS_ACK 0x00 +#define PTCLRR_RSS_REQ 0x10 +#define PTCLRR_RSS_HOST 0x20 #define NSPR_XFERCR 0x1E /* (R) */ @@ -185,6 +192,12 @@ #define SCBUSMON_PHMASK \ (SCBUSMON_SEL | SCBUSMON_CD | SCBUSMON_MSG | SCBUSMON_IO) +/* Data phase */ +#define NSP_IS_PHASE_DATA(ph) \ + ((((ph) & SCBUSMON_PHMASK) & ~SCBUSMON_IO) == 0) +#define NSP_IS_IRQPHS_DATA(ph) \ + ((((ph) & IRQPHS_PHMASK) & ~SCBUSMON_IO) == 0) + /* SCSI phase */ #define PHASE_CMD (SCBUSMON_CMD & SCBUSMON_PHMASK) #define PHASE_DATAIN (SCBUSMON_DATAIN & SCBUSMON_PHMASK) @@ -194,6 +207,13 @@ #define PHASE_MSGOUT (SCBUSMON_MSGOUT & SCBUSMON_PHMASK) #define PHASE_SEL (SCBUSMON_SEL | SCBUSMON_IO) +#define IRQPHS_CMD (IRQPHS_LCD) +#define IRQPHS_DATAIN (IRQPHS_LIO) +#define IRQPHS_DATAOUT (0) +#define IRQPHS_STATUS (IRQPHS_LCD | IRQPHS_LIO) +#define IRQPHS_MSGIN (IRQPHS_LCD | IRQPHS_LMSG | IRQPHS_LIO) +#define IRQPHS_MSGOUT (IRQPHS_LCD | IRQPHS_LMSG) + /* Size */ #define NSP_MEMSIZE NBPG #define NSP_IOSIZE 16 diff --git a/sys/dev/nsp/nspvar.h b/sys/dev/nsp/nspvar.h index 41912d3..e7a348101c 100644 --- a/sys/dev/nsp/nspvar.h +++ b/sys/dev/nsp/nspvar.h @@ -1,11 +1,14 @@ /* $FreeBSD$ */ -/* $NecBSD: nspvar.h,v 1.7 1999/04/15 01:35:55 kmatsuda Exp $ */ +/* $NecBSD: nspvar.h,v 1.7.14.5 2001/06/29 06:27:54 honda Exp $ */ /* $NetBSD$ */ /* * [NetBSD for NEC PC-98 series] - * Copyright (c) 1998 + * Copyright (c) 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. + * + * Copyright (c) 1998, 1999, 2000, 2001 + * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -40,48 +43,57 @@ struct nsp_softc { struct scsi_low_softc sc_sclow; /* generic data */ +#ifdef __NetBSD__ bus_space_tag_t sc_iot; bus_space_handle_t sc_ioh; bus_space_tag_t sc_memt; bus_space_handle_t sc_memh; void *sc_ih; - int sc_wc; +#endif /* __NetBSD__ */ +#ifdef __FreeBSD__ + bus_space_tag_t sc_iot; + bus_space_handle_t sc_ioh; + bus_space_tag_t sc_memt; + bus_space_handle_t sc_memh; + +#if __FreeBSD_version >= 400001 + int port_rid; + int irq_rid; + int mem_rid; + struct resource *port_res; + struct resource *irq_res; + struct resource *mem_res; + + void *nsp_intrhand; +#endif /* __FreeBSD_version */ +#endif /* __FreeBSD__ */ + + int sc_tmaxcnt; /* timeout count */ int sc_seltout; /* selection timeout counter */ int sc_timer; /* timer start */ - int sc_xmode; -#define NSP_HIGH_SMIT 2 /* write address data mode */ -#define NSP_MID_SMIT 1 /* mem access */ -#define NSP_PIO 0 /* io access */ + int sc_suspendio; /* SMIT: data suspendio bytes */ + u_int8_t sc_xfermr; /* SMIT: fifo control reg */ + int sc_dataout_timeout; /* data out timeout counter */ u_int sc_idbit; /* host id bit pattern */ - u_int sc_mask; /* bus width mask */ u_int sc_cnt; /* fifo R/W count (host) */ + u_int8_t sc_iclkdiv; /* scsi chip clock divisor */ u_int8_t sc_clkdiv; /* asic chip clock divisor */ - u_int8_t sc_xfermr; /* fifo control reg */ u_int8_t sc_icr; /* interrupt control reg */ u_int8_t sc_busc; /* busc registers */ - u_long sc_ringp; /* data buffer ring pointer */ -#if defined (__FreeBSD__) && __FreeBSD_version >= 400001 - int port_rid; - int irq_rid; - int mem_rid; - struct resource *port_res; - struct resource *irq_res; - struct resource *mem_res; - void *nsp_intrhand; -#endif + u_int8_t sc_parr; /* parity control register */ }; /***************************************************************** - * Target information + * Lun information *****************************************************************/ struct nsp_targ_info { - struct targ_info nti_ti; /* generic target info */ + struct targ_info nti_ti; /* generic lun info */ u_int8_t nti_reg_syncr; /* sync registers per devices */ u_int8_t nti_reg_ackwidth; /* ackwidth per devices */ -- cgit v1.1