tmc18c30.c revision 131920
179697Snon/* $NecBSD: tmc18c30.c,v 1.28.12.3 2001/06/19 04:35:48 honda Exp $ */ 267468Snon/* $NetBSD$ */ 367468Snon 467468Snon#define STG_DEBUG 567468Snon#define STG_STATICS 679697Snon#define STG_IO_CONTROL_FLAGS (STG_FIFO_INTERRUPTS | STG_WAIT_FOR_SELECT) 767468Snon 867468Snon/* 967468Snon * [NetBSD for NEC PC-98 series] 1079697Snon * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001 1167468Snon * NetBSD/pc98 porting staff. All rights reserved. 1279697Snon * Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001 1367468Snon * Naofumi HONDA. All rights reserved. 1467468Snon * Copyright (c) 1996, 1997, 1998, 1999 1567468Snon * Kouichi Matsuda. All rights reserved. 1667468Snon * 1767468Snon * Redistribution and use in source and binary forms, with or without 1867468Snon * modification, are permitted provided that the following conditions 1967468Snon * are met: 2067468Snon * 1. Redistributions of source code must retain the above copyright 2167468Snon * notice, this list of conditions and the following disclaimer. 2267468Snon * 2. Redistributions in binary form must reproduce the above copyright 2367468Snon * notice, this list of conditions and the following disclaimer in the 2467468Snon * documentation and/or other materials provided with the distribution. 2567468Snon * 3. The name of the author may not be used to endorse or promote products 2667468Snon * derived from this software without specific prior written permission. 2767468Snon * 2867468Snon * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 2967468Snon * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 3067468Snon * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 3167468Snon * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 3267468Snon * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 3367468Snon * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 3467468Snon * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3567468Snon * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3667468Snon * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 3767468Snon * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 3867468Snon * POSSIBILITY OF SUCH DAMAGE. 3967468Snon */ 40119420Sobrien 41119420Sobrien#include <sys/cdefs.h> 42119420Sobrien__FBSDID("$FreeBSD: head/sys/dev/stg/tmc18c30.c 131920 2004-07-10 21:14:20Z marcel $"); 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/tmc18c30reg.h> 7067468Snon#include <i386/Cbus/dev/tmc18c30var.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.h> 7867468Snon 79126928Speter#include <compat/netbsd/dvcfg.h> 80126928Speter#include <compat/netbsd/physio_proc.h> 8167468Snon 8267468Snon#include <cam/scsi/scsi_low.h> 8367468Snon#include <dev/stg/tmc18c30reg.h> 8467468Snon#include <dev/stg/tmc18c30var.h> 8567468Snon#endif /* __FreeBSD__ */ 8667468Snon 8767468Snon/*************************************************** 8867468Snon * USER SETTINGS 8967468Snon ***************************************************/ 9067468Snon/* DEVICE CONFIGURATION FLAGS (MINOR) 9167468Snon * 9267468Snon * 0x01 DISCONECT OFF 9367468Snon * 0x02 PARITY LINE OFF 9467468Snon * 0x04 IDENTIFY MSG OFF ( = single lun) 9567468Snon * 0x08 SYNC TRANSFER OFF 9667468Snon */ 9767468Snon/* #define STG_SYNC_SUPPORT */ /* NOT YET but easy */ 9867468Snon 9967468Snon/* For the 512 fifo type: change below */ 10067468Snon#define TMC18C30_FIFOSZ 0x800 10179697Snon#define TMC18C30_FCBSZ 0x200 10267468Snon#define TMC18C50_FIFOSZ 0x2000 10379697Snon#define TMC18C50_FCBSZ 0x400 10467468Snon 10579697Snon#define STG_MAX_DATA_SIZE (64 * 1024) 10679697Snon#define STG_DELAY_MAX (2 * 1000 * 1000) 10779697Snon#define STG_DELAY_INTERVAL (1) 10879697Snon#define STG_DELAY_SELECT_POLLING_MAX (5 * 1000 * 1000) 10979697Snon 11067468Snon/*************************************************** 11167468Snon * PARAMS 11267468Snon ***************************************************/ 11367468Snon#define STG_NTARGETS 8 11467468Snon#define STG_NLUNS 8 11567468Snon 11667468Snon/*************************************************** 11767468Snon * DEBUG 11867468Snon ***************************************************/ 11967468Snon#ifdef STG_DEBUG 12089093Smsmithstatic int stg_debug; 12167468Snon#endif /* STG_DEBUG */ 12267468Snon 12367468Snon#ifdef STG_STATICS 12489093Smsmithstatic struct stg_statics { 12579697Snon int arbit_fail_0; 12679697Snon int arbit_fail_1; 12767468Snon int disconnect; 12867468Snon int reselect; 12979697Snon} stg_statics; 13067468Snon#endif /* STG_STATICS */ 13167468Snon 13267468Snon/*************************************************** 13379697Snon * IO control flags 13467468Snon ***************************************************/ 13579697Snon#define STG_FIFO_INTERRUPTS 0x0001 13679697Snon#define STG_WAIT_FOR_SELECT 0x0100 13779697Snon 13879697Snonint stg_io_control = STG_IO_CONTROL_FLAGS; 13979697Snon 14079697Snon/*************************************************** 14179697Snon * DEVICE STRUCTURE 14279697Snon ***************************************************/ 14367468Snonextern struct cfdriver stg_cd; 14467468Snon 14567468Snon/************************************************************** 14667468Snon * DECLARE 14767468Snon **************************************************************/ 14867468Snon/* static */ 14992739Salfredstatic void stg_pio_read(struct stg_softc *, struct targ_info *, u_int); 15092739Salfredstatic void stg_pio_write(struct stg_softc *, struct targ_info *, u_int); 15192739Salfredstatic int stg_xfer(struct stg_softc *, u_int8_t *, int, int, int); 15292739Salfredstatic int stg_msg(struct stg_softc *, struct targ_info *, u_int); 15392739Salfredstatic int stg_reselected(struct stg_softc *); 15492739Salfredstatic int stg_disconnected(struct stg_softc *, struct targ_info *); 15592739Salfredstatic __inline void stg_pdma_end(struct stg_softc *, struct targ_info *); 15692739Salfredstatic int stghw_select_targ_wait(struct stg_softc *, int); 15792739Salfredstatic int stghw_check(struct stg_softc *); 15892739Salfredstatic void stghw_init(struct stg_softc *); 15992739Salfredstatic int stg_negate_signal(struct stg_softc *, u_int8_t, u_char *); 16092739Salfredstatic int stg_expect_signal(struct stg_softc *, u_int8_t, u_int8_t); 16192739Salfredstatic int stg_world_start(struct stg_softc *, int); 16292739Salfredstatic int stghw_start_selection(struct stg_softc *sc, struct slccb *); 16392739Salfredstatic void stghw_bus_reset(struct stg_softc *); 16492739Salfredstatic void stghw_attention(struct stg_softc *); 16592739Salfredstatic int stg_target_nexus_establish(struct stg_softc *); 16692739Salfredstatic int stg_lun_nexus_establish(struct stg_softc *); 16792739Salfredstatic int stg_ccb_nexus_establish(struct stg_softc *); 16892739Salfredstatic int stg_targ_init(struct stg_softc *, struct targ_info *, int); 16992739Salfredstatic __inline void stghw_bcr_write_1(struct stg_softc *, u_int8_t); 17092739Salfredstatic int stg_timeout(struct stg_softc *); 17192739Salfredstatic void stg_selection_done_and_expect_msgout(struct stg_softc *); 17267468Snon 17367468Snonstruct scsi_low_funcs stgfuncs = { 17467468Snon SC_LOW_INIT_T stg_world_start, 17567468Snon SC_LOW_BUSRST_T stghw_bus_reset, 17673025Snon SC_LOW_TARG_INIT_T stg_targ_init, 17779697Snon SC_LOW_LUN_INIT_T NULL, 17867468Snon 17967468Snon SC_LOW_SELECT_T stghw_start_selection, 18079697Snon SC_LOW_NEXUS_T stg_lun_nexus_establish, 18179697Snon SC_LOW_NEXUS_T stg_ccb_nexus_establish, 18267468Snon 18367468Snon SC_LOW_ATTEN_T stghw_attention, 18467468Snon SC_LOW_MSG_T stg_msg, 18567468Snon 18679697Snon SC_LOW_TIMEOUT_T stg_timeout, 18767468Snon SC_LOW_POLL_T stgintr, 18867468Snon 18967468Snon NULL, 19067468Snon}; 19167468Snon 19267468Snon/**************************************************** 19379697Snon * hwfuncs 19467468Snon ****************************************************/ 19567468Snonstatic __inline void 19667468Snonstghw_bcr_write_1(sc, bcv) 19767468Snon struct stg_softc *sc; 19867468Snon u_int8_t bcv; 19967468Snon{ 20067468Snon 20167468Snon bus_space_write_1(sc->sc_iot, sc->sc_ioh, tmc_bctl, bcv); 20267468Snon sc->sc_busimg = bcv; 20367468Snon} 20467468Snon 20579697Snonstatic int 20679697Snonstghw_check(sc) 20779697Snon struct stg_softc *sc; 20879697Snon{ 20979697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 21079697Snon bus_space_tag_t iot = sc->sc_iot; 21179697Snon bus_space_handle_t ioh = sc->sc_ioh; 21279697Snon u_int fcbsize, fcb; 21379697Snon u_int16_t lsb, msb; 21479697Snon 21579697Snon lsb = bus_space_read_1(iot, ioh, tmc_idlsb); 21679697Snon msb = bus_space_read_1(iot, ioh, tmc_idmsb); 21779697Snon switch (msb << 8 | lsb) 21879697Snon { 21979697Snon case 0x6127: 22079697Snon /* TMCCHIP_1800 not supported. (it's my policy) */ 22179697Snon sc->sc_chip = TMCCHIP_1800; 22279697Snon return EINVAL; 22379697Snon 22479697Snon case 0x60e9: 22579697Snon if (bus_space_read_1(iot, ioh, tmc_cfg2) & 0x02) 22679697Snon { 22779697Snon sc->sc_chip = TMCCHIP_18C30; 22879697Snon sc->sc_fsz = TMC18C30_FIFOSZ; 22979697Snon fcbsize = TMC18C30_FCBSZ; 23079697Snon } 23179697Snon else 23279697Snon { 23379697Snon sc->sc_chip = TMCCHIP_18C50; 23479697Snon sc->sc_fsz = TMC18C50_FIFOSZ; 23579697Snon fcbsize = TMC18C50_FCBSZ; 23679697Snon } 23779697Snon break; 23879697Snon 23979697Snon default: 24079697Snon sc->sc_chip = TMCCHIP_UNK; 24179697Snon return ENODEV; 24279697Snon } 24379697Snon 24479697Snon sc->sc_fcRinit = FCTL_INTEN; 24579697Snon sc->sc_fcWinit = FCTL_PARENB | FCTL_INTEN; 24679697Snon 24779697Snon if (slp->sl_cfgflags & CFG_NOATTEN) 24879697Snon sc->sc_imsg = 0; 24979697Snon else 25079697Snon sc->sc_imsg = BCTL_ATN; 25179697Snon sc->sc_busc = BCTL_BUSEN; 25279697Snon 25379697Snon sc->sc_wthold = fcbsize + 256; 25479697Snon sc->sc_rthold = fcbsize - 256; 25579697Snon sc->sc_maxwsize = sc->sc_fsz; 25679697Snon 25779697Snon fcb = fcbsize / (sc->sc_fsz / 16); 25879697Snon sc->sc_icinit = ICTL_CD | ICTL_SEL | ICTL_ARBIT | fcb; 25979697Snon return 0; 26079697Snon} 26179697Snon 26267468Snonstatic void 26379697Snonstghw_init(sc) 26479697Snon struct stg_softc *sc; 26579697Snon{ 26679697Snon bus_space_tag_t iot = sc->sc_iot; 26779697Snon bus_space_handle_t ioh = sc->sc_ioh; 26879697Snon 26979697Snon bus_space_write_1(iot, ioh, tmc_ictl, 0); 27079697Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 27179697Snon bus_space_write_1(iot, ioh, tmc_fctl, 27279697Snon sc->sc_fcRinit | FCTL_CLRFIFO | FCTL_CLRINT); 27379697Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 27479697Snon bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit); 27579697Snon 27679697Snon bus_space_write_1(iot, ioh, tmc_ssctl, 0); 27779697Snon} 27879697Snon 27979697Snonstatic int 28079697Snonstg_targ_init(sc, ti, action) 28179697Snon struct stg_softc *sc; 28279697Snon struct targ_info *ti; 28379697Snon int action; 28479697Snon{ 28579697Snon struct stg_targ_info *sti = (void *) ti; 28679697Snon 28779697Snon if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) 28879697Snon { 28979697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 29079697Snon ti->ti_maxsynch.period = 0; 29179697Snon ti->ti_maxsynch.offset = 0; 29279697Snon sti->sti_reg_synch = 0; 29379697Snon } 29479697Snon return 0; 29579697Snon} 29679697Snon 29779697Snon/**************************************************** 29879697Snon * scsi low interface 29979697Snon ****************************************************/ 30079697Snonstatic void 30167468Snonstghw_attention(sc) 30267468Snon struct stg_softc *sc; 30367468Snon{ 30467468Snon 30567468Snon sc->sc_busc |= BCTL_ATN; 30667468Snon sc->sc_busimg |= BCTL_ATN; 30767468Snon bus_space_write_1(sc->sc_iot, sc->sc_ioh, tmc_bctl, sc->sc_busimg); 30879697Snon SCSI_LOW_DELAY(10); 30967468Snon} 31067468Snon 31167468Snonstatic void 31267468Snonstghw_bus_reset(sc) 31367468Snon struct stg_softc *sc; 31467468Snon{ 31567468Snon bus_space_tag_t iot = sc->sc_iot; 31667468Snon bus_space_handle_t ioh = sc->sc_ioh; 31767468Snon 31867468Snon bus_space_write_1(iot, ioh, tmc_ictl, 0); 31967468Snon bus_space_write_1(iot, ioh, tmc_fctl, 0); 32067468Snon stghw_bcr_write_1(sc, BCTL_RST); 32179697Snon SCSI_LOW_DELAY(100000); 32267468Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 32367468Snon} 32467468Snon 32567468Snonstatic int 32667468Snonstghw_start_selection(sc, cb) 32767468Snon struct stg_softc *sc; 32867468Snon struct slccb *cb; 32967468Snon{ 33067468Snon bus_space_tag_t iot = sc->sc_iot; 33167468Snon bus_space_handle_t ioh = sc->sc_ioh; 33267468Snon struct targ_info *ti = cb->ti; 33367468Snon register u_int8_t stat; 33467468Snon int s; 33567468Snon 33679697Snon sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 33779697Snon sc->sc_dataout_timeout = 0; 33879697Snon sc->sc_ubf_timeout = 0; 33967468Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 34079697Snon bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit); 34167468Snon 34267468Snon s = splhigh(); 34379697Snon stat = bus_space_read_1(iot, ioh, tmc_astat); 34479697Snon if ((stat & ASTAT_INT) != 0) 34567468Snon { 34679697Snon splx(s); 34779697Snon return SCSI_LOW_START_FAIL; 34867468Snon } 34967468Snon 35067468Snon bus_space_write_1(iot, ioh, tmc_scsiid, sc->sc_idbit); 35167468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit | FCTL_ARBIT); 35267468Snon splx(s); 35367468Snon 35467468Snon SCSI_LOW_SETUP_PHASE(ti, PH_ARBSTART); 35567468Snon return SCSI_LOW_START_OK; 35667468Snon} 35767468Snon 35867468Snonstatic int 35967468Snonstg_world_start(sc, fdone) 36067468Snon struct stg_softc *sc; 36167468Snon int fdone; 36267468Snon{ 36367468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 36467468Snon int error; 36567468Snon 36679697Snon if ((slp->sl_cfgflags & CFG_NOPARITY) == 0) 36779697Snon sc->sc_fcRinit |= FCTL_PARENB; 36879697Snon else 36979697Snon sc->sc_fcRinit &= ~FCTL_PARENB; 37079697Snon 37167468Snon if ((error = stghw_check(sc)) != 0) 37267468Snon return error; 37367468Snon 37467468Snon stghw_init(sc); 37567468Snon scsi_low_bus_reset(slp); 37667468Snon stghw_init(sc); 37767468Snon 37867468Snon SOFT_INTR_REQUIRED(slp); 37967468Snon return 0; 38067468Snon} 38167468Snon 38267468Snonstatic int 38367468Snonstg_msg(sc, ti, msg) 38467468Snon struct stg_softc *sc; 38567468Snon struct targ_info *ti; 38667468Snon u_int msg; 38767468Snon{ 38879697Snon bus_space_tag_t iot = sc->sc_iot; 38979697Snon bus_space_handle_t ioh = sc->sc_ioh; 39073025Snon struct stg_targ_info *sti = (void *) ti; 39167468Snon u_int period, offset; 39267468Snon 39379697Snon if ((msg & SCSI_LOW_MSG_WIDE) != 0) 39479697Snon { 39579697Snon if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) 39679697Snon { 39779697Snon ti->ti_width = SCSI_LOW_BUS_WIDTH_8; 39879697Snon return EINVAL; 39979697Snon } 40079697Snon return 0; 40179697Snon } 40267468Snon 40379697Snon if ((msg & SCSI_LOW_MSG_SYNCH) == 0) 40479697Snon return 0; 40579697Snon 40673025Snon period = ti->ti_maxsynch.period; 40773025Snon offset = ti->ti_maxsynch.offset; 40867468Snon period = period << 2; 40967468Snon if (period >= 200) 41067468Snon { 41173025Snon sti->sti_reg_synch = (period - 200) / 50; 41267468Snon if (period % 50) 41373025Snon sti->sti_reg_synch ++; 41473025Snon sti->sti_reg_synch |= SSCTL_SYNCHEN; 41567468Snon } 41667468Snon else if (period >= 100) 41767468Snon { 41873025Snon sti->sti_reg_synch = (period - 100) / 50; 41967468Snon if (period % 50) 42073025Snon sti->sti_reg_synch ++; 42173025Snon sti->sti_reg_synch |= SSCTL_SYNCHEN | SSCTL_FSYNCHEN; 42267468Snon } 42379697Snon bus_space_write_1(iot, ioh, tmc_ssctl, sti->sti_reg_synch); 42467468Snon return 0; 42567468Snon} 42667468Snon 42767468Snon/************************************************************** 42867468Snon * General probe attach 42967468Snon **************************************************************/ 43067468Snonint 43167468Snonstgprobesubr(iot, ioh, dvcfg) 43267468Snon bus_space_tag_t iot; 43367468Snon bus_space_handle_t ioh; 43467468Snon u_int dvcfg; 43567468Snon{ 43667468Snon u_int16_t lsb, msb; 43767468Snon 43867468Snon lsb = bus_space_read_1(iot, ioh, tmc_idlsb); 43967468Snon msb = bus_space_read_1(iot, ioh, tmc_idmsb); 44067468Snon switch (msb << 8 | lsb) 44167468Snon { 44267468Snon default: 44367468Snon return 0; 44467468Snon case 0x6127: 44567468Snon /* not support! */ 44667468Snon return 0; 44767468Snon case 0x60e9: 44867468Snon return 1; 44967468Snon } 45067468Snon return 0; 45167468Snon} 45267468Snon 45367468Snonint 45467468Snonstgprint(aux, name) 45567468Snon void *aux; 45667468Snon const char *name; 45767468Snon{ 45867468Snon 45967468Snon if (name != NULL) 46067468Snon printf("%s: scsibus ", name); 46167468Snon return UNCONF; 46267468Snon} 46367468Snon 46467468Snonvoid 46567468Snonstgattachsubr(sc) 46667468Snon struct stg_softc *sc; 46767468Snon{ 46867468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 46967468Snon 47067468Snon printf("\n"); 47167468Snon 47267468Snon sc->sc_idbit = (1 << slp->sl_hostid); 47367468Snon slp->sl_funcs = &stgfuncs; 47479697Snon sc->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ 47567468Snon 47679697Snon slp->sl_flags |= HW_READ_PADDING; 47767468Snon slp->sl_cfgflags |= CFG_ASYNC; /* XXX */ 47867468Snon 47979697Snon (void) scsi_low_attach(slp, 0, STG_NTARGETS, STG_NLUNS, 48079697Snon sizeof(struct stg_targ_info), 0); 48167468Snon} 48267468Snon 48367468Snon/************************************************************** 48467468Snon * PDMA functions 48567468Snon **************************************************************/ 48667468Snonstatic __inline void 48767468Snonstg_pdma_end(sc, ti) 48867468Snon struct stg_softc *sc; 48967468Snon struct targ_info *ti; 49067468Snon{ 49167468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 49267468Snon bus_space_tag_t iot = sc->sc_iot; 49367468Snon bus_space_handle_t ioh = sc->sc_ioh; 49479697Snon struct slccb *cb = slp->sl_Qnexus; 49567468Snon u_int len, tres; 49667468Snon 49767468Snon slp->sl_flags &= ~HW_PDMASTART; 49879697Snon sc->sc_icinit &= ~ICTL_FIFO; 49979697Snon sc->sc_dataout_timeout = 0; 50067468Snon 50179697Snon if (cb == NULL) 50279697Snon { 50379697Snon slp->sl_error |= PDMAERR; 50479697Snon goto out; 50579697Snon } 50679697Snon 50767468Snon if (ti->ti_phase == PH_DATA) 50867468Snon { 50967468Snon len = bus_space_read_2(iot, ioh, tmc_fdcnt); 51067468Snon if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) 51167468Snon { 51267468Snon if (len != 0) 51367468Snon { 51467468Snon tres = len + slp->sl_scp.scp_datalen; 51567468Snon if (tres <= (u_int) cb->ccb_scp.scp_datalen) 51667468Snon { 51767468Snon slp->sl_scp.scp_data -= len; 51867468Snon slp->sl_scp.scp_datalen = tres; 51967468Snon } 52067468Snon else 52167468Snon { 52267468Snon slp->sl_error |= PDMAERR; 52367468Snon printf("%s len %x >= datalen %x\n", 52467468Snon slp->sl_xname, 52567468Snon len, slp->sl_scp.scp_datalen); 52667468Snon } 52767468Snon } 52867468Snon } 52967468Snon else if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 53067468Snon { 53167468Snon if (len != 0) 53267468Snon { 53367468Snon slp->sl_error |= PDMAERR; 53467468Snon printf("%s: len %x left in fifo\n", 53567468Snon slp->sl_xname, len); 53667468Snon } 53767468Snon } 53879697Snon scsi_low_data_finish(slp); 53967468Snon } 54067468Snon else 54167468Snon { 54267468Snon 54367468Snon printf("%s data phase miss\n", slp->sl_xname); 54467468Snon slp->sl_error |= PDMAERR; 54567468Snon } 54667468Snon 54779697Snonout: 54867468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 54967468Snon} 55067468Snon 55167468Snonstatic void 55279697Snonstg_pio_read(sc, ti, thold) 55367468Snon struct stg_softc *sc; 55467468Snon struct targ_info *ti; 55579697Snon u_int thold; 55667468Snon{ 55767468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 55867468Snon bus_space_tag_t iot = sc->sc_iot; 55967468Snon bus_space_handle_t ioh = sc->sc_ioh; 56067468Snon struct sc_p *sp = &slp->sl_scp; 56179697Snon int s, tout; 56267468Snon u_int res; 56367468Snon u_int8_t stat; 56467468Snon 56579697Snon if ((slp->sl_flags & HW_PDMASTART) == 0) 56679697Snon { 56779697Snon bus_space_write_1(iot, ioh, tmc_fctl, 56879697Snon sc->sc_fcRinit | FCTL_FIFOEN); 56979697Snon slp->sl_flags |= HW_PDMASTART; 57079697Snon } 57167468Snon 57279697Snon tout = sc->sc_tmaxcnt; 57379697Snon while (tout -- > 0) 57467468Snon { 57579697Snon if (thold > 0) 57667468Snon { 57779697Snon s = splhigh(); 57879697Snon res = bus_space_read_2(iot, ioh, tmc_fdcnt); 57979697Snon if (res < thold) 58079697Snon { 58179697Snon bus_space_write_1(iot, ioh, tmc_ictl, 58279697Snon sc->sc_icinit); 58379697Snon splx(s); 58479697Snon break; 58579697Snon } 58679697Snon splx(s); 58779697Snon } 58879697Snon else 58979697Snon { 59067468Snon stat = bus_space_read_1(iot, ioh, tmc_bstat); 59179697Snon res = bus_space_read_2(iot, ioh, tmc_fdcnt); 59279697Snon if (res == 0) 59379697Snon { 59479697Snon if ((stat & PHASE_MASK) != DATA_IN_PHASE) 59579697Snon break; 59679697Snon if (sp->scp_datalen <= 0) 59779697Snon break; 59879697Snon SCSI_LOW_DELAY(1); 59967468Snon continue; 60079697Snon } 60167468Snon } 60267468Snon 60379697Snon /* The assumtion res != 0 is valid here */ 60467468Snon if (res > sp->scp_datalen) 60567468Snon { 60679697Snon if (res == (u_int) -1) 60779697Snon break; 60879697Snon 60967468Snon slp->sl_error |= PDMAERR; 61079697Snon if ((slp->sl_flags & HW_READ_PADDING) == 0) 61179697Snon { 61279697Snon printf("%s: read padding required\n", 61379697Snon slp->sl_xname); 61479697Snon break; 61579697Snon } 61679697Snon 61779697Snon sp->scp_datalen = 0; 61879697Snon if (res > STG_MAX_DATA_SIZE) 61979697Snon res = STG_MAX_DATA_SIZE; 62079697Snon while (res -- > 0) 62179697Snon { 62279697Snon (void) bus_space_read_1(iot, ioh, tmc_rfifo); 62379697Snon } 62479697Snon continue; 62567468Snon } 62667468Snon 62767468Snon sp->scp_datalen -= res; 62867468Snon if (res & 1) 62967468Snon { 63067468Snon *sp->scp_data = bus_space_read_1(iot, ioh, tmc_rfifo); 63167468Snon sp->scp_data ++; 63267468Snon res --; 63367468Snon } 63467468Snon 63567468Snon bus_space_read_multi_2(iot, ioh, tmc_rfifo, 63667468Snon (u_int16_t *) sp->scp_data, res >> 1); 63767468Snon sp->scp_data += res; 63867468Snon } 63967468Snon 64073025Snon if (tout <= 0) 64179697Snon printf("%s: pio read timeout\n", slp->sl_xname); 64267468Snon} 64367468Snon 64467468Snonstatic void 64579697Snonstg_pio_write(sc, ti, thold) 64667468Snon struct stg_softc *sc; 64767468Snon struct targ_info *ti; 64879697Snon u_int thold; 64967468Snon{ 65067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 65167468Snon bus_space_tag_t iot = sc->sc_iot; 65267468Snon bus_space_handle_t ioh = sc->sc_ioh; 65367468Snon struct sc_p *sp = &slp->sl_scp; 65467468Snon u_int res; 65579697Snon int s, tout; 65667468Snon register u_int8_t stat; 65767468Snon 65879697Snon if ((slp->sl_flags & HW_PDMASTART) == 0) 65979697Snon { 66079697Snon stat = sc->sc_fcWinit | FCTL_FIFOEN | FCTL_FIFOW; 66179697Snon bus_space_write_1(iot, ioh, tmc_fctl, stat | FCTL_CLRFIFO); 66279697Snon bus_space_write_1(iot, ioh, tmc_fctl, stat); 66379697Snon slp->sl_flags |= HW_PDMASTART; 66479697Snon } 66567468Snon 66679697Snon tout = sc->sc_tmaxcnt; 66779697Snon while (tout -- > 0) 66867468Snon { 66967468Snon stat = bus_space_read_1(iot, ioh, tmc_bstat); 67079697Snon if ((stat & PHASE_MASK) != DATA_OUT_PHASE) 67167468Snon break; 67267468Snon 67379697Snon if (sp->scp_datalen <= 0) 67479697Snon { 67579697Snon if (sc->sc_dataout_timeout == 0) 67679697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 67779697Snon break; 67879697Snon } 67967468Snon 68079697Snon if (thold > 0) 68179697Snon { 68279697Snon s = splhigh(); 68379697Snon res = bus_space_read_2(iot, ioh, tmc_fdcnt); 68479697Snon if (res > thold) 68579697Snon { 68679697Snon bus_space_write_1(iot, ioh, tmc_ictl, 68779697Snon sc->sc_icinit); 68879697Snon splx(s); 68979697Snon break; 69079697Snon } 69179697Snon splx(s); 69279697Snon } 69379697Snon else 69479697Snon { 69579697Snon res = bus_space_read_2(iot, ioh, tmc_fdcnt); 69679697Snon if (res > sc->sc_maxwsize / 2) 69779697Snon { 69879697Snon SCSI_LOW_DELAY(1); 69979697Snon continue; 70079697Snon } 70179697Snon } 70279697Snon 70379697Snon if (res == (u_int) -1) 70479697Snon break; 70579697Snon res = sc->sc_maxwsize - res; 70679697Snon if (res > sp->scp_datalen) 70779697Snon res = sp->scp_datalen; 70879697Snon 70967468Snon sp->scp_datalen -= res; 71067468Snon if ((res & 0x1) != 0) 71167468Snon { 71267468Snon bus_space_write_1(iot, ioh, tmc_wfifo, *sp->scp_data); 71367468Snon sp->scp_data ++; 71467468Snon res --; 71567468Snon } 71667468Snon 71767468Snon bus_space_write_multi_2(iot, ioh, tmc_wfifo, 71867468Snon (u_int16_t *) sp->scp_data, res >> 1); 71967468Snon sp->scp_data += res; 72067468Snon } 72167468Snon 72273025Snon if (tout <= 0) 72379697Snon printf("%s: pio write timeout\n", slp->sl_xname); 72467468Snon} 72567468Snon 72667468Snonstatic int 72767468Snonstg_negate_signal(sc, mask, s) 72867468Snon struct stg_softc *sc; 72967468Snon u_int8_t mask; 73067468Snon u_char *s; 73167468Snon{ 73267468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 73367468Snon bus_space_tag_t bst = sc->sc_iot; 73467468Snon bus_space_handle_t bsh = sc->sc_ioh; 73579697Snon int wc; 73667468Snon u_int8_t regv; 73767468Snon 73879697Snon for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++) 73967468Snon { 74067468Snon regv = bus_space_read_1(bst, bsh, tmc_bstat); 74179697Snon if (regv == (u_int8_t) -1) 74279697Snon return -1; 74379697Snon if ((regv & mask) == 0) 74479697Snon return 1; 74579697Snon 74679697Snon SCSI_LOW_DELAY(STG_DELAY_INTERVAL); 74767468Snon } 74867468Snon 74979697Snon printf("%s: %s stg_negate_signal timeout\n", slp->sl_xname, s); 75079697Snon return -1; 75167468Snon} 75267468Snon 75367468Snonstatic int 75467468Snonstg_expect_signal(sc, phase, mask) 75567468Snon struct stg_softc *sc; 75667468Snon u_int8_t phase, mask; 75767468Snon{ 75867468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 75967468Snon bus_space_tag_t bst = sc->sc_iot; 76067468Snon bus_space_handle_t bsh = sc->sc_ioh; 76179697Snon int wc; 76267468Snon u_int8_t ph; 76367468Snon 76479697Snon phase &= PHASE_MASK; 76579697Snon for (wc = 0; wc < STG_DELAY_MAX / STG_DELAY_INTERVAL; wc ++) 76667468Snon { 76767468Snon ph = bus_space_read_1(bst, bsh, tmc_bstat); 76879697Snon if (ph == (u_int8_t) -1) 76979697Snon return -1; 77079697Snon if ((ph & PHASE_MASK) != phase) 77179697Snon return 0; 77279697Snon if ((ph & mask) != 0) 77379697Snon return 1; 77479697Snon 77579697Snon SCSI_LOW_DELAY(STG_DELAY_INTERVAL); 77667468Snon } 77767468Snon 77879697Snon printf("%s: stg_expect_signal timeout\n", slp->sl_xname); 77979697Snon return -1; 78067468Snon} 78167468Snon 78267468Snonstatic int 78379697Snonstg_xfer(sc, buf, len, phase, clear_atn) 78467468Snon struct stg_softc *sc; 78567468Snon u_int8_t *buf; 78667468Snon int len; 78767468Snon int phase; 78879697Snon int clear_atn; 78967468Snon{ 79067468Snon bus_space_tag_t iot = sc->sc_iot; 79167468Snon bus_space_handle_t ioh = sc->sc_ioh; 79279697Snon int rv, ptr; 79367468Snon 79467468Snon if (phase & BSTAT_IO) 79567468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 79667468Snon else 79767468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcWinit); 79867468Snon 79967468Snon for (ptr = 0; len > 0; len --) 80067468Snon { 80167468Snon rv = stg_expect_signal(sc, phase, BSTAT_REQ); 80267468Snon if (rv <= 0) 80367468Snon goto bad; 80467468Snon 80579697Snon if (len == 1 && clear_atn != 0) 80667468Snon { 80767468Snon sc->sc_busc &= ~BCTL_ATN; 80867468Snon stghw_bcr_write_1(sc, sc->sc_busc); 80979697Snon SCSI_LOW_DEASSERT_ATN(&sc->sc_sclow); 81067468Snon } 81167468Snon 81267468Snon if (phase & BSTAT_IO) 81367468Snon { 81467468Snon buf[ptr ++] = bus_space_read_1(iot, ioh, tmc_rdata); 81567468Snon } 81667468Snon else 81767468Snon { 81867468Snon bus_space_write_1(iot, ioh, tmc_wdata, buf[ptr ++]); 81967468Snon } 82079697Snon 82167468Snon stg_negate_signal(sc, BSTAT_ACK, "xfer<ACK>"); 82267468Snon } 82367468Snon 82467468Snonbad: 82567468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 82667468Snon return len; 82767468Snon} 82867468Snon 82967468Snon/************************************************************** 83067468Snon * disconnect & reselect (HW low) 83167468Snon **************************************************************/ 83267468Snonstatic int 83367468Snonstg_reselected(sc) 83467468Snon struct stg_softc *sc; 83567468Snon{ 83667468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 83767468Snon bus_space_tag_t iot = sc->sc_iot; 83867468Snon bus_space_handle_t ioh = sc->sc_ioh; 83979697Snon int tout; 84067468Snon u_int sid; 84179697Snon u_int8_t regv; 84267468Snon 84367468Snon if (slp->sl_selid != NULL) 84467468Snon { 84567468Snon /* XXX: 84667468Snon * Selection vs Reselection conflicts. 84767468Snon */ 84867468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 84967468Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 85067468Snon } 85179697Snon else if (slp->sl_Tnexus != NULL) 85279697Snon { 85379697Snon printf("%s: unexpected termination\n", slp->sl_xname); 85479697Snon stg_disconnected(sc, slp->sl_Tnexus); 85579697Snon } 85667468Snon 85767468Snon /* XXX: 85867468Snon * We should ack the reselection as soon as possible, 859123608Sjhb * because the target would abort the current reselection seq 86067468Snon * due to reselection timeout. 86167468Snon */ 86279697Snon tout = STG_DELAY_SELECT_POLLING_MAX; 86379697Snon while (tout -- > 0) 86479697Snon { 86579697Snon regv = bus_space_read_1(iot, ioh, tmc_bstat); 86679697Snon if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) == 86779697Snon (BSTAT_IO | BSTAT_SEL)) 86879697Snon { 86979697Snon SCSI_LOW_DELAY(1); 87079697Snon regv = bus_space_read_1(iot, ioh, tmc_bstat); 87179697Snon if ((regv & (BSTAT_IO | BSTAT_SEL | BSTAT_BSY)) == 87279697Snon (BSTAT_IO | BSTAT_SEL)) 87379697Snon goto reselect_start; 87479697Snon } 87579697Snon SCSI_LOW_DELAY(1); 87679697Snon } 87779697Snon printf("%s: reselction timeout I\n", slp->sl_xname); 87879697Snon return EJUSTRETURN; 87979697Snon 88079697Snonreselect_start: 88167468Snon sid = (u_int) bus_space_read_1(iot, ioh, tmc_scsiid); 88279697Snon if ((sid & sc->sc_idbit) == 0) 88379697Snon { 88479697Snon /* not us */ 88579697Snon return EJUSTRETURN; 88679697Snon } 88779697Snon 88879697Snon bus_space_write_1(iot, ioh, tmc_fctl, 88979697Snon sc->sc_fcRinit | FCTL_CLRFIFO | FCTL_CLRINT); 89067468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 89167468Snon stghw_bcr_write_1(sc, sc->sc_busc | BCTL_BSY); 89267468Snon 89379697Snon while (tout -- > 0) 89479697Snon { 89579697Snon regv = bus_space_read_1(iot, ioh, tmc_bstat); 89679697Snon if ((regv & (BSTAT_SEL | BSTAT_BSY)) == BSTAT_BSY) 89779697Snon goto reselected; 89879697Snon SCSI_LOW_DELAY(1); 89979697Snon } 90079697Snon printf("%s: reselction timeout II\n", slp->sl_xname); 90179697Snon return EJUSTRETURN; 90279697Snon 90379697Snonreselected: 90467468Snon sid &= ~sc->sc_idbit; 90567468Snon sid = ffs(sid) - 1; 90679697Snon if (scsi_low_reselected(slp, sid) == NULL) 90767468Snon return EJUSTRETURN; 90867468Snon 90967468Snon#ifdef STG_STATICS 91079697Snon stg_statics.reselect ++; 91167468Snon#endif /* STG_STATICS */ 91267468Snon return EJUSTRETURN; 91367468Snon} 91467468Snon 91579697Snonstatic int 91667468Snonstg_disconnected(sc, ti) 91767468Snon struct stg_softc *sc; 91867468Snon struct targ_info *ti; 91967468Snon{ 92067468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 92167468Snon bus_space_tag_t iot = sc->sc_iot; 92267468Snon bus_space_handle_t ioh = sc->sc_ioh; 92367468Snon 92467468Snon /* clear bus status & fifo */ 92567468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO); 92667468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 92767468Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 92879697Snon sc->sc_icinit &= ~ICTL_FIFO; 92967468Snon sc->sc_busc &= ~BCTL_ATN; 93079697Snon sc->sc_dataout_timeout = 0; 93179697Snon sc->sc_ubf_timeout = 0; 93267468Snon 93367468Snon#ifdef STG_STATICS 93479697Snon stg_statics.disconnect ++; 93567468Snon#endif /* STG_STATICS */ 93667468Snon scsi_low_disconnected(slp, ti); 93767468Snon return 1; 93867468Snon} 93967468Snon 94067468Snon/************************************************************** 94167468Snon * SEQUENCER 94267468Snon **************************************************************/ 94367468Snonstatic int 94479697Snonstg_target_nexus_establish(sc) 94567468Snon struct stg_softc *sc; 94667468Snon{ 94779697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 94867468Snon bus_space_tag_t iot = sc->sc_iot; 94967468Snon bus_space_handle_t ioh = sc->sc_ioh; 95079697Snon struct targ_info *ti = slp->sl_Tnexus; 95173025Snon struct stg_targ_info *sti = (void *) ti; 95267468Snon 95373025Snon bus_space_write_1(iot, ioh, tmc_ssctl, sti->sti_reg_synch); 95479697Snon if ((stg_io_control & STG_FIFO_INTERRUPTS) != 0) 95579697Snon { 95679697Snon sc->sc_icinit |= ICTL_FIFO; 95779697Snon } 95867468Snon return 0; 95967468Snon} 96067468Snon 96167468Snonstatic int 96279697Snonstg_lun_nexus_establish(sc) 96367468Snon struct stg_softc *sc; 96467468Snon{ 96579697Snon 96679697Snon return 0; 96779697Snon} 96879697Snon 96979697Snonstatic int 97079697Snonstg_ccb_nexus_establish(sc) 97179697Snon struct stg_softc *sc; 97279697Snon{ 97379697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 97479697Snon struct slccb *cb = slp->sl_Qnexus; 97579697Snon 97679697Snon sc->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; 97779697Snon return 0; 97879697Snon} 97979697Snon 98079697Snon#define STGHW_SELECT_INTERVAL 10 98179697Snon 98279697Snonstatic int 98379697Snonstghw_select_targ_wait(sc, mu) 98479697Snon struct stg_softc *sc; 98579697Snon int mu; 98679697Snon{ 98767468Snon bus_space_tag_t iot = sc->sc_iot; 98867468Snon bus_space_handle_t ioh = sc->sc_ioh; 98967468Snon 99079697Snon mu = mu / STGHW_SELECT_INTERVAL; 99179697Snon while (mu -- > 0) 99267468Snon { 99379697Snon if ((bus_space_read_1(iot, ioh, tmc_bstat) & BSTAT_BSY) == 0) 99467468Snon { 99579697Snon SCSI_LOW_DELAY(STGHW_SELECT_INTERVAL); 99679697Snon continue; 99767468Snon } 99879697Snon SCSI_LOW_DELAY(1); 99979697Snon if ((bus_space_read_1(iot, ioh, tmc_bstat) & BSTAT_BSY) != 0) 100079697Snon { 100179697Snon return 0; 100279697Snon } 100367468Snon } 100479697Snon return ENXIO; 100579697Snon} 100667468Snon 100779697Snonstatic void 100879697Snonstg_selection_done_and_expect_msgout(sc) 100979697Snon struct stg_softc *sc; 101079697Snon{ 101179697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 101279697Snon bus_space_tag_t iot = sc->sc_iot; 101379697Snon bus_space_handle_t ioh = sc->sc_ioh; 101479697Snon 101567468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit | FCTL_CLRFIFO); 101667468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 101779697Snon stghw_bcr_write_1(sc, sc->sc_imsg | sc->sc_busc); 101879697Snon SCSI_LOW_ASSERT_ATN(slp); 101967468Snon} 102067468Snon 102167468Snonint 102267468Snonstgintr(arg) 102367468Snon void *arg; 102467468Snon{ 102567468Snon struct stg_softc *sc = arg; 102667468Snon struct scsi_low_softc *slp = &sc->sc_sclow; 102767468Snon bus_space_tag_t iot = sc->sc_iot; 102867468Snon bus_space_handle_t ioh = sc->sc_ioh; 102967468Snon struct targ_info *ti; 103067468Snon struct physio_proc *pp; 103167468Snon struct buf *bp; 103279697Snon u_int derror, flags; 103379697Snon int len, s; 103467468Snon u_int8_t status, astatus, regv; 103567468Snon 103667468Snon /******************************************* 103767468Snon * interrupt check 103867468Snon *******************************************/ 103967468Snon if (slp->sl_flags & HW_INACTIVE) 104067468Snon return 0; 104167468Snon 104267468Snon astatus = bus_space_read_1(iot, ioh, tmc_astat); 104367468Snon status = bus_space_read_1(iot, ioh, tmc_bstat); 104467468Snon 104579697Snon if ((astatus & ASTAT_STATMASK) == 0 || astatus == (u_int8_t) -1) 104667468Snon return 0; 104767468Snon 104879697Snon bus_space_write_1(iot, ioh, tmc_ictl, 0); 104967468Snon if (astatus & ASTAT_SCSIRST) 105067468Snon { 105167468Snon bus_space_write_1(iot, ioh, tmc_fctl, 105267468Snon sc->sc_fcRinit | FCTL_CLRFIFO); 105367468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 105479697Snon bus_space_write_1(iot, ioh, tmc_ictl, 0); 105567468Snon 105667468Snon scsi_low_restart(slp, SCSI_LOW_RESTART_SOFT, 105767468Snon "bus reset (power off?)"); 105867468Snon return 1; 105967468Snon } 106067468Snon 106167468Snon /******************************************* 106267468Snon * debug section 106367468Snon *******************************************/ 106467468Snon#ifdef STG_DEBUG 106567468Snon if (stg_debug) 106667468Snon { 106767468Snon scsi_low_print(slp, NULL); 106879697Snon printf("%s: st %x ist %x\n\n", slp->sl_xname, 106967468Snon status, astatus); 1070131920Smarcel#ifdef KDB 107167468Snon if (stg_debug > 1) 107279697Snon SCSI_LOW_DEBUGGER("stg"); 1073131920Smarcel#endif /* KDB */ 107467468Snon } 107567468Snon#endif /* STG_DEBUG */ 107667468Snon 107767468Snon /******************************************* 107867468Snon * reselection & nexus 107967468Snon *******************************************/ 108067468Snon if ((status & RESEL_PHASE_MASK)== PHASE_RESELECTED) 108167468Snon { 108267468Snon if (stg_reselected(sc) == EJUSTRETURN) 108379697Snon goto out; 108467468Snon } 108567468Snon 108679697Snon if ((ti = slp->sl_Tnexus) == NULL) 108779697Snon return 0; 108867468Snon 108979697Snon derror = 0; 109067468Snon if ((astatus & ASTAT_PARERR) != 0 && ti->ti_phase != PH_ARBSTART && 109167468Snon (sc->sc_fcRinit & FCTL_PARENB) != 0) 109267468Snon { 109367468Snon slp->sl_error |= PARITYERR; 109479697Snon derror = SCSI_LOW_DATA_PE; 109579697Snon if ((status & PHASE_MASK) == MESSAGE_IN_PHASE) 109679697Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_PARITY, 0); 109767468Snon else 109867468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ERROR, 1); 109967468Snon } 110067468Snon 110167468Snon /******************************************* 110267468Snon * aribitration & selection 110367468Snon *******************************************/ 110467468Snon switch (ti->ti_phase) 110567468Snon { 110667468Snon case PH_ARBSTART: 110767468Snon if ((astatus & ASTAT_ARBIT) == 0) 110879697Snon { 110979697Snon#ifdef STG_STATICS 111079697Snon stg_statics.arbit_fail_0 ++; 111179697Snon#endif /* STG_STATICS */ 111267468Snon goto arb_fail; 111379697Snon } 111467468Snon 111567468Snon status = bus_space_read_1(iot, ioh, tmc_bstat); 111667468Snon if ((status & BSTAT_IO) != 0) 111767468Snon { 111867468Snon /* XXX: 111967468Snon * Selection vs Reselection conflicts. 112067468Snon */ 112167468Snon#ifdef STG_STATICS 112279697Snon stg_statics.arbit_fail_1 ++; 112367468Snon#endif /* STG_STATICS */ 112467468Snonarb_fail: 112567468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 112667468Snon stghw_bcr_write_1(sc, BCTL_BUSFREE); 112779697Snon scsi_low_arbit_fail(slp, slp->sl_Qnexus); 112879697Snon goto out; 112967468Snon } 113067468Snon 113167468Snon /* 113267468Snon * selection assert start. 113367468Snon */ 113467468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); 113579697Snon scsi_low_arbit_win(slp); 113679697Snon 113779697Snon s = splhigh(); 113867468Snon bus_space_write_1(iot, ioh, tmc_scsiid, 113967468Snon sc->sc_idbit | (1 << ti->ti_id)); 114067468Snon stghw_bcr_write_1(sc, sc->sc_imsg | sc->sc_busc | BCTL_SEL); 114167468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcWinit); 114279697Snon if ((stg_io_control & STG_WAIT_FOR_SELECT) != 0) 114379697Snon { 114479697Snon /* selection abort delay 200 + 100 micro sec */ 114579697Snon if (stghw_select_targ_wait(sc, 300) == 0) 114679697Snon { 114779697Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 114879697Snon stg_selection_done_and_expect_msgout(sc); 114979697Snon } 115079697Snon } 115179697Snon splx(s); 115279697Snon goto out; 115367468Snon 115467468Snon case PH_SELSTART: 115567468Snon if ((status & BSTAT_BSY) == 0) 115667468Snon { 115779697Snon /* selection timeout delay 250 ms */ 115879697Snon if (stghw_select_targ_wait(sc, 250 * 1000) != 0) 115967468Snon { 116079697Snon stg_disconnected(sc, ti); 116179697Snon goto out; 116267468Snon } 116367468Snon } 116467468Snon 116567468Snon SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); 116679697Snon stg_selection_done_and_expect_msgout(sc); 116779697Snon goto out; 116867468Snon 116979697Snon case PH_SELECTED: 117079697Snon if ((status & BSTAT_REQ) == 0) 117179697Snon goto out; 117279697Snon stg_target_nexus_establish(sc); 117379697Snon break; 117479697Snon 117567468Snon case PH_RESEL: 117679697Snon if ((status & BSTAT_REQ) == 0) 117779697Snon goto out; 117879697Snon 117967468Snon /* clear a busy line */ 118067468Snon bus_space_write_1(iot, ioh, tmc_fctl, sc->sc_fcRinit); 118167468Snon stghw_bcr_write_1(sc, sc->sc_busc); 118279697Snon stg_target_nexus_establish(sc); 118367468Snon if ((status & PHASE_MASK) != MESSAGE_IN_PHASE) 118467468Snon { 118579697Snon printf("%s: unexpected phase after reselect\n", 118679697Snon slp->sl_xname); 118779697Snon slp->sl_error |= FATALIO; 118867468Snon scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_ABORT, 1); 118979697Snon goto out; 119067468Snon } 119167468Snon break; 119267468Snon } 119367468Snon 119467468Snon /******************************************* 119579697Snon * data phase 119667468Snon *******************************************/ 119779697Snon if ((slp->sl_flags & HW_PDMASTART) && STG_IS_PHASE_DATA(status) == 0) 119879697Snon { 119979697Snon if (slp->sl_scp.scp_direction == SCSI_LOW_READ) 120079697Snon stg_pio_read(sc, ti, 0); 120179697Snon 120267468Snon stg_pdma_end(sc, ti); 120379697Snon } 120467468Snon 120579697Snon /******************************************* 120679697Snon * scsi seq 120779697Snon *******************************************/ 120867468Snon switch (status & PHASE_MASK) 120967468Snon { 121067468Snon case COMMAND_PHASE: 121179697Snon if (stg_expect_signal(sc, COMMAND_PHASE, BSTAT_REQ) <= 0) 121279697Snon break; 121379697Snon 121467468Snon SCSI_LOW_SETUP_PHASE(ti, PH_CMD); 121567468Snon if (scsi_low_cmd(slp, ti) != 0) 121679697Snon { 121779697Snon scsi_low_attention(slp); 121879697Snon } 121967468Snon 122079697Snon if (stg_xfer(sc, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen, 122179697Snon COMMAND_PHASE, 0) != 0) 122267468Snon { 122379697Snon printf("%s: CMDOUT short\n", slp->sl_xname); 122467468Snon } 122567468Snon break; 122667468Snon 122767468Snon case DATA_OUT_PHASE: 122867468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 122967468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) 123079697Snon { 123179697Snon scsi_low_attention(slp); 123279697Snon } 123367468Snon 123467468Snon pp = physio_proc_enter(bp); 123579697Snon if ((sc->sc_icinit & ICTL_FIFO) != 0) 123679697Snon stg_pio_write(sc, ti, sc->sc_wthold); 123779697Snon else 123879697Snon stg_pio_write(sc, ti, 0); 123967468Snon physio_proc_leave(pp); 124067468Snon break; 124167468Snon 124267468Snon case DATA_IN_PHASE: 124367468Snon SCSI_LOW_SETUP_PHASE(ti, PH_DATA); 124467468Snon if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) 124579697Snon { 124679697Snon scsi_low_attention(slp); 124779697Snon } 124867468Snon 124967468Snon pp = physio_proc_enter(bp); 125079697Snon if ((sc->sc_icinit & ICTL_FIFO) != 0) 125179697Snon stg_pio_read(sc, ti, sc->sc_rthold); 125279697Snon else 125379697Snon stg_pio_read(sc, ti, 0); 125467468Snon physio_proc_leave(pp); 125567468Snon break; 125667468Snon 125767468Snon case STATUS_PHASE: 125879697Snon regv = stg_expect_signal(sc, STATUS_PHASE, BSTAT_REQ); 125979697Snon if (regv <= 0) 126079697Snon break; 126179697Snon 126267468Snon SCSI_LOW_SETUP_PHASE(ti, PH_STAT); 126379697Snon regv = bus_space_read_1(iot, ioh, tmc_sdna); 126479697Snon if (scsi_low_statusin(slp, ti, regv | derror) != 0) 126579697Snon { 126679697Snon scsi_low_attention(slp); 126779697Snon } 126879697Snon if (regv != bus_space_read_1(iot, ioh, tmc_rdata)) 126979697Snon { 127079697Snon printf("%s: STATIN: data mismatch\n", slp->sl_xname); 127179697Snon } 127279697Snon stg_negate_signal(sc, BSTAT_ACK, "statin<ACK>"); 127367468Snon break; 127467468Snon 127567468Snon case MESSAGE_OUT_PHASE: 127679697Snon if (stg_expect_signal(sc, MESSAGE_OUT_PHASE, BSTAT_REQ) <= 0) 127779697Snon break; 127879697Snon 127967468Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); 128079697Snon flags = (ti->ti_ophase != ti->ti_phase) ? 128179697Snon SCSI_LOW_MSGOUT_INIT : 0; 128279697Snon len = scsi_low_msgout(slp, ti, flags); 128379697Snon 128479697Snon if (len > 1 && slp->sl_atten == 0) 128567468Snon { 128679697Snon scsi_low_attention(slp); 128779697Snon } 128879697Snon 128979697Snon if (stg_xfer(sc, ti->ti_msgoutstr, len, MESSAGE_OUT_PHASE, 129079697Snon slp->sl_clear_atten) != 0) 129179697Snon { 129267468Snon printf("%s: MSGOUT short\n", slp->sl_xname); 129367468Snon } 129479697Snon else 129579697Snon { 129679697Snon if (slp->sl_msgphase >= MSGPH_ABORT) 129779697Snon { 129879697Snon stg_disconnected(sc, ti); 129979697Snon } 130079697Snon } 130167468Snon break; 130267468Snon 130367468Snon case MESSAGE_IN_PHASE: 130479697Snon /* confirm phase and req signal */ 130579697Snon if (stg_expect_signal(sc, MESSAGE_IN_PHASE, BSTAT_REQ) <= 0) 130679697Snon break; 130779697Snon 130867468Snon SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); 130967468Snon 131079697Snon /* read data with NOACK */ 131179697Snon regv = bus_space_read_1(iot, ioh, tmc_sdna); 131279697Snon 131379697Snon if (scsi_low_msgin(slp, ti, derror | regv) == 0) 131467468Snon { 131579697Snon if (scsi_low_is_msgout_continue(ti, 0) != 0) 131679697Snon { 131779697Snon scsi_low_attention(slp); 131879697Snon } 131967468Snon } 132067468Snon 132167468Snon /* read data with ACK */ 132279697Snon if (regv != bus_space_read_1(iot, ioh, tmc_rdata)) 132367468Snon { 132467468Snon printf("%s: MSGIN: data mismatch\n", slp->sl_xname); 132567468Snon } 132667468Snon 132779697Snon /* wait for the ack negated */ 132879697Snon stg_negate_signal(sc, BSTAT_ACK, "msgin<ACK>"); 132979697Snon 133079697Snon if (slp->sl_msgphase != 0 && slp->sl_msgphase < MSGPH_ABORT) 133167468Snon { 133279697Snon stg_disconnected(sc, ti); 133367468Snon } 133467468Snon break; 133567468Snon 133667468Snon case BUSFREE_PHASE: 133779697Snon printf("%s: unexpected disconnect\n", slp->sl_xname); 133879697Snon stg_disconnected(sc, ti); 133979697Snon break; 134067468Snon 134167468Snon default: 134279697Snon slp->sl_error |= FATALIO; 134379697Snon printf("%s: unknown phase bus %x intr %x\n", 134467468Snon slp->sl_xname, status, astatus); 134567468Snon break; 134667468Snon } 134767468Snon 134879697Snonout: 134979697Snon bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit); 135067468Snon return 1; 135167468Snon} 135279697Snon 135379697Snonstatic int 135479697Snonstg_timeout(sc) 135579697Snon struct stg_softc *sc; 135679697Snon{ 135779697Snon struct scsi_low_softc *slp = &sc->sc_sclow; 135879697Snon bus_space_tag_t iot = sc->sc_iot; 135979697Snon bus_space_handle_t ioh = sc->sc_ioh; 136079697Snon int tout, count; 136179697Snon u_int8_t status; 136279697Snon 136379697Snon if (slp->sl_Tnexus == NULL) 136479697Snon return 0; 136579697Snon 136679697Snon status = bus_space_read_1(iot, ioh, tmc_bstat); 136779697Snon if ((status & PHASE_MASK) == 0) 136879697Snon { 136979697Snon if (sc->sc_ubf_timeout ++ == 0) 137079697Snon return 0; 137179697Snon 137279697Snon printf("%s: unexpected bus free detected\n", slp->sl_xname); 137379697Snon slp->sl_error |= FATALIO; 137479697Snon scsi_low_print(slp, slp->sl_Tnexus); 137579697Snon stg_disconnected(sc, slp->sl_Tnexus); 137679697Snon return 0; 137779697Snon } 137879697Snon 137979697Snon switch (status & PHASE_MASK) 138079697Snon { 138179697Snon case DATA_OUT_PHASE: 138279697Snon if (sc->sc_dataout_timeout == 0) 138379697Snon break; 138479697Snon if ((status & BSTAT_REQ) == 0) 138579697Snon break; 138679697Snon if (bus_space_read_2(iot, ioh, tmc_fdcnt) != 0) 138779697Snon break; 138879697Snon if ((-- sc->sc_dataout_timeout) > 0) 138979697Snon break; 139079697Snon 139179697Snon slp->sl_error |= PDMAERR; 139279697Snon if ((slp->sl_flags & HW_WRITE_PADDING) == 0) 139379697Snon { 139479697Snon printf("%s: write padding required\n", 139579697Snon slp->sl_xname); 139679697Snon break; 139779697Snon } 139879697Snon 139979697Snon bus_space_write_1(iot, ioh, tmc_ictl, 0); 140079697Snon 140179697Snon tout = STG_DELAY_MAX; 140279697Snon while (tout --) 140379697Snon { 140479697Snon status = bus_space_read_1(iot, ioh, tmc_bstat); 140579697Snon if ((status & PHASE_MASK) != DATA_OUT_PHASE) 140679697Snon break; 140779697Snon 140879697Snon if (bus_space_read_2(iot, ioh, tmc_fdcnt) != 0) 140979697Snon { 141079697Snon SCSI_LOW_DELAY(1); 141179697Snon continue; 141279697Snon } 141379697Snon 141479697Snon for (count = sc->sc_maxwsize; count > 0; count --) 141579697Snon bus_space_write_1(iot, ioh, tmc_wfifo, 0); 141679697Snon } 141779697Snon 141879697Snon status = bus_space_read_1(iot, ioh, tmc_bstat); 141979697Snon if ((status & PHASE_MASK) == DATA_OUT_PHASE) 142079697Snon sc->sc_dataout_timeout = SCSI_LOW_TIMEOUT_HZ; 142179697Snon 142279697Snon bus_space_write_1(iot, ioh, tmc_ictl, sc->sc_icinit); 142379697Snon break; 142479697Snon 142579697Snon default: 142679697Snon break; 142779697Snon } 142879697Snon return 0; 142979697Snon} 1430