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> 5367468Snon 5467468Snon#include <machine/cpu.h> 5567468Snon#include <machine/bus.h> 5667468Snon 5767468Snon#include <cam/scsi/scsi_low.h> 5867468Snon#include <dev/nsp/nspreg.h> 5967468Snon#include <dev/nsp/nspvar.h> 6067468Snon 6167468Snon/*************************************************** 6267468Snon * USER SETTINGS 6367468Snon ***************************************************/ 6467468Snon/* DEVICE CONFIGURATION FLAGS (MINOR) 6567468Snon * 66250460Seadler * 0x01 DISCONNECT OFF 6767468Snon * 0x02 PARITY LINE OFF 6867468Snon * 0x04 IDENTIFY MSG OFF ( = single lun) 6967468Snon * 0x08 SYNC TRANSFER OFF 7067468Snon */ 7167468Snon 7267468Snon/*************************************************** 7367468Snon * PARAMS 7467468Snon ***************************************************/ 7567468Snon#define NSP_NTARGETS 8 7667468Snon#define NSP_NLUNS 8 7767468Snon 7879697Snon#define NSP_MAX_DATA_SIZE (64 * 1024) 7979697Snon#define NSP_SELTIMEOUT (200) 8079697Snon#define NSP_DELAY_MAX (2 * 1000 * 1000) 8179697Snon#define NSP_DELAY_INTERVAL (1) 8279697Snon#define NSP_TIMER_1MS (1000 / 51) 8367468Snon 8467468Snon/*************************************************** 8567468Snon * DEBUG 8667468Snon ***************************************************/ 8767468Snon#ifdef NSP_DEBUG 8867468Snonint nsp_debug; 8967468Snon#endif /* NSP_DEBUG */ 9067468Snon 9167468Snon#ifdef NSP_STATICS 9267468Snonstruct nsp_statics { 9379697Snon int arbit_conflict_1; 9479697Snon int arbit_conflict_2; 9579697Snon int device_data_write; 9679697Snon int device_busy; 9767468Snon int disconnect; 9867468Snon int reselect; 9967468Snon int data_phase_bypass; 10079697Snon} nsp_statics; 10167468Snon#endif /* NSP_STATICS */ 10267468Snon 10367468Snon/*************************************************** 10479697Snon * IO control 10567468Snon ***************************************************/ 10679697Snon#define NSP_READ_SUSPEND_IO 0x0001 10779697Snon#define NSP_WRITE_SUSPEND_IO 0x0002 10879697Snon#define NSP_USE_MEMIO 0x0004 10979697Snon#define NSP_READ_FIFO_INTERRUPTS 0x0010 11079697Snon#define NSP_WRITE_FIFO_INTERRUPTS 0x0020 11179697Snon#define NSP_WAIT_FOR_SELECT 0x0100 11279697Snon 11379697Snonu_int nsp_io_control = NSP_IO_CONTROL_FLAGS; 11479697Snonint nsp_read_suspend_bytes = DEV_BSIZE; 11579697Snonint nsp_write_suspend_bytes = DEV_BSIZE; 11679697Snonint nsp_read_interrupt_bytes = 4096; 11779697Snonint nsp_write_interrupt_bytes = 4096; 11879697Snon 11979697Snon/*************************************************** 12079697Snon * DEVICE STRUCTURE 12179697Snon ***************************************************/ 12267468Snonextern struct cfdriver nsp_cd; 12367468Snon 12467468Snon/************************************************************** 12567468Snon * DECLARE 12667468Snon **************************************************************/ 12779697Snon#define NSP_FIFO_ON 1 12879697Snon#define NSP_FIFO_OFF 0 12992739Salfredstatic void nsp_pio_read(struct nsp_softc *, int); 13092739Salfredstatic void nsp_pio_write(struct nsp_softc *, int); 13192739Salfredstatic int nsp_xfer(struct nsp_softc *, u_int8_t *, int, int, int); 13292739Salfredstatic int nsp_msg(struct nsp_softc *, struct targ_info *, u_int); 13392739Salfredstatic int nsp_reselected(struct nsp_softc *); 13492739Salfredstatic int nsp_disconnected(struct nsp_softc *, struct targ_info *); 13592739Salfredstatic void nsp_pdma_end(struct nsp_softc *, struct targ_info *); 13692739Salfredstatic void nsphw_init(struct nsp_softc *); 13792739Salfredstatic int nsp_target_nexus_establish(struct nsp_softc *); 13892739Salfredstatic int nsp_lun_nexus_establish(struct nsp_softc *); 13992739Salfredstatic int nsp_ccb_nexus_establish(struct nsp_softc *); 14092739Salfredstatic int nsp_world_start(struct nsp_softc *, int); 14192739Salfredstatic int nsphw_start_selection(struct nsp_softc *sc, struct slccb *); 14292739Salfredstatic void nsphw_bus_reset(struct nsp_softc *); 14392739Salfredstatic void nsphw_attention(struct nsp_softc *); 14492739Salfredstatic u_int nsp_fifo_count(struct nsp_softc *); 14592739Salfredstatic u_int nsp_request_count(struct nsp_softc *); 14692739Salfredstatic int nsp_negate_signal(struct nsp_softc *, u_int8_t, u_char *); 14792739Salfredstatic int nsp_expect_signal(struct nsp_softc *, u_int8_t, u_int8_t); 14892739Salfredstatic void nsp_start_timer(struct nsp_softc *, int); 14992739Salfredstatic void nsp_setup_fifo(struct nsp_softc *, int, int, int); 15092739Salfredstatic int nsp_targ_init(struct nsp_softc *, struct targ_info *, int); 15192739Salfredstatic void nsphw_selection_done_and_expect_msgout(struct nsp_softc *); 15292739Salfredstatic void nsp_data_padding(struct nsp_softc *, int, u_int); 15392739Salfredstatic int nsp_timeout(struct nsp_softc *); 15492739Salfredstatic int nsp_read_fifo(struct nsp_softc *, int); 15592739Salfredstatic int nsp_write_fifo(struct nsp_softc *, int); 15692739Salfredstatic int nsp_phase_match(struct nsp_softc *, u_int8_t, u_int8_t); 15792739Salfredstatic int nsp_wait_interrupt(struct nsp_softc *); 15867468Snon 15967468Snonstruct scsi_low_funcs nspfuncs = { 16067468Snon SC_LOW_INIT_T nsp_world_start, 16167468Snon SC_LOW_BUSRST_T nsphw_bus_reset, 16273025Snon SC_LOW_TARG_INIT_T nsp_targ_init, 16379697Snon SC_LOW_LUN_INIT_T NULL, 16467468Snon 16567468Snon SC_LOW_SELECT_T nsphw_start_selection, 16679697Snon SC_LOW_NEXUS_T nsp_lun_nexus_establish, 16779697Snon SC_LOW_NEXUS_T nsp_ccb_nexus_establish, 16867468Snon 16967468Snon SC_LOW_ATTEN_T nsphw_attention, 17067468Snon SC_LOW_MSG_T nsp_msg, 17167468Snon 17279697Snon SC_LOW_TIMEOUT_T nsp_timeout, 17367468Snon SC_LOW_POLL_T nspintr, 17467468Snon 17567468Snon NULL, 17667468Snon}; 17767468Snon 17867468Snon/**************************************************** 17967468Snon * hwfuncs 18067468Snon ****************************************************/ 18192739Salfredstatic __inline u_int8_t nsp_cr_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs); 18292739Salfredstatic __inline void nsp_cr_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs, u_int8_t va); 18367468Snon 18467468Snonstatic __inline u_int8_t 18567468Snonnsp_cr_read_1(bst, bsh, ofs) 18667468Snon bus_space_tag_t bst; 18767468Snon bus_space_handle_t bsh; 18867468Snon bus_addr_t ofs; 18967468Snon{ 19067468Snon 19167468Snon bus_space_write_1(bst, bsh, nsp_idxr, ofs); 19267468Snon return bus_space_read_1(bst, bsh, nsp_datar); 19367468Snon} 19467468Snon 19567468Snonstatic __inline void 196189004Srdivackynsp_cr_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_addr_t ofs, 197189004Srdivacky u_int8_t va) 19867468Snon{ 19967468Snon 20067468Snon bus_space_write_1(bst, bsh, nsp_idxr, ofs); 20167468Snon bus_space_write_1(bst, bsh, nsp_datar, va); 20267468Snon} 20367468Snon 20467468Snonstatic int 205189004Srdivackynsp_expect_signal(struct nsp_softc *sc, u_int8_t curphase, u_int8_t mask) 20667468Snon{ 20767468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 20867468Snon bus_space_tag_t bst = sc->sc_iot; 20967468Snon bus_space_handle_t bsh = sc->sc_ioh; 21079697Snon int wc; 21173025Snon u_int8_t ph, isrc; 21267468Snon 21379697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 21467468Snon { 21567468Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 21679697Snon if (ph == (u_int8_t) -1) 21779697Snon return -1; 21879697Snon 21967468Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 22079697Snon if (isrc & IRQSR_SCSI) 22179697Snon return 0; 22267468Snon 22379697Snon if ((ph & mask) != 0 && (ph & SCBUSMON_PHMASK) == curphase) 22479697Snon return 1; 22579697Snon 226240172Sjhb DELAY(NSP_DELAY_INTERVAL); 22767468Snon } 22867468Snon 229240325Sjhb device_printf(slp->sl_dev, "nsp_expect_signal timeout\n"); 23079697Snon return -1; 23167468Snon} 23267468Snon 23367468Snonstatic void 23467468Snonnsphw_init(sc) 23567468Snon struct nsp_softc *sc; 23667468Snon{ 23767468Snon bus_space_tag_t bst = sc->sc_iot; 23867468Snon bus_space_handle_t bsh = sc->sc_ioh; 23967468Snon 24067468Snon /* block all interrupts */ 24167468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK); 24267468Snon 24367468Snon /* setup SCSI interface */ 24467468Snon bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_IFSEL); 24567468Snon 24667468Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, 0); 24767468Snon 24867468Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8); 24967468Snon nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_iclkdiv); 25067468Snon 25167468Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 25279697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, sc->sc_parr); 25367468Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, 25467468Snon PTCLRR_ACK | PTCLRR_REQ | PTCLRR_HOST | PTCLRR_RSS); 25567468Snon 25667468Snon /* setup fifo asic */ 25767468Snon bus_space_write_1(bst, bsh, nsp_ifselr, IFSELR_REGSEL); 25867468Snon nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, 0); 25967468Snon if ((nsp_cr_read_1(bst, bsh, NSPR_OCR) & OCR_TERMPWRS) == 0) 26067468Snon nsp_cr_write_1(bst, bsh, NSPR_TERMPWRC, TERMPWRC_POWON); 26167468Snon 26267468Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_IO8); 26367468Snon nsp_cr_write_1(bst, bsh, NSPR_CLKDIVR, sc->sc_clkdiv); 26467468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 26567468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 26667468Snon 26767468Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, 0); 26867468Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, 0); 26967468Snon 27067468Snon /* enable interrupts and ack them */ 27179697Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 27267468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); 27367468Snon 27479697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 27567468Snon} 27667468Snon 27767468Snon/**************************************************** 27867468Snon * scsi low interface 27967468Snon ****************************************************/ 28067468Snonstatic void 28167468Snonnsphw_attention(sc) 28267468Snon struct nsp_softc *sc; 28367468Snon{ 28467468Snon bus_space_tag_t bst = sc->sc_iot; 28567468Snon bus_space_handle_t bsh = sc->sc_ioh; 28667468Snon u_int8_t cr; 28767468Snon 28867468Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR)/* & ~SCBUSCR_ACK */; 28967468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr | SCBUSCR_ATN); 290240172Sjhb DELAY(10); 29167468Snon} 29267468Snon 29367468Snonstatic void 29467468Snonnsphw_bus_reset(sc) 29567468Snon struct nsp_softc *sc; 29667468Snon{ 29767468Snon bus_space_tag_t bst = sc->sc_iot; 29867468Snon bus_space_handle_t bsh = sc->sc_ioh; 29967468Snon int i; 30067468Snon 30167468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_ALLMASK); 30267468Snon 30367468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_RST); 304240172Sjhb DELAY(100 * 1000); /* 100ms */ 30567468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0); 30667468Snon for (i = 0; i < 5; i ++) 30767468Snon (void) nsp_cr_read_1(bst, bsh, NSPR_IRQPHS); 30867468Snon 30967468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQSR_MASK); 31067468Snon} 31167468Snon 31279697Snonstatic void 31379697Snonnsphw_selection_done_and_expect_msgout(sc) 31471468Sjhb struct nsp_softc *sc; 31571468Sjhb{ 31679697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 31771468Sjhb bus_space_tag_t bst = sc->sc_iot; 31871468Sjhb bus_space_handle_t bsh = sc->sc_ioh; 31971468Sjhb 32079697Snon /* clear ack counter */ 32179697Snon sc->sc_cnt = 0; 32279697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 32379697Snon PTCLRR_REQ | PTCLRR_HOST); 32479697Snon 32579697Snon /* deassert sel and assert atten */ 32679697Snon sc->sc_seltout = 0; 32779697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, sc->sc_busc); 328240172Sjhb DELAY(1); 32979697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 33079697Snon sc->sc_busc | SCBUSCR_ADIR | SCBUSCR_ACKEN); 33179697Snon SCSI_LOW_ASSERT_ATN(slp); 33271468Sjhb} 33371468Sjhb 33467468Snonstatic int 33567468Snonnsphw_start_selection(sc, cb) 33667468Snon struct nsp_softc *sc; 33767468Snon struct slccb *cb; 33867468Snon{ 33967468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 34067468Snon bus_space_tag_t bst = sc->sc_iot; 34167468Snon bus_space_handle_t bsh = sc->sc_ioh; 34267468Snon struct targ_info *ti = cb->ti; 34367468Snon register u_int8_t arbs, ph; 34479697Snon int s, wc; 34567468Snon 34679697Snon wc = sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 34779697Snon sc->sc_dataout_timeout = 0; 34879697Snon 34967468Snon /* check bus free */ 35079697Snon s = splhigh(); 35179697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 35279697Snon if (ph != SCBUSMON_FREE) 35367468Snon { 35467468Snon splx(s); 35579697Snon#ifdef NSP_STATICS 35679697Snon nsp_statics.arbit_conflict_1 ++; 35779697Snon#endif /* NSP_STATICS */ 35879697Snon return SCSI_LOW_START_FAIL; 35967468Snon } 36067468Snon 36167468Snon /* start arbitration */ 36279697Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_EXEC); 36379697Snon splx(s); 36479697Snon 36567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); 36667468Snon do 36767468Snon { 36867468Snon /* XXX: what a stupid chip! */ 36967468Snon arbs = nsp_cr_read_1(bst, bsh, NSPR_ARBITS); 370240172Sjhb DELAY(1); 37167468Snon } 37273025Snon while ((arbs & (ARBITS_WIN | ARBITS_FAIL)) == 0 && wc -- > 0); 37367468Snon 37467468Snon if ((arbs & ARBITS_WIN) == 0) 37567468Snon { 37667468Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); 37779697Snon#ifdef NSP_STATICS 37879697Snon nsp_statics.arbit_conflict_2 ++; 37979697Snon#endif /* NSP_STATICS */ 38067468Snon return SCSI_LOW_START_FAIL; 38167468Snon } 38267468Snon 38367468Snon /* assert select line */ 38467468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); 38579697Snon scsi_low_arbit_win(slp); 38679697Snon 38779697Snon s = splhigh(); 388240172Sjhb DELAY(3); 38967468Snon nsp_cr_write_1(bst, bsh, NSPR_DATA, 39067468Snon sc->sc_idbit | (1 << ti->ti_id)); 39167468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 39267468Snon SCBUSCR_SEL | SCBUSCR_BSY | sc->sc_busc); 393240172Sjhb DELAY(3); 39467468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, SCBUSCR_SEL | 39567468Snon SCBUSCR_BSY | SCBUSCR_DOUT | sc->sc_busc); 39667468Snon nsp_cr_write_1(bst, bsh, NSPR_ARBITS, ARBITS_CLR); 397240172Sjhb DELAY(3); 39867468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 39967468Snon SCBUSCR_SEL | SCBUSCR_DOUT | sc->sc_busc); 400240172Sjhb DELAY(1); 40167468Snon 40279697Snon if ((nsp_io_control & NSP_WAIT_FOR_SELECT) != 0) 40379697Snon { 40479697Snon#define NSP_FIRST_SEL_WAIT 300 40579697Snon#define NSP_SEL_CHECK_INTERVAL 10 40679697Snon 40779697Snon /* wait for a selection response */ 40879697Snon for (wc = 0; wc < NSP_FIRST_SEL_WAIT / NSP_SEL_CHECK_INTERVAL; 40979697Snon wc ++) 41079697Snon { 41179697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 41279697Snon if ((ph & SCBUSMON_BSY) == 0) 41379697Snon { 414240172Sjhb DELAY(NSP_SEL_CHECK_INTERVAL); 41579697Snon continue; 41679697Snon } 41779697Snon 418240172Sjhb DELAY(1); 41979697Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 42079697Snon if ((ph & SCBUSMON_BSY) != 0) 42179697Snon { 42279697Snon nsphw_selection_done_and_expect_msgout(sc); 42379697Snon splx(s); 42479697Snon 42579697Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 42679697Snon return SCSI_LOW_START_OK; 42779697Snon } 42879697Snon } 42979697Snon } 43079697Snon splx(s); 43179697Snon 43279697Snon /* check a selection timeout */ 43379697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 43467468Snon sc->sc_seltout = 1; 43567468Snon return SCSI_LOW_START_OK; 43667468Snon} 43767468Snon 43867468Snonstatic int 43967468Snonnsp_world_start(sc, fdone) 44067468Snon struct nsp_softc *sc; 44167468Snon int fdone; 44267468Snon{ 44367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 44467468Snon 44567468Snon sc->sc_cnt = 0; 44667468Snon sc->sc_seltout = 0; 44779697Snon 44867468Snon if ((slp->sl_cfgflags & CFG_NOATTEN) == 0) 44967468Snon sc->sc_busc = SCBUSCR_ATN; 45067468Snon else 45167468Snon sc->sc_busc = 0; 45279697Snon 45379697Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0) 45479697Snon sc->sc_parr = PARITYR_ENABLE | PARITYR_CLEAR; 45579697Snon else 45679697Snon sc->sc_parr = 0; 45779697Snon 45867468Snon sc->sc_icr = (SCIENR_SCCHG | SCIENR_RESEL | SCIENR_RST); 45967468Snon 46067468Snon nsphw_init(sc); 46167468Snon scsi_low_bus_reset(slp); 46267468Snon 46367468Snon return 0; 46467468Snon} 46567468Snon 46667468Snonstruct ncp_synch_data { 46767468Snon u_int min_period; 46867468Snon u_int max_period; 46967468Snon u_int chip_period; 47067468Snon u_int ack_width; 47167468Snon}; 47267468Snon 47367468Snonstatic struct ncp_synch_data ncp_sync_data_40M[] = { 47467468Snon {0x0c,0x0c,0x1,0}, /* 20MB 50ns*/ 47567468Snon {0x19,0x19,0x3,1}, /* 10MB 100ns*/ 47667468Snon {0x1a,0x25,0x5,2}, /* 7.5MB 150ns*/ 47767468Snon {0x26,0x32,0x7,3}, /* 5MB 200ns*/ 47867468Snon {0x0, 0, 0, 0} 47967468Snon}; 48067468Snon 48167468Snonstatic struct ncp_synch_data ncp_sync_data_20M[] = { 48267468Snon {0x19,0x19,0x1,0}, /* 10MB 100ns*/ 48367468Snon {0x1a,0x25,0x2,0}, /* 7.5MB 150ns*/ 48467468Snon {0x26,0x32,0x3,1}, /* 5MB 200ns*/ 48567468Snon {0x0, 0, 0, 0} 48667468Snon}; 48767468Snon 48867468Snonstatic int 48967468Snonnsp_msg(sc, ti, msg) 49067468Snon struct nsp_softc *sc; 49167468Snon struct targ_info *ti; 49267468Snon u_int msg; 49367468Snon{ 49479697Snon bus_space_tag_t bst = sc->sc_iot; 49579697Snon bus_space_handle_t bsh = sc->sc_ioh; 49667468Snon struct ncp_synch_data *sdp; 49773025Snon struct nsp_targ_info *nti = (void *) ti; 49867468Snon u_int period, offset; 49979697Snon int i, error; 50067468Snon 50179697Snon if ((msg & SCSI_LOW_MSG_WIDE) != 0) 50279697Snon { 50379697Snon if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) 50479697Snon { 50579697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 50679697Snon return EINVAL; 50779697Snon } 50879697Snon return 0; 50979697Snon } 51079697Snon 51167468Snon if ((msg & SCSI_LOW_MSG_SYNCH) == 0) 51267468Snon return 0; 51367468Snon 51473025Snon period = ti->ti_maxsynch.period; 51573025Snon offset = ti->ti_maxsynch.offset; 51667468Snon if (sc->sc_iclkdiv == CLKDIVR_20M) 51767468Snon sdp = &ncp_sync_data_20M[0]; 51867468Snon else 51967468Snon sdp = &ncp_sync_data_40M[0]; 52067468Snon 52167468Snon for (i = 0; sdp->max_period != 0; i ++, sdp ++) 52267468Snon { 52367468Snon if (period >= sdp->min_period && period <= sdp->max_period) 52467468Snon break; 52567468Snon } 52667468Snon 52767468Snon if (period != 0 && sdp->max_period == 0) 52867468Snon { 52967468Snon /* 53067468Snon * NO proper period/offset found, 53167468Snon * Retry neg with the target. 53267468Snon */ 53373025Snon ti->ti_maxsynch.period = 0; 53473025Snon ti->ti_maxsynch.offset = 0; 53573025Snon nti->nti_reg_syncr = 0; 53673025Snon nti->nti_reg_ackwidth = 0; 53779697Snon error = EINVAL; 53867468Snon } 53979697Snon else 54079697Snon { 54179697Snon nti->nti_reg_syncr = (sdp->chip_period << SYNCR_PERS) | 54279697Snon (offset & SYNCR_OFFM); 54379697Snon nti->nti_reg_ackwidth = sdp->ack_width; 54479697Snon error = 0; 54579697Snon } 54667468Snon 54779697Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); 54879697Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 54979697Snon return error; 55067468Snon} 55167468Snon 55267468Snonstatic int 55379697Snonnsp_targ_init(sc, ti, action) 55467468Snon struct nsp_softc *sc; 55567468Snon struct targ_info *ti; 55679697Snon int action; 55767468Snon{ 55873025Snon struct nsp_targ_info *nti = (void *) ti; 55967468Snon 56079697Snon if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) 56179697Snon { 56279697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 56379697Snon ti->ti_maxsynch.period = 100 / 4; 56479697Snon ti->ti_maxsynch.offset = 15; 56579697Snon nti->nti_reg_syncr = 0; 56679697Snon nti->nti_reg_ackwidth = 0; 56779697Snon } 56867468Snon return 0; 56967468Snon} 57067468Snon 57179697Snonstatic void 57279697Snonnsp_start_timer(sc, time) 57379697Snon struct nsp_softc *sc; 57479697Snon int time; 57579697Snon{ 57679697Snon bus_space_tag_t bst = sc->sc_iot; 57779697Snon bus_space_handle_t bsh = sc->sc_ioh; 57879697Snon 57979697Snon sc->sc_timer = time; 58079697Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, time); 58179697Snon} 58279697Snon 58367468Snon/************************************************************** 58467468Snon * General probe attach 58567468Snon **************************************************************/ 58667468Snonint 58767468Snonnspprobesubr(iot, ioh, dvcfg) 58867468Snon bus_space_tag_t iot; 58967468Snon bus_space_handle_t ioh; 59067468Snon u_int dvcfg; 59167468Snon{ 59267468Snon u_int8_t regv; 59367468Snon 59467468Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 59567468Snon if (regv < 0x11 || regv >= 0x20) 59667468Snon return 0; 59767468Snon return 1; 59867468Snon} 59967468Snon 60067468Snonvoid 60167468Snonnspattachsubr(sc) 60267468Snon struct nsp_softc *sc; 60367468Snon{ 60467468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 60567468Snon 60667468Snon printf("\n"); 60767468Snon 60867468Snon sc->sc_idbit = (1 << slp->sl_hostid); 60979697Snon slp->sl_flags |= HW_READ_PADDING; 61067468Snon slp->sl_funcs = &nspfuncs; 61179697Snon sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ 61267468Snon 61379697Snon (void) scsi_low_attach(slp, 0, NSP_NTARGETS, NSP_NLUNS, 61479697Snon sizeof(struct nsp_targ_info), 0); 61567468Snon} 61667468Snon 61767468Snon/************************************************************** 61867468Snon * PDMA functions 61967468Snon **************************************************************/ 62067468Snonstatic u_int 62167468Snonnsp_fifo_count(sc) 62267468Snon struct nsp_softc *sc; 62367468Snon{ 62467468Snon bus_space_tag_t bst = sc->sc_iot; 62567468Snon bus_space_handle_t bsh = sc->sc_ioh; 62667468Snon u_int count; 62767468Snon 62879697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_ACK | PTCLRR_PT); 62967468Snon count = bus_space_read_1(bst, bsh, nsp_datar); 63067468Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); 63167468Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); 63267468Snon return count; 63367468Snon} 63467468Snon 63579697Snonstatic u_int 63679697Snonnsp_request_count(sc) 63779697Snon struct nsp_softc *sc; 63879697Snon{ 63979697Snon bus_space_tag_t bst = sc->sc_iot; 64079697Snon bus_space_handle_t bsh = sc->sc_ioh; 64179697Snon u_int count; 64279697Snon 64379697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_RSS_REQ | PTCLRR_PT); 64479697Snon count = bus_space_read_1(bst, bsh, nsp_datar); 64579697Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 8); 64679697Snon count += (((u_int) bus_space_read_1(bst, bsh, nsp_datar)) << 16); 64779697Snon return count; 64879697Snon} 64979697Snon 65067468Snonstatic void 65179697Snonnsp_setup_fifo(sc, on, direction, datalen) 65267468Snon struct nsp_softc *sc; 65367468Snon int on; 65479697Snon int direction; 65579697Snon int datalen; 65667468Snon{ 65767468Snon u_int8_t xfermode; 65867468Snon 65979697Snon sc->sc_suspendio = 0; 66079697Snon if (on == NSP_FIFO_OFF) 66179697Snon { 66279697Snon xfermode = XFERMR_IO8; 66379697Snon goto out; 66479697Snon } 66567468Snon 66679697Snon /* check if suspend io OK ? */ 66779697Snon if (datalen > 0) 66867468Snon { 66979697Snon if (direction == SCSI_LOW_READ) 67079697Snon { 67179697Snon if ((nsp_io_control & NSP_READ_SUSPEND_IO) != 0 && 67279697Snon (datalen % nsp_read_suspend_bytes) == 0) 67379697Snon sc->sc_suspendio = nsp_read_suspend_bytes; 67479697Snon } 67579697Snon else 67679697Snon { 67779697Snon if ((nsp_io_control & NSP_WRITE_SUSPEND_IO) != 0 && 67879697Snon (datalen % nsp_write_suspend_bytes) == 0) 67979697Snon sc->sc_suspendio = nsp_write_suspend_bytes; 68079697Snon } 68167468Snon } 68279697Snon 68379697Snon /* determine a transfer type */ 68479697Snon if (datalen < DEV_BSIZE || (datalen & 3) != 0) 68579697Snon { 686102291Sarchie if (sc->sc_memh != 0 && 68779697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 68879697Snon xfermode = XFERMR_XEN | XFERMR_MEM8; 68979697Snon else 69079697Snon xfermode = XFERMR_XEN | XFERMR_IO8; 69179697Snon } 69267468Snon else 69367468Snon { 694102291Sarchie if (sc->sc_memh != 0 && 69579697Snon (nsp_io_control & NSP_USE_MEMIO) != 0) 69679697Snon xfermode = XFERMR_XEN | XFERMR_MEM32; 69767468Snon else 69879697Snon xfermode = XFERMR_XEN | XFERMR_IO32; 69979697Snon 70079697Snon if (sc->sc_suspendio > 0) 70179697Snon xfermode |= XFERMR_FIFOEN; 70267468Snon } 70367468Snon 70479697Snonout: 70567468Snon sc->sc_xfermr = xfermode; 70679697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_XFERMR, sc->sc_xfermr); 70767468Snon} 70867468Snon 70979697Snonstatic void 71067468Snonnsp_pdma_end(sc, ti) 71167468Snon struct nsp_softc *sc; 71267468Snon struct targ_info *ti; 71367468Snon{ 71467468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 71579697Snon struct slccb *cb = slp->sl_Qnexus; 71667468Snon u_int len = 0, cnt; 71767468Snon 71879697Snon sc->sc_dataout_timeout = 0; 71967468Snon slp->sl_flags &= ~HW_PDMASTART; 72079697Snon nsp_setup_fifo(sc, NSP_FIFO_OFF, SCSI_LOW_READ, 0); 72179697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 72279697Snon { 72379697Snon sc->sc_icr &= ~SCIENR_FIFO; 72479697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, NSPR_SCIENR, sc->sc_icr); 72579697Snon } 72667468Snon 72779697Snon if (cb == NULL) 72879697Snon { 72979697Snon slp->sl_error |= PDMAERR; 73079697Snon return; 73179697Snon } 73279697Snon 73367468Snon if (ti->ti_phase == PH_DATA) 73467468Snon { 73567468Snon cnt = nsp_fifo_count(sc); 73667468Snon if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) 73767468Snon { 73867468Snon len = sc->sc_cnt - cnt; 73979697Snon if (sc->sc_cnt >= cnt && 74079697Snon slp->sl_scp.scp_datalen + len <= 74167468Snon cb->ccb_scp.scp_datalen) 74267468Snon { 74367468Snon slp->sl_scp.scp_data -= len; 74467468Snon slp->sl_scp.scp_datalen += len; 74567468Snon } 74667468Snon else 74767468Snon { 74867468Snon slp->sl_error |= PDMAERR; 749240325Sjhb device_printf(slp->sl_dev, 750240325Sjhb "len %x >= datalen %x\n", 75167468Snon len, slp->sl_scp.scp_datalen); 75267468Snon } 75367468Snon } 75467468Snon else if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 75567468Snon { 75679697Snon if (sc->sc_cnt != cnt || 75779697Snon sc->sc_cnt > cb->ccb_scp.scp_datalen) 75867468Snon { 75967468Snon slp->sl_error |= PDMAERR; 760240325Sjhb device_printf(slp->sl_dev, 761240325Sjhb "data read count error %x != %x (%x)\n", 762240325Sjhb sc->sc_cnt, cnt, 76379697Snon cb->ccb_scp.scp_datalen); 76467468Snon } 76567468Snon } 76667468Snon sc->sc_cnt = cnt; 76779697Snon scsi_low_data_finish(slp); 76867468Snon } 76967468Snon else 77067468Snon { 77167468Snon 772240325Sjhb device_printf(slp->sl_dev, "data phase miss\n"); 77367468Snon slp->sl_error |= PDMAERR; 77467468Snon } 77567468Snon} 77667468Snon 77767468Snon#define RFIFO_CRIT 64 77879697Snon#define WFIFO_CRIT 32 77967468Snon 78067468Snonstatic void 78179697Snonnsp_data_padding(sc, direction, count) 78267468Snon struct nsp_softc *sc; 78379697Snon int direction; 78479697Snon u_int count; 78567468Snon{ 78679697Snon bus_space_tag_t bst = sc->sc_iot; 78779697Snon bus_space_handle_t bsh = sc->sc_ioh; 78879697Snon 78979697Snon if (count > NSP_MAX_DATA_SIZE) 79079697Snon count = NSP_MAX_DATA_SIZE; 79179697Snon 79279697Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, XFERMR_XEN | XFERMR_IO8); 79379697Snon if (direction == SCSI_LOW_READ) 79479697Snon { 79579697Snon while (count -- > 0) 79679697Snon (void) bus_space_read_1(bst, bsh, nsp_fifodr); 79779697Snon } 79879697Snon else 79979697Snon { 80079697Snon while (count -- > 0) 80179697Snon (void) bus_space_write_1(bst, bsh, nsp_fifodr, 0); 80279697Snon } 80379697Snon nsp_cr_write_1(bst, bsh, NSPR_XFERMR, sc->sc_xfermr); 80479697Snon} 80579697Snon 80679697Snonstatic int 80779697Snonnsp_read_fifo(sc, suspendio) 80879697Snon struct nsp_softc *sc; 80979697Snon int suspendio; 81079697Snon{ 81167468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 81267468Snon bus_space_tag_t bst = sc->sc_iot; 81367468Snon bus_space_handle_t bsh = sc->sc_ioh; 81479697Snon u_int res; 81567468Snon 81679697Snon res = nsp_fifo_count(sc); 81779697Snon if (res == sc->sc_cnt) 81879697Snon return 0; 81967468Snon 82079697Snon#ifdef NSP_DEBUG 82179697Snon if (res < sc->sc_cnt || res == (u_int) -1) 82267468Snon { 823240325Sjhb device_printf(slp->sl_dev, 824240325Sjhb "strange fifo ack count 0x%x < 0x%x\n", res, sc->sc_cnt); 82579697Snon return 0; 82679697Snon } 82779697Snon#endif /* NSP_DEBUG */ 82879697Snon 82979697Snon res = res - sc->sc_cnt; 83079697Snon if (res > slp->sl_scp.scp_datalen) 83179697Snon { 83279697Snon if ((slp->sl_error & PDMAERR) == 0) 83379697Snon { 834240325Sjhb device_printf(slp->sl_dev, "data overrun 0x%x > 0x%x\n", 835240325Sjhb res, slp->sl_scp.scp_datalen); 83679697Snon } 83779697Snon 83879697Snon slp->sl_error |= PDMAERR; 83979697Snon slp->sl_scp.scp_datalen = 0; 84079697Snon 84179697Snon if ((slp->sl_flags & HW_READ_PADDING) == 0) 84279697Snon { 843240325Sjhb device_printf(slp->sl_dev, "read padding required\n"); 84479697Snon return 0; 84579697Snon } 84679697Snon 84779697Snon nsp_data_padding(sc, SCSI_LOW_READ, res); 84879697Snon sc->sc_cnt += res; 84979697Snon return 1; /* padding start */ 85079697Snon } 85179697Snon 85279697Snon if (suspendio > 0 && slp->sl_scp.scp_datalen >= suspendio) 85379697Snon res = suspendio; 85479697Snon 85579697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 85679697Snon { 85779697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 85879697Snon { 85979697Snon res &= ~3; 86079697Snon bus_space_read_region_4(sc->sc_memt, sc->sc_memh, 0, 86179697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 86279697Snon } 86379697Snon else 86479697Snon { 86579697Snon bus_space_read_region_1(sc->sc_memt, sc->sc_memh, 0, 86679697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 86779697Snon } 86879697Snon } 86979697Snon else 87079697Snon { 87179697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 87279697Snon { 87379697Snon res &= ~3; 87479697Snon bus_space_read_multi_4(bst, bsh, nsp_fifodr, 87579697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 87679697Snon } 87779697Snon else 87879697Snon { 87979697Snon bus_space_read_multi_1(bst, bsh, nsp_fifodr, 88079697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 88179697Snon } 88279697Snon } 88379697Snon 88479697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 88579697Snon { 88679697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, 88779697Snon PARITYR_ENABLE | PARITYR_CLEAR); 88879697Snon scsi_low_assert_msg(slp, slp->sl_Tnexus, SCSI_LOW_MSG_ERROR, 1); 88979697Snon } 89079697Snon 89179697Snon slp->sl_scp.scp_data += res; 89279697Snon slp->sl_scp.scp_datalen -= res; 89379697Snon sc->sc_cnt += res; 89479697Snon return 0; 89579697Snon} 89679697Snon 89779697Snonstatic int 89879697Snonnsp_write_fifo(sc, suspendio) 89979697Snon struct nsp_softc *sc; 90079697Snon int suspendio; 90179697Snon{ 90279697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 90379697Snon bus_space_tag_t bst = sc->sc_iot; 90479697Snon bus_space_handle_t bsh = sc->sc_ioh; 90579697Snon u_int res; 90679697Snon register u_int8_t stat; 90779697Snon 90879697Snon if (suspendio > 0) 90979697Snon { 91079697Snon#ifdef NSP_DEBUG 91179697Snon if ((slp->sl_scp.scp_datalen % WFIFO_CRIT) != 0) 91279697Snon { 913240325Sjhb device_printf(slp->sl_dev, 914240325Sjhb "strange write length 0x%x\n", 915240325Sjhb slp->sl_scp.scp_datalen); 91679697Snon } 91779697Snon#endif /* NSP_DEBUG */ 91879697Snon res = slp->sl_scp.scp_datalen % suspendio; 91967468Snon if (res == 0) 92067468Snon { 92179697Snon res = suspendio; 92267468Snon } 92379697Snon } 92479697Snon else 92579697Snon { 92679697Snon res = WFIFO_CRIT; 92779697Snon } 92867468Snon 92979697Snon if (res > slp->sl_scp.scp_datalen) 93079697Snon res = slp->sl_scp.scp_datalen; 93167468Snon 93279697Snon /* XXX: reconfirm! */ 93379697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 93479697Snon if (stat != PHASE_DATAOUT) 93579697Snon return 0; 93667468Snon 93779697Snon if ((sc->sc_xfermr & (XFERMR_MEM32 | XFERMR_MEM8)) != 0) 93879697Snon { 93979697Snon if ((sc->sc_xfermr & XFERMR_MEM32) != 0) 94079697Snon { 94179697Snon bus_space_write_region_4(sc->sc_memt, sc->sc_memh, 0, 94279697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 94379697Snon } 94467468Snon else 94579697Snon { 94679697Snon bus_space_write_region_1(sc->sc_memt, sc->sc_memh, 0, 94779697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 94879697Snon } 94979697Snon } 95079697Snon else 95179697Snon { 95279697Snon if ((sc->sc_xfermr & XFERMR_IO32) != 0) 95379697Snon { 95479697Snon bus_space_write_multi_4(bst, bsh, nsp_fifodr, 95579697Snon (u_int32_t *) slp->sl_scp.scp_data, res >> 2); 95679697Snon } 95779697Snon else 95879697Snon { 95979697Snon bus_space_write_multi_1(bst, bsh, nsp_fifodr, 96079697Snon (u_int8_t *) slp->sl_scp.scp_data, res); 96179697Snon } 96279697Snon } 96367468Snon 96479697Snon slp->sl_scp.scp_datalen -= res; 96579697Snon slp->sl_scp.scp_data += res; 96679697Snon sc->sc_cnt += res; 96779697Snon return 0; 96879697Snon} 96979697Snon 97079697Snonstatic int 97179697Snonnsp_wait_interrupt(sc) 97279697Snon struct nsp_softc *sc; 97379697Snon{ 97479697Snon bus_space_tag_t bst = sc->sc_iot; 97579697Snon bus_space_handle_t bsh = sc->sc_ioh; 97679697Snon int tout; 97779697Snon register u_int8_t isrc; 97879697Snon 97979697Snon for (tout = 0; tout < DEV_BSIZE / 10; tout ++) 98079697Snon { 98179697Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 98279697Snon if ((isrc & (IRQSR_SCSI | IRQSR_FIFO)) != 0) 98367468Snon { 98479697Snon if ((isrc & IRQSR_FIFO) != 0) 98579697Snon { 98679697Snon bus_space_write_1(bst, bsh, 98779697Snon nsp_irqcr, IRQCR_FIFOCL); 98879697Snon } 98979697Snon return 1; 99067468Snon } 991240172Sjhb DELAY(1); 99279697Snon } 99379697Snon return 0; 99479697Snon} 99579697Snon 99679697Snonstatic void 99779697Snonnsp_pio_read(sc, suspendio) 99879697Snon struct nsp_softc *sc; 99979697Snon int suspendio; 100079697Snon{ 100179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 100279697Snon bus_space_tag_t bst = sc->sc_iot; 100379697Snon bus_space_handle_t bsh = sc->sc_ioh; 100479697Snon int tout, padding, datalen; 100579697Snon register u_int8_t stat, fstat; 100679697Snon 100779697Snon padding = 0; 100879697Snon tout = sc->sc_tmaxcnt; 100979697Snon slp->sl_flags |= HW_PDMASTART; 101079697Snon datalen = slp->sl_scp.scp_datalen; 101179697Snon 101279697SnonReadLoop: 101379697Snon while (1) 101479697Snon { 101579697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 101679697Snon if (stat == (u_int8_t) -1) 101779697Snon return; 101879697Snon 101979697Snon /* out of data phase */ 102079697Snon if ((stat & SCBUSMON_PHMASK) != PHASE_DATAIN) 102179697Snon { 102279697Snon nsp_read_fifo(sc, 0); 102379697Snon return; 102479697Snon } 102579697Snon 102679697Snon /* data phase */ 102779697Snon fstat = bus_space_read_1(bst, bsh, nsp_fifosr); 102879697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 102979697Snon { 103079697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 103179697Snon { 103279697Snon bus_space_write_1(bst, bsh, nsp_irqcr, 103379697Snon IRQCR_FIFOCL); 103479697Snon } 103579697Snon 103679697Snon if (suspendio > 0) 103779697Snon { 103879697Snon padding |= nsp_read_fifo(sc, suspendio); 103979697Snon } 104079697Snon else 104179697Snon { 104279697Snon padding |= nsp_read_fifo(sc, 0); 104379697Snon } 104479697Snon 104579697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 104679697Snon break; 104779697Snon } 104867468Snon else 104967468Snon { 105079697Snon if (padding == 0 && slp->sl_scp.scp_datalen <= 0) 105179697Snon return; 105279697Snon 105379697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 105479697Snon break; 105579697Snon 1056240172Sjhb DELAY(1); 105767468Snon } 105867468Snon 105979697Snon if ((-- tout) <= 0) 106079697Snon { 1061240325Sjhb device_printf(slp->sl_dev, "nsp_pio_read: timeout\n"); 106279697Snon return; 106379697Snon } 106467468Snon } 106567468Snon 106679697Snon 106779697Snon if (slp->sl_scp.scp_datalen > 0 && 106879697Snon slp->sl_scp.scp_datalen > datalen - nsp_read_interrupt_bytes) 106979697Snon { 107079697Snon if (nsp_wait_interrupt(sc) != 0) 107179697Snon goto ReadLoop; 107279697Snon } 107367468Snon} 107467468Snon 107567468Snonstatic void 107679697Snonnsp_pio_write(sc, suspendio) 107767468Snon struct nsp_softc *sc; 107879697Snon int suspendio; 107967468Snon{ 108067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 108167468Snon bus_space_tag_t bst = sc->sc_iot; 108267468Snon bus_space_handle_t bsh = sc->sc_ioh; 108379697Snon u_int rcount, acount; 108479697Snon int tout, datalen; 108579697Snon register u_int8_t stat, fstat; 108667468Snon 108779697Snon tout = sc->sc_tmaxcnt; 108867468Snon slp->sl_flags |= HW_PDMASTART; 108979697Snon datalen = slp->sl_scp.scp_datalen; 109079697Snon 109179697SnonWriteLoop: 109279697Snon while (1) 109367468Snon { 109479697Snon stat = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON) & SCBUSMON_PHMASK; 109567468Snon if (stat != PHASE_DATAOUT) 109679697Snon return; 109767468Snon 109879697Snon if (slp->sl_scp.scp_datalen <= 0) 109979697Snon { 110079697Snon if (sc->sc_dataout_timeout == 0) 110179697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 110279697Snon return; 110379697Snon } 110467468Snon 110579697Snon fstat = bus_space_read_1(bst, bsh, nsp_fifosr); 110679697Snon if ((fstat & FIFOSR_FULLEMP) != 0) 110779697Snon { 110879697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 110979697Snon { 111079697Snon bus_space_write_1(bst, bsh, nsp_irqcr, 111179697Snon IRQCR_FIFOCL); 111279697Snon } 111367468Snon 111479697Snon if (suspendio > 0) 111579697Snon { 111679697Snon /* XXX:IMPORTANT: 111779697Snon * To avoid timeout of pcmcia bus 111879697Snon * (not scsi bus!), we should check 111979697Snon * the scsi device sends us request 112079697Snon * signals, which means the scsi device 112179697Snon * is ready to recieve data without 112279697Snon * heavy delays. 112379697Snon */ 112482784Snon if ((slp->sl_scp.scp_datalen % suspendio) == 0) 112579697Snon { 112682784Snon /* Step I: 112782784Snon * fill the nsp fifo, and waiting for 112882784Snon * the fifo empty. 112982784Snon */ 113079697Snon nsp_write_fifo(sc, 0); 113179697Snon } 113279697Snon else 113379697Snon { 113482784Snon /* Step II: 113582784Snon * check the request singals. 113682784Snon */ 113782784Snon acount = nsp_fifo_count(sc); 113882784Snon rcount = nsp_request_count(sc); 113982784Snon if (rcount <= acount) 114082784Snon { 114182784Snon nsp_write_fifo(sc, 0); 114279697Snon#ifdef NSP_STATICS 114382784Snon nsp_statics.device_busy ++; 114479697Snon#endif /* NSP_STATICS */ 114582784Snon } 114682784Snon else 114782784Snon { 114882784Snon nsp_write_fifo(sc, suspendio); 114982784Snon#ifdef NSP_STATICS 115082784Snon nsp_statics.device_data_write ++; 115182784Snon#endif /* NSP_STATICS */ 115282784Snon } 115379697Snon } 115479697Snon } 115579697Snon else 115679697Snon { 115779697Snon nsp_write_fifo(sc, 0); 115879697Snon } 115979697Snon 116079697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 116179697Snon break; 116267468Snon } 116367468Snon else 116467468Snon { 116579697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 116679697Snon break; 116779697Snon 1168240172Sjhb DELAY(1); 116967468Snon } 117067468Snon 117179697Snon if ((-- tout) <= 0) 117279697Snon { 1173240325Sjhb device_printf(slp->sl_dev, "nsp_pio_write: timeout\n"); 117479697Snon return; 117579697Snon } 117667468Snon } 117767468Snon 117879697Snon if (slp->sl_scp.scp_datalen > 0 && 117979697Snon slp->sl_scp.scp_datalen > datalen - nsp_write_interrupt_bytes) 118079697Snon { 118179697Snon if (nsp_wait_interrupt(sc) != 0) 118279697Snon goto WriteLoop; 118379697Snon } 118467468Snon} 118567468Snon 118667468Snonstatic int 1187189004Srdivackynsp_negate_signal(struct nsp_softc *sc, u_int8_t mask, u_char *s) 118867468Snon{ 118967468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 119067468Snon bus_space_tag_t bst = sc->sc_iot; 119167468Snon bus_space_handle_t bsh = sc->sc_ioh; 119279697Snon int wc; 119367468Snon u_int8_t regv; 119467468Snon 119579697Snon for (wc = 0; wc < NSP_DELAY_MAX / NSP_DELAY_INTERVAL; wc ++) 119667468Snon { 119767468Snon regv = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 119879697Snon if (regv == (u_int8_t) -1) 119979697Snon return -1; 120079697Snon if ((regv & mask) == 0) 120179697Snon return 1; 1202240172Sjhb DELAY(NSP_DELAY_INTERVAL); 120367468Snon } 120467468Snon 1205240325Sjhb device_printf(slp->sl_dev, "%s nsp_negate_signal timeout\n", s); 120679697Snon return -1; 120767468Snon} 120867468Snon 120967468Snonstatic int 121079697Snonnsp_xfer(sc, buf, len, phase, clear_atn) 121167468Snon struct nsp_softc *sc; 121267468Snon u_int8_t *buf; 121367468Snon int len; 121467468Snon int phase; 121579697Snon int clear_atn; 121667468Snon{ 121767468Snon bus_space_tag_t bst = sc->sc_iot; 121867468Snon bus_space_handle_t bsh = sc->sc_ioh; 121979697Snon int ptr, rv; 122067468Snon 122167468Snon for (ptr = 0; len > 0; len --, ptr ++) 122267468Snon { 122367468Snon rv = nsp_expect_signal(sc, phase, SCBUSMON_REQ); 122467468Snon if (rv <= 0) 122567468Snon goto out; 122667468Snon 122779697Snon if (len == 1 && clear_atn != 0) 122867468Snon { 122967468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 123067468Snon SCBUSCR_ADIR | SCBUSCR_ACKEN); 123179697Snon SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow); 123267468Snon } 123367468Snon 123467468Snon if (phase & SCBUSMON_IO) 123567468Snon { 123667468Snon buf[ptr] = nsp_cr_read_1(bst, bsh, NSPR_DATAACK); 123767468Snon } 123867468Snon else 123967468Snon { 124067468Snon nsp_cr_write_1(bst, bsh, NSPR_DATAACK, buf[ptr]); 124167468Snon } 124267468Snon nsp_negate_signal(sc, SCBUSMON_ACK, "xfer<ACK>"); 124367468Snon } 124467468Snon 124567468Snonout: 124667468Snon return len; 124767468Snon} 124867468Snon 124967468Snon/************************************************************** 125067468Snon * disconnect & reselect (HW low) 125167468Snon **************************************************************/ 125267468Snonstatic int 125367468Snonnsp_reselected(sc) 125467468Snon struct nsp_softc *sc; 125567468Snon{ 125667468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 125767468Snon bus_space_tag_t bst = sc->sc_iot; 125867468Snon bus_space_handle_t bsh = sc->sc_ioh; 125967468Snon struct targ_info *ti; 126067468Snon u_int sid; 126167468Snon u_int8_t cr; 126267468Snon 126367468Snon sid = (u_int) nsp_cr_read_1(bst, bsh, NSPR_RESELR); 126467468Snon sid &= ~sc->sc_idbit; 126567468Snon sid = ffs(sid) - 1; 126667468Snon if ((ti = scsi_low_reselected(slp, sid)) == NULL) 126767468Snon return EJUSTRETURN; 126867468Snon 126967468Snon nsp_negate_signal(sc, SCBUSMON_SEL, "reselect<SEL>"); 127067468Snon 127179697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); 127279697Snon cr &= ~(SCBUSCR_BSY | SCBUSCR_ATN); 127367468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 127479697Snon cr |= SCBUSCR_ADIR | SCBUSCR_ACKEN; 127579697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 127667468Snon 127767468Snon#ifdef NSP_STATICS 127879697Snon nsp_statics.reselect ++; 127967468Snon#endif /* NSP_STATCIS */ 128067468Snon return EJUSTRETURN; 128167468Snon} 128267468Snon 128379697Snonstatic int 128467468Snonnsp_disconnected(sc, ti) 128567468Snon struct nsp_softc *sc; 128667468Snon struct targ_info *ti; 128767468Snon{ 128867468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 128979697Snon bus_space_tag_t bst = sc->sc_iot; 129079697Snon bus_space_handle_t bsh = sc->sc_ioh; 129167468Snon 129279697Snon nsp_cr_write_1(bst, bsh, NSPR_PTCLRR, PTCLRR_PT | PTCLRR_ACK | 129379697Snon PTCLRR_REQ | PTCLRR_HOST); 129479697Snon if ((sc->sc_icr & SCIENR_FIFO) != 0) 129579697Snon { 129679697Snon sc->sc_icr &= ~SCIENR_FIFO; 129779697Snon nsp_cr_write_1(bst, bsh, NSPR_SCIENR, sc->sc_icr); 129879697Snon } 129979697Snon sc->sc_cnt = 0; 130079697Snon sc->sc_dataout_timeout = 0; 130167468Snon#ifdef NSP_STATICS 130279697Snon nsp_statics.disconnect ++; 130367468Snon#endif /* NSP_STATICS */ 130467468Snon scsi_low_disconnected(slp, ti); 130567468Snon return 1; 130667468Snon} 130767468Snon 130867468Snon/************************************************************** 130967468Snon * SEQUENCER 131067468Snon **************************************************************/ 131192739Salfredstatic void nsp_error(struct nsp_softc *, u_char *, u_int8_t, u_int8_t, u_int8_t); 131267468Snon 131367468Snonstatic void 1314189004Srdivackynsp_error(struct nsp_softc * sc, u_char *s, u_int8_t isrc, u_int8_t ph, 1315189004Srdivacky u_int8_t irqphs) 131667468Snon{ 131767468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 131867468Snon 1319240325Sjhb device_printf(slp->sl_dev, "%s\n", s); 1320240325Sjhb device_printf(slp->sl_dev, "isrc 0x%x scmon 0x%x irqphs 0x%x\n", 1321240325Sjhb (u_int) isrc, (u_int) ph, (u_int) irqphs); 132267468Snon} 132367468Snon 132467468Snonstatic int 132579697Snonnsp_target_nexus_establish(sc) 132667468Snon struct nsp_softc *sc; 132767468Snon{ 132879697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 132967468Snon bus_space_tag_t bst = sc->sc_iot; 133067468Snon bus_space_handle_t bsh = sc->sc_ioh; 133179697Snon struct targ_info *ti = slp->sl_Tnexus; 133273025Snon struct nsp_targ_info *nti = (void *) ti; 133367468Snon 133467468Snon /* setup synch transfer registers */ 133573025Snon nsp_cr_write_1(bst, bsh, NSPR_SYNCR, nti->nti_reg_syncr); 133673025Snon nsp_cr_write_1(bst, bsh, NSPR_ACKWIDTH, nti->nti_reg_ackwidth); 133767468Snon 133879697Snon /* setup pdma fifo (minimum) */ 133979697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, SCSI_LOW_READ, 0); 134079697Snon return 0; 134179697Snon} 134279697Snon 134379697Snonstatic int 134479697Snonnsp_lun_nexus_establish(sc) 134579697Snon struct nsp_softc *sc; 134679697Snon{ 134779697Snon 134879697Snon return 0; 134979697Snon} 135079697Snon 135179697Snonstatic int 135279697Snonnsp_ccb_nexus_establish(sc) 135379697Snon struct nsp_softc *sc; 135479697Snon{ 135579697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 135679697Snon struct slccb *cb = slp->sl_Qnexus; 135779697Snon 135879697Snon sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 135979697Snon 136067468Snon /* setup pdma fifo */ 136179697Snon nsp_setup_fifo(sc, NSP_FIFO_ON, 136279697Snon slp->sl_scp.scp_direction, slp->sl_scp.scp_datalen); 136367468Snon 136479697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 136579697Snon { 136679697Snon if (sc->sc_suspendio > 0 && 136779697Snon (nsp_io_control & NSP_READ_FIFO_INTERRUPTS) != 0) 136879697Snon { 136979697Snon sc->sc_icr |= SCIENR_FIFO; 137079697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, 137179697Snon NSPR_SCIENR, sc->sc_icr); 137279697Snon } 137379697Snon } 137479697Snon else 137579697Snon { 137679697Snon if (sc->sc_suspendio > 0 && 137779697Snon (nsp_io_control & NSP_WRITE_FIFO_INTERRUPTS) != 0) 137879697Snon { 137979697Snon sc->sc_icr |= SCIENR_FIFO; 138079697Snon nsp_cr_write_1(sc->sc_iot, sc->sc_ioh, 138179697Snon NSPR_SCIENR, sc->sc_icr); 138279697Snon } 138379697Snon } 138467468Snon return 0; 138567468Snon} 138667468Snon 138779697Snonstatic int 1388189004Srdivackynsp_phase_match(struct nsp_softc *sc, u_int8_t phase, u_int8_t stat) 138979697Snon{ 139079697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 139179697Snon 139279697Snon if ((stat & SCBUSMON_PHMASK) != phase) 139379697Snon { 1394240325Sjhb device_printf(slp->sl_dev, "phase mismatch 0x%x != 0x%x\n", 1395240325Sjhb (u_int) phase, (u_int) stat); 139679697Snon return EINVAL; 139779697Snon } 139879697Snon 139979697Snon if ((stat & SCBUSMON_REQ) == 0) 140079697Snon return EINVAL; 140179697Snon 140279697Snon return 0; 140379697Snon} 140479697Snon 140567468Snonint 140667468Snonnspintr(arg) 140767468Snon void *arg; 140867468Snon{ 140967468Snon struct nsp_softc *sc = arg; 141067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 141167468Snon bus_space_tag_t bst = sc->sc_iot; 141267468Snon bus_space_handle_t bsh = sc->sc_ioh; 141367468Snon struct targ_info *ti; 141467468Snon struct buf *bp; 141579697Snon u_int derror, flags; 141667468Snon int len, rv; 141767468Snon u_int8_t isrc, ph, irqphs, cr, regv; 141867468Snon 141967468Snon /******************************************* 142067468Snon * interrupt check 142167468Snon *******************************************/ 142267468Snon if (slp->sl_flags & HW_INACTIVE) 142367468Snon return 0; 142467468Snon 142567468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_IRQDIS); 142667468Snon isrc = bus_space_read_1(bst, bsh, nsp_irqsr); 142779697Snon if (isrc == (u_int8_t) -1 || (isrc & IRQSR_MASK) == 0) 142867468Snon { 142967468Snon bus_space_write_1(bst, bsh, nsp_irqcr, 0); 143067468Snon return 0; 143167468Snon } 143267468Snon 143367468Snon /* XXX: IMPORTANT 143467468Snon * Do not read an irqphs register if no scsi phase interrupt. 143567468Snon * Unless, you should lose a scsi phase interrupt. 143667468Snon */ 143767468Snon ph = nsp_cr_read_1(bst, bsh, NSPR_SCBUSMON); 143867468Snon if ((isrc & IRQSR_SCSI) != 0) 143967468Snon { 144067468Snon irqphs = nsp_cr_read_1(bst, bsh, NSPR_IRQPHS); 144167468Snon } 144267468Snon else 144367468Snon irqphs = 0; 144467468Snon 144567468Snon /* 144667468Snon * timer interrupt handler (scsi vs timer interrupts) 144767468Snon */ 144867468Snon if (sc->sc_timer != 0) 144967468Snon { 145067468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 145167468Snon nsp_cr_write_1(bst, bsh, NSPR_TIMERCNT, 0); 145267468Snon sc->sc_timer = 0; 145367468Snon } 145467468Snon 145579697Snon /* check a timer interrupt */ 145679697Snon regv = 0; 145779697Snon if ((isrc & IRQSR_TIMER) != 0) 145867468Snon { 145979697Snon if ((isrc & IRQSR_MASK) == IRQSR_TIMER && sc->sc_seltout == 0) 146079697Snon { 146179697Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_TIMERCL); 146279697Snon return 1; 146379697Snon } 146479697Snon regv |= IRQCR_TIMERCL; 146567468Snon } 146667468Snon 146779697Snon /* check a fifo interrupt */ 146879697Snon if ((isrc & IRQSR_FIFO) != 0) 146979697Snon { 147079697Snon regv |= IRQCR_FIFOCL; 147179697Snon } 147267468Snon 147379697Snon /* OK. enable all interrupts */ 147479697Snon bus_space_write_1(bst, bsh, nsp_irqcr, regv); 147579697Snon 147667468Snon /******************************************* 147767468Snon * debug section 147867468Snon *******************************************/ 147967468Snon#ifdef NSP_DEBUG 148067468Snon if (nsp_debug) 148167468Snon { 148279697Snon nsp_error(sc, "current status", isrc, ph, irqphs); 148367468Snon scsi_low_print(slp, NULL); 1484131915Smarcel#ifdef KDB 148567468Snon if (nsp_debug > 1) 1486240172Sjhb kdb_enter(KDB_WHY_CAM, "nsp"); 1487131915Smarcel#endif /* KDB */ 148867468Snon } 148967468Snon#endif /* NSP_DEBUG */ 149067468Snon 149167468Snon /******************************************* 149267468Snon * Parse hardware SCSI irq reasons register 149367468Snon *******************************************/ 149467468Snon if ((isrc & IRQSR_SCSI) != 0) 149567468Snon { 149667468Snon if ((irqphs & IRQPHS_RST) != 0) 149767468Snon { 149867468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 149967468Snon "bus reset (power off?)"); 150067468Snon return 1; 150167468Snon } 150267468Snon 150367468Snon if ((irqphs & IRQPHS_RSEL) != 0) 150467468Snon { 150567468Snon bus_space_write_1(bst, bsh, nsp_irqcr, IRQCR_RESCL); 150667468Snon if (nsp_reselected(sc) == EJUSTRETURN) 150767468Snon return 1; 150867468Snon } 150967468Snon 151067468Snon if ((irqphs & (IRQPHS_PCHG | IRQPHS_LBF)) == 0) 151167468Snon return 1; 151267468Snon } 151367468Snon 151467468Snon /******************************************* 151567468Snon * nexus check 151667468Snon *******************************************/ 151779697Snon if ((ti = slp->sl_Tnexus) == NULL) 151867468Snon { 151967468Snon /* unknown scsi phase changes */ 152079697Snon nsp_error(sc, "unknown scsi phase changes", isrc, ph, irqphs); 152167468Snon return 0; 152267468Snon } 152367468Snon 152467468Snon /******************************************* 152567468Snon * aribitration & selection 152667468Snon *******************************************/ 152767468Snon switch (ti->ti_phase) 152867468Snon { 152967468Snon case PH_SELSTART: 153067468Snon if ((ph & SCBUSMON_BSY) == 0) 153167468Snon { 153267468Snon if (sc->sc_seltout >= NSP_SELTIMEOUT) 153367468Snon { 153467468Snon sc->sc_seltout = 0; 153567468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, 0); 153667468Snon return nsp_disconnected(sc, ti); 153767468Snon } 153867468Snon sc->sc_seltout ++; 153979697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 154067468Snon return 1; 154167468Snon } 154267468Snon 154367468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 154479697Snon nsphw_selection_done_and_expect_msgout(sc); 154567468Snon return 1; 154667468Snon 154779697Snon case PH_SELECTED: 154879697Snon if ((isrc & IRQSR_SCSI) == 0) 154979697Snon return 1; 155079697Snon 155179697Snon nsp_target_nexus_establish(sc); 155279697Snon break; 155379697Snon 155467468Snon case PH_RESEL: 155579697Snon if ((isrc & IRQSR_SCSI) == 0) 155679697Snon return 1; 155779697Snon 155879697Snon nsp_target_nexus_establish(sc); 155967468Snon if ((ph & SCBUSMON_PHMASK) != PHASE_MSGIN) 156067468Snon { 1561240325Sjhb device_printf(slp->sl_dev, 1562240325Sjhb "unexpected phase after reselect\n"); 156379697Snon slp->sl_error |= FATALIO; 156467468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); 156567468Snon return 1; 156667468Snon } 156779697Snon break; 156867468Snon 156979697Snon case PH_DATA: 157079697Snon if ((isrc & IRQSR_SCSI) != 0) 157179697Snon break; 157279697Snon if ((isrc & IRQSR_FIFO) != 0) 157379697Snon { 157479697Snon if (NSP_IS_PHASE_DATA(ph) == 0) 157579697Snon return 1; 157679697Snon irqphs = (ph & IRQPHS_PHMASK); 157779697Snon break; 157879697Snon } 157979697Snon return 1; 158079697Snon 158167468Snon default: 158279697Snon if ((isrc & IRQSR_SCSI) == 0) 158367468Snon return 1; 158467468Snon break; 158567468Snon } 158667468Snon 158767468Snon /******************************************* 158879697Snon * data phase control 158967468Snon *******************************************/ 159067468Snon if (slp->sl_flags & HW_PDMASTART) 159179697Snon { 159279697Snon if ((isrc & IRQSR_SCSI) != 0 && 159379697Snon NSP_IS_IRQPHS_DATA(irqphs) == 0) 159479697Snon { 159579697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 159679697Snon nsp_pio_read(sc, 0); 159779697Snon nsp_pdma_end(sc, ti); 159879697Snon } 159979697Snon } 160067468Snon 160179697Snon /******************************************* 160279697Snon * scsi seq 160379697Snon *******************************************/ 160467468Snon if (slp->sl_msgphase != 0 && (irqphs & IRQPHS_LBF) != 0) 160567468Snon return nsp_disconnected(sc, ti); 160667468Snon 160767468Snon /* check unexpected bus free state */ 160867468Snon if (ph == 0) 160967468Snon { 161079697Snon nsp_error(sc, "unexpected bus free", isrc, ph, irqphs); 161167468Snon return nsp_disconnected(sc, ti); 161267468Snon } 161367468Snon 161467468Snon /* check normal scsi phase */ 161579697Snon switch (irqphs & IRQPHS_PHMASK) 161667468Snon { 161779697Snon case IRQPHS_CMD: 161879697Snon if (nsp_phase_match(sc, PHASE_CMD, ph) != 0) 161967468Snon return 1; 162067468Snon 162167468Snon SCSI_LOW_SETUP_PHASE(ti, PH_CMD); 162267468Snon if (scsi_low_cmd(slp, ti) != 0) 162379697Snon { 162479697Snon scsi_low_attention(slp); 162579697Snon } 162667468Snon 162767468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR); 162867468Snon for (len = 0; len < slp->sl_scp.scp_cmdlen; len ++) 162967468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDDR, 163067468Snon slp->sl_scp.scp_cmd[len]); 163167468Snon 163267468Snon nsp_cr_write_1(bst, bsh, NSPR_CMDCR, CMDCR_PTCLR | CMDCR_EXEC); 163367468Snon break; 163467468Snon 163579697Snon case IRQPHS_DATAOUT: 163667468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 163767468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) 163879697Snon { 163979697Snon scsi_low_attention(slp); 164079697Snon } 164167468Snon 164279697Snon nsp_pio_write(sc, sc->sc_suspendio); 164367468Snon break; 164467468Snon 164579697Snon case IRQPHS_DATAIN: 164667468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 164767468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) 164879697Snon { 164979697Snon scsi_low_attention(slp); 165079697Snon } 165167468Snon 165279697Snon nsp_pio_read(sc, sc->sc_suspendio); 165367468Snon break; 165467468Snon 165579697Snon case IRQPHS_STATUS: 165679697Snon if (nsp_phase_match(sc, PHASE_STATUS, ph) != 0) 165767468Snon return 1; 165867468Snon 165967468Snon SCSI_LOW_SETUP_PHASE(ti, PH_STAT); 166079697Snon regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); 166179697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 166279697Snon { 166379697Snon nsp_cr_write_1(bst, bsh, NSPR_PARITYR, 166479697Snon PARITYR_ENABLE | PARITYR_CLEAR); 166579697Snon derror = SCSI_LOW_DATA_PE; 166679697Snon } 166779697Snon else 166879697Snon derror = 0; 166979697Snon 167079697Snon /* assert ACK */ 167179697Snon cr = SCBUSCR_ACK | nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR); 167279697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 167379697Snon 167479697Snon if (scsi_low_statusin(slp, ti, derror | regv) != 0) 167579697Snon { 167679697Snon scsi_low_attention(slp); 167779697Snon } 167879697Snon 167979697Snon /* check REQ nagated */ 168079697Snon nsp_negate_signal(sc, SCBUSMON_REQ, "statin<REQ>"); 168179697Snon 168279697Snon /* deassert ACK */ 168379697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 168479697Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 168567468Snon break; 168667468Snon 168779697Snon case IRQPHS_MSGOUT: 168879697Snon if (nsp_phase_match(sc, PHASE_MSGOUT, ph) != 0) 168979697Snon return 1; 169067468Snon 169179697Snon#ifdef NSP_MSGOUT_SERIALIZE 169267468Snon /* 169367468Snon * XXX: NSP QUIRK 169467468Snon * NSP invoke interrupts only in the case of scsi phase changes, 169567468Snon * therefore we should poll the scsi phase here to catch 169667468Snon * the next "msg out" if exists (no scsi phase changes). 169767468Snon */ 169867468Snon rv = len = 16; 169967468Snon do { 170067468Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 170179697Snon flags = (ti->ti_ophase != ti->ti_phase) ? 170279697Snon SCSI_LOW_MSGOUT_INIT : 0; 170379697Snon len = scsi_low_msgout(slp, ti, flags); 170467468Snon 170579697Snon if (len > 1 && slp->sl_atten == 0) 170667468Snon { 170779697Snon scsi_low_attention(slp); 170879697Snon } 170979697Snon 171079697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 171179697Snon slp->sl_clear_atten) != 0) 171279697Snon { 171379697Snon slp->sl_error |= FATALIO; 171479697Snon nsp_error(sc, "MSGOUT: xfer short", 171567468Snon isrc, ph, irqphs); 171667468Snon } 171767468Snon 171867468Snon /* catch a next signal */ 171967468Snon rv = nsp_expect_signal(sc, PHASE_MSGOUT, SCBUSMON_REQ); 172067468Snon } 172167468Snon while (rv > 0 && len -- > 0); 172279697Snon 172379697Snon#else /* !NSP_MSGOUT_SERIALIZE */ 172479697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 172579697Snon flags = SCSI_LOW_MSGOUT_UNIFY; 172679697Snon if (ti->ti_ophase != ti->ti_phase) 172779697Snon flags |= SCSI_LOW_MSGOUT_INIT; 172879697Snon len = scsi_low_msgout(slp, ti, flags); 172979697Snon 173079697Snon if (len > 1 && slp->sl_atten == 0) 173179697Snon { 173279697Snon scsi_low_attention(slp); 173379697Snon } 173479697Snon 173579697Snon if (nsp_xfer(sc, ti->ti_msgoutstr, len, PHASE_MSGOUT, 173679697Snon slp->sl_clear_atten) != 0) 173779697Snon { 173879697Snon nsp_error(sc, "MSGOUT: xfer short", isrc, ph, irqphs); 173979697Snon } 174079697Snon 174179697Snon#endif /* !NSP_MSGOUT_SERIALIZE */ 174267468Snon break; 174367468Snon 174479697Snon case IRQPHS_MSGIN: 174579697Snon if (nsp_phase_match(sc, PHASE_MSGIN, ph) != 0) 174679697Snon return 1; 174767468Snon 174867468Snon /* 174967468Snon * XXX: NSP QUIRK 175067468Snon * NSP invoke interrupts only in the case of scsi phase changes, 175167468Snon * therefore we should poll the scsi phase here to catch 175267468Snon * the next "msg in" if exists (no scsi phase changes). 175367468Snon */ 175467468Snon rv = len = 16; 175567468Snon do { 175679697Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); 175779697Snon 175867468Snon /* read a data */ 175967468Snon regv = nsp_cr_read_1(bst, bsh, NSPR_DATA); 176079697Snon if (nsp_cr_read_1(bst, bsh, NSPR_PARITYR) & PARITYR_PE) 176179697Snon { 176279697Snon nsp_cr_write_1(bst, bsh, 176379697Snon NSPR_PARITYR, 176479697Snon PARITYR_ENABLE | PARITYR_CLEAR); 176579697Snon derror = SCSI_LOW_DATA_PE; 176679697Snon } 176779697Snon else 176879697Snon { 176979697Snon derror = 0; 177079697Snon } 177167468Snon 177267468Snon /* assert ack */ 177379697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) | SCBUSCR_ACK; 177467468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 177579697Snon 177679697Snon if (scsi_low_msgin(slp, ti, regv | derror) == 0) 177779697Snon { 177879697Snon if (scsi_low_is_msgout_continue(ti, 0) != 0) 177979697Snon { 178079697Snon scsi_low_attention(slp); 178179697Snon } 178279697Snon } 178379697Snon 178479697Snon /* check REQ nagated */ 178567468Snon nsp_negate_signal(sc, SCBUSMON_REQ, "msgin<REQ>"); 178667468Snon 178767468Snon /* deassert ack */ 178879697Snon cr = nsp_cr_read_1(bst, bsh, NSPR_SCBUSCR) & (~SCBUSCR_ACK); 178967468Snon nsp_cr_write_1(bst, bsh, NSPR_SCBUSCR, cr); 179067468Snon 179167468Snon /* catch a next signal */ 179267468Snon rv = nsp_expect_signal(sc, PHASE_MSGIN, SCBUSMON_REQ); 179367468Snon } 179467468Snon while (rv > 0 && len -- > 0); 179567468Snon break; 179667468Snon 179767468Snon default: 179879697Snon slp->sl_error |= FATALIO; 179979697Snon nsp_error(sc, "unknown scsi phase", isrc, ph, irqphs); 180067468Snon break; 180167468Snon } 180267468Snon 180367468Snon return 1; 180467468Snon 180579697Snon#if 0 180667468Snontimerout: 180779697Snon nsp_start_timer(sc, NSP_TIMER_1MS); 180867468Snon return 0; 180979697Snon#endif 181067468Snon} 181179697Snon 181279697Snonstatic int 181379697Snonnsp_timeout(sc) 181479697Snon struct nsp_softc *sc; 181579697Snon{ 181679697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 181779697Snon bus_space_tag_t iot = sc->sc_iot; 181879697Snon bus_space_handle_t ioh = sc->sc_ioh; 181979697Snon int tout; 182079697Snon u_int8_t ph, regv; 182179697Snon 182279697Snon if (slp->sl_Tnexus == NULL) 182379697Snon return 0; 182479697Snon 182579697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 182679697Snon switch (ph & SCBUSMON_PHMASK) 182779697Snon { 182879697Snon case PHASE_DATAOUT: 182979697Snon if (sc->sc_dataout_timeout == 0) 183079697Snon break; 183179697Snon 183279697Snon /* check a fifo empty */ 183379697Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 183479697Snon if ((regv & FIFOSR_FULLEMP) == 0) 183579697Snon break; 183679697Snon bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); 183779697Snon 183879697Snon /* check still requested */ 183979697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 184079697Snon if ((ph & SCBUSMON_REQ) == 0) 184179697Snon break; 184279697Snon /* check timeout */ 184379697Snon if ((-- sc->sc_dataout_timeout) > 0) 184479697Snon break; 184579697Snon 184679697Snon slp->sl_error |= PDMAERR; 184779697Snon if ((slp->sl_flags & HW_WRITE_PADDING) == 0) 184879697Snon { 1849240325Sjhb device_printf(slp->sl_dev, "write padding required\n"); 185079697Snon break; 185179697Snon } 185279697Snon 185379697Snon tout = NSP_DELAY_MAX; 185479697Snon while (tout -- > 0) 185579697Snon { 185679697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 185779697Snon if ((ph & SCBUSMON_PHMASK) != PHASE_DATAOUT) 185879697Snon break; 185979697Snon regv = bus_space_read_1(iot, ioh, nsp_fifosr); 186079697Snon if ((regv & FIFOSR_FULLEMP) == 0) 186179697Snon { 1862240172Sjhb DELAY(1); 186379697Snon continue; 186479697Snon } 186579697Snon 186679697Snon bus_space_write_1(iot, ioh, nsp_irqcr, IRQCR_FIFOCL); 186779697Snon nsp_data_padding(sc, SCSI_LOW_WRITE, 32); 186879697Snon } 186979697Snon ph = nsp_cr_read_1(iot, ioh, NSPR_SCBUSMON); 187079697Snon if ((ph & SCBUSMON_PHMASK) == PHASE_DATAOUT) 187179697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 187279697Snon break; 187379697Snon 187479697Snon default: 187579697Snon break; 187679697Snon } 187779697Snon return 0; 187879697Snon} 1879