Added another wd33c93 based SCSI card driver which replaces the bs driver.
Now, default is still bs. Submitted by: nyan and non. Obtained from: NetBSD/pc98
This commit is contained in:
parent
b564bac285
commit
9e90d5aab0
@ -27,9 +27,11 @@ cam/scsi/scsi_all.c optional scbus
|
||||
cam/scsi/scsi_cd.c optional cd
|
||||
cam/scsi/scsi_ch.c optional ch
|
||||
cam/scsi/scsi_da.c optional da
|
||||
cam/scsi/scsi_low.c optional ct
|
||||
cam/scsi/scsi_low.c optional ncv
|
||||
cam/scsi/scsi_low.c optional nsp
|
||||
cam/scsi/scsi_low.c optional stg
|
||||
cam/scsi/scsi_low_pisa.c optional ct
|
||||
cam/scsi/scsi_low_pisa.c optional ncv
|
||||
cam/scsi/scsi_low_pisa.c optional nsp
|
||||
cam/scsi/scsi_low_pisa.c optional stg
|
||||
|
@ -93,6 +93,9 @@ contrib/dev/oltr/trlldmac.c optional oltr
|
||||
#dev/advansys/adv_isa.c optional adv isa
|
||||
dev/aic/aic_cbus.c optional aic isa
|
||||
#dev/ar/if_ar_isa.c optional ar isa
|
||||
dev/ct/bshw_machdep.c optional ct
|
||||
dev/ct/ct.c optional ct
|
||||
dev/ct/ct_isa.c optional ct isa
|
||||
dev/ed/if_ed_cbus.c optional ed isa
|
||||
dev/eisa/eisaconf.c optional eisa
|
||||
dev/fb/fb.c optional fb
|
||||
|
767
sys/dev/ct/bshw_machdep.c
Normal file
767
sys/dev/ct/bshw_machdep.c
Normal file
@ -0,0 +1,767 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: bshw_machdep.c,v 1.8 1999/07/23 20:54:00 honda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999
|
||||
* Naofumi HONDA. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/bio.h>
|
||||
#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 <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
#include <dev/scsipi/scsi_disk.h>
|
||||
|
||||
#include <machine/dvcfg.h>
|
||||
#include <machine/physio_proc.h>
|
||||
|
||||
#include <i386/Cbus/dev/scsi_low.h>
|
||||
|
||||
#include <dev/ic/wd33c93reg.h>
|
||||
#include <i386/Cbus/dev/ct/ctvar.h>
|
||||
#include <i386/Cbus/dev/ct/bshwvar.h>
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#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>
|
||||
|
||||
#include <cam/scsi/scsi_low.h>
|
||||
|
||||
#include <i386/isa/ic/wd33c93.h>
|
||||
#include <dev/ct/ctvar.h>
|
||||
#include <dev/ct/bshwvar.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/*********************************************************
|
||||
* GENERIC MACHDEP FUNCTIONS
|
||||
*********************************************************/
|
||||
void
|
||||
bshw_synch_setup(ct, li)
|
||||
struct ct_softc *ct;
|
||||
struct lun_info *li;
|
||||
{
|
||||
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_targ_info *cti = (void *) ti;
|
||||
struct bshw_softc *bs = ct->ct_hw;
|
||||
struct bshw *hw = bs->sc_hw;
|
||||
|
||||
if (hw->sregaddr == 0)
|
||||
return;
|
||||
|
||||
ct_cr_write_1(bst, bsh, 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,
|
||||
cti->cti_syncreg);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
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 bshw_softc *bs = ct->ct_hw;
|
||||
struct bshw *hw = bs->sc_hw;
|
||||
bus_addr_t offs;
|
||||
u_int8_t regv;
|
||||
int i;
|
||||
|
||||
/* open hardware busmaster mode */
|
||||
if (hw->dma_init != NULL && ((*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));
|
||||
}
|
||||
|
||||
/* clear hardware synch registers */
|
||||
offs = hw->sregaddr;
|
||||
if (offs != 0)
|
||||
{
|
||||
for (i = 0; i < 8; i ++, offs ++)
|
||||
{
|
||||
ct_cr_write_1(bst, bsh, offs, 0);
|
||||
if ((hw->hw_flags & BSHW_DOUBLE_DMACHAN) != 0)
|
||||
ct_cr_write_1(bst, bsh, offs + 8, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* disable interrupt & assert reset */
|
||||
regv = ct_cr_read_1(bst, bsh, wd3s_mbank);
|
||||
regv |= MBR_RST;
|
||||
regv &= ~MBR_IEN;
|
||||
ct_cr_write_1(bst, bsh, wd3s_mbank, regv);
|
||||
|
||||
delay(500000);
|
||||
|
||||
/* reset signal off */
|
||||
regv &= ~MBR_RST;
|
||||
ct_cr_write_1(bst, bsh, wd3s_mbank, regv);
|
||||
|
||||
/* interrupt enable */
|
||||
regv |= MBR_IEN;
|
||||
ct_cr_write_1(bst, bsh, wd3s_mbank, regv);
|
||||
}
|
||||
|
||||
/* probe */
|
||||
int
|
||||
bshw_read_settings(bst, bsh, bs)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
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;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* DMA PIO TRANSFER (SMIT)
|
||||
*********************************************************/
|
||||
#define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */
|
||||
#define LC_SMIT_OFFSET 0x1000
|
||||
#define LC_FSZ DEV_BSIZE
|
||||
#define LC_SFSZ 0x0c
|
||||
#define LC_REST (LC_FSZ - LC_SFSZ)
|
||||
|
||||
#define BSHW_LC_FSET 0x36
|
||||
#define BSHW_LC_FCTRL 0x44
|
||||
#define FCTRL_EN 0x01
|
||||
#define FCTRL_WRITE 0x02
|
||||
|
||||
#define SF_ABORT 0x08
|
||||
#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 __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;
|
||||
|
||||
ct_cr_write_1(bst, bsh, BSHW_LC_FCTRL, 0);
|
||||
bus_space_write_1(ct->sc_iot, ct->sc_ioh, cmd_port, CMDP_DMER);
|
||||
}
|
||||
|
||||
static __inline void
|
||||
bshw_lc_smit_start(ct, count, direction)
|
||||
struct ct_softc *ct;
|
||||
int count;
|
||||
u_int direction;
|
||||
{
|
||||
bus_space_tag_t bst = ct->sc_iot;
|
||||
bus_space_handle_t bsh = ct->sc_ioh;
|
||||
u_int8_t pval, val;
|
||||
|
||||
val = ct_cr_read_1(bst, bsh, BSHW_LC_FSET);
|
||||
cthw_set_count(bst, bsh, 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);
|
||||
}
|
||||
|
||||
static int
|
||||
bshw_lc_smit_fstat(ct, wc, read)
|
||||
struct ct_softc *ct;
|
||||
int wc, read;
|
||||
{
|
||||
u_int8_t stat;
|
||||
|
||||
while (wc -- > 0)
|
||||
{
|
||||
outb(0x5f, 0);
|
||||
stat = bus_space_read_1(ct->sc_iot, ct->sc_ioh, cmd_port);
|
||||
if (read == SCSI_LOW_READ)
|
||||
{
|
||||
if ((stat & SF_RDY) != 0)
|
||||
return 0;
|
||||
if ((stat & SF_ABORT) != 0)
|
||||
return EIO;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((stat & SF_ABORT) != 0)
|
||||
return EIO;
|
||||
if ((stat & SF_RDY) != 0)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s: SMIT fifo status timeout\n", ct->sc_sclow.sl_xname);
|
||||
return EIO;
|
||||
}
|
||||
|
||||
void
|
||||
bshw_smit_xfer_stop(ct)
|
||||
struct ct_softc *ct;
|
||||
{
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
struct bshw_softc *bs = ct->ct_hw;
|
||||
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;
|
||||
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)
|
||||
{
|
||||
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";
|
||||
goto bad;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (count == (u_int) sp->scp_datalen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s = "strange count";
|
||||
}
|
||||
else
|
||||
s = "extra smit interrupt";
|
||||
|
||||
bad:
|
||||
printf("%s: smit_xfer_end: %s", slp->sl_xname, s);
|
||||
slp->sl_error |= PDMAERR;
|
||||
}
|
||||
|
||||
void
|
||||
bshw_smit_xfer_start(ct)
|
||||
struct ct_softc *ct;
|
||||
{
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
struct bshw_softc *bs = ct->ct_hw;
|
||||
struct sc_p *sp = &slp->sl_scp;
|
||||
struct targ_info *ti = slp->sl_nexus;
|
||||
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_int8_t *data;
|
||||
|
||||
data = sp->scp_data;
|
||||
datalen = sp->scp_datalen;
|
||||
|
||||
ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA);
|
||||
bshw_lc_smit_start(ct, sp->scp_datalen, sp->scp_direction);
|
||||
|
||||
if (sp->scp_direction == SCSI_LOW_READ)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_READ))
|
||||
break;
|
||||
|
||||
count = (datalen > LC_FSZ ? LC_FSZ : datalen);
|
||||
bus_space_read_region_4(ct->sc_memt, ct->sc_memh,
|
||||
LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
}
|
||||
while (datalen > 0);
|
||||
|
||||
bs->sc_tdatalen = datalen;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
|
||||
break;
|
||||
if (cti->cti_syncreg == 0)
|
||||
{
|
||||
/* XXX:
|
||||
* If async transfer, reconfirm a scsi phase
|
||||
* again. Unless C bus might hang up.
|
||||
*/
|
||||
if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
|
||||
break;
|
||||
}
|
||||
|
||||
count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
|
||||
bus_space_write_region_4(ct->sc_memt, ct->sc_memh,
|
||||
LC_SMIT_OFFSET, (u_int32_t *) data, count >> 2);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
|
||||
if (bshw_lc_smit_fstat(ct, wc, SCSI_LOW_WRITE))
|
||||
break;
|
||||
|
||||
count = (datalen > LC_REST ? LC_REST : datalen);
|
||||
bus_space_write_region_4(ct->sc_memt, ct->sc_memh,
|
||||
LC_SMIT_OFFSET + LC_SFSZ,
|
||||
(u_int32_t *) data, count >> 2);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
}
|
||||
while (datalen > 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* DMA TRANSFER (BS)
|
||||
*********************************************************/
|
||||
static void bshw_dmastart __P((struct ct_softc *));
|
||||
static void bshw_dmadone __P((struct ct_softc *));
|
||||
|
||||
void
|
||||
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 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;
|
||||
|
||||
ct_cr_write_1(bst, bsh, wd3s_ctrl, ct->sc_creg | CR_DMA);
|
||||
phys = vtophys((vaddr_t) sp->scp_data);
|
||||
if (phys >= bs->sc_minphys)
|
||||
{
|
||||
/* setup segaddr */
|
||||
bs->sc_segaddr = bs->sc_bounce_phys;
|
||||
/* setup seglen */
|
||||
bs->sc_seglen = sp->scp_datalen;
|
||||
if (bs->sc_seglen > bs->sc_bounce_size)
|
||||
bs->sc_seglen = bs->sc_bounce_size;
|
||||
/* setup bufp */
|
||||
bs->sc_bufp = bs->sc_bounce_addr;
|
||||
if (sp->scp_direction == SCSI_LOW_WRITE)
|
||||
bcopy(sp->scp_data, bs->sc_bufp, bs->sc_seglen);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* setup segaddr */
|
||||
bs->sc_segaddr = (u_int8_t *) phys;
|
||||
/* setup seglen */
|
||||
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)
|
||||
{
|
||||
bs->sc_seglen = sp->scp_datalen;
|
||||
break;
|
||||
}
|
||||
|
||||
nphys = vtophys(va);
|
||||
if (phys + PAGE_SIZE != nphys ||
|
||||
nphys >= bs->sc_minphys)
|
||||
{
|
||||
bs->sc_seglen =
|
||||
(u_int8_t *) trunc_page(va) - sp->scp_data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* setup bufp */
|
||||
bs->sc_bufp = NULL;
|
||||
}
|
||||
|
||||
bshw_dmastart(ct);
|
||||
cthw_set_count(bst, bsh, bs->sc_seglen);
|
||||
}
|
||||
|
||||
void
|
||||
bshw_dma_xfer_stop(ct)
|
||||
struct ct_softc *ct;
|
||||
{
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
struct sc_p *sp = &slp->sl_scp;
|
||||
struct bshw_softc *bs = ct->ct_hw;
|
||||
struct targ_info *ti;
|
||||
u_int count, transbytes;
|
||||
|
||||
bshw_dmadone(ct);
|
||||
|
||||
ti = slp->sl_nexus;
|
||||
if (ti == NULL)
|
||||
return;
|
||||
|
||||
if (ti->ti_phase == PH_DATA)
|
||||
{
|
||||
count = cthw_get_count(ct->sc_iot, ct->sc_ioh);
|
||||
if (count < (u_int) bs->sc_seglen)
|
||||
{
|
||||
transbytes = bs->sc_seglen - count;
|
||||
if (bs->sc_bufp != NULL &&
|
||||
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)
|
||||
{
|
||||
bs->sc_bufp = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
printf("%s: port data %x != seglen %x\n",
|
||||
slp->sl_xname, count, bs->sc_seglen);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("%s: extra DMA interrupt\n", slp->sl_xname);
|
||||
}
|
||||
|
||||
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)
|
||||
#undef DMA1_MODE
|
||||
#define DMA1_MODE (0x17)
|
||||
#undef DMA1_FFC
|
||||
#define DMA1_FFC (0x19)
|
||||
#undef DMA1_CHN
|
||||
#define DMA1_CHN(c) (0x01 + ((c) << 2))
|
||||
|
||||
#define DMA37SM_SET 0x04
|
||||
#define DMA37MD_WRITE 0x04
|
||||
#define DMA37MD_READ 0x08
|
||||
#define DMA37MD_SINGLE 0x40
|
||||
|
||||
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;
|
||||
int chan = bs->sc_drq;
|
||||
int waport;
|
||||
u_int8_t *phys = bs->sc_segaddr;
|
||||
u_int nbytes = bs->sc_seglen;
|
||||
|
||||
/*
|
||||
* 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);
|
||||
else
|
||||
outb(DMA1_MODE, DMA37MD_SINGLE | DMA37MD_READ | chan);
|
||||
outb(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);
|
||||
|
||||
/* send count */
|
||||
outb(waport + 2, --nbytes);
|
||||
outb(waport + 2, nbytes >> 8);
|
||||
|
||||
/* vendor unique hook */
|
||||
if (bs->sc_hw->dma_start)
|
||||
(*bs->sc_hw->dma_start)(ct);
|
||||
|
||||
outb(DMA1_SMSK, chan);
|
||||
bus_space_write_1(bst, bsh, cmd_port, CMDP_DMES);
|
||||
}
|
||||
|
||||
static void
|
||||
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;
|
||||
|
||||
outb(DMA1_SMSK, (bs->sc_drq | DMA37SM_SET));
|
||||
bus_space_write_1(bst, bsh, cmd_port, CMDP_DMER);
|
||||
|
||||
/* vendor unique hook */
|
||||
if (bs->sc_hw->dma_stop)
|
||||
(*bs->sc_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
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* VENDOR UNIQUE DMA FUNCS
|
||||
**********************************************/
|
||||
static int bshw_dma_init_sc98 __P((struct ct_softc *));
|
||||
static void bshw_dma_start_sc98 __P((struct ct_softc *));
|
||||
static void bshw_dma_stop_sc98 __P((struct ct_softc *));
|
||||
static int bshw_dma_init_texa __P((struct ct_softc *));
|
||||
static void bshw_dma_start_elecom __P((struct ct_softc *));
|
||||
static void bshw_dma_stop_elecom __P((struct ct_softc *));
|
||||
|
||||
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;
|
||||
u_int8_t regval;
|
||||
|
||||
if ((regval = ct_cr_read_1(bst, bsh, 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);
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (ct_cr_read_1(bst, bsh, 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);
|
||||
#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);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ct_cr_write_1(bst, bsh, 0x73, 0x32);
|
||||
ct_cr_write_1(bst, bsh, 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;
|
||||
|
||||
ct_cr_write_1(bst, bsh, 0x73, 0x43);
|
||||
ct_cr_write_1(bst, bsh, 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);
|
||||
|
||||
ct_cr_write_1(bst, bsh, 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);
|
||||
|
||||
ct_cr_write_1(bst, bsh, 0x32, tmp | 0x20);
|
||||
}
|
||||
|
||||
static struct bshw bshw_generic = {
|
||||
BSHW_SYNC_RELOAD,
|
||||
|
||||
0,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bshw bshw_sc98 = {
|
||||
BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
bshw_dma_init_sc98,
|
||||
bshw_dma_start_sc98,
|
||||
bshw_dma_stop_sc98,
|
||||
};
|
||||
|
||||
static struct bshw bshw_texa = {
|
||||
BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
bshw_dma_init_texa,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bshw bshw_elecom = {
|
||||
0,
|
||||
|
||||
0x38,
|
||||
|
||||
NULL,
|
||||
bshw_dma_start_elecom,
|
||||
bshw_dma_stop_elecom,
|
||||
};
|
||||
|
||||
static struct bshw bshw_lc_smit = {
|
||||
BSHW_SMFIFO | BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct bshw bshw_lha20X = {
|
||||
BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
/* hw tabs */
|
||||
static dvcfg_hw_t bshw_hwsel_array[] = {
|
||||
/* 0x00 */ &bshw_generic,
|
||||
/* 0x01 */ &bshw_sc98,
|
||||
/* 0x02 */ &bshw_texa,
|
||||
/* 0x03 */ &bshw_elecom,
|
||||
/* 0x04 */ &bshw_lc_smit,
|
||||
/* 0x05 */ &bshw_lha20X,
|
||||
};
|
||||
|
||||
struct dvcfg_hwsel bshw_hwsel = {
|
||||
DVCFG_HWSEL_SZ(bshw_hwsel_array),
|
||||
bshw_hwsel_array
|
||||
};
|
86
sys/dev/ct/bshwvar.h
Normal file
86
sys/dev/ct/bshwvar.h
Normal file
@ -0,0 +1,86 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: bshwvar.h,v 1.3 1999/04/15 01:36:10 kmatsuda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1994, 1995, 1996, 1997, 1998
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#ifndef _BSHWVAR_H_
|
||||
#define _BSHWVAR_H_
|
||||
|
||||
/*
|
||||
* bshwvar.h
|
||||
* NEC 55 compatible board specific definitions
|
||||
*/
|
||||
|
||||
#define BSHW_DEFAULT_CHIPCLK 20 /* 20MHz */
|
||||
#define BSHW_DEFAULT_HOSTID 7
|
||||
|
||||
struct bshw {
|
||||
#define BSHW_SYNC_RELOAD 0x01
|
||||
#define BSHW_SMFIFO 0x02
|
||||
#define BSHW_DOUBLE_DMACHAN 0x04
|
||||
u_int hw_flags;
|
||||
|
||||
u_int sregaddr;
|
||||
|
||||
int ((*dma_init) __P((struct ct_softc *)));
|
||||
void ((*dma_start) __P((struct ct_softc *)));
|
||||
void ((*dma_stop) __P((struct ct_softc *)));
|
||||
};
|
||||
|
||||
struct bshw_softc {
|
||||
int sc_hostid;
|
||||
int sc_irq; /* irq */
|
||||
int sc_drq; /* drq */
|
||||
|
||||
/* dma transfer */
|
||||
u_int8_t *sc_segaddr;
|
||||
u_int8_t *sc_bufp;
|
||||
int sc_seglen;
|
||||
int sc_tdatalen; /* temp datalen */
|
||||
|
||||
/* private bounce */
|
||||
u_int8_t *sc_bounce_phys;
|
||||
u_int8_t *sc_bounce_addr;
|
||||
u_int sc_bounce_size;
|
||||
bus_addr_t sc_minphys;
|
||||
|
||||
/* hardware */
|
||||
struct bshw *sc_hw;
|
||||
};
|
||||
|
||||
void bshw_synch_setup __P((struct ct_softc *, struct lun_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 *));
|
||||
void bshw_smit_xfer_stop __P((struct ct_softc *));
|
||||
void 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_ */
|
960
sys/dev/ct/ct.c
Normal file
960
sys/dev/ct/ct.c
Normal file
@ -0,0 +1,960 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: ct.c,v 1.13 1999/07/23 20:54:00 honda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
#define CT_DEBUG
|
||||
#define CT_USE_CCSEQ
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
*
|
||||
* Copyright (c) 1994, 1995, 1996, 1997, 1998, 1999
|
||||
* Naofumi HONDA. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "opt_ddb.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/bio.h>
|
||||
#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 <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
#include <dev/scsipi/scsi_disk.h>
|
||||
|
||||
#include <machine/dvcfg.h>
|
||||
#include <machine/physio_proc.h>
|
||||
|
||||
#include <i386/Cbus/dev/scsi_low.h>
|
||||
|
||||
#include <dev/ic/wd33c93reg.h>
|
||||
#include <i386/Cbus/dev/ct/ctvar.h>
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <machine/bus.h>
|
||||
|
||||
#include <machine/dvcfg.h>
|
||||
#include <machine/physio_proc.h>
|
||||
|
||||
#include <cam/scsi/scsi_low.h>
|
||||
|
||||
#include <i386/isa/ic/wd33c93.h>
|
||||
#include <dev/ct/ctvar.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* 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 */
|
||||
|
||||
/***************************************************
|
||||
* default data
|
||||
***************************************************/
|
||||
u_int8_t cthw_cmdlevel[256] = {
|
||||
/* 0 1 2 3 4 5 6 7 8 9 A B C E D F */
|
||||
/*0*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*1*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*2*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,1 ,0 ,1 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*3*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*4*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*5*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*6*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*7*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*8*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*9*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*A*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*B*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*C*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*D*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*E*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*F*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,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[] = {
|
||||
{25, 0xa0}, {37, 0xb0}, {50, 0x20}, {62, 0xd0}, {75, 0x30},
|
||||
{87, 0xf0}, {100, 0x40}, {125, 0x50}, {0, 0}
|
||||
};
|
||||
|
||||
extern unsigned int delaycount;
|
||||
|
||||
/*****************************************************************
|
||||
* Interface functions
|
||||
*****************************************************************/
|
||||
static int ct_xfer __P((struct ct_softc *, u_int8_t *, int, int));
|
||||
static void ct_io_xfer __P((struct ct_softc *));
|
||||
static __inline int ct_reselected __P((struct ct_softc *));
|
||||
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 void cthw_bus_reset __P((struct ct_softc *));
|
||||
static int ct_nexus __P((struct ct_softc *, struct targ_info *));
|
||||
static void cthw_attention __P((struct ct_softc *));
|
||||
static int ct_targ_init __P((struct ct_softc *, struct targ_info *));
|
||||
|
||||
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_SELECT_T ct_start_selection,
|
||||
SC_LOW_NEXUS_T ct_nexus,
|
||||
|
||||
SC_LOW_ATTEN_T cthw_attention,
|
||||
SC_LOW_MSG_T ct_msg,
|
||||
|
||||
SC_LOW_POLL_T ctintr,
|
||||
|
||||
NULL, /* SC_LOW_POWER_T cthw_power, */
|
||||
};
|
||||
|
||||
/**************************************************
|
||||
* HW functions
|
||||
**************************************************/
|
||||
static __inline void
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static void
|
||||
cthw_bus_reset(ct)
|
||||
struct ct_softc *ct;
|
||||
{
|
||||
|
||||
/*
|
||||
* wd33c93 does not have bus reset function.
|
||||
*/
|
||||
if (ct->ct_bus_reset != NULL)
|
||||
((*ct->ct_bus_reset) (ct));
|
||||
}
|
||||
|
||||
static int
|
||||
cthw_chip_reset(bst, bsh, chipclk, hostid)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
int chipclk, hostid;
|
||||
{
|
||||
#define CT_SELTIMEOUT_20MHz_REGV (0x80)
|
||||
u_int8_t aux, regv;
|
||||
u_int seltout;
|
||||
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);
|
||||
|
||||
/* setup chip registers */
|
||||
regv = 0;
|
||||
seltout = CT_SELTIMEOUT_20MHz_REGV;
|
||||
switch (chipclk)
|
||||
{
|
||||
case 10:
|
||||
seltout = (seltout * chipclk) / 20;
|
||||
regv = 0;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
seltout = (seltout * chipclk) / 20;
|
||||
regv = IDR_FS_12_15;
|
||||
break;
|
||||
|
||||
case 20:
|
||||
seltout = (seltout * chipclk) / 20;
|
||||
regv = IDR_FS_15_20;
|
||||
break;
|
||||
|
||||
default:
|
||||
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);
|
||||
for (wc = CT_RESET_DEFAULT; wc > 0; wc --)
|
||||
{
|
||||
aux = ct_stat_read_1(bst, bsh);
|
||||
if (aux != 0xff && (aux & STR_INT))
|
||||
{
|
||||
if (ct_cr_read_1(bst, bsh, wd3s_stat) == 0)
|
||||
break;
|
||||
|
||||
ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_RESET);
|
||||
}
|
||||
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);
|
||||
|
||||
(void) ct_stat_read_1(bst, bsh);
|
||||
(void) ct_cr_read_1(bst, bsh, wd3s_stat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* Attach & Probe
|
||||
**************************************************/
|
||||
int
|
||||
ctprobesubr(bst, bsh, dvcfg, hsid, chipclk)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
u_int dvcfg, chipclk;
|
||||
int hsid;
|
||||
{
|
||||
|
||||
#if 0
|
||||
if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 0)
|
||||
return 0;
|
||||
#endif
|
||||
if (cthw_chip_reset(bst, bsh, chipclk, hsid) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
ctprint(aux, name)
|
||||
void *aux;
|
||||
const char *name;
|
||||
{
|
||||
|
||||
if (name != NULL)
|
||||
printf("%s: scsibus ", name);
|
||||
return UNCONF;
|
||||
}
|
||||
|
||||
void
|
||||
ctattachsubr(ct)
|
||||
struct ct_softc *ct;
|
||||
{
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
|
||||
ct->sc_wc = delaycount * 2000; /* 2 sec */
|
||||
slp->sl_funcs = &ct_funcs;
|
||||
(void) scsi_low_attach(slp, 2, CT_NTARGETS, CT_NLUNS,
|
||||
sizeof(struct ct_targ_info));
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* SCSI LOW interface functions
|
||||
**************************************************/
|
||||
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;
|
||||
|
||||
if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 0)
|
||||
{
|
||||
ct->sc_atten = 1;
|
||||
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->sc_atten = 1;
|
||||
return;
|
||||
}
|
||||
ct->sc_atten = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_targ_init(ct, ti)
|
||||
struct ct_softc *ct;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct ct_targ_info *cti = (void *) ti;
|
||||
|
||||
if (ct->sc_chiprev == CT_WD33C93_A)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
cti->cti_syncreg = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_world_start(ct, fdone)
|
||||
struct ct_softc *ct;
|
||||
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;
|
||||
|
||||
if (ct->sc_sdp == NULL)
|
||||
ct->sc_sdp = &ct_synch_data_20MHz[0];
|
||||
|
||||
slp->sl_cfgflags |= CFG_MSGUNIFY;
|
||||
if (slp->sl_cfgflags & CFG_NOPARITY)
|
||||
ct->sc_creg = CR_DEFAULT;
|
||||
else
|
||||
ct->sc_creg = CR_DEFAULT_HP;
|
||||
|
||||
if (ct->sc_dma & CT_DMA_DMASTART)
|
||||
(*ct->ct_dma_xfer_stop) (ct);
|
||||
if (ct->sc_dma & CT_DMA_PIOSTART)
|
||||
(*ct->ct_pio_xfer_stop) (ct);
|
||||
ct->sc_dma = 0;
|
||||
ct->sc_atten = 0;
|
||||
|
||||
s = splcam();
|
||||
cthw_chip_reset(bst, bsh, ct->sc_chipclk, slp->sl_hostid);
|
||||
scsi_low_bus_reset(slp);
|
||||
cthw_chip_reset(bst, bsh, ct->sc_chipclk, slp->sl_hostid);
|
||||
splx(s);
|
||||
|
||||
SOFT_INTR_REQUIRED(slp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_start_selection(ct, cb)
|
||||
struct ct_softc *ct;
|
||||
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;
|
||||
u_int8_t cmd;
|
||||
|
||||
ct->sc_atten = 0;
|
||||
if (cthw_cmdlevel[slp->sl_scp.scp_cmd[0]] != 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;
|
||||
ct->sc_satgo = CT_SAT_GOING;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmd = WD3S_SELECT_ATN;
|
||||
ct->sc_satgo = 0;
|
||||
}
|
||||
|
||||
if ((ct_stat_read_1(bst, bsh) & STR_BUSY) != 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);
|
||||
|
||||
s = splhigh();
|
||||
if ((ct_stat_read_1(bst, bsh) & STR_BUSY) == 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)
|
||||
{
|
||||
splx(s);
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_SELSTART);
|
||||
return SCSI_LOW_START_OK;
|
||||
}
|
||||
}
|
||||
splx(s);
|
||||
return SCSI_LOW_START_FAIL;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_msg(ct, ti, msg)
|
||||
struct ct_softc *ct;
|
||||
struct targ_info *ti;
|
||||
u_int msg;
|
||||
{
|
||||
struct lun_info *li = ti->ti_li;
|
||||
struct ct_targ_info *cti = (void *) ti;
|
||||
struct ct_synch_data *csp = ct->sc_sdp;
|
||||
u_int offset, period;
|
||||
|
||||
if (msg != SCSI_LOW_MSG_SYNCH)
|
||||
return 0;
|
||||
|
||||
offset = ti->ti_maxsynch.offset;
|
||||
period = ti->ti_maxsynch.period;
|
||||
for ( ; csp->cs_period != 0; csp ++)
|
||||
{
|
||||
if (period == csp->cs_period)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ti->ti_maxsynch.period != 0 && csp->cs_period == 0)
|
||||
{
|
||||
ti->ti_maxsynch.period = 0;
|
||||
ti->ti_maxsynch.offset = 0;
|
||||
cti->cti_syncreg = 0;
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
cti->cti_syncreg = ((offset & 0x0f) | csp->cs_syncr);
|
||||
if (ct->ct_synch_setup != 0)
|
||||
(*ct->ct_synch_setup) (ct, li);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*************************************************
|
||||
* <DATA PHASE>
|
||||
*************************************************/
|
||||
static int
|
||||
ct_xfer(ct, data, len, direction)
|
||||
struct ct_softc *ct;
|
||||
u_int8_t *data;
|
||||
int len, direction;
|
||||
{
|
||||
bus_space_tag_t bst = ct->sc_iot;
|
||||
bus_space_handle_t bsh = ct->sc_ioh;
|
||||
int wc;
|
||||
register u_int8_t aux;
|
||||
|
||||
if (len == 1)
|
||||
{
|
||||
ct_cr_write_1(bst, bsh, 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);
|
||||
}
|
||||
|
||||
aux = ct_stat_read_1(bst, bsh);
|
||||
if ((aux & STR_LCI) != 0)
|
||||
{
|
||||
cthw_set_count(bst, bsh, 0);
|
||||
return len;
|
||||
}
|
||||
|
||||
for (wc = ct->sc_wc ; wc > 0; 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);
|
||||
else
|
||||
ct_cr_write_1(bst, bsh, wd3s_data, *data);
|
||||
len --;
|
||||
if (len <= 0)
|
||||
break;
|
||||
data ++;
|
||||
}
|
||||
|
||||
/* check phase miss */
|
||||
aux = ct_stat_read_1(bst, bsh);
|
||||
if ((aux & STR_INT) != 0)
|
||||
break;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
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 sc_p *sp = &slp->sl_scp;
|
||||
u_int dummy;
|
||||
int len;
|
||||
|
||||
/* io polling mode */
|
||||
ct_cr_write_1(bst, bsh, 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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* <PHASE ERROR>
|
||||
**************************************************/
|
||||
struct ct_err {
|
||||
u_char *pe_msg;
|
||||
u_int pe_err;
|
||||
u_int pe_errmsg;
|
||||
int pe_done;
|
||||
};
|
||||
|
||||
struct ct_err ct_cmderr[] = {
|
||||
/*0*/ { "illegal cmd", FATALIO, SCSI_LOW_MSG_ABORT, 1},
|
||||
/*1*/ { "unexpected bus free", FATALIO, 0, 1},
|
||||
/*2*/ { NULL, SELTIMEOUTIO, 0, 1},
|
||||
/*3*/ { "scsi bus parity error", PARITYERR, SCSI_LOW_MSG_ERROR, 0},
|
||||
/*4*/ { "scsi bus parity error", PARITYERR, SCSI_LOW_MSG_ERROR, 0},
|
||||
/*5*/ { "unknown" , FATALIO, SCSI_LOW_MSG_ABORT, 1},
|
||||
/*6*/ { "miss reselection (target mode)", FATALIO, SCSI_LOW_MSG_ABORT, 0},
|
||||
/*7*/ { "wrong status byte", PARITYERR, SCSI_LOW_MSG_ERROR, 0},
|
||||
};
|
||||
|
||||
static void
|
||||
ct_phase_error(ct, scsi_status)
|
||||
struct ct_softc *ct;
|
||||
u_int8_t scsi_status;
|
||||
{
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
struct targ_info *ti = slp->sl_nexus;
|
||||
struct ct_err *pep;
|
||||
u_int msg = 0;
|
||||
|
||||
if ((scsi_status & BSR_CM) == BSR_CMDERR &&
|
||||
(scsi_status & BSR_PHVALID) == 0)
|
||||
{
|
||||
pep = &ct_cmderr[scsi_status & BSR_PM];
|
||||
slp->sl_error |= pep->pe_err;
|
||||
if ((pep->pe_err & PARITYERR) != 0)
|
||||
{
|
||||
if (ti->ti_phase == PH_MSGIN)
|
||||
msg = SCSI_LOW_MSG_PARITY;
|
||||
else
|
||||
msg = SCSI_LOW_MSG_ERROR;
|
||||
}
|
||||
else
|
||||
msg = pep->pe_errmsg;
|
||||
|
||||
if (msg != 0)
|
||||
scsi_low_assert_msg(slp, slp->sl_nexus, 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);
|
||||
}
|
||||
|
||||
if (pep->pe_done != 0)
|
||||
scsi_low_disconnected(slp, ti);
|
||||
}
|
||||
else
|
||||
{
|
||||
slp->sl_error |= FATALIO;
|
||||
scsi_low_restart(slp, SCSI_LOW_RESTART_HARD, "phase error");
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* ### SCSI PHASE SEQUENCER ###
|
||||
**************************************************/
|
||||
static __inline int
|
||||
ct_reselected(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 targ_info *ti;
|
||||
u_int sid;
|
||||
|
||||
ct->sc_atten = 0;
|
||||
sid = (ct_cr_read_1(bst, bsh, wd3s_sid) & 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);
|
||||
return EJUSTRETURN;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_nexus(ct, ti)
|
||||
struct ct_softc *ct;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
bus_space_tag_t bst = ct->sc_iot;
|
||||
bus_space_handle_t bsh = ct->sc_ioh;
|
||||
struct lun_info *li = ti->ti_li;
|
||||
struct ct_targ_info *cti = (void *) ti;
|
||||
|
||||
if ((li->li_flags & SCSI_LOW_NOPARITY) != 0)
|
||||
ct->sc_creg = CR_DEFAULT;
|
||||
else
|
||||
ct->sc_creg = CR_DEFAULT_HP;
|
||||
|
||||
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 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 targ_info *ti;
|
||||
struct physio_proc *pp;
|
||||
struct buf *bp;
|
||||
int len, satgo;
|
||||
u_int8_t scsi_status, regv;
|
||||
|
||||
if (slp->sl_flags & HW_INACTIVE)
|
||||
return 0;
|
||||
|
||||
/**************************************************
|
||||
* Get status & bus phase
|
||||
**************************************************/
|
||||
if ((ct_stat_read_1(bst, bsh) & STR_INT) == 0)
|
||||
return 0;
|
||||
|
||||
scsi_status = ct_cr_read_1(bst, bsh, wd3s_stat);
|
||||
if (scsi_status == ((u_int8_t) -1))
|
||||
return 1;
|
||||
|
||||
/**************************************************
|
||||
* Check reselection, or nexus
|
||||
**************************************************/
|
||||
if (scsi_status == BSR_RESEL)
|
||||
{
|
||||
if (ct_reselected(ct) == EJUSTRETURN)
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((ti = slp->sl_nexus) == NULL)
|
||||
return 1;
|
||||
|
||||
/**************************************************
|
||||
* Debug section
|
||||
**************************************************/
|
||||
#ifdef CT_DEBUG
|
||||
if (ct_debug > 0)
|
||||
{
|
||||
scsi_low_print(slp, NULL);
|
||||
printf("%s: scsi_status 0x%x\n\n", slp->sl_xname,
|
||||
(u_int) scsi_status);
|
||||
if (ct_debug > 1)
|
||||
Debugger();
|
||||
}
|
||||
#endif /* CT_DEBUG */
|
||||
|
||||
/**************************************************
|
||||
* Internal scsi phase
|
||||
**************************************************/
|
||||
satgo = ct->sc_satgo;
|
||||
ct->sc_satgo = 0;
|
||||
|
||||
switch (ti->ti_phase)
|
||||
{
|
||||
case PH_SELSTART:
|
||||
if ((satgo & CT_SAT_GOING) == 0)
|
||||
{
|
||||
if (scsi_status != BSR_SELECTED)
|
||||
{
|
||||
ct_phase_error(ct, scsi_status);
|
||||
return 1;
|
||||
}
|
||||
scsi_low_arbit_win(slp, ti);
|
||||
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);
|
||||
}
|
||||
break;
|
||||
|
||||
case PH_RESEL:
|
||||
if ((scsi_status & BSR_PHVALID) == 0 ||
|
||||
(scsi_status & BSR_PM) != BSR_MSGIN)
|
||||
{
|
||||
scsi_low_restart(slp, SCSI_LOW_RESTART_HARD,
|
||||
"phase miss after reselect");
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (slp->sl_flags & HW_PDMASTART)
|
||||
{
|
||||
slp->sl_flags &= ~HW_PDMASTART;
|
||||
if (ct->sc_dma & CT_DMA_DMASTART)
|
||||
{
|
||||
(*ct->ct_dma_xfer_stop) (ct);
|
||||
ct->sc_dma &= ~CT_DMA_DMASTART;
|
||||
}
|
||||
else
|
||||
{
|
||||
(*ct->ct_pio_xfer_stop) (ct);
|
||||
ct->sc_dma &= ~CT_DMA_PIOSTART;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* parse scsi phase
|
||||
**************************************************/
|
||||
if (scsi_status & BSR_PHVALID)
|
||||
{
|
||||
/**************************************************
|
||||
* Normal SCSI phase.
|
||||
**************************************************/
|
||||
if ((scsi_status & BSR_CM) == BSR_CMDABT)
|
||||
{
|
||||
ct_phase_error(ct, scsi_status);
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (scsi_status & BSR_PM)
|
||||
{
|
||||
case BSR_DATAOUT:
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_DATA);
|
||||
if (scsi_low_data(slp, ti, &bp, SCSI_LOW_WRITE) != 0)
|
||||
return 1;
|
||||
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;
|
||||
}
|
||||
|
||||
slp->sl_flags |= HW_PDMASTART;
|
||||
if ((ct->sc_xmode & CT_XMODE_PIO) != 0 &&
|
||||
(slp->sl_scp.scp_datalen % DEV_BSIZE) == 0)
|
||||
{
|
||||
pp = physio_proc_enter(bp);
|
||||
ct->sc_dma |= CT_DMA_PIOSTART;
|
||||
(*ct->ct_pio_xfer_start) (ct);
|
||||
physio_proc_leave(pp);
|
||||
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);
|
||||
}
|
||||
return 1;
|
||||
|
||||
case BSR_CMDOUT:
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_CMD);
|
||||
if (scsi_low_cmd(slp, ti) != 0)
|
||||
break;
|
||||
|
||||
if (ct_xfer(ct,
|
||||
slp->sl_scp.scp_cmd,
|
||||
slp->sl_scp.scp_cmdlen,
|
||||
SCSI_LOW_WRITE) != 0)
|
||||
{
|
||||
printf("%s: scsi cmd xfer short\n",
|
||||
slp->sl_xname);
|
||||
}
|
||||
return 1;
|
||||
|
||||
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)
|
||||
{
|
||||
ct_xfer(ct, &ti->ti_status, 1, SCSI_LOW_READ);
|
||||
}
|
||||
else
|
||||
{
|
||||
cthw_set_count(bst, bsh, 0);
|
||||
cthw_phase_bypass(ct, 0x41);
|
||||
}
|
||||
#else /* !CT_USE_CCSEQ */
|
||||
ct_xfer(ct, &ti->ti_status, 1, SCSI_LOW_READ);
|
||||
#endif /* !CT_USE_CCSEQ */
|
||||
return 1;
|
||||
|
||||
case BSR_UNSPINFO0:
|
||||
case BSR_UNSPINFO1:
|
||||
printf("%s: illegal bus phase (0x%x)\n", slp->sl_xname,
|
||||
(u_int) scsi_status);
|
||||
scsi_low_print(slp, ti);
|
||||
return 1;
|
||||
|
||||
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))
|
||||
{
|
||||
printf("%s: scsi msgout xfer short\n",
|
||||
slp->sl_xname);
|
||||
scsi_low_assert_msg(slp, ti,
|
||||
SCSI_LOW_MSG_ABORT, 1);
|
||||
}
|
||||
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);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/**************************************************
|
||||
* Special SCSI phase
|
||||
**************************************************/
|
||||
switch (scsi_status)
|
||||
{
|
||||
case BSR_SATSDP: /* SAT with save data pointer */
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
|
||||
scsi_low_msgin(slp, ti, MSG_SAVESP);
|
||||
cthw_phase_bypass(ct, 0x41);
|
||||
return 1;
|
||||
|
||||
case BSR_SATFIN: /* SAT COMPLETE */
|
||||
/*
|
||||
* emulate statusin => msgin
|
||||
*/
|
||||
ti->ti_status = ct_cr_read_1(bst, bsh, wd3s_lun);
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
|
||||
SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_CMDC);
|
||||
scsi_low_disconnected(slp, ti);
|
||||
return 1;
|
||||
|
||||
case BSR_ACKREQ: /* negate ACK */
|
||||
if (ct->sc_atten != 0)
|
||||
cthw_attention(ct);
|
||||
|
||||
ct_cr_write_1(bst, bsh, wd3s_cmd, WD3S_NEGATE_ACK);
|
||||
return 1;
|
||||
|
||||
case BSR_DISC: /* disconnect */
|
||||
if (slp->sl_msgphase == MSGPH_NULL &&
|
||||
(satgo & CT_SAT_GOING) != 0)
|
||||
{
|
||||
/*
|
||||
* emulate disconnect msg
|
||||
*/
|
||||
SCSI_LOW_SETUP_PHASE(ti, PH_MSGIN);
|
||||
SCSI_LOW_SETUP_MSGPHASE(slp, MSGPH_DISC);
|
||||
}
|
||||
scsi_low_disconnected(slp, ti);
|
||||
return 1;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ct_phase_error(ct, scsi_status);
|
||||
return 1;
|
||||
}
|
322
sys/dev/ct/ct_isa.c
Normal file
322
sys/dev/ct/ct_isa.c
Normal file
@ -0,0 +1,322 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: ct_isa.c,v 1.6 1999/07/26 06:32:01 honda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#define SCSIBUS_RESCAN
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/bio.h>
|
||||
#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 <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <dev/scsipi/scsi_all.h>
|
||||
#include <dev/scsipi/scsipi_all.h>
|
||||
#include <dev/scsipi/scsiconf.h>
|
||||
#include <dev/scsipi/scsi_disk.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/isadmavar.h>
|
||||
|
||||
#include <machine/dvcfg.h>
|
||||
#include <machine/physio_proc.h>
|
||||
#include <machine/syspmgr.h>
|
||||
|
||||
#include <i386/Cbus/dev/scsi_low.h>
|
||||
|
||||
#include <dev/ic/wd33c93reg.h>
|
||||
#include <i386/Cbus/dev/ct/ctvar.h>
|
||||
#include <i386/Cbus/dev/ct/bshwvar.h>
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <machine/bus.h>
|
||||
#include <machine/resource.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/rman.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <isa/isavar.h>
|
||||
|
||||
#include <machine/dvcfg.h>
|
||||
#include <machine/physio_proc.h>
|
||||
|
||||
#include <cam/scsi/scsi_low.h>
|
||||
|
||||
#include <i386/isa/ic/wd33c93.h>
|
||||
#include <dev/ct/ctvar.h>
|
||||
#include <dev/ct/bshwvar.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#define BSHW_IOSZ 0x08
|
||||
#define BSHW_IOBASE 0xcc0
|
||||
#define BSHW_MEMSZ (PAGE_SIZE * 2)
|
||||
|
||||
static int ct_isa_match(device_t);
|
||||
static int ct_isa_attach(device_t);
|
||||
static int ct_space_map(device_t, struct bshw *,
|
||||
struct resource **, struct resource **);
|
||||
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);
|
||||
|
||||
struct ct_isa_softc {
|
||||
struct ct_softc sc_ct;
|
||||
struct bshw_softc sc_bshw;
|
||||
};
|
||||
|
||||
static struct isa_pnp_id ct_pnp_ids[] = {
|
||||
{ 0x110154dc, "I-O DATA SC-98III" },
|
||||
{ 0x4120acb4, "MELCO IFC-NN" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static device_method_t ct_isa_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, ct_isa_match),
|
||||
DEVMETHOD(device_attach, ct_isa_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ct_isa_driver = {
|
||||
"ct", ct_isa_methods, sizeof(struct ct_isa_softc),
|
||||
};
|
||||
|
||||
static devclass_t ct_devclass;
|
||||
|
||||
DRIVER_MODULE(ct, isa, ct_isa_driver, ct_devclass, 0, 0);
|
||||
|
||||
static int
|
||||
ct_isa_match(device_t dev)
|
||||
{
|
||||
struct bshw *hw;
|
||||
struct resource *port_res, *mem_res;
|
||||
int rv;
|
||||
|
||||
if (ISA_PNP_PROBE(device_get_parent(dev), dev, ct_pnp_ids) == ENXIO)
|
||||
return ENXIO;
|
||||
|
||||
if (isa_get_port(dev) == -1)
|
||||
bus_set_resource(dev, SYS_RES_IOPORT, 0,
|
||||
BSHW_IOBASE, BSHW_IOSZ);
|
||||
|
||||
if ((hw = ct_find_hw(dev)) == NULL)
|
||||
return ENXIO;
|
||||
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);
|
||||
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);
|
||||
bus_set_resource(dev, SYS_RES_IRQ, 0, bs->sc_irq, 1);
|
||||
bus_set_resource(dev, SYS_RES_DRQ, 0, bs->sc_drq, 1);
|
||||
}
|
||||
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, port_res);
|
||||
if (mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, mem_res);
|
||||
|
||||
if (rv != 0)
|
||||
return 0;
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
static int
|
||||
ct_isa_attach(device_t dev)
|
||||
{
|
||||
struct ct_isa_softc *pct = device_get_softc(dev);
|
||||
struct ct_softc *ct = &pct->sc_ct;
|
||||
struct scsi_low_softc *slp = &ct->sc_sclow;
|
||||
struct bshw_softc *bs = &pct->sc_bshw;
|
||||
struct bshw *hw;
|
||||
int irq_rid, drq_rid;
|
||||
u_int8_t *vaddr;
|
||||
bus_addr_t addr;
|
||||
|
||||
hw = ct_find_hw(dev);
|
||||
if (ct_space_map(dev, hw, &ct->port_res, &ct->mem_res) != 0) {
|
||||
device_printf(dev, "bus io mem map failed\n");
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
ct->sc_iot = rman_get_bustag(ct->port_res);
|
||||
ct->sc_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);
|
||||
}
|
||||
|
||||
irq_rid = 0;
|
||||
ct->irq_res = bus_alloc_resource(dev, SYS_RES_IRQ, &irq_rid, 0, ~0,
|
||||
1, RF_ACTIVE);
|
||||
drq_rid = 0;
|
||||
ct->drq_res = bus_alloc_resource(dev, SYS_RES_DRQ, &drq_rid, 0, ~0,
|
||||
1, RF_ACTIVE);
|
||||
if (ct->irq_res == NULL || ct->drq_res == NULL) {
|
||||
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,
|
||||
NULL, NULL, MAXBSIZE, 1,
|
||||
BUS_SPACE_MAXSIZE_32BIT,
|
||||
BUS_DMA_ALLOCNOW, &ct->sc_dmat) != 0) {
|
||||
device_printf(dev, "can't set up ISA DMA map\n");
|
||||
ct_space_unmap(dev, ct);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
if (bus_dmamem_alloc(ct->sc_dmat, (void **)&vaddr, BUS_DMA_NOWAIT,
|
||||
&ct->sc_dmamapt) != 0) {
|
||||
device_printf(dev, "can't set up ISA DMA map\n");
|
||||
ct_space_unmap(dev, ct);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
bus_dmamap_load(ct->sc_dmat, ct->sc_dmamapt, vaddr, MAXBSIZE,
|
||||
ct_dmamap, &addr, 0);
|
||||
|
||||
/* setup machdep softc */
|
||||
bs->sc_hw = hw;
|
||||
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);
|
||||
|
||||
/* setup ct driver softc */
|
||||
ct->ct_hw = bs;
|
||||
ct->ct_dma_xfer_start = bshw_dma_xfer_start;
|
||||
ct->ct_pio_xfer_start = bshw_smit_xfer_start;
|
||||
ct->ct_dma_xfer_stop = bshw_dma_xfer_stop;
|
||||
ct->ct_pio_xfer_stop = bshw_smit_xfer_stop;
|
||||
ct->ct_bus_reset = bshw_bus_reset;
|
||||
ct->ct_synch_setup = bshw_synch_setup;
|
||||
|
||||
ct->sc_xmode = CT_XMODE_DMA;
|
||||
if (ct->sc_memh != NULL)
|
||||
ct->sc_xmode |= CT_XMODE_PIO;
|
||||
ct->sc_chiprev = CT_WD33C93_B;
|
||||
ct->sc_chipclk = BSHW_DEFAULT_CHIPCLK;
|
||||
|
||||
slp->sl_dev = dev;
|
||||
slp->sl_hostid = bs->sc_hostid;
|
||||
slp->sl_irq = isa_get_irq(dev);
|
||||
slp->sl_cfgflags = device_get_flags(dev);
|
||||
|
||||
ctattachsubr(ct);
|
||||
|
||||
if (bus_setup_intr(dev, ct->irq_res, INTR_TYPE_CAM,
|
||||
(driver_intr_t *)ctintr, ct, &ct->sc_ih)) {
|
||||
ct_space_unmap(dev, ct);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct bshw *
|
||||
ct_find_hw(device_t dev)
|
||||
{
|
||||
return DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(device_get_flags(dev)));
|
||||
}
|
||||
|
||||
static int
|
||||
ct_space_map(device_t dev, struct bshw *hw,
|
||||
struct resource **iohp, struct resource **memhp)
|
||||
{
|
||||
int port_rid, mem_rid;
|
||||
|
||||
*memhp = NULL;
|
||||
|
||||
port_rid = 0;
|
||||
*iohp = bus_alloc_resource(dev, SYS_RES_IOPORT, &port_rid, 0, ~0,
|
||||
BSHW_IOSZ, RF_ACTIVE);
|
||||
if (*iohp == NULL)
|
||||
return ENXIO;
|
||||
|
||||
if ((hw->hw_flags & BSHW_SMFIFO) == 0 || isa_get_maddr(dev) == -1)
|
||||
return 0;
|
||||
|
||||
mem_rid = 0;
|
||||
*memhp = bus_alloc_resource(dev, SYS_RES_MEMORY, &mem_rid, 0, ~0,
|
||||
BSHW_MEMSZ, RF_ACTIVE);
|
||||
if (*memhp == NULL) {
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, port_rid, *iohp);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ct_space_unmap(device_t dev, struct ct_softc *ct)
|
||||
{
|
||||
if (ct->port_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IOPORT, 0, ct->port_res);
|
||||
if (ct->mem_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_MEMORY, 0, ct->mem_res);
|
||||
if (ct->irq_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_IRQ, 0, ct->irq_res);
|
||||
if (ct->drq_res != NULL)
|
||||
bus_release_resource(dev, SYS_RES_DRQ, 0, ct->drq_res);
|
||||
}
|
||||
|
||||
static void
|
||||
ct_dmamap(void *arg, bus_dma_segment_t *seg, int nseg, int error)
|
||||
{
|
||||
bus_addr_t *addr = (bus_addr_t *)arg;
|
||||
|
||||
*addr = seg->ds_addr;
|
||||
}
|
155
sys/dev/ct/ct_machdep.h
Normal file
155
sys/dev/ct/ct_machdep.h
Normal file
@ -0,0 +1,155 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: ct_machdep.h,v 1.4 1999/07/23 20:54:00 honda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
* Naofumi HONDA. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _CT_MACHDEP_H_
|
||||
#define _CT_MACHDEP_H_
|
||||
|
||||
/*
|
||||
* Principal rules:
|
||||
* 1) do not use bus_space_write/read_X directly in ct.c.
|
||||
* 2) do not use port offset defs directly in ct.c.
|
||||
*/
|
||||
|
||||
/* special weight if requried */
|
||||
#define CT_BUS_WEIGHT
|
||||
|
||||
/* port offset */
|
||||
#define addr_port 0
|
||||
#define stat_port 0
|
||||
#define ctrl_port 2
|
||||
#define cmd_port 4
|
||||
|
||||
/*
|
||||
* 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));
|
||||
|
||||
#define ct_stat_read_1(bst, bsh) bus_space_read_1((bst), (bsh), stat_port)
|
||||
|
||||
static __inline void
|
||||
cthw_set_count(bst, bsh, count)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
u_int count;
|
||||
{
|
||||
|
||||
bus_space_write_1(bst, bsh, addr_port, wd3s_cnt);
|
||||
CT_BUS_WEIGHT
|
||||
bus_space_write_1(bst, bsh, ctrl_port, count >> 16);
|
||||
CT_BUS_WEIGHT
|
||||
bus_space_write_1(bst, bsh, ctrl_port, count >> 8);
|
||||
CT_BUS_WEIGHT
|
||||
bus_space_write_1(bst, bsh, ctrl_port, count);
|
||||
CT_BUS_WEIGHT
|
||||
}
|
||||
|
||||
static __inline u_int
|
||||
cthw_get_count(bst, bsh)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
{
|
||||
u_int count;
|
||||
|
||||
bus_space_write_1(bst, bsh, addr_port, wd3s_cnt);
|
||||
CT_BUS_WEIGHT
|
||||
count = (((u_int) bus_space_read_1(bst, bsh, ctrl_port)) << 16);
|
||||
CT_BUS_WEIGHT
|
||||
count += (((u_int) bus_space_read_1(bst, bsh, ctrl_port)) << 8);
|
||||
CT_BUS_WEIGHT
|
||||
count += ((u_int) bus_space_read_1(bst, bsh, ctrl_port));
|
||||
CT_BUS_WEIGHT
|
||||
return count;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ct_write_cmds(bst, bsh, cmd, len)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
u_int8_t *cmd;
|
||||
int len;
|
||||
{
|
||||
int i;
|
||||
|
||||
bus_space_write_1(bst, bsh, addr_port, wd3s_cdb);
|
||||
for (i = 0; i < len; i ++)
|
||||
bus_space_write_1(bst, bsh, ctrl_port, cmd[i]);
|
||||
}
|
||||
|
||||
static __inline u_int8_t
|
||||
ct_cr_read_1(bst, bsh, offs)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_addr_t offs;
|
||||
{
|
||||
u_int8_t regv;
|
||||
|
||||
bus_space_write_1(bst, bsh, addr_port, offs);
|
||||
CT_BUS_WEIGHT
|
||||
regv = bus_space_read_1(bst, bsh, ctrl_port);
|
||||
CT_BUS_WEIGHT
|
||||
return regv;
|
||||
}
|
||||
|
||||
static __inline void
|
||||
ct_cr_write_1(bst, bsh, offs, val)
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
bus_addr_t offs;
|
||||
u_int8_t val;
|
||||
{
|
||||
|
||||
bus_space_write_1(bst, bsh, addr_port, offs);
|
||||
CT_BUS_WEIGHT
|
||||
bus_space_write_1(bst, bsh, ctrl_port, val);
|
||||
CT_BUS_WEIGHT
|
||||
}
|
||||
|
||||
#if defined(i386)
|
||||
#define SOFT_INTR_REQUIRED(slp) (softintr((slp)->sl_irq))
|
||||
#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_ */
|
127
sys/dev/ct/ctvar.h
Normal file
127
sys/dev/ct/ctvar.h
Normal file
@ -0,0 +1,127 @@
|
||||
/* $FreeBSD$ */
|
||||
/* $NecBSD: ctvar.h,v 1.4 1999/04/15 01:36:13 kmatsuda Exp $ */
|
||||
/* $NetBSD$ */
|
||||
|
||||
/*
|
||||
* [NetBSD for NEC PC-98 series]
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
* NetBSD/pc98 porting staff. All rights reserved.
|
||||
* Copyright (c) 1995, 1996, 1997, 1998
|
||||
* Naofumi HONDA. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _CTVAR_H_
|
||||
#define _CTVAR_H_
|
||||
/*
|
||||
* ctvar.h
|
||||
* Generic wd33c93 chip driver's definitions
|
||||
*/
|
||||
|
||||
/*****************************************************************
|
||||
* Host adapter structure
|
||||
*****************************************************************/
|
||||
struct ct_softc {
|
||||
struct scsi_low_softc sc_sclow; /* generic data */
|
||||
|
||||
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 */
|
||||
|
||||
int sc_chiprev; /* chip version */
|
||||
#define CT_WD33C93_A 0x00000
|
||||
#define CT_WD33C93_B 0x10000
|
||||
#define CT_WD33C93_C 0x20000
|
||||
|
||||
int sc_xmode;
|
||||
#define CT_XMODE_PIO 1
|
||||
#define CT_XMODE_DMA 2
|
||||
|
||||
int sc_dma; /* dma transfer start */
|
||||
#define CT_DMA_PIOSTART 1
|
||||
#define CT_DMA_DMASTART 2
|
||||
|
||||
int sc_satgo; /* combination cmd start */
|
||||
#define CT_SAT_GOING 1
|
||||
|
||||
int sc_atten; /* attention */
|
||||
u_int8_t sc_creg; /* control register value */
|
||||
|
||||
int sc_chipclk; /* chipclk 0, 10, 15, 20 */
|
||||
struct ct_synch_data {
|
||||
u_int cs_period;
|
||||
u_int cs_syncr;
|
||||
} *sc_sdp; /* synchronous data table pt */
|
||||
|
||||
/*
|
||||
* 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 *));
|
||||
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 *));
|
||||
};
|
||||
|
||||
/*****************************************************************
|
||||
* Target information
|
||||
*****************************************************************/
|
||||
struct ct_targ_info {
|
||||
struct targ_info cti_ti;
|
||||
|
||||
u_int8_t cti_syncreg;
|
||||
};
|
||||
|
||||
/*****************************************************************
|
||||
* 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));
|
||||
void ctattachsubr __P((struct ct_softc *));
|
||||
int ctprint __P((void *, const char *));
|
||||
int ctintr __P((void *));
|
||||
#endif /* !_CTVAR_H_ */
|
@ -87,11 +87,10 @@ device isp # Qlogic family
|
||||
#device ncr # NCR/Symbios Logic
|
||||
device sym # NCR/Symbios Logic (newer chipsets + those of `ncr')
|
||||
|
||||
# WD33C93 SCSI card (55/92 like board)
|
||||
options BS_TARG_SAFEMODE
|
||||
device bs 1
|
||||
|
||||
device aic # PC-9801-100
|
||||
options BS_TARG_SAFEMODE
|
||||
device bs 1 # WD33C93 SCSI card (55/92 like board)
|
||||
#device ct # host adapter using WD33C93[ABC] chip (C bus)
|
||||
|
||||
device ncv # NCR 53C500
|
||||
device nsp # Workbit Ninja SCSI-3
|
||||
|
@ -24,6 +24,12 @@ hint.wd.0.drive="0"
|
||||
#hint.wd.3.at="wdc0"
|
||||
#hint.wd.3.drive="3"
|
||||
|
||||
# PC-9801-100
|
||||
hint.aic.0.at="isa"
|
||||
hint.aic.0.port="0x1840"
|
||||
hint.aic.0.irq="5"
|
||||
hint.aic.0.flags="0x10000"
|
||||
|
||||
# PC-9801-92
|
||||
hint.bs.0.at="isa"
|
||||
hint.bs.0.port="0xCC0"
|
||||
@ -63,11 +69,24 @@ hint.bs.0.flags="0"
|
||||
#hint.bs.0.drq="3"
|
||||
#hint.bs.0.flags="0x50000"
|
||||
|
||||
# PC-9801-100
|
||||
hint.aic.0.at="isa"
|
||||
hint.aic.0.port="0x1840"
|
||||
hint.aic.0.irq="5"
|
||||
hint.aic.0.flags="0x10000"
|
||||
# GENERIC
|
||||
hint.ct.0.at="isa"
|
||||
# SC98
|
||||
#hint.ct.0.at="isa"
|
||||
#hint.ct.0.flags="0x10000"
|
||||
# TEXA
|
||||
#hint.ct.0.at="isa"
|
||||
#hint.ct.0.flags="0x20000"
|
||||
# ELECOM
|
||||
#hint.ct.0.at="isa"
|
||||
#hint.ct.0.flags="0x30000"
|
||||
# SMIT
|
||||
#hint.ct.0.at="isa"
|
||||
#hint.ct.0.maddr="0xdc000"
|
||||
#hint.ct.0.flags="0x40000"
|
||||
# LOGITEC
|
||||
#hint.ct.0.at="isa"
|
||||
#hint.ct.0.flags="0x50000"
|
||||
|
||||
hint.pckbd.0.at="isa"
|
||||
hint.pckbd.0.port="0x041"
|
||||
|
Loading…
x
Reference in New Issue
Block a user