Replace sbic driver (WD33C93 SCSI card driver) with new bs driver.
Submitted by: The FreeBSD(98) Development Team Obtained from: NetBSD/pc98 based on NetBSD 1.2
This commit is contained in:
parent
f48465862b
commit
778128e3f9
1622
sys/i386/isa/bs/bs.c
Normal file
1622
sys/i386/isa/bs/bs.c
Normal file
File diff suppressed because it is too large
Load Diff
60
sys/i386/isa/bs/bs_isa.c
Normal file
60
sys/i386/isa/bs/bs_isa.c
Normal file
@ -0,0 +1,60 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1995, 1996 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.
|
||||
*/
|
||||
|
||||
#include <dev/isa/bs/bsif.h>
|
||||
|
||||
static int bs_isa_probe __P((struct device *, void *, void *));
|
||||
static void bs_isa_attach __P((struct device *, struct device *, void *));
|
||||
|
||||
struct cfattach bs_isa_ca = {
|
||||
sizeof(struct bs_softc), bs_isa_probe, bs_isa_attach
|
||||
};
|
||||
|
||||
static int
|
||||
bs_isa_probe(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct isa_attach_args *ia = aux;
|
||||
|
||||
ia->ia_irq = IRQUNK;
|
||||
ia->ia_drq = DRQUNK;
|
||||
|
||||
return bsprobe(parent, match, aux);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_isa_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
|
||||
bsattach(parent, self, aux);
|
||||
}
|
126
sys/i386/isa/bs/bs_pisa.c
Normal file
126
sys/i386/isa/bs/bs_pisa.c
Normal file
@ -0,0 +1,126 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1995, 1996 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.
|
||||
*/
|
||||
|
||||
#include <dev/isa/bs/bsif.h>
|
||||
|
||||
static int bs_pisa_probe __P((struct device *, void *, void *));
|
||||
static void bs_pisa_attach __P((struct device *, struct device *, void *));
|
||||
static int bs_deactivate __P((pisa_device_args_t));
|
||||
static int bs_activate __P((pisa_device_args_t));
|
||||
|
||||
struct cfattach bs_pisa_ca = {
|
||||
sizeof(struct bs_softc), bs_pisa_probe, bs_pisa_attach
|
||||
};
|
||||
|
||||
struct pisa_driver bs_pd = {
|
||||
bs_activate, bs_deactivate,
|
||||
};
|
||||
|
||||
static int
|
||||
bs_pisa_probe(parent, match, aux)
|
||||
struct device *parent;
|
||||
void *match, *aux;
|
||||
{
|
||||
struct bs_softc *sc = match;
|
||||
struct pisa_attach_args *pa = aux;
|
||||
struct isa_attach_args *ia = &pa->pa_ia;
|
||||
|
||||
if (ia->ia_iobase == IOBASEUNK ||
|
||||
ia->ia_irq == IRQUNK || ia->ia_drq == DRQUNK)
|
||||
return 0;
|
||||
|
||||
sc->sc_pdv = pa->pa_pdv;
|
||||
|
||||
return bsprobe(parent, match, ia);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_pisa_attach(parent, self, aux)
|
||||
struct device *parent, *self;
|
||||
void *aux;
|
||||
{
|
||||
struct bs_softc *sc = (void *) self;
|
||||
struct pisa_attach_args *pa = aux;
|
||||
|
||||
sc->sc_pdv = PISAMSG_BIND(pa->pa_pdv, sc, &bs_pd);
|
||||
|
||||
bsattach(parent, self, (void *) &pa->pa_ia);
|
||||
|
||||
PISA_INTR_REGISTER(sc->sc_pdv, sc->sc_ih);
|
||||
}
|
||||
|
||||
static int
|
||||
bs_deactivate(arg)
|
||||
pisa_device_args_t arg;
|
||||
{
|
||||
struct bs_softc *bsc = arg->id;
|
||||
|
||||
bsc->sc_flags |= BSINACTIVE;
|
||||
bs_terminate_timeout(bsc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define SCSIBUS_RESCAN
|
||||
|
||||
static int
|
||||
bs_activate(arg)
|
||||
pisa_device_args_t arg;
|
||||
{
|
||||
struct bs_softc *bsc = arg->id;
|
||||
struct isa_attach_args *ia = arg->ia;
|
||||
struct targ_info *ti;
|
||||
int i;
|
||||
|
||||
bsc->sc_irqmasks = (1 << ia->ia_irq);
|
||||
|
||||
while((ti = bsc->sc_titab.tqh_first) != NULL)
|
||||
TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
|
||||
|
||||
bsc->sc_openf = 0;
|
||||
for (i = 0; i < NTARGETS; i ++)
|
||||
if (i != bsc->sc_hostid && (ti = bsc->sc_ti[i]) != NULL)
|
||||
{
|
||||
TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
|
||||
bsc->sc_openf |= (1 << i);
|
||||
}
|
||||
|
||||
bsc->sc_hstate = BSC_BOOTUP;
|
||||
bsc->sc_flags &= ~BSINACTIVE;
|
||||
bs_reset_nexus(bsc);
|
||||
|
||||
#ifdef SCSIBUS_RESCAN
|
||||
if (bsc->sc_nexus == NULL)
|
||||
scsi_probe_busses((int) bsc->sc_link.scsibus, -1, -1);
|
||||
#endif
|
||||
|
||||
bs_start_timeout(bsc);
|
||||
return 0;
|
||||
}
|
926
sys/i386/isa/bs/bsfunc.c
Normal file
926
sys/i386/isa/bs/bsfunc.c
Normal file
@ -0,0 +1,926 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <dev/isa/bs/bsif.h>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <i386/isa/bs/bsif.h>
|
||||
#endif
|
||||
|
||||
#ifdef BS_STATICS
|
||||
struct bs_statics bs_statics[NTARGETS];
|
||||
u_int bs_linkcmd_count[NTARGETS];
|
||||
u_int bs_bounce_used[NTARGETS];
|
||||
#endif /* BS_STATICS */
|
||||
|
||||
#ifdef BS_DEBUG
|
||||
int bs_debug_flag = 0;
|
||||
#endif /* BS_DEBUG */
|
||||
|
||||
static void bs_print_syncmsg __P((struct targ_info *, char*));
|
||||
static void bs_timeout_target __P((struct targ_info *));
|
||||
static void bs_kill_msg __P((struct ccb *cb));
|
||||
|
||||
static int bs_start_target __P((struct targ_info *));
|
||||
static int bs_check_target __P((struct targ_info *));
|
||||
|
||||
/*************************************************************
|
||||
* CCB
|
||||
************************************************************/
|
||||
GENERIC_CCB_STATIC_ALLOC(bs, ccb)
|
||||
GENERIC_CCB(bs, ccb, ccb_chain)
|
||||
|
||||
/*************************************************************
|
||||
* TIMEOUT
|
||||
************************************************************/
|
||||
static void
|
||||
bs_timeout_target(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
|
||||
ti->ti_error |= BSTIMEOUT;
|
||||
bsc->sc_flags |= BSRESET;
|
||||
|
||||
if (ti->ti_herrcnt ++ >= HARDRETRIES)
|
||||
{
|
||||
bs_printf(ti, "timeout", "async transfer!");
|
||||
ti->ti_syncmax.period = ti->ti_syncmax.offset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bstimeout(arg)
|
||||
void *arg;
|
||||
{
|
||||
struct bs_softc *bsc = (struct bs_softc *) arg;
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
int s;
|
||||
|
||||
s = splbio();
|
||||
bsc->sc_flags &= ~BSSTARTTIMEOUT;
|
||||
|
||||
/* check */
|
||||
if ((ti = bsc->sc_nexus) && (cb = ti->ti_ctab.tqh_first))
|
||||
{
|
||||
if ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0)
|
||||
bs_timeout_target(ti);
|
||||
}
|
||||
else for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
|
||||
{
|
||||
if (bsc->sc_dtgnum && ti->ti_phase < DISCONNECTED)
|
||||
continue;
|
||||
|
||||
cb = ti->ti_ctab.tqh_first;
|
||||
if (cb && ((cb->tc -= BS_TIMEOUT_CHECK_INTERVAL) < 0))
|
||||
bs_timeout_target(ti);
|
||||
}
|
||||
|
||||
/* try to recover */
|
||||
if (bsc->sc_flags & BSRESET)
|
||||
{
|
||||
bs_debug_print_all(bsc);
|
||||
bs_printf(ti, "timeout", "bus hang up");
|
||||
bs_reset_nexus(bsc);
|
||||
}
|
||||
|
||||
bs_start_timeout(bsc);
|
||||
splx(s);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* MAKE CCB & MSG CCB
|
||||
*************************************************/
|
||||
static u_int8_t cmd_unit_ready[6];
|
||||
|
||||
struct ccb *
|
||||
bs_make_internal_ccb(ti, lun, cmd, cmdlen, data, datalen, flags, timeout)
|
||||
struct targ_info *ti;
|
||||
u_int lun;
|
||||
u_int8_t *cmd;
|
||||
u_int cmdlen;
|
||||
u_int8_t *data;
|
||||
u_int datalen;
|
||||
u_int flags;
|
||||
int timeout;
|
||||
{
|
||||
struct ccb *cb;
|
||||
|
||||
if ((cb = bs_get_ccb(XSBS_SCSI_NOSLEEP)) == NULL)
|
||||
bs_panic(ti->ti_bsc, "can not get ccb mem");
|
||||
|
||||
cb->xs = NULL;
|
||||
cb->lun = lun;
|
||||
cb->cmd = (cmd ? cmd : cmd_unit_ready);
|
||||
cb->cmdlen = (cmd ? cmdlen : sizeof(cmd_unit_ready));
|
||||
cb->data = data;
|
||||
cb->datalen = (data ? datalen : 0);
|
||||
cb->msgoutlen = 0;
|
||||
cb->flags = flags & BSCFLAGSMASK;
|
||||
bs_targ_flags(ti, cb);
|
||||
cb->rcnt = 0;
|
||||
cb->tcmax = (timeout > BS_DEFAULT_TIMEOUT_SECOND ? timeout :
|
||||
BS_DEFAULT_TIMEOUT_SECOND);
|
||||
|
||||
TAILQ_INSERT_HEAD(&ti->ti_ctab, cb, ccb_chain);
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
struct ccb *
|
||||
bs_make_msg_ccb(ti, lun, cb, msg, timex)
|
||||
struct targ_info *ti;
|
||||
u_int lun;
|
||||
struct ccb *cb;
|
||||
struct msgbase *msg;
|
||||
u_int timex;
|
||||
{
|
||||
u_int flags;
|
||||
|
||||
flags = BSFORCEIOPOLL | msg->flag;
|
||||
if (cb == NULL)
|
||||
cb = bs_make_internal_ccb(ti, lun, NULL, 0, NULL, 0,
|
||||
flags, timex);
|
||||
else
|
||||
cb->flags |= flags & BSCFLAGSMASK;
|
||||
|
||||
cb->msgoutlen = msg->msglen;
|
||||
bcopy(msg->msg, cb->msgout, msg->msglen);
|
||||
return cb;
|
||||
}
|
||||
|
||||
int
|
||||
bs_send_msg(ti, lun, msg, timex)
|
||||
struct targ_info *ti;
|
||||
u_int lun;
|
||||
struct msgbase *msg;
|
||||
int timex;
|
||||
{
|
||||
struct ccb *cb;
|
||||
|
||||
cb = bs_make_msg_ccb(ti, lun, NULL, msg, timex);
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
return bs_scsi_cmd_poll(ti, cb);
|
||||
}
|
||||
|
||||
static void
|
||||
bs_kill_msg(cb)
|
||||
struct ccb *cb;
|
||||
{
|
||||
cb->msgoutlen = 0;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* MAKE SENSE CCB
|
||||
**************************************************/
|
||||
struct ccb *
|
||||
bs_request_sense(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct ccb *cb;
|
||||
|
||||
bzero(ti->scsi_cmd, sizeof(struct scsi_sense));
|
||||
bzero(&ti->sense, sizeof(struct scsi_sense_data));
|
||||
ti->scsi_cmd[0] = REQUEST_SENSE;
|
||||
ti->scsi_cmd[1] = (ti->ti_lun << 5);
|
||||
ti->scsi_cmd[4] = sizeof(struct scsi_sense_data);
|
||||
cb = bs_make_internal_ccb(ti, ti->ti_lun, ti->scsi_cmd,
|
||||
sizeof(struct scsi_sense),
|
||||
(u_int8_t *) & ti->sense,
|
||||
sizeof(struct scsi_sense_data),
|
||||
BSFORCEIOPOLL,
|
||||
BS_DEFAULT_TIMEOUT_SECOND);
|
||||
cb->flags |= BSSENSECCB;
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* SYNC MSG
|
||||
*************************************************/
|
||||
/* sync neg */
|
||||
int
|
||||
bs_start_syncmsg(ti, cb, flag)
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
int flag;
|
||||
{
|
||||
struct syncdata *negp, *maxp;
|
||||
struct msgbase msg;
|
||||
u_int lun;
|
||||
|
||||
negp = &ti->ti_syncnow;
|
||||
maxp = &ti->ti_syncmax;
|
||||
|
||||
ti->ti_state = BS_TARG_SYNCH;
|
||||
|
||||
if (flag == BS_SYNCMSG_REQUESTED)
|
||||
{
|
||||
if (negp->offset > maxp->offset)
|
||||
negp->offset = maxp->offset;
|
||||
if (negp->offset != 0 && negp->period < maxp->period)
|
||||
negp->period = maxp->period;
|
||||
|
||||
msg.flag = 0;
|
||||
lun = ti->ti_lun;
|
||||
if (cb == NULL)
|
||||
cb = ti->ti_ctab.tqh_first;
|
||||
}
|
||||
else if (ti->ti_cfgflags & BS_SCSI_SYNC)
|
||||
{
|
||||
negp->offset = maxp->offset;
|
||||
negp->period = maxp->period;
|
||||
|
||||
msg.flag = BSERROROK;
|
||||
lun = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ti->ti_state = BS_TARG_RDY;
|
||||
return COMPLETE;
|
||||
}
|
||||
|
||||
BS_SETUP_SYNCSTATE(flag);
|
||||
msg.msg[0] = MSG_EXTEND;
|
||||
msg.msg[1] = MSG_EXTEND_SYNCHLEN;
|
||||
msg.msg[2] = MSG_EXTEND_SYNCHCODE;
|
||||
msg.msg[3] = negp->period;
|
||||
msg.msg[4] = negp->offset;
|
||||
msg.msglen = MSG_EXTEND_SYNCHLEN + 2;
|
||||
|
||||
bs_make_msg_ccb(ti, lun, cb, &msg, BS_SYNC_TIMEOUT);
|
||||
return COMPLETE;
|
||||
}
|
||||
|
||||
static void
|
||||
bs_print_syncmsg(ti, s)
|
||||
struct targ_info *ti;
|
||||
char *s;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct syncdata *negp;
|
||||
u_int speed;
|
||||
|
||||
negp = &ti->ti_syncnow;
|
||||
speed = (negp->offset && negp->period) ?
|
||||
(2500 / ((u_int) negp->period)) : 0;
|
||||
|
||||
printf("%s(%d:%d): <%s> ", bsc->sc_dvname, ti->ti_id, ti->ti_lun, s);
|
||||
printf("period 0x%x offset %d chip (0x%x)", negp->period, negp->offset,
|
||||
ti->ti_sync);
|
||||
if (speed)
|
||||
printf(" %d.%d M/s", speed / 10, speed % 10);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
int
|
||||
bs_analyze_syncmsg(ti, cb)
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
u_int8_t ans = ti->ti_syncnow.state;
|
||||
struct syncdata *negp, *maxp;
|
||||
struct syncdata bdata;
|
||||
char *s = NULL;
|
||||
u_int8_t period;
|
||||
|
||||
negp = &ti->ti_syncnow;
|
||||
bdata = *negp;
|
||||
maxp = &ti->ti_syncmax;
|
||||
|
||||
switch(ans)
|
||||
{
|
||||
case BS_SYNCMSG_REJECT:
|
||||
period = 0;
|
||||
s = "msg reject";
|
||||
break;
|
||||
|
||||
case BS_SYNCMSG_ASSERT:
|
||||
period = 0;
|
||||
s = "no msg";
|
||||
break;
|
||||
|
||||
default:
|
||||
if (negp->offset != 0 && negp->period < maxp->period)
|
||||
{
|
||||
period = 0xff;
|
||||
s = "illegal(period)";
|
||||
}
|
||||
else if (negp->offset > maxp->offset)
|
||||
{
|
||||
period = 0xff;
|
||||
s = "illegal(offset)";
|
||||
}
|
||||
else
|
||||
period = negp->offset ? negp->period : 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (s == NULL)
|
||||
{
|
||||
bshw_adj_syncdata(negp);
|
||||
*maxp = *negp;
|
||||
|
||||
if (ans == BS_SYNCMSG_REQUESTED)
|
||||
s = "requested";
|
||||
else
|
||||
s = negp->offset ? "synchronous" : "async";
|
||||
}
|
||||
else
|
||||
{
|
||||
negp->offset = maxp->offset = 0;
|
||||
bshw_adj_syncdata(negp);
|
||||
bshw_adj_syncdata(maxp);
|
||||
}
|
||||
|
||||
/* really setup hardware */
|
||||
bshw_set_synchronous(bsc, ti);
|
||||
if (cb == NULL || (period >= negp->period && period <= negp->period + 2))
|
||||
{
|
||||
bs_print_syncmsg(ti, s);
|
||||
BS_SETUP_TARGSTATE(BS_TARG_RDY);
|
||||
BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
|
||||
if (cb)
|
||||
bs_kill_msg(cb);
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
bs_printf(ti, "bs_analyze_syncmsg",
|
||||
"sync(period) mismatch, retry neg...");
|
||||
printf("expect(%d:0x%x) => reply(%d:0x%x)\n",
|
||||
bdata.offset, bdata.period, negp->offset, negp->period);
|
||||
|
||||
bs_start_syncmsg(ti, cb, BS_SYNCMSG_ASSERT);
|
||||
return EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* ABORT AND RESET MSG
|
||||
**************************************************/
|
||||
/* send device reset msg and wait */
|
||||
void
|
||||
bs_reset_device(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct msgbase msg;
|
||||
|
||||
msg.msglen = 1;
|
||||
msg.msg[0] = MSG_RESET;
|
||||
msg.flag = 0;
|
||||
|
||||
bs_send_msg(ti, 0, &msg, 0);
|
||||
|
||||
delay(ti->ti_bsc->sc_RSTdelay);
|
||||
bs_check_target(ti);
|
||||
}
|
||||
|
||||
/* send abort msg */
|
||||
struct ccb *
|
||||
bs_force_abort(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct msgbase msg;
|
||||
struct ccb *cb = ti->ti_ctab.tqh_first;
|
||||
u_int lun;
|
||||
|
||||
if (cb)
|
||||
{
|
||||
lun = cb->lun;
|
||||
cb->rcnt++;
|
||||
}
|
||||
else
|
||||
lun = 0;
|
||||
|
||||
msg.msglen = 1;
|
||||
msg.msg[0] = MSG_ABORT;
|
||||
msg.flag = 0;
|
||||
|
||||
cb = bs_make_msg_ccb(ti, lun, NULL, &msg, 0);
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
|
||||
if (bsc->sc_nexus == ti)
|
||||
BS_LOAD_SDP
|
||||
|
||||
return cb;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* COMPLETE SCSI BUS RESET
|
||||
*************************************************/
|
||||
/*
|
||||
* XXX:
|
||||
* 1) reset scsi bus (ie. all target reseted).
|
||||
* 2) chip reset.
|
||||
* 3) check target status.
|
||||
* 4) sync neg with all targets.
|
||||
* 5) setup sync reg in host.
|
||||
* 6) recover previous nexus.
|
||||
*/
|
||||
void
|
||||
bs_scsibus_start(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
struct targ_info *ti, *nextti = NULL;
|
||||
struct ccb *cb;
|
||||
int error = HASERROR;
|
||||
u_int querm, bits, skip = 0;
|
||||
|
||||
querm = (bsc->sc_hstate == BSC_BOOTUP);
|
||||
bsc->sc_hstate = BSC_TARG_CHECK;
|
||||
|
||||
/* target check */
|
||||
do
|
||||
{
|
||||
if (error != COMPLETE)
|
||||
{
|
||||
printf("%s: scsi bus reset and try to restart ...",
|
||||
bsc->sc_dvname);
|
||||
bshw_smitabort(bsc);
|
||||
bshw_dmaabort(bsc, NULL);
|
||||
bshw_chip_reset(bsc);
|
||||
bshw_bus_reset(bsc);
|
||||
bshw_chip_reset(bsc);
|
||||
printf(" done. scsi bus ready.\n");
|
||||
nextti = bsc->sc_titab.tqh_first;
|
||||
error = COMPLETE;
|
||||
}
|
||||
|
||||
if ((ti = nextti) == NULL)
|
||||
break;
|
||||
nextti = ti->ti_tchain.tqe_next;
|
||||
|
||||
bits = (1 << ti->ti_id);
|
||||
if (skip & bits)
|
||||
continue;
|
||||
|
||||
if ((error = bs_check_target(ti)) != COMPLETE)
|
||||
{
|
||||
if (querm)
|
||||
{
|
||||
TAILQ_REMOVE(&bsc->sc_titab, ti, ti_tchain);
|
||||
bsc->sc_openf &= ~bits;
|
||||
}
|
||||
|
||||
if (error == NOTARGET)
|
||||
error = COMPLETE;
|
||||
|
||||
skip |= bits;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
|
||||
/* ok now ready */
|
||||
bsc->sc_hstate = BSC_RDY;
|
||||
|
||||
/* recover */
|
||||
for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
|
||||
{
|
||||
ti->ti_ctab = ti->ti_bctab;
|
||||
TAILQ_INIT(&ti->ti_bctab);
|
||||
if (ti->ti_ctab.tqh_first)
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bs_reset_nexus(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
|
||||
bsc->sc_flags &= ~(BSRESET | BSUNDERRESET);
|
||||
if (bsc->sc_poll)
|
||||
{
|
||||
bsc->sc_flags |= BSUNDERRESET;
|
||||
return;
|
||||
}
|
||||
|
||||
/* host state clear */
|
||||
BS_HOST_TERMINATE
|
||||
BS_SETUP_MSGPHASE(FREE)
|
||||
bsc->sc_dtgnum = 0;
|
||||
|
||||
/* target state clear */
|
||||
for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
|
||||
{
|
||||
if (ti->ti_state == BS_TARG_SYNCH)
|
||||
bs_analyze_syncmsg(ti, NULL);
|
||||
if (ti->ti_state > BS_TARG_START)
|
||||
BS_SETUP_TARGSTATE(BS_TARG_START);
|
||||
|
||||
BS_SETUP_PHASE(UNDEF)
|
||||
bs_hostque_delete(bsc, ti);
|
||||
if (cb = ti->ti_ctab.tqh_first)
|
||||
{
|
||||
if (bsc->sc_hstate == BSC_TARG_CHECK)
|
||||
{
|
||||
ti->ti_error |= BSFATALIO;
|
||||
bscmddone(ti);
|
||||
}
|
||||
else if (cb->rcnt >= bsc->sc_retry)
|
||||
{
|
||||
ti->ti_error |= BSABNORMAL;
|
||||
bscmddone(ti);
|
||||
}
|
||||
else if (ti->ti_error)
|
||||
cb->rcnt++;
|
||||
}
|
||||
|
||||
/* target state clear */
|
||||
BS_SETUP_PHASE(FREE)
|
||||
BS_SETUP_SYNCSTATE(BS_SYNCMSG_NULL);
|
||||
ti->ti_flags &= ~BSCFLAGSMASK;
|
||||
ti->ti_msgout = 0;
|
||||
#ifdef BS_DIAG
|
||||
ti->ti_flags &= ~BSNEXUS;
|
||||
#endif /* BS_DIAG */
|
||||
|
||||
for ( ; cb; cb = cb->ccb_chain.tqe_next)
|
||||
{
|
||||
bs_kill_msg(cb);
|
||||
cb->flags &= ~(BSITSDONE | BSCASTAT);
|
||||
cb->error = 0;
|
||||
}
|
||||
|
||||
if (bsc->sc_hstate != BSC_TARG_CHECK &&
|
||||
ti->ti_bctab.tqh_first == NULL)
|
||||
ti->ti_bctab = ti->ti_ctab;
|
||||
|
||||
TAILQ_INIT(&ti->ti_ctab);
|
||||
}
|
||||
|
||||
if (bsc->sc_hstate != BSC_TARG_CHECK)
|
||||
bs_scsibus_start(bsc);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* CHECK TARGETS AND START TARGETS
|
||||
*************************************************/
|
||||
static int
|
||||
bs_start_target(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct ccb *cb;
|
||||
struct scsi_start_stop cmd;
|
||||
|
||||
bzero(&cmd, sizeof(struct scsi_start_stop));
|
||||
#ifdef __NetBSD__
|
||||
cmd.opcode = START_STOP;
|
||||
#else
|
||||
cmd.op_code = START_STOP;
|
||||
#endif
|
||||
cmd.how = SSS_START;
|
||||
ti->ti_lun = 0;
|
||||
cb = bs_make_internal_ccb(ti, 0, (u_int8_t *) &cmd,
|
||||
sizeof(struct scsi_start_stop),
|
||||
NULL, 0, BSFORCEIOPOLL, BS_MOTOR_TIMEOUT);
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
return bs_scsi_cmd_poll(ti, cb);
|
||||
}
|
||||
|
||||
/* test unit ready and check ATN msgout response */
|
||||
static int
|
||||
bs_check_target(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct scsi_inquiry scsi_cmd;
|
||||
struct scsi_inquiry_data scsi_inquiry_data;
|
||||
struct ccb *cb;
|
||||
int count, retry = bsc->sc_retry;
|
||||
int s, error = COMPLETE;
|
||||
|
||||
ti->ti_lun = 0;
|
||||
bsc->sc_retry = 2;
|
||||
s = splbio();
|
||||
|
||||
/* inquiry */
|
||||
bzero(&scsi_cmd, sizeof(scsi_cmd));
|
||||
#ifdef __NetBSD__
|
||||
scsi_cmd.opcode = INQUIRY;
|
||||
#else
|
||||
scsi_cmd.op_code = INQUIRY;
|
||||
#endif
|
||||
scsi_cmd.length = sizeof(struct scsi_inquiry_data);
|
||||
cb = bs_make_internal_ccb(ti, 0,
|
||||
(u_int8_t *) &scsi_cmd, sizeof(scsi_cmd),
|
||||
(u_int8_t *) &scsi_inquiry_data,
|
||||
sizeof(scsi_inquiry_data),
|
||||
BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
error = bs_scsi_cmd_poll(ti, cb);
|
||||
if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
|
||||
goto done;
|
||||
ti->targ_type = scsi_inquiry_data.device;
|
||||
ti->targ_support = scsi_inquiry_data.flags;
|
||||
|
||||
/* test unit ready twice */
|
||||
for (count = 0; count < 2; count++)
|
||||
{
|
||||
cb = bs_make_internal_ccb(ti, 0, NULL, 0, NULL, 0,
|
||||
BSFORCEIOPOLL, BS_STARTUP_TIMEOUT);
|
||||
bscmdstart(ti, BSCMDSTART);
|
||||
error = bs_scsi_cmd_poll(ti, cb);
|
||||
if (error != COMPLETE || (ti->ti_error & BSSELTIMEOUT))
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (cb->flags & BSCASTAT)
|
||||
bs_printf(ti, "check", "could not clear CA state");
|
||||
ti->ti_error = 0;
|
||||
|
||||
done:
|
||||
bsc->sc_retry = retry;
|
||||
|
||||
if (ti->ti_error & BSSELTIMEOUT)
|
||||
error = NOTARGET;
|
||||
|
||||
if (error == COMPLETE)
|
||||
error = bs_start_target(ti);
|
||||
|
||||
splx(s);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* TARGET CONTROL
|
||||
**************************************************/
|
||||
struct targ_info *
|
||||
bs_init_target_info(bsc, target)
|
||||
struct bs_softc *bsc;
|
||||
int target;
|
||||
{
|
||||
struct targ_info *ti;
|
||||
|
||||
ti = malloc(sizeof(struct targ_info), M_DEVBUF, M_NOWAIT);
|
||||
if (ti == NULL)
|
||||
{
|
||||
bs_printf(NULL, "bs_init_targ_info", "no target info memory");
|
||||
return ti;
|
||||
}
|
||||
|
||||
bzero(ti, sizeof(*ti));
|
||||
|
||||
ti->ti_bsc = bsc;
|
||||
ti->ti_id = target;
|
||||
ti->sm_vaddr = (u_int8_t *) MADDRUNK;
|
||||
ti->ti_cfgflags = BS_SCSI_NOPARITY | BS_SCSI_NOSAT;
|
||||
ti->ti_mflags = ~(BSSAT | BSDISC | BSSMIT | BSLINK);
|
||||
BS_SETUP_TARGSTATE(BS_TARG_CTRL);
|
||||
|
||||
TAILQ_INIT(&ti->ti_ctab);
|
||||
|
||||
bs_alloc_buf(ti);
|
||||
if (ti->bounce_addr == NULL)
|
||||
{
|
||||
free(ti, M_DEVBUF);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TAILQ_INSERT_TAIL(&bsc->sc_titab, ti, ti_tchain);
|
||||
bsc->sc_ti[target] = ti;
|
||||
bsc->sc_openf |= (1 << target);
|
||||
|
||||
return ti;
|
||||
}
|
||||
|
||||
void
|
||||
bs_setup_ctrl(ti, quirks, flags)
|
||||
struct targ_info *ti;
|
||||
u_int quirks;
|
||||
u_int flags;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
u_int offset, period, maxperiod;
|
||||
|
||||
if (ti->ti_state == BS_TARG_CTRL)
|
||||
{
|
||||
ti->ti_cfgflags = BS_SCSI_POSITIVE;
|
||||
ti->ti_syncmax.offset = BSHW_MAX_OFFSET;
|
||||
BS_SETUP_TARGSTATE(BS_TARG_START);
|
||||
}
|
||||
else
|
||||
flags |= ti->ti_cfgflags & BS_SCSI_NEGATIVE;
|
||||
|
||||
#ifdef BS_TARG_SAFEMODE
|
||||
if (ti->targ_type != 0)
|
||||
{
|
||||
flags &= ~(BS_SCSI_DISC | BS_SCSI_SYNC);
|
||||
flags |= BS_SCSI_NOPARITY;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef SDEV_NODISC
|
||||
if (quirks & SDEV_NODISC)
|
||||
flags &= ~BS_SCSI_DISC;
|
||||
#endif
|
||||
#ifdef SDEV_NOPARITY
|
||||
if (quirks & SDEV_NOPARITY)
|
||||
flags |= BS_SCSI_NOPARITY;
|
||||
#endif
|
||||
#ifdef SDEV_NOCMDLNK
|
||||
if (quirks & SDEV_NOCMDLNK)
|
||||
flags &= ~BS_SCSI_LINK;
|
||||
#endif
|
||||
#ifdef SDEV_ASYNC
|
||||
if (quirks & SDEV_ASYNC)
|
||||
flags &= ~BS_SCSI_SYNC;
|
||||
#endif
|
||||
#ifdef SDEV_AUTOSAVE
|
||||
if (quirks & SDEV_AUTOSAVE)
|
||||
flags |= BS_SCSI_SAVESP;
|
||||
#endif
|
||||
|
||||
if ((flags & BS_SCSI_DISC) == 0 ||
|
||||
(ti->targ_support & SID_Linked) == 0)
|
||||
flags &= ~BS_SCSI_LINK;
|
||||
|
||||
ti->sm_vaddr = (flags & BS_SCSI_NOSMIT) ?
|
||||
(u_int8_t *) MADDRUNK : bsc->sm_vaddr;
|
||||
|
||||
if (ti->sm_vaddr == (u_int8_t *) MADDRUNK)
|
||||
flags |= BS_SCSI_NOSMIT;
|
||||
else if (bsc->sc_cfgflags & BSC_SMITSAT_DISEN)
|
||||
flags |= BS_SCSI_NOSAT;
|
||||
|
||||
flags &= (ti->ti_cfgflags & BS_SCSI_POSITIVE) | (~BS_SCSI_POSITIVE);
|
||||
ti->ti_cfgflags = flags;
|
||||
|
||||
/* calculate synch setup */
|
||||
period = BS_SCSI_PERIOD(flags);
|
||||
offset = (flags & BS_SCSI_SYNC) ? BS_SCSI_OFFSET(flags) : 0;
|
||||
|
||||
maxperiod = (bsc->sc_cspeed & IDR_FS_15_20) ? 100 : 50;
|
||||
if (period > maxperiod)
|
||||
period = maxperiod;
|
||||
|
||||
if (period)
|
||||
period = 2500 / period;
|
||||
|
||||
if (ti->ti_syncmax.offset > offset)
|
||||
ti->ti_syncmax.offset = offset;
|
||||
if (ti->ti_syncmax.period < period)
|
||||
ti->ti_syncmax.period = period;
|
||||
|
||||
bshw_adj_syncdata(&ti->ti_syncmax);
|
||||
|
||||
/* finally report our info */
|
||||
printf("%s(%d:%d): {%d:0x%x:0x%x:%s} flags 0x%b\n",
|
||||
bsc->sc_dvname, ti->ti_id, ti->ti_lun,
|
||||
(u_int) ti->targ_type,
|
||||
(u_int) ti->targ_support,
|
||||
(u_int) ti->bounce_size,
|
||||
(flags & BS_SCSI_NOSMIT) ? "dma" : "pdma",
|
||||
flags, BS_SCSI_BITS);
|
||||
|
||||
/* internal representation */
|
||||
ti->ti_mflags = ~0;
|
||||
if ((ti->ti_cfgflags & BS_SCSI_DISC) == 0)
|
||||
ti->ti_mflags &= ~BSDISC;
|
||||
if ((ti->ti_cfgflags & BS_SCSI_LINK) == 0)
|
||||
ti->ti_mflags &= ~BSLINK;
|
||||
if (ti->ti_cfgflags & BS_SCSI_NOSAT)
|
||||
ti->ti_mflags &= ~BSSAT;
|
||||
if (ti->ti_cfgflags & BS_SCSI_NOSMIT)
|
||||
ti->ti_mflags &= ~BSSMIT;
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* MISC
|
||||
**************************************************/
|
||||
void
|
||||
bs_printf(ti, ph, c)
|
||||
struct targ_info *ti;
|
||||
char *ph;
|
||||
char *c;
|
||||
{
|
||||
|
||||
if (ti)
|
||||
printf("%s(%d:%d): <%s> %s\n",
|
||||
ti->ti_bsc->sc_dvname, ti->ti_id, ti->ti_lun, ph, c);
|
||||
else
|
||||
printf("bs*(*:*): <%s> %s\n", ph, c);
|
||||
}
|
||||
|
||||
void
|
||||
bs_panic(bsc, c)
|
||||
struct bs_softc *bsc;
|
||||
u_char *c;
|
||||
{
|
||||
|
||||
panic("%s %s\n", bsc->sc_dvname, c);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* DEBUG FUNC
|
||||
**************************************************/
|
||||
#ifdef BS_DEBUG_ROUTINE
|
||||
u_int
|
||||
bsr(addr)
|
||||
u_int addr;
|
||||
{
|
||||
|
||||
outb(0xcc0, addr);
|
||||
return inb(0xcc2);
|
||||
}
|
||||
|
||||
u_int
|
||||
bsw(addr, data)
|
||||
u_int addr;
|
||||
int data;
|
||||
{
|
||||
|
||||
outb(0xcc0, addr);
|
||||
outb(0xcc2, data);
|
||||
return 0;
|
||||
}
|
||||
#endif /* BS_DEBUG_ROUTINE */
|
||||
|
||||
void
|
||||
bs_debug_print_all(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
struct targ_info *ti;
|
||||
|
||||
for (ti = bsc->sc_titab.tqh_first; ti; ti = ti->ti_tchain.tqe_next)
|
||||
bs_debug_print(bsc, ti);
|
||||
}
|
||||
|
||||
static u_char *phase[] =
|
||||
{
|
||||
"FREE", "HOSTQUE", "DISC", "COMPMSG", "ATN", "DISCMSG", "SELECT",
|
||||
"SELECTED", "RESELECTED", "MSGIN", "MSGOUT", "STATIN", "CMDOUT",
|
||||
"DATA", "SATSEL", "SATRESEL", "SATSDP", "SATCOMPSEQ", "UNDEF",
|
||||
};
|
||||
|
||||
void
|
||||
bs_debug_print(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct ccb *cb;
|
||||
|
||||
/* host stat */
|
||||
printf("%s <DEBUG INFO> nexus %x bs %x bus status %x \n",
|
||||
bsc->sc_dvname, ti, bsc->sc_nexus, (u_int) bsc->sc_busstat);
|
||||
|
||||
/* target stat */
|
||||
if (ti)
|
||||
{
|
||||
struct sc_p *sp = &bsc->sc_p;
|
||||
|
||||
printf("%s(%d:%d) ph<%s> ", bsc->sc_dvname, ti->ti_id,
|
||||
ti->ti_lun, phase[(int) ti->ti_phase]);
|
||||
printf("msgptr %x msg[0] %x status %x tqh %x fl %x\n",
|
||||
(u_int) (ti->ti_msginptr), (u_int) (ti->ti_msgin[0]),
|
||||
ti->ti_status, cb = ti->ti_ctab.tqh_first, ti->ti_flags);
|
||||
if (cb)
|
||||
printf("cmdlen %x cmdaddr %x cmd[0] %x\n",
|
||||
cb->cmdlen, cb->cmd, (int) cb->cmd[0]);
|
||||
printf("datalen %x dataaddr %x seglen %x ",
|
||||
sp->datalen, sp->data, sp->seglen);
|
||||
if (cb)
|
||||
printf("odatalen %x flags %x\n",
|
||||
cb->datalen, cb->flags);
|
||||
else
|
||||
printf("\n");
|
||||
printf("error flags %b\n", ti->ti_error, BSERRORBITS);
|
||||
}
|
||||
}
|
229
sys/i386/isa/bs/bsfunc.h
Normal file
229
sys/i386/isa/bs/bsfunc.h
Normal file
@ -0,0 +1,229 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
/**************************************************
|
||||
* FUNC
|
||||
**************************************************/
|
||||
/* timeout */
|
||||
void bstimeout __P((void *));
|
||||
|
||||
/* ctrl setup */
|
||||
void bs_setup_ctrl __P((struct targ_info *, u_int, u_int));
|
||||
struct targ_info *bs_init_target_info __P((struct bs_softc *, int));
|
||||
|
||||
/* msg op */
|
||||
int bs_send_msg __P((struct targ_info *, u_int, struct msgbase *, int));
|
||||
struct ccb *bs_request_sense __P((struct targ_info *));
|
||||
|
||||
/* sync msg op */
|
||||
int bs_start_syncmsg __P((struct targ_info *, struct ccb *, int));
|
||||
int bs_send_syncmsg __P((struct targ_info *));
|
||||
int bs_analyze_syncmsg __P((struct targ_info *, struct ccb *));
|
||||
|
||||
/* reset device */
|
||||
void bs_scsibus_start __P((struct bs_softc *));
|
||||
void bs_reset_nexus __P((struct bs_softc *));
|
||||
struct ccb *bs_force_abort __P((struct targ_info *));
|
||||
void bs_reset_device __P((struct targ_info *));
|
||||
|
||||
/* ccb */
|
||||
struct ccb *bs_make_internal_ccb __P((struct targ_info *, u_int, u_int8_t *, u_int, u_int8_t *, u_int, u_int, int));
|
||||
struct ccb *bs_make_msg_ccb __P((struct targ_info *, u_int, struct ccb *, struct msgbase *, u_int));
|
||||
|
||||
/* misc funcs */
|
||||
void bs_printf __P((struct targ_info *, char *, char *));
|
||||
void bs_panic __P((struct bs_softc *, u_char *));
|
||||
|
||||
/* misc debug */
|
||||
u_int bsr __P((u_int));
|
||||
u_int bsw __P((u_int, int));
|
||||
void bs_debug_print_all __P((struct bs_softc *));
|
||||
void bs_debug_print __P((struct bs_softc *, struct targ_info *));
|
||||
|
||||
/**************************************************
|
||||
* TARG FLAGS
|
||||
*************************************************/
|
||||
static BS_INLINE int bs_check_sat __P((struct targ_info *));
|
||||
static BS_INLINE int bs_check_smit __P((struct targ_info *));
|
||||
static BS_INLINE int bs_check_disc __P((struct targ_info *));
|
||||
static BS_INLINE int bs_check_link __P((struct targ_info *, struct ccb *));
|
||||
static BS_INLINE u_int8_t bs_identify_msg __P((struct targ_info *));
|
||||
static BS_INLINE void bs_targ_flags __P((struct targ_info *, struct ccb *));
|
||||
|
||||
static BS_INLINE int
|
||||
bs_check_disc(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
return (ti->ti_flags & BSDISC);
|
||||
}
|
||||
|
||||
static BS_INLINE int
|
||||
bs_check_sat(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
return (ti->ti_flags & BSSAT);
|
||||
}
|
||||
|
||||
static BS_INLINE int
|
||||
bs_check_smit(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
return (ti->ti_flags & BSSMIT);
|
||||
}
|
||||
|
||||
static BS_INLINE int
|
||||
bs_check_link(ti, cb)
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
{
|
||||
struct ccb *nextcb;
|
||||
|
||||
return ((ti->ti_flags & BSLINK) &&
|
||||
(nextcb = cb->ccb_chain.tqe_next) &&
|
||||
(nextcb->flags & BSLINK));
|
||||
}
|
||||
|
||||
static BS_INLINE u_int8_t
|
||||
bs_identify_msg(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
return ((bs_check_disc(ti) ? 0xc0 : 0x80) | ti->ti_lun);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bs_targ_flags(ti, cb)
|
||||
struct targ_info *ti;
|
||||
struct ccb *cb;
|
||||
{
|
||||
u_int cmf = (u_int) bshw_cmd[cb->cmd[0]];
|
||||
|
||||
cb->flags |= ((cmf & (BSSAT | BSSMIT | BSLINK)) | BSDISC);
|
||||
cb->flags &= ti->ti_mflags;
|
||||
|
||||
if (cb->datalen < DEV_BSIZE)
|
||||
cb->flags &= ~BSSMIT;
|
||||
if (cb->flags & BSFORCEIOPOLL)
|
||||
cb->flags &= ~(BSLINK | BSSMIT | BSSAT | BSDISC);
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* QUEUE OP
|
||||
**************************************************/
|
||||
static BS_INLINE void bs_hostque_init __P((struct bs_softc *));
|
||||
static BS_INLINE void bs_hostque_head __P((struct bs_softc *, struct targ_info *));
|
||||
static BS_INLINE void bs_hostque_tail __P((struct bs_softc *, struct targ_info *));
|
||||
static BS_INLINE void bs_hostque_delete __P((struct bs_softc *, struct targ_info *));
|
||||
|
||||
static BS_INLINE void
|
||||
bs_hostque_init(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
TAILQ_INIT(&bsc->sc_sttab);
|
||||
TAILQ_INIT(&bsc->sc_titab);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bs_hostque_head(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
if (ti->ti_flags & BSQUEUED)
|
||||
TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
|
||||
else
|
||||
ti->ti_flags |= BSQUEUED;
|
||||
|
||||
TAILQ_INSERT_HEAD(&bsc->sc_sttab, ti, ti_wchain);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bs_hostque_tail(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
if (ti->ti_flags & BSQUEUED)
|
||||
TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
|
||||
else
|
||||
ti->ti_flags |= BSQUEUED;
|
||||
|
||||
TAILQ_INSERT_TAIL(&bsc->sc_sttab, ti, ti_wchain)
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bs_hostque_delete(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
if (ti->ti_flags & BSQUEUED)
|
||||
{
|
||||
ti->ti_flags &= ~BSQUEUED;
|
||||
TAILQ_REMOVE(&bsc->sc_sttab, ti, ti_wchain)
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* TIMEOUT
|
||||
************************************************************/
|
||||
static BS_INLINE void bs_start_timeout __P((struct bs_softc *));
|
||||
static BS_INLINE void bs_terminate_timeout __P((struct bs_softc *));
|
||||
|
||||
static BS_INLINE void
|
||||
bs_start_timeout(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
if ((bsc->sc_flags & BSSTARTTIMEOUT) == 0)
|
||||
{
|
||||
bsc->sc_flags |= BSSTARTTIMEOUT;
|
||||
timeout(bstimeout, bsc, BS_TIMEOUT_INTERVAL);
|
||||
}
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bs_terminate_timeout(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
if (bsc->sc_flags & BSSTARTTIMEOUT)
|
||||
{
|
||||
untimeout(bstimeout, bsc);
|
||||
bsc->sc_flags &= ~BSSTARTTIMEOUT;
|
||||
}
|
||||
}
|
451
sys/i386/isa/bs/bshw.c
Normal file
451
sys/i386/isa/bs/bshw.c
Normal file
@ -0,0 +1,451 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <dev/isa/isadmareg.h>
|
||||
#include <dev/isa/bs/bsif.h>
|
||||
#include <dev/isa/bs/bshw.lst>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <i386/isa/ic/i8237.h>
|
||||
#include <i386/isa/bs/bsif.h>
|
||||
#include <i386/isa/bs/bshw.lst>
|
||||
#include <machine/clock.h>
|
||||
#include <i386/i386/cons.h>
|
||||
#endif
|
||||
|
||||
static struct bs_softc *gbsc;
|
||||
|
||||
/**************************************************
|
||||
* DECLARATION
|
||||
**************************************************/
|
||||
static void bshw_force_bsmode __P((struct bs_softc *));
|
||||
|
||||
/**************************************************
|
||||
* STATIC VAL
|
||||
**************************************************/
|
||||
static int irq_tbl[] = { 3, 5, 6, 9, 12, 13 };
|
||||
|
||||
/**************************************************
|
||||
* SCSI CMD BRANCH
|
||||
**************************************************/
|
||||
#define RS (BSSAT | BSSMIT | BSLINK | BSREAD)
|
||||
#define WS (BSSAT | BSSMIT | BSLINK)
|
||||
#define EOK (BSERROROK)
|
||||
|
||||
u_int8_t bshw_cmd[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 ,RS ,0 ,WS ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*1*/0 ,0 ,EOK,0 ,0 ,0 ,0 ,0 ,0 ,0 ,EOK,0 ,0 ,0 ,0 ,0 ,
|
||||
/*2*/0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,RS ,0 ,WS ,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 ,EOK,EOK,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,0 ,
|
||||
/*5*/0 ,0 ,0 ,0 ,EOK,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 ,
|
||||
};
|
||||
|
||||
#undef RS
|
||||
#undef WS
|
||||
#undef EOK
|
||||
|
||||
/**********************************************
|
||||
* init
|
||||
**********************************************/
|
||||
static void
|
||||
bshw_force_bsmode(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
if (bsc->sc_flags & BSBSMODE)
|
||||
return;
|
||||
bsc->sc_flags |= BSBSMODE;
|
||||
|
||||
/*
|
||||
* If you have memory over 16M, some stupid boards always force to
|
||||
* use the io polling mode. Check such a case and change mode into
|
||||
* bus master DMA. However this depends heavily on the board's
|
||||
* specifications!
|
||||
*/
|
||||
|
||||
if (bsc->sc_hw->dma_init && ((*bsc->sc_hw->dma_init)(bsc)))
|
||||
printf("%s change mode using external DMA (%x)\n",
|
||||
bsc->sc_dvname, (u_int)read_wd33c93(bsc, 0x37));
|
||||
}
|
||||
|
||||
#define RESET_DEFAULT 2000
|
||||
|
||||
int
|
||||
bshw_chip_reset(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
int ct;
|
||||
u_int8_t aux;
|
||||
|
||||
bshw_lock(bsc);
|
||||
|
||||
bshw_abort_cmd(bsc);
|
||||
delay(10000);
|
||||
|
||||
bshw_get_auxstat(bsc);
|
||||
bshw_get_busstat(bsc);
|
||||
|
||||
write_wd33c93(bsc, wd3s_oid, IDR_EHP | bsc->sc_cspeed | bsc->sc_hostid);
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
|
||||
|
||||
for (ct = RESET_DEFAULT; ct > 0; ct--)
|
||||
{
|
||||
aux = bshw_get_auxstat(bsc);
|
||||
if (aux != 0xff && (aux & STR_INT))
|
||||
{
|
||||
if (bshw_get_busstat(bsc) == 0)
|
||||
break;
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_RESET);
|
||||
}
|
||||
delay(1);
|
||||
}
|
||||
|
||||
if (ct == 0)
|
||||
{
|
||||
bshw_unlock(bsc);
|
||||
return ENXIO;
|
||||
}
|
||||
|
||||
bshw_force_bsmode(bsc);
|
||||
|
||||
write_wd33c93(bsc, wd3s_tout, BSHW_SEL_TIMEOUT);
|
||||
write_wd33c93(bsc, wd3s_sid, SIDR_RESEL);
|
||||
bsc->sc_flags |= BSDMATRANSFER;
|
||||
write_wd33c93(bsc, wd3s_ctrl, CR_DEFAULT);
|
||||
write_wd33c93(bsc, wd3s_synch, 0);
|
||||
|
||||
bshw_get_auxstat(bsc);
|
||||
bsc->sc_busstat = bshw_get_busstat(bsc);
|
||||
bshw_unlock(bsc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scsi bus hard reset */
|
||||
#define TWIDDLEWAIT 10000
|
||||
static int tw_pos;
|
||||
static char tw_chars[] = "|/-\\";
|
||||
|
||||
/* this is some jokes */
|
||||
static void
|
||||
twiddle_wait(void)
|
||||
{
|
||||
|
||||
cnputc('\b');
|
||||
cnputc(tw_chars[tw_pos++]);
|
||||
tw_pos %= (sizeof(tw_chars) - 1);
|
||||
delay(TWIDDLEWAIT);
|
||||
}
|
||||
|
||||
static void bshw_set_vsp __P((struct bs_softc *, u_int, u_int8_t));
|
||||
|
||||
static void
|
||||
bshw_set_vsp(bsc, chan, spva)
|
||||
struct bs_softc *bsc;
|
||||
u_int chan;
|
||||
u_int8_t spva;
|
||||
{
|
||||
struct bshw *hw = bsc->sc_hw;
|
||||
|
||||
if (hw->sregaddr == 0)
|
||||
return;
|
||||
|
||||
write_wd33c93(bsc, hw->sregaddr + chan, spva);
|
||||
if (hw->hw_flags & BSHW_DOUBLE_DMACHAN)
|
||||
write_wd33c93(bsc, hw->sregaddr + chan + 8, spva);
|
||||
}
|
||||
|
||||
void
|
||||
bshw_bus_reset(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
struct targ_info *ti;
|
||||
int i, lpc;
|
||||
|
||||
if (bsc->sc_RSTdelay == 0)
|
||||
bsc->sc_RSTdelay = 6 * 1000 * 1000;
|
||||
else
|
||||
{
|
||||
/* XXX:
|
||||
* second time reset will be requested by hardware failuer.
|
||||
*/
|
||||
bsc->sc_RSTdelay = 12 * 1000 * 1000;
|
||||
}
|
||||
|
||||
bshw_lock(bsc);
|
||||
write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank | MBR_RST) & ~MBR_IEN);
|
||||
delay(500000);
|
||||
write_wd33c93(bsc, wd3s_mbank, (bsc->sc_membank) & ~MBR_IEN);
|
||||
bshw_unlock(bsc);
|
||||
|
||||
for (lpc = 0; lpc < 2; lpc ++)
|
||||
{
|
||||
cnputc(' ');
|
||||
for (i = 0; i <= bsc->sc_RSTdelay / TWIDDLEWAIT; i++)
|
||||
twiddle_wait();
|
||||
cnputc('\b');
|
||||
|
||||
(void) read_wd33c93(bsc, wd3s_auxc);
|
||||
|
||||
delay(10000);
|
||||
|
||||
if ((read_wd33c93(bsc, wd3s_auxc) & AUXCR_RRST) == 0)
|
||||
break;
|
||||
|
||||
printf("\nreset state still continue, wait ...");
|
||||
}
|
||||
|
||||
for (i = 0; i < NTARGETS; i++)
|
||||
{
|
||||
if (ti = bsc->sc_ti[i])
|
||||
{
|
||||
ti->ti_sync = 0;
|
||||
bshw_set_vsp(bsc, i, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* probe */
|
||||
int
|
||||
bshw_board_probe(bsc, drq, irq)
|
||||
struct bs_softc *bsc;
|
||||
u_int *drq;
|
||||
u_int *irq;
|
||||
{
|
||||
|
||||
gbsc = bsc;
|
||||
#ifdef SHOW_PORT
|
||||
bshw_print_port(bsc);
|
||||
#endif /* SHOW_PORT */
|
||||
|
||||
bsc->sc_hostid = (read_wd33c93(bsc, wd3s_auxc) & AUXCR_HIDM);
|
||||
|
||||
if ((*irq) == IRQUNK)
|
||||
*irq = irq_tbl[(read_wd33c93(bsc, wd3s_auxc) >> 3) & 7];
|
||||
|
||||
if ((*drq) == DRQUNK)
|
||||
*drq = BUS_IOR(cmd_port) & 3;
|
||||
|
||||
bsc->sc_dmachan = *drq;
|
||||
bsc->sc_irqmasks = (1 << (*irq));
|
||||
|
||||
bsc->sc_membank = read_wd33c93(bsc, wd3s_mbank);
|
||||
bsc->sc_membank &= ~MBR_RST;
|
||||
bsc->sc_membank |= MBR_IEN;
|
||||
|
||||
bsc->sc_cspeed = (read_wd33c93(bsc, wd3s_oid) & (~IDR_IDM));
|
||||
switch (BSC_CHIP_CLOCK(bsc->sc_cfgflags))
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
|
||||
case 1:
|
||||
bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
|
||||
bsc->sc_cspeed |= IDR_FS_12_15;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
bsc->sc_cspeed &= ~(IDR_FS_12_15 | IDR_FS_15_20);
|
||||
bsc->sc_cspeed |= IDR_FS_15_20;
|
||||
break;
|
||||
}
|
||||
|
||||
/* XXX: host id fixed(7) */
|
||||
bsc->sc_hostid = 7;
|
||||
|
||||
if (bshw_chip_reset(bsc))
|
||||
return ENXIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX:
|
||||
* Assume the board clock rate must be 20Mhz (always satisfied, maybe)!
|
||||
* Only 10M/s 6.6M/s 5.0M/s 3.3M/s for synchronus transfer speed set.
|
||||
*/
|
||||
#define ILLEGAL_SYNCH
|
||||
#ifdef ILLEGAL_SYNCH
|
||||
/* 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 u_int bshw_scsi_period[] =
|
||||
{0, 25, 37, 50, 62, 75, 87, 100, 125};
|
||||
static u_int8_t bshw_chip_pval[] =
|
||||
{0, 0xa0, 0xb0, 0x20, 0xd0, 0x30, 0xf0, 0x40, 0x50};
|
||||
#else /* !ILLEGAL_SYNCH */
|
||||
/* A 10 6.6 5.0 3.3 2.5 M/s */
|
||||
/* X 100 150 200 300 400 ns */
|
||||
static u_int bshw_scsi_period[] =
|
||||
{0, 25, 37, 50, 75, 100};
|
||||
static u_int8_t bshw_chip_pval[] =
|
||||
{0, 0xa0, 0xb0, 0x20, 0x30, 0x40};
|
||||
#endif /* !ILLEGAL_SYNCH */
|
||||
|
||||
void
|
||||
bshw_adj_syncdata(sdp)
|
||||
struct syncdata *sdp;
|
||||
{
|
||||
int i;
|
||||
|
||||
if (sdp->offset == 0 || sdp->period < 25 || sdp->period > 100)
|
||||
sdp->offset = sdp->period = 0;
|
||||
else
|
||||
{
|
||||
for (i = 0; sdp->period > bshw_scsi_period[i] + 2; i ++)
|
||||
;
|
||||
sdp->period = bshw_scsi_period[i];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bshw_set_synchronous(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bshw *hw = bsc->sc_hw;
|
||||
struct syncdata sd;
|
||||
int i;
|
||||
|
||||
sd = ti->ti_syncnow;
|
||||
bshw_adj_syncdata(&sd);
|
||||
for (i = 0; sd.period != bshw_scsi_period[i]; i++)
|
||||
;
|
||||
|
||||
ti->ti_sync = ((sd.offset & 0x0f) | bshw_chip_pval[i]);
|
||||
bshw_set_vsp(bsc, ti->ti_id, ti->ti_sync);
|
||||
|
||||
if (bsc->sc_nexus == ti)
|
||||
bshw_set_sync_reg(bsc, ti->ti_sync);
|
||||
}
|
||||
|
||||
/* ctrl reg */
|
||||
void
|
||||
bshw_setup_ctrl_reg(bsc, flags)
|
||||
struct bs_softc *bsc;
|
||||
u_int flags;
|
||||
{
|
||||
u_int8_t regval;
|
||||
|
||||
regval = (flags & BS_SCSI_NOPARITY) ? CR_DEFAULT : CR_DEFAULT_HP;
|
||||
if (bsc->sc_flags & BSDMATRANSFER)
|
||||
regval |= CR_DMA;
|
||||
write_wd33c93(bsc, wd3s_ctrl, regval);
|
||||
}
|
||||
|
||||
/* sat command */
|
||||
void
|
||||
bshw_issue_satcmd(bsc, cb, link)
|
||||
struct bs_softc *bsc;
|
||||
struct ccb *cb;
|
||||
int link;
|
||||
{
|
||||
int i;
|
||||
|
||||
BUS_IOW(addr_port, wd3s_cdb);
|
||||
for (i = 0; i < cb->cmdlen - 1; i++)
|
||||
BUS_IOW(ctrl_port, cb->cmd[i]);
|
||||
BUS_IOW(ctrl_port, cb->cmd[i] | (link ? 1 : 0));
|
||||
}
|
||||
|
||||
/* lock */
|
||||
void
|
||||
bshw_lock(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
bsc->sc_hwlock++;
|
||||
write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank & (~MBR_IEN));
|
||||
}
|
||||
|
||||
void
|
||||
bshw_unlock(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
if ((--bsc->sc_hwlock) <= 0)
|
||||
write_wd33c93(bsc, wd3s_mbank, bsc->sc_membank);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* DMA OPERATIONS
|
||||
**********************************************/
|
||||
#ifdef __NetBSD__
|
||||
#include <dev/isa/bs/bshw_dma.c>
|
||||
#include <dev/isa/bs/bshw_pdma.c>
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#include <i386/isa/bs/bshw_dma.c>
|
||||
#include <i386/isa/bs/bshw_pdma.c>
|
||||
#endif
|
||||
|
||||
/**********************************************
|
||||
* DEBUG
|
||||
**********************************************/
|
||||
/* misc */
|
||||
void
|
||||
bshw_print_port(bsc)
|
||||
struct bs_softc * bsc;
|
||||
{
|
||||
int i, j;
|
||||
int port = 0x0;
|
||||
|
||||
if (bsc == NULL)
|
||||
bsc = gbsc;
|
||||
|
||||
printf("\n");
|
||||
for (j = 0; j <= 0x70; j += 0x10)
|
||||
{
|
||||
printf("port %x: ", port);
|
||||
for (i = 0; i < 0x10; i++)
|
||||
printf("%x ", (u_int) read_wd33c93(bsc, port++));
|
||||
printf("\n");
|
||||
}
|
||||
}
|
363
sys/i386/isa/bs/bshw.h
Normal file
363
sys/i386/isa/bs/bshw.h
Normal file
@ -0,0 +1,363 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
/* NEC port offsets */
|
||||
#define BSHW_DEFAULT_PORT 0xcc0
|
||||
#define BSHW_IOSZ 5
|
||||
|
||||
#define addr_port 0
|
||||
#define stat_port 0
|
||||
#define ctrl_port 2
|
||||
#define cmd_port 4
|
||||
|
||||
#define BSHW_MAX_OFFSET 12
|
||||
#define BSHW_SEL_TIMEOUT 0x80
|
||||
|
||||
#define BSHW_READ BSR_IOR
|
||||
#define BSHW_WRITE 0x0
|
||||
|
||||
#define BSHW_CMD_CHECK(CCB, CAT) (bshw_cmd[(CCB)->cmd[0]] & (CAT))
|
||||
|
||||
/*********************************************************
|
||||
* static inline declare.
|
||||
*********************************************************/
|
||||
static BS_INLINE void write_wd33c93 __P((struct bs_softc *, u_int, u_int8_t));
|
||||
static BS_INLINE u_int8_t read_wd33c93 __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE u_int8_t bshw_get_auxstat __P((struct bs_softc *));
|
||||
static BS_INLINE u_int8_t bshw_get_busstat __P((struct bs_softc *));
|
||||
static BS_INLINE u_int8_t bshw_get_status_insat __P((struct bs_softc *));
|
||||
static BS_INLINE u_int8_t bshw_read_data __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_write_data __P((struct bs_softc *, u_int8_t));
|
||||
static BS_INLINE void bshw_set_count __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE u_int bshw_get_count __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_set_dst_id __P((struct bs_softc *, u_int, u_int));
|
||||
static BS_INLINE void bshw_set_lun __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE u_int bshw_get_src_id __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_negate_ack __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_assert_atn __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_assert_select __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_start_xfer __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_start_sxfer __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_cmd_pass __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE void bshw_start_sat __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE void bshw_abort_cmd __P((struct bs_softc *));
|
||||
static BS_INLINE void bshw_set_sync_reg __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE void bshw_set_poll_trans __P((struct bs_softc *, u_int));
|
||||
static BS_INLINE void bshw_set_dma_trans __P((struct bs_softc *, u_int));
|
||||
|
||||
/*********************************************************
|
||||
* global declare
|
||||
*********************************************************/
|
||||
void bs_dma_xfer __P((struct targ_info *, u_int));
|
||||
void bs_dma_xfer_end __P((struct targ_info *));
|
||||
void bshw_dmaabort __P((struct bs_softc *, struct targ_info *));
|
||||
|
||||
void bshw_adj_syncdata __P((struct syncdata *));
|
||||
void bshw_set_synchronous __P((struct bs_softc *, struct targ_info *));
|
||||
|
||||
void bs_smit_xfer_end __P((struct targ_info *));
|
||||
void bshw_smitabort __P((struct bs_softc *));
|
||||
|
||||
void bshw_setup_ctrl_reg __P((struct bs_softc *, u_int));
|
||||
int bshw_chip_reset __P((struct bs_softc *));
|
||||
void bshw_bus_reset __P((struct bs_softc *));
|
||||
int bshw_board_probe __P((struct bs_softc *, u_int *, u_int *));
|
||||
void bshw_lock __P((struct bs_softc *));
|
||||
void bshw_unlock __P((struct bs_softc *));
|
||||
void bshw_get_syncreg __P((struct bs_softc *));
|
||||
void bshw_issue_satcmd __P((struct bs_softc *, struct ccb *, int));
|
||||
void bshw_print_port __P((struct bs_softc *));
|
||||
|
||||
void bs_lc_smit_xfer __P((struct targ_info *, u_int));
|
||||
|
||||
extern struct dvcfg_hwsel bshw_hwsel;
|
||||
extern u_int8_t bshw_cmd[];
|
||||
|
||||
/*********************************************************
|
||||
* hw
|
||||
*********************************************************/
|
||||
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 bs_softc *)));
|
||||
void ((*dma_start) __P((struct bs_softc *)));
|
||||
void ((*dma_stop) __P((struct bs_softc *)));
|
||||
};
|
||||
|
||||
/*********************************************************
|
||||
* inline funcs.
|
||||
*********************************************************/
|
||||
/*
|
||||
* XXX: If your board does not work well, Please try BS_NEEDS_WEIGHT.
|
||||
*/
|
||||
static BS_INLINE void
|
||||
write_wd33c93(bsc, addr, data)
|
||||
struct bs_softc *bsc;
|
||||
u_int addr;
|
||||
u_int8_t data;
|
||||
{
|
||||
|
||||
BUS_IOW(addr_port, addr);
|
||||
BUS_IOW(ctrl_port, data);
|
||||
}
|
||||
|
||||
static BS_INLINE u_int8_t
|
||||
read_wd33c93(bsc, addr)
|
||||
struct bs_softc *bsc;
|
||||
u_int addr;
|
||||
{
|
||||
|
||||
BUS_IOW(addr_port, addr);
|
||||
return BUS_IOR(ctrl_port);
|
||||
}
|
||||
|
||||
/* status */
|
||||
static BS_INLINE u_int8_t
|
||||
bshw_get_auxstat(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
return BUS_IOR(stat_port);
|
||||
}
|
||||
|
||||
static BS_INLINE u_int8_t
|
||||
bshw_get_busstat(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
return read_wd33c93(bsc, wd3s_stat);
|
||||
}
|
||||
|
||||
static BS_INLINE u_int8_t
|
||||
bshw_get_status_insat(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
return read_wd33c93(bsc, wd3s_lun);
|
||||
}
|
||||
|
||||
/* data */
|
||||
static BS_INLINE u_int8_t
|
||||
bshw_read_data(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
return read_wd33c93(bsc, wd3s_data);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_write_data(bsc, data)
|
||||
struct bs_softc *bsc;
|
||||
u_int8_t data;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_data, data);
|
||||
}
|
||||
|
||||
/* counter */
|
||||
static BS_INLINE void
|
||||
bshw_set_count(bsc, count)
|
||||
struct bs_softc *bsc;
|
||||
u_int count;
|
||||
{
|
||||
|
||||
BUS_IOW(addr_port, wd3s_cnt);
|
||||
BUS_IOW(ctrl_port, count >> 16);
|
||||
BUS_IOW(ctrl_port, count >> 8);
|
||||
BUS_IOW(ctrl_port, count);
|
||||
}
|
||||
|
||||
static BS_INLINE u_int
|
||||
bshw_get_count(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
u_int count;
|
||||
|
||||
BUS_IOW(addr_port, wd3s_cnt);
|
||||
count = (((u_int) BUS_IOR(ctrl_port)) << 16);
|
||||
count += (((u_int) BUS_IOR(ctrl_port)) << 8);
|
||||
count += ((u_int) BUS_IOR(ctrl_port));
|
||||
return count;
|
||||
}
|
||||
|
||||
/* ID */
|
||||
static BS_INLINE void
|
||||
bshw_set_lun(bsc, lun)
|
||||
struct bs_softc *bsc;
|
||||
u_int lun;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_lun, lun);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_set_dst_id(bsc, target, lun)
|
||||
struct bs_softc *bsc;
|
||||
u_int target, lun;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_did, target);
|
||||
write_wd33c93(bsc, wd3s_lun, lun);
|
||||
}
|
||||
|
||||
static BS_INLINE u_int
|
||||
bshw_get_src_id(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
return (read_wd33c93(bsc, wd3s_sid) & SIDR_IDM);
|
||||
}
|
||||
|
||||
/* phase */
|
||||
static BS_INLINE void
|
||||
bshw_negate_ack(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_NEGATE_ACK);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_assert_atn(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_ASSERT_ATN);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_assert_select(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_SELECT_ATN);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_start_xfer(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_TFR_INFO);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_start_sxfer(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_SBT | WD3S_TFR_INFO);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_cmd_pass(bsc, ph)
|
||||
struct bs_softc *bsc;
|
||||
u_int ph;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cph, ph);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_start_sat(bsc, flag)
|
||||
struct bs_softc *bsc;
|
||||
u_int flag;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd,
|
||||
(flag ? WD3S_SELECT_ATN_TFR : WD3S_SELECT_NO_ATN_TFR));
|
||||
}
|
||||
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_abort_cmd(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_cmd, WD3S_ABORT);
|
||||
}
|
||||
|
||||
/* transfer mode */
|
||||
static BS_INLINE void
|
||||
bshw_set_sync_reg(bsc, val)
|
||||
struct bs_softc *bsc;
|
||||
u_int val;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, wd3s_synch, val);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_set_poll_trans(bsc, flags)
|
||||
struct bs_softc *bsc;
|
||||
u_int flags;
|
||||
{
|
||||
|
||||
if (bsc->sc_flags & BSDMATRANSFER)
|
||||
{
|
||||
bsc->sc_flags &= ~BSDMATRANSFER;
|
||||
bshw_setup_ctrl_reg(bsc, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_set_dma_trans(bsc, flags)
|
||||
struct bs_softc *bsc;
|
||||
u_int flags;
|
||||
{
|
||||
|
||||
if ((bsc->sc_flags & BSDMATRANSFER) == 0)
|
||||
{
|
||||
bsc->sc_flags |= BSDMATRANSFER;
|
||||
bshw_setup_ctrl_reg(bsc, flags);
|
||||
}
|
||||
}
|
||||
|
||||
static BS_INLINE void memcopy __P((void *from, void *to, register size_t len));
|
||||
|
||||
static BS_INLINE void
|
||||
memcopy(from, to, len)
|
||||
void *from, *to;
|
||||
register size_t len;
|
||||
{
|
||||
|
||||
len >>= 2;
|
||||
__asm __volatile("cld\n\trep\n\tmovsl" : :
|
||||
"S" (from), "D" (to), "c" (len) :
|
||||
"%esi", "%edi", "%ecx");
|
||||
}
|
113
sys/i386/isa/bs/bshw.lst
Normal file
113
sys/i386/isa/bs/bshw.lst
Normal file
@ -0,0 +1,113 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
static struct bshw bshw_generic = {
|
||||
BSHW_SYNC_RELOAD,
|
||||
|
||||
0,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static int bshw_dma_init_sc98 __P((struct bs_softc *));
|
||||
static void bshw_dma_start_sc98 __P((struct bs_softc *));
|
||||
static void bshw_dma_stop_sc98 __P((struct bs_softc *));
|
||||
static struct bshw bshw_sc98 = {
|
||||
BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
bshw_dma_init_sc98,
|
||||
bshw_dma_start_sc98,
|
||||
bshw_dma_stop_sc98,
|
||||
};
|
||||
|
||||
static int bshw_dma_init_texa __P((struct bs_softc *));
|
||||
static struct bshw bshw_texa = {
|
||||
BSHW_DOUBLE_DMACHAN,
|
||||
|
||||
0x60,
|
||||
|
||||
bshw_dma_init_texa,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void bshw_dma_start_elecom __P((struct bs_softc *));
|
||||
static void bshw_dma_stop_elecom __P((struct bs_softc *));
|
||||
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
|
||||
};
|
339
sys/i386/isa/bs/bshw_dma.c
Normal file
339
sys/i386/isa/bs/bshw_dma.c
Normal file
@ -0,0 +1,339 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
/*********************************************************
|
||||
* static declare.
|
||||
*********************************************************/
|
||||
static BS_INLINE void bshw_dmastart __P((struct bs_softc *));
|
||||
static void bshw_dmadone __P((struct bs_softc *));
|
||||
|
||||
/**********************************************
|
||||
* UPPER INTERFACE FUNCS (all funcs exported)
|
||||
**********************************************/
|
||||
void
|
||||
bshw_dmaabort(bsc, ti)
|
||||
struct bs_softc *bsc;
|
||||
struct targ_info *ti;
|
||||
{
|
||||
|
||||
bshw_dmadone(bsc);
|
||||
bsc->sc_p.seglen = 0;
|
||||
bshw_set_count(bsc, 0);
|
||||
|
||||
if (ti == NULL)
|
||||
{
|
||||
int i;
|
||||
struct targ_info *tmpti;
|
||||
|
||||
for (i = 0; i < NTARGETS; i++)
|
||||
if (tmpti = bsc->sc_ti[i])
|
||||
tmpti->ti_scsp.seglen = 0;
|
||||
}
|
||||
else
|
||||
ti->ti_scsp.seglen = 0;
|
||||
}
|
||||
|
||||
/* DMA TRANSFER */
|
||||
void
|
||||
bs_dma_xfer(ti, direction)
|
||||
struct targ_info *ti;
|
||||
u_int direction;
|
||||
{
|
||||
vm_offset_t va, endva, phys, nphys;
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct sc_p *sp = &bsc->sc_p;
|
||||
|
||||
bsc->sc_dmadir = direction;
|
||||
bshw_set_dma_trans(bsc, ti->ti_cfgflags);
|
||||
|
||||
if (sp->seglen == 0)
|
||||
{
|
||||
phys = vtophys((vm_offset_t) sp->data);
|
||||
if (phys >= RAM_END)
|
||||
{
|
||||
/* setup segaddr */
|
||||
sp->segaddr = ti->bounce_phys;
|
||||
/* setup seglen */
|
||||
sp->seglen = sp->datalen;
|
||||
if (sp->seglen > ti->bounce_size)
|
||||
sp->seglen = ti->bounce_size;
|
||||
/* setup bufp */
|
||||
sp->bufp = ti->bounce_addr;
|
||||
if (bsc->sc_dmadir != BSHW_READ)
|
||||
bcopy(sp->data, sp->bufp, sp->seglen);
|
||||
#ifdef BS_STATICS
|
||||
bs_bounce_used[ti->ti_id]++;
|
||||
#endif /* BS_STATICS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* setup segaddr */
|
||||
sp->segaddr = (u_int8_t *) phys;
|
||||
/* setup seglen */
|
||||
endva = (vm_offset_t)round_page(sp->data + sp->datalen);
|
||||
for (va = (vm_offset_t) sp->data; ; phys = nphys)
|
||||
{
|
||||
if ((va += BSHW_NBPG) >= endva)
|
||||
{
|
||||
sp->seglen = sp->datalen;
|
||||
break;
|
||||
}
|
||||
|
||||
nphys = vtophys(va);
|
||||
if (phys + BSHW_NBPG != nphys || nphys >= RAM_END)
|
||||
{
|
||||
sp->seglen =
|
||||
(u_int8_t *) trunc_page(va) - sp->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* setup bufp */
|
||||
sp->bufp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
bshw_dmastart(bsc);
|
||||
bshw_set_count(bsc, sp->seglen);
|
||||
}
|
||||
|
||||
void
|
||||
bs_dma_xfer_end(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct sc_p *sp = &bsc->sc_p;
|
||||
u_int count, transbytes;
|
||||
|
||||
bshw_dmadone(bsc);
|
||||
if (ti->ti_phase == DATAPHASE)
|
||||
{
|
||||
count = bshw_get_count(bsc);
|
||||
if (count < (u_int) sp->seglen)
|
||||
{
|
||||
transbytes = sp->seglen - count;
|
||||
if (sp->bufp)
|
||||
{
|
||||
if (bsc->sc_dmadir == BSHW_READ)
|
||||
bcopy(sp->bufp, sp->data, transbytes);
|
||||
sp->bufp += transbytes;
|
||||
}
|
||||
sp->seglen = count;
|
||||
sp->segaddr += transbytes;
|
||||
sp->data += transbytes;
|
||||
sp->datalen -= transbytes;
|
||||
return;
|
||||
}
|
||||
else if (count == (u_int) sp->seglen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
bs_printf(ti, "xfer_end", "strange count");
|
||||
printf("port data %x seglen %x\n", count, sp->seglen);
|
||||
}
|
||||
else
|
||||
bs_printf(ti, "xfer_end", "extra dma interrupt");
|
||||
|
||||
ti->ti_error |= BSDMAABNORMAL;
|
||||
sp->seglen = ti->ti_scsp.seglen = 0; /* XXX */
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* GENERIC DMA FUNCS
|
||||
**********************************************/
|
||||
static short dmapageport[4] = { 0x27, 0x21, 0x23, 0x25 };
|
||||
|
||||
/* common dma settings */
|
||||
#undef DMA1_SMSK
|
||||
#define DMA1_SMSK (IO_DMA + 0x14)
|
||||
#undef DMA1_MODE
|
||||
#define DMA1_MODE (IO_DMA + 0x16)
|
||||
#undef DMA1_FFC
|
||||
#define DMA1_FFC (IO_DMA + 0x18)
|
||||
#undef DMA37SM_SET
|
||||
#define DMA37SM_SET 0x04
|
||||
#undef DMA1_CHN
|
||||
#define DMA1_CHN(c) (IO_DMA + ((c) << 2))
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_dmastart(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
int chan = bsc->sc_dmachan;
|
||||
int waport;
|
||||
u_int8_t *phys = bsc->sc_p.segaddr;
|
||||
u_int nbytes = bsc->sc_p.seglen;
|
||||
|
||||
/*
|
||||
* Program one of DMA channels 0..3. These are
|
||||
* byte mode channels.
|
||||
*/
|
||||
/* set dma channel mode, and reset address ff */
|
||||
#ifdef __FreeBSD__
|
||||
#ifdef CYRIX_5X86
|
||||
asm("wbinvd");
|
||||
#endif
|
||||
#else /* NetBSD/pc98 */
|
||||
if (cpuspec->cpuspec_cache_flush_before)
|
||||
(*cpuspec->cpuspec_cache_flush_before)();
|
||||
#endif
|
||||
|
||||
if (bsc->sc_dmadir & BSHW_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 (bsc->sc_hw->dma_start)
|
||||
(*bsc->sc_hw->dma_start)(bsc);
|
||||
|
||||
outb(DMA1_SMSK, chan);
|
||||
BUS_IOW(cmd_port, CMDP_DMES);
|
||||
|
||||
bsc->sc_flags |= BSDMASTART;
|
||||
}
|
||||
|
||||
static void
|
||||
bshw_dmadone(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
outb(DMA1_SMSK, (bsc->sc_dmachan | DMA37SM_SET));
|
||||
BUS_IOW(cmd_port, CMDP_DMER);
|
||||
|
||||
/* vendor unique hook */
|
||||
if (bsc->sc_hw->dma_stop)
|
||||
(*bsc->sc_hw->dma_stop)(bsc);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(CYRIX_486DLC) || defined(IBM_486SLC)
|
||||
asm(".byte 0x0f, 0x08");
|
||||
#endif
|
||||
#else
|
||||
if (cpuspec->cpuspec_cache_flush_after)
|
||||
(*cpuspec->cpuspec_cache_flush_after)();
|
||||
#endif
|
||||
|
||||
bsc->sc_flags &= (~BSDMASTART);
|
||||
}
|
||||
|
||||
/**********************************************
|
||||
* VENDOR UNIQUE DMA FUNCS
|
||||
**********************************************/
|
||||
static int
|
||||
bshw_dma_init_texa(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
u_int8_t regval;
|
||||
|
||||
if ((regval = read_wd33c93(bsc, 0x37)) & 0x08)
|
||||
return 0;
|
||||
|
||||
write_wd33c93(bsc, 0x37, regval | 0x08);
|
||||
regval = read_wd33c93(bsc, 0x3f);
|
||||
write_wd33c93(bsc, 0x3f, regval | 0x08);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int
|
||||
bshw_dma_init_sc98(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
if (read_wd33c93(bsc, 0x37) & 0x08)
|
||||
return 0;
|
||||
|
||||
/* If your card is SC98 with bios ver 1.01 or 1.02 under no PCI */
|
||||
write_wd33c93(bsc, 0x37, 0x1a);
|
||||
write_wd33c93(bsc, 0x3f, 0x1a);
|
||||
#if 0
|
||||
/* only valid for IO */
|
||||
write_wd33c93(bsc, 0x40, 0xf4);
|
||||
write_wd33c93(bsc, 0x41, 0x9);
|
||||
write_wd33c93(bsc, 0x43, 0xff);
|
||||
write_wd33c93(bsc, 0x46, 0x4e);
|
||||
|
||||
write_wd33c93(bsc, 0x48, 0xf4);
|
||||
write_wd33c93(bsc, 0x49, 0x9);
|
||||
write_wd33c93(bsc, 0x4b, 0xff);
|
||||
write_wd33c93(bsc, 0x4e, 0x4e);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void
|
||||
bshw_dma_start_sc98(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, 0x73, 0x32);
|
||||
write_wd33c93(bsc, 0x74, 0x23);
|
||||
}
|
||||
|
||||
static void
|
||||
bshw_dma_stop_sc98(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, 0x73, 0x43);
|
||||
write_wd33c93(bsc, 0x74, 0x34);
|
||||
}
|
||||
|
||||
static void
|
||||
bshw_dma_start_elecom(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
u_int8_t tmp = read_wd33c93(bsc, 0x4c);
|
||||
|
||||
write_wd33c93(bsc, 0x32, tmp & 0xdf);
|
||||
}
|
||||
|
||||
static void
|
||||
bshw_dma_stop_elecom(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
u_int8_t tmp = read_wd33c93(bsc, 0x4c);
|
||||
|
||||
write_wd33c93(bsc, 0x32, tmp | 0x20);
|
||||
}
|
242
sys/i386/isa/bs/bshw_pdma.c
Normal file
242
sys/i386/isa/bs/bshw_pdma.c
Normal file
@ -0,0 +1,242 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#define LC_SMIT_TIMEOUT 2 /* 2 sec: timeout for a fifo status ready */
|
||||
|
||||
static BS_INLINE void bshw_lc_smit_start __P((struct bs_softc *, int, u_int));
|
||||
static int bshw_lc_smit_fstat __P((struct bs_softc *, int, int));
|
||||
static BS_INLINE void bshw_lc_smit_stop __P((struct bs_softc *));
|
||||
|
||||
/*********************************************************
|
||||
* SM FIFO (GENERIC)
|
||||
*********************************************************/
|
||||
void
|
||||
bshw_smitabort(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
if (bsc->sc_hw->hw_flags & BSHW_SMFIFO)
|
||||
bshw_lc_smit_stop(bsc);
|
||||
|
||||
bshw_set_count(bsc, 0);
|
||||
bsc->sc_flags &= ~BSSMITSTART;
|
||||
}
|
||||
|
||||
void
|
||||
bs_smit_xfer_end(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct sc_p *sp = &bsc->sc_p;
|
||||
u_int count;
|
||||
u_char *s;
|
||||
|
||||
bshw_lc_smit_stop(bsc);
|
||||
bsc->sc_flags &= ~BSSMITSTART;
|
||||
|
||||
if (ti->ti_phase == DATAPHASE)
|
||||
{
|
||||
count = bshw_get_count(bsc);
|
||||
if (count < (u_int) sp->datalen)
|
||||
{
|
||||
sp->data += (sp->datalen - count);
|
||||
sp->datalen = count;
|
||||
/* XXX:
|
||||
* strict double checks!
|
||||
* target => wd33c93c transfer counts
|
||||
* wd33c93c => memory transfer counts
|
||||
*/
|
||||
if ((bsc->sc_dmadir & BSHW_READ) &&
|
||||
count != bsc->sm_tdatalen)
|
||||
{
|
||||
s = "read count miss";
|
||||
goto bad;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (count == (u_int) sp->datalen)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
s = "strange count";
|
||||
}
|
||||
else
|
||||
s = "extra smit interrupt";
|
||||
|
||||
bad:
|
||||
bs_printf(ti, "smit_xfer_end", s);
|
||||
ti->ti_error |= BSDMAABNORMAL;
|
||||
}
|
||||
|
||||
/*********************************************************
|
||||
* LOGITEC's SMIT TRANSFER
|
||||
*********************************************************/
|
||||
|
||||
#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
|
||||
|
||||
#define LC_FSZ DEV_BSIZE
|
||||
#define LC_SFSZ 0x0c
|
||||
#define LC_REST (LC_FSZ - LC_SFSZ)
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_lc_smit_stop(bsc)
|
||||
struct bs_softc *bsc;
|
||||
{
|
||||
|
||||
write_wd33c93(bsc, BSHW_LC_FCTRL, 0);
|
||||
BUS_IOW(cmd_port, CMDP_DMER);
|
||||
}
|
||||
|
||||
static BS_INLINE void
|
||||
bshw_lc_smit_start(bsc, count, direction)
|
||||
struct bs_softc *bsc;
|
||||
int count;
|
||||
u_int direction;
|
||||
{
|
||||
u_int8_t pval, val = read_wd33c93(bsc, BSHW_LC_FSET);
|
||||
|
||||
bsc->sc_flags |= BSSMITSTART;
|
||||
bshw_set_count(bsc, count);
|
||||
|
||||
pval = FCTRL_EN;
|
||||
if ((direction & BSHW_READ) == 0)
|
||||
pval |= (val & 0xe0) | FCTRL_WRITE;
|
||||
write_wd33c93(bsc, BSHW_LC_FCTRL, pval);
|
||||
bshw_start_xfer(bsc);
|
||||
}
|
||||
|
||||
static int
|
||||
bshw_lc_smit_fstat(bsc, wc, read)
|
||||
struct bs_softc *bsc;
|
||||
int wc, read;
|
||||
{
|
||||
u_int8_t stat;
|
||||
|
||||
#define ALWAYS_ABORT
|
||||
#ifdef ALWAYS_ABORT
|
||||
if (read == BSHW_READ)
|
||||
{
|
||||
while (wc -- > 0)
|
||||
{
|
||||
BUS_IO_WEIGHT;
|
||||
stat = BUS_IOR(cmd_port);
|
||||
if (stat & SF_RDY)
|
||||
return 0;
|
||||
if (stat & SF_ABORT)
|
||||
return EIO;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* ALWAYS_ABORT */
|
||||
while (wc -- > 0)
|
||||
{
|
||||
BUS_IO_WEIGHT;
|
||||
stat = BUS_IOR(cmd_port);
|
||||
if (stat & SF_ABORT)
|
||||
return EIO;
|
||||
if (stat & SF_RDY)
|
||||
return 0;
|
||||
}
|
||||
#ifdef ALWAYS_ABORT
|
||||
}
|
||||
#endif /* ALWAYS_ABORT */
|
||||
|
||||
bs_poll_timeout(bsc, "bshw_lc_smit");
|
||||
return EIO;
|
||||
}
|
||||
|
||||
void
|
||||
bs_lc_smit_xfer(ti, direction)
|
||||
struct targ_info *ti;
|
||||
u_int direction;
|
||||
{
|
||||
struct bs_softc *bsc = ti->ti_bsc;
|
||||
struct sc_p *sp = &bsc->sc_p;
|
||||
int datalen, count, wc = LC_SMIT_TIMEOUT * 1024 * 1024;
|
||||
u_int8_t *data;
|
||||
|
||||
sp->bufp = NULL;
|
||||
sp->seglen = 0;
|
||||
data = sp->data;
|
||||
datalen = sp->datalen;
|
||||
|
||||
bsc->sc_dmadir = direction;
|
||||
bshw_set_dma_trans(bsc, ti->ti_cfgflags);
|
||||
bshw_lc_smit_start(bsc, sp->datalen, direction);
|
||||
|
||||
if (direction & BSHW_READ)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (bshw_lc_smit_fstat(bsc, wc, BSHW_READ))
|
||||
break;
|
||||
|
||||
count = (datalen > LC_FSZ ? LC_FSZ : datalen);
|
||||
memcopy(ti->sm_vaddr, data, count);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
}
|
||||
while (datalen > 0);
|
||||
|
||||
bsc->sm_tdatalen = datalen;
|
||||
}
|
||||
else
|
||||
{
|
||||
do
|
||||
{
|
||||
if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
|
||||
break;
|
||||
|
||||
count = (datalen > LC_SFSZ ? LC_SFSZ : datalen);
|
||||
memcopy(data, ti->sm_vaddr, count);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
|
||||
if (bshw_lc_smit_fstat(bsc, wc, BSHW_WRITE))
|
||||
break;
|
||||
|
||||
count = (datalen > LC_REST ? LC_REST : datalen);
|
||||
memcopy(data, ti->sm_vaddr + LC_SFSZ, count);
|
||||
data += count;
|
||||
datalen -= count;
|
||||
}
|
||||
while (datalen > 0);
|
||||
}
|
||||
}
|
520
sys/i386/isa/bs/bsif.c
Normal file
520
sys/i386/isa/bs/bsif.c
Normal file
@ -0,0 +1,520 @@
|
||||
/*
|
||||
* Copyright (c) HONDA Naofumi, KATO Takenori, 1996. 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* WARNING: Any bug report must contain BS_REL_VERSION */
|
||||
#define BS_REL_VERSION "NetBSD1.2/030" /* major jump */
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <dev/isa/bs/bsif.h>
|
||||
#endif /* __NetBSD__ */
|
||||
#ifdef __FreeBSD__
|
||||
#include "bs.h"
|
||||
#include <i386/isa/bs/bsif.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/**************************************************
|
||||
* DEVICE DECLARE
|
||||
**************************************************/
|
||||
#ifdef __NetBSD__
|
||||
int bsintr __P((void *));
|
||||
static int bsprint __P((void *, char *));
|
||||
static void bs_scsi_minphys __P((struct buf *));
|
||||
|
||||
struct cfdriver bs_cd = {
|
||||
NULL, "bs", DV_DULL
|
||||
};
|
||||
|
||||
struct scsi_device bs_dev = {
|
||||
NULL, /* Use default error handler */
|
||||
NULL, /* have a queue, served by this */
|
||||
NULL, /* have no async handler */
|
||||
NULL, /* Use default 'done' routine */
|
||||
};
|
||||
|
||||
struct scsi_adapter pc98texa55bs = {
|
||||
bs_scsi_cmd,
|
||||
bs_scsi_minphys,
|
||||
bs_target_open,
|
||||
0,
|
||||
};
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int bsprobe __P((struct isa_device *));
|
||||
static int bsattach __P((struct isa_device *));
|
||||
static int bsprint __P((void *, char *));
|
||||
static void bs_scsi_minphys __P((struct buf *));
|
||||
static int bs_dmarangecheck __P((caddr_t, unsigned));
|
||||
|
||||
struct isa_driver bsdriver = {
|
||||
bsprobe,
|
||||
bsattach,
|
||||
"bs"
|
||||
};
|
||||
|
||||
struct scsi_device bs_dev = {
|
||||
NULL, /* Use default error handler */
|
||||
NULL, /* have a queue, served by this */
|
||||
NULL, /* have no async handler */
|
||||
NULL, /* Use default 'done' routine */
|
||||
"bs",
|
||||
0, {0, 0}
|
||||
};
|
||||
|
||||
u_int32_t
|
||||
bs_adapter_info(unit)
|
||||
int unit;
|
||||
{
|
||||
return (1);
|
||||
}
|
||||
|
||||
struct scsi_adapter pc98texa55bs = {
|
||||
bs_scsi_cmd,
|
||||
bs_scsi_minphys,
|
||||
bs_target_open,
|
||||
0,
|
||||
bs_adapter_info,
|
||||
"bs", {0, 0}
|
||||
};
|
||||
|
||||
static u_short pc98_irq_ball[16] = {
|
||||
IRQ0, IRQ1, IRQ2, IRQ3, IRQ4, IRQ5, IRQ6, IRQ7,
|
||||
IRQ8, IRQ9, IRQ10, IRQ11, IRQ12, IRQ13, IRQ14, IRQ15
|
||||
};
|
||||
|
||||
static struct bs_softc *bscdata[NBS];
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/*****************************************************************
|
||||
* OS <=> BS INTERFACE
|
||||
*****************************************************************/
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
bsprobe(dev)
|
||||
struct isa_device *dev;
|
||||
#else /* __NetBSD__ */
|
||||
int
|
||||
bsprobe(parent, self, aux)
|
||||
struct device *parent;
|
||||
struct device *self;
|
||||
void *aux;
|
||||
#endif /* __NetBSD__ */
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
struct bs_softc *bsc;
|
||||
int unit = dev->id_unit;
|
||||
#else /* __NetBSD__ */
|
||||
struct bs_softc *bsc = (void *) self;
|
||||
struct isa_attach_args *ia = aux;
|
||||
bus_chipset_tag_t bc = ia->ia_bc;
|
||||
#endif /* __NetBSD__ */
|
||||
u_int irq, drq;
|
||||
int i, rv = 0;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (unit >= NBS) {
|
||||
printf("bs%d: unit number too high\n", unit);
|
||||
return rv;
|
||||
}
|
||||
/*
|
||||
* Allocate a storage for us
|
||||
*/
|
||||
if (bscdata[unit]) {
|
||||
printf("bs%d: memory already allocated\n", unit);
|
||||
return rv;
|
||||
}
|
||||
if (!(bsc = malloc(sizeof(struct bs_softc), M_TEMP, M_NOWAIT))) {
|
||||
printf("bs%d cannot malloc!\n", unit);
|
||||
return rv;
|
||||
}
|
||||
bzero(bsc, sizeof(struct bs_softc));
|
||||
bscdata[unit] = bsc;
|
||||
bsc->unit = unit;
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
bsc->sc_cfgflags = DVCFG_MINOR(dev->id_flags);
|
||||
bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(dev->id_flags));
|
||||
#else /* __NetBSD__ */
|
||||
bsc->sc_cfgflags = DVCFG_MINOR(ia->ia_cfgflags);
|
||||
bsc->sc_hw = DVCFG_HW(&bshw_hwsel, DVCFG_MAJOR(ia->ia_cfgflags));
|
||||
#endif /* __NetBSD__ */
|
||||
if (bsc->sc_hw == NULL)
|
||||
return rv;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) &&
|
||||
(dev->id_maddr != (caddr_t)MADDRUNK))
|
||||
bsc->sm_vaddr = (u_int8_t *) dev->id_maddr;
|
||||
else
|
||||
bsc->sm_vaddr = (u_int8_t *) MADDRUNK;
|
||||
#else /* __NetBSD__ */
|
||||
if ((bsc->sc_hw->hw_flags & BSHW_SMFIFO) && (ia->ia_maddr != MADDRUNK))
|
||||
{
|
||||
ia->ia_maddr &= ~((NBPG * 2) - 1);
|
||||
ia->ia_maddr += NBPG;
|
||||
ia->ia_msize = NBPG;
|
||||
if (bus_mem_map(bc, ia->ia_maddr, NBPG, 0, &bsc->sc_memh))
|
||||
return 0;
|
||||
bsc->sm_vaddr = (u_int8_t *) bsc->sc_memh; /* XXX */
|
||||
}
|
||||
else
|
||||
{
|
||||
bsc->sm_vaddr = (u_int8_t *) MADDRUNK;
|
||||
ia->ia_msize = 0;
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
sprintf(bsc->sc_dvname, "bs%d", unit);
|
||||
#else /* __NetBSD__ */
|
||||
strcpy(bsc->sc_dvname, bsc->sc_dev.dv_xname);
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
if (dev->id_iobase == 0)
|
||||
#else /* __NetBSD__ */
|
||||
if (ia->ia_iobase == IOBASEUNK)
|
||||
#endif /* __NetBSD__ */
|
||||
{
|
||||
printf("%s: iobase not specified. Assume default port(0x%x)\n",
|
||||
bsc->sc_dvname, BSHW_DEFAULT_PORT);
|
||||
#ifdef __FreeBSD__
|
||||
dev->id_iobase = BSHW_DEFAULT_PORT;
|
||||
#else /* __NetBSD__ */
|
||||
ia->ia_iobase = BSHW_DEFAULT_PORT;
|
||||
#endif /* __NetBSD__ */
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
bsc->sc_iobase = dev->id_iobase;
|
||||
#else /* __NetBSD__ */
|
||||
bsc->sc_iobase = ia->ia_iobase;
|
||||
bsc->sc_bc = bc;
|
||||
bsc->sc_delayioh = ia->ia_delayioh;
|
||||
if (bus_io_map(bsc->sc_bc, bsc->sc_iobase, BSHW_IOSZ, &bsc->sc_ioh))
|
||||
return rv;
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
irq = IRQUNK;
|
||||
drq = DRQUNK;
|
||||
#else /* __NetBSD__ */
|
||||
irq = ia->ia_irq;
|
||||
drq = ia->ia_drq;
|
||||
#endif /* __NetBSD__ */
|
||||
if (bshw_board_probe(bsc, &drq, &irq))
|
||||
goto bad;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
dev->id_irq = pc98_irq_ball[irq];
|
||||
dev->id_drq = (short)drq;
|
||||
#else /* __NetBSD__ */
|
||||
ia->ia_irq = irq;
|
||||
ia->ia_drq = drq;
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
/* initialize host queue and target info */
|
||||
bs_hostque_init(bsc);
|
||||
for (i = 0; i < NTARGETS; i++)
|
||||
if (i != bsc->sc_hostid)
|
||||
bs_init_target_info(bsc, i);
|
||||
|
||||
/* initialize ccb queue */
|
||||
bs_init_ccbque(BS_MAX_CCB);
|
||||
|
||||
#ifdef __NetBSD__
|
||||
/* init port data */
|
||||
ia->ia_iosize = BSHW_IOSZ;
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
/* scsi bus reset and restart */
|
||||
bsc->sc_hstate = BSC_BOOTUP;
|
||||
bsc->sc_retry = RETRIES;
|
||||
bsc->sc_wc = delaycount * 250; /* about 1 sec */
|
||||
bs_reset_nexus(bsc);
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
return BSHW_IOSZ;
|
||||
bad:
|
||||
return rv;
|
||||
#else /* __NetBSD__ */
|
||||
rv = 1;
|
||||
bad:
|
||||
bus_io_unmap(bsc->sc_bc, bsc->sc_ioh, BSHW_IOSZ);
|
||||
return rv;
|
||||
#endif /* __NetBSD__ */
|
||||
}
|
||||
|
||||
static int
|
||||
bsprint(aux, name)
|
||||
void *aux;
|
||||
char *name;
|
||||
{
|
||||
|
||||
if (name != NULL)
|
||||
printf("%s: scsibus ", name);
|
||||
return UNCONF;
|
||||
}
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int
|
||||
bsattach(dev)
|
||||
struct isa_device *dev;
|
||||
#else /* __NetBSD__ */
|
||||
void
|
||||
bsattach(parent, self, aux)
|
||||
struct device *parent;
|
||||
struct device *self;
|
||||
void *aux;
|
||||
#endif /* __NetBSD__ */
|
||||
{
|
||||
#ifdef __FreeBSD__
|
||||
int unit = dev->id_unit;
|
||||
struct bs_softc *bsc = bscdata[unit];
|
||||
struct scsibus_data *scbus;
|
||||
#else /* __NetBSD__ */
|
||||
struct bs_softc *bsc = (void *) self;
|
||||
struct isa_attach_args *ia = aux;
|
||||
|
||||
printf("\n");
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __NetBSD__
|
||||
bsc->sc_iobase = ia->ia_iobase;
|
||||
bsc->sc_bc = ia->ia_bc;
|
||||
bsc->sc_delayioh = ia->ia_delayioh;
|
||||
if (bus_io_map(bsc->sc_bc, bsc->sc_iobase, BSHW_IOSZ, &bsc->sc_ioh))
|
||||
panic("%s: bus io map failed\n", bsc->sc_dev.dv_xname);
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
bsc->sc_link.adapter_unit = unit;
|
||||
bsc->sc_link.adapter_targ = bsc->sc_hostid;
|
||||
bsc->sc_link.flags = SDEV_BOUNCE;
|
||||
bsc->sc_link.opennings = XSMAX;
|
||||
#else /* __NetBSD__ */
|
||||
bsc->sc_link.adapter_target = bsc->sc_hostid;
|
||||
bsc->sc_link.openings = XSMAX;
|
||||
#endif /* __NetBSD__ */
|
||||
bsc->sc_link.adapter_softc = bsc;
|
||||
bsc->sc_link.adapter = &pc98texa55bs;
|
||||
bsc->sc_link.device = &bs_dev;
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
/*
|
||||
* Prepare the scsibus_data area for the upperlevel
|
||||
* scsi code.
|
||||
*/
|
||||
scbus = scsi_alloc_bus();
|
||||
if (!scbus)
|
||||
return 0;
|
||||
scbus->adapter_link = &bsc->sc_link;
|
||||
/*
|
||||
* ask the adapter what subunits are present
|
||||
*/
|
||||
scsi_attachdevs(scbus);
|
||||
#else /* __NetBSD__ */
|
||||
bsc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
|
||||
IPL_BIO, bsintr, bsc);
|
||||
config_found(self, &bsc->sc_link, bsprint);
|
||||
#endif /* __NetBSD__ */
|
||||
bs_start_timeout(bsc);
|
||||
#ifdef __FreeBSD__
|
||||
return 1;
|
||||
#endif /* __FreeBSD__ */
|
||||
}
|
||||
|
||||
#ifdef __NetBSD__
|
||||
int
|
||||
bsintr(arg)
|
||||
void *arg;
|
||||
{
|
||||
|
||||
return bs_sequencer((struct bs_softc *)arg);
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
void
|
||||
bsintr(unit)
|
||||
int unit;
|
||||
{
|
||||
(void)bs_sequencer(bscdata[unit]);
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/*****************************************************************
|
||||
* JULIAN SCSI <=> BS INTERFACE
|
||||
*****************************************************************/
|
||||
static void
|
||||
bs_scsi_minphys(bp)
|
||||
struct buf *bp;
|
||||
{
|
||||
|
||||
if (bp->b_bcount > BSDMABUFSIZ)
|
||||
bp->b_bcount = BSDMABUFSIZ;
|
||||
minphys(bp);
|
||||
}
|
||||
|
||||
XSBS_INT32T
|
||||
bs_target_open(sc, cf)
|
||||
struct scsi_link *sc;
|
||||
struct cfdata *cf;
|
||||
{
|
||||
u_int target = sc->target;
|
||||
struct bs_softc *bsc = (struct bs_softc *) (sc->adapter_softc);
|
||||
struct targ_info *ti = bsc->sc_ti[target];
|
||||
u_int flags;
|
||||
|
||||
if ((bsc->sc_openf & (1 << target)) == 0)
|
||||
return ENODEV;
|
||||
|
||||
if ((flags = cf->cf_flags) == 0)
|
||||
flags = BS_SCSI_DEFCFG;
|
||||
|
||||
bs_setup_ctrl(ti, (u_int)sc->quirks, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************
|
||||
* BS MEMORY ALLOCATION INTERFACE
|
||||
*****************************************************************/
|
||||
#ifdef __NetBSD__
|
||||
void
|
||||
bs_alloc_buf(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
extern int cold;
|
||||
caddr_t addr, physaddr;
|
||||
u_int pages;
|
||||
|
||||
/* XXX:
|
||||
* strategy change!
|
||||
* A) total memory >= 16M at boot: MAXBSIZE * 7 = 112k.
|
||||
* B) others: 4K * 7 = 28 K.
|
||||
*/
|
||||
if (get_sysinfo(SYSINFO_MEMLEVEL) == MEM_LEVEL1 && cold != 0)
|
||||
pages = 4;
|
||||
else
|
||||
pages = 1;
|
||||
|
||||
ti->bounce_size = NBPG * pages;
|
||||
if ((addr = alloc_bounce_buffer(ti->bounce_size)) == NULL)
|
||||
{
|
||||
ti->bounce_size = NBPG;
|
||||
if ((addr = malloc(NBPG, M_DEVBUF, M_NOWAIT)) == NULL)
|
||||
goto bad;
|
||||
}
|
||||
|
||||
physaddr = (caddr_t) vtophys(addr);
|
||||
if ((u_int) physaddr >= RAM_END)
|
||||
{
|
||||
/* XXX: mem from malloc only! */
|
||||
free(addr, M_DEVBUF);
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ti->bounce_addr = (u_int8_t *) addr;
|
||||
ti->bounce_phys = (u_int8_t *) physaddr;
|
||||
return;
|
||||
|
||||
bad:
|
||||
bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
|
||||
printf("WARNING: this target is dislocated\n");
|
||||
}
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
static int bs_dmarangecheck(caddr_t va, unsigned length)
|
||||
{
|
||||
vm_offset_t phys, priorpage = 0, endva;
|
||||
|
||||
endva = (vm_offset_t)round_page(va+length);
|
||||
for (; va < (caddr_t)endva; va += PAGE_SIZE) {
|
||||
phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va));
|
||||
if (phys == 0)
|
||||
panic("bs_dmarangecheck: no physical page present");
|
||||
if (phys >= RAM_END)
|
||||
return 1;
|
||||
if (priorpage) {
|
||||
if (priorpage + PAGE_SIZE != phys)
|
||||
return 1;
|
||||
}
|
||||
priorpage = phys;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
bs_alloc_buf(ti)
|
||||
struct targ_info *ti;
|
||||
{
|
||||
caddr_t addr, physaddr;
|
||||
|
||||
#if BS_BOUNCE_SIZE != 0
|
||||
ti->bounce_size = BS_BOUNCE_SIZE;
|
||||
#else
|
||||
ti->bounce_size = BSHW_NBPG;
|
||||
#endif
|
||||
/* Try malloc() first. It works better if it works. */
|
||||
addr = malloc(ti->bounce_size, M_DEVBUF, M_NOWAIT);
|
||||
if (addr != NULL) {
|
||||
if (bs_dmarangecheck(addr, ti->bounce_size) == 0) {
|
||||
physaddr = (caddr_t) vtophys(addr);
|
||||
ti->bounce_addr = (u_int8_t *) addr;
|
||||
ti->bounce_phys = (u_int8_t *) physaddr;
|
||||
return;
|
||||
}
|
||||
free(buf, M_DEVBUF);
|
||||
}
|
||||
addr = contigmalloc(ti->bounce_size, M_DEVBUF, M_NOWAIT,
|
||||
0ul, RAM_END, 1ul, 0x10000ul);
|
||||
if (addr == NULL)
|
||||
goto bad;
|
||||
|
||||
physaddr = (caddr_t) vtophys(addr);
|
||||
if ((u_int) physaddr >= RAM_END)
|
||||
{
|
||||
/* XXX:
|
||||
* must free memory !
|
||||
*/
|
||||
goto bad;
|
||||
}
|
||||
|
||||
ti->bounce_addr = (u_int8_t *) addr;
|
||||
ti->bounce_phys = (u_int8_t *) physaddr;
|
||||
return;
|
||||
|
||||
bad:
|
||||
bs_printf(ti, "bs_alloc_buf", "no phys bounce buffer");
|
||||
printf("WARNING: this target is dislocated\n");
|
||||
}
|
||||
#endif /* __FreeBSD__ */
|
201
sys/i386/isa/bs/bsif.h
Normal file
201
sys/i386/isa/bs/bsif.h
Normal file
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) HONDA Naofumi, KATO Takenori, 1996. 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 as
|
||||
* the first lines of this file unmodified.
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/***************************************************
|
||||
* misc device header in bs_softc
|
||||
***************************************************/
|
||||
#ifdef __NetBSD__
|
||||
#define OS_DEPEND_DEVICE_HEADER \
|
||||
struct device sc_dev; \
|
||||
void *sc_ih;
|
||||
|
||||
#define OS_DEPEND_SCSI_HEADER \
|
||||
struct scsi_link sc_link;
|
||||
|
||||
#define OS_DEPEND_MISC_HEADER \
|
||||
pisa_device_handle_t sc_pdv; \
|
||||
bus_chipset_tag_t sc_bc; \
|
||||
bus_io_handle_t sc_ioh; \
|
||||
bus_io_handle_t sc_delayioh; \
|
||||
bus_mem_handle_t sc_memh;
|
||||
|
||||
#endif /* __NetBSD__ */
|
||||
#ifdef __FreeBSD__
|
||||
#define OS_DEPEND_DEVICE_HEADER \
|
||||
int unit;
|
||||
|
||||
#define OS_DEPEND_SCSI_HEADER \
|
||||
struct scsi_link sc_link;
|
||||
|
||||
#define OS_DEPEND_MISC_HEADER
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
#if defined(__NetBSD__)
|
||||
#define BSHW_NBPG NBPG
|
||||
#endif
|
||||
#if defined(__FreeBSD__)
|
||||
#define BSHW_NBPG PAGE_SIZE
|
||||
#endif
|
||||
|
||||
/***************************************************
|
||||
* include
|
||||
***************************************************/
|
||||
/* (I) common include */
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/disklabel.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/errno.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
|
||||
/* (II) os depend include */
|
||||
#ifdef __NetBSD__
|
||||
#include <sys/device.h>
|
||||
|
||||
#include <dev/isa/isareg.h>
|
||||
#include <dev/isa/isavar.h>
|
||||
#include <dev/isa/pisaif.h>
|
||||
|
||||
#include <machine/cpufunc.h>
|
||||
#include <machine/bus.h>
|
||||
#include <machine/intr.h>
|
||||
#include <machine/dvcfg.h>
|
||||
|
||||
#include <scsi/scsi_all.h>
|
||||
#include <scsi/scsiconf.h>
|
||||
#include <scsi/scsi_disk.h>
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/device.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
#include <machine/clock.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <vm/pmap.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <scsi/scsi_all.h>
|
||||
#include <scsi/scsiconf.h>
|
||||
#include <scsi/scsi_disk.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* BUS IO MAPPINGS & BS specific inclusion
|
||||
***************************************************/
|
||||
#ifdef __NetBSD__
|
||||
#define BUS_IO_DELAY ((void) bus_io_read_1(bsc->sc_bc, bsc->sc_delayioh, 0))
|
||||
#define BUS_IO_WEIGHT (bus_io_write_1(bsc->sc_bc, bsc->sc_delayioh, 0, 0))
|
||||
#define BUS_IOR(offs) (BUS_IO_DELAY, bus_io_read_1(bsc->sc_bc, bsc->sc_ioh, (offs)))
|
||||
#define BUS_IOW(offs, val) (BUS_IO_DELAY, bus_io_write_1(bsc->sc_bc, bsc->sc_ioh, (offs), (val)))
|
||||
|
||||
#include <dev/ic/wd33c93reg.h>
|
||||
#include <dev/isa/ccbque.h>
|
||||
|
||||
#include <dev/isa/scsi_dvcfg.h>
|
||||
#include <dev/isa/bs/bsvar.h>
|
||||
#include <dev/isa/bs/bshw.h>
|
||||
#include <dev/isa/bs/bsfunc.h>
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define BUS_IO_DELAY ((void) inb(0x5f))
|
||||
#define BUS_IO_WEIGHT (outb(0x5f, 0))
|
||||
#define BUS_IOR(offs) (BUS_IO_DELAY, inb(bsc->sc_iobase + (offs)))
|
||||
#define BUS_IOW(offs, val) (BUS_IO_DELAY, outb(bsc->sc_iobase + (offs), (val)))
|
||||
|
||||
#include <i386/isa/ic/wd33c93.h>
|
||||
#include <i386/isa/bs/ccbque.h>
|
||||
#include <i386/isa/bs/dvcfg.h>
|
||||
|
||||
#include <i386/isa/bs/scsi_dvcfg.h>
|
||||
#include <i386/isa/bs/bsvar.h>
|
||||
#include <i386/isa/bs/bshw.h>
|
||||
#include <i386/isa/bs/bsfunc.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* XS return type
|
||||
***************************************************/
|
||||
#ifdef __NetBSD__
|
||||
#define XSBS_INT32T int
|
||||
#endif /* __NetBSD__ */
|
||||
#ifdef __FreeBSD__
|
||||
#define XSBS_INT32T int32_t
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* xs flags's abstraction (all currently used)
|
||||
***************************************************/
|
||||
#define XSBS_ITSDONE ITSDONE
|
||||
#define XSBS_SCSI_NOSLEEP SCSI_NOSLEEP
|
||||
#ifdef __NetBSD__
|
||||
#define XSBS_SCSI_POLL SCSI_POLL
|
||||
#endif /* __NetBSD__ */
|
||||
#ifdef __FreeBSD__
|
||||
#define XSBS_SCSI_POLL SCSI_NOMASK
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* Special operations
|
||||
***************************************************/
|
||||
#ifdef __FreeBSD__
|
||||
#define BS_ADDRESS_CHECK
|
||||
#endif /* __FreeBSD__ */
|
||||
|
||||
/***************************************************
|
||||
* declare
|
||||
***************************************************/
|
||||
/* (I) common declare */
|
||||
void bs_alloc_buf __P((struct targ_info *));
|
||||
XSBS_INT32T bs_target_open __P((struct scsi_link *, struct cfdata *));
|
||||
XSBS_INT32T bs_scsi_cmd __P((struct scsi_xfer *));
|
||||
|
||||
extern int delaycount;
|
||||
|
||||
/* (II) os depend declare */
|
||||
#ifdef __NetBSD__
|
||||
int bsprobe __P((struct device *, struct device *, void *));
|
||||
void bsattach __P((struct device *, struct device *, void *));
|
||||
#endif /* __NetBSD__ */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
u_int32_t bs_adapter_info __P((int));
|
||||
#define delay(y) DELAY(y)
|
||||
extern int dma_init_flag;
|
||||
#define softintr(y) ipending |= (y)
|
||||
#endif /* __FreeBSD__ */
|
542
sys/i386/isa/bs/bsvar.h
Normal file
542
sys/i386/isa/bs/bsvar.h
Normal file
@ -0,0 +1,542 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994, 1995, 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#define BS_INLINE inline
|
||||
|
||||
/**************************************************
|
||||
* CONTROL FLAGS (cf_flags)
|
||||
*************************************************/
|
||||
#define BSC_FASTACK 0x01
|
||||
#define BSC_SMITSAT_DISEN 0x02
|
||||
#define BSC_CHIP_CLOCK(dvcfg) (((dvcfg) >> 4) & 0x03)
|
||||
|
||||
#define BS_SCSI_SYNC DVF_SCSI_SYNC
|
||||
#define BS_SCSI_DISC DVF_SCSI_DISC
|
||||
#define BS_SCSI_WAIT DVF_SCSI_WAIT
|
||||
#define BS_SCSI_LINK DVF_SCSI_LINK
|
||||
#define BS_SCSI_QTAG DVF_SCSI_QTAG
|
||||
#define BS_SCSI_NOSAT DVF_SCSI_SP0
|
||||
#define BS_SCSI_NOPARITY DVF_SCSI_NOPARITY
|
||||
#define BS_SCSI_SAVESP DVF_SCSI_SAVESP
|
||||
#define BS_SCSI_NOSMIT DVF_SCSI_SP1
|
||||
#define BS_SCSI_PERIOD(XXX) DVF_SCSI_PERIOD(XXX)
|
||||
#define BS_SCSI_OFFSET(XXX) DVF_SCSI_OFFSET(XXX)
|
||||
#define BS_SCSI_SYNCMASK DVF_SCSI_SYNCMASK
|
||||
#define BS_SCSI_BITS DVF_SCSI_BITS
|
||||
|
||||
#define BS_SCSI_DEFCFG (BS_SCSI_NOSAT | DVF_SCSI_DEFCFG)
|
||||
|
||||
#define BS_SCSI_POSITIVE (BS_SCSI_SYNC | BS_SCSI_DISC | BS_SCSI_LINK)
|
||||
#define BS_SCSI_NEGATIVE (BS_SCSI_WAIT | BS_SCSI_NOSAT | BS_SCSI_NOPARITY |\
|
||||
BS_SCSI_SAVESP | BS_SCSI_NOSMIT)
|
||||
/*******************************************
|
||||
* CONFIG SECTION
|
||||
******************************************/
|
||||
/* Enable timeout watch dog */
|
||||
#define BS_DEFAULT_TIMEOUT_SECOND 16 /* default 16 sec */
|
||||
#define BS_SYNC_TIMEOUT 16
|
||||
#define BS_STARTUP_TIMEOUT 60
|
||||
#define BS_MOTOR_TIMEOUT 120
|
||||
#define BS_TIMEOUT_CHECK_INTERVAL 4 /* check each 4 sec */
|
||||
|
||||
/* If you use memory over 16M */
|
||||
#ifdef SCSI_BOUNCE_SIZE
|
||||
#define BS_BOUNCE_SIZE SCSI_BOUNCE_SIZE
|
||||
#else /* !SCSI_BOUNCE_SIZE */
|
||||
#define BS_BOUNCE_SIZE 0
|
||||
#endif /* !SCSI_BOUNCE_SIZE */
|
||||
|
||||
/* debug */
|
||||
#define BS_STATICS 1
|
||||
#define BS_DIAG 1
|
||||
#define BS_DEBUG_ROUTINE 1
|
||||
#define BS_DEBUG 1
|
||||
/* #define SHOW_PORT 1 */
|
||||
|
||||
/**************************************************
|
||||
* PARAMETER
|
||||
**************************************************/
|
||||
#define NTARGETS 8
|
||||
#define RETRIES 4 /* number of retries before giving up */
|
||||
#define HARDRETRIES 3
|
||||
#define XSMAX 4
|
||||
#define BSDMABUFSIZ 0x10000
|
||||
#define BS_MAX_CCB (XSMAX * (NTARGETS - 1))
|
||||
|
||||
#define BSCMDSTART 0
|
||||
#define BSCMDRESTART 0x01
|
||||
#define BSCMDFORCE 0x02
|
||||
|
||||
#define BS_TIMEOUT_INTERVAL (hz * BS_TIMEOUT_CHECK_INTERVAL)
|
||||
|
||||
/**************************************************
|
||||
* SCSI PHASE
|
||||
**************************************************/
|
||||
enum scsi_phase {
|
||||
FREE = 0,
|
||||
HOSTQUEUE,
|
||||
DISCONNECTED,
|
||||
IOCOMPLETED,
|
||||
ATTENTIONASSERT,
|
||||
DISCONNECTASSERT,
|
||||
SELECTASSERT,
|
||||
SELECTED,
|
||||
RESELECTED,
|
||||
MSGIN,
|
||||
MSGOUT,
|
||||
STATUSIN,
|
||||
CMDPHASE,
|
||||
DATAPHASE,
|
||||
SATSEL,
|
||||
SATRESEL,
|
||||
SATSDP,
|
||||
SATCOMPSEQ,
|
||||
UNDEF,
|
||||
};
|
||||
|
||||
/**************************************************
|
||||
* SCSI PHASE CONTROL MACRO
|
||||
**************************************************/
|
||||
#define BS_HOST_START \
|
||||
{ \
|
||||
bsc->sc_nexus = ti; \
|
||||
}
|
||||
|
||||
#define BS_HOST_TERMINATE \
|
||||
{ \
|
||||
bsc->sc_selwait = NULL; \
|
||||
bsc->sc_nexus = NULL; \
|
||||
}
|
||||
|
||||
#define BS_SELECTION_START \
|
||||
{ \
|
||||
bsc->sc_selwait = ti; \
|
||||
}
|
||||
|
||||
#define BS_SELECTION_TERMINATE \
|
||||
{ \
|
||||
bsc->sc_selwait = NULL; \
|
||||
}
|
||||
|
||||
#define BS_SETUP_PHASE(PHASE) \
|
||||
{ \
|
||||
ti->ti_ophase = ti->ti_phase; \
|
||||
ti->ti_phase = (PHASE); \
|
||||
}
|
||||
|
||||
#define BS_SETUP_MSGPHASE(PHASE) \
|
||||
{ \
|
||||
bsc->sc_msgphase = (PHASE); \
|
||||
}
|
||||
|
||||
#define BS_SETUP_SYNCSTATE(STATE) \
|
||||
{ \
|
||||
ti->ti_syncnow.state = (STATE); \
|
||||
}
|
||||
|
||||
#define BS_SETUP_TARGSTATE(STATE) \
|
||||
{ \
|
||||
ti->ti_state = (STATE); \
|
||||
}
|
||||
|
||||
#define BS_LOAD_SDP \
|
||||
{ \
|
||||
bsc->sc_p.data = ti->ti_scsp.data; \
|
||||
bsc->sc_p.datalen = ti->ti_scsp.datalen; \
|
||||
bsc->sc_p.seglen = ti->ti_scsp.seglen; \
|
||||
}
|
||||
|
||||
#define BS_RESTORE_SDP \
|
||||
{ \
|
||||
bsc->sc_p = ti->ti_scsp; \
|
||||
}
|
||||
|
||||
#define BS_SAVE_SDP \
|
||||
{ \
|
||||
ti->ti_scsp = bsc->sc_p; \
|
||||
}
|
||||
|
||||
/**************************************************
|
||||
* STRUCTURES
|
||||
**************************************************/
|
||||
struct msgbase {
|
||||
#define MAXMSGLEN 8
|
||||
u_int8_t msg[MAXMSGLEN];
|
||||
u_int msglen;
|
||||
|
||||
u_int flag;
|
||||
};
|
||||
|
||||
struct syncdata {
|
||||
u_int8_t period;
|
||||
u_int8_t offset;
|
||||
|
||||
#define BS_SYNCMSG_NULL 0x00
|
||||
#define BS_SYNCMSG_ASSERT 0x01
|
||||
#define BS_SYNCMSG_REJECT 0x02
|
||||
#define BS_SYNCMSG_ACCEPT 0x03
|
||||
#define BS_SYNCMSG_REQUESTED 0x04
|
||||
u_int state;
|
||||
};
|
||||
|
||||
struct sc_p {
|
||||
u_int8_t *data;
|
||||
int datalen;
|
||||
|
||||
u_int8_t *segaddr;
|
||||
int seglen;
|
||||
|
||||
u_int8_t *bufp;
|
||||
};
|
||||
|
||||
/* targ_info error flags */
|
||||
#define BSDMAABNORMAL 0x01
|
||||
#define BSCMDABNORMAL 0x02
|
||||
#define BSPARITY 0x04
|
||||
#define BSSTATUSERROR 0x08
|
||||
#define BSTIMEOUT 0x10
|
||||
#define BSREQSENSE 0x20
|
||||
#define BSSELTIMEOUT 0x40
|
||||
#define BSFATALIO 0x80
|
||||
#define BSMSGERROR 0x100
|
||||
#define BSTRYRECOV 0x200
|
||||
#define BSABNORMAL 0x400
|
||||
#define BSTARGETBUSY 0x800
|
||||
|
||||
#define BSERRORBITS "\020\014busy\013abnormal\012retry\011msgerr\010fatal\007seltimeout\006sense\005timeout\004statuserr\003parity\002cmderr\001dmaerr"
|
||||
|
||||
/* ccb & targ_info flags & cmd flags*/
|
||||
#define BSREAD 0x0001
|
||||
#define BSSAT 0x0002
|
||||
#define BSLINK 0x0004
|
||||
#define BSERROROK 0x0008
|
||||
#define BSSMIT 0x0010
|
||||
#define BSDISC 0x1000
|
||||
#define BSFORCEIOPOLL 0x2000
|
||||
|
||||
#define BSCASTAT 0x01000000
|
||||
#define BSSENSECCB 0x02000000
|
||||
#define BSQUEUED 0x04000000
|
||||
#define BSALTBUF 0x08000000
|
||||
#define BSITSDONE 0x10000000
|
||||
#define BSNEXUS 0x20000000
|
||||
|
||||
#define BSCFLAGSMASK (0xffff)
|
||||
|
||||
struct ccb {
|
||||
TAILQ_ENTRY(ccb) ccb_chain;
|
||||
|
||||
struct scsi_xfer *xs; /* upper drivers info */
|
||||
|
||||
u_int lun; /* lun */
|
||||
|
||||
u_int flags; /* control flags */
|
||||
|
||||
int rcnt; /* retry counter of this ccb */
|
||||
|
||||
u_int error; /* recorded error */
|
||||
|
||||
/*****************************************
|
||||
* scsi cmd & data
|
||||
*****************************************/
|
||||
u_int8_t *cmd; /* scsi cmd */
|
||||
int cmdlen;
|
||||
|
||||
u_int8_t *data; /* scsi data */
|
||||
int datalen;
|
||||
|
||||
u_int8_t msgout[MAXMSGLEN]; /* scsi msgout */
|
||||
u_int msgoutlen;
|
||||
|
||||
/*****************************************
|
||||
* timeout counter
|
||||
*****************************************/
|
||||
int tc;
|
||||
int tcmax;
|
||||
};
|
||||
|
||||
GENERIC_CCB_ASSERT(bs, ccb)
|
||||
|
||||
/* target info */
|
||||
struct targ_info {
|
||||
TAILQ_ENTRY(targ_info) ti_tchain; /* targ_info link */
|
||||
|
||||
TAILQ_ENTRY(targ_info) ti_wchain; /* wait link */
|
||||
|
||||
struct bs_softc *ti_bsc; /* our controller */
|
||||
u_int ti_id; /* scsi id */
|
||||
u_int ti_lun; /* current lun */
|
||||
|
||||
struct ccbtab ti_ctab, ti_bctab; /* ccb */
|
||||
|
||||
#define BS_TARG_NULL 0
|
||||
#define BS_TARG_CTRL 1
|
||||
#define BS_TARG_START 2
|
||||
#define BS_TARG_SYNCH 3
|
||||
#define BS_TARG_RDY 4
|
||||
int ti_state; /* target state */
|
||||
|
||||
u_int ti_cfgflags; /* target cfg flags */
|
||||
|
||||
u_int ti_flags; /* flags */
|
||||
u_int ti_mflags; /* flags masks */
|
||||
|
||||
u_int ti_error; /* error flags */
|
||||
u_int ti_herrcnt; /* hardware err retry counter */
|
||||
|
||||
/*****************************************
|
||||
* scsi phase data
|
||||
*****************************************/
|
||||
struct sc_p ti_scsp; /* saved scsi data pointer */
|
||||
|
||||
enum scsi_phase ti_phase; /* scsi phase */
|
||||
enum scsi_phase ti_ophase; /* previous scsi phase */
|
||||
|
||||
u_int8_t ti_status; /* status in */
|
||||
|
||||
u_int8_t ti_msgin[MAXMSGLEN]; /* msgin buffer */
|
||||
int ti_msginptr;
|
||||
|
||||
u_int8_t ti_msgout; /* last msgout byte */
|
||||
u_int8_t ti_emsgout; /* last msgout byte */
|
||||
u_int ti_omsgoutlen; /* for retry msgout */
|
||||
|
||||
struct syncdata ti_syncmax; /* synch data (scsi) */
|
||||
struct syncdata ti_syncnow;
|
||||
u_int8_t ti_sync; /* synch val (chip) */
|
||||
|
||||
/*****************************************
|
||||
* bounce buffer & smit data pointer
|
||||
*****************************************/
|
||||
u_int8_t *bounce_phys;
|
||||
u_int8_t *bounce_addr;
|
||||
u_int bounce_size;
|
||||
|
||||
u_int8_t *sm_vaddr;
|
||||
|
||||
/*****************************************
|
||||
* target inq data
|
||||
*****************************************/
|
||||
u_int8_t targ_type;
|
||||
u_int8_t targ_support;
|
||||
|
||||
/*****************************************
|
||||
* generic scsi cmd buffer for this target
|
||||
*****************************************/
|
||||
u_int8_t scsi_cmd[12];
|
||||
struct scsi_sense_data sense;
|
||||
};
|
||||
|
||||
TAILQ_HEAD(titab, targ_info);
|
||||
struct bshw;
|
||||
|
||||
struct bs_softc {
|
||||
/*****************************************
|
||||
* OS depend header
|
||||
*****************************************/
|
||||
OS_DEPEND_DEVICE_HEADER
|
||||
|
||||
OS_DEPEND_SCSI_HEADER
|
||||
|
||||
OS_DEPEND_MISC_HEADER
|
||||
|
||||
/*****************************************
|
||||
* target link
|
||||
*****************************************/
|
||||
struct targ_info *sc_ti[NTARGETS];
|
||||
u_int sc_openf;
|
||||
|
||||
struct titab sc_sttab;
|
||||
struct titab sc_titab;
|
||||
|
||||
/*****************************************
|
||||
* current scsi phase
|
||||
*****************************************/
|
||||
struct targ_info *sc_nexus; /* current active nexus */
|
||||
|
||||
enum scsi_phase sc_msgphase; /* scsi phase pointed by msg */
|
||||
|
||||
struct targ_info *sc_selwait; /* selection assert */
|
||||
|
||||
u_int sc_dtgnum; /* disconnected target */
|
||||
|
||||
/*****************************************
|
||||
* current scsi data pointer
|
||||
*****************************************/
|
||||
struct sc_p sc_p; /* scsi data pointer */
|
||||
|
||||
int sc_dmadir; /* dma direction */
|
||||
|
||||
int sm_tdatalen; /* smit data transfer bytes */
|
||||
|
||||
/*****************************************
|
||||
* parameter
|
||||
*****************************************/
|
||||
u_int sc_retry; /* max retry count */
|
||||
|
||||
#define BSDMATRANSFER 0x01
|
||||
#define BSDMASTART 0x02
|
||||
#define BSSMITSTART 0x04
|
||||
#define BSUNDERRESET 0x08
|
||||
#define BSRESET 0x10
|
||||
#define BSSTARTTIMEOUT 0x20
|
||||
#define BSPOLLDONE 0x100
|
||||
#define BSJOBDONE 0x200
|
||||
#define BSBSMODE 0x400
|
||||
#define BSINACTIVE 0x800
|
||||
volatile int sc_flags; /* host flags */
|
||||
|
||||
#define BSC_NULL 0
|
||||
#define BSC_BOOTUP 1
|
||||
#define BSC_TARG_CHECK 2
|
||||
#define BSC_RDY 3
|
||||
int sc_hstate; /* host state */
|
||||
|
||||
/*****************************************
|
||||
* polling misc
|
||||
*****************************************/
|
||||
u_int sc_wc; /* weight count */
|
||||
|
||||
int sc_poll;
|
||||
struct ccb *sc_outccb;
|
||||
|
||||
/*****************************************
|
||||
* wd33c93 chip depend section
|
||||
*****************************************/
|
||||
u_int sc_cfgflags; /* hardware cfg flags */
|
||||
|
||||
struct bshw *sc_hw; /* hw selection */
|
||||
|
||||
u_int8_t *sm_vaddr; /* smit buffer */
|
||||
|
||||
u_int sc_RSTdelay;
|
||||
|
||||
int sc_hwlock; /* hardware lock count */
|
||||
|
||||
int sc_iobase; /* iobase for FreeBSD */
|
||||
u_int32_t sc_irqmasks; /* irq */
|
||||
|
||||
u_int sc_dmachan; /* dma channel */
|
||||
u_int8_t sc_busstat; /* scsi bus status register */
|
||||
u_int8_t sc_hostid; /* host scsi id */
|
||||
u_int8_t sc_cspeed; /* chip clock rate */
|
||||
u_int8_t sc_membank; /* memory back (NEC) register */
|
||||
|
||||
/*****************************************
|
||||
* our name
|
||||
*****************************************/
|
||||
#define BS_DVNAME_LEN 16
|
||||
u_char sc_dvname[BS_DVNAME_LEN];
|
||||
};
|
||||
|
||||
/*************************************************
|
||||
* debug
|
||||
*************************************************/
|
||||
#ifdef BS_STATICS
|
||||
struct bs_statics {
|
||||
u_int select;
|
||||
u_int select_miss_in_assert;
|
||||
u_int select_miss_by_reselect;
|
||||
u_int select_miss;
|
||||
u_int select_win;
|
||||
u_int selected;
|
||||
u_int disconnected;
|
||||
u_int reselect;
|
||||
};
|
||||
|
||||
extern struct bs_statics bs_statics[NTARGETS];
|
||||
extern u_int bs_linkcmd_count[];
|
||||
extern u_int bs_bounce_used[];
|
||||
#endif /* BS_STATICS */
|
||||
|
||||
#ifdef BS_DEBUG_ROUTINE
|
||||
#ifndef DDB
|
||||
#define Debugger() panic("should call debugger here (bs.c)")
|
||||
#endif /* DDB */
|
||||
#ifdef BS_DEBUG
|
||||
extern int bs_debug_flag;
|
||||
#endif /* BS_DEBUG */
|
||||
#endif /* BS_DEBUG_ROUTINE */
|
||||
|
||||
/*************************************************
|
||||
* Function declare
|
||||
*************************************************/
|
||||
int bs_scsi_cmd_internal __P((struct ccb *, u_int));
|
||||
struct ccb *bscmddone __P((struct targ_info *));
|
||||
int bscmdstart __P((struct targ_info *, int));
|
||||
int bs_scsi_cmd_poll __P((struct targ_info *, struct ccb *));
|
||||
int bs_sequencer __P((struct bs_softc *));
|
||||
void bs_poll_timeout __P((struct bs_softc *, char *));
|
||||
|
||||
/*************************************************
|
||||
* XXX
|
||||
*************************************************/
|
||||
/* misc error */
|
||||
#define NOTARGET -2
|
||||
#define HASERROR -1
|
||||
|
||||
/* XXX: use scsi_message.h */
|
||||
/* status */
|
||||
#define ST_GOOD 0x00
|
||||
#define ST_CHKCOND 0x02
|
||||
#define ST_MET 0x04
|
||||
#define ST_BUSY 0x08
|
||||
#define ST_INTERGOOD 0x10
|
||||
#define ST_INTERMET 0x14
|
||||
#define ST_CONFLICT 0x18
|
||||
#define ST_QUEFULL 0x28
|
||||
#define ST_UNK 0xff
|
||||
|
||||
/* message */
|
||||
#define MSG_COMP 0x00
|
||||
#define MSG_EXTEND 0x01
|
||||
|
||||
#define MKMSG_EXTEND(XLEN, XCODE) ((((u_int)(XLEN)) << NBBY) | ((u_int)(XCODE)))
|
||||
#define MSG_EXTEND_MDPCODE 0x00
|
||||
#define MSG_EXTEND_MDPLEN 0x05
|
||||
#define MSG_EXTEND_SYNCHCODE 0x01
|
||||
#define MSG_EXTEND_SYNCHLEN 0x03
|
||||
#define MSG_EXTEND_WIDECODE 0x03
|
||||
#define MSG_EXTEND_WIDELEN 0x02
|
||||
|
||||
#define MSG_SAVESP 0x02
|
||||
#define MSG_RESTORESP 0x03
|
||||
#define MSG_DISCON 0x04
|
||||
#define MSG_I_ERROR 0x05
|
||||
#define MSG_ABORT 0x06
|
||||
#define MSG_REJECT 0x07
|
||||
#define MSG_NOOP 0x08
|
||||
#define MSG_PARITY 0x09
|
||||
#define MSG_LCOMP 0x0a
|
||||
#define MSG_LCOMP_F 0x0b
|
||||
#define MSG_RESET 0x0c
|
130
sys/i386/isa/bs/ccbque.h
Normal file
130
sys/i386/isa/bs/ccbque.h
Normal file
@ -0,0 +1,130 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1994, 1995, 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Common command control queue funcs.
|
||||
* Written by N. Honda.
|
||||
*/
|
||||
|
||||
#ifndef _CCBQUE_H_
|
||||
#define _CCBQUE_H_
|
||||
|
||||
/* (I) structure and prototype */
|
||||
#define GENERIC_CCB_ASSERT(DEV, CCBTYPE) \
|
||||
TAILQ_HEAD(CCBTYPE##tab, CCBTYPE); \
|
||||
struct CCBTYPE##que { \
|
||||
struct CCBTYPE##tab CCBTYPE##tab; \
|
||||
int count; \
|
||||
int maxccb; \
|
||||
}; \
|
||||
void DEV##_init_ccbque __P((int)); \
|
||||
struct CCBTYPE *DEV##_get_ccb __P((int)); \
|
||||
void DEV##_free_ccb __P((struct CCBTYPE *));
|
||||
|
||||
/* (II) static allocated memory */
|
||||
#define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE) \
|
||||
static struct CCBTYPE##que CCBTYPE##que;
|
||||
|
||||
/* (III) functions */
|
||||
#define GENERIC_CCB(DEV, CCBTYPE, CHAIN) \
|
||||
\
|
||||
void \
|
||||
DEV##_init_ccbque(count) \
|
||||
int count; \
|
||||
{ \
|
||||
if (CCBTYPE##que.maxccb == 0) \
|
||||
TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab) \
|
||||
CCBTYPE##que.maxccb += count; \
|
||||
} \
|
||||
\
|
||||
struct CCBTYPE * \
|
||||
DEV##_get_ccb(flags) \
|
||||
int flags; \
|
||||
{ \
|
||||
struct CCBTYPE *cb; \
|
||||
int s = splbio(); \
|
||||
\
|
||||
do \
|
||||
{ \
|
||||
if (CCBTYPE##que.count > CCBTYPE##que.maxccb) \
|
||||
{ \
|
||||
if (flags) \
|
||||
{ \
|
||||
cb = NULL; \
|
||||
goto done; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
tsleep((caddr_t) &CCBTYPE##que.count, \
|
||||
PRIBIO, "ccbwait", 0); \
|
||||
continue; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (cb = CCBTYPE##que.CCBTYPE##tab.tqh_first) \
|
||||
{ \
|
||||
TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN)\
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
if (cb = malloc(sizeof(*cb), M_DEVBUF, M_NOWAIT))\
|
||||
{ \
|
||||
bzero(cb, sizeof(*cb)); \
|
||||
break; \
|
||||
} \
|
||||
else if (flags) \
|
||||
goto done; \
|
||||
\
|
||||
tsleep((caddr_t) &CCBTYPE##que.count, \
|
||||
PRIBIO, "ccbwait", 0); \
|
||||
} \
|
||||
} \
|
||||
while (1); \
|
||||
CCBTYPE##que.count ++; \
|
||||
\
|
||||
done: \
|
||||
splx(s); \
|
||||
return cb; \
|
||||
} \
|
||||
\
|
||||
void \
|
||||
DEV##_free_ccb(cb) \
|
||||
struct CCBTYPE *cb; \
|
||||
{ \
|
||||
int s = splbio(); \
|
||||
\
|
||||
TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN) \
|
||||
CCBTYPE##que.count --; \
|
||||
\
|
||||
if (CCBTYPE##que.count == CCBTYPE##que.maxccb) \
|
||||
wakeup ((caddr_t) &CCBTYPE##que.count); \
|
||||
splx(s); \
|
||||
}
|
||||
#endif /* !_CCBQUE_H_ */
|
64
sys/i386/isa/bs/dvcfg.h
Normal file
64
sys/i386/isa/bs/dvcfg.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* $NetBSD$ */
|
||||
/*
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1996 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.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1996 Naofumi HONDA. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _I386_DVCFG_H_
|
||||
#define _I386_DVCFG_H_
|
||||
|
||||
typedef void *dvcfg_hw_t;
|
||||
|
||||
struct dvcfg_hwsel {
|
||||
int cfg_max;
|
||||
|
||||
dvcfg_hw_t *cfg_sel;
|
||||
};
|
||||
|
||||
#define DVCFG_MAJOR(dvcfg) (((u_int)(dvcfg)) >> 16)
|
||||
#define DVCFG_MINOR(dvcfg) (((u_int)(dvcfg)) & 0xffff)
|
||||
|
||||
#define DVCFG_MKCFG(major, minor) ((((u_int)(major)) << 16) | ((minor) & 0xffff))
|
||||
|
||||
#define DVCFG_HWSEL_SZ(array) (sizeof(array) / sizeof(dvcfg_hw_t))
|
||||
|
||||
static inline dvcfg_hw_t dvcfg_hw __P((struct dvcfg_hwsel *, u_int));
|
||||
|
||||
static inline dvcfg_hw_t
|
||||
dvcfg_hw(selp, num)
|
||||
struct dvcfg_hwsel *selp;
|
||||
u_int num;
|
||||
{
|
||||
|
||||
return ((num >= selp->cfg_max) ? NULL : selp->cfg_sel[num]);
|
||||
}
|
||||
|
||||
#define DVCFG_HW(SELP, NUM) dvcfg_hw((SELP), (NUM))
|
||||
#endif /* _I386_DVCFG_H_ */
|
@ -1,127 +1,155 @@
|
||||
/*
|
||||
* PC9801 SCSI I/F (PC-9801-55)
|
||||
* modified for PC9801 by A.Kojima
|
||||
* Kyoto University Microcomputer Club (KMC)
|
||||
* [NetBSD for NEC PC98 series]
|
||||
* Copyright (c) 1996 NetBSD/pc98 porting staff.
|
||||
* Copyright (c) 1996 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.
|
||||
*/
|
||||
|
||||
/* I/O address */
|
||||
#ifndef _WD33C93REG_H_
|
||||
#define _WD33C93REG_H_
|
||||
|
||||
/* WD33C93 */
|
||||
#define SCSI_ADR_REG 0xcc0 /* write Address Register */
|
||||
#define SCSI_AUX_REG 0xcc0 /* read Aux. Status Register */
|
||||
#define SCSI_CTL_REG 0xcc2 /* read/write Control Registers */
|
||||
/* wd33c93 register */
|
||||
#define wd3s_oid 0x00
|
||||
#define IDR_FS_15_20 0x80
|
||||
#define IDR_FS_12_15 0x40
|
||||
#define IDR_FS_8_10 0x00
|
||||
#define IDR_EHP 0x10
|
||||
#define IDR_EAF 0x08
|
||||
#define IDR_IDM 0x07
|
||||
|
||||
/* Port */
|
||||
#define SCSI_STAT_RD 0xcc4 /* read Status Read */
|
||||
#define SCSI_CMD_WRT 0xcc4 /* write Command Write */
|
||||
#define wd3s_ctrl 0x01
|
||||
#define CR_DMA 0x80
|
||||
#define CR_DMAD 0x40
|
||||
#define CR_HLT_HOST_PARITY 0x10
|
||||
#define CR_DIS_INT 0x08
|
||||
#define CR_IDIS_INT 0x04
|
||||
#define CR_HLT_ATN 0x02
|
||||
#define CR_HLT_BUS_PARITY 0x01
|
||||
#define CR_DEFAULT (CR_DIS_INT | CR_IDIS_INT)
|
||||
#define CR_DEFAULT_HP (CR_DEFAULT | CR_HLT_BUS_PARITY)
|
||||
|
||||
#if 0 /* H98 extended mode */
|
||||
/* WD33C93 */
|
||||
#define SCSI_ADR_REG 0xee0 /* write Address Register */
|
||||
#define SCSI_AUX_REG 0xee0 /* read Control Register */
|
||||
#define SCSI_CTL_REG 0xee2 /* read/write Registers */
|
||||
#define wd3s_tout 0x02
|
||||
#define wd3s_cdb 0x03
|
||||
#define wd3s_lun 0x0f
|
||||
#define wd3s_cph 0x10
|
||||
#define wd3s_synch 0x11
|
||||
#define wd3s_cnt 0x12
|
||||
#define wd3s_did 0x15
|
||||
|
||||
/* Port */
|
||||
#define SCSI_STAT_RD 0xee4 /* read Status Read */
|
||||
#define SCSI_CMD_WRT 0xee4 /* write Command Write */
|
||||
#endif
|
||||
#define wd3s_sid 0x16
|
||||
#define SIDR_RESEL 0x80
|
||||
#define SIDR_SEL 0x40
|
||||
#define SIDR_VALID 0x08
|
||||
#define SIDR_IDM 0x07
|
||||
|
||||
/****************************************************************/
|
||||
#define wd3s_stat 0x17
|
||||
|
||||
/* WD33C93 Registers */
|
||||
#define REG_OWN_ID 0x00 /* Own ID */
|
||||
#define REG_CONTROL 0x01 /* Control */
|
||||
#define REG_TIMEOUT_PERIOD 0x02 /* Timeout Period */
|
||||
#define REG_TOTAL_SECTORS 0x03 /* Total Sectors */
|
||||
#define REG_TOTAL_HEADS 0x04 /* Total Heads */
|
||||
#define REG_TOTAL_CYL_H 0x05 /* Total Cylinders (MSB) */
|
||||
#define REG_TOTAL_CYL_L 0x06 /* Total Cylinders (LSB) */
|
||||
#define REG_LOG_SECTOR_HH 0x07 /* Logical Address (MSB) */
|
||||
#define REG_LOG_SECTOR_HL 0x08 /* Logical Address */
|
||||
#define REG_LOG_SECTOR_LH 0x09 /* Logical Address */
|
||||
#define REG_LOG_SECTOR_LL 0x0a /* Logical Address (LSB) */
|
||||
#define REG_SECTOR_NUMBER 0x0b /* Sector Number */
|
||||
#define REG_HEAD_NUMBER 0x0c /* Head Number */
|
||||
#define REG_CYL_NUMBER_H 0x0d /* Cylinder Number (MSB) */
|
||||
#define REG_CYL_NUMBER_L 0x0e /* Cylinder Number (LSB) */
|
||||
#define REG_TARGET_LUN 0x0f /* Target LUN */
|
||||
#define REG_CMD_PHASE 0x10 /* Command Phase */
|
||||
#define REG_SYNC_TFR 0x11 /* Synchronous Transfer */
|
||||
#define REG_TFR_COUNT_H 0x12 /* Transfer Count (MSB) */
|
||||
#define REG_TFR_COUNT_M 0x13 /* Transfer Count */
|
||||
#define REG_TFR_COUNT_L 0x14 /* Transfer Count (LSB) */
|
||||
#define REG_DST_ID 0x15 /* Destination ID */
|
||||
#define REG_SRC_ID 0x16 /* Source ID */
|
||||
#define REG_SCSI_STATUS 0x17 /* SCSI Status (Read Only) */
|
||||
#define REG_COMMAND 0x18 /* Command */
|
||||
#define REG_DATA 0x19 /* Data */
|
||||
#define BSR_CM 0xf0
|
||||
#define BSR_CMDCPL 0x10
|
||||
#define BSR_CMDABT 0x20
|
||||
#define BSR_CMDERR 0x40
|
||||
#define BSR_CMDREQ 0x80
|
||||
|
||||
/* PC98 only */
|
||||
#define REG_MEM_BANK 0x30 /* Memory Bank */
|
||||
#define REG_MEM_WIN 0x31 /* Memery Window */
|
||||
#define REG_RESERVED1 0x32 /* NEC Reserved 1 */
|
||||
#define REG_RESET_INT 0x33 /* Reset/Int */
|
||||
#define REG_RESERVED2 0x34 /* NEC Reserved 2 */
|
||||
#define BSR_SM 0x0f
|
||||
#define BSR_PM 0x07
|
||||
#define BSR_PHVALID 0x08
|
||||
#define BSR_IOR 0x01
|
||||
#define BSR_DATAOUT 0x00
|
||||
#define BSR_DATAIN 0x01
|
||||
#define BSR_CMDOUT 0x02
|
||||
#define BSR_STATIN 0x03
|
||||
#define BSR_UNSPINFO0 0x04
|
||||
#define BSR_UNSPINFO1 0x05
|
||||
#define BSR_MSGOUT 0x06
|
||||
#define BSR_MSGIN 0x07
|
||||
|
||||
/****************************************************************/
|
||||
#define BSR_SELECTED 0x11
|
||||
#define BSR_SATFIN 0x16
|
||||
#define BSR_ACKREQ 0x20
|
||||
#define BSR_SATSDP 0x21
|
||||
#define BSR_RESEL 0x80
|
||||
#define BSR_DISC 0x85
|
||||
|
||||
/* WD33C93 Commands */
|
||||
#define CMD_RESET 0x00 /* Reset */
|
||||
#define CMD_ABORT 0x01 /* Abort */
|
||||
#define CMD_ASSERT_ATN 0x02 /* Assert ATN */
|
||||
#define CMD_NEGATE_ATN 0x03 /* Negate ATN */
|
||||
#define CMD_DISCONNECT 0x04 /* Disconnect */
|
||||
#define CMD_RESELECT 0x05 /* Reselect */
|
||||
#define CMD_SELECT_ATN 0x06 /* Select with ATN */
|
||||
#define CMD_SELECT_NO_ATN 0x07 /* Select without ATN */
|
||||
#define CMD_SELECT_ATN_TFR 0x08 /* Select with ATN and Transfer */
|
||||
#define CMD_SELECT_NO_ATN_TFR 0x09 /* Select without ATN and Transfer */
|
||||
#define CMD_RESELECT_RCV_DATA 0x0a /* Reselect and Recieve Data */
|
||||
#define CMD_RESELECT_SEND_DATA 0x0b /* Reselect and Send Data */
|
||||
#define CMD_WAIT_SELECT_RCV 0x0c /* Wait for Select and Recieve */
|
||||
#define CMD_RCV_CMD 0x10 /* Recieve Command */
|
||||
#define CMD_RCV_DATA 0x11 /* Recieve Data */
|
||||
#define CMD_RCV_MSG_OUT 0x12 /* Recieve Message Info Out*/
|
||||
#define CMD_RCV_UNSP_INFO_OUT 0x13 /* Recieve Unspecified Info Out */
|
||||
#define CMD_SEND_STATUS 0x14 /* Send Status */
|
||||
#define CMD_SEND_DATA 0x15 /* Send Data */
|
||||
#define CMD_SEND_MSG_IN 0x16 /* Send Message In */
|
||||
#define CMD_SEND_UNSP_INFO_IN 0x17 /* Send Unspecified Info In */
|
||||
#define CMD_TRANSLATE_ADDRESS 0x18 /* Translate Address */
|
||||
#define CMD_TFR_INFO 0x20 /* Transfer Info */
|
||||
#define CMD_TFR_PAD 0x21 /* Transfer Pad */
|
||||
#define CMD_SBT_SFX 0x80 /* single byte suffix */
|
||||
#define wd3s_cmd 0x18
|
||||
#define wd3s_data 0x19
|
||||
#define wd3s_qtag 0x1a
|
||||
|
||||
/* WD33C93 bus status register (lower nibble) */
|
||||
#define STAT_DATAOUT 0x08 /* Data out phase */
|
||||
#define STAT_DATAIN 0x09 /* Data in phase */
|
||||
#define STAT_CMDOUT 0x0a /* Command out phase */
|
||||
#define STAT_STATIN 0x0b /* Status in phase */
|
||||
#define STAT_MSGOUT 0x0e /* Message out phase */
|
||||
#define STAT_MSGIN 0x0f /* Message in phase */
|
||||
#define wd3s_mbank 0x30
|
||||
#define MBR_RST 0x02
|
||||
#define MBR_IEN 0x04
|
||||
|
||||
/* SCSI Status byte */
|
||||
#define SS_GOOD 0x00 /* Good status */
|
||||
#define SS_CHKCOND 0x02
|
||||
#define SS_MET 0x04
|
||||
#define SS_BUSY 0x08
|
||||
#define SS_INTERGOOD 0x10
|
||||
#define SS_INTERMET 0x14
|
||||
#define SS_CONFLICT 0x18
|
||||
#define wd3s_mwin 0x31
|
||||
#define wd3s_auxc 0x33
|
||||
#define AUXCR_HIDM 0x07
|
||||
#define AUXCR_INTM 0x38
|
||||
#define AUXCR_RRST 0x80
|
||||
|
||||
/* SCSI message system */
|
||||
#define MSG_COMPLETE 0x00 /* Command complete message */
|
||||
#define MSG_EXTEND 0x01 /* Extend message */
|
||||
#define MSG_SAVEPTR 0x02 /* Save data pointer message */
|
||||
#define MSG_RESTORE 0x03 /* Restore data pointer message */
|
||||
#define MSG_DISCON 0x04 /* Disconnect message */
|
||||
#define MSG_INIERROR 0x05
|
||||
#define MSG_ABORT 0x06
|
||||
#define MSG_REJECT 0x07
|
||||
#define MSG_NOP 0x08
|
||||
#define MSG_PARERROR 0x09
|
||||
#define MSG_LCOMPLETE 0x0a
|
||||
#define MSG_LCOMPLETEF 0x0b
|
||||
#define MSG_DEVRESET 0x0c
|
||||
#define MSG_IDENTIFY 0x80 /* Identify message */
|
||||
/* status port */
|
||||
#define STR_INT 0x80
|
||||
#define STR_LCI 0x40
|
||||
#define STR_BSY 0x20
|
||||
#define STR_CIP 0x10
|
||||
#define STR_PE 0x02
|
||||
#define STR_DBR 0x01
|
||||
#define STR_BUSY 0xf0
|
||||
|
||||
/* cmd port */
|
||||
#define CMDP_DMES 0x01
|
||||
#define CMDP_DMER 0x02
|
||||
#define CMDP_TCMS 0x04
|
||||
#define CMDP_TCMR 0x08
|
||||
#define CMDP_TCIR 0x10
|
||||
|
||||
/* wd33c93 chip cmds */
|
||||
#define WD3S_SBT 0x80
|
||||
#define WD3S_RESET 0x00
|
||||
#define WD3S_ABORT 0x01
|
||||
#define WD3S_ASSERT_ATN 0x02
|
||||
#define WD3S_NEGATE_ACK 0x03
|
||||
#define WD3S_DISCONNECT 0x04
|
||||
#define WD3S_RESELECT 0x05
|
||||
#define WD3S_SELECT_ATN 0x06
|
||||
#define WD3S_SELECT_NO_ATN 0x07
|
||||
#define WD3S_SELECT_ATN_TFR 0x08
|
||||
#define WD3S_SELECT_NO_ATN_TFR 0x09
|
||||
#define WD3S_RESELECT_RCV_DATA 0x0a
|
||||
#define WD3S_RESELECT_SEND_DATA 0x0b
|
||||
#define WD3S_WAIT_SELECT_RCV 0x0c
|
||||
#define WD3S_CMD_COMPSEQ 0x0d
|
||||
#define WD3S_SEND_DISC_MSG 0x0e
|
||||
#define WD3S_SET_IDI 0x0f
|
||||
#define WD3S_RCV_CMD 0x10
|
||||
#define WD3S_RCV_DATA 0x11
|
||||
#define WD3S_RCV_MSG_OUT 0x12
|
||||
#define WD3S_RCV_UNSP_INFO_OUT 0x13
|
||||
#define WD3S_SEND_STATUS 0x14
|
||||
#define WD3S_SEND_DATA 0x15
|
||||
#define WD3S_SEND_MSG_IN 0x16
|
||||
#define WD3S_SEND_UNSP_INFO_IN 0x17
|
||||
#define WD3S_TRANSLATE_ADDRESS 0x18
|
||||
#define WD3S_TFR_INFO 0x20
|
||||
|
||||
#endif /* !_WD33C93REG_H_ */
|
||||
|
@ -11,7 +11,7 @@
|
||||
# device lines is present in the ./LINT configuration file. If you are
|
||||
# in doubt as to the purpose or necessity of a line, check first in LINT.
|
||||
#
|
||||
# $Id: GENERIC98,v 1.8 1996/10/30 22:39:29 asami Exp $
|
||||
# $Id: GENERIC98,v 1.9 1996/11/14 08:46:11 asami Exp $
|
||||
|
||||
# GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks
|
||||
|
||||
@ -58,12 +58,6 @@ options COM_MULTIPORT
|
||||
#options SUSP_HLT # CPU enters suspend mode when HALT
|
||||
#options "DISABLE_5X86_LSSER" # Load-Store reordering enable
|
||||
#
|
||||
# sbic55.c.new
|
||||
#
|
||||
#options SCSI_SYNC # synchronous transfer mode
|
||||
#options FORCE_BUSMASTER
|
||||
#options "HA55BS_ID=0"
|
||||
#
|
||||
# IBM-PC HDD support
|
||||
#options COMPAT_ATDISK
|
||||
#
|
||||
@ -100,13 +94,24 @@ device wcd0 #IDE CD-ROM
|
||||
# for any number of installed devices.
|
||||
controller ncr0
|
||||
controller ahc0
|
||||
options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O,
|
||||
# so use PIO in the ahc driver in the
|
||||
# generic kernel.
|
||||
|
||||
controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr
|
||||
# sbic55.c.new
|
||||
#controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0xff vector sbicintr
|
||||
#
|
||||
# WD33C93 SCSI card (55/92 like board)
|
||||
#
|
||||
|
||||
options BS_TARG_SAFEMODE
|
||||
|
||||
# PC-9801-92
|
||||
controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr
|
||||
# SC-98
|
||||
# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr
|
||||
# HA-55BS2 and later
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr
|
||||
# ELECOM type
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr
|
||||
# SMIT
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr
|
||||
|
||||
controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr
|
||||
|
||||
controller scbus0
|
||||
|
@ -11,7 +11,7 @@
|
||||
# device lines is present in the ./LINT configuration file. If you are
|
||||
# in doubt as to the purpose or necessity of a line, check first in LINT.
|
||||
#
|
||||
# $Id: GENERIC98,v 1.8 1996/10/30 22:39:29 asami Exp $
|
||||
# $Id: GENERIC98,v 1.9 1996/11/14 08:46:11 asami Exp $
|
||||
|
||||
# GENERIC98 -- Generic PC98 machine with WD/SBIC55 disks
|
||||
|
||||
@ -58,12 +58,6 @@ options COM_MULTIPORT
|
||||
#options SUSP_HLT # CPU enters suspend mode when HALT
|
||||
#options "DISABLE_5X86_LSSER" # Load-Store reordering enable
|
||||
#
|
||||
# sbic55.c.new
|
||||
#
|
||||
#options SCSI_SYNC # synchronous transfer mode
|
||||
#options FORCE_BUSMASTER
|
||||
#options "HA55BS_ID=0"
|
||||
#
|
||||
# IBM-PC HDD support
|
||||
#options COMPAT_ATDISK
|
||||
#
|
||||
@ -100,13 +94,24 @@ device wcd0 #IDE CD-ROM
|
||||
# for any number of installed devices.
|
||||
controller ncr0
|
||||
controller ahc0
|
||||
options "AHC_FORCE_PIO" # Some motherboards choke on MemI/O,
|
||||
# so use PIO in the ahc driver in the
|
||||
# generic kernel.
|
||||
|
||||
controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 vector sbicintr
|
||||
# sbic55.c.new
|
||||
#controller sbic0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0xff vector sbicintr
|
||||
#
|
||||
# WD33C93 SCSI card (55/92 like board)
|
||||
#
|
||||
|
||||
options BS_TARG_SAFEMODE
|
||||
|
||||
# PC-9801-92
|
||||
controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0 vector bsintr
|
||||
# SC-98
|
||||
# controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x10000 vector bsintr
|
||||
# HA-55BS2 and later
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x20000 vector bsintr
|
||||
# ELECOM type
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 flags 0x30000 vector bsintr
|
||||
# SMIT
|
||||
#controller bs0 at isa? port "IO_SCSI" bio irq 5 drq 3 iomem 0xdd000 iosiz 0x1000 flags 0x40000 vector bsintr
|
||||
|
||||
controller aic0 at isa? port 0x1840 bio irq 5 flags 0x10000 vector aicintr
|
||||
|
||||
controller scbus0
|
||||
|
@ -1,917 +0,0 @@
|
||||
/*
|
||||
* Julian SCSI driver for PC-9801 based on aha1542.c
|
||||
*
|
||||
* Copyright (c) by Yoshio Kimura
|
||||
* 05/14/1994
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include "sbic.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/buf.h>
|
||||
#include <sys/proc.h>
|
||||
|
||||
#include <machine/clock.h>
|
||||
#include <machine/cpu.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_param.h>
|
||||
#include <vm/pmap.h>
|
||||
|
||||
#include <pc98/pc98/pc98.h>
|
||||
#include <i386/isa/isa_device.h>
|
||||
#include <i386/isa/icu.h>
|
||||
#include <i386/isa/ic/i8237.h>
|
||||
#include <pc98/pc98/scsireg.h>
|
||||
#include <scsi/scsi_all.h>
|
||||
#include <scsi/scsiconf.h>
|
||||
|
||||
#include <sys/kernel.h>
|
||||
|
||||
/************************** board definitions *******************************/
|
||||
|
||||
/*
|
||||
* I/O Port Interface
|
||||
*/
|
||||
|
||||
#define SBIC_BASE sbic->sbic_base
|
||||
#define SBIC_AUX_REG (SBIC_BASE + 0) /* auxiliary status(R) */
|
||||
#define SBIC_ADR_REG (SBIC_BASE + 0) /* address(W) */
|
||||
#define SBIC_CTL_REG (SBIC_BASE + 2) /* control(R/W) */
|
||||
#define SBIC_STA_REG (SBIC_BASE + 4) /* status(R/W) */
|
||||
|
||||
/*
|
||||
* Register Access Interface
|
||||
*/
|
||||
|
||||
#define SBIC_asr(val) (val) = inb(SBIC_AUX_REG)
|
||||
#define GET_SBIC_REG(regno, val) { \
|
||||
outb(SBIC_ADR_REG, (regno)); \
|
||||
(val) = inb(SBIC_CTL_REG); \
|
||||
}
|
||||
#define SET_SBIC_REG(regno, val) { \
|
||||
outb(SBIC_ADR_REG, (regno)); \
|
||||
outb(SBIC_CTL_REG, (val)); \
|
||||
}
|
||||
#define SET_SCSI_CMD(cmd, cmdlen) { \
|
||||
int n; \
|
||||
u_char *cmds = (u_char *)(cmd); \
|
||||
SET_SBIC_REG(SBIC_cdbsize, (cmdlen)); \
|
||||
for (n = 0; n < (cmdlen); n++) { \
|
||||
SET_SBIC_REG(SBIC_cdb1 + n, cmds[n]); \
|
||||
} \
|
||||
}
|
||||
#define SET_XFER_LEN(val) { \
|
||||
SET_SBIC_REG(SBIC_count_hi, ((val) & 0xff0000) >> 16); \
|
||||
SET_SBIC_REG(SBIC_count_med, ((val) & 0x00ff00) >> 8); \
|
||||
SET_SBIC_REG(SBIC_count_lo, (val) & 0x0000ff); \
|
||||
}
|
||||
#define SBIC_ENABLE_INT() { \
|
||||
int tmp; \
|
||||
GET_SBIC_REG(SBIC_bank, tmp); \
|
||||
SET_SBIC_REG(SBIC_bank, tmp | 0x04); \
|
||||
}
|
||||
#define SBIC_DISABLE_INT() { \
|
||||
int tmp; \
|
||||
GET_SBIC_REG(SBIC_bank, tmp); \
|
||||
SET_SBIC_REG(SBIC_bank, tmp & 0xfb); \
|
||||
}
|
||||
#define SBIC_DMA_ENABLE() outb(SBIC_STA_REG, 1)
|
||||
|
||||
#define INT3 0
|
||||
#define INT5 1
|
||||
#define INT6 2
|
||||
#define INT9 3
|
||||
#define INT12 4
|
||||
#define INT13 5
|
||||
|
||||
#define SBIC_NSEG 17
|
||||
#define SBIC_ID 7
|
||||
#define MAXSIMUL 8
|
||||
#define SBIC_RESET_TIMEOUT 2000 /* time to wait for reset */
|
||||
|
||||
extern short dmapageport[];
|
||||
|
||||
|
||||
struct sbic_ccb {
|
||||
u_char target;
|
||||
u_char lun;
|
||||
u_char status;
|
||||
u_char message;
|
||||
int datalen;
|
||||
int sense_addr;
|
||||
int sense_len;
|
||||
u_char scsi_cmdlen;
|
||||
struct scsi_generic scsi_cmd;
|
||||
struct scsi_xfer *xfer;
|
||||
struct scat_gather {
|
||||
int seg_addr;
|
||||
int seg_len;
|
||||
} scat_gath[SBIC_NSEG];
|
||||
int seg;
|
||||
int use_seg;
|
||||
int xs_flags;
|
||||
int flags;
|
||||
#define CCB_FREE 0x00
|
||||
#define CCB_ACTIVE 0x01
|
||||
#define CCB_ABORT 0x40
|
||||
#define CCB_SENSE 0x80
|
||||
#define CCB_BOUNCE 0x100
|
||||
};
|
||||
|
||||
struct sbic_config {
|
||||
u_char chan;
|
||||
u_char intr;
|
||||
u_char scsi_dev:3;
|
||||
u_char :5;
|
||||
};
|
||||
/*********************************** end of board definitions***************/
|
||||
|
||||
#define KVTOPHYS(x) vtophys(x)
|
||||
#define SBIC_DMA_PAGES SBIC_NSEG
|
||||
|
||||
#define PAGESIZ 4096
|
||||
#define ALLWAYS_BOUNCE
|
||||
|
||||
#ifdef ALLWAYS_BOUNCE
|
||||
static vm_offset_t sbic_bounce;
|
||||
#endif
|
||||
|
||||
#ifdef SBICDEBUG
|
||||
static int sbic_debug = 1;
|
||||
#endif
|
||||
|
||||
struct sbic_data {
|
||||
short sbic_base; /* base port for each board */
|
||||
struct sbic_ccb sbic_ccb[MAXSIMUL];
|
||||
int top; /* ccb queue top */
|
||||
int bottom; /* ccb queue end */
|
||||
int active; /* number of active ccb */
|
||||
int free; /* number of free ccb */
|
||||
int unit;
|
||||
int sbic_int; /* our irq level */
|
||||
int sbic_dma; /* our DMA req channel */
|
||||
int sbic_scsi_dev; /* our scsi bus address */
|
||||
struct scsi_link sc_link; /* prototype for subdevs */
|
||||
};
|
||||
|
||||
struct sbic_data *sbicdata[NSBIC];;
|
||||
|
||||
static struct sbic_ccb *sbic_get_ccb(struct sbic_data *, int);
|
||||
static int sbicprobe(struct isa_device *);
|
||||
static void sbic_done(struct sbic_data *, struct sbic_ccb *);
|
||||
static int sbicattach(struct isa_device *);
|
||||
static int32_t sbic_scsi_cmd(struct scsi_xfer *xs);
|
||||
static u_int32_t sbic_adapter_info(int);
|
||||
static void sbicminphys(struct buf *);
|
||||
static void sbic_free_ccb(struct sbic_data *, struct sbic_ccb *, int);
|
||||
static int sbic_init(int);
|
||||
static int xfer_addr_check(int, struct sbic_ccb *);
|
||||
static int sbic_poll(struct sbic_data *, struct sbic_ccb *);
|
||||
static void start_scsi(struct sbic_data *, struct sbic_ccb *);
|
||||
static void dataphase(struct sbic_data *, struct sbic_ccb *);
|
||||
static void sbic_request_sense(struct sbic_data *, struct sbic_ccb *);
|
||||
static void sbic_dmastart(int, int, unsigned, unsigned);
|
||||
static void sbic_dmadone(int, int, unsigned, unsigned);
|
||||
|
||||
static struct scsi_adapter sbic_switch = {
|
||||
sbic_scsi_cmd,
|
||||
sbicminphys,
|
||||
0,
|
||||
0,
|
||||
sbic_adapter_info,
|
||||
"sbic",
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
/* the below structure is so we have a default dev struct for out link struct */
|
||||
static struct scsi_device sbic_dev = {
|
||||
NULL, /* Use default error handler */
|
||||
NULL, /* have a queue, served by this */
|
||||
NULL, /* have no async handler */
|
||||
NULL, /* Use default 'done' routine */
|
||||
"sbic",
|
||||
0,
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
struct isa_driver sbicdriver = {
|
||||
sbicprobe,
|
||||
sbicattach,
|
||||
"sbic"
|
||||
};
|
||||
|
||||
static int sbicunit = 0;
|
||||
|
||||
/*
|
||||
* Check if the device can be found at the port given
|
||||
* and if so, set it up ready for further work
|
||||
* as an argument, takes the isa_device structure from
|
||||
* autoconf.c
|
||||
*/
|
||||
static int
|
||||
sbicprobe(struct isa_device *dev)
|
||||
{
|
||||
int unit = sbicunit;
|
||||
struct sbic_data *sbic;
|
||||
|
||||
/*
|
||||
* find unit and check we have that many defined
|
||||
*/
|
||||
if (unit >= NSBIC) {
|
||||
printf("sbic: unit number (%d) to high\n", unit);
|
||||
return(0);
|
||||
}
|
||||
dev->id_unit = unit;
|
||||
|
||||
/*
|
||||
* a quick safety check so we can be sleazy later
|
||||
*/
|
||||
if (sizeof(struct sbic_data) > PAGESIZ) {
|
||||
printf("sbic struct > pagesize\n");
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* Allocate a storage area for us
|
||||
*/
|
||||
if (sbicdata[unit]) {
|
||||
printf("sbic%d: memory already allocated\n", unit);
|
||||
return(0);
|
||||
}
|
||||
sbic = malloc(sizeof(struct sbic_data), M_TEMP, M_NOWAIT);
|
||||
if (!sbic) {
|
||||
printf("sbic%d: cannot malloc!\n", unit);
|
||||
return(0);
|
||||
}
|
||||
bzero(sbic, sizeof(struct sbic_data));
|
||||
sbicdata[unit] = sbic;
|
||||
sbic->sbic_base = dev->id_iobase;
|
||||
|
||||
#ifdef ALLWAYS_BOUNCE
|
||||
/*
|
||||
* allocate bounce buffer for sense data
|
||||
*/
|
||||
#ifdef EPSON_BOUNCEDMA
|
||||
#define PC98_RAMEND 0xf00000
|
||||
#else
|
||||
#define PC98_RAMEND RAM_END
|
||||
#endif
|
||||
|
||||
/* try malloc() first. */
|
||||
sbic_bounce = (vm_offset_t)malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT);
|
||||
if (sbic_bounce != NULL) {
|
||||
if (vtophys(sbic_bounce) >= PC98_RAMEND) {
|
||||
free(buf, M_DEVBUF);
|
||||
sbic_bounce = (vm_offset_t)contigmalloc(PAGE_SIZE, M_DEVBUF,
|
||||
M_NOWAIT,
|
||||
0ul, PC98_RAMEND, 1ul,
|
||||
0x10000ul);
|
||||
}
|
||||
}
|
||||
if (sbic_bounce == NULL)
|
||||
panic("Can't allocate bounce buffer.");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Try initialize a unit at this location
|
||||
* sets up dma, loads sbic_init[unit]
|
||||
*/
|
||||
if (sbic_init(unit) != 0) {
|
||||
sbicdata[unit] = NULL;
|
||||
free(sbic, M_TEMP);
|
||||
return(0);
|
||||
}
|
||||
/*
|
||||
* If it's there, put in it's interrupt vectors
|
||||
*/
|
||||
dev->id_irq = (1 << sbic->sbic_int);
|
||||
dev->id_drq = sbic->sbic_dma;
|
||||
sbicunit++;
|
||||
return(5);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach all the sub-devices we can find.
|
||||
*/
|
||||
static int
|
||||
sbicattach(struct isa_device *dev)
|
||||
{
|
||||
int unit = dev->id_unit;
|
||||
struct sbic_data *sbic = sbicdata[unit];
|
||||
struct scsibus_data *scbus;
|
||||
|
||||
/*
|
||||
* fill in the prototype scsi_link
|
||||
*/
|
||||
sbic->sc_link.adapter_unit = unit;
|
||||
sbic->sc_link.adapter_targ = sbic->sbic_scsi_dev;
|
||||
sbic->sc_link.adapter_softc = sbic;
|
||||
sbic->sc_link.adapter = &sbic_switch;
|
||||
sbic->sc_link.device = &sbic_dev;
|
||||
sbic->sc_link.flags = SDEV_BOUNCE;
|
||||
|
||||
/*
|
||||
* Prepare the scsibus_data area for the upperlevel
|
||||
* scsi code.
|
||||
*/
|
||||
scbus = scsi_alloc_bus();
|
||||
if(!scbus)
|
||||
return 0;
|
||||
scbus->adapter_link = &sbic->sc_link;
|
||||
|
||||
/*
|
||||
* ask the adapter what subunits are present
|
||||
*/
|
||||
scsi_attachdevs(scbus);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return some information to the caller about
|
||||
* the adapter and it's capabilities
|
||||
*/
|
||||
static u_int32_t
|
||||
sbic_adapter_info(int unit)
|
||||
{
|
||||
return(1); /* 1 outstanding request at a time per device */
|
||||
}
|
||||
|
||||
/*
|
||||
* Catch an interrupt from the adapter
|
||||
*/
|
||||
void
|
||||
sbicintr(int unit)
|
||||
{
|
||||
struct sbic_ccb *ccb;
|
||||
struct sbic_data *sbic = sbicdata[unit];
|
||||
u_char asr, host_stat, cmd_phase;
|
||||
u_char *cmd;
|
||||
int i, seg, phys;
|
||||
|
||||
#ifdef SBICDEBUG
|
||||
printf("sbicintr");
|
||||
#endif /* SBICDEBUG */
|
||||
|
||||
SBIC_asr(asr);
|
||||
/* drop spurious interrupts */
|
||||
if (!(asr & SBIC_ASR_INT))
|
||||
return;
|
||||
GET_SBIC_REG(SBIC_csr, host_stat);
|
||||
GET_SBIC_REG(SBIC_cmd_phase, cmd_phase);
|
||||
|
||||
ccb = &sbic->sbic_ccb[sbic->top];
|
||||
seg = ccb->seg;
|
||||
|
||||
switch(host_stat) {
|
||||
case SBIC_CSR_XFERRED | SBIC_MCI_DATA_OUT: /* data phase start */
|
||||
case SBIC_CSR_MIS_1 | SBIC_MCI_DATA_OUT: /* data phase continue */
|
||||
case SBIC_CSR_XFERRED | SBIC_MCI_DATA_IN:
|
||||
case SBIC_CSR_MIS_1 | SBIC_MCI_DATA_IN:
|
||||
dataphase(sbic, ccb);
|
||||
return;
|
||||
case SBIC_CSR_MIS_1 | SBIC_MCI_STATUS: /* status phase start */
|
||||
case SBIC_CSR_XFERRED | SBIC_MCI_STATUS: /* status phase start */
|
||||
SET_XFER_LEN(0);
|
||||
SET_SBIC_REG(SBIC_cmd_phase, 0x46);
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
|
||||
return;
|
||||
case SBIC_CSR_S_XFERRED:
|
||||
phys = KVTOPHYS(ccb->sense_addr);
|
||||
if (ccb->flags & CCB_SENSE) {
|
||||
sbic_dmadone(B_READ, phys,
|
||||
ccb->sense_len, sbic->sbic_dma);
|
||||
} else {
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN)) {
|
||||
sbic_dmadone(B_READ,
|
||||
ccb->scat_gath[seg - 1].seg_addr,
|
||||
ccb->scat_gath[seg - 1].seg_len,
|
||||
sbic->sbic_dma);
|
||||
}
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT)) {
|
||||
sbic_dmadone(B_WRITE,
|
||||
ccb->scat_gath[seg - 1].seg_addr,
|
||||
ccb->scat_gath[seg - 1].seg_len,
|
||||
sbic->sbic_dma);
|
||||
}
|
||||
}
|
||||
GET_SBIC_REG(SBIC_tlun, ccb->status);
|
||||
ccb->status &= 0x1f;
|
||||
switch(ccb->status) {
|
||||
case SCSI_CHECK:
|
||||
ccb->flags |= CCB_SENSE;
|
||||
ccb->xfer->error = XS_SENSE;
|
||||
sbic_request_sense(sbic, ccb);
|
||||
return;
|
||||
case SCSI_BUSY:
|
||||
ccb->xfer->error = XS_BUSY;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
sbic_done(sbic, ccb);
|
||||
break;
|
||||
|
||||
case SBIC_CSR_SEL_TIMEO: /* selection timeout */
|
||||
ccb->xfer->error = XS_TIMEOUT;
|
||||
sbic_done(sbic, ccb);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("sbic%d:%d:%d -- ", unit, ccb->target, ccb->lun);
|
||||
printf("host: %x interrupt occured\n", host_stat);
|
||||
panic("Unsupported interrupts. check intr code\n");
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* A ccb is put onto the free list.
|
||||
*/
|
||||
static void
|
||||
sbic_free_ccb(struct sbic_data *sbic, struct sbic_ccb *ccb, int flags)
|
||||
{
|
||||
unsigned opri = 0;
|
||||
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
if (ccb = &sbic->sbic_ccb[sbic->top])
|
||||
sbic->top = ++sbic->top % MAXSIMUL;
|
||||
else
|
||||
sbic->bottom = (--sbic->bottom + MAXSIMUL) % MAXSIMUL;
|
||||
sbic->active--;
|
||||
sbic->free++;
|
||||
ccb->flags = CCB_FREE;
|
||||
if (sbic->free)
|
||||
wakeup((caddr_t)&sbic->free);
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
splx(opri);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get a free ccb
|
||||
*/
|
||||
static struct sbic_ccb *
|
||||
sbic_get_ccb(struct sbic_data *sbic, int flags)
|
||||
{
|
||||
unsigned opri = 0;
|
||||
struct sbic_ccb *rc;
|
||||
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
opri = splbio();
|
||||
/*
|
||||
* If we can and have to, sleep waiting for one to come free
|
||||
*/
|
||||
while((!sbic->free) && (!(flags & SCSI_NOSLEEP)))
|
||||
tsleep((caddr_t)&sbic->free, PRIBIO, "sbicccb", 0);
|
||||
if (sbic->free) {
|
||||
rc = &sbic->sbic_ccb[sbic->bottom];
|
||||
sbic->free--;
|
||||
sbic->active++;
|
||||
sbic->bottom = ++sbic->bottom % MAXSIMUL;
|
||||
rc->flags = CCB_ACTIVE;
|
||||
} else
|
||||
rc = (struct sbic_ccb *)0;
|
||||
if (!(flags & SCSI_NOMASK))
|
||||
splx(opri);
|
||||
return(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* We have a ccb which has been processed by the
|
||||
* adapter, now we lock to see how the operation
|
||||
* went. Wake up the owner if waiting
|
||||
*/
|
||||
static void
|
||||
sbic_done(struct sbic_data *sbic, struct sbic_ccb *ccb)
|
||||
{
|
||||
struct scsi_xfer *xs = ccb->xfer;
|
||||
unsigned opri;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("sbic_done\n"));
|
||||
if (!(xs->flags & INUSE)) {
|
||||
printf("sbic%d: exiting but not in use!\n", sbic->unit);
|
||||
Debugger("sbic55");
|
||||
}
|
||||
if ((!xs->error) || (xs->flags & SCSI_ERR_OK))
|
||||
xs->resid = 0;
|
||||
|
||||
xs->flags |= ITSDONE;
|
||||
#ifdef ALLWAYS_BOUNCE
|
||||
bcopy((char *)ccb->sense_addr, (char *)&xs->sense, ccb->sense_len);
|
||||
#else
|
||||
if(ccb->flags & CCB_BOUNCE)
|
||||
bcopy((char *)ccb->sense_addr,
|
||||
(char *)&xs->sense, ccb->sense_len);
|
||||
#endif
|
||||
sbic_free_ccb(sbic, ccb, xs->flags);
|
||||
if(sbic->active) {
|
||||
opri = splbio();
|
||||
SBIC_ENABLE_INT();
|
||||
start_scsi(sbic, &sbic->sbic_ccb[sbic->top]);
|
||||
splx(opri);
|
||||
}
|
||||
scsi_done(xs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start the board, ready for normal operation
|
||||
*/
|
||||
static int
|
||||
sbic_init(int unit)
|
||||
{
|
||||
struct sbic_data *sbic = sbicdata[unit];
|
||||
struct sbic_config conf;
|
||||
int i, asr, csr, tmp;
|
||||
|
||||
SBIC_asr(asr); /* dummy read */
|
||||
GET_SBIC_REG(SBIC_csr, csr);
|
||||
SBIC_DISABLE_INT();
|
||||
|
||||
SET_SBIC_REG(SBIC_myid, SBIC_ID_FS_16_20 | SBIC_ID);
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_RESET);
|
||||
for (i = SBIC_RESET_TIMEOUT; i; i--) {
|
||||
SBIC_asr(asr);
|
||||
if ((asr != 0xff) && (asr & SBIC_ASR_INT)) {
|
||||
GET_SBIC_REG(SBIC_csr, csr);
|
||||
if (csr == SBIC_CSR_RESET)
|
||||
break;
|
||||
}
|
||||
DELAY(1); /* calibrated in msec */
|
||||
}
|
||||
if (i == 0) {
|
||||
#ifdef SBICDEBUG
|
||||
if (sbic_debug)
|
||||
printf("sbic_init: No answer from sbic board\n");
|
||||
#endif
|
||||
return(ENXIO);
|
||||
}
|
||||
|
||||
conf.chan = (inb(SBIC_STA_REG) & 0x03);
|
||||
GET_SBIC_REG(SBIC_int, tmp);
|
||||
conf.intr = (tmp >> 3) & 0x07;
|
||||
conf.scsi_dev = tmp & 0x07;
|
||||
sbic->sbic_dma = conf.chan;
|
||||
sbic->sbic_scsi_dev = conf.scsi_dev;
|
||||
switch(conf.intr) {
|
||||
case INT3:
|
||||
sbic->sbic_int = 3;
|
||||
break;
|
||||
case INT5:
|
||||
sbic->sbic_int = 5;
|
||||
break;
|
||||
case INT6:
|
||||
sbic->sbic_int = 6;
|
||||
break;
|
||||
case INT9:
|
||||
sbic->sbic_int = 9;
|
||||
break;
|
||||
case INT12:
|
||||
sbic->sbic_int = 12;
|
||||
break;
|
||||
case INT13:
|
||||
sbic->sbic_int = 13;
|
||||
break;
|
||||
default:
|
||||
printf("illegal int jumpter setting\n");
|
||||
return(EIO);
|
||||
}
|
||||
|
||||
SET_SBIC_REG(SBIC_rselid, 0);
|
||||
#if 1
|
||||
SET_SBIC_REG(SBIC_timeo, 0x80);
|
||||
#else
|
||||
SET_SBIC_REG(SBIC_timeo, 0xa0);
|
||||
#endif
|
||||
SET_SBIC_REG(SBIC_control, SBIC_CTL_EDI);
|
||||
SET_SBIC_REG(SBIC_syn, 0);
|
||||
SBIC_ENABLE_INT();
|
||||
/*
|
||||
* ccb queue initialize
|
||||
*/
|
||||
for (i = 0; i < MAXSIMUL; i++) {
|
||||
sbic->sbic_ccb[i].flags = CCB_FREE;
|
||||
}
|
||||
sbic->top = sbic->bottom = sbic->active = 0;
|
||||
sbic->free = MAXSIMUL;
|
||||
/*
|
||||
* Note that wa are going and return (to probe)
|
||||
*/
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
sbicminphys(struct buf *bp)
|
||||
{
|
||||
/* sbic seems to explode with 17 segs (64k may require 17 segs) */
|
||||
if (bp->b_bcount > ((SBIC_NSEG - 1) *PAGESIZ))
|
||||
bp->b_bcount = ((SBIC_NSEG - 1) * PAGESIZ);
|
||||
}
|
||||
|
||||
/*
|
||||
* start a scsi operation given the command and
|
||||
* the data address. Also needs the unit, target
|
||||
* and lu
|
||||
*/
|
||||
static int32_t
|
||||
sbic_scsi_cmd(struct scsi_xfer *xs)
|
||||
{
|
||||
struct scsi_link *sc_link = xs->sc_link;
|
||||
int unit = sc_link->adapter_unit;
|
||||
struct sbic_data *sbic = sc_link->adapter_softc;
|
||||
struct sbic_ccb *ccb;
|
||||
int s, i, retval, flags;
|
||||
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB2, ("sbic_scsi_cmd\n"));
|
||||
flags = xs->flags;
|
||||
if (!(ccb = sbic_get_ccb(sbic, flags))) {
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return(TRY_AGAIN_LATER);
|
||||
}
|
||||
ccb->xfer = xs;
|
||||
ccb->target = xs->sc_link->target;
|
||||
ccb->lun = xs->sc_link->lun;
|
||||
ccb->xs_flags = xs->flags;
|
||||
ccb->scsi_cmdlen = xs->cmdlen;
|
||||
ccb->datalen = xs->datalen;
|
||||
ccb->sense_len = sizeof(xs->sense);
|
||||
#ifdef ALLWAYS_BOUNCE
|
||||
ccb->sense_addr = (int)(sbic_bounce);
|
||||
#else
|
||||
ccb->sense_addr = (int)&xs->sense;
|
||||
#endif
|
||||
ccb->seg = 0;
|
||||
|
||||
if (retval = xfer_addr_check(unit, ccb)) {
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
sbic_free_ccb(sbic, ccb, flags);
|
||||
return(retval);
|
||||
}
|
||||
if (!(flags & SCSI_RESET)) {
|
||||
bcopy(xs->cmd, &ccb->scsi_cmd, ccb->scsi_cmdlen);
|
||||
ccb->scsi_cmd.bytes[0] |= ((ccb->lun << 5) & 0xe0);
|
||||
}
|
||||
if (!(flags & SCSI_NOMASK)) {
|
||||
if (sbic->active == 1) {
|
||||
s = splbio();
|
||||
SBIC_ENABLE_INT();
|
||||
start_scsi(sbic, ccb);
|
||||
splx(s);
|
||||
}
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB3, ("sent\n"));
|
||||
return(SUCCESSFULLY_QUEUED);
|
||||
}
|
||||
SBIC_DISABLE_INT();
|
||||
start_scsi(sbic, ccb);
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB3, ("cmd sent, waiting\n"));
|
||||
return(sbic_poll(sbic, ccb));
|
||||
}
|
||||
|
||||
static int
|
||||
sbic_poll(struct sbic_data *sbic, struct sbic_ccb *ccb)
|
||||
{
|
||||
int count, asr, done = 0;
|
||||
|
||||
count = ccb->xfer->timeout * 1000;
|
||||
while(count) {
|
||||
SBIC_asr(asr);
|
||||
if ((asr != 0xff) && (asr & SBIC_ASR_INT)) {
|
||||
sbicintr(sbic->unit);
|
||||
}
|
||||
if (ccb->xfer->flags & ITSDONE) {
|
||||
break;
|
||||
}
|
||||
DELAY(1);
|
||||
count--;
|
||||
}
|
||||
if (!count) panic("sbic scsi timeout!!");
|
||||
if (ccb->xfer->error) return(HAD_ERROR);
|
||||
return(COMPLETE);
|
||||
}
|
||||
|
||||
static int
|
||||
xfer_addr_check(int unit, struct sbic_ccb *ccb)
|
||||
{
|
||||
struct iovec *iovp;
|
||||
struct scat_gather *sg;
|
||||
struct scsi_xfer *xs;
|
||||
int thiskv, thisphys, nextphys;
|
||||
int bytes_this_page, bytes_this_seg;
|
||||
int datalen, flags;
|
||||
|
||||
xs = ccb->xfer;
|
||||
flags = ccb->xs_flags;
|
||||
if ((xs->datalen) && (!(flags & SCSI_RESET))) {
|
||||
sg = ccb->scat_gath;
|
||||
ccb->use_seg = 0;
|
||||
if (flags & SCSI_DATA_UIO) {
|
||||
iovp = ((struct uio *)xs->data)->uio_iov;
|
||||
datalen = ((struct uio *)xs->data)->uio_iovcnt;
|
||||
while((datalen) && (ccb->use_seg < SBIC_NSEG)) {
|
||||
sg->seg_addr = KVTOPHYS((int)iovp->iov_base);
|
||||
sg->seg_len = iovp->iov_len;
|
||||
SC_DEBUGN(xs->sc_link, SDEV_DB4, ("UIO(0x%x@0x%x)"
|
||||
,iovp->iov_len
|
||||
,iovp->iov_base));
|
||||
sg++;
|
||||
iovp++;
|
||||
ccb->use_seg++;
|
||||
datalen++;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* Set up scatter gather block
|
||||
*/
|
||||
SC_DEBUG(xs->sc_link, SDEV_DB4,
|
||||
("%d @0x%x:- ", xs->datalen, xs->data));
|
||||
datalen = xs->datalen;
|
||||
thiskv = (int)xs->data;
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
while((datalen) && (ccb->use_seg < SBIC_NSEG)) {
|
||||
bytes_this_seg = 0;
|
||||
sg->seg_addr = thisphys;
|
||||
SC_DEBUGN(xs->sc_link, SDEV_DB4,
|
||||
("0x%x", thisphys));
|
||||
nextphys = thisphys;
|
||||
while((datalen) && (thisphys == nextphys)) {
|
||||
if (thisphys > 0xFFFFFF) {
|
||||
printf("sbic%d: DMA beyond"
|
||||
" end of PC98\n", unit);
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return(HAD_ERROR);
|
||||
}
|
||||
nextphys = (thisphys & (~(PAGESIZ - 1)))
|
||||
+ PAGESIZ;
|
||||
bytes_this_page = nextphys - thisphys;
|
||||
bytes_this_page = min(bytes_this_page,
|
||||
datalen);
|
||||
bytes_this_seg += bytes_this_page;
|
||||
datalen -= bytes_this_page;
|
||||
thiskv = (thiskv & (~(PAGESIZ - 1)))
|
||||
+ PAGESIZ;
|
||||
if (datalen)
|
||||
thisphys = KVTOPHYS(thiskv);
|
||||
}
|
||||
SC_DEBUGN(xs->sc_link, SDEV_DB4,
|
||||
("(0x%x)", bytes_this_seg));
|
||||
sg->seg_len = bytes_this_seg;
|
||||
sg++;
|
||||
ccb->use_seg++;
|
||||
}
|
||||
}
|
||||
SC_DEBUGN(xs->sc_link, SDEV_DB4, ("\n"));
|
||||
if (datalen) {
|
||||
printf("sbic%d: sbic_scsi_cmd, more than %d DMA segs\n",
|
||||
unit, SBIC_NSEG);
|
||||
xs->error = XS_DRIVER_STUFFUP;
|
||||
return(HAD_ERROR);
|
||||
}
|
||||
} else {
|
||||
ccb->scat_gath[0].seg_len = 0;
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
static void
|
||||
start_scsi(struct sbic_data *sbic, struct sbic_ccb *ccb)
|
||||
{
|
||||
if (ccb->xs_flags & SCSI_RESET) {
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_RESET);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN))
|
||||
sbic_dmastart(B_READ, ccb->scat_gath[0].seg_addr,
|
||||
ccb->scat_gath[0].seg_len, sbic->sbic_dma);
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT))
|
||||
sbic_dmastart(B_WRITE, ccb->scat_gath[0].seg_addr,
|
||||
ccb->scat_gath[0].seg_len, sbic->sbic_dma);
|
||||
SET_SCSI_CMD(&ccb->scsi_cmd, ccb->scsi_cmdlen);
|
||||
SET_XFER_LEN(ccb->scat_gath[0].seg_len);
|
||||
SET_SBIC_REG(SBIC_selid, ccb->target);
|
||||
SET_SBIC_REG(SBIC_tlun, ccb->lun);
|
||||
SBIC_DMA_ENABLE();
|
||||
SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
|
||||
ccb->seg++;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
dataphase(struct sbic_data *sbic, struct sbic_ccb *ccb)
|
||||
{
|
||||
int seg = ccb->seg, tmp;
|
||||
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_IN)) {
|
||||
sbic_dmadone(B_READ, ccb->scat_gath[seg - 1].seg_addr,
|
||||
ccb->scat_gath[seg - 1].seg_len, sbic->sbic_dma);
|
||||
sbic_dmastart(B_READ, ccb->scat_gath[seg].seg_addr,
|
||||
ccb->scat_gath[seg].seg_len, sbic->sbic_dma);
|
||||
}
|
||||
if ((ccb->datalen) && (ccb->xs_flags & SCSI_DATA_OUT)) {
|
||||
sbic_dmadone(B_WRITE, ccb->scat_gath[seg - 1].seg_addr,
|
||||
ccb->scat_gath[seg - 1].seg_len, sbic->sbic_dma);
|
||||
sbic_dmastart(B_WRITE, ccb->scat_gath[seg].seg_addr,
|
||||
ccb->scat_gath[seg].seg_len, sbic->sbic_dma);
|
||||
}
|
||||
SBIC_DMA_ENABLE();
|
||||
SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
|
||||
SET_XFER_LEN(ccb->scat_gath[seg].seg_len);
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_XFER_INFO);
|
||||
ccb->seg++;
|
||||
return;
|
||||
}
|
||||
|
||||
static void
|
||||
sbic_request_sense(struct sbic_data *sbic, struct sbic_ccb *ccb)
|
||||
{
|
||||
int phys, len;
|
||||
unsigned chan;
|
||||
u_char cmd[6] = { 3, 0, 0, 0, 0, 0 };
|
||||
|
||||
cmd[1] |= ((ccb->lun << 5) & 0xe0);
|
||||
|
||||
chan = sbic->sbic_dma;
|
||||
len = ccb->sense_len;
|
||||
#ifndef ALLWAYS_BOUNCE
|
||||
if(isa_dmarangecheck((caddr_t)ccb->sense_addr,len)) {
|
||||
ccb->sense_addr = (int)(sbic_bounce);
|
||||
ccb->flags |= CCB_BOUNCE;
|
||||
}
|
||||
#endif
|
||||
phys = KVTOPHYS(ccb->sense_addr);
|
||||
sbic_dmastart(B_READ, phys, len, chan);
|
||||
|
||||
SET_SCSI_CMD(cmd, 6);
|
||||
SET_XFER_LEN(ccb->sense_len);
|
||||
SET_SBIC_REG(SBIC_selid, ccb->target);
|
||||
SET_SBIC_REG(SBIC_tlun, ccb->lun);
|
||||
SBIC_DMA_ENABLE();
|
||||
SET_SBIC_REG(SBIC_control, SBIC_CTL_DMA | SBIC_CTL_EDI);
|
||||
SET_SBIC_REG(SBIC_cmd, SBIC_CMD_SEL_XFER);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sbic_dmastart(int flags, int phys, unsigned nbytes, unsigned chan)
|
||||
{
|
||||
int modeport, waport, mskport;
|
||||
caddr_t newaddr;
|
||||
int s;
|
||||
|
||||
if (chan > 3 || nbytes > (1<<16))
|
||||
panic("sbic_dmastart: impossible request");
|
||||
|
||||
s = splbio(); /* mask on */
|
||||
|
||||
#ifdef CYRIX_5X86
|
||||
asm("wbinvd"); /* wbinvd (WB cache flush) */
|
||||
#endif
|
||||
|
||||
/* mask channel */
|
||||
mskport = IO_DMA + 0x14; /* 0x15 */
|
||||
outb(mskport, chan & 3 | 0x04);
|
||||
|
||||
/* set dma channel mode, and reset address ff */
|
||||
modeport = IO_DMA + 0x16; /* 0x17 */
|
||||
if (flags & B_READ) {
|
||||
outb(modeport, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3));
|
||||
} else {
|
||||
outb(modeport, DMA37MD_SINGLE|DMA37MD_READ|(chan&3));
|
||||
}
|
||||
outb(modeport + 1*2, 0); /* 0x19 (clear byte pointer) */
|
||||
|
||||
/* send start address */
|
||||
waport = IO_DMA + (chan<<2); /* 0x1, 0x5, 0x9, 0xd */
|
||||
outb(waport, phys);
|
||||
outb(waport, phys>>8);
|
||||
outb(dmapageport[chan], phys>>16);
|
||||
|
||||
/* send count */
|
||||
outb(waport + 2, --nbytes); /* 0x3, 0x7, 0xb, 0xf */
|
||||
outb(waport + 2, nbytes>>8);
|
||||
|
||||
/* unmask channel */
|
||||
mskport = IO_DMA + 0x14; /* 0x15 */
|
||||
outb(mskport, chan & 3);
|
||||
|
||||
splx(s); /* mask off */
|
||||
}
|
||||
|
||||
static void
|
||||
sbic_dmadone(int flags, int addr, unsigned nbytes, unsigned chan)
|
||||
{
|
||||
#if defined(CYRIX_486DLC) || defined(IBM_486SLC)
|
||||
if (flags & B_READ) {
|
||||
/* cache flush only after reading 92/12/9 by A.Kojima */
|
||||
asm(" .byte 0x0f,0x08"); /* invd (cache flush) */
|
||||
}
|
||||
#endif
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,429 +0,0 @@
|
||||
/* $NetBSD: sbicreg.h,v 1.2 1994/10/26 02:04:40 cgd Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Van Jacobson of Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)scsireg.h 7.3 (Berkeley) 2/5/91
|
||||
*/
|
||||
/*
|
||||
* Ported to PC-9801 by Yoshio Kimura, 1994
|
||||
* last update 09/24/1994
|
||||
*/
|
||||
|
||||
/*
|
||||
* AMD AM33C93A SCSI interface hardware description.
|
||||
*
|
||||
* Using parts of the Mach scsi driver for the 33C93
|
||||
*/
|
||||
|
||||
#define SBIC_myid 0
|
||||
#define SBIC_cdbsize 0
|
||||
#define SBIC_control 1
|
||||
#define SBIC_timeo 2
|
||||
#define SBIC_cdb1 3
|
||||
#define SBIC_tsecs 3
|
||||
#define SBIC_cdb2 4
|
||||
#define SBIC_theads 4
|
||||
#define SBIC_cdb3 5
|
||||
#define SBIC_tcyl_hi 5
|
||||
#define SBIC_cdb4 6
|
||||
#define SBIC_tcyl_lo 6
|
||||
#define SBIC_cdb5 7
|
||||
#define SBIC_addr_hi 7
|
||||
#define SBIC_cdb6 8
|
||||
#define SBIC_addr_2 8
|
||||
#define SBIC_cdb7 9
|
||||
#define SBIC_addr_3 9
|
||||
#define SBIC_cdb8 10
|
||||
#define SBIC_addr_lo 10
|
||||
#define SBIC_cdb9 11
|
||||
#define SBIC_secno 11
|
||||
#define SBIC_cdb10 12
|
||||
#define SBIC_headno 12
|
||||
#define SBIC_cdb11 13
|
||||
#define SBIC_cylno_hi 13
|
||||
#define SBIC_cdb12 14
|
||||
#define SBIC_cylno_lo 14
|
||||
#define SBIC_tlun 15
|
||||
#define SBIC_cmd_phase 16
|
||||
#define SBIC_syn 17
|
||||
#define SBIC_count_hi 18
|
||||
#define SBIC_count_med 19
|
||||
#define SBIC_count_lo 20
|
||||
#define SBIC_selid 21
|
||||
#define SBIC_rselid 22
|
||||
#define SBIC_csr 23
|
||||
#define SBIC_cmd 24
|
||||
#define SBIC_data 25
|
||||
#define SBIC_mem_bank 48
|
||||
#define SBIC_mem_win 49
|
||||
#define SBIC_reserved1 50
|
||||
#define SBIC_reset_int 51
|
||||
#define SBIC_reserved2 52
|
||||
#define SBIC_reserved3 53
|
||||
/* sbic_asr is addressed directly */
|
||||
|
||||
/*
|
||||
* Register defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Auxiliary Status Register
|
||||
*/
|
||||
|
||||
#define SBIC_ASR_INT 0x80 /* Interrupt pending */
|
||||
#define SBIC_ASR_LCI 0x40 /* Last command ignored */
|
||||
#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
|
||||
#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
|
||||
#define SBIC_ASR_xxx 0x0c
|
||||
#define SBIC_ASR_PE 0x02 /* Parity error (even) */
|
||||
#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
|
||||
|
||||
/*
|
||||
* My ID register, and/or CDB Size
|
||||
*/
|
||||
|
||||
#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
|
||||
/* 11 Mhz is invalid */
|
||||
#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
|
||||
#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
|
||||
#define SBIC_ID_EHP 0x10 /* Enable host parity */
|
||||
#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
|
||||
#define SBIC_ID_MASK 0x07
|
||||
#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
|
||||
|
||||
/*
|
||||
* Control register
|
||||
*/
|
||||
|
||||
#define SBIC_CTL_DMA 0x80 /* Single byte dma */
|
||||
#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
|
||||
#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
|
||||
#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
|
||||
#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
|
||||
#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
|
||||
#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
|
||||
#define SBIC_CTL_HA 0x02 /* Halt on ATN */
|
||||
#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
|
||||
|
||||
/*
|
||||
* Timeout period register
|
||||
* [val in msecs, input clk in 0.1 Mhz]
|
||||
*/
|
||||
|
||||
#define SBIC_TIMEOUT(val,clk) ((((val) * (clk)) / 800) + 1)
|
||||
|
||||
/*
|
||||
* CDBn registers, note that
|
||||
* cdb11 is used for status byte in target mode (send-status-and-cc)
|
||||
* cdb12 sez if linked command complete, and w/flag if so
|
||||
*/
|
||||
|
||||
/*
|
||||
* Target LUN register
|
||||
* [holds target status when select-and-xfer]
|
||||
*/
|
||||
|
||||
#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */
|
||||
#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */
|
||||
#define SBIC_TLUN_xxx 0x38
|
||||
#define SBIC_TLUN_MASK 0x07
|
||||
|
||||
/*
|
||||
* Command Phase register
|
||||
*/
|
||||
|
||||
#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */
|
||||
#define SBIC_CPH(p) ((p) & SBIC_CPH_MASK)
|
||||
|
||||
/*
|
||||
* FIFO register
|
||||
*/
|
||||
|
||||
#define SBIC_FIFO_DEEP 12
|
||||
|
||||
/*
|
||||
* maximum possible size in TC registers. Since this is 24 bit, it's easy
|
||||
*/
|
||||
#define SBIC_TC_MAX ((1 << 24) - 1)
|
||||
|
||||
/*
|
||||
* Synchronous xfer register
|
||||
*/
|
||||
|
||||
#define SBIC_SYN_OFF_MASK 0x0f
|
||||
#define SBIC_SYN_MAX_OFFSET SBIC_FIFO_DEEP
|
||||
#define SBIC_SYN_PER_MASK 0x70
|
||||
#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */
|
||||
|
||||
#define SBIC_SYN(o,p) \
|
||||
(((o) & SBIC_SYN_OFF_MASK) | (((p) << 4) & SBIC_SYN_PER_MASK))
|
||||
|
||||
/*
|
||||
* Transfer count register
|
||||
* optimal access macros depend on addressing
|
||||
*/
|
||||
|
||||
/*
|
||||
* Destination ID (selid) register
|
||||
*/
|
||||
|
||||
#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */
|
||||
#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */
|
||||
#define SBIC_SID_FROM_SCSI 0x40
|
||||
#define SBIC_SID_TO_SCSI 0x00
|
||||
#define SBIC_SID_xxx 0x38
|
||||
#define SBIC_SID_IDMASK 0x07
|
||||
|
||||
/*
|
||||
* Source ID (rselid) register
|
||||
*/
|
||||
|
||||
#define SBIC_RID_ER 0x80 /* Enable reselection */
|
||||
#define SBIC_RID_ES 0x40 /* Enable selection */
|
||||
#define SBIC_RID_DSP 0x20 /* Disable select parity */
|
||||
#define SBIC_RID_SIV 0x08 /* Source ID valid */
|
||||
#define SBIC_RID_MASK 0x07
|
||||
|
||||
/*
|
||||
* Status register
|
||||
*/
|
||||
|
||||
#define SBIC_CSR_CAUSE 0xf0
|
||||
#define SBIC_CSR_RESET 0x00 /* chip was reset */
|
||||
#define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */
|
||||
#define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/
|
||||
#define SBIC_CSR_CMD_ERR 0x40 /* end with error */
|
||||
#define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */
|
||||
|
||||
|
||||
#define SBIC_CSR_QUALIFIER 0x0f
|
||||
/* Reset State Interrupts */
|
||||
#define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/
|
||||
#define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/
|
||||
/* Successful Completion Interrupts */
|
||||
#define SBIC_CSR_TARGET 0x10 /* reselect complete */
|
||||
#define SBIC_CSR_INITIATOR 0x11 /* select complete */
|
||||
#define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */
|
||||
#define SBIC_CSR_W_ATN 0x14 /* ditto */
|
||||
#define SBIC_CSR_XLATED 0x15 /* translate address cmd */
|
||||
#define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/
|
||||
#define SBIC_CSR_XFERRED 0x18 /* phase in low bits */
|
||||
/* Paused or Aborted Interrupts */
|
||||
#define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/
|
||||
#define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */
|
||||
#define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */
|
||||
#define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */
|
||||
#define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */
|
||||
#define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */
|
||||
#define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */
|
||||
/* Terminated Interrupts */
|
||||
#define SBIC_CSR_CMD_INVALID 0x40
|
||||
#define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */
|
||||
#define SBIC_CSR_SEL_TIMEO 0x42
|
||||
#define SBIC_CSR_PE 0x43 /* parity error */
|
||||
#define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */
|
||||
#define SBIC_CSR_XLATE_TOOBIG 0x45
|
||||
#define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */
|
||||
#define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */
|
||||
#define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */
|
||||
/* Service Required Interrupts */
|
||||
#define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */
|
||||
#define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */
|
||||
#define SBIC_CSR_SLT 0x82 /* selected, no ATN */
|
||||
#define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */
|
||||
#define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */
|
||||
#define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */
|
||||
#define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */
|
||||
#define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */
|
||||
|
||||
#define SBIC_PHASE(csr) SCSI_PHASE(csr)
|
||||
|
||||
/*
|
||||
* Command register (command codes)
|
||||
*/
|
||||
|
||||
#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */
|
||||
#define SBIC_CMD_MASK 0x7f
|
||||
|
||||
/* Miscellaneous */
|
||||
#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */
|
||||
#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */
|
||||
#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */
|
||||
#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */
|
||||
#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */
|
||||
#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */
|
||||
|
||||
/* Initiator state */
|
||||
#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */
|
||||
#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */
|
||||
#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */
|
||||
#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */
|
||||
|
||||
/* Target state */
|
||||
#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND 0x17 /* ( T ) lev II */
|
||||
|
||||
/* Disconnected state */
|
||||
#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL 0x07 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */
|
||||
#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */
|
||||
#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */
|
||||
#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
|
||||
#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
|
||||
|
||||
/* approximate, but we won't do SBT on selects */
|
||||
#define sbic_isa_select(cmd) (((cmd) > 0x5) && ((cmd) < 0xa))
|
||||
|
||||
#define SBIC_MACHINE_DMA_MODE SBIC_CTL_DMA
|
||||
|
||||
#define sbic_read_reg(iobase,regno,val) do { \
|
||||
outb(iobase, (regno)); \
|
||||
(val) = inb((iobase) + 2); \
|
||||
} while (0)
|
||||
|
||||
#define sbic_write_reg(iobase,regno,val) do { \
|
||||
outb(iobase, (regno)); \
|
||||
outb((iobase) + 2, (val)); \
|
||||
} while (0)
|
||||
|
||||
#define SET_SBIC_myid(iobase,val) sbic_write_reg(iobase,SBIC_myid,val)
|
||||
#define GET_SBIC_myid(iobase,val) sbic_read_reg(iobase,SBIC_myid,val)
|
||||
#define SET_SBIC_cdbsize(iobase,val) sbic_write_reg(iobase,SBIC_cdbsize,val)
|
||||
#define GET_SBIC_cdbsize(iobase,val) sbic_read_reg(iobase,SBIC_cdbsize,val)
|
||||
#define SET_SBIC_control(iobase,val) sbic_write_reg(iobase,SBIC_control,val)
|
||||
#define GET_SBIC_control(iobase,val) sbic_read_reg(iobase,SBIC_control,val)
|
||||
#define SET_SBIC_timeo(iobase,val) sbic_write_reg(iobase,SBIC_timeo,val)
|
||||
#define GET_SBIC_timeo(iobase,val) sbic_read_reg(iobase,SBIC_timeo,val)
|
||||
#define SET_SBIC_cdb1(iobase,val) sbic_write_reg(iobase,SBIC_cdb1,val)
|
||||
#define GET_SBIC_cdb1(iobase,val) sbic_read_reg(iobase,SBIC_cdb1,val)
|
||||
#define SET_SBIC_cdb2(iobase,val) sbic_write_reg(iobase,SBIC_cdb2,val)
|
||||
#define GET_SBIC_cdb2(iobase,val) sbic_read_reg(iobase,SBIC_cdb2,val)
|
||||
#define SET_SBIC_cdb3(iobase,val) sbic_write_reg(iobase,SBIC_cdb3,val)
|
||||
#define GET_SBIC_cdb3(iobase,val) sbic_read_reg(iobase,SBIC_cdb3,val)
|
||||
#define SET_SBIC_cdb4(iobase,val) sbic_write_reg(iobase,SBIC_cdb4,val)
|
||||
#define GET_SBIC_cdb4(iobase,val) sbic_read_reg(iobase,SBIC_cdb4,val)
|
||||
#define SET_SBIC_cdb5(iobase,val) sbic_write_reg(iobase,SBIC_cdb5,val)
|
||||
#define GET_SBIC_cdb5(iobase,val) sbic_read_reg(iobase,SBIC_cdb5,val)
|
||||
#define SET_SBIC_cdb6(iobase,val) sbic_write_reg(iobase,SBIC_cdb6,val)
|
||||
#define GET_SBIC_cdb6(iobase,val) sbic_read_reg(iobase,SBIC_cdb6,val)
|
||||
#define SET_SBIC_cdb7(iobase,val) sbic_write_reg(iobase,SBIC_cdb7,val)
|
||||
#define GET_SBIC_cdb7(iobase,val) sbic_read_reg(iobase,SBIC_cdb7,val)
|
||||
#define SET_SBIC_cdb8(iobase,val) sbic_write_reg(iobase,SBIC_cdb8,val)
|
||||
#define GET_SBIC_cdb8(iobase,val) sbic_read_reg(iobase,SBIC_cdb8,val)
|
||||
#define SET_SBIC_cdb9(iobase,val) sbic_write_reg(iobase,SBIC_cdb9,val)
|
||||
#define GET_SBIC_cdb9(iobase,val) sbic_read_reg(iobase,SBIC_cdb9,val)
|
||||
#define SET_SBIC_cdb10(iobase,val) sbic_write_reg(iobase,SBIC_cdb10,val)
|
||||
#define GET_SBIC_cdb10(iobase,val) sbic_read_reg(iobase,SBIC_cdb10,val)
|
||||
#define SET_SBIC_cdb11(iobase,val) sbic_write_reg(iobase,SBIC_cdb11,val)
|
||||
#define GET_SBIC_cdb11(iobase,val) sbic_read_reg(iobase,SBIC_cdb11,val)
|
||||
#define SET_SBIC_cdb12(iobase,val) sbic_write_reg(iobase,SBIC_cdb12,val)
|
||||
#define GET_SBIC_cdb12(iobase,val) sbic_read_reg(iobase,SBIC_cdb12,val)
|
||||
#define SET_SBIC_tlun(iobase,val) sbic_write_reg(iobase,SBIC_tlun,val)
|
||||
#define GET_SBIC_tlun(iobase,val) sbic_read_reg(iobase,SBIC_tlun,val)
|
||||
#define SET_SBIC_cmd_phase(iobase,val) sbic_write_reg(iobase,SBIC_cmd_phase,val)
|
||||
#define GET_SBIC_cmd_phase(iobase,val) sbic_read_reg(iobase,SBIC_cmd_phase,val)
|
||||
#define SET_SBIC_syn(iobase,val) sbic_write_reg(iobase,SBIC_syn,val)
|
||||
#define GET_SBIC_syn(iobase,val) sbic_read_reg(iobase,SBIC_syn,val)
|
||||
#define SET_SBIC_count_hi(iobase,val) sbic_write_reg(iobase,SBIC_count_hi,val)
|
||||
#define GET_SBIC_count_hi(iobase,val) sbic_read_reg(iobase,SBIC_count_hi,val)
|
||||
#define SET_SBIC_count_med(iobase,val) sbic_write_reg(iobase,SBIC_count_med,val)
|
||||
#define GET_SBIC_count_med(iobase,val) sbic_read_reg(iobase,SBIC_count_med,val)
|
||||
#define SET_SBIC_count_lo(iobase,val) sbic_write_reg(iobase,SBIC_count_lo,val)
|
||||
#define GET_SBIC_count_lo(iobase,val) sbic_read_reg(iobase,SBIC_count_lo,val)
|
||||
#define SET_SBIC_selid(iobase,val) sbic_write_reg(iobase,SBIC_selid,val)
|
||||
#define GET_SBIC_selid(iobase,val) sbic_read_reg(iobase,SBIC_selid,val)
|
||||
#define SET_SBIC_rselid(iobase,val) sbic_write_reg(iobase,SBIC_rselid,val)
|
||||
#define GET_SBIC_rselid(iobase,val) sbic_read_reg(iobase,SBIC_rselid,val)
|
||||
#define SET_SBIC_csr(iobase,val) sbic_write_reg(iobase,SBIC_csr,val)
|
||||
#define GET_SBIC_csr(iobase,val) sbic_read_reg(iobase,SBIC_csr,val)
|
||||
#define SET_SBIC_cmd(iobase,val) sbic_write_reg(iobase,SBIC_cmd,val)
|
||||
#define GET_SBIC_cmd(iobase,val) sbic_read_reg(iobase,SBIC_cmd,val)
|
||||
#define SET_SBIC_data(iobase,val) sbic_write_reg(iobase,SBIC_data,val)
|
||||
#define GET_SBIC_data(iobase,val) sbic_read_reg(iobase,SBIC_data,val)
|
||||
#define SET_SBIC_mem_bank(iobase,val) sbic_write_reg(iobase,SBIC_mem_bank,val)
|
||||
#define GET_SBIC_mem_bank(iobase,val) sbic_read_reg(iobase,SBIC_mem_bank,val)
|
||||
#define GET_SBIC_mem_win(iobase,val) sbic_read_reg(iobase,SBIC_mem_win,val)
|
||||
#define GET_SBIC_reset_int(iobase,val) sbic_read_reg(iobase,SBIC_reset_int,val)
|
||||
|
||||
#define SBIC_TC_PUT(iobase,val) do { \
|
||||
sbic_write_reg(iobase,SBIC_count_hi,((val)>>16)); \
|
||||
outb((iobase) + 2, ((val)>>8)); \
|
||||
outb((iobase) + 2, (val)); \
|
||||
} while (0)
|
||||
#define SBIC_TC_GET(iobase,val) do { \
|
||||
sbic_read_reg(iobase,SBIC_count_hi,(val)); \
|
||||
(val) = ((val)<<8) | inb((iobase) + 2); \
|
||||
(val) = ((val)<<8) | inb((iobase) + 2); \
|
||||
} while (0)
|
||||
|
||||
#define SBIC_LOAD_COMMAND(iobase,cmd,cmdsize) do { \
|
||||
int n=(cmdsize)-1; \
|
||||
char *ptr = (char*)(cmd); \
|
||||
sbic_write_reg(iobase,SBIC_cdb1,*ptr++); \
|
||||
while (n-- > 0) outb((iobase) + 2, *ptr++); \
|
||||
} while (0)
|
||||
|
||||
#define GET_SBIC_asr(iobase,val) (val) = inb(iobase)
|
||||
|
||||
#define WAIT_CIP(iobase) do { \
|
||||
while (inb(iobase) & SBIC_ASR_CIP) \
|
||||
; \
|
||||
} while (0)
|
||||
|
||||
/* transmit a byte in programmed I/O mode */
|
||||
#define SEND_BYTE(iobase,ch) do { \
|
||||
WAIT_CIP((iobase)->sc_base); \
|
||||
SET_SBIC_cmd((iobase)->sc_base, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
|
||||
SBIC_WAIT(iobase, SBIC_ASR_DBR, 0); \
|
||||
SET_SBIC_data((iobase)->sc_base, ch); \
|
||||
} while (0)
|
||||
|
||||
/* receive a byte in programmed I/O mode */
|
||||
#define RECV_BYTE(iobase,ch) do { \
|
||||
WAIT_CIP((iobase)->sc_base); \
|
||||
SET_SBIC_cmd((iobase)->sc_base, SBIC_CMD_SBT | SBIC_CMD_XFER_INFO); \
|
||||
SBIC_WAIT(iobase, SBIC_ASR_DBR, 0); \
|
||||
GET_SBIC_data((iobase)->sc_base, ch); \
|
||||
} while (0)
|
@ -1,157 +0,0 @@
|
||||
/* $NetBSD: sbicvar.h,v 1.5 1995/02/12 19:19:21 chopps Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Van Jacobson of Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)scsivar.h 7.1 (Berkeley) 5/8/90
|
||||
*/
|
||||
/*
|
||||
* Ported to PC-9801 by Yoshio Kimura, 1994
|
||||
* last update 09/23/1994
|
||||
*/
|
||||
#ifndef _SBICVAR_H_
|
||||
#define _SBICVAR_H_
|
||||
|
||||
/*
|
||||
* The largest single request will be MAXPHYS bytes which will require
|
||||
* at most MAXPHYS/PAGE_SIZE+1 chain elements to describe, i.e. if none of
|
||||
* the buffer pages are physically contiguous (MAXPHYS/PAGE_SIZE) and the
|
||||
* buffer is not page aligned (+1).
|
||||
*/
|
||||
#define SBIC_NSEG 17
|
||||
|
||||
struct dma_chain {
|
||||
int dc_count;
|
||||
int dc_addr;
|
||||
};
|
||||
|
||||
struct sbic_pending {
|
||||
TAILQ_ENTRY(sbic_pending) link;
|
||||
struct scsi_xfer *xs;
|
||||
};
|
||||
|
||||
struct sbic_softc {
|
||||
#ifndef __FreeBSD__
|
||||
struct device sc_dev;
|
||||
struct pc98dev sc_id;
|
||||
struct intrhand sc_ih;
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
int unit; /* unit number */
|
||||
#endif
|
||||
u_short sc_base;
|
||||
u_short sc_int;
|
||||
u_short sc_dma;
|
||||
int sc_scsi_dev;
|
||||
u_long sc_clkfreq;
|
||||
|
||||
struct target_sync {
|
||||
u_char state;
|
||||
u_char period;
|
||||
u_char offset;
|
||||
} sc_sync[8];
|
||||
struct scsi_link sc_link; /* proto for sub devices */
|
||||
TAILQ_HEAD(,sbic_pending) sc_xslist; /* LIFO */
|
||||
struct sbic_pending sc_xsstore[8][8]; /* one for every unit */
|
||||
struct scsi_xfer *sc_xs; /* transfer from high level code */
|
||||
u_char sc_flags;
|
||||
u_char sc_stat[2];
|
||||
u_char sc_msg[7];
|
||||
struct dma_chain sc_chain[SBIC_NSEG];
|
||||
struct dma_chain *sc_cur;
|
||||
struct dma_chain *sc_last;
|
||||
};
|
||||
|
||||
/* sc_flags */
|
||||
#define SBICF_ALIVE 0x01 /* controller initialized */
|
||||
#define SBICF_DCFLUSH 0x02 /* need flush for overlap after dma finishes */
|
||||
#define SBICF_SELECTED 0x04 /* bus is in selected state. */
|
||||
#define SBICF_BADDMA 0x10 /* controller can only DMA to ztwobus space */
|
||||
#define SBICF_BBUF 0x20 /* DMA input needs to be copied from bounce */
|
||||
#define SBICF_INTR 0x40 /* SBICF interrupt expected */
|
||||
#define SBICF_INDMA 0x80 /* not used yet, DMA I/O in progress */
|
||||
|
||||
/* sync states */
|
||||
#define SYNC_START 0 /* no sync handshake started */
|
||||
#define SYNC_SENT 1 /* we sent sync request, no answer yet */
|
||||
#define SYNC_DONE 2 /* target accepted our (or inferior) settings,
|
||||
or it rejected the request and we stay async */
|
||||
#ifdef DEBUG
|
||||
#define DDB_FOLLOW 0x04
|
||||
#define DDB_IO 0x08
|
||||
#endif
|
||||
|
||||
#define PHASE 0x07 /* mask for psns/pctl phase */
|
||||
#define DATA_OUT_PHASE 0x00
|
||||
#define DATA_IN_PHASE 0x01
|
||||
#define CMD_PHASE 0x02
|
||||
#define STATUS_PHASE 0x03
|
||||
#define BUS_FREE_PHASE 0x04
|
||||
#define ARB_SEL_PHASE 0x05 /* Fuji chip combines arbitration with sel. */
|
||||
#define MESG_OUT_PHASE 0x06
|
||||
#define MESG_IN_PHASE 0x07
|
||||
|
||||
#define MSG_CMD_COMPLETE 0x00
|
||||
#define MSG_EXT_MESSAGE 0x01
|
||||
#define MSG_SAVE_DATA_PTR 0x02
|
||||
#define MSG_RESTORE_PTR 0x03
|
||||
#define MSG_DISCONNECT 0x04
|
||||
#define MSG_INIT_DETECT_ERROR 0x05
|
||||
#define MSG_ABORT 0x06
|
||||
#define MSG_REJECT 0x07
|
||||
#define MSG_NOOP 0x08
|
||||
#define MSG_PARITY_ERROR 0x09
|
||||
#define MSG_BUS_DEVICE_RESET 0x0C
|
||||
#define MSG_IDENTIFY 0x80
|
||||
#define MSG_IDENTIFY_DR 0xc0 /* (disconnect/reconnect allowed) */
|
||||
#define MSG_SYNC_REQ 0x01
|
||||
|
||||
|
||||
#define STS_CHECKCOND 0x02 /* Check Condition (ie., read sense) */
|
||||
#define STS_CONDMET 0x04 /* Condition Met (ie., search worked) */
|
||||
#define STS_BUSY 0x08
|
||||
#define STS_INTERMED 0x10 /* Intermediate status sent */
|
||||
#define STS_EXT 0x80 /* Extended status valid */
|
||||
|
||||
/*
|
||||
* XXXX
|
||||
*/
|
||||
struct scsi_fmt_cdb {
|
||||
int len; /* cdb length (in bytes) */
|
||||
u_char cdb[28]; /* cdb to use on next read/write */
|
||||
};
|
||||
|
||||
#endif /* _SBICVAR_H_ */
|
@ -1,312 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1990 The Regents of the University of California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to Berkeley by
|
||||
* Van Jacobson of Lawrence Berkeley Laboratory.
|
||||
*
|
||||
* 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. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* This product includes software developed by the University of
|
||||
* California, Berkeley and its contributors.
|
||||
* 4. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
|
||||
*
|
||||
* @(#)scsireg.h 7.3 (Berkeley) 2/5/91
|
||||
*/
|
||||
|
||||
/*
|
||||
* AMD AM33C93A SCSI interface hardware description.
|
||||
*
|
||||
* Using parts of the Mach scsi driver for the 33C93
|
||||
*/
|
||||
|
||||
#define SBIC_myid 0
|
||||
#define SBIC_cdbsize 0
|
||||
#define SBIC_control 1
|
||||
#define SBIC_timeo 2
|
||||
#define SBIC_cdb1 3
|
||||
#define SBIC_tsecs 3
|
||||
#define SBIC_cdb2 4
|
||||
#define SBIC_theads 4
|
||||
#define SBIC_cdb3 5
|
||||
#define SBIC_tcyl_hi 5
|
||||
#define SBIC_cdb4 6
|
||||
#define SBIC_tcyl_lo 6
|
||||
#define SBIC_cdb5 7
|
||||
#define SBIC_addr_hi 7
|
||||
#define SBIC_cdb6 8
|
||||
#define SBIC_addr_2 8
|
||||
#define SBIC_cdb7 9
|
||||
#define SBIC_addr_3 9
|
||||
#define SBIC_cdb8 10
|
||||
#define SBIC_addr_lo 10
|
||||
#define SBIC_cdb9 11
|
||||
#define SBIC_secno 11
|
||||
#define SBIC_cdb10 12
|
||||
#define SBIC_headno 12
|
||||
#define SBIC_cdb11 13
|
||||
#define SBIC_cylno_hi 13
|
||||
#define SBIC_cdb12 14
|
||||
#define SBIC_cylno_lo 14
|
||||
#define SBIC_tlun 15
|
||||
#define SBIC_cmd_phase 16
|
||||
#define SBIC_syn 17
|
||||
#define SBIC_count_hi 18
|
||||
#define SBIC_count_med 19
|
||||
#define SBIC_count_lo 20
|
||||
#define SBIC_selid 21
|
||||
#define SBIC_rselid 22
|
||||
#define SBIC_csr 23
|
||||
#define SBIC_cmd 24
|
||||
#define SBIC_data 25
|
||||
#define SBIC_bank 48
|
||||
#define SBIC_window 49
|
||||
#define SBIC_int 51
|
||||
/* sbic_asr is addressed directly */
|
||||
|
||||
/*
|
||||
* Register defines
|
||||
*/
|
||||
|
||||
/*
|
||||
* Auxiliary Status Register
|
||||
*/
|
||||
|
||||
#define SBIC_ASR_INT 0x80 /* Interrupt pending */
|
||||
#define SBIC_ASR_LCI 0x40 /* Last command ignored */
|
||||
#define SBIC_ASR_BSY 0x20 /* Busy, only cmd/data/asr readable */
|
||||
#define SBIC_ASR_CIP 0x10 /* Busy, cmd unavail also */
|
||||
#define SBIC_ASR_xxx 0x0c
|
||||
#define SBIC_ASR_PE 0x02 /* Parity error (even) */
|
||||
#define SBIC_ASR_DBR 0x01 /* Data Buffer Ready */
|
||||
|
||||
/*
|
||||
* My ID register, and/or CDB Size
|
||||
*/
|
||||
|
||||
#define SBIC_ID_FS_8_10 0x00 /* Input clock is 8-10 Mhz */
|
||||
/* 11 Mhz is invalid */
|
||||
#define SBIC_ID_FS_12_15 0x40 /* Input clock is 12-15 Mhz */
|
||||
#define SBIC_ID_FS_16_20 0x80 /* Input clock is 16-20 Mhz */
|
||||
#define SBIC_ID_EHP 0x10 /* Enable host parity */
|
||||
#define SBIC_ID_EAF 0x08 /* Enable Advanced Features */
|
||||
#define SBIC_ID_MASK 0x07
|
||||
#define SBIC_ID_CBDSIZE_MASK 0x0f /* if unk SCSI cmd group */
|
||||
|
||||
/*
|
||||
* Control register
|
||||
*/
|
||||
|
||||
#define SBIC_CTL_DMA 0x80 /* Single byte dma */
|
||||
#define SBIC_CTL_DBA_DMA 0x40 /* direct buffer acces (bus master)*/
|
||||
#define SBIC_CTL_BURST_DMA 0x20 /* continuous mode (8237) */
|
||||
#define SBIC_CTL_NO_DMA 0x00 /* Programmed I/O */
|
||||
#define SBIC_CTL_HHP 0x10 /* Halt on host parity error */
|
||||
#define SBIC_CTL_EDI 0x08 /* Ending disconnect interrupt */
|
||||
#define SBIC_CTL_IDI 0x04 /* Intermediate disconnect interrupt*/
|
||||
#define SBIC_CTL_HA 0x02 /* Halt on ATN */
|
||||
#define SBIC_CTL_HSP 0x01 /* Halt on SCSI parity error */
|
||||
|
||||
/*
|
||||
* Timeout period register
|
||||
* [val in msecs, input clk in Mhz]
|
||||
*/
|
||||
|
||||
#define SBIC_TIMEOUT(val,clk) ((((val)*(clk))/80)+1)
|
||||
|
||||
/*
|
||||
* CDBn registers, note that
|
||||
* cdb11 is used for status byte in target mode (send-status-and-cc)
|
||||
* cdb12 sez if linked command complete, and w/flag if so
|
||||
*/
|
||||
|
||||
/*
|
||||
* Target LUN register
|
||||
* [holds target status when select-and-xfer]
|
||||
*/
|
||||
|
||||
#define SBIC_TLUN_VALID 0x80 /* did we receive an Identify msg */
|
||||
#define SBIC_TLUN_DOK 0x40 /* Disconnect OK */
|
||||
#define SBIC_TLUN_xxx 0x38
|
||||
#define SBIC_TLUN_MASK 0x07
|
||||
|
||||
/*
|
||||
* Command Phase register
|
||||
*/
|
||||
|
||||
#define SBIC_CPH_MASK 0x7f /* values/restarts are cmd specific */
|
||||
#define SBIC_CPH(p) ((p)&SBIC_CPH_MASK)
|
||||
|
||||
/*
|
||||
* FIFO register
|
||||
*/
|
||||
|
||||
#define SBIC_FIFO_DEEP 12
|
||||
|
||||
/*
|
||||
* Synchronous xfer register
|
||||
*/
|
||||
|
||||
#define SBIC_SYN_OFF_MASK 0x0f
|
||||
#define SBIC_SYN_MAX_OFFSET (SBIC_FIFO_DEEP-1)
|
||||
#define SBIC_SYN_PER_MASK 0x70
|
||||
#define SBIC_SYN_MIN_PERIOD 2 /* upto 8, encoded as 0 */
|
||||
|
||||
#define SBIC_SYN(o,p) (((o)&SBIC_SYN_OFF_MASK)|(((p)<<4)&SBIC_SYN_PER_MASK))
|
||||
|
||||
/*
|
||||
* Transfer count register
|
||||
* optimal access macros depend on addressing
|
||||
*/
|
||||
|
||||
/*
|
||||
* Destination ID (selid) register
|
||||
*/
|
||||
|
||||
#define SBIC_SID_SCC 0x80 /* Select command chaining (tgt) */
|
||||
#define SBIC_SID_DPD 0x40 /* Data phase direction (inittor) */
|
||||
# define SBIC_SID_FROM_SCSI 0x40
|
||||
# define SBIC_SID_TO_SCSI 0x00
|
||||
#define SBIC_SID_xxx 0x38
|
||||
#define SBIC_SID_IDMASK 0x07
|
||||
|
||||
/*
|
||||
* Source ID (rselid) register
|
||||
*/
|
||||
|
||||
#define SBIC_RID_ER 0x80 /* Enable reselection */
|
||||
#define SBIC_RID_ES 0x40 /* Enable selection */
|
||||
#define SBIC_RID_DSP 0x20 /* Disable select parity */
|
||||
#define SBIC_RID_SIV 0x08 /* Source ID valid */
|
||||
#define SBIC_RID_MASK 0x07
|
||||
|
||||
/*
|
||||
* Status register
|
||||
*/
|
||||
|
||||
#define SBIC_CSR_CAUSE 0xf0
|
||||
# define SBIC_CSR_RESET 0x00 /* chip was reset */
|
||||
# define SBIC_CSR_CMD_DONE 0x10 /* cmd completed */
|
||||
# define SBIC_CSR_CMD_STOPPED 0x20 /* interrupted or abrted*/
|
||||
# define SBIC_CSR_CMD_ERR 0x40 /* end with error */
|
||||
# define SBIC_CSR_BUS_SERVICE 0x80 /* REQ pending on the bus */
|
||||
|
||||
#define SBIC_CSR_QUALIFIER 0x0f
|
||||
|
||||
/* Reset State Interrupts */
|
||||
# define SBIC_CSR_RESET 0x00 /* reset w/advanced features*/
|
||||
# define SBIC_CSR_RESET_AM 0x01 /* reset w/advanced features*/
|
||||
|
||||
/* Successful Completion Interrupts */
|
||||
# define SBIC_CSR_TARGET 0x10 /* reselect complete */
|
||||
# define SBIC_CSR_INITIATOR 0x11 /* select complete */
|
||||
# define SBIC_CSR_WO_ATN 0x13 /* tgt mode completion */
|
||||
# define SBIC_CSR_W_ATN 0x14 /* ditto */
|
||||
# define SBIC_CSR_XLATED 0x15 /* translate address cmd */
|
||||
# define SBIC_CSR_S_XFERRED 0x16 /* initiator mode completion*/
|
||||
# define SBIC_CSR_XFERRED 0x18 /* phase in low bits */
|
||||
|
||||
/* Paused or Aborted Interrupts */
|
||||
# define SBIC_CSR_MSGIN_W_ACK 0x20 /* (I) msgin, ACK asserted*/
|
||||
# define SBIC_CSR_SDP 0x21 /* (I) SDP msg received */
|
||||
# define SBIC_CSR_SEL_ABRT 0x22 /* sel/resel aborted */
|
||||
# define SBIC_CSR_XFR_PAUSED 0x23 /* (T) no ATN */
|
||||
# define SBIC_CSR_XFR_PAUSED_ATN 0x24 /* (T) ATN is asserted */
|
||||
# define SBIC_CSR_RSLT_AM 0x27 /* (I) lost selection (AM) */
|
||||
# define SBIC_CSR_MIS 0x28 /* (I) xfer aborted, ph mis */
|
||||
|
||||
/* Terminated Interrupts */
|
||||
# define SBIC_CSR_CMD_INVALID 0x40
|
||||
# define SBIC_CSR_DISC 0x41 /* (I) tgt disconnected */
|
||||
# define SBIC_CSR_SEL_TIMEO 0x42
|
||||
# define SBIC_CSR_PE 0x43 /* parity error */
|
||||
# define SBIC_CSR_PE_ATN 0x44 /* ditto, ATN is asserted */
|
||||
# define SBIC_CSR_XLATE_TOOBIG 0x45
|
||||
# define SBIC_CSR_RSLT_NOAM 0x46 /* (I) lost sel, no AM mode */
|
||||
# define SBIC_CSR_BAD_STATUS 0x47 /* status byte was nok */
|
||||
# define SBIC_CSR_MIS_1 0x48 /* ph mis, see low bits */
|
||||
|
||||
# define SBIC_MCI_DATA_OUT 0x00 /* Data Out phase */
|
||||
# define SBIC_MCI_DATA_IN 0x01 /* Data In phase */
|
||||
# define SBIC_MCI_CMD 0x02 /* Command phase */
|
||||
# define SBIC_MCI_STATUS 0x03 /* Status phase */
|
||||
# define SBIC_MCI_INFO_OUT 0x04 /* Unspecified Info Out phase */
|
||||
# define SBIC_MCI_INFO_IN 0x05 /* Unspecified Info In phase */
|
||||
# define SBIC_MCI_MES_OUT 0x06 /* Message Out phase */
|
||||
# define SBIC_MCI_MES_IN 0x07 /* Message In phase */
|
||||
|
||||
/* Service Required Interrupts */
|
||||
# define SBIC_CSR_RSLT_NI 0x80 /* reselected, no ify msg */
|
||||
# define SBIC_CSR_RSLT_IFY 0x81 /* ditto, AM mode, got ify */
|
||||
# define SBIC_CSR_SLT 0x82 /* selected, no ATN */
|
||||
# define SBIC_CSR_SLT_ATN 0x83 /* selected with ATN */
|
||||
# define SBIC_CSR_ATN 0x84 /* (T) ATN asserted */
|
||||
# define SBIC_CSR_DISC_1 0x85 /* (I) bus is free */
|
||||
# define SBIC_CSR_UNK_GROUP 0x87 /* strange CDB1 */
|
||||
# define SBIC_CSR_MIS_2 0x88 /* (I) ph mis, see low bits */
|
||||
|
||||
#define SBIC_PHASE(csr) SCSI_PHASE(csr)
|
||||
|
||||
/*
|
||||
* Command register (command codes)
|
||||
*/
|
||||
|
||||
#define SBIC_CMD_SBT 0x80 /* Single byte xfer qualifier */
|
||||
#define SBIC_CMD_MASK 0x7f
|
||||
|
||||
/* Miscellaneous */
|
||||
#define SBIC_CMD_RESET 0x00 /* (DTI) lev I */
|
||||
#define SBIC_CMD_ABORT 0x01 /* (DTI) lev I */
|
||||
#define SBIC_CMD_DISC 0x04 /* ( TI) lev I */
|
||||
#define SBIC_CMD_SSCC 0x0d /* ( TI) lev I */
|
||||
#define SBIC_CMD_SET_IDI 0x0f /* (DTI) lev I */
|
||||
#define SBIC_CMD_XLATE 0x18 /* (DT ) lev II */
|
||||
|
||||
/* Initiator state */
|
||||
#define SBIC_CMD_SET_ATN 0x02 /* ( I) lev I */
|
||||
#define SBIC_CMD_CLR_ACK 0x03 /* ( I) lev I */
|
||||
#define SBIC_CMD_XFER_PAD 0x19 /* ( I) lev II */
|
||||
#define SBIC_CMD_XFER_INFO 0x20 /* ( I) lev II */
|
||||
|
||||
/* Target state */
|
||||
#define SBIC_CMD_SND_DISC 0x0e /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_CMD 0x10 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_DATA 0x11 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV_MSG_OUT 0x12 /* ( T ) lev II */
|
||||
#define SBIC_CMD_RCV 0x13 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_STATUS 0x14 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_DATA 0x15 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND_MSG_IN 0x16 /* ( T ) lev II */
|
||||
#define SBIC_CMD_SND 0x17 /* ( T ) lev II */
|
||||
|
||||
/* Disconnected state */
|
||||
#define SBIC_CMD_RESELECT 0x05 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL_ATN 0x06 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL 0x07 /* (D ) lev II */
|
||||
#define SBIC_CMD_SEL_ATN_XFER 0x08 /* (D I) lev II */
|
||||
#define SBIC_CMD_SEL_XFER 0x09 /* (D I) lev II */
|
||||
#define SBIC_CMD_RESELECT_RECV 0x0a /* (DT ) lev II */
|
||||
#define SBIC_CMD_RESELECT_SEND 0x0b /* (DT ) lev II */
|
||||
#define SBIC_CMD_WAIT_SEL_RECV 0x0c /* (DT ) lev II */
|
Loading…
Reference in New Issue
Block a user