summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>1998-11-23 01:33:47 +0000
committergibbs <gibbs@FreeBSD.org>1998-11-23 01:33:47 +0000
commitad7080d581f4d14be46b9ce97e1d89ab54565fd9 (patch)
tree7bab1dcb022f080626a0b5a06296e839a6d4c72a /sys/dev
parent0b3bd2def8c0b1aad4cf5df500e9eb3c3947b7c8 (diff)
downloadFreeBSD-src-ad7080d581f4d14be46b9ce97e1d89ab54565fd9.zip
FreeBSD-src-ad7080d581f4d14be46b9ce97e1d89ab54565fd9.tar.gz
Change the delivery mechanism for incoming target commands. We now
use a 256 entry ring buffer of descriptersfor this purpose. This allows the use of a simple 8bit counter in the sequencer code for tracking start location. Entries in the ring buffer now contain a "cmd_valid" byte at their tail. As an entry is serviced, this byte is cleared by the kernel and set by the sequencer during its dma of a new entry. Since this byte is the last portion of the command touched during a dma, the kernel can use this byte to ensure the command it processes is completely valid. The new command format requires a fixed sized DMA from the controller to deliver which allowed for additional simplification of the sequencer code. The hack that required 1 SCB slot to be stolen for incoming command delivery notification is also gone.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c60
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h29
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg26
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq67
4 files changed, 99 insertions, 83 deletions
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 48014ae..f0139b9 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -36,7 +36,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.c,v 1.8 1998/10/15 18:21:47 gibbs Exp $
+ * $Id: aic7xxx.c,v 1.9 1998/10/15 23:49:27 gibbs Exp $
*/
/*
* A few notes on features of the driver.
@@ -207,7 +207,8 @@ static void ahc_compile_devinfo(struct ahc_devinfo *devinfo,
u_int target, char channel);
static u_int ahc_abort_wscb(struct ahc_softc *ahc, u_int scbpos, u_int prev);
static void ahc_done(struct ahc_softc *ahc, struct scb *scbp);
-static void ahc_handle_target_cmd(struct ahc_softc *ahc);
+static void ahc_handle_target_cmd(struct ahc_softc *ahc,
+ struct target_cmd *cmd);
static void ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat);
static void ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat);
static void ahc_handle_reqinit(struct ahc_softc *ahc,
@@ -989,12 +990,6 @@ ahc_intr(void *arg)
scb_index = ahc->qoutfifo[ahc->qoutfifonext];
ahc->qoutfifo[ahc->qoutfifonext++] = SCB_LIST_NULL;
- if (scb_index == TARGET_CMD_CMPLT
- && (ahc->flags & AHC_TARGETMODE) != 0) {
- ahc_handle_target_cmd(ahc);
- continue;
- }
-
scb = ahc->scb_data->scbarray[scb_index];
if (!scb || !(scb->flags & SCB_ACTIVE)) {
printf("%s: WARNING no command for scb %d "
@@ -1012,6 +1007,16 @@ ahc_intr(void *arg)
ahc_calc_residual(scb);
ahc_done(ahc, scb);
}
+
+ if ((ahc->flags & AHC_TARGETMODE) != 0) {
+ while (ahc->targetcmds[ahc->tqinfifonext].cmd_valid) {
+ struct target_cmd *cmd;
+
+ cmd = &ahc->targetcmds[ahc->tqinfifonext++];
+ ahc_handle_target_cmd(ahc, cmd);
+ cmd->cmd_valid = 0;
+ }
+ }
}
if (intstat & BRKADRINT) {
/*
@@ -1041,23 +1046,17 @@ ahc_intr(void *arg)
}
static void
-ahc_handle_target_cmd(struct ahc_softc *ahc)
+ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
{
struct tmode_tstate *tstate;
struct tmode_lstate *lstate;
struct ccb_accept_tio *atio;
- struct target_cmd *cmd;
u_int8_t *byte;
int initiator;
int target;
int lun;
- cmd = &ahc->targetcmds[ahc->next_targetcmd];
- ahc->next_targetcmd++;
- if (ahc->next_targetcmd >= ahc->num_targetcmds)
- ahc->next_targetcmd = 0;
-
- initiator = cmd->icl >> 4;
+ initiator = cmd->initiator_channel >> 4;
target = cmd->targ_id;
lun = (cmd->identify & MSG_IDENTIFY_LUNMASK);
@@ -2535,18 +2534,10 @@ ahc_init(struct ahc_softc *ahc)
if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) {
ahc->flags |= AHC_PAGESCBS;
ahc->scb_data->maxscbs = AHC_SCB_MAX;
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- /* Steal one slot for TMODE commands */
- ahc->scb_data->maxscbs--;
- }
printf("%d/%d SCBs\n", ahc->scb_data->maxhscbs,
ahc->scb_data->maxscbs);
} else {
ahc->scb_data->maxscbs = ahc->scb_data->maxhscbs;
- if ((ahc->flags & AHC_TARGETMODE) != 0) {
- /* Steal one slot for TMODE commands */
- ahc->scb_data->maxscbs--;
- }
ahc->flags &= ~AHC_PAGESCBS;
printf("%d SCBs\n", ahc->scb_data->maxhscbs);
}
@@ -2761,9 +2752,10 @@ ahc_init(struct ahc_softc *ahc)
if ((ahc->flags & AHC_TARGETMODE) != 0) {
size_t array_size;
- ahc->num_targetcmds = 32;
- array_size = ahc->num_targetcmds * sizeof(struct target_cmd);
- ahc->targetcmds = malloc(array_size, M_DEVBUF, M_NOWAIT);
+ array_size = AHC_TMODE_CMDS * sizeof(struct target_cmd);
+ ahc->targetcmds = contigmalloc(array_size, M_DEVBUF,
+ M_NOWAIT, 0ul, 0xffffffff,
+ PAGE_SIZE, 0x10000);
if (ahc->targetcmds == NULL) {
printf("%s: unable to allocate targetcmd array. "
@@ -2771,8 +2763,11 @@ ahc_init(struct ahc_softc *ahc)
return (-1);
}
- bzero(ahc->targetcmds, array_size);
- ahc_outb(ahc, TMODE_CMDADDR_NEXT, 0);
+ /* All target command blocks start out invalid. */
+ for (i = 0; i < AHC_TMODE_CMDS; i++)
+ ahc->targetcmds[i].cmd_valid = 0;
+ ahc_outb(ahc, KERNEL_TQINPOS, 0);
+ ahc_outb(ahc, TQINPOS, 0);
}
/*
@@ -3811,7 +3806,10 @@ ahc_loadseq(struct ahc_softc *ahc)
u_int8_t download_consts[4];
/* Setup downloadable constant table */
+#if 0
+ /* No downloaded constants are currently defined. */
download_consts[TMODE_NUMCMDS] = ahc->num_targetcmds;
+#endif
cur_patch = patches;
downloaded = 0;
@@ -4812,9 +4810,9 @@ ahc_dump_targcmd(struct target_cmd *cmd)
u_int8_t *last_byte;
int i;
- byte = &cmd->icl;
+ byte = &cmd->initiator_channel;
/* Debugging info for received commands */
- last_byte = &cmd[1].icl;
+ last_byte = &cmd[1].initiator_channel;
i = 0;
while (byte < last_byte) {
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index 06f7d4a..560cb3f 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -34,7 +34,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.h,v 1.40 1997/02/25 03:05:35 gibbs Exp $
+ * $Id: aic7xxx.h,v 1.1 1998/09/15 07:24:16 gibbs Exp $
*/
#ifndef _AIC7XXX_H_
@@ -68,6 +68,12 @@
* aic7850 has only 3.
*/
+#define AHC_TMODE_CMDS 256 /*
+ * Ring Buffer of incoming target commands.
+ * We allocate 256 to simplify the logic
+ * in the sequencer by using the natural
+ * wrap point of an 8bit counter.
+ */
#if defined(__FreeBSD__)
extern u_long ahc_unit;
@@ -247,13 +253,17 @@ struct scb_data {
* Connection desciptor for select-in requests in target mode.
* The first byte is the connecting target, followed by identify
* message and optional tag information, terminated by 0xFF. The
- * remainder is the command to execute.
+ * remainder is the command to execute. The cmd_valid byte is on
+ * an 8 byte boundary to simplify setting it on aic7880 hardware
+ * which only has limited direct access to the DMA FIFO.
*/
struct target_cmd {
- u_int8_t icl; /* Really only holds Initiator ID */
- u_int8_t targ_id; /* Target ID we were selected at */
- u_int8_t identify; /* Identify message */
- u_int8_t bytes[29];
+ u_int8_t initiator_channel;
+ u_int8_t targ_id; /* Target ID we were selected at */
+ u_int8_t identify; /* Identify message */
+ u_int8_t bytes[21];
+ u_int8_t cmd_valid;
+ u_int8_t pad[7];
};
/*
@@ -462,10 +472,11 @@ struct ahc_softc {
int unsolicited_ints;
pcici_t pci_config_id;
- /* Hmmm. */
+ /*
+ * Target incoming command FIFO.
+ */
struct target_cmd *targetcmds;
- int next_targetcmd;
- int num_targetcmds;
+ u_int8_t tqinfifonext;
/*
* Incoming and outgoing message handling.
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index fff2b6f..a6ab963 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.reg,v 1.4 1997/06/27 19:38:39 gibbs Exp $
+ * $Id: aic7xxx.reg,v 1.7 1998/09/15 07:24:16 gibbs Exp $
*/
/*
@@ -763,6 +763,16 @@ register DFSTATUS {
bit FIFOEMP 0x01
}
+register DFWADDR {
+ address 0x95
+ access_mode RW
+}
+
+register DFRADDR {
+ address 0x97
+ access_mode RW
+}
+
register DFDAT {
address 0x099
access_mode RW
@@ -1255,10 +1265,14 @@ scratch_ram {
size 1
}
/*
- * Offset into the command descriptor array for the next
- * available desciptor to use.
+ * Kernel and sequencer offsets into the queue of
+ * incoming target mode command descriptors. The
+ * queue is full when the ((KERNEL_TQINPOS - TQINPOS) == 1)
*/
- TMODE_CMDADDR_NEXT {
+ KERNEL_TQINPOS {
+ size 1
+ }
+ TQINPOS {
size 1
}
ARG_1 {
@@ -1360,5 +1374,7 @@ const CMD_GROUP5_BYTE_DELTA 11
/*
* Number of command descriptors in the command descriptor array.
- */
+ * No longer used, but left here as an example for how downloaded
+ * constantants can be defined.
const TMODE_NUMCMDS download
+ */
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index c1ab64d..2a4e92e 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -32,7 +32,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: aic7xxx.seq,v 1.78 1998/09/15 07:24:16 gibbs Exp $
+ * $Id: aic7xxx.seq,v 1.79 1998/09/21 16:46:13 gibbs Exp $
*/
#include <dev/aic7xxx/aic7xxx.reg>
@@ -234,11 +234,12 @@ select_in:
/*
* Setup the DMA for sending the identify and
- * command information. We keep a count of the
- * number of bytes to send to the host in ARG_2.
+ * command information.
*/
or SEQ_FLAGS, CMDPHASE_PENDING;
- mov A, TMODE_CMDADDR_NEXT;
+
+ /* XXX If ring buffer is full, return busy or queue full */
+ mov A, TQINPOS;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mvi DINDEX, CCHADDR;
mvi TMODE_CMDADDR call set_32byte_addr;
@@ -289,6 +290,7 @@ select_in:
* Our first message must be one of IDENTIFY, ABORT, or
* BUS_DEVICE_RESET.
*/
+ /* XXX May need to be more lax here for older initiators... */
test DINDEX, MSG_IDENTIFYFLAG jz more_first_messages;
/* Store for host */
if ((ahc->features & AHC_CMD_CHAN) != 0) {
@@ -296,7 +298,6 @@ select_in:
} else {
mov DFDAT, DINDEX;
}
- mvi ARG_2, 3;
/* Remember for disconnection decision */
test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
@@ -337,7 +338,6 @@ select_in:
} else {
mov DFDAT, DINDEX;
}
- add ARG_2, 2;
jmp ident_messages_done;
more_first_messages:
@@ -483,17 +483,6 @@ target_busfree:
jmp poll_for_work;
target_cmdphase:
- /*
- * Add one for the terminating byte
- * and one for the command code.
- */
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- add CCHCNT, 2, ARG_2;
- } else {
- add HCNT[0], 2, ARG_2;
- clr HCNT[1];
- clr HCNT[2];
- }
mvi SCSISIGO, P_COMMAND|BSYO;
call targ_inb;
mov A, DINDEX;
@@ -506,20 +495,16 @@ target_cmdphase:
/*
* Determine the number of bytes to read
- * based on the command group code using an adding
- * jump table. Count is one less than the total
- * since we've already fetched the first byte.
+ * based on the command group code via table lookup.
+ * We reuse the first 8 bytes of the TARG_SCSIRATE
+ * BIOS array for this table. Count is one less than
+ * the total for the command since we've already fetched
+ * the first byte.
*/
shr A, CMD_GROUP_CODE_SHIFT;
add SINDEX, TARG_SCSIRATE, A;
mov A, SINDIR;
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- add CCHCNT, A;
- } else {
- add HCNT[0], A;
- }
-
test A, 0xFF jz command_phase_done;
command_loop:
or SXFRCTL0, SPIOEN;
@@ -566,17 +551,28 @@ complete_target_cmd:
test SEQ_FLAGS, TARG_CMD_PENDING jnz . + 2;
mov SCB_TAG jmp complete_post;
if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ /* Set the valid byte */
+ mvi CCSCBADDR, 24;
+ mov CCSCBRAM, ALLONES;
+ mvi CCHCNT, 28;
or CCSCBCTL, CCSCBEN|CCSCBRESET;
test CCSCBCTL, CCSCBDONE jz .;
clr CCSCBCTL;
} else {
+ /* Set the valid byte */
+ or DFCNTRL, FIFORESET;
+ mvi DFWADDR, 3; /* Third 64bit word or byte 24 */
+ mov DFDAT, ALLONES;
+ mvi HCNT[0], 28;
+ clr HCNT[1];
+ clr HCNT[2];
or DFCNTRL, HDMAEN|FIFOFLUSH;
call dma_finish;
}
- inc TMODE_CMDADDR_NEXT;
- cmp TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2;
- clr TMODE_CMDADDR_NEXT;
- mvi TARGET_CMD_CMPLT jmp complete_post;
+ inc TQINPOS;
+ test SEQ_FLAGS, NO_DISCONNECT jz . + 2;
+ mvi INTSTAT,TARGET_SYNC_CMD|CMDCMPLT ret;
+ mvi INTSTAT,CMDCMPLT ret;
}
initiator_select:
mvi SPIOEN call initialize_channel;
@@ -960,11 +956,7 @@ p_mesgout:
mov SINDEX, MSG_OUT;
cmp SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
p_mesgout_identify:
- if ((ahc->features & AHC_WIDE) != 0) {
- and SINDEX,0xf,SCB_TCL; /* lun */
- } else {
- and SINDEX,0x7,SCB_TCL; /* lun */
- }
+ and SINDEX,LID,SCB_TCL; /* lun */
and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */
or SINDEX,A; /* or in disconnect privledge */
or SINDEX,MSG_IDENTIFYFLAG;
@@ -1122,9 +1114,8 @@ complete_post:
inc QOUTPOS;
}
if ((ahc->flags & AHC_TARGETMODE) != 0) {
- test SEQ_FLAGS, NO_DISCONNECT jz . + 3;
- mvi INTSTAT,TARGET_SYNC_CMD|CMDCMPLT;
- ret;
+ test SEQ_FLAGS, NO_DISCONNECT jz . + 2;
+ mvi INTSTAT,TARGET_SYNC_CMD|CMDCMPLT ret;
}
mvi INTSTAT,CMDCMPLT ret;
OpenPOWER on IntegriCloud