From ad7080d581f4d14be46b9ce97e1d89ab54565fd9 Mon Sep 17 00:00:00 2001 From: gibbs Date: Mon, 23 Nov 1998 01:33:47 +0000 Subject: 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. --- sys/dev/aic7xxx/aic7xxx.c | 60 ++++++++++++++++++++-------------------- sys/dev/aic7xxx/aic7xxx.h | 29 ++++++++++++++------ sys/dev/aic7xxx/aic7xxx.reg | 26 ++++++++++++++---- sys/dev/aic7xxx/aic7xxx.seq | 67 ++++++++++++++++++++------------------------- 4 files changed, 99 insertions(+), 83 deletions(-) (limited to 'sys/dev') 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 @@ -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; -- cgit v1.1