* Copyright (c) 1992 OMRON Corporation.
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
* This code is derived from software contributed to Berkeley by
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 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
* @(#)sc.c 8.2 (Berkeley) 12/6/93
* sc.c -- FUJITSU MB89352 SCSI Protocole Controller (SPC) Device Driver
* remaked by A.Fujita, Mar-22-1992
* remaked again by A.Fujita, Apr-16-1992
#include <luna68k/dev/device.h>
#include <luna68k/dev/screg.h>
#include <luna68k/dev/scvar.h>
#define QUADBYTES /* 4 bytes access to SPC DREG Reg. */
#define NODISCONNECT /* not used SCSI DISCONNECT Ops. */
#undef XFER_ENABLE /* using interrupt for DREG access */
int scinit(), scstart(), scintr();
struct driver scdriver
= {
scinit
, "sc", scstart
, (int (*)()) 0, scintr
, (int (*)()) 0
struct sc_softc sc_softc
[NSC
];
#define SC_TIMEOUT 0x01400000 /* (20971520) */
else if ((stat
& 0x1e) == STS_CHECKCOND
)
return("Check Condition");
else if ((stat
& 0x1e) == STS_CONDMET
)
else if ((stat
& 0x1e) == STS_BUSY
)
else if ((stat
& 0x1e) == STS_INTERMED
)
return("Intermediate status sent");
else if ((stat
& 0x1e) == STS_EXT
)
return("Extended status valid");
return("Unknown Status");
if (cmd
== CMD_TEST_UNIT_READY
)
return("TEST_UNIT_READY");
else if (cmd
== CMD_REQUEST_SENSE
)
else if (cmd
== CMD_INQUIRY
)
else if (cmd
== CMD_READ
)
else if (cmd
== CMD_WRITE
)
else if (cmd
== CMD_READ_EXT
)
else if (cmd
== CMD_WRITE_EXT
)
else if (cmd
== CMD_READ_CAPACITY
)
if (mesg
== MSG_CMD_COMPLETE
)
return("Command Complete");
else if (mesg
== MSG_EXT_MESSAGE
)
return("Extended Message");
else if (mesg
== MSG_SAVE_DATA_PTR
)
return("Save Data Pointer");
else if (mesg
== MSG_RESTORE_PTR
)
return("Restore Pointer");
else if (mesg
== MSG_DISCONNECT
)
else if (mesg
== MSG_INIT_DETECT_ERROR
)
return("Initiator Detected Error");
else if (mesg
== MSG_ABORT
)
else if (mesg
== MSG_REJECT
)
return("Message Reject");
else if (mesg
== MSG_NOOP
)
else if (mesg
== MSG_PARITY_ERROR
)
return("Message Parity Error");
else if (mesg
== MSG_BUS_DEVICE_RESET
)
return("Bus Device Reset");
else if (mesg
== MSG_IDENTIFY
)
else if (mesg
== MSG_IDENTIFY_DR
)
return("Identify (Disconnect)");
return("Unknown Message");
if (phase
== DATA_OUT_PHASE
)
else if (phase
== DATA_IN_PHASE
)
else if (phase
== CMD_PHASE
)
else if (phase
== STATUS_PHASE
)
else if (phase
== BUS_FREE_PHASE
)
else if (phase
== ARB_SEL_PHASE
)
return("Arbitration/Select");
else if (phase
== MESG_OUT_PHASE
)
else if (phase
== MESG_IN_PHASE
)
* Initialize SPC & Data Structure
register struct hp_ctlr
*hc
;
register struct sc_softc
*hs
= &sc_softc
[hc
->hp_unit
];
hs
->sc_sq
.dq_forw
= hs
->sc_sq
.dq_back
= &hs
->sc_sq
;
hs
->sc_wq
.dq_forw
= hs
->sc_wq
.dq_back
= &hs
->sc_wq
;
hs
->sc_phase
= BUS_FREE_PHASE
;
register struct sc_softc
*hs
= &sc_softc
[unit
];
volatile register struct scsidevice
*hd
=
(struct scsidevice
*)hs
->sc_hc
->hp_addr
;
* Disable interrupts then reset the FUJI chip.
hd
->scsi_sctl
= SCTL_DISABLE
| SCTL_CTRLRST
;
/* We can use Asynchronous Transfer only */
* Configure MB89352 with its SCSI address, all
* interrupts enabled & appropriate parity.
hd
->scsi_sctl
= SCTL_DISABLE
| SCTL_ABRT_ENAB
|
SCTL_PARITY_ENAB
| SCTL_RESEL_ENAB
|
hd
->scsi_sctl
&= ~SCTL_DISABLE
;
printf(", scsi id %d\n", SCSI_ID
);
* SPC Arbitration/Selection routine
issue_select(hd
, target
, flags
)
volatile register struct scsidevice
*hd
;
if (flags
& DQ_DISCONNECT
) {
hd
->scsi_scmd
= SCMD_SET_ATN
;
hd
->scsi_temp
= (1 << SCSI_ID
) | (1 << target
);
/* select timeout is hardcoded to 2ms */
hd
->scsi_scmd
= SCMD_SELECT
;
* SPC Manual Transfer routines
* SPC Program Transfer routines
ixfer_start(hd
, len
, phase
)
volatile register struct scsidevice
*hd
;
hd
->scsi_tch
= ((len
& 0xff0000) >> 16);
hd
->scsi_tcm
= ((len
& 0x00ff00) >> 8);
hd
->scsi_tcl
= (len
& 0x0000ff);
hd
->scsi_scmd
= SCMD_XFR
| SCMD_PROG_XFR
;
while ((hd
->scsi_ssts
& SSTS_BUSY
) == 0) {
panic("ixfer_start: too long wait");
volatile register struct scsidevice
*hd
;
register int l_len
= len
>> 3;
register u_long
* l_buf
= (u_long
*) buf
;
for(; l_len
> 0; l_len
--) {
while ((hd
->scsi_ssts
& SSTS_DREG_EMPTY
) == 0) {
if (qwait
> SC_TIMEOUT
) {
printf("ixfer_out: quad time out\n");
printf("ixfer_out: %d bytes sended\n",
(((u_char
*) l_buf
) - t
));
printf("ixfer_out: TC = %d\n",
*((u_long
*) &hd
->scsi_dreg
) = *l_buf
++;
*((u_long
*) &hd
->scsi_dreg
) = *l_buf
++;
while (hd
->scsi_ssts
& SSTS_DREG_FULL
) {
printf("ixfer_out: time out\n");
printf("ixfer_out: %d bytes sended\n",
volatile register struct scsidevice
*hd
;
register int l_len
= len
>> 3;
register u_long
* l_buf
= (u_long
*) buf
;
for(; l_len
> 0; l_len
--) {
while ((hd
->scsi_ssts
& SSTS_DREG_FULL
) == 0) {
if (qwait
> SC_TIMEOUT
) {
printf("ixfer_in: quad time out\n");
printf("ixfer_in: %d bytes recieved\n",
(((u_char
*) l_buf
) - t
));
*l_buf
++ = *((u_long
*) &hd
->scsi_dreg
);
*l_buf
++ = *((u_long
*) &hd
->scsi_dreg
);
while (hd
->scsi_ssts
& SSTS_DREG_EMPTY
) {
printf("ixfer_in: time out\n");
printf("ixfer_in: %d bytes recieved\n",
* SPC Interrupt base Transfer Routines
txfer_start(hd
, len
, phase
)
volatile register struct scsidevice
*hd
;
hd
->scsi_sdgc
= SDGC_XFER_ENAB
; /* for interrupt */
hd
->scsi_tch
= ((len
& 0xff0000) >> 16);
hd
->scsi_tcm
= ((len
& 0x00ff00) >> 8);
hd
->scsi_tcl
= (len
& 0x0000ff);
hd
->scsi_scmd
= SCMD_XFR
| SCMD_PROG_XFR
;
while ((hd
->scsi_ssts
& SSTS_BUSY
) == 0) {
panic("ixfer_start: too long wait");
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
volatile register struct scsidevice
*hd
= (struct scsidevice
*) hs
->sc_hc
->hp_addr
;
register struct scsi_queue
*dq
= hs
->sc_sq
.dq_forw
;
if (hd
->scsi_ssts
& SSTS_DREG_FULL
) {
lp
= (u_long
*) dq
->dq_xferp
;
*lp
++ = *((u_long
*) &hd
->scsi_dreg
);
*lp
++ = *((u_long
*) &hd
->scsi_dreg
);
dq
->dq_xferp
= (u_char
*) lp
;
*dq
->dq_xferp
++ = hd
->scsi_dreg
;
if (dq
->dq_xfercnt
== 0) {
dbgprintf("dq->dq_bp->b_un.b_addr = 0x%s, ", hexstr(dq
->dq_bp
->b_un
.b_addr
, 8));
dbgprintf("dq->dq_xferp = 0x%s :", hexstr(dq
->dq_xferp
, 8));
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
volatile register struct scsidevice
*hd
=
(struct scsidevice
*) hs
->sc_hc
->hp_addr
;
register struct scsi_queue
*dq
= hs
->sc_sq
.dq_forw
;
hs
->sc_phase
= ARB_SEL_PHASE
;
dbgprintf("scstart: ID = %d\n", dq
->dq_slave
);
dbgprintf("scstart: cdb[0] = %s\n", scsi_command(dq
->dq_cdb
->cdb
[0]));
dbgprintf("scstart: cdb[1] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[1], 2));
dbgprintf("scstart: cdb[2] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[2], 2));
dbgprintf("scstart: cdb[3] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[3], 2));
dbgprintf("scstart: cdb[4] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[4], 2));
dbgprintf("scstart: cdb[5] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[5], 2));
if (dq
->dq_cdb
->cdb
[0] & 0xE0) {
dbgprintf("scstart: cdb[6] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[6], 2));
dbgprintf("scstart: cdb[7] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[7], 2));
dbgprintf("scstart: cdb[8] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[8], 2));
dbgprintf("scstart: cdb[9] = 0x%s\n", hexstr(dq
->dq_cdb
->cdb
[9], 2));
dbgprintf("scstart: bp->b_bcount = %d\n", dq
->dq_bp
->b_bcount
);
dbgprintf("scstart: %s\n", phase_name(hs
->sc_phase
));
issue_select(hd
, dq
->dq_slave
, dq
->dq_flags
);
register struct sc_softc
*hs
;
volatile register struct scsidevice
*hd
;
for (ctlr
= 0; ctlr
< NSC
; ctlr
++) {
hd
= (struct scsidevice
*) hs
->sc_hc
->hp_addr
;
if (((hd
->scsi_psns
& PHASE
) == DATA_IN_PHASE
) &&
(hd
->scsi_serr
& SERR_XFER_OUT
))
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
volatile register struct scsidevice
*hd
= (struct scsidevice
*) hs
->sc_hc
->hp_addr
;
register struct scsi_queue
*dq
= hs
->sc_sq
.dq_forw
;
register u_char ints
, temp
;
dbgprintf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x",
ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
if (hs
->sc_phase
== CMD_PHASE
)
dbgprintf(" [%s]", scsi_command(dq
->dq_cdb
->cdb
[0]));
if (hs
->sc_phase
& PHASE_MSG
)
dbgprintf(" [%s]", scsi_mesg(hs
->sc_msg
[0]));
if (ints
& INTS_DISCON
) {
if (hs
->sc_msg
[0] == MSG_CMD_COMPLETE
) {
if (hs
->sc_lock
!= NULL
) {
*(hs
->sc_lock
) = SC_IO_COMPLETE
;
(dq
->dq_driver
->d_intr
)(dq
->dq_unit
, hs
->sc_stat
);
} else if (hs
->sc_msg
[0] == MSG_DISCONNECT
) {
dbgprintf("scintr: DISCONNECT : ctlr = %d, slave = %d, cdb = %s\n",
dq
->dq_ctlr
, dq
->dq_slave
, scsi_command(dq
->dq_cdb
->cdb
[0]));
(dq
->dq_driver
->d_start
)(dq
->dq_unit
);
} else if (ints
& INTS_RESEL
) {
temp
= hd
->scsi_temp
& ~(1 << SCSI_ID
);
for (slave
= 0; temp
!= 1; slave
++) {
dbgprintf("scintr: RESELECT : ctlr = %d, slave = %d, cdb = %s\n",
dq
->dq_ctlr
, dq
->dq_slave
, scsi_command(dq
->dq_cdb
->cdb
[0]));
} else if (ints
& INTS_CMD_DONE
) {
if (hs
->sc_phase
== BUS_FREE_PHASE
)
else if (hs
->sc_phase
== MESG_IN_PHASE
) {
hd
->scsi_scmd
= SCMD_RST_ACK
;
if ((hs
->sc_msg
[0] == MSG_CMD_COMPLETE
) ||
(hs
->sc_msg
[0] == MSG_DISCONNECT
)) {
hs
->sc_phase
= BUS_FREE_PHASE
;
if (hs
->sc_flags
& SC_SEL_TIMEOUT
)
hs
->sc_flags
&= ~SC_SEL_TIMEOUT
;
} else if (ints
& INTS_SRV_REQ
) {
if (hs
->sc_phase
!= MESG_IN_PHASE
)
} else if (ints
& INTS_TIMEOUT
) {
if (hs
->sc_phase
== ARB_SEL_PHASE
) {
if (hs
->sc_flags
& SC_SEL_TIMEOUT
) {
hs
->sc_flags
&= ~SC_SEL_TIMEOUT
;
/* Such SCSI Device is not conected. */
if (hs
->sc_lock
!= NULL
) {
*(hs
->sc_lock
) = SC_DEV_NOT_FOUND
;
(dq
->dq_driver
->d_intr
)(dq
->dq_unit
, SC_DEV_NOT_FOUND
);
hs
->sc_flags
|= SC_SEL_TIMEOUT
;
while ((hd
->scsi_psns
& PSNS_REQ
) == 0) {
/* hd->scsi_scmd = SCMD_SET_ATN; */
hd
->scsi_scmd
= SCMD_RST
;
DELAY(40); /* wait 25 micro sec */
if (hs
->sc_lock
!= NULL
) {
*(hs
->sc_lock
) = SC_IO_TIMEOUT
;
(dq
->dq_driver
->d_intr
)(dq
->dq_unit
, SC_IO_TIMEOUT
);
hs
->sc_phase
= hd
->scsi_psns
& PHASE
;
dbgprintf("scintr: %s\n", phase_name(hs
->sc_phase
));
if ((hs
->sc_phase
== DATA_OUT_PHASE
) || (hs
->sc_phase
== DATA_IN_PHASE
)) {
len
= ( hs
->sc_lock
!= NULL
? hs
->sc_len
: dq
->dq_bp
->b_bcount
);
buf
= ( hs
->sc_lock
!= NULL
? hs
->sc_buf
: (u_char
*) dq
->dq_bp
->b_un
.b_addr
);
} else if (hs
->sc_phase
== CMD_PHASE
) {
len
= ( hs
->sc_lock
!= NULL
? hs
->sc_cdblen
: dq
->dq_cdb
->len
);
buf
= ( hs
->sc_lock
!= NULL
? hs
->sc_cdb
: dq
->dq_cdb
->cdb
);
} else if (hs
->sc_phase
== STATUS_PHASE
) {
if (hs
->sc_phase
== MESG_OUT_PHASE
) {
hs
->sc_msg
[0] = MSG_IDENTIFY_DR
;
hs
->sc_msg
[0] = MSG_IDENTIFY
;
if ((hs
->sc_lock
== NULL
) && (hs
->sc_phase
== DATA_IN_PHASE
)) {
txfer_start(hd
, len
, hs
->sc_phase
);
ixfer_start(hd
, len
, hs
->sc_phase
);
if (hs
->sc_phase
& PHASE_IO
) {
if ((wait
= ixfer_in(hd
, len
, buf
)) == -1) {
dq
->dq_imin
= min(wait
, dq
->dq_imin
);
dq
->dq_imax
= max(wait
, dq
->dq_imax
);
if ((wait
= ixfer_out(hd
, len
, buf
)) == -1) {
dq
->dq_omin
= min(wait
, dq
->dq_omin
);
dq
->dq_omax
= max(wait
, dq
->dq_omax
);
printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
if (hs
->sc_lock
!= NULL
) {
*(hs
->sc_lock
) = SC_IO_TIMEOUT
;
(dq
->dq_driver
->d_intr
)(dq
->dq_unit
, SC_IO_TIMEOUT
);
if (hs
->sc_lock
!= NULL
) {
*(hs
->sc_lock
) = SC_IO_FAILED
;
(dq
->dq_driver
->d_intr
)(dq
->dq_unit
, SC_IO_FAILED
);
register struct sc_softc
*hs
;
volatile register struct scsidevice
*hd
;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
hd
->scsi_ints
= hd
->scsi_ints
;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset INTS reg.\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
if (hd
->scsi_psns
== 0 || (hd
->scsi_ssts
& SSTS_INITIATOR
) == 0)
/* no longer connected to scsi target */
/* get the number of bytes remaining in current xfer + fudge */
len
= (hd
->scsi_tch
<< 16) | (hd
->scsi_tcm
<< 8) | hd
->scsi_tcl
;
printf("scabort: Current xfer count = %d\n", len
);
/* for that many bus cycles, try to send an abort msg */
for (len
+= 1024; (hd
->scsi_ssts
& SSTS_INITIATOR
) && --len
>= 0; ) {
hd->scsi_scmd = SCMD_SET_ATN;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ATN\n",
hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
while ((hd
->scsi_psns
& PSNS_REQ
) == 0) {
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
if (! (hd
->scsi_ssts
& SSTS_INITIATOR
))
if ((hd->scsi_psns & PHASE) == MESG_OUT_PHASE) {
hd->scsi_scmd = SCMD_RST_ATN;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ATN\n",
hd->scsi_ints, hd->scsi_ssts, hd->scsi_pctl, hd->scsi_psns);
hd
->scsi_pctl
= hs
->sc_phase
= hd
->scsi_psns
& PHASE
;
printf("scabort: Phase = %s\n", phase_name(hs
->sc_phase
));
if (hd
->scsi_psns
& PHASE_IO
) {
/* one of the input phases - read & discard a byte */
hd
->scsi_scmd
= SCMD_SET_ACK
;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
while (hd
->scsi_psns
& PSNS_REQ
) {
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
printf("scabort: TEMP = 0x%s\n", hexstr(junk
, 2));
/* one of the output phases - send an abort msg */
hd
->scsi_temp
= MSG_ABORT
;
hd
->scsi_scmd
= SCMD_SET_ACK
;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Set ACK\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
while (hd
->scsi_psns
& PSNS_REQ
) {
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Wait for REQ\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
hd
->scsi_scmd
= SCMD_RST_ACK
;
printf("scabort: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Reset ACK\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
* Either the abort was successful & the bus is disconnected or
* the device didn't listen. If the latter, announce the problem.
* Either way, reset the card & the SPC.
printf("sc%d: abort failed. phase=0x%x, ssts=0x%x\n",
hs
->sc_hc
->hp_unit
, hd
->scsi_psns
, hd
->scsi_ssts
);
while (hd
->scsi_ints
== 0)
hd
->scsi_ints
= hd
->scsi_ints
;
printf("scintr: INTS 0x%x, SSTS 0x%x, PCTL 0x%x, PSNS 0x%x Current Status\n",
hd
->scsi_ints
, hd
->scsi_ssts
, hd
->scsi_pctl
, hd
->scsi_psns
);
printf("scabort: SCSI abort operation is done\n");
* SPC device queue handling
register struct scsi_queue
*dq
;
register struct sc_softc
*hs
= &sc_softc
[dq
->dq_ctlr
];
register struct scsi_queue
*hq
= &hs
->sc_sq
;
printf("screq: slave = %d, command = %s\n",
scsi_command(hq
->dq_forw
->dq_cdb
->cdb
[0]));
register struct scsi_queue
*dq
;
register struct sc_softc
*hs
= &sc_softc
[dq
->dq_ctlr
];
register struct scsi_queue
*hq
= &hs
->sc_sq
;
register struct scsi_queue
*wq
= &hs
->sc_wq
;
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
register struct scsi_queue
*wq
= &hs
->sc_wq
;
register struct scsi_queue
*hq
= &hs
->sc_sq
;
register struct scsi_queue
*dq
;
for (dq
= wq
->dq_forw
; dq
!= wq
; dq
= dq
->dq_forw
) {
if (dq
->dq_slave
== slave
)
register struct scsi_queue
*dq
;
register struct sc_softc
*hs
= &sc_softc
[dq
->dq_ctlr
];
register struct scsi_queue
*hq
= &hs
->sc_sq
;
int status
= hs
->sc_stat
;
hs
->sc_phase
= BUS_FREE_PHASE
;
if ((dq
= hq
->dq_forw
) != hq
) {
printf("scfree: slave = %d, command = %s\n",
scsi_command(dq
->dq_cdb
->cdb
[0]));
(dq
->dq_driver
->d_start
)(dq
->dq_unit
);
printf("scsi_result: stat = %s\n", scsi_status(stat
));
scsi_lock
[unit
] = SC_IO_COMPLETE
;
struct driver scsi_driver
= {
(int (*)()) 0, "scsi", (int (*)()) 0, (int (*)()) 0, scsi_result
, (int (*)()) 0
struct scsi_queue scsi_entry
[NSC
];
scsi_immed_command(ctlr
, slave
, lun
, cdb
, buf
, len
)
struct scsi_fmt_cdb
*cdb
;
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
volatile register struct scsidevice
*hd
=
(struct scsidevice
*) hs
->sc_hc
->hp_addr
;
register struct scsi_queue
*dq
= &scsi_entry
[ctlr
];
int s
, status
, wait
= 30;
printf("scsi_immed_command( %d, %d, %d, cdb(%d,%s), buf, %d): Start\n",
ctlr
, slave
, lun
, cdb
->len
, scsi_command(cdb
->cdb
[0]), len
);
dq
->dq_driver
= &scsi_driver
;
scsi_lock
[ctlr
] = SC_IN_PROGRESS
;
while (scsi_lock
[ctlr
] == SC_IN_PROGRESS
) {
status
= scsi_lock
[ctlr
];
bcopy(bp
->b_un
.b_addr
, buf
, len
);
printf("scsi_immed_command: Status -- 0x%x\n", status
);
sc_test_unit_rdy(ctlr
, slave
, lun
)
static struct scsi_fmt_cdb cdb
= { 6, CMD_TEST_UNIT_READY
};
while ((stat
= scsi_immed_command(ctlr
, slave
, lun
,
&cdb
, (u_char
*) 0, 0)) == SC_BUSY
) {
sc_request_sense(ctlr
, slave
, lun
, buf
, len
)
register struct sc_softc
*hs
= &sc_softc
[ctlr
];
volatile register struct scsidevice
*hd
=
(struct scsidevice
*) hs
->sc_hc
->hp_addr
;
static struct scsi_fmt_cdb req_cmd
= { 6, CMD_REQUEST_SENSE
};
printf("sc_request_sense( %d, %d, %d, buf, %d) -- Start\n",
if (hd
->scsi_ssts
& (SSTS_INITIATOR
|SSTS_TARGET
|SSTS_BUSY
))
hs
->sc_phase
= ARB_SEL_PHASE
;
hs
->sc_cdb
= req_cmd
.cdb
;
hs
->sc_cdblen
= req_cmd
.len
;
issue_select(hd
, slave
, 0);
while ((lock
== SC_IN_PROGRESS
) || (lock
== SC_DISCONNECTED
))
hs
->sc_phase
= BUS_FREE_PHASE
;
if (lock
== SC_IO_COMPLETE
) {
printf("sc_request_sense: Status -- 0x%x\n", status
);