nsp.c revision 79697
167468Snon/* $FreeBSD: head/sys/dev/nsp/nsp.c 79697 2001-07-14 00:38:51Z non $ */ 279697Snon/* $NecBSD: nsp.c,v 1.21.12.6 2001/06/29 06:27:52 honda Exp $ */ 367468Snon/* $NetBSD$ */ 467468Snon 567468Snon#define NSP_DEBUG 667468Snon#define NSP_STATICS 779697Snon#define NSP_IO_CONTROL_FLAGS \ 879697Snon (NSP_READ_SUSPEND_IO | NSP_WRITE_SUSPEND_IO | \ 979697Snon NSP_READ_FIFO_INTERRUPTS | NSP_WRITE_FIFO_INTERRUPTS | \ 1079697Snon NSP_USE_MEMIO | NSP_WAIT_FOR_SELECT) 1167468Snon 1267468Snon/* 1379697Snon * Copyright (c) 1998, 1999, 2000, 2001 1467468Snon * NetBSD/pc98 porting staff. All rights reserved. 1579697Snon * 1679697Snon * Copyright (c) 1998, 1999, 2000, 2001 1779697Snon * Naofumi HONDA. All rights reserved. 1867468Snon * 1967468Snon * Redistribution and use in source and binary forms, with or without 2067468Snon * modification, are permitted provided that the following conditions 2167468Snon * are met: 2267468Snon * 1. Redistributions of source code must retain the above copyright 2367468Snon * notice, this list of conditions and the following disclaimer. 2467468Snon * 2. Redistributions in binary form must reproduce the above copyright 2567468Snon * notice, this list of conditions and the following disclaimer in the 2667468Snon * documentation and/or other materials provided with the distribution. 2767468Snon * 3. The name of the author may not be used to endorse or promote products 2867468Snon * derived from this software without specific prior written permission. 2967468Snon * 3067468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 3167468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3267468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 3367468Snon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 3467468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3567468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3667468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3767468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3867468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3967468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4067468Snon * POSSIBILITY OF SUCH DAMAGE. 4167468Snon */ 4267468Snon#include "opt_ddb.h" 4367468Snon 4467468Snon#include <sys/param.h> 4567468Snon#include <sys/systm.h> 4667468Snon#include <sys/kernel.h> 4767468Snon#if defined(__FreeBSD__) && __FreeBSD_version > 500001 4867468Snon#include <sys/bio.h> 4979697Snon#endif /* __ FreeBSD__ */ 5067468Snon#include <sys/buf.h> 5167468Snon#include <sys/queue.h> 5267468Snon#include <sys/malloc.h> 5367468Snon#include <sys/errno.h> 5467468Snon 5567468Snon#ifdef __NetBSD__ 5679697Snon#include <sys/device.h> 5767468Snon#include <machine/bus.h> 5867468Snon#include <machine/intr.h> 5967468Snon 6067468Snon#include <dev/scsipi/scsi_all.h> 6167468Snon#include <dev/scsipi/scsipi_all.h> 6267468Snon#include <dev/scsipi/scsiconf.h> 6367468Snon#include <dev/scsipi/scsi_disk.h> 6467468Snon 6567468Snon#include <machine/dvcfg.h> 6667468Snon#include <machine/physio_proc.h> 6767468Snon 6867468Snon#include <i386/Cbus/dev/scsi_low.h> 6967468Snon#include <i386/Cbus/dev/nspreg.h> 7067468Snon#include <i386/Cbus/dev/nspvar.h> 7167468Snon#endif /* __NetBSD__ */ 7267468Snon 7367468Snon#ifdef __FreeBSD__ 7467468Snon#include <machine/clock.h> 7567468Snon#include <machine/cpu.h> 7667468Snon#include <machine/bus_pio.h> 7767468Snon#include <machine/bus_memio.h> 7867468Snon#include <machine/bus.h> 7967468Snon 8067468Snon#include <machine/dvcfg.h> 8167468Snon#include <machine/physio_proc.h> 8267468Snon 8367468Snon#include <cam/scsi/scsi_low.h> 8467468Snon#include <dev/nsp/nspreg.h> 8567468Snon#include <dev/nsp/nspvar.h> 8667468Snon 8767468Snon#if __FreeBSD_version < 400001 8867468Snon#include "nsp.h" 8967468Snonstruct nsp_softc *nspdata[NNSP]; 9067468Snon#endif 9167468Snon#endif /* __FreeBSD__ */ 9267468Snon 9367468Snon/*************************************************** 9467468Snon * USER SETTINGS 9567468Snon ***************************************************/ 9667468Snon/* DEVICE CONFIGURATION FLAGS (MINOR) 9767468Snon * 9867468Snon * 0x01 DISCONECT OFF 9967468Snon * 0x02 PARITY LINE OFF 10067468Snon * 0x04 IDENTIFY MSG OFF ( = single lun) 10167468Snon * 0x08 SYNC TRANSFER OFF 10267468Snon */ 10367468Snon 10467468Snon/*************************************************** 10567468Snon * PARAMS 10667468Snon ***************************************************/ 10767468Snon#define NSP_NTARGETS 8 10867468Snon#define NSP_NLUNS 8 10967468Snon 11079697Snon#define NSP_MAX_DATA_SIZE (64 * 1024) 11179697Snon#define NSP_SELTIMEOUT (200) 11279697Snon#define NSP_DELAY_MAX (2 * 1000 * 1000) 11379697Snon#define NSP_DELAY_INTERVAL (1) 11479697Snon#define NSP_TIMER_1MS (1000 / 51) 11567468Snon 11667468Snon/*************************************************** 11767468Snon * DEBUG 11867468Snon ***************************************************/ 11967468Snon#ifdef NSP_DEBUG 12067468Snonint nsp_debug; 12167468Snon#endif /* NSP_DEBUG */ 12267468Snon 12367468Snon#ifdef NSP_STATICS 12467468Snonstruct nsp_statics { 12579697Snon int arbit_conflict_1; 12679697Snon int arbit_conflict_2; 12779697Snon int device_data_write; 12879697Snon int device_busy; 12967468Snon int disconnect; 13067468Snon int reselect; 13167468Snon int data_phase_bypass; 13279697Snon} nsp_statics; 13367468Snon#endif /* NSP_STATICS */ 13467468Snon 13567468Snon/*************************************************** 13679697Snon * IO control 13767468Snon ***************************************************/ 13879697Snon#define NSP_READ_SUSPEND_IO 0x0001 13979697Snon#define NSP_WRITE_SUSPEND_IO 0x0002 14079697Snon#define NSP_USE_MEMIO 0x0004 14179697Snon#define NSP_READ_FIFO_INTERRUPTS 0x0010 14279697Snon#define NSP_WRITE_FIFO_INTERRUPTS 0x0020 14379697Snon#define NSP_WAIT_FOR_SELECT 0x0100 14479697Snon 14579697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS; 14679697Snonint nsp_read_suspend_bytes = DEV_BSIZE; 14779697Snonint nsp_write_suspend_bytes = DEV_BSIZE; 14879697Snonint nsp_read_interrupt_bytes = 4096; 14979697Snonint nsp_write_interrupt_bytes = 4096; 15079697Snon 15179697Snon/*************************************************** 15279697Snon * DEVICE STRUCTURE 15379697Snon ***************************************************/ 15467468Snonextern struct cfdriver nsp_cd; 15567468Snon 15667468Snon/************************************************************** 15767468Snon * DECLARE 15867468Snon **************************************************************/ 15979697Snon#define NSP_FIFO_ON 1 16079697Snon#define NSP_FIFO_OFF 0 16179697Snonstatic void nsp_pio_read __P((struct nsp_softc *, int)); 16279697Snonstatic void nsp_pio_write __P((struct nsp_softc *, int)); 16379697Snonstatic int nsp_xfer __P((struct nsp_softc *, u_int8_t *, int, int, int)); 16467468Snonstatic int nsp_msg __P((struct nsp_softc *, struct targ_info *, u_int)); 16567468Snonstatic int nsp_reselected __P((struct nsp_softc *)); 16679697Snonstatic int nsp_disconnected __P((struct nsp_softc *, struct targ_info *)); 16779697Snonstatic void nsp_pdma_end __P((struct nsp_softc *, struct targ_info *)); 16867468Snonstatic void nsphw_init __P((struct nsp_softc *)); 16979697Snonstatic int nsp_target_nexus_establish __P((struct nsp_softc *)); 17079697Snonstatic int nsp_lun_nexus_establish __P((struct nsp_softc *)); 17179697Snonstatic int nsp_ccb_nexus_establish __P((struct nsp_softc *)); 17267468Snonstatic int nsp_world_start __P((struct nsp_softc *, int)); 17367468Snonstatic int nsphw_start_selection __P((struct nsp_softc *sc, struct slccb *)); 17467468Snonstatic void nsphw_bus_reset __P((struct nsp_softc *)); 17567468Snonstatic void nsphw_attention __P((struct nsp_softc *)); 17667468Snonstatic u_int nsp_fifo_count __P((struct nsp_softc *)); 17779697Snonstatic u_int nsp_request_count __P((struct nsp_softc *)); 17867468Snonstatic int nsp_negate_signal __P((struct nsp_softc *, u_int8_t, u_char *)); 17967468Snonstatic int nsp_expect_signal __P((struct nsp_softc *, u_int8_t, u_int8_t)); 18079697Snonstatic void nsp_start_timer __P((struct nsp_softc *, int)); 18179697Snonstatic void nsp_setup_fifo __P((struct nsp_softc *, int, int, int)); 18279697Snonstatic int nsp_targ_init __P((struct nsp_softc *, struct targ_info *, int)); 18379697Snonstatic void nsphw_selection_done_and_expect_msgout __P((struct nsp_softc *)); 18479697Snonstatic void nsp_data_padding __P((struct nsp_softc *, int, u_int)); 18579697Snonstatic int nsp_timeout __P((struct nsp_softc *)); 18679697Snonstatic int nsp_read_fifo __P((struct nsp_softc *, int)); 18779697Snonstatic int nsp_write_fifo __P((struct nsp_softc *, int)); 18879697Snonstatic int nsp_phase_match __P((struct nsp_softc *, u_int8_t, u_int8_t)); 18979697Snonstatic int nsp_wait_interrupt __P((struct nsp_softc *)); 19067468Snon 19167468Snonstruct scsi_low_funcs nspfuncs = { 19267468Snon SC_LOW_INIT_T nsp_world_start, 19367468Snon SC_LOW_BUSRST_T nsphw_bus_reset, 19473025Snon SC_LOW_TARG_INIT_T nsp_targ_init, 19579697Snon SC_LOW_LUN_INIT_T NULL, 19667468Snon 19767468Snon SC_LOW_SELECT_T nsphw_start_selection, 19879697Snon SC_LOW_NEXUS_T nsp_lun_nexus_establish, 19979697Snon SC_LOW_NEXUS_T nsp_ccb_nexus_establish, 20067468Snon 20167468Snon SC_LOW_ATTEN_T nsphw_attention, 20267468Snon SC_LOW_MSG_T nsp_msg, 20367468Snon 20479697Snon SC_LOW_TIMEOUT_T nsp_timeout, 20567468Snon SC_LOW_POLL_T nspintr, 20667468Snon 20767468Snon NULL, 20867468Snon}; 20967468Snon 21067468Snon/**************************************************** 21167468Snon * hwfuncs 21267468Snon ****************************************************/ 21367468Snonstatic __inline u_int8_t nsp_cr_read_1 __P((bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs)); 21467468Snonstatic __inline void nsp_cr_write_1 __P((bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs, u_int8_t va)); 21567468Snon 21667468Snonstatic __inline u_int8_t 21767468Snonnsp_cr_read_1(bst, bsh, ofs) 21867468Snon bus_space_tag_t bst; 21967468Snon bus_space_handle_t bsh; 22067468Snon bus_addr_t ofs; 22167468Snon{ 22267468Snon 22367468Snon bus_space_write_1(bst, bsh, nsp_idxr, ofs); 22467468Snon return bus_space_read_1(bst, bsh, nsp_datar); 22567468Snon} 22667468Snon 22767468Snonstatic __inline void 22867468Snonnsp_cr_write_1(bst, bsh, ofs, va) 22967468Snon bus_space_tag_t bst; 23067468Snon bus_space_handle_t bsh; 23167468Snon bus_addr_t ofs; 23267468Snon u_int8_t va; 23367468Snon{ 23467468Snon 23567468Snon bus_space_write_1(bst, bsh, nsp_idxr, ofs); 23667468Snon bus_space_write_1(bst, bsh, nsp_datar, va); 23767468Snon} 23867468Snon 23967468Snonstatic int 24067468Snonnsp_expect_signal(sc, curphase, mask) 24167468Snon struct nsp_softc *sc; 24267468Snon u_int8_t curphase, mask; 24367468Snon{ 24467468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 24567468Snon bus_space_tag_t bst = sc->sc_iot; 24667468Snon bus_space_handle_t bsh = sc->sc_ioh; 24779697Snon int wc; 24873025Snon u_int8_t ph, isrc; 24967468Snon 25079697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 25167468Snon { 25267468Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 25379697Snon if (ph == (u_int8_t) -1) 25479697Snon return -1; 25579697Snon 25667468Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 25779697Snon if (isrc & IRQSR_SCSI) 25879697Snon return 0; 25967468Snon 26079697Snon if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase) 26179697Snon return 1; 26279697Snon 26379697Snon SCSI_LOW_DELAY(NSP_DELAY_INTERVAL); 26467468Snon } 26567468Snon 26679697Snon printf("%s: nsp_expect_signal timeout\n", slp->sl_xname); 26779697Snon return -1; 26867468Snon} 26967468Snon 27067468Snonstatic void 27167468Snonnsphw_init(sc) 27267468Snon struct nsp_softc *sc; 27367468Snon{ 27467468Snon bus_space_tag_t bst = sc->sc_iot; 27567468Snon bus_space_handle_t bsh = sc->sc_ioh; 27667468Snon 27767468Snon /* block all interrupts */ 27867468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK); 27967468Snon 28067468Snon /* setup SCSI interface */ 28167468Snon bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_IFSEL); 28267468Snon 28367468Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, 0); 28467468Snon 28567468Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8); 28667468Snon nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_iclkdiv); 28767468Snon 28867468Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 28979697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, sc->sc_parr); 29067468Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, 29167468Snon PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS); 29267468Snon 29367468Snon /* setup fifo asic */ 29467468Snon bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_REGSEL); 29567468Snon nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, 0); 29667468Snon if ((nsp_cr_read_1(bst, bsh, NSPR_OCR) & OCR_TERMPWRS) == 0) 29767468Snon nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, TERMPWRC_POWON); 29867468Snon 29967468Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8); 30067468Snon nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_clkdiv); 30167468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 30267468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 30367468Snon 30467468Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, 0); 30567468Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, 0); 30667468Snon 30767468Snon /* enable interrupts and ack them */ 30879697Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 30967468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); 31067468Snon 31179697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 31267468Snon} 31367468Snon 31467468Snon/**************************************************** 31567468Snon * scsi low interface 31667468Snon ****************************************************/ 31767468Snonstatic void 31867468Snonnsphw_attention(sc) 31967468Snon struct nsp_softc *sc; 32067468Snon{ 32167468Snon bus_space_tag_t bst = sc->sc_iot; 32267468Snon bus_space_handle_t bsh = sc->sc_ioh; 32367468Snon u_int8_t cr; 32467468Snon 32567468Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR)/* & ~SCBUSCR_ACK */; 32667468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ATN); 32779697Snon SCSI_LOW_DELAY(10); 32867468Snon} 32967468Snon 33067468Snonstatic void 33167468Snonnsphw_bus_reset(sc) 33267468Snon struct nsp_softc *sc; 33367468Snon{ 33467468Snon bus_space_tag_t bst = sc->sc_iot; 33567468Snon bus_space_handle_t bsh = sc->sc_ioh; 33667468Snon int i; 33767468Snon 33867468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK); 33967468Snon 34067468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_RST); 34179697Snon SCSI_LOW_DELAY(100 * 1000); /* 100ms */ 34267468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0); 34367468Snon for (i = 0; i < 5; i ++) 34467468Snon (void) nsp_cr_read_1(bst, bsh, NSPR_IRQPHS); 34567468Snon 34667468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); 34767468Snon} 34867468Snon 34979697Snonstatic void 35079697Snonnsphw_selection_done_and_expect_msgout(sc) 35171468Sjhb struct nsp_softc *sc; 35271468Sjhb{ 35379697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 35471468Sjhb bus_space_tag_t bst = sc->sc_iot; 35571468Sjhb bus_space_handle_t bsh = sc->sc_ioh; 35671468Sjhb 35779697Snon /* clear ack counter */ 35879697Snon sc->sc_cnt = 0; 35979697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 36079697Snon PTCLRR_REQ | PTCLRR_HOST); 36179697Snon 36279697Snon /* deassert sel and assert atten */ 36379697Snon sc->sc_seltout = 0; 36479697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc); 36579697Snon SCSI_LOW_DELAY(1); 36679697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 36779697Snon sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN); 36879697Snon SCSI_LOW_ASSERT_ATN(slp); 36971468Sjhb} 37071468Sjhb 37167468Snonstatic int 37267468Snonnsphw_start_selection(sc, cb) 37367468Snon struct nsp_softc *sc; 37467468Snon struct slccb *cb; 37567468Snon{ 37667468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 37767468Snon bus_space_tag_t bst = sc->sc_iot; 37867468Snon bus_space_handle_t bsh = sc->sc_ioh; 37967468Snon struct targ_info *ti = cb->ti; 38067468Snon register u_int8_t arbs, ph; 38179697Snon int s, wc; 38267468Snon 38379697Snon wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 38479697Snon sc->sc_dataout_timeout = 0; 38579697Snon 38667468Snon /* check bus free */ 38779697Snon s = splhigh(); 38879697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 38979697Snon if (ph != SCBUSMON_FREE) 39067468Snon { 39167468Snon splx(s); 39279697Snon#ifdef NSP_STATICS 39379697Snon nsp_statics.arbit_conflict_1 ++; 39479697Snon#endif /* NSP_STATICS */ 39579697Snon return SCSI_LOW_START_FAIL; 39667468Snon } 39767468Snon 39867468Snon /* start arbitration */ 39979697Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_EXEC); 40079697Snon splx(s); 40179697Snon 40267468Snon SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); 40367468Snon do 40467468Snon { 40567468Snon /* XXX: what a stupid chip! */ 40667468Snon arbs = nsp_cr_read_1(bst, bsh, NSPR_ARBITS); 40779697Snon SCSI_LOW_DELAY(1); 40867468Snon } 40973025Snon while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0); 41067468Snon 41167468Snon if ((arbs & ARBITS_WIN) == 0) 41267468Snon { 41367468Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); 41479697Snon#ifdef NSP_STATICS 41579697Snon nsp_statics.arbit_conflict_2 ++; 41679697Snon#endif /* NSP_STATICS */ 41767468Snon return SCSI_LOW_START_FAIL; 41867468Snon } 41967468Snon 42067468Snon /* assert select line */ 42167468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); 42279697Snon scsi_low_arbit_win(slp); 42379697Snon 42479697Snon s = splhigh(); 42579697Snon SCSI_LOW_DELAY(3); 42667468Snon nsp_cr_write_1(bst, bsh, NSPR_DATA, 42767468Snon sc->sc_idbit | (1 << ti->ti_id)); 42867468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 42967468Snon SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc); 43079697Snon SCSI_LOW_DELAY(3); 43167468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL | 43267468Snon SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc); 43367468Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); 43479697Snon SCSI_LOW_DELAY(3); 43567468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 43667468Snon SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc); 43779697Snon SCSI_LOW_DELAY(1); 43867468Snon 43979697Snon if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0) 44079697Snon { 44179697Snon#define NSP_FIRST_SEL_WAIT 300 44279697Snon#define NSP_SEL_CHECK_INTERVAL 10 44379697Snon 44479697Snon /* wait for a selection response */ 44579697Snon for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL; 44679697Snon wc ++) 44779697Snon { 44879697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 44979697Snon if ((ph & SCBUSMON_BSY) == 0) 45079697Snon { 45179697Snon SCSI_LOW_DELAY(NSP_SEL_CHECK_INTERVAL); 45279697Snon continue; 45379697Snon } 45479697Snon 45579697Snon SCSI_LOW_DELAY(1); 45679697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 45779697Snon if ((ph & SCBUSMON_BSY) != 0) 45879697Snon { 45979697Snon nsphw_selection_done_and_expect_msgout(sc); 46079697Snon splx(s); 46179697Snon 46279697Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 46379697Snon return SCSI_LOW_START_OK; 46479697Snon } 46579697Snon } 46679697Snon } 46779697Snon splx(s); 46879697Snon 46979697Snon /* check a selection timeout */ 47079697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 47167468Snon sc->sc_seltout = 1; 47267468Snon return SCSI_LOW_START_OK; 47367468Snon} 47467468Snon 47567468Snonstatic int 47667468Snonnsp_world_start(sc, fdone) 47767468Snon struct nsp_softc *sc; 47867468Snon int fdone; 47967468Snon{ 48067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 48167468Snon 48267468Snon sc->sc_cnt = 0; 48367468Snon sc->sc_seltout = 0; 48479697Snon 48567468Snon if ((slp->sl_cfgflags & CFG_NOATTEN) == 0) 48667468Snon sc->sc_busc = SCBUSCR_ATN; 48767468Snon else 48867468Snon sc->sc_busc = 0; 48979697Snon 49079697Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0) 49179697Snon sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR; 49279697Snon else 49379697Snon sc->sc_parr = 0; 49479697Snon 49567468Snon sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST); 49667468Snon 49767468Snon nsphw_init(sc); 49867468Snon scsi_low_bus_reset(slp); 49967468Snon 50067468Snon SOFT_INTR_REQUIRED(slp); 50167468Snon return 0; 50267468Snon} 50367468Snon 50467468Snonstruct ncp_synch_data { 50567468Snon u_int min_period; 50667468Snon u_int max_period; 50767468Snon u_int chip_period; 50867468Snon u_int ack_width; 50967468Snon}; 51067468Snon 51167468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = { 51267468Snon {0x0c,0x0c,0x1,0}, /* 20MB 50ns*/ 51367468Snon {0x19,0x19,0x3,1}, /* 10MB 100ns*/ 51467468Snon {0x1a,0x25,0x5,2}, /* 7.5MB 150ns*/ 51567468Snon {0x26,0x32,0x7,3}, /* 5MB 200ns*/ 51667468Snon {0x0, 0, 0, 0} 51767468Snon}; 51867468Snon 51967468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = { 52067468Snon {0x19,0x19,0x1,0}, /* 10MB 100ns*/ 52167468Snon {0x1a,0x25,0x2,0}, /* 7.5MB 150ns*/ 52267468Snon {0x26,0x32,0x3,1}, /* 5MB 200ns*/ 52367468Snon {0x0, 0, 0, 0} 52467468Snon}; 52567468Snon 52667468Snonstatic int 52767468Snonnsp_msg(sc, ti, msg) 52867468Snon struct nsp_softc *sc; 52967468Snon struct targ_info *ti; 53067468Snon u_int msg; 53167468Snon{ 53279697Snon bus_space_tag_t bst = sc->sc_iot; 53379697Snon bus_space_handle_t bsh = sc->sc_ioh; 53467468Snon struct ncp_synch_data *sdp; 53573025Snon struct nsp_targ_info *nti = (void *) ti; 53667468Snon u_int period, offset; 53779697Snon int i, error; 53867468Snon 53979697Snon if ((msg & SCSI_LOW_MSG_WIDE) != 0) 54079697Snon { 54179697Snon if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) 54279697Snon { 54379697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 54479697Snon return EINVAL; 54579697Snon } 54679697Snon return 0; 54779697Snon } 54879697Snon 54967468Snon if ((msg & SCSI_LOW_MSG_SYNCH) == 0) 55067468Snon return 0; 55167468Snon 55273025Snon period = ti->ti_maxsynch.period; 55373025Snon offset = ti->ti_maxsynch.offset; 55467468Snon if (sc->sc_iclkdiv == CLKDIVR_20M) 55567468Snon sdp = &ncp_sync_data_20M[0]; 55667468Snon else 55767468Snon sdp = &ncp_sync_data_40M[0]; 55867468Snon 55967468Snon for (i = 0; sdp->max_period != 0; i ++, sdp ++) 56067468Snon { 56167468Snon if (period >= sdp->min_period && period <= sdp->max_period) 56267468Snon break; 56367468Snon } 56467468Snon 56567468Snon if (period != 0 && sdp->max_period == 0) 56667468Snon { 56767468Snon /* 56867468Snon * NO proper period/offset found, 56967468Snon * Retry neg with the target. 57067468Snon */ 57173025Snon ti->ti_maxsynch.period = 0; 57273025Snon ti->ti_maxsynch.offset = 0; 57373025Snon nti->nti_reg_syncr = 0; 57473025Snon nti->nti_reg_ackwidth = 0; 57579697Snon error = EINVAL; 57667468Snon } 57779697Snon else 57879697Snon { 57979697Snon nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) | 58079697Snon (offset & SYNCR_OFFM); 58179697Snon nti->nti_reg_ackwidth = sdp->ack_width; 58279697Snon error = 0; 58379697Snon } 58467468Snon 58579697Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); 58679697Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 58779697Snon return error; 58867468Snon} 58967468Snon 59067468Snonstatic int 59179697Snonnsp_targ_init(sc, ti, action) 59267468Snon struct nsp_softc *sc; 59367468Snon struct targ_info *ti; 59479697Snon int action; 59567468Snon{ 59673025Snon struct nsp_targ_info *nti = (void *) ti; 59767468Snon 59879697Snon if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) 59979697Snon { 60079697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 60179697Snon ti->ti_maxsynch.period = 100 / 4; 60279697Snon ti->ti_maxsynch.offset = 15; 60379697Snon nti->nti_reg_syncr = 0; 60479697Snon nti->nti_reg_ackwidth = 0; 60579697Snon } 60667468Snon return 0; 60767468Snon} 60867468Snon 60979697Snonstatic void 61079697Snonnsp_start_timer(sc, time) 61179697Snon struct nsp_softc *sc; 61279697Snon int time; 61379697Snon{ 61479697Snon bus_space_tag_t bst = sc->sc_iot; 61579697Snon bus_space_handle_t bsh = sc->sc_ioh; 61679697Snon 61779697Snon sc->sc_timer = time; 61879697Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time); 61979697Snon} 62079697Snon 62167468Snon/************************************************************** 62267468Snon * General probe attach 62367468Snon **************************************************************/ 62467468Snonint 62567468Snonnspprobesubr(iot, ioh, dvcfg) 62667468Snon bus_space_tag_t iot; 62767468Snon bus_space_handle_t ioh; 62867468Snon u_int dvcfg; 62967468Snon{ 63067468Snon u_int8_t regv; 63167468Snon 63267468Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 63367468Snon if (regv < 0x11 || regv >= 0x20) 63467468Snon return 0; 63567468Snon return 1; 63667468Snon} 63767468Snon 63867468Snonint 63967468Snonnspprint(aux, name) 64067468Snon void *aux; 64167468Snon const char *name; 64267468Snon{ 64367468Snon 64467468Snon if (name != NULL) 64567468Snon printf("%s: scsibus ", name); 64667468Snon return UNCONF; 64767468Snon} 64867468Snon 64967468Snonvoid 65067468Snonnspattachsubr(sc) 65167468Snon struct nsp_softc *sc; 65267468Snon{ 65367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 65467468Snon 65567468Snon printf("\n"); 65667468Snon 65767468Snon sc->sc_idbit = (1 << slp->sl_hostid); 65879697Snon slp->sl_flags |= HW_READ_PADDING; 65967468Snon slp->sl_funcs = &nspfuncs; 66079697Snon sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ 66167468Snon 66279697Snon (void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS, 66379697Snon sizeof(struct nsp_targ_info), 0); 66467468Snon} 66567468Snon 66667468Snon/************************************************************** 66767468Snon * PDMA functions 66867468Snon **************************************************************/ 66967468Snonstatic u_int 67067468Snonnsp_fifo_count(sc) 67167468Snon struct nsp_softc *sc; 67267468Snon{ 67367468Snon bus_space_tag_t bst = sc->sc_iot; 67467468Snon bus_space_handle_t bsh = sc->sc_ioh; 67567468Snon u_int count; 67667468Snon 67779697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT); 67867468Snon count = bus_space_read_1(bst, bsh, nsp_datar); 67967468Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); 68067468Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); 68167468Snon return count; 68267468Snon} 68367468Snon 68479697Snonstatic u_int 68579697Snonnsp_request_count(sc) 68679697Snon struct nsp_softc *sc; 68779697Snon{ 68879697Snon bus_space_tag_t bst = sc->sc_iot; 68979697Snon bus_space_handle_t bsh = sc->sc_ioh; 69079697Snon u_int count; 69179697Snon 69279697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT); 69379697Snon count = bus_space_read_1(bst, bsh, nsp_datar); 69479697Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); 69579697Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); 69679697Snon return count; 69779697Snon} 69879697Snon 69967468Snonstatic void 70079697Snonnsp_setup_fifo(sc, on, direction, datalen) 70167468Snon struct nsp_softc *sc; 70267468Snon int on; 70379697Snon int direction; 70479697Snon int datalen; 70567468Snon{ 70667468Snon u_int8_t xfermode; 70767468Snon 70879697Snon sc->sc_suspendio = 0; 70979697Snon if (on == NSP_FIFO_OFF) 71079697Snon { 71179697Snon xfermode = XFERMR_IO8; 71279697Snon goto out; 71379697Snon } 71467468Snon 71579697Snon /* check if suspend io OK ? */ 71679697Snon if (datalen > 0) 71767468Snon { 71879697Snon if (direction == SCSI_LOW_READ) 71979697Snon { 72079697Snon if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 && 72179697Snon (datalen % nsp_read_suspend_bytes) == 0) 72279697Snon sc->sc_suspendio = nsp_read_suspend_bytes; 72379697Snon } 72479697Snon else 72579697Snon { 72679697Snon if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 && 72779697Snon (datalen % nsp_write_suspend_bytes) == 0) 72879697Snon sc->sc_suspendio = nsp_write_suspend_bytes; 72979697Snon } 73067468Snon } 73179697Snon 73279697Snon /* determine a transfer type */ 73379697Snon if (datalen < DEV_BSIZE || (datalen & 3) != 0) 73479697Snon { 73579697Snon if (sc->sc_memh != NULL && 73679697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 73779697Snon xfermode = XFERMR_XEN | XFERMR_MEM8; 73879697Snon else 73979697Snon xfermode = XFERMR_XEN | XFERMR_IO8; 74079697Snon } 74167468Snon else 74267468Snon { 74379697Snon if (sc->sc_memh != NULL && 74479697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 74579697Snon xfermode = XFERMR_XEN | XFERMR_MEM32; 74667468Snon else 74779697Snon xfermode = XFERMR_XEN | XFERMR_IO32; 74879697Snon 74979697Snon if (sc->sc_suspendio > 0) 75079697Snon xfermode |= XFERMR_FIFOEN; 75167468Snon } 75267468Snon 75379697Snonout: 75467468Snon sc->sc_xfermr = xfermode; 75579697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_XFERMR, sc->sc_xfermr); 75667468Snon} 75767468Snon 75879697Snonstatic void 75967468Snonnsp_pdma_end(sc, ti) 76067468Snon struct nsp_softc *sc; 76167468Snon struct targ_info *ti; 76267468Snon{ 76367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 76479697Snon struct slccb *cb = slp->sl_Qnexus; 76567468Snon u_int len = 0, cnt; 76667468Snon 76779697Snon sc->sc_dataout_timeout = 0; 76867468Snon slp->sl_flags &= ~HW_PDMASTART; 76979697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 77079697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 77179697Snon { 77279697Snon sc->sc_icr &= ~SCIENR_FIFO; 77379697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_SCIENR, sc->sc_icr); 77479697Snon } 77567468Snon 77679697Snon if (cb == NULL) 77779697Snon { 77879697Snon slp->sl_error |= PDMAERR; 77979697Snon return; 78079697Snon } 78179697Snon 78267468Snon if (ti->ti_phase == PH_DATA) 78367468Snon { 78467468Snon cnt = nsp_fifo_count(sc); 78567468Snon if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) 78667468Snon { 78767468Snon len = sc->sc_cnt - cnt; 78879697Snon if (sc->sc_cnt >= cnt && 78979697Snon slp->sl_scp.scp_datalen + len <= 79067468Snon cb->ccb_scp.scp_datalen) 79167468Snon { 79267468Snon slp->sl_scp.scp_data -= len; 79367468Snon slp->sl_scp.scp_datalen += len; 79467468Snon } 79567468Snon else 79667468Snon { 79767468Snon slp->sl_error |= PDMAERR; 79867468Snon printf("%s len %x >= datalen %x\n", 79967468Snon slp->sl_xname, 80067468Snon len, slp->sl_scp.scp_datalen); 80167468Snon } 80267468Snon } 80367468Snon else if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 80467468Snon { 80579697Snon if (sc->sc_cnt != cnt || 80679697Snon sc->sc_cnt > cb->ccb_scp.scp_datalen) 80767468Snon { 80867468Snon slp->sl_error |= PDMAERR; 80979697Snon printf("%s: data read count error %x != %x (%x)\n", 81079697Snon slp->sl_xname, sc->sc_cnt, cnt, 81179697Snon cb->ccb_scp.scp_datalen); 81267468Snon } 81367468Snon } 81467468Snon sc->sc_cnt = cnt; 81579697Snon scsi_low_data_finish(slp); 81667468Snon } 81767468Snon else 81867468Snon { 81967468Snon 82067468Snon printf("%s data phase miss\n", slp->sl_xname); 82167468Snon slp->sl_error |= PDMAERR; 82267468Snon } 82367468Snon} 82467468Snon 82567468Snon#define RFIFO_CRIT 64 82679697Snon#define WFIFO_CRIT 32 82767468Snon 82867468Snonstatic void 82979697Snonnsp_data_padding(sc, direction, count) 83067468Snon struct nsp_softc *sc; 83179697Snon int direction; 83279697Snon u_int count; 83367468Snon{ 83479697Snon bus_space_tag_t bst = sc->sc_iot; 83579697Snon bus_space_handle_t bsh = sc->sc_ioh; 83679697Snon 83779697Snon if (count > NSP_MAX_DATA_SIZE) 83879697Snon count = NSP_MAX_DATA_SIZE; 83979697Snon 84079697Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8); 84179697Snon if (direction == SCSI_LOW_READ) 84279697Snon { 84379697Snon while (count -- > 0) 84479697Snon (void) bus_space_read_1(bst, bsh, nsp_fifodr); 84579697Snon } 84679697Snon else 84779697Snon { 84879697Snon while (count -- > 0) 84979697Snon (void) bus_space_write_1(bst, bsh, nsp_fifodr, 0); 85079697Snon } 85179697Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr); 85279697Snon} 85379697Snon 85479697Snonstatic int 85579697Snonnsp_read_fifo(sc, suspendio) 85679697Snon struct nsp_softc *sc; 85779697Snon int suspendio; 85879697Snon{ 85967468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 86067468Snon bus_space_tag_t bst = sc->sc_iot; 86167468Snon bus_space_handle_t bsh = sc->sc_ioh; 86279697Snon u_int res; 86367468Snon 86479697Snon res = nsp_fifo_count(sc); 86579697Snon if (res == sc->sc_cnt) 86679697Snon return 0; 86767468Snon 86879697Snon#ifdef NSP_DEBUG 86979697Snon if (res < sc->sc_cnt || res == (u_int) -1) 87067468Snon { 87179697Snon printf("%s: strange fifo ack count 0x%x < 0x%x\n", 87279697Snon slp->sl_xname, res, sc->sc_cnt); 87379697Snon return 0; 87479697Snon } 87579697Snon#endif /* NSP_DEBUG */ 87679697Snon 87779697Snon res = res - sc->sc_cnt; 87879697Snon if (res > slp->sl_scp.scp_datalen) 87979697Snon { 88079697Snon if ((slp->sl_error & PDMAERR) == 0) 88179697Snon { 88279697Snon printf("%s: data overrun 0x%x > 0x%x\n", 88379697Snon slp->sl_xname, res, slp->sl_scp.scp_datalen); 88479697Snon } 88579697Snon 88679697Snon slp->sl_error |= PDMAERR; 88779697Snon slp->sl_scp.scp_datalen = 0; 88879697Snon 88979697Snon if ((slp->sl_flags & HW_READ_PADDING) == 0) 89079697Snon { 89179697Snon printf("%s: read padding required\n", slp->sl_xname); 89279697Snon return 0; 89379697Snon } 89479697Snon 89579697Snon nsp_data_padding(sc, SCSI_LOW_READ, res); 89679697Snon sc->sc_cnt += res; 89779697Snon return 1; /* padding start */ 89879697Snon } 89979697Snon 90079697Snon if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio) 90179697Snon res = suspendio; 90279697Snon 90379697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 90479697Snon { 90579697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 90679697Snon { 90779697Snon res &= ~3; 90879697Snon bus_space_read_region_4(sc->sc_memt, sc->sc_memh, 0, 90979697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 91079697Snon } 91179697Snon else 91279697Snon { 91379697Snon bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 0, 91479697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 91579697Snon } 91679697Snon } 91779697Snon else 91879697Snon { 91979697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 92079697Snon { 92179697Snon res &= ~3; 92279697Snon bus_space_read_multi_4(bst, bsh, nsp_fifodr, 92379697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 92479697Snon } 92579697Snon else 92679697Snon { 92779697Snon bus_space_read_multi_1(bst, bsh, nsp_fifodr, 92879697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 92979697Snon } 93079697Snon } 93179697Snon 93279697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 93379697Snon { 93479697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, 93579697Snon PARITYR_ENABLE | PARITYR_CLEAR); 93679697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1); 93779697Snon } 93879697Snon 93979697Snon slp->sl_scp.scp_data += res; 94079697Snon slp->sl_scp.scp_datalen -= res; 94179697Snon sc->sc_cnt += res; 94279697Snon return 0; 94379697Snon} 94479697Snon 94579697Snonstatic int 94679697Snonnsp_write_fifo(sc, suspendio) 94779697Snon struct nsp_softc *sc; 94879697Snon int suspendio; 94979697Snon{ 95079697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 95179697Snon bus_space_tag_t bst = sc->sc_iot; 95279697Snon bus_space_handle_t bsh = sc->sc_ioh; 95379697Snon u_int res; 95479697Snon register u_int8_t stat; 95579697Snon 95679697Snon if (suspendio > 0) 95779697Snon { 95879697Snon#ifdef NSP_DEBUG 95979697Snon if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0) 96079697Snon { 96179697Snon printf("%s: strange write length 0x%x\n", 96279697Snon slp->sl_xname, slp->sl_scp.scp_datalen); 96379697Snon } 96479697Snon#endif /* NSP_DEBUG */ 96579697Snon res = slp->sl_scp.scp_datalen % suspendio; 96667468Snon if (res == 0) 96767468Snon { 96879697Snon res = suspendio; 96967468Snon } 97079697Snon } 97179697Snon else 97279697Snon { 97379697Snon res = WFIFO_CRIT; 97479697Snon } 97567468Snon 97679697Snon if (res > slp->sl_scp.scp_datalen) 97779697Snon res = slp->sl_scp.scp_datalen; 97867468Snon 97979697Snon /* XXX: reconfirm! */ 98079697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 98179697Snon if (stat != PHASE_DATAOUT) 98279697Snon return 0; 98367468Snon 98479697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 98579697Snon { 98679697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 98779697Snon { 98879697Snon bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 0, 98979697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 99079697Snon } 99167468Snon else 99279697Snon { 99379697Snon bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 0, 99479697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 99579697Snon } 99679697Snon } 99779697Snon else 99879697Snon { 99979697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 100079697Snon { 100179697Snon bus_space_write_multi_4(bst, bsh, nsp_fifodr, 100279697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 100379697Snon } 100479697Snon else 100579697Snon { 100679697Snon bus_space_write_multi_1(bst, bsh, nsp_fifodr, 100779697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 100879697Snon } 100979697Snon } 101067468Snon 101179697Snon slp->sl_scp.scp_datalen -= res; 101279697Snon slp->sl_scp.scp_data += res; 101379697Snon sc->sc_cnt += res; 101479697Snon return 0; 101579697Snon} 101679697Snon 101779697Snonstatic int 101879697Snonnsp_wait_interrupt(sc) 101979697Snon struct nsp_softc *sc; 102079697Snon{ 102179697Snon bus_space_tag_t bst = sc->sc_iot; 102279697Snon bus_space_handle_t bsh = sc->sc_ioh; 102379697Snon int tout; 102479697Snon register u_int8_t isrc; 102579697Snon 102679697Snon for (tout = 0; tout < DEV_BSIZE / 10; tout ++) 102779697Snon { 102879697Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 102979697Snon if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0) 103067468Snon { 103179697Snon if ((isrc & IRQSR_FIFO) != 0) 103279697Snon { 103379697Snon bus_space_write_1(bst, bsh, 103479697Snon nsp_irqcr, IRQCR_FIFOCL); 103579697Snon } 103679697Snon return 1; 103767468Snon } 103879697Snon SCSI_LOW_DELAY(1); 103979697Snon } 104079697Snon return 0; 104179697Snon} 104279697Snon 104379697Snonstatic void 104479697Snonnsp_pio_read(sc, suspendio) 104579697Snon struct nsp_softc *sc; 104679697Snon int suspendio; 104779697Snon{ 104879697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 104979697Snon bus_space_tag_t bst = sc->sc_iot; 105079697Snon bus_space_handle_t bsh = sc->sc_ioh; 105179697Snon int tout, padding, datalen; 105279697Snon register u_int8_t stat, fstat; 105379697Snon 105479697Snon padding = 0; 105579697Snon tout = sc->sc_tmaxcnt; 105679697Snon slp->sl_flags |= HW_PDMASTART; 105779697Snon datalen = slp->sl_scp.scp_datalen; 105879697Snon 105979697SnonReadLoop: 106079697Snon while (1) 106179697Snon { 106279697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 106379697Snon if (stat == (u_int8_t) -1) 106479697Snon return; 106579697Snon 106679697Snon /* out of data phase */ 106779697Snon if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN) 106879697Snon { 106979697Snon nsp_read_fifo(sc, 0); 107079697Snon return; 107179697Snon } 107279697Snon 107379697Snon /* data phase */ 107479697Snon fstat = bus_space_read_1(bst, bsh, nsp_fifosr); 107579697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 107679697Snon { 107779697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 107879697Snon { 107979697Snon bus_space_write_1(bst, bsh, nsp_irqcr, 108079697Snon IRQCR_FIFOCL); 108179697Snon } 108279697Snon 108379697Snon if (suspendio > 0) 108479697Snon { 108579697Snon padding |= nsp_read_fifo(sc, suspendio); 108679697Snon } 108779697Snon else 108879697Snon { 108979697Snon padding |= nsp_read_fifo(sc, 0); 109079697Snon } 109179697Snon 109279697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 109379697Snon break; 109479697Snon } 109567468Snon else 109667468Snon { 109779697Snon if (padding == 0 && slp->sl_scp.scp_datalen <= 0) 109879697Snon return; 109979697Snon 110079697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 110179697Snon break; 110279697Snon 110379697Snon SCSI_LOW_DELAY(1); 110467468Snon } 110567468Snon 110679697Snon if ((-- tout) <= 0) 110779697Snon { 110879697Snon printf("%s: nsp_pio_read: timeout\n", slp->sl_xname); 110979697Snon return; 111079697Snon } 111167468Snon } 111267468Snon 111379697Snon 111479697Snon if (slp->sl_scp.scp_datalen > 0 && 111579697Snon slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes) 111679697Snon { 111779697Snon if (nsp_wait_interrupt(sc) != 0) 111879697Snon goto ReadLoop; 111979697Snon } 112067468Snon} 112167468Snon 112267468Snonstatic void 112379697Snonnsp_pio_write(sc, suspendio) 112467468Snon struct nsp_softc *sc; 112579697Snon int suspendio; 112667468Snon{ 112767468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 112867468Snon bus_space_tag_t bst = sc->sc_iot; 112967468Snon bus_space_handle_t bsh = sc->sc_ioh; 113079697Snon u_int rcount, acount; 113179697Snon int tout, datalen; 113279697Snon register u_int8_t stat, fstat; 113367468Snon 113479697Snon tout = sc->sc_tmaxcnt; 113567468Snon slp->sl_flags |= HW_PDMASTART; 113679697Snon datalen = slp->sl_scp.scp_datalen; 113779697Snon 113879697SnonWriteLoop: 113979697Snon while (1) 114067468Snon { 114179697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 114267468Snon if (stat != PHASE_DATAOUT) 114379697Snon return; 114467468Snon 114579697Snon if (slp->sl_scp.scp_datalen <= 0) 114679697Snon { 114779697Snon if (sc->sc_dataout_timeout == 0) 114879697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 114979697Snon return; 115079697Snon } 115167468Snon 115279697Snon fstat = bus_space_read_1(bst, bsh, nsp_fifosr); 115379697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 115479697Snon { 115579697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 115679697Snon { 115779697Snon bus_space_write_1(bst, bsh, nsp_irqcr, 115879697Snon IRQCR_FIFOCL); 115979697Snon } 116067468Snon 116179697Snon if (suspendio > 0) 116279697Snon { 116379697Snon /* XXX:IMPORTANT: 116479697Snon * To avoid timeout of pcmcia bus 116579697Snon * (not scsi bus!), we should check 116679697Snon * the scsi device sends us request 116779697Snon * signals, which means the scsi device 116879697Snon * is ready to recieve data without 116979697Snon * heavy delays. 117079697Snon */ 117179697Snon acount = nsp_fifo_count(sc); 117279697Snon rcount = nsp_request_count(sc); 117379697Snon if (rcount <= acount) 117479697Snon { 117579697Snon nsp_write_fifo(sc, 0); 117679697Snon#ifdef NSP_STATICS 117779697Snon nsp_statics.device_busy ++; 117879697Snon#endif /* NSP_STATICS */ 117979697Snon } 118079697Snon else 118179697Snon { 118279697Snon nsp_write_fifo(sc, suspendio); 118379697Snon#ifdef NSP_STATICS 118479697Snon nsp_statics.device_data_write ++; 118579697Snon#endif /* NSP_STATICS */ 118679697Snon } 118779697Snon } 118879697Snon else 118979697Snon { 119079697Snon nsp_write_fifo(sc, 0); 119179697Snon } 119279697Snon 119379697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 119479697Snon break; 119567468Snon } 119667468Snon else 119767468Snon { 119879697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 119979697Snon break; 120079697Snon 120179697Snon SCSI_LOW_DELAY(1); 120267468Snon } 120367468Snon 120479697Snon if ((-- tout) <= 0) 120579697Snon { 120679697Snon printf("%s: nsp_pio_write: timeout\n", slp->sl_xname); 120779697Snon return; 120879697Snon } 120967468Snon } 121067468Snon 121179697Snon if (slp->sl_scp.scp_datalen > 0 && 121279697Snon slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes) 121379697Snon { 121479697Snon if (nsp_wait_interrupt(sc) != 0) 121579697Snon goto WriteLoop; 121679697Snon } 121767468Snon} 121867468Snon 121967468Snonstatic int 122067468Snonnsp_negate_signal(sc, mask, s) 122167468Snon struct nsp_softc *sc; 122267468Snon u_int8_t mask; 122367468Snon u_char *s; 122467468Snon{ 122567468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 122667468Snon bus_space_tag_t bst = sc->sc_iot; 122767468Snon bus_space_handle_t bsh = sc->sc_ioh; 122879697Snon int wc; 122967468Snon u_int8_t regv; 123067468Snon 123179697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 123267468Snon { 123367468Snon regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 123479697Snon if (regv == (u_int8_t) -1) 123579697Snon return -1; 123679697Snon if ((regv & mask) == 0) 123779697Snon return 1; 123879697Snon SCSI_LOW_DELAY(NSP_DELAY_INTERVAL); 123967468Snon } 124067468Snon 124179697Snon printf("%s: %s nsp_negate_signal timeout\n", slp->sl_xname, s); 124279697Snon return -1; 124367468Snon} 124467468Snon 124567468Snonstatic int 124679697Snonnsp_xfer(sc, buf, len, phase, clear_atn) 124767468Snon struct nsp_softc *sc; 124867468Snon u_int8_t *buf; 124967468Snon int len; 125067468Snon int phase; 125179697Snon int clear_atn; 125267468Snon{ 125367468Snon bus_space_tag_t bst = sc->sc_iot; 125467468Snon bus_space_handle_t bsh = sc->sc_ioh; 125579697Snon int ptr, rv; 125667468Snon 125767468Snon for (ptr = 0; len > 0; len --, ptr ++) 125867468Snon { 125967468Snon rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ); 126067468Snon if (rv <= 0) 126167468Snon goto out; 126267468Snon 126379697Snon if (len == 1 && clear_atn != 0) 126467468Snon { 126567468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 126667468Snon SCBUSCR_ADIR | SCBUSCR_ACKEN); 126779697Snon SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow); 126867468Snon } 126967468Snon 127067468Snon if (phase & SCBUSMON_IO) 127167468Snon { 127267468Snon buf[ptr] = nsp_cr_read_1(bst, bsh, NSPR_DATAACK); 127367468Snon } 127467468Snon else 127567468Snon { 127667468Snon nsp_cr_write_1(bst, bsh, NSPR_DATAACK, buf[ptr]); 127767468Snon } 127867468Snon nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>"); 127967468Snon } 128067468Snon 128167468Snonout: 128267468Snon return len; 128367468Snon} 128467468Snon 128567468Snon/************************************************************** 128667468Snon * disconnect & reselect (HW low) 128767468Snon **************************************************************/ 128867468Snonstatic int 128967468Snonnsp_reselected(sc) 129067468Snon struct nsp_softc *sc; 129167468Snon{ 129267468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 129367468Snon bus_space_tag_t bst = sc->sc_iot; 129467468Snon bus_space_handle_t bsh = sc->sc_ioh; 129567468Snon struct targ_info *ti; 129667468Snon u_int sid; 129767468Snon u_int8_t cr; 129867468Snon 129967468Snon sid = (u_int) nsp_cr_read_1(bst, bsh, NSPR_RESELR); 130067468Snon sid &= ~sc->sc_idbit; 130167468Snon sid = ffs(sid) - 1; 130267468Snon if ((ti = scsi_low_reselected(slp, sid)) == NULL) 130367468Snon return EJUSTRETURN; 130467468Snon 130567468Snon nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>"); 130667468Snon 130779697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); 130879697Snon cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN); 130967468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 131079697Snon cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN; 131179697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 131267468Snon 131367468Snon#ifdef NSP_STATICS 131479697Snon nsp_statics.reselect ++; 131567468Snon#endif /* NSP_STATCIS */ 131667468Snon return EJUSTRETURN; 131767468Snon} 131867468Snon 131979697Snonstatic int 132067468Snonnsp_disconnected(sc, ti) 132167468Snon struct nsp_softc *sc; 132267468Snon struct targ_info *ti; 132367468Snon{ 132467468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 132579697Snon bus_space_tag_t bst = sc->sc_iot; 132679697Snon bus_space_handle_t bsh = sc->sc_ioh; 132767468Snon 132879697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 132979697Snon PTCLRR_REQ | PTCLRR_HOST); 133079697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 133179697Snon { 133279697Snon sc->sc_icr &= ~SCIENR_FIFO; 133379697Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 133479697Snon } 133579697Snon sc->sc_cnt = 0; 133679697Snon sc->sc_dataout_timeout = 0; 133767468Snon#ifdef NSP_STATICS 133879697Snon nsp_statics.disconnect ++; 133967468Snon#endif /* NSP_STATICS */ 134067468Snon scsi_low_disconnected(slp, ti); 134167468Snon return 1; 134267468Snon} 134367468Snon 134467468Snon/************************************************************** 134567468Snon * SEQUENCER 134667468Snon **************************************************************/ 134779697Snonstatic void nsp_error __P((struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t)); 134867468Snon 134967468Snonstatic void 135079697Snonnsp_error(sc, s, isrc, ph, irqphs) 135167468Snon struct nsp_softc *sc; 135267468Snon u_char *s; 135367468Snon u_int8_t isrc, ph, irqphs; 135467468Snon{ 135567468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 135667468Snon 135767468Snon printf("%s: %s\n", slp->sl_xname, s); 135867468Snon printf("%s: isrc 0x%x scmon 0x%x irqphs 0x%x\n", 135967468Snon slp->sl_xname, (u_int) isrc, (u_int) ph, (u_int) irqphs); 136067468Snon} 136167468Snon 136267468Snonstatic int 136379697Snonnsp_target_nexus_establish(sc) 136467468Snon struct nsp_softc *sc; 136567468Snon{ 136679697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 136767468Snon bus_space_tag_t bst = sc->sc_iot; 136867468Snon bus_space_handle_t bsh = sc->sc_ioh; 136979697Snon struct targ_info *ti = slp->sl_Tnexus; 137073025Snon struct nsp_targ_info *nti = (void *) ti; 137167468Snon 137267468Snon /* setup synch transfer registers */ 137373025Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); 137473025Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 137567468Snon 137679697Snon /* setup pdma fifo (minimum) */ 137779697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0); 137879697Snon return 0; 137979697Snon} 138079697Snon 138179697Snonstatic int 138279697Snonnsp_lun_nexus_establish(sc) 138379697Snon struct nsp_softc *sc; 138479697Snon{ 138579697Snon 138679697Snon return 0; 138779697Snon} 138879697Snon 138979697Snonstatic int 139079697Snonnsp_ccb_nexus_establish(sc) 139179697Snon struct nsp_softc *sc; 139279697Snon{ 139379697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 139479697Snon struct slccb *cb = slp->sl_Qnexus; 139579697Snon 139679697Snon sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 139779697Snon 139867468Snon /* setup pdma fifo */ 139979697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, 140079697Snon slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen); 140167468Snon 140279697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 140379697Snon { 140479697Snon if (sc->sc_suspendio > 0 && 140579697Snon (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0) 140679697Snon { 140779697Snon sc->sc_icr |= SCIENR_FIFO; 140879697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, 140979697Snon NSPR_SCIENR, sc->sc_icr); 141079697Snon } 141179697Snon } 141279697Snon else 141379697Snon { 141479697Snon if (sc->sc_suspendio > 0 && 141579697Snon (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0) 141679697Snon { 141779697Snon sc->sc_icr |= SCIENR_FIFO; 141879697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, 141979697Snon NSPR_SCIENR, sc->sc_icr); 142079697Snon } 142179697Snon } 142267468Snon return 0; 142367468Snon} 142467468Snon 142579697Snonstatic int 142679697Snonnsp_phase_match(sc, phase, stat) 142779697Snon struct nsp_softc *sc; 142879697Snon u_int8_t phase; 142979697Snon u_int8_t stat; 143079697Snon{ 143179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 143279697Snon 143379697Snon if ((stat & SCBUSMON_PHMASK) != phase) 143479697Snon { 143579697Snon printf("%s: phase mismatch 0x%x != 0x%x\n", 143679697Snon slp->sl_xname, (u_int) phase, (u_int) stat); 143779697Snon return EINVAL; 143879697Snon } 143979697Snon 144079697Snon if ((stat & SCBUSMON_REQ) == 0) 144179697Snon return EINVAL; 144279697Snon 144379697Snon return 0; 144479697Snon} 144579697Snon 144667468Snonint 144767468Snonnspintr(arg) 144867468Snon void *arg; 144967468Snon{ 145067468Snon struct nsp_softc *sc = arg; 145167468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 145267468Snon bus_space_tag_t bst = sc->sc_iot; 145367468Snon bus_space_handle_t bsh = sc->sc_ioh; 145467468Snon struct targ_info *ti; 145567468Snon struct physio_proc *pp; 145667468Snon struct buf *bp; 145779697Snon u_int derror, flags; 145867468Snon int len, rv; 145967468Snon u_int8_t isrc, ph, irqphs, cr, regv; 146067468Snon 146167468Snon /******************************************* 146267468Snon * interrupt check 146367468Snon *******************************************/ 146467468Snon if (slp->sl_flags & HW_INACTIVE) 146567468Snon return 0; 146667468Snon 146767468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_IRQDIS); 146867468Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 146979697Snon if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0) 147067468Snon { 147167468Snon bus_space_write_1(bst, bsh, nsp_irqcr, 0); 147267468Snon return 0; 147367468Snon } 147467468Snon 147567468Snon /* XXX: IMPORTANT 147667468Snon * Do not read an irqphs register if no scsi phase interrupt. 147767468Snon * Unless, you should lose a scsi phase interrupt. 147867468Snon */ 147967468Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 148067468Snon if ((isrc & IRQSR_SCSI) != 0) 148167468Snon { 148267468Snon irqphs = nsp_cr_read_1(bst, bsh, NSPR_IRQPHS); 148367468Snon } 148467468Snon else 148567468Snon irqphs = 0; 148667468Snon 148767468Snon /* 148867468Snon * timer interrupt handler (scsi vs timer interrupts) 148967468Snon */ 149067468Snon if (sc->sc_timer != 0) 149167468Snon { 149267468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 149367468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 149467468Snon sc->sc_timer = 0; 149567468Snon } 149667468Snon 149779697Snon /* check a timer interrupt */ 149879697Snon regv = 0; 149979697Snon if ((isrc & IRQSR_TIMER) != 0) 150067468Snon { 150179697Snon if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0) 150279697Snon { 150379697Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL); 150479697Snon return 1; 150579697Snon } 150679697Snon regv |= IRQCR_TIMERCL; 150767468Snon } 150867468Snon 150979697Snon /* check a fifo interrupt */ 151079697Snon if ((isrc & IRQSR_FIFO) != 0) 151179697Snon { 151279697Snon regv |= IRQCR_FIFOCL; 151379697Snon } 151467468Snon 151579697Snon /* OK. enable all interrupts */ 151679697Snon bus_space_write_1(bst, bsh, nsp_irqcr, regv); 151779697Snon 151867468Snon /******************************************* 151967468Snon * debug section 152067468Snon *******************************************/ 152167468Snon#ifdef NSP_DEBUG 152267468Snon if (nsp_debug) 152367468Snon { 152479697Snon nsp_error(sc, "current status", isrc, ph, irqphs); 152567468Snon scsi_low_print(slp, NULL); 152679697Snon#ifdef DDB 152767468Snon if (nsp_debug > 1) 152879697Snon SCSI_LOW_DEBUGGER("nsp"); 152979697Snon#endif /* DDB */ 153067468Snon } 153167468Snon#endif /* NSP_DEBUG */ 153267468Snon 153367468Snon /******************************************* 153467468Snon * Parse hardware SCSI irq reasons register 153567468Snon *******************************************/ 153667468Snon if ((isrc & IRQSR_SCSI) != 0) 153767468Snon { 153867468Snon if ((irqphs & IRQPHS_RST) != 0) 153967468Snon { 154067468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 154167468Snon "bus reset (power off?)"); 154267468Snon return 1; 154367468Snon } 154467468Snon 154567468Snon if ((irqphs & IRQPHS_RSEL) != 0) 154667468Snon { 154767468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_RESCL); 154867468Snon if (nsp_reselected(sc) == EJUSTRETURN) 154967468Snon return 1; 155067468Snon } 155167468Snon 155267468Snon if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0) 155367468Snon return 1; 155467468Snon } 155567468Snon 155667468Snon /******************************************* 155767468Snon * nexus check 155867468Snon *******************************************/ 155979697Snon if ((ti = slp->sl_Tnexus) == NULL) 156067468Snon { 156167468Snon /* unknown scsi phase changes */ 156279697Snon nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs); 156367468Snon return 0; 156467468Snon } 156567468Snon 156667468Snon /******************************************* 156767468Snon * aribitration & selection 156867468Snon *******************************************/ 156967468Snon switch (ti->ti_phase) 157067468Snon { 157167468Snon case PH_SELSTART: 157267468Snon if ((ph & SCBUSMON_BSY) == 0) 157367468Snon { 157467468Snon if (sc->sc_seltout >= NSP_SELTIMEOUT) 157567468Snon { 157667468Snon sc->sc_seltout = 0; 157767468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0); 157867468Snon return nsp_disconnected(sc, ti); 157967468Snon } 158067468Snon sc->sc_seltout ++; 158179697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 158267468Snon return 1; 158367468Snon } 158467468Snon 158567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 158679697Snon nsphw_selection_done_and_expect_msgout(sc); 158767468Snon return 1; 158867468Snon 158979697Snon case PH_SELECTED: 159079697Snon if ((isrc & IRQSR_SCSI) == 0) 159179697Snon return 1; 159279697Snon 159379697Snon nsp_target_nexus_establish(sc); 159479697Snon break; 159579697Snon 159667468Snon case PH_RESEL: 159779697Snon if ((isrc & IRQSR_SCSI) == 0) 159879697Snon return 1; 159979697Snon 160079697Snon nsp_target_nexus_establish(sc); 160167468Snon if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN) 160267468Snon { 160379697Snon printf("%s: unexpected phase after reselect\n", 160479697Snon slp->sl_xname); 160579697Snon slp->sl_error |= FATALIO; 160667468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); 160767468Snon return 1; 160867468Snon } 160979697Snon break; 161067468Snon 161179697Snon case PH_DATA: 161279697Snon if ((isrc & IRQSR_SCSI) != 0) 161379697Snon break; 161479697Snon if ((isrc & IRQSR_FIFO) != 0) 161579697Snon { 161679697Snon if (NSP_IS_PHASE_DATA(ph) == 0) 161779697Snon return 1; 161879697Snon irqphs = (ph & IRQPHS_PHMASK); 161979697Snon break; 162079697Snon } 162179697Snon return 1; 162279697Snon 162367468Snon default: 162479697Snon if ((isrc & IRQSR_SCSI) == 0) 162567468Snon return 1; 162667468Snon break; 162767468Snon } 162867468Snon 162967468Snon /******************************************* 163079697Snon * data phase control 163167468Snon *******************************************/ 163267468Snon if (slp->sl_flags & HW_PDMASTART) 163379697Snon { 163479697Snon if ((isrc & IRQSR_SCSI) != 0 && 163579697Snon NSP_IS_IRQPHS_DATA(irqphs) == 0) 163679697Snon { 163779697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 163879697Snon nsp_pio_read(sc, 0); 163979697Snon nsp_pdma_end(sc, ti); 164079697Snon } 164179697Snon } 164267468Snon 164379697Snon /******************************************* 164479697Snon * scsi seq 164579697Snon *******************************************/ 164667468Snon if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0) 164767468Snon return nsp_disconnected(sc, ti); 164867468Snon 164967468Snon /* check unexpected bus free state */ 165067468Snon if (ph == 0) 165167468Snon { 165279697Snon nsp_error(sc, "unexpected bus free", isrc, ph, irqphs); 165367468Snon return nsp_disconnected(sc, ti); 165467468Snon } 165567468Snon 165667468Snon /* check normal scsi phase */ 165779697Snon switch (irqphs & IRQPHS_PHMASK) 165867468Snon { 165979697Snon case IRQPHS_CMD: 166079697Snon if (nsp_phase_match(sc, PHASE_CMD, ph) != 0) 166167468Snon return 1; 166267468Snon 166367468Snon SCSI_LOW_SETUP_PHASE(ti, PH_CMD); 166467468Snon if (scsi_low_cmd(slp, ti) != 0) 166579697Snon { 166679697Snon scsi_low_attention(slp); 166779697Snon } 166867468Snon 166967468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR); 167067468Snon for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++) 167167468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDDR, 167267468Snon slp->sl_scp.scp_cmd[len]); 167367468Snon 167467468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC); 167567468Snon break; 167667468Snon 167779697Snon case IRQPHS_DATAOUT: 167867468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 167967468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) 168079697Snon { 168179697Snon scsi_low_attention(slp); 168279697Snon } 168367468Snon 168467468Snon pp = physio_proc_enter(bp); 168579697Snon nsp_pio_write(sc, sc->sc_suspendio); 168667468Snon physio_proc_leave(pp); 168767468Snon break; 168867468Snon 168979697Snon case IRQPHS_DATAIN: 169067468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 169167468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) 169279697Snon { 169379697Snon scsi_low_attention(slp); 169479697Snon } 169567468Snon 169667468Snon pp = physio_proc_enter(bp); 169779697Snon nsp_pio_read(sc, sc->sc_suspendio); 169867468Snon physio_proc_leave(pp); 169967468Snon break; 170067468Snon 170179697Snon case IRQPHS_STATUS: 170279697Snon if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0) 170367468Snon return 1; 170467468Snon 170567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_STAT); 170679697Snon regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); 170779697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 170879697Snon { 170979697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, 171079697Snon PARITYR_ENABLE | PARITYR_CLEAR); 171179697Snon derror = SCSI_LOW_DATA_PE; 171279697Snon } 171379697Snon else 171479697Snon derror = 0; 171579697Snon 171679697Snon /* assert ACK */ 171779697Snon cr = SCBUSCR_ACK | nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); 171879697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 171979697Snon 172079697Snon if (scsi_low_statusin(slp, ti, derror | regv) != 0) 172179697Snon { 172279697Snon scsi_low_attention(slp); 172379697Snon } 172479697Snon 172579697Snon /* check REQ nagated */ 172679697Snon nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>"); 172779697Snon 172879697Snon /* deassert ACK */ 172979697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 173079697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 173167468Snon break; 173267468Snon 173379697Snon case IRQPHS_MSGOUT: 173479697Snon if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0) 173579697Snon return 1; 173667468Snon 173779697Snon#ifdef NSP_MSGOUT_SERIALIZE 173867468Snon /* 173967468Snon * XXX: NSP QUIRK 174067468Snon * NSP invoke interrupts only in the case of scsi phase changes, 174167468Snon * therefore we should poll the scsi phase here to catch 174267468Snon * the next "msg out" if exists (no scsi phase changes). 174367468Snon */ 174467468Snon rv = len = 16; 174567468Snon do { 174667468Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 174779697Snon flags = (ti->ti_ophase != ti->ti_phase) ? 174879697Snon SCSI_LOW_MSGOUT_INIT : 0; 174979697Snon len = scsi_low_msgout(slp, ti, flags); 175067468Snon 175179697Snon if (len > 1 && slp->sl_atten == 0) 175267468Snon { 175379697Snon scsi_low_attention(slp); 175479697Snon } 175579697Snon 175679697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 175779697Snon slp->sl_clear_atten) != 0) 175879697Snon { 175979697Snon slp->sl_error |= FATALIO; 176079697Snon nsp_error(sc, "MSGOUT: xfer short", 176167468Snon isrc, ph, irqphs); 176267468Snon } 176367468Snon 176467468Snon /* catch a next signal */ 176567468Snon rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ); 176667468Snon } 176767468Snon while (rv > 0 && len -- > 0); 176879697Snon 176979697Snon#else /* !NSP_MSGOUT_SERIALIZE */ 177079697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 177179697Snon flags = SCSI_LOW_MSGOUT_UNIFY; 177279697Snon if (ti->ti_ophase != ti->ti_phase) 177379697Snon flags |= SCSI_LOW_MSGOUT_INIT; 177479697Snon len = scsi_low_msgout(slp, ti, flags); 177579697Snon 177679697Snon if (len > 1 && slp->sl_atten == 0) 177779697Snon { 177879697Snon scsi_low_attention(slp); 177979697Snon } 178079697Snon 178179697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 178279697Snon slp->sl_clear_atten) != 0) 178379697Snon { 178479697Snon nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs); 178579697Snon } 178679697Snon 178779697Snon#endif /* !NSP_MSGOUT_SERIALIZE */ 178867468Snon break; 178967468Snon 179079697Snon case IRQPHS_MSGIN: 179179697Snon if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0) 179279697Snon return 1; 179367468Snon 179467468Snon /* 179567468Snon * XXX: NSP QUIRK 179667468Snon * NSP invoke interrupts only in the case of scsi phase changes, 179767468Snon * therefore we should poll the scsi phase here to catch 179867468Snon * the next "msg in" if exists (no scsi phase changes). 179967468Snon */ 180067468Snon rv = len = 16; 180167468Snon do { 180279697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); 180379697Snon 180467468Snon /* read a data */ 180567468Snon regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); 180679697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 180779697Snon { 180879697Snon nsp_cr_write_1(bst, bsh, 180979697Snon NSPR_PARITYR, 181079697Snon PARITYR_ENABLE | PARITYR_CLEAR); 181179697Snon derror = SCSI_LOW_DATA_PE; 181279697Snon } 181379697Snon else 181479697Snon { 181579697Snon derror = 0; 181679697Snon } 181767468Snon 181867468Snon /* assert ack */ 181979697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) | SCBUSCR_ACK; 182067468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 182179697Snon 182279697Snon if (scsi_low_msgin(slp, ti, regv | derror) == 0) 182379697Snon { 182479697Snon if (scsi_low_is_msgout_continue(ti, 0) != 0) 182579697Snon { 182679697Snon scsi_low_attention(slp); 182779697Snon } 182879697Snon } 182979697Snon 183079697Snon /* check REQ nagated */ 183167468Snon nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>"); 183267468Snon 183367468Snon /* deassert ack */ 183479697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 183567468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 183667468Snon 183767468Snon /* catch a next signal */ 183867468Snon rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ); 183967468Snon } 184067468Snon while (rv > 0 && len -- > 0); 184167468Snon break; 184267468Snon 184367468Snon default: 184479697Snon slp->sl_error |= FATALIO; 184579697Snon nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs); 184667468Snon break; 184767468Snon } 184867468Snon 184967468Snon return 1; 185067468Snon 185179697Snon#if 0 185267468Snontimerout: 185379697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 185467468Snon return 0; 185579697Snon#endif 185667468Snon} 185779697Snon 185879697Snonstatic int 185979697Snonnsp_timeout(sc) 186079697Snon struct nsp_softc *sc; 186179697Snon{ 186279697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 186379697Snon bus_space_tag_t iot = sc->sc_iot; 186479697Snon bus_space_handle_t ioh = sc->sc_ioh; 186579697Snon int tout; 186679697Snon u_int8_t ph, regv; 186779697Snon 186879697Snon if (slp->sl_Tnexus == NULL) 186979697Snon return 0; 187079697Snon 187179697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 187279697Snon switch (ph & SCBUSMON_PHMASK) 187379697Snon { 187479697Snon case PHASE_DATAOUT: 187579697Snon if (sc->sc_dataout_timeout == 0) 187679697Snon break; 187779697Snon 187879697Snon /* check a fifo empty */ 187979697Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 188079697Snon if ((regv & FIFOSR_FULLEMP) == 0) 188179697Snon break; 188279697Snon bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); 188379697Snon 188479697Snon /* check still requested */ 188579697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 188679697Snon if ((ph & SCBUSMON_REQ) == 0) 188779697Snon break; 188879697Snon /* check timeout */ 188979697Snon if ((-- sc->sc_dataout_timeout) > 0) 189079697Snon break; 189179697Snon 189279697Snon slp->sl_error |= PDMAERR; 189379697Snon if ((slp->sl_flags & HW_WRITE_PADDING) == 0) 189479697Snon { 189579697Snon printf("%s: write padding required\n", slp->sl_xname); 189679697Snon break; 189779697Snon } 189879697Snon 189979697Snon tout = NSP_DELAY_MAX; 190079697Snon while (tout -- > 0) 190179697Snon { 190279697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 190379697Snon if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT) 190479697Snon break; 190579697Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 190679697Snon if ((regv & FIFOSR_FULLEMP) == 0) 190779697Snon { 190879697Snon SCSI_LOW_DELAY(1); 190979697Snon continue; 191079697Snon } 191179697Snon 191279697Snon bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); 191379697Snon nsp_data_padding(sc, SCSI_LOW_WRITE, 32); 191479697Snon } 191579697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 191679697Snon if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT) 191779697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 191879697Snon break; 191979697Snon 192079697Snon default: 192179697Snon break; 192279697Snon } 192379697Snon return 0; 192479697Snon} 1925