179697Snon/* $NecBSD: nsp.c,v 1.21.12.6 2001/06/29 06:27:52 honda Exp $ */ 267468Snon/* $NetBSD$ */ 367468Snon 467468Snon#define NSP_DEBUG 567468Snon#define NSP_STATICS 679697Snon#define NSP_IO_CONTROL_FLAGS \ 779697Snon (NSP_READ_SUSPEND_IO | NSP_WRITE_SUSPEND_IO | \ 879697Snon NSP_READ_FIFO_INTERRUPTS | NSP_WRITE_FIFO_INTERRUPTS | \ 979697Snon NSP_USE_MEMIO | NSP_WAIT_FOR_SELECT) 1067468Snon 11139749Simp/*- 1279697Snon * Copyright (c) 1998, 1999, 2000, 2001 1367468Snon * NetBSD/pc98 porting staff. All rights reserved. 1479697Snon * 1579697Snon * Copyright (c) 1998, 1999, 2000, 2001 1679697Snon * Naofumi HONDA. All rights reserved. 1767468Snon * 1867468Snon * Redistribution and use in source and binary forms, with or without 1967468Snon * modification, are permitted provided that the following conditions 2067468Snon * are met: 2167468Snon * 1. Redistributions of source code must retain the above copyright 2267468Snon * notice, this list of conditions and the following disclaimer. 2367468Snon * 2. Redistributions in binary form must reproduce the above copyright 2467468Snon * notice, this list of conditions and the following disclaimer in the 2567468Snon * documentation and/or other materials provided with the distribution. 2667468Snon * 3. The name of the author may not be used to endorse or promote products 2767468Snon * derived from this software without specific prior written permission. 2867468Snon * 2967468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 3067468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3167468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 3267468Snon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 3367468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3467468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3567468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3667468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3767468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3867468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3967468Snon * POSSIBILITY OF SUCH DAMAGE. 4067468Snon */ 41119418Sobrien 42119418Sobrien#include <sys/cdefs.h> 43119418Sobrien__FBSDID("$FreeBSD$"); 4467468Snon 4567468Snon#include <sys/param.h> 4667468Snon#include <sys/systm.h> 4767468Snon#include <sys/kernel.h> 4867468Snon#include <sys/bio.h> 4967468Snon#include <sys/buf.h> 5067468Snon#include <sys/queue.h> 5167468Snon#include <sys/malloc.h> 5267468Snon#include <sys/errno.h> 53274760Sjhb#include <sys/rman.h> 5467468Snon 5567468Snon#include <machine/cpu.h> 5667468Snon#include <machine/bus.h> 5767468Snon 5867468Snon#include <cam/scsi/scsi_low.h> 5967468Snon#include <dev/nsp/nspreg.h> 6067468Snon#include <dev/nsp/nspvar.h> 6167468Snon 6267468Snon/*************************************************** 6367468Snon * USER SETTINGS 6467468Snon ***************************************************/ 6567468Snon/* DEVICE CONFIGURATION FLAGS (MINOR) 6667468Snon * 67250460Seadler * 0x01 DISCONNECT OFF 6867468Snon * 0x02 PARITY LINE OFF 6967468Snon * 0x04 IDENTIFY MSG OFF ( = single lun) 7067468Snon * 0x08 SYNC TRANSFER OFF 7167468Snon */ 7267468Snon 7367468Snon/*************************************************** 7467468Snon * PARAMS 7567468Snon ***************************************************/ 7667468Snon#define NSP_NTARGETS 8 7767468Snon#define NSP_NLUNS 8 7867468Snon 7979697Snon#define NSP_MAX_DATA_SIZE (64 * 1024) 8079697Snon#define NSP_SELTIMEOUT (200) 8179697Snon#define NSP_DELAY_MAX (2 * 1000 * 1000) 8279697Snon#define NSP_DELAY_INTERVAL (1) 8379697Snon#define NSP_TIMER_1MS (1000 / 51) 8467468Snon 8567468Snon/*************************************************** 8667468Snon * DEBUG 8767468Snon ***************************************************/ 8867468Snon#ifdef NSP_DEBUG 8967468Snonint nsp_debug; 9067468Snon#endif /* NSP_DEBUG */ 9167468Snon 9267468Snon#ifdef NSP_STATICS 9367468Snonstruct nsp_statics { 9479697Snon int arbit_conflict_1; 9579697Snon int arbit_conflict_2; 9679697Snon int device_data_write; 9779697Snon int device_busy; 9867468Snon int disconnect; 9967468Snon int reselect; 10067468Snon int data_phase_bypass; 10179697Snon} nsp_statics; 10267468Snon#endif /* NSP_STATICS */ 10367468Snon 10467468Snon/*************************************************** 10579697Snon * IO control 10667468Snon ***************************************************/ 10779697Snon#define NSP_READ_SUSPEND_IO 0x0001 10879697Snon#define NSP_WRITE_SUSPEND_IO 0x0002 10979697Snon#define NSP_USE_MEMIO 0x0004 11079697Snon#define NSP_READ_FIFO_INTERRUPTS 0x0010 11179697Snon#define NSP_WRITE_FIFO_INTERRUPTS 0x0020 11279697Snon#define NSP_WAIT_FOR_SELECT 0x0100 11379697Snon 11479697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS; 11579697Snonint nsp_read_suspend_bytes = DEV_BSIZE; 11679697Snonint nsp_write_suspend_bytes = DEV_BSIZE; 11779697Snonint nsp_read_interrupt_bytes = 4096; 11879697Snonint nsp_write_interrupt_bytes = 4096; 11979697Snon 12079697Snon/*************************************************** 12179697Snon * DEVICE STRUCTURE 12279697Snon ***************************************************/ 12367468Snonextern struct cfdriver nsp_cd; 12467468Snon 12567468Snon/************************************************************** 12667468Snon * DECLARE 12767468Snon **************************************************************/ 12879697Snon#define NSP_FIFO_ON 1 12979697Snon#define NSP_FIFO_OFF 0 13092739Salfredstatic void nsp_pio_read(struct nsp_softc *, int); 13192739Salfredstatic void nsp_pio_write(struct nsp_softc *, int); 13292739Salfredstatic int nsp_xfer(struct nsp_softc *, u_int8_t *, int, int, int); 13392739Salfredstatic int nsp_msg(struct nsp_softc *, struct targ_info *, u_int); 13492739Salfredstatic int nsp_reselected(struct nsp_softc *); 13592739Salfredstatic int nsp_disconnected(struct nsp_softc *, struct targ_info *); 13692739Salfredstatic void nsp_pdma_end(struct nsp_softc *, struct targ_info *); 13792739Salfredstatic void nsphw_init(struct nsp_softc *); 13892739Salfredstatic int nsp_target_nexus_establish(struct nsp_softc *); 13992739Salfredstatic int nsp_lun_nexus_establish(struct nsp_softc *); 14092739Salfredstatic int nsp_ccb_nexus_establish(struct nsp_softc *); 14192739Salfredstatic int nsp_world_start(struct nsp_softc *, int); 14292739Salfredstatic int nsphw_start_selection(struct nsp_softc *sc, struct slccb *); 14392739Salfredstatic void nsphw_bus_reset(struct nsp_softc *); 14492739Salfredstatic void nsphw_attention(struct nsp_softc *); 14592739Salfredstatic u_int nsp_fifo_count(struct nsp_softc *); 14692739Salfredstatic u_int nsp_request_count(struct nsp_softc *); 14792739Salfredstatic int nsp_negate_signal(struct nsp_softc *, u_int8_t, u_char *); 14892739Salfredstatic int nsp_expect_signal(struct nsp_softc *, u_int8_t, u_int8_t); 14992739Salfredstatic void nsp_start_timer(struct nsp_softc *, int); 15092739Salfredstatic void nsp_setup_fifo(struct nsp_softc *, int, int, int); 15192739Salfredstatic int nsp_targ_init(struct nsp_softc *, struct targ_info *, int); 15292739Salfredstatic void nsphw_selection_done_and_expect_msgout(struct nsp_softc *); 15392739Salfredstatic void nsp_data_padding(struct nsp_softc *, int, u_int); 15492739Salfredstatic int nsp_timeout(struct nsp_softc *); 15592739Salfredstatic int nsp_read_fifo(struct nsp_softc *, int); 15692739Salfredstatic int nsp_write_fifo(struct nsp_softc *, int); 15792739Salfredstatic int nsp_phase_match(struct nsp_softc *, u_int8_t, u_int8_t); 15892739Salfredstatic int nsp_wait_interrupt(struct nsp_softc *); 15967468Snon 16067468Snonstruct scsi_low_funcs nspfuncs = { 16167468Snon SC_LOW_INIT_T nsp_world_start, 16267468Snon SC_LOW_BUSRST_T nsphw_bus_reset, 16373025Snon SC_LOW_TARG_INIT_T nsp_targ_init, 16479697Snon SC_LOW_LUN_INIT_T NULL, 16567468Snon 16667468Snon SC_LOW_SELECT_T nsphw_start_selection, 16779697Snon SC_LOW_NEXUS_T nsp_lun_nexus_establish, 16879697Snon SC_LOW_NEXUS_T nsp_ccb_nexus_establish, 16967468Snon 17067468Snon SC_LOW_ATTEN_T nsphw_attention, 17167468Snon SC_LOW_MSG_T nsp_msg, 17267468Snon 17379697Snon SC_LOW_TIMEOUT_T nsp_timeout, 17467468Snon SC_LOW_POLL_T nspintr, 17567468Snon 17667468Snon NULL, 17767468Snon}; 17867468Snon 17967468Snon/**************************************************** 18067468Snon * hwfuncs 18167468Snon ****************************************************/ 182274760Sjhbstatic __inline uint8_t 183274760Sjhbnsp_cr_read_1(struct resource *res, bus_addr_t ofs) 184274760Sjhb{ 18567468Snon 186274760Sjhb bus_write_1(res, nsp_idxr, ofs); 187274760Sjhb return bus_read_1(res, nsp_datar); 18867468Snon} 18967468Snon 19067468Snonstatic __inline void 191274760Sjhbnsp_cr_write_1(struct resource *res, bus_addr_t ofs, uint8_t va) 19267468Snon{ 19367468Snon 194274760Sjhb bus_write_1(res, nsp_idxr, ofs); 195274760Sjhb bus_write_1(res, nsp_datar, va); 19667468Snon} 19767468Snon 19867468Snonstatic int 199189004Srdivackynsp_expect_signal(struct nsp_softc *sc, u_int8_t curphase, u_int8_t mask) 20067468Snon{ 20167468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 20279697Snon int wc; 20373025Snon u_int8_t ph, isrc; 20467468Snon 20579697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 20667468Snon { 207274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 20879697Snon if (ph == (u_int8_t) -1) 20979697Snon return -1; 21079697Snon 211274760Sjhb isrc = bus_read_1(sc->port_res, nsp_irqsr); 21279697Snon if (isrc & IRQSR_SCSI) 21379697Snon return 0; 21467468Snon 21579697Snon if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase) 21679697Snon return 1; 21779697Snon 218240172Sjhb DELAY(NSP_DELAY_INTERVAL); 21967468Snon } 22067468Snon 221240325Sjhb device_printf(slp->sl_dev, "nsp_expect_signal timeout\n"); 22279697Snon return -1; 22367468Snon} 22467468Snon 22567468Snonstatic void 22667468Snonnsphw_init(sc) 22767468Snon struct nsp_softc *sc; 22867468Snon{ 22967468Snon 23067468Snon /* block all interrupts */ 231274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_ALLMASK); 23267468Snon 23367468Snon /* setup SCSI interface */ 234274760Sjhb bus_write_1(sc->port_res, nsp_ifselr, IFSELR_IFSEL); 23567468Snon 236274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCIENR, 0); 23767468Snon 238274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_IO8); 239274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_CLKDIVR, sc->sc_iclkdiv); 24067468Snon 241274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr); 242274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PARITYR, sc->sc_parr); 243274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, 24467468Snon PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS); 24567468Snon 24667468Snon /* setup fifo asic */ 247274760Sjhb bus_write_1(sc->port_res, nsp_ifselr, IFSELR_REGSEL); 248274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TERMPWRC, 0); 249274760Sjhb if ((nsp_cr_read_1(sc->port_res, NSPR_OCR) & OCR_TERMPWRS) == 0) 250274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TERMPWRC, TERMPWRC_POWON); 25167468Snon 252274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_IO8); 253274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_CLKDIVR, sc->sc_clkdiv); 254274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0); 255274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0); 25667468Snon 257274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SYNCR, 0); 258274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, 0); 25967468Snon 26067468Snon /* enable interrupts and ack them */ 261274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr); 262274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQSR_MASK); 26367468Snon 26479697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 26567468Snon} 26667468Snon 26767468Snon/**************************************************** 26867468Snon * scsi low interface 26967468Snon ****************************************************/ 27067468Snonstatic void 27167468Snonnsphw_attention(sc) 27267468Snon struct nsp_softc *sc; 27367468Snon{ 27467468Snon u_int8_t cr; 27567468Snon 276274760Sjhb cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR)/* & ~SCBUSCR_ACK */; 277274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr | SCBUSCR_ATN); 278240172Sjhb DELAY(10); 27967468Snon} 28067468Snon 28167468Snonstatic void 28267468Snonnsphw_bus_reset(sc) 28367468Snon struct nsp_softc *sc; 28467468Snon{ 28567468Snon int i; 28667468Snon 287274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_ALLMASK); 28867468Snon 289274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, SCBUSCR_RST); 290240172Sjhb DELAY(100 * 1000); /* 100ms */ 291274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 0); 29267468Snon for (i = 0; i < 5; i ++) 293274760Sjhb (void) nsp_cr_read_1(sc->port_res, NSPR_IRQPHS); 29467468Snon 295274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQSR_MASK); 29667468Snon} 29767468Snon 29879697Snonstatic void 29979697Snonnsphw_selection_done_and_expect_msgout(sc) 30071468Sjhb struct nsp_softc *sc; 30171468Sjhb{ 30279697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 30371468Sjhb 30479697Snon /* clear ack counter */ 30579697Snon sc->sc_cnt = 0; 306274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 30779697Snon PTCLRR_REQ | PTCLRR_HOST); 30879697Snon 30979697Snon /* deassert sel and assert atten */ 31079697Snon sc->sc_seltout = 0; 311274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, sc->sc_busc); 312240172Sjhb DELAY(1); 313274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 31479697Snon sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN); 31579697Snon SCSI_LOW_ASSERT_ATN(slp); 31671468Sjhb} 31771468Sjhb 31867468Snonstatic int 31967468Snonnsphw_start_selection(sc, cb) 32067468Snon struct nsp_softc *sc; 32167468Snon struct slccb *cb; 32267468Snon{ 32367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 32467468Snon struct targ_info *ti = cb->ti; 32567468Snon register u_int8_t arbs, ph; 326274760Sjhb int wc; 32767468Snon 32879697Snon wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 32979697Snon sc->sc_dataout_timeout = 0; 33079697Snon 33167468Snon /* check bus free */ 332274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 33379697Snon if (ph != SCBUSMON_FREE) 33467468Snon { 33579697Snon#ifdef NSP_STATICS 33679697Snon nsp_statics.arbit_conflict_1 ++; 33779697Snon#endif /* NSP_STATICS */ 33879697Snon return SCSI_LOW_START_FAIL; 33967468Snon } 34067468Snon 34167468Snon /* start arbitration */ 342274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_EXEC); 34379697Snon 34467468Snon SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); 34567468Snon do 34667468Snon { 34767468Snon /* XXX: what a stupid chip! */ 348274760Sjhb arbs = nsp_cr_read_1(sc->port_res, NSPR_ARBITS); 349240172Sjhb DELAY(1); 35067468Snon } 35173025Snon while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0); 35267468Snon 35367468Snon if ((arbs & ARBITS_WIN) == 0) 35467468Snon { 355274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_CLR); 35679697Snon#ifdef NSP_STATICS 35779697Snon nsp_statics.arbit_conflict_2 ++; 35879697Snon#endif /* NSP_STATICS */ 35967468Snon return SCSI_LOW_START_FAIL; 36067468Snon } 36167468Snon 36267468Snon /* assert select line */ 36367468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); 36479697Snon scsi_low_arbit_win(slp); 36579697Snon 366240172Sjhb DELAY(3); 367274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_DATA, 36867468Snon sc->sc_idbit | (1 << ti->ti_id)); 369274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 37067468Snon SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc); 371240172Sjhb DELAY(3); 372274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, SCBUSCR_SEL | 37367468Snon SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc); 374274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ARBITS, ARBITS_CLR); 375240172Sjhb DELAY(3); 376274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 37767468Snon SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc); 378240172Sjhb DELAY(1); 37967468Snon 38079697Snon if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0) 38179697Snon { 38279697Snon#define NSP_FIRST_SEL_WAIT 300 38379697Snon#define NSP_SEL_CHECK_INTERVAL 10 38479697Snon 38579697Snon /* wait for a selection response */ 38679697Snon for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL; 38779697Snon wc ++) 38879697Snon { 389274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 39079697Snon if ((ph & SCBUSMON_BSY) == 0) 39179697Snon { 392240172Sjhb DELAY(NSP_SEL_CHECK_INTERVAL); 39379697Snon continue; 39479697Snon } 39579697Snon 396240172Sjhb DELAY(1); 397274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 39879697Snon if ((ph & SCBUSMON_BSY) != 0) 39979697Snon { 40079697Snon nsphw_selection_done_and_expect_msgout(sc); 40179697Snon 40279697Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 40379697Snon return SCSI_LOW_START_OK; 40479697Snon } 40579697Snon } 40679697Snon } 40779697Snon 40879697Snon /* check a selection timeout */ 40979697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 41067468Snon sc->sc_seltout = 1; 41167468Snon return SCSI_LOW_START_OK; 41267468Snon} 41367468Snon 41467468Snonstatic int 41567468Snonnsp_world_start(sc, fdone) 41667468Snon struct nsp_softc *sc; 41767468Snon int fdone; 41867468Snon{ 41967468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 42067468Snon 42167468Snon sc->sc_cnt = 0; 42267468Snon sc->sc_seltout = 0; 42379697Snon 42467468Snon if ((slp->sl_cfgflags & CFG_NOATTEN) == 0) 42567468Snon sc->sc_busc = SCBUSCR_ATN; 42667468Snon else 42767468Snon sc->sc_busc = 0; 42879697Snon 42979697Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0) 43079697Snon sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR; 43179697Snon else 43279697Snon sc->sc_parr = 0; 43379697Snon 43467468Snon sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST); 43567468Snon 43667468Snon nsphw_init(sc); 43767468Snon scsi_low_bus_reset(slp); 43867468Snon 43967468Snon return 0; 44067468Snon} 44167468Snon 44267468Snonstruct ncp_synch_data { 44367468Snon u_int min_period; 44467468Snon u_int max_period; 44567468Snon u_int chip_period; 44667468Snon u_int ack_width; 44767468Snon}; 44867468Snon 44967468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = { 45067468Snon {0x0c,0x0c,0x1,0}, /* 20MB 50ns*/ 45167468Snon {0x19,0x19,0x3,1}, /* 10MB 100ns*/ 45267468Snon {0x1a,0x25,0x5,2}, /* 7.5MB 150ns*/ 45367468Snon {0x26,0x32,0x7,3}, /* 5MB 200ns*/ 45467468Snon {0x0, 0, 0, 0} 45567468Snon}; 45667468Snon 45767468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = { 45867468Snon {0x19,0x19,0x1,0}, /* 10MB 100ns*/ 45967468Snon {0x1a,0x25,0x2,0}, /* 7.5MB 150ns*/ 46067468Snon {0x26,0x32,0x3,1}, /* 5MB 200ns*/ 46167468Snon {0x0, 0, 0, 0} 46267468Snon}; 46367468Snon 46467468Snonstatic int 46567468Snonnsp_msg(sc, ti, msg) 46667468Snon struct nsp_softc *sc; 46767468Snon struct targ_info *ti; 46867468Snon u_int msg; 46967468Snon{ 47067468Snon struct ncp_synch_data *sdp; 47173025Snon struct nsp_targ_info *nti = (void *) ti; 47267468Snon u_int period, offset; 47379697Snon int i, error; 47467468Snon 47579697Snon if ((msg & SCSI_LOW_MSG_WIDE) != 0) 47679697Snon { 47779697Snon if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) 47879697Snon { 47979697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 48079697Snon return EINVAL; 48179697Snon } 48279697Snon return 0; 48379697Snon } 48479697Snon 48567468Snon if ((msg & SCSI_LOW_MSG_SYNCH) == 0) 48667468Snon return 0; 48767468Snon 48873025Snon period = ti->ti_maxsynch.period; 48973025Snon offset = ti->ti_maxsynch.offset; 49067468Snon if (sc->sc_iclkdiv == CLKDIVR_20M) 49167468Snon sdp = &ncp_sync_data_20M[0]; 49267468Snon else 49367468Snon sdp = &ncp_sync_data_40M[0]; 49467468Snon 49567468Snon for (i = 0; sdp->max_period != 0; i ++, sdp ++) 49667468Snon { 49767468Snon if (period >= sdp->min_period && period <= sdp->max_period) 49867468Snon break; 49967468Snon } 50067468Snon 50167468Snon if (period != 0 && sdp->max_period == 0) 50267468Snon { 50367468Snon /* 50467468Snon * NO proper period/offset found, 50567468Snon * Retry neg with the target. 50667468Snon */ 50773025Snon ti->ti_maxsynch.period = 0; 50873025Snon ti->ti_maxsynch.offset = 0; 50973025Snon nti->nti_reg_syncr = 0; 51073025Snon nti->nti_reg_ackwidth = 0; 51179697Snon error = EINVAL; 51267468Snon } 51379697Snon else 51479697Snon { 51579697Snon nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) | 51679697Snon (offset & SYNCR_OFFM); 51779697Snon nti->nti_reg_ackwidth = sdp->ack_width; 51879697Snon error = 0; 51979697Snon } 52067468Snon 521274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SYNCR, nti->nti_reg_syncr); 522274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 52379697Snon return error; 52467468Snon} 52567468Snon 52667468Snonstatic int 52779697Snonnsp_targ_init(sc, ti, action) 52867468Snon struct nsp_softc *sc; 52967468Snon struct targ_info *ti; 53079697Snon int action; 53167468Snon{ 53273025Snon struct nsp_targ_info *nti = (void *) ti; 53367468Snon 53479697Snon if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) 53579697Snon { 53679697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 53779697Snon ti->ti_maxsynch.period = 100 / 4; 53879697Snon ti->ti_maxsynch.offset = 15; 53979697Snon nti->nti_reg_syncr = 0; 54079697Snon nti->nti_reg_ackwidth = 0; 54179697Snon } 54267468Snon return 0; 54367468Snon} 54467468Snon 54579697Snonstatic void 54679697Snonnsp_start_timer(sc, time) 54779697Snon struct nsp_softc *sc; 54879697Snon int time; 54979697Snon{ 55079697Snon 55179697Snon sc->sc_timer = time; 552274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, time); 55379697Snon} 55479697Snon 55567468Snon/************************************************************** 55667468Snon * General probe attach 55767468Snon **************************************************************/ 55867468Snonint 559274760Sjhbnspprobesubr(struct resource *res, u_int dvcfg) 56067468Snon{ 56167468Snon u_int8_t regv; 56267468Snon 563274760Sjhb regv = bus_read_1(res, nsp_fifosr); 56467468Snon if (regv < 0x11 || regv >= 0x20) 56567468Snon return 0; 56667468Snon return 1; 56767468Snon} 56867468Snon 56967468Snonvoid 57067468Snonnspattachsubr(sc) 57167468Snon struct nsp_softc *sc; 57267468Snon{ 57367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 57467468Snon 57567468Snon sc->sc_idbit = (1 << slp->sl_hostid); 57679697Snon slp->sl_flags |= HW_READ_PADDING; 57767468Snon slp->sl_funcs = &nspfuncs; 57879697Snon sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ 57967468Snon 58079697Snon (void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS, 58179697Snon sizeof(struct nsp_targ_info), 0); 58267468Snon} 58367468Snon 58467468Snon/************************************************************** 58567468Snon * PDMA functions 58667468Snon **************************************************************/ 58767468Snonstatic u_int 58867468Snonnsp_fifo_count(sc) 58967468Snon struct nsp_softc *sc; 59067468Snon{ 59167468Snon u_int count; 59267468Snon 593274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT); 594274760Sjhb count = bus_read_1(sc->port_res, nsp_datar); 595274760Sjhb count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 8); 596274760Sjhb count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 16); 59767468Snon return count; 59867468Snon} 59967468Snon 60079697Snonstatic u_int 60179697Snonnsp_request_count(sc) 60279697Snon struct nsp_softc *sc; 60379697Snon{ 60479697Snon u_int count; 60579697Snon 606274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT); 607274760Sjhb count = bus_read_1(sc->port_res, nsp_datar); 608274760Sjhb count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 8); 609274760Sjhb count += (((u_int) bus_read_1(sc->port_res, nsp_datar)) << 16); 61079697Snon return count; 61179697Snon} 61279697Snon 61367468Snonstatic void 61479697Snonnsp_setup_fifo(sc, on, direction, datalen) 61567468Snon struct nsp_softc *sc; 61667468Snon int on; 61779697Snon int direction; 61879697Snon int datalen; 61967468Snon{ 62067468Snon u_int8_t xfermode; 62167468Snon 62279697Snon sc->sc_suspendio = 0; 62379697Snon if (on == NSP_FIFO_OFF) 62479697Snon { 62579697Snon xfermode = XFERMR_IO8; 62679697Snon goto out; 62779697Snon } 62867468Snon 62979697Snon /* check if suspend io OK ? */ 63079697Snon if (datalen > 0) 63167468Snon { 63279697Snon if (direction == SCSI_LOW_READ) 63379697Snon { 63479697Snon if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 && 63579697Snon (datalen % nsp_read_suspend_bytes) == 0) 63679697Snon sc->sc_suspendio = nsp_read_suspend_bytes; 63779697Snon } 63879697Snon else 63979697Snon { 64079697Snon if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 && 64179697Snon (datalen % nsp_write_suspend_bytes) == 0) 64279697Snon sc->sc_suspendio = nsp_write_suspend_bytes; 64379697Snon } 64467468Snon } 64579697Snon 64679697Snon /* determine a transfer type */ 64779697Snon if (datalen < DEV_BSIZE || (datalen & 3) != 0) 64879697Snon { 649274760Sjhb if (sc->mem_res != NULL && 65079697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 65179697Snon xfermode = XFERMR_XEN | XFERMR_MEM8; 65279697Snon else 65379697Snon xfermode = XFERMR_XEN | XFERMR_IO8; 65479697Snon } 65567468Snon else 65667468Snon { 657274760Sjhb if (sc->mem_res != NULL && 65879697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 65979697Snon xfermode = XFERMR_XEN | XFERMR_MEM32; 66067468Snon else 66179697Snon xfermode = XFERMR_XEN | XFERMR_IO32; 66279697Snon 66379697Snon if (sc->sc_suspendio > 0) 66479697Snon xfermode |= XFERMR_FIFOEN; 66567468Snon } 66667468Snon 66779697Snonout: 66867468Snon sc->sc_xfermr = xfermode; 669274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_XFERMR, sc->sc_xfermr); 67067468Snon} 67167468Snon 67279697Snonstatic void 67367468Snonnsp_pdma_end(sc, ti) 67467468Snon struct nsp_softc *sc; 67567468Snon struct targ_info *ti; 67667468Snon{ 67767468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 67879697Snon struct slccb *cb = slp->sl_Qnexus; 67967468Snon u_int len = 0, cnt; 68067468Snon 68179697Snon sc->sc_dataout_timeout = 0; 68267468Snon slp->sl_flags &= ~HW_PDMASTART; 68379697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 68479697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 68579697Snon { 68679697Snon sc->sc_icr &= ~SCIENR_FIFO; 687274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr); 68879697Snon } 68967468Snon 69079697Snon if (cb == NULL) 69179697Snon { 69279697Snon slp->sl_error |= PDMAERR; 69379697Snon return; 69479697Snon } 69579697Snon 69667468Snon if (ti->ti_phase == PH_DATA) 69767468Snon { 69867468Snon cnt = nsp_fifo_count(sc); 69967468Snon if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) 70067468Snon { 70167468Snon len = sc->sc_cnt - cnt; 70279697Snon if (sc->sc_cnt >= cnt && 70379697Snon slp->sl_scp.scp_datalen + len <= 70467468Snon cb->ccb_scp.scp_datalen) 70567468Snon { 70667468Snon slp->sl_scp.scp_data -= len; 70767468Snon slp->sl_scp.scp_datalen += len; 70867468Snon } 70967468Snon else 71067468Snon { 71167468Snon slp->sl_error |= PDMAERR; 712240325Sjhb device_printf(slp->sl_dev, 713240325Sjhb "len %x >= datalen %x\n", 71467468Snon len, slp->sl_scp.scp_datalen); 71567468Snon } 71667468Snon } 71767468Snon else if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 71867468Snon { 71979697Snon if (sc->sc_cnt != cnt || 72079697Snon sc->sc_cnt > cb->ccb_scp.scp_datalen) 72167468Snon { 72267468Snon slp->sl_error |= PDMAERR; 723240325Sjhb device_printf(slp->sl_dev, 724240325Sjhb "data read count error %x != %x (%x)\n", 725240325Sjhb sc->sc_cnt, cnt, 72679697Snon cb->ccb_scp.scp_datalen); 72767468Snon } 72867468Snon } 72967468Snon sc->sc_cnt = cnt; 73079697Snon scsi_low_data_finish(slp); 73167468Snon } 73267468Snon else 73367468Snon { 73467468Snon 735240325Sjhb device_printf(slp->sl_dev, "data phase miss\n"); 73667468Snon slp->sl_error |= PDMAERR; 73767468Snon } 73867468Snon} 73967468Snon 74067468Snon#define RFIFO_CRIT 64 74179697Snon#define WFIFO_CRIT 32 74267468Snon 74367468Snonstatic void 74479697Snonnsp_data_padding(sc, direction, count) 74567468Snon struct nsp_softc *sc; 74679697Snon int direction; 74779697Snon u_int count; 74867468Snon{ 74979697Snon 75079697Snon if (count > NSP_MAX_DATA_SIZE) 75179697Snon count = NSP_MAX_DATA_SIZE; 75279697Snon 753274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8); 75479697Snon if (direction == SCSI_LOW_READ) 75579697Snon { 75679697Snon while (count -- > 0) 757274760Sjhb (void) bus_read_1(sc->port_res, nsp_fifodr); 75879697Snon } 75979697Snon else 76079697Snon { 76179697Snon while (count -- > 0) 762274760Sjhb (void) bus_write_1(sc->port_res, nsp_fifodr, 0); 76379697Snon } 764274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_XFERMR, sc->sc_xfermr); 76579697Snon} 76679697Snon 76779697Snonstatic int 76879697Snonnsp_read_fifo(sc, suspendio) 76979697Snon struct nsp_softc *sc; 77079697Snon int suspendio; 77179697Snon{ 77267468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 77379697Snon u_int res; 77467468Snon 77579697Snon res = nsp_fifo_count(sc); 77679697Snon if (res == sc->sc_cnt) 77779697Snon return 0; 77867468Snon 77979697Snon#ifdef NSP_DEBUG 78079697Snon if (res < sc->sc_cnt || res == (u_int) -1) 78167468Snon { 782240325Sjhb device_printf(slp->sl_dev, 783240325Sjhb "strange fifo ack count 0x%x < 0x%x\n", res, sc->sc_cnt); 78479697Snon return 0; 78579697Snon } 78679697Snon#endif /* NSP_DEBUG */ 78779697Snon 78879697Snon res = res - sc->sc_cnt; 78979697Snon if (res > slp->sl_scp.scp_datalen) 79079697Snon { 79179697Snon if ((slp->sl_error & PDMAERR) == 0) 79279697Snon { 793240325Sjhb device_printf(slp->sl_dev, "data overrun 0x%x > 0x%x\n", 794240325Sjhb res, slp->sl_scp.scp_datalen); 79579697Snon } 79679697Snon 79779697Snon slp->sl_error |= PDMAERR; 79879697Snon slp->sl_scp.scp_datalen = 0; 79979697Snon 80079697Snon if ((slp->sl_flags & HW_READ_PADDING) == 0) 80179697Snon { 802240325Sjhb device_printf(slp->sl_dev, "read padding required\n"); 80379697Snon return 0; 80479697Snon } 80579697Snon 80679697Snon nsp_data_padding(sc, SCSI_LOW_READ, res); 80779697Snon sc->sc_cnt += res; 80879697Snon return 1; /* padding start */ 80979697Snon } 81079697Snon 81179697Snon if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio) 81279697Snon res = suspendio; 81379697Snon 81479697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 81579697Snon { 81679697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 81779697Snon { 81879697Snon res &= ~3; 819274760Sjhb bus_read_region_4(sc->mem_res, 0, 82079697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 82179697Snon } 82279697Snon else 82379697Snon { 824274760Sjhb bus_read_region_1(sc->mem_res, 0, 82579697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 82679697Snon } 82779697Snon } 82879697Snon else 82979697Snon { 83079697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 83179697Snon { 83279697Snon res &= ~3; 833274760Sjhb bus_read_multi_4(sc->port_res, nsp_fifodr, 83479697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 83579697Snon } 83679697Snon else 83779697Snon { 838274760Sjhb bus_read_multi_1(sc->port_res, nsp_fifodr, 83979697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 84079697Snon } 84179697Snon } 84279697Snon 843274760Sjhb if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE) 84479697Snon { 845274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PARITYR, 84679697Snon PARITYR_ENABLE | PARITYR_CLEAR); 84779697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1); 84879697Snon } 84979697Snon 85079697Snon slp->sl_scp.scp_data += res; 85179697Snon slp->sl_scp.scp_datalen -= res; 85279697Snon sc->sc_cnt += res; 85379697Snon return 0; 85479697Snon} 85579697Snon 85679697Snonstatic int 85779697Snonnsp_write_fifo(sc, suspendio) 85879697Snon struct nsp_softc *sc; 85979697Snon int suspendio; 86079697Snon{ 86179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 86279697Snon u_int res; 86379697Snon register u_int8_t stat; 86479697Snon 86579697Snon if (suspendio > 0) 86679697Snon { 86779697Snon#ifdef NSP_DEBUG 86879697Snon if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0) 86979697Snon { 870240325Sjhb device_printf(slp->sl_dev, 871240325Sjhb "strange write length 0x%x\n", 872240325Sjhb slp->sl_scp.scp_datalen); 87379697Snon } 87479697Snon#endif /* NSP_DEBUG */ 87579697Snon res = slp->sl_scp.scp_datalen % suspendio; 87667468Snon if (res == 0) 87767468Snon { 87879697Snon res = suspendio; 87967468Snon } 88079697Snon } 88179697Snon else 88279697Snon { 88379697Snon res = WFIFO_CRIT; 88479697Snon } 88567468Snon 88679697Snon if (res > slp->sl_scp.scp_datalen) 88779697Snon res = slp->sl_scp.scp_datalen; 88867468Snon 88979697Snon /* XXX: reconfirm! */ 890274760Sjhb stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 89179697Snon if (stat != PHASE_DATAOUT) 89279697Snon return 0; 89367468Snon 89479697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 89579697Snon { 89679697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 89779697Snon { 898274760Sjhb bus_write_region_4(sc->mem_res, 0, 89979697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 90079697Snon } 90167468Snon else 90279697Snon { 903274760Sjhb bus_write_region_1(sc->mem_res, 0, 90479697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 90579697Snon } 90679697Snon } 90779697Snon else 90879697Snon { 90979697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 91079697Snon { 911274760Sjhb bus_write_multi_4(sc->port_res, nsp_fifodr, 91279697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 91379697Snon } 91479697Snon else 91579697Snon { 916274760Sjhb bus_write_multi_1(sc->port_res, nsp_fifodr, 91779697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 91879697Snon } 91979697Snon } 92067468Snon 92179697Snon slp->sl_scp.scp_datalen -= res; 92279697Snon slp->sl_scp.scp_data += res; 92379697Snon sc->sc_cnt += res; 92479697Snon return 0; 92579697Snon} 92679697Snon 92779697Snonstatic int 92879697Snonnsp_wait_interrupt(sc) 92979697Snon struct nsp_softc *sc; 93079697Snon{ 93179697Snon int tout; 93279697Snon register u_int8_t isrc; 93379697Snon 93479697Snon for (tout = 0; tout < DEV_BSIZE / 10; tout ++) 93579697Snon { 936274760Sjhb isrc = bus_read_1(sc->port_res, nsp_irqsr); 93779697Snon if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0) 93867468Snon { 93979697Snon if ((isrc & IRQSR_FIFO) != 0) 94079697Snon { 941274760Sjhb bus_write_1(sc->port_res, 94279697Snon nsp_irqcr, IRQCR_FIFOCL); 94379697Snon } 94479697Snon return 1; 94567468Snon } 946240172Sjhb DELAY(1); 94779697Snon } 94879697Snon return 0; 94979697Snon} 95079697Snon 95179697Snonstatic void 95279697Snonnsp_pio_read(sc, suspendio) 95379697Snon struct nsp_softc *sc; 95479697Snon int suspendio; 95579697Snon{ 95679697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 95779697Snon int tout, padding, datalen; 95879697Snon register u_int8_t stat, fstat; 95979697Snon 96079697Snon padding = 0; 96179697Snon tout = sc->sc_tmaxcnt; 96279697Snon slp->sl_flags |= HW_PDMASTART; 96379697Snon datalen = slp->sl_scp.scp_datalen; 96479697Snon 96579697SnonReadLoop: 96679697Snon while (1) 96779697Snon { 968274760Sjhb stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 96979697Snon if (stat == (u_int8_t) -1) 97079697Snon return; 97179697Snon 97279697Snon /* out of data phase */ 97379697Snon if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN) 97479697Snon { 97579697Snon nsp_read_fifo(sc, 0); 97679697Snon return; 97779697Snon } 97879697Snon 97979697Snon /* data phase */ 980274760Sjhb fstat = bus_read_1(sc->port_res, nsp_fifosr); 98179697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 98279697Snon { 98379697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 98479697Snon { 985274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, 98679697Snon IRQCR_FIFOCL); 98779697Snon } 98879697Snon 98979697Snon if (suspendio > 0) 99079697Snon { 99179697Snon padding |= nsp_read_fifo(sc, suspendio); 99279697Snon } 99379697Snon else 99479697Snon { 99579697Snon padding |= nsp_read_fifo(sc, 0); 99679697Snon } 99779697Snon 99879697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 99979697Snon break; 100079697Snon } 100167468Snon else 100267468Snon { 100379697Snon if (padding == 0 && slp->sl_scp.scp_datalen <= 0) 100479697Snon return; 100579697Snon 100679697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 100779697Snon break; 100879697Snon 1009240172Sjhb DELAY(1); 101067468Snon } 101167468Snon 101279697Snon if ((-- tout) <= 0) 101379697Snon { 1014240325Sjhb device_printf(slp->sl_dev, "nsp_pio_read: timeout\n"); 101579697Snon return; 101679697Snon } 101767468Snon } 101867468Snon 101979697Snon 102079697Snon if (slp->sl_scp.scp_datalen > 0 && 102179697Snon slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes) 102279697Snon { 102379697Snon if (nsp_wait_interrupt(sc) != 0) 102479697Snon goto ReadLoop; 102579697Snon } 102667468Snon} 102767468Snon 102867468Snonstatic void 102979697Snonnsp_pio_write(sc, suspendio) 103067468Snon struct nsp_softc *sc; 103179697Snon int suspendio; 103267468Snon{ 103367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 103479697Snon u_int rcount, acount; 103579697Snon int tout, datalen; 103679697Snon register u_int8_t stat, fstat; 103767468Snon 103879697Snon tout = sc->sc_tmaxcnt; 103967468Snon slp->sl_flags |= HW_PDMASTART; 104079697Snon datalen = slp->sl_scp.scp_datalen; 104179697Snon 104279697SnonWriteLoop: 104379697Snon while (1) 104467468Snon { 1045274760Sjhb stat = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 104667468Snon if (stat != PHASE_DATAOUT) 104779697Snon return; 104867468Snon 104979697Snon if (slp->sl_scp.scp_datalen <= 0) 105079697Snon { 105179697Snon if (sc->sc_dataout_timeout == 0) 105279697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 105379697Snon return; 105479697Snon } 105567468Snon 1056274760Sjhb fstat = bus_read_1(sc->port_res, nsp_fifosr); 105779697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 105879697Snon { 105979697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 106079697Snon { 1061274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, 106279697Snon IRQCR_FIFOCL); 106379697Snon } 106467468Snon 106579697Snon if (suspendio > 0) 106679697Snon { 106779697Snon /* XXX:IMPORTANT: 106879697Snon * To avoid timeout of pcmcia bus 106979697Snon * (not scsi bus!), we should check 107079697Snon * the scsi device sends us request 107179697Snon * signals, which means the scsi device 1072298955Spfg * is ready to receive data without 107379697Snon * heavy delays. 107479697Snon */ 107582784Snon if ((slp->sl_scp.scp_datalen % suspendio) == 0) 107679697Snon { 107782784Snon /* Step I: 107882784Snon * fill the nsp fifo, and waiting for 107982784Snon * the fifo empty. 108082784Snon */ 108179697Snon nsp_write_fifo(sc, 0); 108279697Snon } 108379697Snon else 108479697Snon { 108582784Snon /* Step II: 108682784Snon * check the request singals. 108782784Snon */ 108882784Snon acount = nsp_fifo_count(sc); 108982784Snon rcount = nsp_request_count(sc); 109082784Snon if (rcount <= acount) 109182784Snon { 109282784Snon nsp_write_fifo(sc, 0); 109379697Snon#ifdef NSP_STATICS 109482784Snon nsp_statics.device_busy ++; 109579697Snon#endif /* NSP_STATICS */ 109682784Snon } 109782784Snon else 109882784Snon { 109982784Snon nsp_write_fifo(sc, suspendio); 110082784Snon#ifdef NSP_STATICS 110182784Snon nsp_statics.device_data_write ++; 110282784Snon#endif /* NSP_STATICS */ 110382784Snon } 110479697Snon } 110579697Snon } 110679697Snon else 110779697Snon { 110879697Snon nsp_write_fifo(sc, 0); 110979697Snon } 111079697Snon 111179697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 111279697Snon break; 111367468Snon } 111467468Snon else 111567468Snon { 111679697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 111779697Snon break; 111879697Snon 1119240172Sjhb DELAY(1); 112067468Snon } 112167468Snon 112279697Snon if ((-- tout) <= 0) 112379697Snon { 1124240325Sjhb device_printf(slp->sl_dev, "nsp_pio_write: timeout\n"); 112579697Snon return; 112679697Snon } 112767468Snon } 112867468Snon 112979697Snon if (slp->sl_scp.scp_datalen > 0 && 113079697Snon slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes) 113179697Snon { 113279697Snon if (nsp_wait_interrupt(sc) != 0) 113379697Snon goto WriteLoop; 113479697Snon } 113567468Snon} 113667468Snon 113767468Snonstatic int 1138189004Srdivackynsp_negate_signal(struct nsp_softc *sc, u_int8_t mask, u_char *s) 113967468Snon{ 114067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 114179697Snon int wc; 114267468Snon u_int8_t regv; 114367468Snon 114479697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 114567468Snon { 1146274760Sjhb regv = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 114779697Snon if (regv == (u_int8_t) -1) 114879697Snon return -1; 114979697Snon if ((regv & mask) == 0) 115079697Snon return 1; 1151240172Sjhb DELAY(NSP_DELAY_INTERVAL); 115267468Snon } 115367468Snon 1154240325Sjhb device_printf(slp->sl_dev, "%s nsp_negate_signal timeout\n", s); 115579697Snon return -1; 115667468Snon} 115767468Snon 115867468Snonstatic int 115979697Snonnsp_xfer(sc, buf, len, phase, clear_atn) 116067468Snon struct nsp_softc *sc; 116167468Snon u_int8_t *buf; 116267468Snon int len; 116367468Snon int phase; 116479697Snon int clear_atn; 116567468Snon{ 116679697Snon int ptr, rv; 116767468Snon 116867468Snon for (ptr = 0; len > 0; len --, ptr ++) 116967468Snon { 117067468Snon rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ); 117167468Snon if (rv <= 0) 117267468Snon goto out; 117367468Snon 117479697Snon if (len == 1 && clear_atn != 0) 117567468Snon { 1176274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 117767468Snon SCBUSCR_ADIR | SCBUSCR_ACKEN); 117879697Snon SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow); 117967468Snon } 118067468Snon 118167468Snon if (phase & SCBUSMON_IO) 118267468Snon { 1183274760Sjhb buf[ptr] = nsp_cr_read_1(sc->port_res, NSPR_DATAACK); 118467468Snon } 118567468Snon else 118667468Snon { 1187274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_DATAACK, buf[ptr]); 118867468Snon } 118967468Snon nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>"); 119067468Snon } 119167468Snon 119267468Snonout: 119367468Snon return len; 119467468Snon} 119567468Snon 119667468Snon/************************************************************** 119767468Snon * disconnect & reselect (HW low) 119867468Snon **************************************************************/ 119967468Snonstatic int 120067468Snonnsp_reselected(sc) 120167468Snon struct nsp_softc *sc; 120267468Snon{ 120367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 120467468Snon struct targ_info *ti; 120567468Snon u_int sid; 120667468Snon u_int8_t cr; 120767468Snon 1208274760Sjhb sid = (u_int) nsp_cr_read_1(sc->port_res, NSPR_RESELR); 120967468Snon sid &= ~sc->sc_idbit; 121067468Snon sid = ffs(sid) - 1; 121167468Snon if ((ti = scsi_low_reselected(slp, sid)) == NULL) 121267468Snon return EJUSTRETURN; 121367468Snon 121467468Snon nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>"); 121567468Snon 1216274760Sjhb cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR); 121779697Snon cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN); 1218274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 121979697Snon cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN; 1220274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 122167468Snon 122267468Snon#ifdef NSP_STATICS 122379697Snon nsp_statics.reselect ++; 122467468Snon#endif /* NSP_STATCIS */ 122567468Snon return EJUSTRETURN; 122667468Snon} 122767468Snon 122879697Snonstatic int 122967468Snonnsp_disconnected(sc, ti) 123067468Snon struct nsp_softc *sc; 123167468Snon struct targ_info *ti; 123267468Snon{ 123367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 123467468Snon 1235274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 123679697Snon PTCLRR_REQ | PTCLRR_HOST); 123779697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 123879697Snon { 123979697Snon sc->sc_icr &= ~SCIENR_FIFO; 1240274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCIENR, sc->sc_icr); 124179697Snon } 124279697Snon sc->sc_cnt = 0; 124379697Snon sc->sc_dataout_timeout = 0; 124467468Snon#ifdef NSP_STATICS 124579697Snon nsp_statics.disconnect ++; 124667468Snon#endif /* NSP_STATICS */ 124767468Snon scsi_low_disconnected(slp, ti); 124867468Snon return 1; 124967468Snon} 125067468Snon 125167468Snon/************************************************************** 125267468Snon * SEQUENCER 125367468Snon **************************************************************/ 125492739Salfredstatic void nsp_error(struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t); 125567468Snon 125667468Snonstatic void 1257189004Srdivackynsp_error(struct nsp_softc * sc, u_char *s, u_int8_t isrc, u_int8_t ph, 1258189004Srdivacky u_int8_t irqphs) 125967468Snon{ 126067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 126167468Snon 1262240325Sjhb device_printf(slp->sl_dev, "%s\n", s); 1263240325Sjhb device_printf(slp->sl_dev, "isrc 0x%x scmon 0x%x irqphs 0x%x\n", 1264240325Sjhb (u_int) isrc, (u_int) ph, (u_int) irqphs); 126567468Snon} 126667468Snon 126767468Snonstatic int 126879697Snonnsp_target_nexus_establish(sc) 126967468Snon struct nsp_softc *sc; 127067468Snon{ 127179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 127279697Snon struct targ_info *ti = slp->sl_Tnexus; 127373025Snon struct nsp_targ_info *nti = (void *) ti; 127467468Snon 127567468Snon /* setup synch transfer registers */ 1276274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SYNCR, nti->nti_reg_syncr); 1277274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 127867468Snon 127979697Snon /* setup pdma fifo (minimum) */ 128079697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0); 128179697Snon return 0; 128279697Snon} 128379697Snon 128479697Snonstatic int 128579697Snonnsp_lun_nexus_establish(sc) 128679697Snon struct nsp_softc *sc; 128779697Snon{ 128879697Snon 128979697Snon return 0; 129079697Snon} 129179697Snon 129279697Snonstatic int 129379697Snonnsp_ccb_nexus_establish(sc) 129479697Snon struct nsp_softc *sc; 129579697Snon{ 129679697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 129779697Snon struct slccb *cb = slp->sl_Qnexus; 129879697Snon 129979697Snon sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 130079697Snon 130167468Snon /* setup pdma fifo */ 130279697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, 130379697Snon slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen); 130467468Snon 130579697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 130679697Snon { 130779697Snon if (sc->sc_suspendio > 0 && 130879697Snon (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0) 130979697Snon { 131079697Snon sc->sc_icr |= SCIENR_FIFO; 1311274760Sjhb nsp_cr_write_1(sc->port_res, 131279697Snon NSPR_SCIENR, sc->sc_icr); 131379697Snon } 131479697Snon } 131579697Snon else 131679697Snon { 131779697Snon if (sc->sc_suspendio > 0 && 131879697Snon (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0) 131979697Snon { 132079697Snon sc->sc_icr |= SCIENR_FIFO; 1321274760Sjhb nsp_cr_write_1(sc->port_res, 132279697Snon NSPR_SCIENR, sc->sc_icr); 132379697Snon } 132479697Snon } 132567468Snon return 0; 132667468Snon} 132767468Snon 132879697Snonstatic int 1329189004Srdivackynsp_phase_match(struct nsp_softc *sc, u_int8_t phase, u_int8_t stat) 133079697Snon{ 133179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 133279697Snon 133379697Snon if ((stat & SCBUSMON_PHMASK) != phase) 133479697Snon { 1335240325Sjhb device_printf(slp->sl_dev, "phase mismatch 0x%x != 0x%x\n", 1336240325Sjhb (u_int) phase, (u_int) stat); 133779697Snon return EINVAL; 133879697Snon } 133979697Snon 134079697Snon if ((stat & SCBUSMON_REQ) == 0) 134179697Snon return EINVAL; 134279697Snon 134379697Snon return 0; 134479697Snon} 134579697Snon 134667468Snonint 134767468Snonnspintr(arg) 134867468Snon void *arg; 134967468Snon{ 135067468Snon struct nsp_softc *sc = arg; 135167468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 135267468Snon struct targ_info *ti; 135367468Snon struct buf *bp; 135479697Snon u_int derror, flags; 135567468Snon int len, rv; 135667468Snon u_int8_t isrc, ph, irqphs, cr, regv; 135767468Snon 135867468Snon /******************************************* 135967468Snon * interrupt check 136067468Snon *******************************************/ 136167468Snon if (slp->sl_flags & HW_INACTIVE) 136267468Snon return 0; 136367468Snon 1364274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_IRQDIS); 1365274760Sjhb isrc = bus_read_1(sc->port_res, nsp_irqsr); 136679697Snon if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0) 136767468Snon { 1368274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, 0); 136967468Snon return 0; 137067468Snon } 137167468Snon 137267468Snon /* XXX: IMPORTANT 137367468Snon * Do not read an irqphs register if no scsi phase interrupt. 137467468Snon * Unless, you should lose a scsi phase interrupt. 137567468Snon */ 1376274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 137767468Snon if ((isrc & IRQSR_SCSI) != 0) 137867468Snon { 1379274760Sjhb irqphs = nsp_cr_read_1(sc->port_res, NSPR_IRQPHS); 138067468Snon } 138167468Snon else 138267468Snon irqphs = 0; 138367468Snon 138467468Snon /* 138567468Snon * timer interrupt handler (scsi vs timer interrupts) 138667468Snon */ 138767468Snon if (sc->sc_timer != 0) 138867468Snon { 1389274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0); 1390274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_TIMERCNT, 0); 139167468Snon sc->sc_timer = 0; 139267468Snon } 139367468Snon 139479697Snon /* check a timer interrupt */ 139579697Snon regv = 0; 139679697Snon if ((isrc & IRQSR_TIMER) != 0) 139767468Snon { 139879697Snon if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0) 139979697Snon { 1400274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_TIMERCL); 140179697Snon return 1; 140279697Snon } 140379697Snon regv |= IRQCR_TIMERCL; 140467468Snon } 140567468Snon 140679697Snon /* check a fifo interrupt */ 140779697Snon if ((isrc & IRQSR_FIFO) != 0) 140879697Snon { 140979697Snon regv |= IRQCR_FIFOCL; 141079697Snon } 141167468Snon 141279697Snon /* OK. enable all interrupts */ 1413274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, regv); 141479697Snon 141567468Snon /******************************************* 141667468Snon * debug section 141767468Snon *******************************************/ 141867468Snon#ifdef NSP_DEBUG 141967468Snon if (nsp_debug) 142067468Snon { 142179697Snon nsp_error(sc, "current status", isrc, ph, irqphs); 142267468Snon scsi_low_print(slp, NULL); 1423131915Smarcel#ifdef KDB 142467468Snon if (nsp_debug > 1) 1425240172Sjhb kdb_enter(KDB_WHY_CAM, "nsp"); 1426131915Smarcel#endif /* KDB */ 142767468Snon } 142867468Snon#endif /* NSP_DEBUG */ 142967468Snon 143067468Snon /******************************************* 143167468Snon * Parse hardware SCSI irq reasons register 143267468Snon *******************************************/ 143367468Snon if ((isrc & IRQSR_SCSI) != 0) 143467468Snon { 143567468Snon if ((irqphs & IRQPHS_RST) != 0) 143667468Snon { 143767468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 143867468Snon "bus reset (power off?)"); 143967468Snon return 1; 144067468Snon } 144167468Snon 144267468Snon if ((irqphs & IRQPHS_RSEL) != 0) 144367468Snon { 1444274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_RESCL); 144567468Snon if (nsp_reselected(sc) == EJUSTRETURN) 144667468Snon return 1; 144767468Snon } 144867468Snon 144967468Snon if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0) 145067468Snon return 1; 145167468Snon } 145267468Snon 145367468Snon /******************************************* 145467468Snon * nexus check 145567468Snon *******************************************/ 145679697Snon if ((ti = slp->sl_Tnexus) == NULL) 145767468Snon { 145867468Snon /* unknown scsi phase changes */ 145979697Snon nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs); 146067468Snon return 0; 146167468Snon } 146267468Snon 146367468Snon /******************************************* 146467468Snon * aribitration & selection 146567468Snon *******************************************/ 146667468Snon switch (ti->ti_phase) 146767468Snon { 146867468Snon case PH_SELSTART: 146967468Snon if ((ph & SCBUSMON_BSY) == 0) 147067468Snon { 147167468Snon if (sc->sc_seltout >= NSP_SELTIMEOUT) 147267468Snon { 147367468Snon sc->sc_seltout = 0; 1474274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, 0); 147567468Snon return nsp_disconnected(sc, ti); 147667468Snon } 147767468Snon sc->sc_seltout ++; 147879697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 147967468Snon return 1; 148067468Snon } 148167468Snon 148267468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 148379697Snon nsphw_selection_done_and_expect_msgout(sc); 148467468Snon return 1; 148567468Snon 148679697Snon case PH_SELECTED: 148779697Snon if ((isrc & IRQSR_SCSI) == 0) 148879697Snon return 1; 148979697Snon 149079697Snon nsp_target_nexus_establish(sc); 149179697Snon break; 149279697Snon 149367468Snon case PH_RESEL: 149479697Snon if ((isrc & IRQSR_SCSI) == 0) 149579697Snon return 1; 149679697Snon 149779697Snon nsp_target_nexus_establish(sc); 149867468Snon if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN) 149967468Snon { 1500240325Sjhb device_printf(slp->sl_dev, 1501240325Sjhb "unexpected phase after reselect\n"); 150279697Snon slp->sl_error |= FATALIO; 150367468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); 150467468Snon return 1; 150567468Snon } 150679697Snon break; 150767468Snon 150879697Snon case PH_DATA: 150979697Snon if ((isrc & IRQSR_SCSI) != 0) 151079697Snon break; 151179697Snon if ((isrc & IRQSR_FIFO) != 0) 151279697Snon { 151379697Snon if (NSP_IS_PHASE_DATA(ph) == 0) 151479697Snon return 1; 151579697Snon irqphs = (ph & IRQPHS_PHMASK); 151679697Snon break; 151779697Snon } 151879697Snon return 1; 151979697Snon 152067468Snon default: 152179697Snon if ((isrc & IRQSR_SCSI) == 0) 152267468Snon return 1; 152367468Snon break; 152467468Snon } 152567468Snon 152667468Snon /******************************************* 152779697Snon * data phase control 152867468Snon *******************************************/ 152967468Snon if (slp->sl_flags & HW_PDMASTART) 153079697Snon { 153179697Snon if ((isrc & IRQSR_SCSI) != 0 && 153279697Snon NSP_IS_IRQPHS_DATA(irqphs) == 0) 153379697Snon { 153479697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 153579697Snon nsp_pio_read(sc, 0); 153679697Snon nsp_pdma_end(sc, ti); 153779697Snon } 153879697Snon } 153967468Snon 154079697Snon /******************************************* 154179697Snon * scsi seq 154279697Snon *******************************************/ 154367468Snon if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0) 154467468Snon return nsp_disconnected(sc, ti); 154567468Snon 154667468Snon /* check unexpected bus free state */ 154767468Snon if (ph == 0) 154867468Snon { 154979697Snon nsp_error(sc, "unexpected bus free", isrc, ph, irqphs); 155067468Snon return nsp_disconnected(sc, ti); 155167468Snon } 155267468Snon 155367468Snon /* check normal scsi phase */ 155479697Snon switch (irqphs & IRQPHS_PHMASK) 155567468Snon { 155679697Snon case IRQPHS_CMD: 155779697Snon if (nsp_phase_match(sc, PHASE_CMD, ph) != 0) 155867468Snon return 1; 155967468Snon 156067468Snon SCSI_LOW_SETUP_PHASE(ti, PH_CMD); 156167468Snon if (scsi_low_cmd(slp, ti) != 0) 156279697Snon { 156379697Snon scsi_low_attention(slp); 156479697Snon } 156567468Snon 1566274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_CMDCR, CMDCR_PTCLR); 156767468Snon for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++) 1568274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_CMDDR, 156967468Snon slp->sl_scp.scp_cmd[len]); 157067468Snon 1571274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC); 157267468Snon break; 157367468Snon 157479697Snon case IRQPHS_DATAOUT: 157567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 157667468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) 157779697Snon { 157879697Snon scsi_low_attention(slp); 157979697Snon } 158067468Snon 158179697Snon nsp_pio_write(sc, sc->sc_suspendio); 158267468Snon break; 158367468Snon 158479697Snon case IRQPHS_DATAIN: 158567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 158667468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) 158779697Snon { 158879697Snon scsi_low_attention(slp); 158979697Snon } 159067468Snon 159179697Snon nsp_pio_read(sc, sc->sc_suspendio); 159267468Snon break; 159367468Snon 159479697Snon case IRQPHS_STATUS: 159579697Snon if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0) 159667468Snon return 1; 159767468Snon 159867468Snon SCSI_LOW_SETUP_PHASE(ti, PH_STAT); 1599274760Sjhb regv = nsp_cr_read_1(sc->port_res, NSPR_DATA); 1600274760Sjhb if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE) 160179697Snon { 1602274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_PARITYR, 160379697Snon PARITYR_ENABLE | PARITYR_CLEAR); 160479697Snon derror = SCSI_LOW_DATA_PE; 160579697Snon } 160679697Snon else 160779697Snon derror = 0; 160879697Snon 160979697Snon /* assert ACK */ 1610274760Sjhb cr = SCBUSCR_ACK | nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR); 1611274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 161279697Snon 161379697Snon if (scsi_low_statusin(slp, ti, derror | regv) != 0) 161479697Snon { 161579697Snon scsi_low_attention(slp); 161679697Snon } 161779697Snon 161879697Snon /* check REQ nagated */ 161979697Snon nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>"); 162079697Snon 162179697Snon /* deassert ACK */ 1622274760Sjhb cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 1623274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 162467468Snon break; 162567468Snon 162679697Snon case IRQPHS_MSGOUT: 162779697Snon if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0) 162879697Snon return 1; 162967468Snon 163079697Snon#ifdef NSP_MSGOUT_SERIALIZE 163167468Snon /* 163267468Snon * XXX: NSP QUIRK 163367468Snon * NSP invoke interrupts only in the case of scsi phase changes, 163467468Snon * therefore we should poll the scsi phase here to catch 163567468Snon * the next "msg out" if exists (no scsi phase changes). 163667468Snon */ 163767468Snon rv = len = 16; 163867468Snon do { 163967468Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 164079697Snon flags = (ti->ti_ophase != ti->ti_phase) ? 164179697Snon SCSI_LOW_MSGOUT_INIT : 0; 164279697Snon len = scsi_low_msgout(slp, ti, flags); 164367468Snon 164479697Snon if (len > 1 && slp->sl_atten == 0) 164567468Snon { 164679697Snon scsi_low_attention(slp); 164779697Snon } 164879697Snon 164979697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 165079697Snon slp->sl_clear_atten) != 0) 165179697Snon { 165279697Snon slp->sl_error |= FATALIO; 165379697Snon nsp_error(sc, "MSGOUT: xfer short", 165467468Snon isrc, ph, irqphs); 165567468Snon } 165667468Snon 165767468Snon /* catch a next signal */ 165867468Snon rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ); 165967468Snon } 166067468Snon while (rv > 0 && len -- > 0); 166179697Snon 166279697Snon#else /* !NSP_MSGOUT_SERIALIZE */ 166379697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 166479697Snon flags = SCSI_LOW_MSGOUT_UNIFY; 166579697Snon if (ti->ti_ophase != ti->ti_phase) 166679697Snon flags |= SCSI_LOW_MSGOUT_INIT; 166779697Snon len = scsi_low_msgout(slp, ti, flags); 166879697Snon 166979697Snon if (len > 1 && slp->sl_atten == 0) 167079697Snon { 167179697Snon scsi_low_attention(slp); 167279697Snon } 167379697Snon 167479697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 167579697Snon slp->sl_clear_atten) != 0) 167679697Snon { 167779697Snon nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs); 167879697Snon } 167979697Snon 168079697Snon#endif /* !NSP_MSGOUT_SERIALIZE */ 168167468Snon break; 168267468Snon 168379697Snon case IRQPHS_MSGIN: 168479697Snon if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0) 168579697Snon return 1; 168667468Snon 168767468Snon /* 168867468Snon * XXX: NSP QUIRK 168967468Snon * NSP invoke interrupts only in the case of scsi phase changes, 169067468Snon * therefore we should poll the scsi phase here to catch 169167468Snon * the next "msg in" if exists (no scsi phase changes). 169267468Snon */ 169367468Snon rv = len = 16; 169467468Snon do { 169579697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); 169679697Snon 169767468Snon /* read a data */ 1698274760Sjhb regv = nsp_cr_read_1(sc->port_res, NSPR_DATA); 1699274760Sjhb if (nsp_cr_read_1(sc->port_res, NSPR_PARITYR) & PARITYR_PE) 170079697Snon { 1701274760Sjhb nsp_cr_write_1(sc->port_res, 170279697Snon NSPR_PARITYR, 170379697Snon PARITYR_ENABLE | PARITYR_CLEAR); 170479697Snon derror = SCSI_LOW_DATA_PE; 170579697Snon } 170679697Snon else 170779697Snon { 170879697Snon derror = 0; 170979697Snon } 171067468Snon 171167468Snon /* assert ack */ 1712274760Sjhb cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) | SCBUSCR_ACK; 1713274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 171479697Snon 171579697Snon if (scsi_low_msgin(slp, ti, regv | derror) == 0) 171679697Snon { 171779697Snon if (scsi_low_is_msgout_continue(ti, 0) != 0) 171879697Snon { 171979697Snon scsi_low_attention(slp); 172079697Snon } 172179697Snon } 172279697Snon 172379697Snon /* check REQ nagated */ 172467468Snon nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>"); 172567468Snon 172667468Snon /* deassert ack */ 1727274760Sjhb cr = nsp_cr_read_1(sc->port_res, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 1728274760Sjhb nsp_cr_write_1(sc->port_res, NSPR_SCBUSCR, cr); 172967468Snon 173067468Snon /* catch a next signal */ 173167468Snon rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ); 173267468Snon } 173367468Snon while (rv > 0 && len -- > 0); 173467468Snon break; 173567468Snon 173667468Snon default: 173779697Snon slp->sl_error |= FATALIO; 173879697Snon nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs); 173967468Snon break; 174067468Snon } 174167468Snon 174267468Snon return 1; 174367468Snon 174479697Snon#if 0 174567468Snontimerout: 174679697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 174767468Snon return 0; 174879697Snon#endif 174967468Snon} 175079697Snon 175179697Snonstatic int 175279697Snonnsp_timeout(sc) 175379697Snon struct nsp_softc *sc; 175479697Snon{ 175579697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 175679697Snon int tout; 175779697Snon u_int8_t ph, regv; 175879697Snon 175979697Snon if (slp->sl_Tnexus == NULL) 176079697Snon return 0; 176179697Snon 1762274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 176379697Snon switch (ph & SCBUSMON_PHMASK) 176479697Snon { 176579697Snon case PHASE_DATAOUT: 176679697Snon if (sc->sc_dataout_timeout == 0) 176779697Snon break; 176879697Snon 176979697Snon /* check a fifo empty */ 1770274760Sjhb regv = bus_read_1(sc->port_res, nsp_fifosr); 177179697Snon if ((regv & FIFOSR_FULLEMP) == 0) 177279697Snon break; 1773274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_FIFOCL); 177479697Snon 177579697Snon /* check still requested */ 1776274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 177779697Snon if ((ph & SCBUSMON_REQ) == 0) 177879697Snon break; 177979697Snon /* check timeout */ 178079697Snon if ((-- sc->sc_dataout_timeout) > 0) 178179697Snon break; 178279697Snon 178379697Snon slp->sl_error |= PDMAERR; 178479697Snon if ((slp->sl_flags & HW_WRITE_PADDING) == 0) 178579697Snon { 1786240325Sjhb device_printf(slp->sl_dev, "write padding required\n"); 178779697Snon break; 178879697Snon } 178979697Snon 179079697Snon tout = NSP_DELAY_MAX; 179179697Snon while (tout -- > 0) 179279697Snon { 1793274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 179479697Snon if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT) 179579697Snon break; 1796274760Sjhb regv = bus_read_1(sc->port_res, nsp_fifosr); 179779697Snon if ((regv & FIFOSR_FULLEMP) == 0) 179879697Snon { 1799240172Sjhb DELAY(1); 180079697Snon continue; 180179697Snon } 180279697Snon 1803274760Sjhb bus_write_1(sc->port_res, nsp_irqcr, IRQCR_FIFOCL); 180479697Snon nsp_data_padding(sc, SCSI_LOW_WRITE, 32); 180579697Snon } 1806274760Sjhb ph = nsp_cr_read_1(sc->port_res, NSPR_SCBUSMON); 180779697Snon if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT) 180879697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 180979697Snon break; 181079697Snon 181179697Snon default: 181279697Snon break; 181379697Snon } 181479697Snon return 0; 181579697Snon} 1816