diff options
author | non <non@FreeBSD.org> | 2001-07-14 00:38:51 +0000 |
---|---|---|
committer | non <non@FreeBSD.org> | 2001-07-14 00:38:51 +0000 |
commit | e91272502526170cc4f62c2357a8b7d3ee9b2c27 (patch) | |
tree | 01f4c48045db66f0e363a543a36a88e13470d6c9 /sys/dev/ct | |
parent | a67c5263965b3cce0db11089854bd6f3f56f2f8e (diff) | |
download | FreeBSD-src-e91272502526170cc4f62c2357a8b7d3ee9b2c27.zip FreeBSD-src-e91272502526170cc4f62c2357a8b7d3ee9b2c27.tar.gz |
Catch up with NetBSD/pc98.
o Much cleanly separate NetBSD(XS) / FreeBSD(CAM) codes.
o Improve tagged queing support (full QTAG).
o Improve quirk support.
o Improve parity error retry.
o Impliment wide negotheation.
o Cmd link support.
o Add copyright of CAM part.
o Change for CAM_NEW_TRAN_CODE.
o Work around for buggy KME UJDCD450.
o stg: add disconnet condition.
o nsp: use suspend I/O.
and more. I thank Honda-san.
conf/options.pc98: add CT_USE_RELOCATE_OFFSET and CT_BUS_WEIGHT
dev/{ct,ncv,nsp,stg}/*_{pccard,isa}.c: add splcam() before calling
attach/detach functions.
Tested by: bsd-nomads
Obtained from: NetBSD/pc98
Diffstat (limited to 'sys/dev/ct')
-rw-r--r-- | sys/dev/ct/bshw_machdep.c | 396 | ||||
-rw-r--r-- | sys/dev/ct/bshwvar.h | 32 | ||||
-rw-r--r-- | sys/dev/ct/ct.c | 809 | ||||
-rw-r--r-- | sys/dev/ct/ct_isa.c | 114 | ||||
-rw-r--r-- | sys/dev/ct/ct_machdep.h | 149 | ||||
-rw-r--r-- | sys/dev/ct/ctvar.h | 70 |
6 files changed, 1061 insertions, 509 deletions
diff --git a/sys/dev/ct/bshw_machdep.c b/sys/dev/ct/bshw_machdep.c index 6b375ab..c7995ce 100644 --- a/sys/dev/ct/bshw_machdep.c +++ b/sys/dev/ct/bshw_machdep.c @@ -1,13 +1,13 @@ /* $FreeBSD$ */ -/* $NecBSD: bshw_machdep.c,v 1.8 1999/07/23 20:54:00 honda Exp $ */ +/* $NecBSD: bshw_machdep.c,v 1.8.12.6 2001/06/29 06:28:05 honda Exp $ */ /* $NetBSD$ */ /* * [NetBSD for NEC PC-98 series] - * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 + * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. * - * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 + * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,18 +39,19 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/disklabel.h> +#if defined(__FreeBSD__) && __FreeBSD_version > 500001 #include <sys/bio.h> +#endif /* __ FreeBSD__ */ #include <sys/buf.h> #include <sys/queue.h> #include <sys/malloc.h> -#include <sys/device_port.h> #include <sys/errno.h> #include <vm/vm.h> -#include <vm/pmap.h> #ifdef __NetBSD__ +#include <sys/device.h> + #include <machine/bus.h> #include <machine/intr.h> @@ -66,6 +67,7 @@ #include <dev/ic/wd33c93reg.h> #include <i386/Cbus/dev/ct/ctvar.h> +#include <i386/Cbus/dev/ct/ct_machdep.h> #include <i386/Cbus/dev/ct/bshwvar.h> #endif /* __NetBSD__ */ @@ -73,7 +75,6 @@ #include <machine/bus.h> #include <machine/clock.h> #include <machine/md_var.h> -#include <machine/pmap.h> #include <machine/dvcfg.h> #include <machine/physio_proc.h> @@ -82,32 +83,50 @@ #include <dev/ic/wd33c93reg.h> #include <dev/ct/ctvar.h> +#include <dev/ct/ct_machdep.h> #include <dev/ct/bshwvar.h> + +#include <vm/pmap.h> +#endif /* __FreeBSD__ */ + +#define BSHW_IO_CONTROL_FLAGS 0 + +u_int bshw_io_control = BSHW_IO_CONTROL_FLAGS; +int bshw_data_read_bytes = 4096; +int bshw_data_write_bytes = 4096; + +/********************************************************* + * OS dep part + *********************************************************/ +#ifdef __NetBSD__ +#define BSHW_PAGE_SIZE NBPG +#endif /* __NetBSD__ */ + +#ifdef __FreeBSD__ +#define BSHW_PAGE_SIZE PAGE_SIZE +typedef unsigned long vaddr_t; #endif /* __FreeBSD__ */ /********************************************************* * GENERIC MACHDEP FUNCTIONS *********************************************************/ void -bshw_synch_setup(ct, li) +bshw_synch_setup(ct, ti) struct ct_softc *ct; - struct lun_info *li; + struct targ_info *ti; { - struct scsi_low_softc *slp = &ct->sc_sclow; - struct targ_info *ti = slp->sl_nexus; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct ct_targ_info *cti = (void *) ti; struct bshw_softc *bs = ct->ct_hw; struct bshw *hw = bs->sc_hw; - if (hw->sregaddr == 0) + if (hw->hw_sregaddr == 0) return; - ct_cr_write_1(bst, bsh, hw->sregaddr + ti->ti_id, cti->cti_syncreg); + ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id, cti->cti_syncreg); if (hw->hw_flags & BSHW_DOUBLE_DMACHAN) { - ct_cr_write_1(bst, bsh, hw->sregaddr + ti->ti_id + 8, + ct_cr_write_1(chp, hw->hw_sregaddr + ti->ti_id + 8, cti->cti_syncreg); } } @@ -117,8 +136,7 @@ bshw_bus_reset(ct) struct ct_softc *ct; { struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct bshw_softc *bs = ct->ct_hw; struct bshw *hw = bs->sc_hw; bus_addr_t offs; @@ -126,53 +144,52 @@ bshw_bus_reset(ct) int i; /* open hardware busmaster mode */ - if (hw->dma_init != NULL && ((*hw->dma_init)(ct)) != 0) + if (hw->hw_dma_init != NULL && ((*hw->hw_dma_init)(ct)) != 0) { - printf("%s change mode using external DMA (%x)\n", - slp->sl_xname, (u_int)ct_cr_read_1(bst, bsh, 0x37)); + printf("%s: change mode using external DMA (%x)\n", + slp->sl_xname, (u_int)ct_cr_read_1(chp, 0x37)); } /* clear hardware synch registers */ - offs = hw->sregaddr; + offs = hw->hw_sregaddr; if (offs != 0) { for (i = 0; i < 8; i ++, offs ++) { - ct_cr_write_1(bst, bsh, offs, 0); + ct_cr_write_1(chp, offs, 0); if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0) - ct_cr_write_1(bst, bsh, offs + 8, 0); + ct_cr_write_1(chp, offs + 8, 0); } } /* disable interrupt & assert reset */ - regv = ct_cr_read_1(bst, bsh, wd3s_mbank); + regv = ct_cr_read_1(chp, wd3s_mbank); regv |= MBR_RST; regv &= ~MBR_IEN; - ct_cr_write_1(bst, bsh, wd3s_mbank, regv); + ct_cr_write_1(chp, wd3s_mbank, regv); - delay(500000); + SCSI_LOW_DELAY(500000); /* reset signal off */ regv &= ~MBR_RST; - ct_cr_write_1(bst, bsh, wd3s_mbank, regv); + ct_cr_write_1(chp, wd3s_mbank, regv); /* interrupt enable */ regv |= MBR_IEN; - ct_cr_write_1(bst, bsh, wd3s_mbank, regv); + ct_cr_write_1(chp, wd3s_mbank, regv); } /* probe */ int -bshw_read_settings(bst, bsh, bs) - bus_space_tag_t bst; - bus_space_handle_t bsh; +bshw_read_settings(chp, bs) + struct ct_bus_access_handle *chp; struct bshw_softc *bs; { static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 }; - bs->sc_hostid = (ct_cr_read_1(bst, bsh, wd3s_auxc) & AUXCR_HIDM); - bs->sc_irq = irq_tbl[(ct_cr_read_1(bst, bsh, wd3s_auxc) >> 3) & 7]; - bs->sc_drq = bus_space_read_1(bst, bsh, cmd_port) & 3; + bs->sc_hostid = (ct_cr_read_1(chp, wd3s_auxc) & AUXCR_HIDM); + bs->sc_irq = irq_tbl[(ct_cr_read_1(chp, wd3s_auxc) >> 3) & 7]; + bs->sc_drq = ct_cmdp_read_1(chp) & 3; return 0; } @@ -194,18 +211,17 @@ bshw_read_settings(bst, bsh, bs) #define SF_RDY 0x10 static __inline void bshw_lc_smit_start __P((struct ct_softc *, int, u_int)); -static int bshw_lc_smit_fstat __P((struct ct_softc *, int, int)); static __inline void bshw_lc_smit_stop __P((struct ct_softc *)); +static int bshw_lc_smit_fstat __P((struct ct_softc *, int, int)); static __inline void bshw_lc_smit_stop(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - ct_cr_write_1(bst, bsh, BSHW_LC_FCTRL, 0); - bus_space_write_1(ct->sc_iot, ct->sc_ioh, cmd_port, CMDP_DMER); + ct_cr_write_1(chp, BSHW_LC_FCTRL, 0); + ct_cmdp_write_1(chp, CMDP_DMER); } static __inline void @@ -214,18 +230,17 @@ bshw_lc_smit_start(ct, count, direction) int count; u_int direction; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; u_int8_t pval, val; - val = ct_cr_read_1(bst, bsh, BSHW_LC_FSET); - cthw_set_count(bst, bsh, count); + val = ct_cr_read_1(chp, BSHW_LC_FSET); + cthw_set_count(chp, count); pval = FCTRL_EN; if (direction == SCSI_LOW_WRITE) pval |= (val & 0xe0) | FCTRL_WRITE; - ct_cr_write_1(bst, bsh, BSHW_LC_FCTRL, pval); - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_TFR_INFO); + ct_cr_write_1(chp, BSHW_LC_FCTRL, pval); + ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO); } static int @@ -233,12 +248,13 @@ bshw_lc_smit_fstat(ct, wc, read) struct ct_softc *ct; int wc, read; { + struct ct_bus_access_handle *chp = &ct->sc_ch; u_int8_t stat; while (wc -- > 0) { - outb(0x5f, 0); - stat = bus_space_read_1(ct->sc_iot, ct->sc_ioh, cmd_port); + chp->ch_bus_weight(chp); + stat = ct_cmdp_read_1(chp); if (read == SCSI_LOW_READ) { if ((stat & SF_RDY) != 0) @@ -268,68 +284,85 @@ bshw_smit_xfer_stop(ct) struct targ_info *ti; struct sc_p *sp = &slp->sl_scp; u_int count; - u_char *s; bshw_lc_smit_stop(ct); - ti = slp->sl_nexus; + ti = slp->sl_Tnexus; if (ti == NULL) return; if (ti->ti_phase == PH_DATA) { - count = cthw_get_count(ct->sc_iot, ct->sc_ioh); - if (count < (u_int) sp->scp_datalen) + count = cthw_get_count(&ct->sc_ch); + if (count < bs->sc_sdatalen) { - sp->scp_data += (sp->scp_datalen - count); - sp->scp_datalen = count; - /* XXX: - * strict double checks! - * target => wd33c93c transfer counts - * wd33c93c => memory transfer counts - */ if (sp->scp_direction == SCSI_LOW_READ && - count != bs->sc_tdatalen) - { - s = "read count miss"; + count != bs->sc_edatalen) goto bad; - } - return; + + count = bs->sc_sdatalen - count; + if (count > (u_int) sp->scp_datalen) + goto bad; + + sp->scp_data += count; + sp->scp_datalen -= count; } - else if (count == (u_int) sp->scp_datalen) + else if (count > bs->sc_sdatalen) { - return; +bad: + printf("%s: smit_xfer_end: cnt error\n", slp->sl_xname); + slp->sl_error |= PDMAERR; } - - s = "strange count"; + scsi_low_data_finish(slp); } else - s = "extra smit interrupt"; - -bad: - printf("%s: smit_xfer_end: %s", slp->sl_xname, s); - slp->sl_error |= PDMAERR; + { + printf("%s: smit_xfer_end: phase miss\n", slp->sl_xname); + slp->sl_error |= PDMAERR; + } } -void +int bshw_smit_xfer_start(ct) struct ct_softc *ct; { struct scsi_low_softc *slp = &ct->sc_sclow; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct bshw_softc *bs = ct->ct_hw; struct sc_p *sp = &slp->sl_scp; - struct targ_info *ti = slp->sl_nexus; + struct targ_info *ti = slp->sl_Tnexus; struct ct_targ_info *cti = (void *) ti; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - int datalen, count, wc = LC_SMIT_TIMEOUT * 1024 * 1024; + u_int datalen, count, io_control; + int wc; u_int8_t *data; - data = sp->scp_data; + io_control = bs->sc_io_control | bshw_io_control; + if ((io_control & BSHW_SMIT_BLOCK) != 0) + return EINVAL; + + if ((slp->sl_scp.scp_datalen % DEV_BSIZE) != 0) + return EINVAL; + datalen = sp->scp_datalen; + if (slp->sl_scp.scp_direction == SCSI_LOW_READ) + { + if ((io_control & BSHW_READ_INTERRUPT_DRIVEN) != 0 && + datalen > bshw_data_read_bytes) + datalen = bshw_data_read_bytes; + } + else + { + if ((io_control & BSHW_WRITE_INTERRUPT_DRIVEN) != 0 && + datalen > bshw_data_write_bytes) + datalen = bshw_data_write_bytes; + } + + bs->sc_sdatalen = datalen; + data = sp->scp_data; + wc = LC_SMIT_TIMEOUT * 1024 * 1024; - ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA); - bshw_lc_smit_start(ct, sp->scp_datalen, sp->scp_direction); + ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA); + bshw_lc_smit_start(ct, datalen, sp->scp_direction); if (sp->scp_direction == SCSI_LOW_READ) { @@ -339,14 +372,14 @@ bshw_smit_xfer_start(ct) break; count = (datalen > LC_FSZ ? LC_FSZ : datalen); - bus_space_read_region_4(ct->sc_memt, ct->sc_memh, + bus_space_read_region_4(chp->ch_memt, chp->ch_memh, LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2); data += count; datalen -= count; } while (datalen > 0); - bs->sc_tdatalen = datalen; + bs->sc_edatalen = datalen; } else { @@ -365,7 +398,7 @@ bshw_smit_xfer_start(ct) } count = (datalen > LC_SFSZ ? LC_SFSZ : datalen); - bus_space_write_region_4(ct->sc_memt, ct->sc_memh, + bus_space_write_region_4(chp->ch_memt, chp->ch_memh, LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2); data += count; datalen -= count; @@ -374,7 +407,7 @@ bshw_smit_xfer_start(ct) break; count = (datalen > LC_REST ? LC_REST : datalen); - bus_space_write_region_4(ct->sc_memt, ct->sc_memh, + bus_space_write_region_4(chp->ch_memt, chp->ch_memh, LC_SMIT_OFFSET + LC_SFSZ, (u_int32_t *) data, count >> 2); data += count; @@ -382,26 +415,33 @@ bshw_smit_xfer_start(ct) } while (datalen > 0); } + return 0; } /********************************************************* * DMA TRANSFER (BS) *********************************************************/ +static __inline void bshw_dma_write_1 \ + __P((struct ct_bus_access_handle *, bus_addr_t, u_int8_t)); static void bshw_dmastart __P((struct ct_softc *)); static void bshw_dmadone __P((struct ct_softc *)); -void +int bshw_dma_xfer_start(ct) struct ct_softc *ct; { struct scsi_low_softc *slp = &ct->sc_sclow; struct sc_p *sp = &slp->sl_scp; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct bshw_softc *bs = ct->ct_hw; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; vaddr_t va, endva, phys, nphys; + u_int io_control; + + io_control = bs->sc_io_control | bshw_io_control; + if ((io_control & BSHW_DMA_BLOCK) != 0 && sp->scp_datalen < 256) + return EINVAL; - ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA); + ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA); phys = vtophys((vaddr_t) sp->scp_data); if (phys >= bs->sc_minphys) { @@ -421,19 +461,17 @@ bshw_dma_xfer_start(ct) /* setup segaddr */ bs->sc_segaddr = (u_int8_t *) phys; /* setup seglen */ - endva = (vaddr_t)round_page((vaddr_t)(sp->scp_data + - sp->scp_datalen)); + endva = (vaddr_t) round_page((vaddr_t) sp->scp_data + sp->scp_datalen); for (va = (vaddr_t) sp->scp_data; ; phys = nphys) { - if ((va += PAGE_SIZE) >= endva) + if ((va += BSHW_PAGE_SIZE) >= endva) { bs->sc_seglen = sp->scp_datalen; break; } nphys = vtophys(va); - if (phys + PAGE_SIZE != nphys || - nphys >= bs->sc_minphys) + if (phys + BSHW_PAGE_SIZE != nphys || nphys >= bs->sc_minphys) { bs->sc_seglen = (u_int8_t *) trunc_page(va) - sp->scp_data; @@ -445,7 +483,9 @@ bshw_dma_xfer_start(ct) } bshw_dmastart(ct); - cthw_set_count(bst, bsh, bs->sc_seglen); + cthw_set_count(chp, bs->sc_seglen); + ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO); + return 0; } void @@ -460,13 +500,13 @@ bshw_dma_xfer_stop(ct) bshw_dmadone(ct); - ti = slp->sl_nexus; + ti = slp->sl_Tnexus; if (ti == NULL) return; if (ti->ti_phase == PH_DATA) { - count = cthw_get_count(ct->sc_iot, ct->sc_ioh); + count = cthw_get_count(&ct->sc_ch); if (count < (u_int) bs->sc_seglen) { transbytes = bs->sc_seglen - count; @@ -474,31 +514,27 @@ bshw_dma_xfer_stop(ct) sp->scp_direction == SCSI_LOW_READ) bcopy(bs->sc_bufp, sp->scp_data, transbytes); - bs->sc_bufp = NULL; sp->scp_data += transbytes; sp->scp_datalen -= transbytes; - return; } - else if (count == (u_int) bs->sc_seglen) + else if (count > (u_int) bs->sc_seglen) { - bs->sc_bufp = NULL; - return; + printf("%s: port data %x != seglen %x\n", + slp->sl_xname, count, bs->sc_seglen); + slp->sl_error |= PDMAERR; } - printf("%s: port data %x != seglen %x\n", - slp->sl_xname, count, bs->sc_seglen); + scsi_low_data_finish(slp); } else { printf("%s: extra DMA interrupt\n", slp->sl_xname); + slp->sl_error |= PDMAERR; } - slp->sl_error |= PDMAERR; bs->sc_bufp = NULL; } -static int dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 }; - /* common dma settings */ #undef DMA1_SMSK #define DMA1_SMSK (0x15) @@ -514,56 +550,64 @@ static int dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 }; #define DMA37MD_READ 0x08 #define DMA37MD_SINGLE 0x40 +static bus_addr_t dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 }; + +static __inline void +bshw_dma_write_1(chp, port, val) + struct ct_bus_access_handle *chp; + bus_addr_t port; + u_int8_t val; +{ + + CT_BUS_WEIGHT(chp); + outb(port, val); +} + static void bshw_dmastart(ct) struct ct_softc *ct; { struct scsi_low_softc *slp = &ct->sc_sclow; struct bshw_softc *bs = ct->ct_hw; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; int chan = bs->sc_drq; - int waport; - u_int8_t *phys = bs->sc_segaddr; + bus_addr_t waport; + u_int8_t regv, *phys = bs->sc_segaddr; u_int nbytes = bs->sc_seglen; + /* flush cpu cache */ + (*bs->sc_dmasync_before) (ct); + /* * Program one of DMA channels 0..3. These are * byte mode channels. */ /* set dma channel mode, and reset address ff */ -#ifdef __FreeBSD__ - if (need_pre_dma_flush) - wbinvd(); -#else - if (slp->sl_scp.scp_direction == SCSI_LOW_READ) - cpu_cf_preRead(curcpu); - else - cpu_cf_preWrite(curcpu); -#endif if (slp->sl_scp.scp_direction == SCSI_LOW_READ) - outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_WRITE | chan); + regv = DMA37MD_WRITE | DMA37MD_SINGLE | chan; else - outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan); - outb(DMA1_FFC, 0); + regv = DMA37MD_READ | DMA37MD_SINGLE | chan; + + bshw_dma_write_1(chp, DMA1_MODE, regv); + bshw_dma_write_1(chp, DMA1_FFC, 0); /* send start address */ waport = DMA1_CHN(chan); - outb(waport, (u_int) phys); - outb(waport, ((u_int) phys) >> 8); - outb(dmapageport[chan], ((u_int) phys) >> 16); + bshw_dma_write_1(chp, waport, (u_int) phys); + bshw_dma_write_1(chp, waport, ((u_int) phys) >> 8); + bshw_dma_write_1(chp, dmapageport[chan], ((u_int) phys) >> 16); /* send count */ - outb(waport + 2, --nbytes); - outb(waport + 2, nbytes >> 8); + bshw_dma_write_1(chp, waport + 2, --nbytes); + bshw_dma_write_1(chp, waport + 2, nbytes >> 8); /* vendor unique hook */ - if (bs->sc_hw->dma_start) - (*bs->sc_hw->dma_start)(ct); + if (bs->sc_hw->hw_dma_start) + (*bs->sc_hw->hw_dma_start)(ct); - outb(DMA1_SMSK, chan); - bus_space_write_1(bst, bsh, cmd_port, CMDP_DMES); + bshw_dma_write_1(chp, DMA1_SMSK, chan); + ct_cmdp_write_1(chp, CMDP_DMES); } static void @@ -571,25 +615,17 @@ bshw_dmadone(ct) struct ct_softc *ct; { struct bshw_softc *bs = ct->ct_hw; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - outb(DMA1_SMSK, (bs->sc_drq | DMA37SM_SET)); - bus_space_write_1(bst, bsh, cmd_port, CMDP_DMER); + bshw_dma_write_1(chp, DMA1_SMSK, (bs->sc_drq | DMA37SM_SET)); + ct_cmdp_write_1(chp, CMDP_DMER); /* vendor unique hook */ - if (bs->sc_hw->dma_stop) - (*bs->sc_hw->dma_stop)(ct); + if (bs->sc_hw->hw_dma_stop) + (*bs->sc_hw->hw_dma_stop) (ct); -#ifdef __FreeBSD__ - if (need_post_dma_flush) - invd(); -#else - if (slp->sl_scp.scp_direction == SCSI_LOW_READ) - cpu_cf_postRead(curcpu); - else - cpu_cf_postWrite(curcpu); -#endif + /* flush cpu cache */ + (*bs->sc_dmasync_after) (ct); } /********************************************** @@ -606,16 +642,15 @@ static int bshw_dma_init_texa(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; u_int8_t regval; - if ((regval = ct_cr_read_1(bst, bsh, 0x37)) & 0x08) + if ((regval = ct_cr_read_1(chp, 0x37)) & 0x08) return 0; - ct_cr_write_1(bst, bsh, 0x37, regval | 0x08); - regval = ct_cr_read_1(bst, bsh, 0x3f); - ct_cr_write_1(bst, bsh, 0x3f, regval | 0x08); + ct_cr_write_1(chp, 0x37, regval | 0x08); + regval = ct_cr_read_1(chp, 0x3f); + ct_cr_write_1(chp, 0x3f, regval | 0x08); return 1; } @@ -623,26 +658,25 @@ static int bshw_dma_init_sc98(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - if (ct_cr_read_1(bst, bsh, 0x37) & 0x08) + if (ct_cr_read_1(chp, 0x37) & 0x08) return 0; /* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */ - ct_cr_write_1(bst, bsh, 0x37, 0x1a); - ct_cr_write_1(bst, bsh, 0x3f, 0x1a); + ct_cr_write_1(chp, 0x37, 0x1a); + ct_cr_write_1(chp, 0x3f, 0x1a); #if 0 /* only valid for IO */ - ct_cr_write_1(bst, bsh, 0x40, 0xf4); - ct_cr_write_1(bst, bsh, 0x41, 0x9); - ct_cr_write_1(bst, bsh, 0x43, 0xff); - ct_cr_write_1(bst, bsh, 0x46, 0x4e); - - ct_cr_write_1(bst, bsh, 0x48, 0xf4); - ct_cr_write_1(bst, bsh, 0x49, 0x9); - ct_cr_write_1(bst, bsh, 0x4b, 0xff); - ct_cr_write_1(bst, bsh, 0x4e, 0x4e); + ct_cr_write_1(chp, 0x40, 0xf4); + ct_cr_write_1(chp, 0x41, 0x9); + ct_cr_write_1(chp, 0x43, 0xff); + ct_cr_write_1(chp, 0x46, 0x4e); + + ct_cr_write_1(chp, 0x48, 0xf4); + ct_cr_write_1(chp, 0x49, 0x9); + ct_cr_write_1(chp, 0x4b, 0xff); + ct_cr_write_1(chp, 0x4e, 0x4e); #endif return 1; } @@ -651,44 +685,40 @@ static void bshw_dma_start_sc98(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - ct_cr_write_1(bst, bsh, 0x73, 0x32); - ct_cr_write_1(bst, bsh, 0x74, 0x23); + ct_cr_write_1(chp, 0x73, 0x32); + ct_cr_write_1(chp, 0x74, 0x23); } static void bshw_dma_stop_sc98(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - ct_cr_write_1(bst, bsh, 0x73, 0x43); - ct_cr_write_1(bst, bsh, 0x74, 0x34); + ct_cr_write_1(chp, 0x73, 0x43); + ct_cr_write_1(chp, 0x74, 0x34); } static void bshw_dma_start_elecom(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - u_int8_t tmp = ct_cr_read_1(bst, bsh, 0x4c); + struct ct_bus_access_handle *chp = &ct->sc_ch; + u_int8_t tmp = ct_cr_read_1(chp, 0x4c); - ct_cr_write_1(bst, bsh, 0x32, tmp & 0xdf); + ct_cr_write_1(chp, 0x32, tmp & 0xdf); } static void bshw_dma_stop_elecom(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - u_int8_t tmp = ct_cr_read_1(bst, bsh, 0x4c); + struct ct_bus_access_handle *chp = &ct->sc_ch; + u_int8_t tmp = ct_cr_read_1(chp, 0x4c); - ct_cr_write_1(bst, bsh, 0x32, tmp | 0x20); + ct_cr_write_1(chp, 0x32, tmp | 0x20); } static struct bshw bshw_generic = { diff --git a/sys/dev/ct/bshwvar.h b/sys/dev/ct/bshwvar.h index 6e31b4d..17268f0 100644 --- a/sys/dev/ct/bshwvar.h +++ b/sys/dev/ct/bshwvar.h @@ -1,5 +1,5 @@ /* $FreeBSD$ */ -/* $NecBSD: bshwvar.h,v 1.3 1999/04/15 01:36:10 kmatsuda Exp $ */ +/* $NecBSD: bshwvar.h,v 1.3.14.3 2001/06/21 04:07:37 honda Exp $ */ /* $NetBSD$ */ /* @@ -46,12 +46,11 @@ struct bshw { #define BSHW_SMFIFO 0x02 #define BSHW_DOUBLE_DMACHAN 0x04 u_int hw_flags; + u_int hw_sregaddr; - u_int sregaddr; - - int ((*dma_init) __P((struct ct_softc *))); - void ((*dma_start) __P((struct ct_softc *))); - void ((*dma_stop) __P((struct ct_softc *))); + int ((*hw_dma_init) __P((struct ct_softc *))); + void ((*hw_dma_start) __P((struct ct_softc *))); + void ((*hw_dma_stop) __P((struct ct_softc *))); }; struct bshw_softc { @@ -63,7 +62,8 @@ struct bshw_softc { u_int8_t *sc_segaddr; u_int8_t *sc_bufp; int sc_seglen; - int sc_tdatalen; /* temp datalen */ + u_int sc_sdatalen; /* SMIT */ + u_int sc_edatalen; /* SMIT */ /* private bounce */ u_int8_t *sc_bounce_phys; @@ -71,16 +71,26 @@ struct bshw_softc { u_int sc_bounce_size; bus_addr_t sc_minphys; + /* io control */ +#define BSHW_READ_INTERRUPT_DRIVEN 0x0001 +#define BSHW_WRITE_INTERRUPT_DRIVEN 0x0002 +#define BSHW_DMA_BLOCK 0x0010 +#define BSHW_SMIT_BLOCK 0x0020 + u_int sc_io_control; + /* hardware */ struct bshw *sc_hw; + void ((*sc_dmasync_before)) __P((struct ct_softc *)); + void ((*sc_dmasync_after)) __P((struct ct_softc *)); }; -void bshw_synch_setup __P((struct ct_softc *, struct lun_info *)); +void bshw_synch_setup __P((struct ct_softc *, struct targ_info *)); void bshw_bus_reset __P((struct ct_softc *)); -int bshw_read_settings __P((bus_space_tag_t, bus_space_handle_t, struct bshw_softc *)); -void bshw_smit_xfer_start __P((struct ct_softc *)); +int bshw_read_settings __P((struct ct_bus_access_handle *, struct bshw_softc *)); +int bshw_smit_xfer_start __P((struct ct_softc *)); void bshw_smit_xfer_stop __P((struct ct_softc *)); -void bshw_dma_xfer_start __P((struct ct_softc *)); +int bshw_dma_xfer_start __P((struct ct_softc *)); void bshw_dma_xfer_stop __P((struct ct_softc *)); + extern struct dvcfg_hwsel bshw_hwsel; #endif /* !_BSHWVAR_H_ */ diff --git a/sys/dev/ct/ct.c b/sys/dev/ct/ct.c index f2fe883a..6c46493 100644 --- a/sys/dev/ct/ct.c +++ b/sys/dev/ct/ct.c @@ -1,16 +1,16 @@ /* $FreeBSD$ */ -/* $NecBSD: ct.c,v 1.13 1999/07/23 20:54:00 honda Exp $ */ +/* $NecBSD: ct.c,v 1.13.12.5 2001/06/26 07:31:53 honda Exp $ */ /* $NetBSD$ */ #define CT_DEBUG -#define CT_USE_CCSEQ +#define CT_IO_CONTROL_FLAGS (CT_USE_CCSEQ | CT_FAST_INTR) /* * [NetBSD for NEC PC-98 series] - * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 + * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. * - * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999 + * Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,17 +42,17 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> -#include <sys/disklabel.h> +#if defined(__FreeBSD__) && __FreeBSD_version > 500001 #include <sys/bio.h> +#endif /* __ FreeBSD__ */ #include <sys/buf.h> #include <sys/queue.h> #include <sys/malloc.h> -#include <sys/device_port.h> #include <sys/errno.h> -#include <vm/vm.h> - #ifdef __NetBSD__ +#include <sys/device.h> + #include <machine/bus.h> #include <machine/intr.h> @@ -68,6 +68,7 @@ #include <dev/ic/wd33c93reg.h> #include <i386/Cbus/dev/ct/ctvar.h> +#include <i386/Cbus/dev/ct/ct_machdep.h> #endif /* __NetBSD__ */ #ifdef __FreeBSD__ @@ -80,28 +81,31 @@ #include <dev/ic/wd33c93reg.h> #include <dev/ct/ctvar.h> +#include <dev/ct/ct_machdep.h> #endif /* __FreeBSD__ */ +#define CT_NTARGETS 8 +#define CT_NLUNS 8 +#define CT_RESET_DEFAULT 2000 +#define CT_DELAY_MAX (2 * 1000 * 1000) +#define CT_DELAY_INTERVAL (1) + /*************************************************** * DEBUG ***************************************************/ -#define CT_NTARGETS 8 -#define CT_NLUNS 8 -#define CT_RESET_DEFAULT 2000 - -#ifndef DDB -#define Debugger() panic("should call debugger here (ct.c)") -#else /* ! DDB */ -#ifdef __FreeBSD__ -#define Debugger() Debugger("ct") -#endif /* __FreeBSD__ */ -#endif - #ifdef CT_DEBUG int ct_debug; #endif /* CT_DEBUG */ /*************************************************** + * IO control + ***************************************************/ +#define CT_USE_CCSEQ 0x0100 +#define CT_FAST_INTR 0x0200 + +u_int ct_io_control = CT_IO_CONTROL_FLAGS; + +/*************************************************** * default data ***************************************************/ u_int8_t cthw_cmdlevel[256] = { @@ -124,44 +128,61 @@ u_int8_t cthw_cmdlevel[256] = { /*F*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 , }; +#if 0 /* default synch data table */ /* A 10 6.6 5.0 4.0 3.3 2.8 2.5 2.0 M/s */ /* X 100 150 200 250 300 350 400 500 ns */ -static struct ct_synch_data ct_synch_data_20MHz[] = { +static struct ct_synch_data ct_synch_data_FSCSI[] = { {25, 0xa0}, {37, 0xb0}, {50, 0x20}, {62, 0xd0}, {75, 0x30}, {87, 0xf0}, {100, 0x40}, {125, 0x50}, {0, 0} }; -extern unsigned int delaycount; +static struct ct_synch_data ct_synch_data_SCSI[] = { + {50, 0x20}, {75, 0x30}, {100, 0x40}, {125, 0x50}, {0, 0} +}; +#endif +/*************************************************** + * DEVICE STRUCTURE + ***************************************************/ +extern struct cfdriver ct_cd; /***************************************************************** * Interface functions *****************************************************************/ -static int ct_xfer __P((struct ct_softc *, u_int8_t *, int, int)); +static int ct_xfer __P((struct ct_softc *, u_int8_t *, int, int, u_int *)); static void ct_io_xfer __P((struct ct_softc *)); -static __inline int ct_reselected __P((struct ct_softc *)); +static int ct_reselected __P((struct ct_softc *, u_int8_t)); static void ct_phase_error __P((struct ct_softc *, u_int8_t)); static int ct_start_selection __P((struct ct_softc *, struct slccb *)); static int ct_msg __P((struct ct_softc *, struct targ_info *, u_int)); static int ct_world_start __P((struct ct_softc *, int)); static __inline void cthw_phase_bypass __P((struct ct_softc *, u_int8_t)); -static int cthw_chip_reset __P((bus_space_tag_t, bus_space_handle_t, int, int)); +static int cthw_chip_reset __P((struct ct_bus_access_handle *, int *, int, int)); static void cthw_bus_reset __P((struct ct_softc *)); -static int ct_nexus __P((struct ct_softc *, struct targ_info *)); +static int ct_ccb_nexus_establish __P((struct ct_softc *)); +static int ct_lun_nexus_establish __P((struct ct_softc *)); +static int ct_target_nexus_establish __P((struct ct_softc *, int, int)); static void cthw_attention __P((struct ct_softc *)); -static int ct_targ_init __P((struct ct_softc *, struct targ_info *)); +static int ct_targ_init __P((struct ct_softc *, struct targ_info *, int)); +static int ct_unbusy __P((struct ct_softc *)); +static void ct_attention __P((struct ct_softc *)); +static struct ct_synch_data *ct_make_synch_table __P((struct ct_softc *)); +static int ct_catch_intr __P((struct ct_softc *)); struct scsi_low_funcs ct_funcs = { SC_LOW_INIT_T ct_world_start, SC_LOW_BUSRST_T cthw_bus_reset, SC_LOW_TARG_INIT_T ct_targ_init, + SC_LOW_LUN_INIT_T NULL, SC_LOW_SELECT_T ct_start_selection, - SC_LOW_NEXUS_T ct_nexus, + SC_LOW_NEXUS_T ct_lun_nexus_establish, + SC_LOW_NEXUS_T ct_ccb_nexus_establish, SC_LOW_ATTEN_T cthw_attention, SC_LOW_MSG_T ct_msg, + SC_LOW_TIMEOUT_T NULL, SC_LOW_POLL_T ctintr, NULL, /* SC_LOW_POWER_T cthw_power, */ @@ -175,12 +196,10 @@ cthw_phase_bypass(ct, ph) struct ct_softc *ct; u_int8_t ph; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - ct_cr_write_1(bst, bsh, wd3s_cph, ph); - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_SELECT_ATN_TFR); - ct->sc_satgo = CT_SAT_GOING; + ct_cr_write_1(chp, wd3s_cph, ph); + ct_cr_write_1(chp, wd3s_cmd, WD3S_SELECT_ATN_TFR); } static void @@ -196,9 +215,9 @@ cthw_bus_reset(ct) } static int -cthw_chip_reset(bst, bsh, chipclk, hostid) - bus_space_tag_t bst; - bus_space_handle_t bsh; +cthw_chip_reset(chp, chiprevp, chipclk, hostid) + struct ct_bus_access_handle *chp; + int *chiprevp; int chipclk, hostid; { #define CT_SELTIMEOUT_20MHz_REGV (0x80) @@ -207,26 +226,29 @@ cthw_chip_reset(bst, bsh, chipclk, hostid) int wc; /* issue abort cmd */ - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_ABORT); - delay(1000); /* 1ms wait */ - (void) ct_stat_read_1(bst, bsh); - (void) ct_cr_read_1(bst, bsh, wd3s_stat); + ct_cr_write_1(chp, wd3s_cmd, WD3S_ABORT); + SCSI_LOW_DELAY(1000); /* 1ms wait */ + (void) ct_stat_read_1(chp); + (void) ct_cr_read_1(chp, wd3s_stat); /* setup chip registers */ regv = 0; seltout = CT_SELTIMEOUT_20MHz_REGV; switch (chipclk) { + case 8: case 10: seltout = (seltout * chipclk) / 20; - regv = 0; + regv = IDR_FS_8_10; break; + case 12: case 15: seltout = (seltout * chipclk) / 20; regv = IDR_FS_12_15; break; + case 16: case 20: seltout = (seltout * chipclk) / 20; regv = IDR_FS_16_20; @@ -236,51 +258,117 @@ cthw_chip_reset(bst, bsh, chipclk, hostid) panic("ct: illegal chip clk rate\n"); break; } - regv |= IDR_EHP | hostid; - ct_cr_write_1(bst, bsh, wd3s_oid, regv); - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_RESET); + regv |= IDR_EHP | hostid | IDR_RAF | IDR_EAF; + ct_cr_write_1(chp, wd3s_oid, regv); + + ct_cr_write_1(chp, wd3s_cmd, WD3S_RESET); for (wc = CT_RESET_DEFAULT; wc > 0; wc --) { - aux = ct_stat_read_1(bst, bsh); + aux = ct_stat_read_1(chp); if (aux != 0xff && (aux & STR_INT)) { - if (ct_cr_read_1(bst, bsh, wd3s_stat) == 0) + regv = ct_cr_read_1(chp, wd3s_stat); + if (regv == BSR_RESET || regv == BSR_AFM_RESET) break; - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_RESET); + ct_cr_write_1(chp, wd3s_cmd, WD3S_RESET); } - delay(1); + SCSI_LOW_DELAY(1); } if (wc == 0) return ENXIO; - ct_cr_write_1(bst, bsh, wd3s_tout, seltout); - ct_cr_write_1(bst, bsh, wd3s_sid, SIDR_RESEL); - ct_cr_write_1(bst, bsh, wd3s_ctrl, CR_DEFAULT); - ct_cr_write_1(bst, bsh, wd3s_synch, 0); + ct_cr_write_1(chp, wd3s_tout, seltout); + ct_cr_write_1(chp, wd3s_sid, SIDR_RESEL); + ct_cr_write_1(chp, wd3s_ctrl, CR_DEFAULT); + ct_cr_write_1(chp, wd3s_synch, 0); + if (chiprevp != NULL) + { + *chiprevp = CT_WD33C93; + if (regv == BSR_RESET) + goto out; + + *chiprevp = CT_WD33C93_A; + ct_cr_write_1(chp, wd3s_qtag, 0xaa); + if (ct_cr_read_1(chp, wd3s_qtag) != 0xaa) + { + ct_cr_write_1(chp, wd3s_qtag, 0x0); + goto out; + } + ct_cr_write_1(chp, wd3s_qtag, 0x55); + if (ct_cr_read_1(chp, wd3s_qtag) != 0x55) + { + ct_cr_write_1(chp, wd3s_qtag, 0x0); + goto out; + } + ct_cr_write_1(chp, wd3s_qtag, 0x0); + *chiprevp = CT_WD33C93_B; + } - (void) ct_stat_read_1(bst, bsh); - (void) ct_cr_read_1(bst, bsh, wd3s_stat); +out: + (void) ct_stat_read_1(chp); + (void) ct_cr_read_1(chp, wd3s_stat); return 0; } +static struct ct_synch_data * +ct_make_synch_table(ct) + struct ct_softc *ct; +{ + struct ct_synch_data *sdtp, *sdp; + u_int base, i, period; + + sdtp = sdp = &ct->sc_default_sdt[0]; + + if ((ct->sc_chipclk % 5) == 0) + base = 1000 / (5 * 2); /* 5 MHz type */ + else + base = 1000 / (4 * 2); /* 4 MHz type */ + + if (ct->sc_chiprev >= CT_WD33C93_B) + { + /* fast scsi */ + for (i = 2; i < 8; i ++, sdp ++) + { + period = (base * i) / 2; + if (period >= 200) /* 5 MHz */ + break; + sdp->cs_period = period / 4; + sdp->cs_syncr = (i * 0x10) | 0x80; + } + } + + for (i = 2; i < 8; i ++, sdp ++) + { + period = (base * i); + if (period > 500) /* 2 MHz */ + break; + sdp->cs_period = period / 4; + sdp->cs_syncr = (i * 0x10); + } + + sdp->cs_period = 0; + sdp->cs_syncr = 0; + return sdtp; +} + /************************************************** * Attach & Probe **************************************************/ int -ctprobesubr(bst, bsh, dvcfg, hsid, chipclk) - bus_space_tag_t bst; - bus_space_handle_t bsh; +ctprobesubr(chp, dvcfg, hsid, chipclk, chiprevp) + struct ct_bus_access_handle *chp; u_int dvcfg, chipclk; int hsid; + int *chiprevp; { #if 0 - if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 0) + if ((ct_stat_read_1(chp) & STR_BSY) != 0) return 0; #endif - if (cthw_chip_reset(bst, bsh, chipclk, hsid) != 0) + if (cthw_chip_reset(chp, chiprevp, chipclk, hsid) != 0) return 0; return 1; } @@ -302,10 +390,11 @@ ctattachsubr(ct) { struct scsi_low_softc *slp = &ct->sc_sclow; - ct->sc_wc = delaycount * 2000; /* 2 sec */ + ct->sc_tmaxcnt = SCSI_LOW_MIN_TOUT * 1000 * 1000; /* default */ slp->sl_funcs = &ct_funcs; - (void) scsi_low_attach(slp, 2, CT_NTARGETS, CT_NLUNS, - sizeof(struct ct_targ_info)); + slp->sl_flags |= HW_READ_PADDING; + (void) scsi_low_attach(slp, 0, CT_NTARGETS, CT_NLUNS, + sizeof(struct ct_targ_info), 0); } /************************************************** @@ -315,44 +404,75 @@ static void cthw_attention(ct) struct ct_softc *ct; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; - if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 0) - { - ct->sc_atten = 1; + ct->sc_atten = 1; + if ((ct_stat_read_1(chp) & (STR_BSY | STR_CIP)) != 0) return; - } - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_ASSERT_ATN); - delay(10); - if ((ct_stat_read_1(bst, bsh) & STR_LCI) != 0) + ct_cr_write_1(chp, wd3s_cmd, WD3S_ASSERT_ATN); + SCSI_LOW_DELAY(10); + if ((ct_stat_read_1(chp) & STR_LCI) == 0) + ct->sc_atten = 0; + ct_unbusy(ct); + return; +} + +static void +ct_attention(ct) + struct ct_softc *ct; +{ + struct scsi_low_softc *slp = &ct->sc_sclow; + + if (slp->sl_atten == 0) { - ct->sc_atten = 1; - return; + ct_unbusy(ct); + scsi_low_attention(slp); + } + else if (ct->sc_atten != 0) + { + ct_unbusy(ct); + cthw_attention(ct); } - ct->sc_atten = 0; } static int -ct_targ_init(ct, ti) +ct_targ_init(ct, ti, action) struct ct_softc *ct; struct targ_info *ti; + int action; { struct ct_targ_info *cti = (void *) ti; - if (ct->sc_chiprev == CT_WD33C93_A) + if (action == SCSI_LOW_INFO_ALLOC || action == SCSI_LOW_INFO_REVOKE) { - ti->ti_maxsynch.period = 200 / 4; /* 5MHz */ - ti->ti_maxsynch.offset = 8; - } - else - { - ti->ti_maxsynch.period = 100 / 4; /* 10MHz */ - ti->ti_maxsynch.offset = 12; + if (ct->sc_sdp == NULL) + { + ct->sc_sdp = ct_make_synch_table(ct); + } + + switch (ct->sc_chiprev) + { + default: + ti->ti_maxsynch.offset = 5; + break; + + case CT_WD33C93_A: + case CT_AM33C93_A: + ti->ti_maxsynch.offset = 12; + break; + + case CT_WD33C93_B: + case CT_WD33C93_C: + ti->ti_maxsynch.offset = 12; + break; + } + + ti->ti_maxsynch.period = ct->sc_sdp[0].cs_period; + ti->ti_width = SCSI_LOW_BUS_WIDTH_8; + cti->cti_syncreg = 0; } - cti->cti_syncreg = 0; return 0; } @@ -362,14 +482,13 @@ ct_world_start(ct, fdone) int fdone; { struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - intrmask_t s; + struct ct_bus_access_handle *chp = &ct->sc_ch; if (ct->sc_sdp == NULL) - ct->sc_sdp = &ct_synch_data_20MHz[0]; + { + ct->sc_sdp = ct_make_synch_table(ct); + } - slp->sl_cfgflags |= CFG_MSGUNIFY; if (slp->sl_cfgflags & CFG_NOPARITY) ct->sc_creg = CR_DEFAULT; else @@ -382,11 +501,9 @@ ct_world_start(ct, fdone) ct->sc_dma = 0; ct->sc_atten = 0; - s = splcam(); - cthw_chip_reset(bst, bsh, ct->sc_chipclk, slp->sl_hostid); + cthw_chip_reset(chp, NULL, ct->sc_chipclk, slp->sl_hostid); scsi_low_bus_reset(slp); - cthw_chip_reset(bst, bsh, ct->sc_chipclk, slp->sl_hostid); - splx(s); + cthw_chip_reset(chp, NULL, ct->sc_chipclk, slp->sl_hostid); SOFT_INTR_REQUIRED(slp); return 0; @@ -398,25 +515,29 @@ ct_start_selection(ct, cb) struct slccb *cb; { struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - struct targ_info *ti = slp->sl_nexus; - struct lun_info *li = ti->ti_li; - int s; + struct ct_bus_access_handle *chp = &ct->sc_ch; + + struct targ_info *ti = slp->sl_Tnexus; + struct lun_info *li = slp->sl_Lnexus; + int s, satok; u_int8_t cmd; + ct->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; ct->sc_atten = 0; - if (cthw_cmdlevel[slp->sl_scp.scp_cmd[0]] != 0) + satok = 0; + + if (scsi_low_is_disconnect_ok(cb) != 0) + { + if (ct->sc_chiprev >= CT_WD33C93_A) + satok = 1; + else if (cthw_cmdlevel[slp->sl_scp.scp_cmd[0]] != 0) + satok = 1; + } + + if (satok != 0 && + scsi_low_is_msgout_continue(ti, SCSI_LOW_MSG_IDENTIFY) == 0) { - /* - * This completely violates scsi protocols, - * however some old devices do not work - * properly with scsi attentions. - */ - if ((li->li_flags & SCSI_LOW_DISC) != 0) - cmd = WD3S_SELECT_ATN_TFR; - else - cmd = WD3S_SELECT_NO_ATN_TFR; + cmd = WD3S_SELECT_ATN_TFR; ct->sc_satgo = CT_SAT_GOING; } else @@ -425,24 +546,33 @@ ct_start_selection(ct, cb) ct->sc_satgo = 0; } - if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 0) + if ((ct_stat_read_1(chp) & (STR_BSY | STR_INT | STR_CIP)) != 0) return SCSI_LOW_START_FAIL; - scsi_low_cmd(slp, ti); - if ((ct->sc_satgo & CT_SAT_GOING) != 0) - ct_write_cmds(bst, bsh, - slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen); + { + (void) scsi_low_msgout(slp, ti, SCSI_LOW_MSGOUT_INIT); + scsi_low_cmd(slp, ti); + ct_cr_write_1(chp, wd3s_oid, slp->sl_scp.scp_cmdlen); + ct_write_cmds(chp, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen); + } + else + { + /* anyway attention assert */ + SCSI_LOW_ASSERT_ATN(slp); + } + + ct_target_nexus_establish(ct, li->li_lun, slp->sl_scp.scp_direction); s = splhigh(); - if ((ct_stat_read_1(bst, bsh) & STR_BUSY) == 0) + if ((ct_stat_read_1(chp) & (STR_BSY | STR_INT | STR_CIP)) == 0) { /* XXX: * Reload a lun again here. */ - ct_cr_write_1(bst, bsh, wd3s_lun, li->li_lun); - ct_cr_write_1(bst, bsh, wd3s_cmd, cmd); - if ((ct_stat_read_1(bst, bsh) & STR_LCI) == 0) + ct_cr_write_1(chp, wd3s_lun, li->li_lun); + ct_cr_write_1(chp, wd3s_cmd, cmd); + if ((ct_stat_read_1(chp) & STR_LCI) == 0) { splx(s); SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART); @@ -459,12 +589,23 @@ ct_msg(ct, ti, msg) struct targ_info *ti; u_int msg; { - struct lun_info *li = ti->ti_li; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct ct_targ_info *cti = (void *) ti; struct ct_synch_data *csp = ct->sc_sdp; u_int offset, period; + int error; + + if ((msg & SCSI_LOW_MSG_WIDE) != 0) + { + if (ti->ti_width != SCSI_LOW_BUS_WIDTH_8) + { + ti->ti_width = SCSI_LOW_BUS_WIDTH_8; + return EINVAL; + } + return 0; + } - if (msg != SCSI_LOW_MSG_SYNCH) + if ((msg & SCSI_LOW_MSG_SYNCH) == 0) return 0; offset = ti->ti_maxsynch.offset; @@ -480,95 +621,117 @@ ct_msg(ct, ti, msg) ti->ti_maxsynch.period = 0; ti->ti_maxsynch.offset = 0; cti->cti_syncreg = 0; - return EINVAL; + error = EINVAL; + } + else + { + cti->cti_syncreg = ((offset & 0x0f) | csp->cs_syncr); + error = 0; } - cti->cti_syncreg = ((offset & 0x0f) | csp->cs_syncr); if (ct->ct_synch_setup != 0) - (*ct->ct_synch_setup) (ct, li); - return 0; + (*ct->ct_synch_setup) (ct, ti); + ct_cr_write_1(chp, wd3s_synch, cti->cti_syncreg); + return error; } /************************************************* * <DATA PHASE> *************************************************/ static int -ct_xfer(ct, data, len, direction) +ct_xfer(ct, data, len, direction, statp) struct ct_softc *ct; u_int8_t *data; int len, direction; + u_int *statp; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; int wc; register u_int8_t aux; + *statp = 0; if (len == 1) { - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_SBT | WD3S_TFR_INFO); + ct_cr_write_1(chp, wd3s_cmd, WD3S_SBT | WD3S_TFR_INFO); } else { - cthw_set_count(bst, bsh, len); - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_TFR_INFO); + cthw_set_count(chp, len); + ct_cr_write_1(chp, wd3s_cmd, WD3S_TFR_INFO); } - aux = ct_stat_read_1(bst, bsh); + aux = ct_stat_read_1(chp); if ((aux & STR_LCI) != 0) { - cthw_set_count(bst, bsh, 0); + cthw_set_count(chp, 0); return len; } - for (wc = ct->sc_wc ; wc > 0; wc --) + for (wc = 0; wc < ct->sc_tmaxcnt; wc ++) { /* check data ready */ if ((aux & (STR_BSY | STR_DBR)) == (STR_BSY | STR_DBR)) { if (direction == SCSI_LOW_READ) - *data = ct_cr_read_1(bst, bsh, wd3s_data); + { + *data = ct_cr_read_1(chp, wd3s_data); + if ((aux & STR_PE) != 0) + *statp |= SCSI_LOW_DATA_PE; + } else - ct_cr_write_1(bst, bsh, wd3s_data, *data); + { + ct_cr_write_1(chp, wd3s_data, *data); + } len --; if (len <= 0) break; data ++; } + else + { + SCSI_LOW_DELAY(1); + } /* check phase miss */ - aux = ct_stat_read_1(bst, bsh); + aux = ct_stat_read_1(chp); if ((aux & STR_INT) != 0) break; } return len; } +#define CT_PADDING_BUF_SIZE 32 + static void ct_io_xfer(ct) struct ct_softc *ct; { struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct sc_p *sp = &slp->sl_scp; - u_int dummy; + u_int stat; int len; + u_int8_t pbuf[CT_PADDING_BUF_SIZE]; - /* io polling mode */ - ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg); + /* polling mode */ + ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg); if (sp->scp_datalen <= 0) { slp->sl_error |= PDMAERR; - dummy = 0; - len = ct_xfer(ct, (u_int8_t *) &dummy, 1, sp->scp_direction); + + if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) + SCSI_LOW_BZERO(pbuf, CT_PADDING_BUF_SIZE); + ct_xfer(ct, pbuf, CT_PADDING_BUF_SIZE, + sp->scp_direction, &stat); } else + { len = ct_xfer(ct, sp->scp_data, sp->scp_datalen, - sp->scp_direction); - - sp->scp_data += (sp->scp_datalen - len); - sp->scp_datalen = len; + sp->scp_direction, &stat); + sp->scp_data += (sp->scp_datalen - len); + sp->scp_datalen = len; + } } /************************************************** @@ -598,7 +761,7 @@ ct_phase_error(ct, scsi_status) u_int8_t scsi_status; { struct scsi_low_softc *slp = &ct->sc_sclow; - struct targ_info *ti = slp->sl_nexus; + struct targ_info *ti = slp->sl_Tnexus; struct ct_err *pep; u_int msg = 0; @@ -618,13 +781,13 @@ ct_phase_error(ct, scsi_status) msg = pep->pe_errmsg; if (msg != 0) - scsi_low_assert_msg(slp, slp->sl_nexus, msg, 1); + scsi_low_assert_msg(slp, slp->sl_Tnexus, msg, 1); if (pep->pe_msg != NULL) { printf("%s: phase error: %s", slp->sl_xname, pep->pe_msg); - scsi_low_print(slp, slp->sl_nexus); + scsi_low_print(slp, slp->sl_Tnexus); } if (pep->pe_done != 0) @@ -640,90 +803,193 @@ ct_phase_error(ct, scsi_status) /************************************************** * ### SCSI PHASE SEQUENCER ### **************************************************/ -static __inline int -ct_reselected(ct) +static int +ct_reselected(ct, scsi_status) struct ct_softc *ct; + u_int8_t scsi_status; { struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct targ_info *ti; u_int sid; + u_int8_t regv; ct->sc_atten = 0; - sid = (ct_cr_read_1(bst, bsh, wd3s_sid) & SIDR_IDM); + ct->sc_satgo &= ~CT_SAT_GOING; + regv = ct_cr_read_1(chp, wd3s_sid); + if ((regv & SIDR_VALID) == 0) + return EJUSTRETURN; + + sid = regv & SIDR_IDM; if ((ti = scsi_low_reselected(slp, sid)) == NULL) return EJUSTRETURN; - ct_cr_write_1(bst, bsh, wd3s_did, sid); - ct_cr_write_1(bst, bsh, wd3s_lun, 0); /* temp */ - ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA); - cthw_set_count(bst, bsh, 0); + ct_target_nexus_establish(ct, 0, SCSI_LOW_READ); + if (scsi_status != BSR_AFM_RESEL) + return EJUSTRETURN; + + SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); + regv = ct_cr_read_1(chp, wd3s_data); + if (scsi_low_msgin(slp, ti, (u_int) regv) == 0) + { + if (scsi_low_is_msgout_continue(ti, 0) != 0) + { + /* XXX: scsi_low_attetion */ + scsi_low_attention(slp); + } + } + + if (ct->sc_atten != 0) + { + ct_attention(ct); + } + + ct_cr_write_1(chp, wd3s_cmd, WD3S_NEGATE_ACK); return EJUSTRETURN; } static int -ct_nexus(ct, ti) +ct_target_nexus_establish(ct, lun, dir) struct ct_softc *ct; - struct targ_info *ti; + int lun, dir; { - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; - struct lun_info *li = ti->ti_li; + struct scsi_low_softc *slp = &ct->sc_sclow; + struct ct_bus_access_handle *chp = &ct->sc_ch; + struct targ_info *ti = slp->sl_Tnexus; struct ct_targ_info *cti = (void *) ti; - if ((li->li_flags & SCSI_LOW_NOPARITY) != 0) - ct->sc_creg = CR_DEFAULT; + if (dir == SCSI_LOW_WRITE) + ct_cr_write_1(chp, wd3s_did, ti->ti_id); else - ct->sc_creg = CR_DEFAULT_HP; + ct_cr_write_1(chp, wd3s_did, ti->ti_id | DIDR_DPD); + ct_cr_write_1(chp, wd3s_lun, lun); + ct_cr_write_1(chp, wd3s_ctrl, ct->sc_creg | CR_DMA); + ct_cr_write_1(chp, wd3s_cph, 0); + ct_cr_write_1(chp, wd3s_synch, cti->cti_syncreg); + cthw_set_count(chp, 0); + return 0; +} + +static int +ct_lun_nexus_establish(ct) + struct ct_softc *ct; +{ + struct scsi_low_softc *slp = &ct->sc_sclow; + struct ct_bus_access_handle *chp = &ct->sc_ch; + struct lun_info *li = slp->sl_Lnexus; + + ct_cr_write_1(chp, wd3s_lun, li->li_lun); + return 0; +} + +static int +ct_ccb_nexus_establish(ct) + struct ct_softc *ct; +{ + struct scsi_low_softc *slp = &ct->sc_sclow; + struct ct_bus_access_handle *chp = &ct->sc_ch; + struct lun_info *li = slp->sl_Lnexus; + struct targ_info *ti = slp->sl_Tnexus; + struct ct_targ_info *cti = (void *) ti; + struct slccb *cb = slp->sl_Qnexus; - ct_cr_write_1(bst, bsh, wd3s_did, ti->ti_id); - ct_cr_write_1(bst, bsh, wd3s_lun, li->li_lun); - ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA); - ct_cr_write_1(bst, bsh, wd3s_cph, 0); - ct_cr_write_1(bst, bsh, wd3s_synch, cti->cti_syncreg); - cthw_set_count(bst, bsh, 0); - ct_cr_write_1(bst, bsh, wd3s_lun, li->li_lun); /* XXX */ + ct->sc_tmaxcnt = cb->ccb_tcmax * 1000 * 1000; + + if ((ct->sc_satgo & CT_SAT_GOING) != 0) + { + ct_cr_write_1(chp, wd3s_oid, slp->sl_scp.scp_cmdlen); + ct_write_cmds(chp, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen); + } + if (slp->sl_scp.scp_direction == SCSI_LOW_WRITE) + ct_cr_write_1(chp, wd3s_did, ti->ti_id); + else + ct_cr_write_1(chp, wd3s_did, ti->ti_id | DIDR_DPD); + ct_cr_write_1(chp, wd3s_lun, li->li_lun); + ct_cr_write_1(chp, wd3s_synch, cti->cti_syncreg); return 0; } +static int +ct_unbusy(ct) + struct ct_softc *ct; +{ + struct scsi_low_softc *slp = &ct->sc_sclow; + struct ct_bus_access_handle *chp = &ct->sc_ch; + int wc; + register u_int8_t regv; + + for (wc = 0; wc < CT_DELAY_MAX / CT_DELAY_INTERVAL; wc ++) + { + regv = ct_stat_read_1(chp); + if ((regv & (STR_BSY | STR_CIP)) == 0) + return 0; + if (regv == (u_int8_t) -1) + return EIO; + + SCSI_LOW_DELAY(CT_DELAY_INTERVAL); + } + + printf("%s: unbusy timeout\n", slp->sl_xname); + return EBUSY; +} + +static int +ct_catch_intr(ct) + struct ct_softc *ct; +{ + struct ct_bus_access_handle *chp = &ct->sc_ch; + int wc; + register u_int8_t regv; + + for (wc = 0; wc < CT_DELAY_MAX / CT_DELAY_INTERVAL; wc ++) + { + regv = ct_stat_read_1(chp); + if ((regv & (STR_INT | STR_BSY | STR_CIP)) == STR_INT) + return 0; + + SCSI_LOW_DELAY(CT_DELAY_INTERVAL); + } + return EJUSTRETURN; +} + int ctintr(arg) void *arg; { struct ct_softc *ct = arg; struct scsi_low_softc *slp = &ct->sc_sclow; - bus_space_tag_t bst = ct->sc_iot; - bus_space_handle_t bsh = ct->sc_ioh; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct targ_info *ti; struct physio_proc *pp; struct buf *bp; - int len, satgo; + u_int derror, flags; + int len, satgo, error; u_int8_t scsi_status, regv; +again: if (slp->sl_flags & HW_INACTIVE) return 0; /************************************************** * Get status & bus phase **************************************************/ - if ((ct_stat_read_1(bst, bsh) & STR_INT) == 0) + if ((ct_stat_read_1(chp) & STR_INT) == 0) return 0; - scsi_status = ct_cr_read_1(bst, bsh, wd3s_stat); + scsi_status = ct_cr_read_1(chp, wd3s_stat); if (scsi_status == ((u_int8_t) -1)) return 1; /************************************************** * Check reselection, or nexus **************************************************/ - if (scsi_status == BSR_RESEL) + if (scsi_status == BSR_RESEL || scsi_status == BSR_AFM_RESEL) { - if (ct_reselected(ct) == EJUSTRETURN) + if (ct_reselected(ct, scsi_status) == EJUSTRETURN) return 1; } - if ((ti = slp->sl_nexus) == NULL) + if ((ti = slp->sl_Tnexus) == NULL) return 1; /************************************************** @@ -735,8 +1001,10 @@ ctintr(arg) scsi_low_print(slp, NULL); printf("%s: scsi_status 0x%x\n\n", slp->sl_xname, (u_int) scsi_status); +#ifdef DDB if (ct_debug > 1) - Debugger(); + SCSI_LOW_DEBUGGER("ct"); +#endif /* DDB */ } #endif /* CT_DEBUG */ @@ -744,7 +1012,7 @@ ctintr(arg) * Internal scsi phase **************************************************/ satgo = ct->sc_satgo; - ct->sc_satgo = 0; + ct->sc_satgo &= ~CT_SAT_GOING; switch (ti->ti_phase) { @@ -756,15 +1024,14 @@ ctintr(arg) ct_phase_error(ct, scsi_status); return 1; } - scsi_low_arbit_win(slp, ti); + scsi_low_arbit_win(slp); SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); - scsi_low_assert_msg(slp, ti, SCSI_LOW_MSG_IDENTIFY, 0); return 1; } else { - scsi_low_arbit_win(slp, ti); - SCSI_LOW_SETUP_PHASE(ti, PH_SELECTED); + scsi_low_arbit_win(slp); + SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); /* XXX */ } break; @@ -787,11 +1054,15 @@ ctintr(arg) (*ct->ct_dma_xfer_stop) (ct); ct->sc_dma &= ~CT_DMA_DMASTART; } - else + else if (ct->sc_dma & CT_DMA_PIOSTART) { (*ct->ct_pio_xfer_stop) (ct); ct->sc_dma &= ~CT_DMA_PIOSTART; } + else + { + scsi_low_data_finish(slp); + } } break; } @@ -815,48 +1086,78 @@ ctintr(arg) case BSR_DATAOUT: SCSI_LOW_SETUP_PHASE(ti, PH_DATA); if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0) - return 1; + { + ct_attention(ct); + } goto common_data_phase; case BSR_DATAIN: SCSI_LOW_SETUP_PHASE(ti, PH_DATA); if (scsi_low_data(slp, ti, &bp, SCSI_LOW_READ) != 0) - return 1; - -common_data_phase: - if (slp->sl_scp.scp_datalen <= 0) { - ct_io_xfer(ct); - return 1; + ct_attention(ct); } - slp->sl_flags |= HW_PDMASTART; - if ((ct->sc_xmode & CT_XMODE_PIO) != 0 && - (slp->sl_scp.scp_datalen % DEV_BSIZE) == 0) +common_data_phase: + if (slp->sl_scp.scp_datalen > 0) { - pp = physio_proc_enter(bp); - ct->sc_dma |= CT_DMA_PIOSTART; - (*ct->ct_pio_xfer_start) (ct); - physio_proc_leave(pp); - return 1; + slp->sl_flags |= HW_PDMASTART; + if ((ct->sc_xmode & CT_XMODE_PIO) != 0) + { + pp = physio_proc_enter(bp); + error = (*ct->ct_pio_xfer_start) (ct); + physio_proc_leave(pp); + if (error == 0) + { + ct->sc_dma |= CT_DMA_PIOSTART; + return 1; + } + } + + if ((ct->sc_xmode & CT_XMODE_DMA) != 0) + { + error = (*ct->ct_dma_xfer_start) (ct); + if (error == 0) + { + ct->sc_dma |= CT_DMA_DMASTART; + return 1; + } + } } else - { - ct->sc_dma |= CT_DMA_DMASTART; - (*ct->ct_dma_xfer_start) (ct); - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_TFR_INFO); + { + if (slp->sl_scp.scp_direction == SCSI_LOW_READ) + { + if (!(slp->sl_flags & HW_READ_PADDING)) + { + printf("%s: read padding required\n", slp->sl_xname); + return 1; + } + } + else + { + if (!(slp->sl_flags & HW_WRITE_PADDING)) + { + printf("%s: write padding required\n", slp->sl_xname); + return 1; + } + } + slp->sl_flags |= HW_PDMASTART; } + + ct_io_xfer(ct); return 1; case BSR_CMDOUT: SCSI_LOW_SETUP_PHASE(ti, PH_CMD); if (scsi_low_cmd(slp, ti) != 0) - break; + { + ct_attention(ct); + } - if (ct_xfer(ct, - slp->sl_scp.scp_cmd, + if (ct_xfer(ct, slp->sl_scp.scp_cmd, slp->sl_scp.scp_cmdlen, - SCSI_LOW_WRITE) != 0) + SCSI_LOW_WRITE, &derror) != 0) { printf("%s: scsi cmd xfer short\n", slp->sl_xname); @@ -865,20 +1166,28 @@ common_data_phase: case BSR_STATIN: SCSI_LOW_SETUP_PHASE(ti, PH_STAT); -#ifdef CT_USE_CCSEQ - if (scsi_low_is_msgout_continue(ti) != 0 || - ct->sc_atten != 0) + if ((ct_io_control & CT_USE_CCSEQ) != 0) { - ct_xfer(ct, &ti->ti_status, 1, SCSI_LOW_READ); + if (scsi_low_is_msgout_continue(ti, 0) != 0 || + ct->sc_atten != 0) + { + ct_xfer(ct, ®v, 1, SCSI_LOW_READ, + &derror); + scsi_low_statusin(slp, ti, + regv | derror); + } + else + { + ct->sc_satgo |= CT_SAT_GOING; + cthw_set_count(chp, 0); + cthw_phase_bypass(ct, 0x41); + } } else { - cthw_set_count(bst, bsh, 0); - cthw_phase_bypass(ct, 0x41); + ct_xfer(ct, ®v, 1, SCSI_LOW_READ, &derror); + scsi_low_statusin(slp, ti, regv | derror); } -#else /* !CT_USE_CCSEQ */ - ct_xfer(ct, &ti->ti_status, 1, SCSI_LOW_READ); -#endif /* !CT_USE_CCSEQ */ return 1; case BSR_UNSPINFO0: @@ -890,20 +1199,44 @@ common_data_phase: case BSR_MSGOUT: SCSI_LOW_SETUP_PHASE(ti, PH_MSGOUT); - len = scsi_low_msgout(slp, ti); - if (ct_xfer(ct, ti->ti_msgoutstr, len, SCSI_LOW_WRITE)) + flags = SCSI_LOW_MSGOUT_UNIFY; + if (ti->ti_ophase != ti->ti_phase) + flags |= SCSI_LOW_MSGOUT_INIT; + len = scsi_low_msgout(slp, ti, flags); + + if (len > 1 && slp->sl_atten == 0) + { + ct_attention(ct); + } + + if (ct_xfer(ct, ti->ti_msgoutstr, len, + SCSI_LOW_WRITE, &derror) != 0) { printf("%s: scsi msgout xfer short\n", slp->sl_xname); - scsi_low_assert_msg(slp, ti, - SCSI_LOW_MSG_ABORT, 1); } + SCSI_LOW_DEASSERT_ATN(slp); + ct->sc_atten = 0; return 1; case BSR_MSGIN:/* msg in */ SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); - ct_xfer(ct, ®v, 1, SCSI_LOW_READ); - scsi_low_msgin(slp, ti, regv); + + ct_xfer(ct, ®v, 1, SCSI_LOW_READ, &derror); + if (scsi_low_msgin(slp, ti, regv | derror) == 0) + { + if (scsi_low_is_msgout_continue(ti, 0) != 0) + { + /* XXX: scsi_low_attetion */ + scsi_low_attention(slp); + } + } + + if ((ct_io_control & CT_FAST_INTR) != 0) + { + if (ct_catch_intr(ct) == 0) + goto again; + } return 1; } } @@ -916,6 +1249,7 @@ common_data_phase: { case BSR_SATSDP: /* SAT with save data pointer */ SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); + ct->sc_satgo |= CT_SAT_GOING; scsi_low_msgin(slp, ti, MSG_SAVESP); cthw_phase_bypass(ct, 0x41); return 1; @@ -924,17 +1258,30 @@ common_data_phase: /* * emulate statusin => msgin */ - ti->ti_status = ct_cr_read_1(bst, bsh, wd3s_lun); + SCSI_LOW_SETUP_PHASE(ti, PH_STAT); + scsi_low_statusin(slp, ti, ct_cr_read_1(chp, wd3s_lun)); + SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); - SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC); + scsi_low_msgin(slp, ti, MSG_COMP); + scsi_low_disconnected(slp, ti); return 1; case BSR_ACKREQ: /* negate ACK */ if (ct->sc_atten != 0) - cthw_attention(ct); + { + ct_attention(ct); + } - ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_NEGATE_ACK); + ct_cr_write_1(chp, wd3s_cmd, WD3S_NEGATE_ACK); + if ((ct_io_control & CT_FAST_INTR) != 0) + { + /* XXX: + * Should clear a pending interrupt and + * sync with a next interrupt! + */ + ct_catch_intr(ct); + } return 1; case BSR_DISC: /* disconnect */ @@ -945,7 +1292,7 @@ common_data_phase: * emulate disconnect msg */ SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN); - SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC); + scsi_low_msgin(slp, ti, MSG_DISCON); } scsi_low_disconnected(slp, ti); return 1; diff --git a/sys/dev/ct/ct_isa.c b/sys/dev/ct/ct_isa.c index 5ca8006..ec38efe 100644 --- a/sys/dev/ct/ct_isa.c +++ b/sys/dev/ct/ct_isa.c @@ -75,6 +75,7 @@ #include <machine/resource.h> #include <sys/bus.h> #include <sys/rman.h> +#include <machine/md_var.h> #include <pc98/pc98/pc98.h> #include <isa/isavar.h> @@ -100,6 +101,9 @@ static int ct_space_map(device_t, struct bshw *, static void ct_space_unmap(device_t, struct ct_softc *); static struct bshw *ct_find_hw(device_t); static void ct_dmamap(void *, bus_dma_segment_t *, int, int); +static void ct_isa_bus_access_weight __P((struct ct_bus_access_handle *)); +static void ct_isa_dmasync_before __P((struct ct_softc *)); +static void ct_isa_dmasync_after __P((struct ct_softc *)); struct ct_isa_softc { struct ct_softc sc_ct; @@ -132,6 +136,7 @@ ct_isa_match(device_t dev) { struct bshw *hw; struct resource *port_res, *mem_res; + struct ct_bus_access_handle ch; int rv; if (ISA_PNP_PROBE(device_get_parent(dev), dev, ct_pnp_ids) == ENXIO) @@ -146,17 +151,20 @@ ct_isa_match(device_t dev) if (ct_space_map(dev, hw, &port_res, &mem_res) != 0) return ENXIO; - rv = ctprobesubr(rman_get_bustag(port_res), - rman_get_bushandle(port_res), - 0, BSHW_DEFAULT_HOSTID, BSHW_DEFAULT_CHIPCLK); + bzero(&ch, sizeof(ch)); + ch.ch_iot = rman_get_bustag(port_res); + ch.ch_ioh = rman_get_bushandle(port_res), + ch.ch_bus_weight = ct_isa_bus_access_weight; + + rv = ctprobesubr(&ch, 0, BSHW_DEFAULT_HOSTID, + BSHW_DEFAULT_CHIPCLK, NULL); if (rv != 0) { struct bshw_softc bshw_tab; struct bshw_softc *bs = &bshw_tab; memset(bs, 0, sizeof(*bs)); - bshw_read_settings(rman_get_bustag(port_res), - rman_get_bushandle(port_res), bs); + bshw_read_settings(&ch, bs); bus_set_resource(dev, SYS_RES_IRQ, 0, bs->sc_irq, 1); bus_set_resource(dev, SYS_RES_DRQ, 0, bs->sc_drq, 1); } @@ -175,12 +183,14 @@ ct_isa_attach(device_t dev) { struct ct_isa_softc *pct = device_get_softc(dev); struct ct_softc *ct = &pct->sc_ct; + struct ct_bus_access_handle *chp = &ct->sc_ch; struct scsi_low_softc *slp = &ct->sc_sclow; struct bshw_softc *bs = &pct->sc_bshw; struct bshw *hw; - int irq_rid, drq_rid; + int irq_rid, drq_rid, chiprev; u_int8_t *vaddr; bus_addr_t addr; + intrmask_t s; hw = ct_find_hw(dev); if (ct_space_map(dev, hw, &ct->port_res, &ct->mem_res) != 0) { @@ -188,12 +198,14 @@ ct_isa_attach(device_t dev) return ENXIO; } - ct->sc_iot = rman_get_bustag(ct->port_res); - ct->sc_ioh = rman_get_bushandle(ct->port_res); + bzero(chp, sizeof(*chp)); + chp->ch_iot = rman_get_bustag(ct->port_res); + chp->ch_ioh = rman_get_bushandle(ct->port_res); if (ct->mem_res) { - ct->sc_memt = rman_get_bustag(ct->mem_res); - ct->sc_memh = rman_get_bushandle(ct->mem_res); + chp->ch_memt = rman_get_bustag(ct->mem_res); + chp->ch_memh = rman_get_bushandle(ct->mem_res); } + chp->ch_bus_weight = ct_isa_bus_access_weight; irq_rid = 0; ct->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0, ~0, @@ -206,6 +218,14 @@ ct_isa_attach(device_t dev) return ENXIO; } + if (ctprobesubr(chp, 0, BSHW_DEFAULT_HOSTID, + BSHW_DEFAULT_CHIPCLK, &chiprev) == 0) + { + device_printf(dev, "hardware missing\n"); + ct_space_unmap(dev, ct); + return ENXIO; + } + /* setup DMA map */ if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_24BIT, BUS_SPACE_MAXADDR, @@ -229,11 +249,14 @@ ct_isa_attach(device_t dev) /* setup machdep softc */ bs->sc_hw = hw; + bs->sc_io_control = 0; bs->sc_bounce_phys = (u_int8_t *)addr; bs->sc_bounce_addr = vaddr; bs->sc_bounce_size = MAXBSIZE; bs->sc_minphys = (1 << 24); - bshw_read_settings(ct->sc_iot, ct->sc_ioh, bs); + bs->sc_dmasync_before = ct_isa_dmasync_before; + bs->sc_dmasync_after = ct_isa_dmasync_after; + bshw_read_settings(chp, bs); /* setup ct driver softc */ ct->ct_hw = bs; @@ -245,17 +268,54 @@ ct_isa_attach(device_t dev) ct->ct_synch_setup = bshw_synch_setup; ct->sc_xmode = CT_XMODE_DMA; - if (ct->sc_memh != NULL) + if (chp->ch_memh != NULL) ct->sc_xmode |= CT_XMODE_PIO; - ct->sc_chiprev = CT_WD33C93_B; - ct->sc_chipclk = BSHW_DEFAULT_CHIPCLK; + + ct->sc_chiprev = chiprev; + switch (chiprev) + { + case CT_WD33C93: + /* s = "WD33C93"; */ + ct->sc_chipclk = 8; + break; + case CT_WD33C93_A: + if (DVCFG_MAJOR(device_get_flags(dev)) > 0) + { + /* s = "AM33C93_A"; */ + ct->sc_chipclk = 20; + ct->sc_chiprev = CT_AM33C93_A; + } + else + { + /* s = "WD33C93_A"; */ + ct->sc_chipclk = 10; + } + break; + + case CT_AM33C93_A: + /* s = "AM33C93_A"; */ + ct->sc_chipclk = 20; + break; + + default: + case CT_WD33C93_B: + /* s = "WD33C93_B"; */ + ct->sc_chipclk = 20; + break; + } +#if 0 + printf("%s: chiprev %s chipclk %d Mhz\n", + slp->sl_dev.dv_xname, s, ct->sc_chipclk); +#endif slp->sl_dev = dev; slp->sl_hostid = bs->sc_hostid; slp->sl_irq = isa_get_irq(dev); slp->sl_cfgflags = device_get_flags(dev); + s = splcam(); ctattachsubr(ct); + splx(s); if (bus_setup_intr(dev, ct->irq_res, INTR_TYPE_CAM, (driver_intr_t *)ctintr, ct, &ct->sc_ih)) { @@ -320,3 +380,29 @@ ct_dmamap(void *arg, bus_dma_segment_t *seg, int nseg, int error) *addr = seg->ds_addr; } + +static void +ct_isa_bus_access_weight(chp) + struct ct_bus_access_handle *chp; +{ + + outb(0x5f, 0); +} + +static void +ct_isa_dmasync_before(ct) + struct ct_softc *ct; +{ + + if (need_pre_dma_flush) + wbinvd(); +} + +static void +ct_isa_dmasync_after(ct) + struct ct_softc *ct; +{ + + if (need_post_dma_flush) + invd(); +} diff --git a/sys/dev/ct/ct_machdep.h b/sys/dev/ct/ct_machdep.h index 195af5b..be10331 100644 --- a/sys/dev/ct/ct_machdep.h +++ b/sys/dev/ct/ct_machdep.h @@ -1,12 +1,12 @@ /* $FreeBSD$ */ -/* $NecBSD: ct_machdep.h,v 1.4 1999/07/23 20:54:00 honda Exp $ */ +/* $NecBSD: ct_machdep.h,v 1.4.12.2 2001/06/20 06:13:34 honda Exp $ */ /* $NetBSD$ */ /* * [NetBSD for NEC PC-98 series] - * Copyright (c) 1995, 1996, 1997, 1998 + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. - * Copyright (c) 1995, 1996, 1997, 1998 + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +36,8 @@ #ifndef _CT_MACHDEP_H_ #define _CT_MACHDEP_H_ +#include "opt_ct.h" + /* * Principal rules: * 1) do not use bus_space_write/read_X directly in ct.c. @@ -43,101 +45,167 @@ */ /* special weight if requried */ -#define CT_BUS_WEIGHT +#ifdef CT_BUS_WEIGHT +#undef CT_BUS_WEIGHT +#define CT_BUS_WEIGHT(chp) \ +{ \ + if ((chp)->ch_bus_weight != NULL) \ + (chp)->ch_bus_weight((chp)); \ +} +#else /* !CT_BUS_WEIGHT */ +#define CT_BUS_WEIGHT(chp) +#endif /* !CT_BUS_WEIGHT */ /* port offset */ +#ifndef CT_USE_RELOCATE_OFFSET #define addr_port 0 #define stat_port 0 #define ctrl_port 2 #define cmd_port 4 +#else /* CT_USE_RELOCATE_OFFSET */ +#define addr_port ((chp)->ch_offset[0]) +#define stat_port ((chp)->ch_offset[1]) +#define ctrl_port ((chp)->ch_offset[2]) +#define cmd_port ((chp)->ch_offset[3]) +#endif /* CT_USE_RELOCATE_OFFSET */ /* * All port accesses primitive methods */ -static __inline u_int8_t ct_cr_read_1 __P((bus_space_tag_t, bus_space_handle_t, bus_addr_t)); -static __inline void ct_cr_write_1 __P((bus_space_tag_t, bus_space_handle_t, bus_addr_t, u_int8_t)); -static __inline void ct_write_cmds __P((bus_space_tag_t, bus_space_handle_t, u_int8_t *, int)); -static __inline u_int cthw_get_count __P((bus_space_tag_t, bus_space_handle_t)); -static __inline void cthw_set_count __P((bus_space_tag_t, bus_space_handle_t, u_int)); +static __inline u_int8_t ct_stat_read_1 + __P((struct ct_bus_access_handle *)); +static __inline u_int8_t ct_cmdp_read_1 + __P((struct ct_bus_access_handle *)); +static __inline void ct_cmdp_write_1 + __P((struct ct_bus_access_handle *, u_int8_t)); +static __inline u_int8_t ct_cr_read_1 + __P((struct ct_bus_access_handle *, bus_addr_t)); +static __inline void ct_cr_write_1 + __P((struct ct_bus_access_handle *, bus_addr_t, u_int8_t)); +static __inline void ct_write_cmds + __P((struct ct_bus_access_handle *, u_int8_t *, int)); +static __inline u_int cthw_get_count + __P((struct ct_bus_access_handle *)); +static __inline void cthw_set_count + __P((struct ct_bus_access_handle *, u_int)); + +static __inline u_int8_t +ct_stat_read_1(chp) + struct ct_bus_access_handle *chp; +{ + u_int8_t regv; -#define ct_stat_read_1(bst, bsh) bus_space_read_1((bst), (bsh), stat_port) + regv = bus_space_read_1(chp->ch_iot, chp->ch_ioh, stat_port); + CT_BUS_WEIGHT(chp) + return regv; +} static __inline void -cthw_set_count(bst, bsh, count) - bus_space_tag_t bst; - bus_space_handle_t bsh; +cthw_set_count(chp, count) + struct ct_bus_access_handle *chp; u_int count; { + bus_space_tag_t bst = chp->ch_iot; + bus_space_handle_t bsh = chp->ch_ioh; bus_space_write_1(bst, bsh, addr_port, wd3s_cnt); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) bus_space_write_1(bst, bsh, ctrl_port, count >> 16); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) bus_space_write_1(bst, bsh, ctrl_port, count >> 8); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) bus_space_write_1(bst, bsh, ctrl_port, count); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) } static __inline u_int -cthw_get_count(bst, bsh) - bus_space_tag_t bst; - bus_space_handle_t bsh; +cthw_get_count(chp) + struct ct_bus_access_handle *chp; { + bus_space_tag_t bst = chp->ch_iot; + bus_space_handle_t bsh = chp->ch_ioh; u_int count; bus_space_write_1(bst, bsh, addr_port, wd3s_cnt); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) count = (((u_int) bus_space_read_1(bst, bsh, ctrl_port)) << 16); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) count += (((u_int) bus_space_read_1(bst, bsh, ctrl_port)) << 8); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) count += ((u_int) bus_space_read_1(bst, bsh, ctrl_port)); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) return count; } static __inline void -ct_write_cmds(bst, bsh, cmd, len) - bus_space_tag_t bst; - bus_space_handle_t bsh; +ct_write_cmds(chp, cmd, len) + struct ct_bus_access_handle *chp; u_int8_t *cmd; int len; { + bus_space_tag_t bst = chp->ch_iot; + bus_space_handle_t bsh = chp->ch_ioh; int i; bus_space_write_1(bst, bsh, addr_port, wd3s_cdb); + CT_BUS_WEIGHT(chp) for (i = 0; i < len; i ++) + { bus_space_write_1(bst, bsh, ctrl_port, cmd[i]); + CT_BUS_WEIGHT(chp) + } } static __inline u_int8_t -ct_cr_read_1(bst, bsh, offs) - bus_space_tag_t bst; - bus_space_handle_t bsh; +ct_cr_read_1(chp, offs) + struct ct_bus_access_handle *chp; bus_addr_t offs; { + bus_space_tag_t bst = chp->ch_iot; + bus_space_handle_t bsh = chp->ch_ioh; u_int8_t regv; bus_space_write_1(bst, bsh, addr_port, offs); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) regv = bus_space_read_1(bst, bsh, ctrl_port); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) return regv; } static __inline void -ct_cr_write_1(bst, bsh, offs, val) - bus_space_tag_t bst; - bus_space_handle_t bsh; +ct_cr_write_1(chp, offs, val) + struct ct_bus_access_handle *chp; bus_addr_t offs; u_int8_t val; { + bus_space_tag_t bst = chp->ch_iot; + bus_space_handle_t bsh = chp->ch_ioh; bus_space_write_1(bst, bsh, addr_port, offs); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) bus_space_write_1(bst, bsh, ctrl_port, val); - CT_BUS_WEIGHT + CT_BUS_WEIGHT(chp) +} + +static __inline u_int8_t +ct_cmdp_read_1(chp) + struct ct_bus_access_handle *chp; +{ + u_int8_t regv; + + regv = bus_space_read_1(chp->ch_iot, chp->ch_ioh, cmd_port); + CT_BUS_WEIGHT(chp) + return regv; +} + +static __inline void +ct_cmdp_write_1(chp, val) + struct ct_bus_access_handle *chp; + u_int8_t val; +{ + + bus_space_write_1(chp->ch_iot, chp->ch_ioh, cmd_port, val); + CT_BUS_WEIGHT(chp) } #if defined(i386) @@ -145,11 +213,4 @@ ct_cr_write_1(bst, bsh, offs, val) #else /* !i386 */ #define SOFT_INTR_REQUIRED(slp) #endif /* !i386 */ - -#ifdef __FreeBSD__ -typedef unsigned long vaddr_t; - -#define delay(t) DELAY(t) -#endif - #endif /* !_CT_MACHDEP_H_ */ diff --git a/sys/dev/ct/ctvar.h b/sys/dev/ct/ctvar.h index 5ad3db1..235990a 100644 --- a/sys/dev/ct/ctvar.h +++ b/sys/dev/ct/ctvar.h @@ -1,12 +1,12 @@ /* $FreeBSD$ */ -/* $NecBSD: ctvar.h,v 1.4 1999/04/15 01:36:13 kmatsuda Exp $ */ +/* $NecBSD: ctvar.h,v 1.4.14.3 2001/06/20 06:13:34 honda Exp $ */ /* $NetBSD$ */ /* * [NetBSD for NEC PC-98 series] - * Copyright (c) 1995, 1996, 1997, 1998 + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 * NetBSD/pc98 porting staff. All rights reserved. - * Copyright (c) 1995, 1996, 1997, 1998 + * Copyright (c) 1995, 1996, 1997, 1998, 1999, 2000, 2001 * Naofumi HONDA. All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -43,31 +43,53 @@ /***************************************************************** * Host adapter structure *****************************************************************/ +struct ct_bus_access_handle { + bus_space_tag_t ch_iot; /* core chip ctrl port tag */ + bus_space_tag_t ch_delayt; /* delay port tag */ + bus_space_tag_t ch_datat; /* data port tag (pio) */ + bus_space_tag_t ch_memt; /* data port tag (shm) */ + + bus_space_handle_t ch_ioh; + bus_space_handle_t ch_delaybah; + bus_space_handle_t ch_datah; + bus_space_handle_t ch_memh; + + void (*ch_bus_weight) __P((struct ct_bus_access_handle *)); + +#ifdef CT_USE_RELOCATE_OFFSET + bus_addr_t ch_offset[4]; +#endif /* CT_USE_RELOCATE_OFFSET */ +}; + struct ct_softc { struct scsi_low_softc sc_sclow; /* generic data */ + struct ct_bus_access_handle sc_ch; /* bus access handle */ + +#ifdef __NetBSD__ + bus_dma_tag_t sc_dmat; /* data DMA tag */ + + void *sc_ih; +#endif /* __NetBSD__ */ + +#ifdef __FreeBSD__ struct resource *port_res; struct resource *mem_res; struct resource *irq_res; struct resource *drq_res; - bus_space_tag_t sc_iot; /* core chip ctrl port tag */ - bus_space_tag_t sc_datat; /* data port tag (pio) */ - bus_space_tag_t sc_memt; /* data port tag (shm) */ bus_dma_tag_t sc_dmat; /* data DMA tag */ bus_dmamap_t sc_dmamapt; /* data DMAMAP tag */ - bus_space_handle_t sc_ioh; - bus_space_handle_t sc_datah; - bus_space_handle_t sc_memh; - void *sc_ih; - int sc_wc; /* weight counter */ +#endif /* __FreeBSD__ */ int sc_chiprev; /* chip version */ -#define CT_WD33C93_A 0x00000 -#define CT_WD33C93_B 0x10000 -#define CT_WD33C93_C 0x20000 +#define CT_WD33C93 0x00000 +#define CT_WD33C93_A 0x10000 +#define CT_AM33C93_A 0x10001 +#define CT_WD33C93_B 0x20000 +#define CT_WD33C93_C 0x30000 int sc_xmode; #define CT_XMODE_PIO 1 @@ -80,6 +102,7 @@ struct ct_softc { int sc_satgo; /* combination cmd start */ #define CT_SAT_GOING 1 + int sc_tmaxcnt; int sc_atten; /* attention */ u_int8_t sc_creg; /* control register value */ @@ -89,20 +112,22 @@ struct ct_softc { u_int cs_syncr; } *sc_sdp; /* synchronous data table pt */ + struct ct_synch_data sc_default_sdt[16]; + /* * Machdep stuff. */ void *ct_hw; /* point to bshw_softc etc ... */ - void (*ct_dma_xfer_start) __P((struct ct_softc *)); - void (*ct_pio_xfer_start) __P((struct ct_softc *)); + int (*ct_dma_xfer_start) __P((struct ct_softc *)); + int (*ct_pio_xfer_start) __P((struct ct_softc *)); void (*ct_dma_xfer_stop) __P((struct ct_softc *)); void (*ct_pio_xfer_stop) __P((struct ct_softc *)); void (*ct_bus_reset) __P((struct ct_softc *)); - void (*ct_synch_setup) __P((struct ct_softc *, struct lun_info *)); + void (*ct_synch_setup) __P((struct ct_softc *, struct targ_info *)); }; /***************************************************************** - * Target information + * Lun information *****************************************************************/ struct ct_targ_info { struct targ_info cti_ti; @@ -113,14 +138,7 @@ struct ct_targ_info { /***************************************************************** * PROTO *****************************************************************/ -#ifdef __NetBSD__ -#include <i386/Cbus/dev/ct/ct_machdep.h> -#endif -#ifdef __FreeBSD__ -#include <dev/ct/ct_machdep.h> -#endif - -int ctprobesubr __P((bus_space_tag_t, bus_space_handle_t ioh, u_int, int, u_int)); +int ctprobesubr __P((struct ct_bus_access_handle *, u_int, int, u_int, int *)); void ctattachsubr __P((struct ct_softc *)); int ctprint __P((void *, const char *)); int ctintr __P((void *)); |