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:
Satoshi Asami 1996-12-04 04:32:52 +00:00
parent f48465862b
commit 778128e3f9
23 changed files with 6103 additions and 3697 deletions

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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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_ */

View File

@ -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_ */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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_ */

View File

@ -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 */