Major overhaul of the aic7xxx driver:
- Report valid residual byte counts. We actually pause the sequencer when the residual is non-zero. I thought about using DMA to do this, bus sequencer program space is tight. - Fix embarassing off by one error in the computation of a 2's compliment variable. This was most likely the cause of the many problems reported with the tagged queuing code. - Handle "MAX_SYNC" as a special case (ie we are the ones starting the sync negotiation sequence). This was done so that the target scratch area can be initialed to 0 offset (asyncronous transfers) safely. The initialization to 0 (was 15) is necessary since in some cases a Wide negotiation could run into problems if SCSIRATE was set wrong and we went into data(in/out). - Trim the DMA routines a little by using some procedures. Net effect is more functionality with 3 less instructions after this update. - Toggle the WIDEODD bit of the DFCNTRL whenever this is not the last SG block. It has no effect in the 8bit bus configuration, but in the Wide configuration ensures that the overlap byte is held in the SCSI block if the transfer is odd so it will end up in the next SG (the correct behavior).
This commit is contained in:
parent
c5e0851d47
commit
5743c01c3f
@ -22,7 +22,7 @@
|
||||
# optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org)
|
||||
#
|
||||
|
||||
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.9 1995/03/07 09:00:44 gibbs Exp $"
|
||||
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.10 1995/03/17 23:54:17 gibbs Exp $"
|
||||
|
||||
SCBMASK = 0x1f
|
||||
|
||||
@ -56,6 +56,9 @@ SINDIR = 0x6c
|
||||
DINDIR = 0x6d
|
||||
FUNCTION1 = 0x6e
|
||||
HADDR = 0x88
|
||||
HADDR+1 = 0x89
|
||||
HADDR+2 = 0x8a
|
||||
HADDR+3 = 0x8b
|
||||
HCNT = 0x8c
|
||||
HCNT+0 = 0x8c
|
||||
HCNT+1 = 0x8d
|
||||
@ -113,8 +116,12 @@ SCBARRAY+23 = 0xb7
|
||||
SCBARRAY+24 = 0xb8
|
||||
SCBARRAY+25 = 0xb9
|
||||
SCBARRAY+26 = 0xba
|
||||
SCBARRAY+27 = 0xbb
|
||||
SCBARRAY+28 = 0xbc
|
||||
SCBARRAY+29 = 0xbd
|
||||
|
||||
BAD_PHASE = 0x01 # unknown scsi bus phase
|
||||
CMDCMPLT = 0x02
|
||||
SEND_REJECT = 0x11 # sending a message reject
|
||||
NO_IDENT = 0x21 # no IDENTIFY after reconnect
|
||||
NO_MATCH = 0x31 # no cmd match for reconnect
|
||||
@ -122,6 +129,7 @@ MSG_SDTR = 0x41 # SDTR message recieved
|
||||
MSG_WDTR = 0x51 # WDTR message recieved
|
||||
MSG_REJECT = 0x61 # Reject message recieved
|
||||
BAD_STATUS = 0x71 # Bad status from target
|
||||
RESIDUAL = 0x81 # Residual byte count != 0
|
||||
|
||||
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
|
||||
# device information, 32-33 and 5a-5f as well. As it turns out, the
|
||||
@ -164,7 +172,7 @@ MSG_START+2 = 0x37
|
||||
MSG_START+3 = 0x38
|
||||
MSG_START+4 = 0x39
|
||||
MSG_START+5 = 0x3a
|
||||
-MSG_START+0 = 0xcb # 2's complement of MSG_START+0
|
||||
-MSG_START+0 = 0xcc # 2's complement of MSG_START+0
|
||||
|
||||
ARG_1 = 0x4a # sdtr conversion args & return
|
||||
BUS_16_BIT = 0x01
|
||||
@ -189,6 +197,7 @@ SCBCOUNT = 0x52 # the actual number of SCBs
|
||||
FLAGS = 0x53 # Device configuration flags
|
||||
TWIN_BUS = 0x01
|
||||
WIDE_BUS = 0x02
|
||||
MAX_SYNC = 0x08
|
||||
SENSE = 0x10
|
||||
ACTIVE_MSG = 0x20
|
||||
IDENTIFY_SEEN = 0x40
|
||||
@ -236,34 +245,16 @@ test SCBARRAY+0,NEEDDMA jz test_busy
|
||||
# Wait for DMA from host memory to data FIFO to complete, then disable
|
||||
# DMA and wait for it to acknowledge that it's off.
|
||||
#
|
||||
scb_load1:
|
||||
test DFSTATUS,0x8 jz scb_load1 # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
scb_load2:
|
||||
test DFCNTRL,0x8 jnz scb_load2 # HDMAENACK
|
||||
call dma_finish
|
||||
|
||||
# Copy the SCB from the FIFO to the SCBARRAY
|
||||
|
||||
mov SCBARRAY+0, DFDAT
|
||||
mov SCBARRAY+1, DFDAT
|
||||
mov SCBARRAY+2, DFDAT
|
||||
mov SCBARRAY+3, DFDAT
|
||||
mov SCBARRAY+4, DFDAT
|
||||
mov SCBARRAY+5, DFDAT
|
||||
mov SCBARRAY+6, DFDAT
|
||||
mov SCBARRAY+7, DFDAT
|
||||
mov SCBARRAY+8, DFDAT
|
||||
mov SCBARRAY+9, DFDAT
|
||||
mov SCBARRAY+10, DFDAT
|
||||
mov SCBARRAY+11, DFDAT
|
||||
mov SCBARRAY+12, DFDAT
|
||||
mov SCBARRAY+13, DFDAT
|
||||
mov SCBARRAY+14, DFDAT
|
||||
mov SCBARRAY+15, DFDAT
|
||||
mov SCBARRAY+16, DFDAT
|
||||
mov SCBARRAY+17, DFDAT
|
||||
mov SCBARRAY+18, DFDAT
|
||||
mvi DINDEX, SCBARRAY+0
|
||||
call bcopy_3_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
|
||||
# See if there is not already an active SCB for this target. This code
|
||||
# locks out on a per target basis instead of target/lun. Although this
|
||||
@ -338,7 +329,6 @@ mk_tag:
|
||||
mov DINDIR,SCBPTR
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX # update message length
|
||||
jmp !message # Can't do DTR when taged
|
||||
|
||||
mk_tag_done:
|
||||
|
||||
@ -441,9 +431,17 @@ p_dataout:
|
||||
mvi DINDEX,STCNT
|
||||
mvi SCBARRAY+23 call bcopy_3
|
||||
|
||||
# If we are the last SG block, don't set wideodd.
|
||||
test SCBARRAY+18,0xff jnz p_dataout_wideodd
|
||||
mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
|
||||
# DIRECTION|FIFORESET
|
||||
jmp p_dataout_rest
|
||||
|
||||
p_dataout_wideodd:
|
||||
mvi 0xbd call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
|
||||
# DIRECTION|FIFORESET
|
||||
|
||||
p_dataout_rest:
|
||||
# After a DMA finishes, save the final transfer pointer and count
|
||||
# back into the SCB, in case a device disconnects in the middle of
|
||||
# a transfer. Use SHADDR and STCNT instead of HADDR and HCNT, since
|
||||
@ -475,8 +473,15 @@ p_datain:
|
||||
mvi DINDEX,STCNT
|
||||
mvi SCBARRAY+23 call bcopy_3
|
||||
|
||||
# If we are the last SG block, don't set wideodd.
|
||||
test SCBARRAY+18,0xff jnz p_datain_wideodd
|
||||
mvi 0x39 call dma # SCSIEN|SDMAEN|HDMAEN|
|
||||
# !DIRECTION|FIFORESET
|
||||
jmp p_datain_rest
|
||||
p_datain_wideodd:
|
||||
mvi 0xb9 call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
|
||||
# !DIRECTION|FIFORESET
|
||||
p_datain_rest:
|
||||
mvi DINDEX,SCBARRAY+23
|
||||
mvi STCNT call bcopy_3
|
||||
|
||||
@ -611,21 +616,25 @@ p_mesgin:
|
||||
# This allows the driver to interpret errors only when they occur
|
||||
# instead of always uploading the scb. If the status is SCSI_CHECK,
|
||||
# the driver will download a new scb requesting sense, to replace
|
||||
# the old one and the sequencer code will imediately jump to start
|
||||
# working on it. If the kernel driver does not wish to request sense,
|
||||
# the sequencer program counter is incremented by 1, preventing another run
|
||||
# on the current SCB and the command is allowed to complete. We don't
|
||||
# the old one and set the SENSE sequencer flag. If the sense flag is
|
||||
# set, the sequencer imediately jumps to start working on the sense
|
||||
# command. If the kernel driver does not wish to request sense, it need
|
||||
# do nothing, and the command is allowed to complete. We don't
|
||||
# bother to post to the QOUTFIFO in the error case since it would require
|
||||
# extra work in the kernel driver to ensure that the entry was removed
|
||||
# before the command complete code tried processing it.
|
||||
|
||||
test SCBARRAY+15,0xff jnz resid
|
||||
test SCBARRAY+16,0xff jnz resid
|
||||
test SCBARRAY+17,0xff jnz resid
|
||||
|
||||
check_status:
|
||||
test SCBARRAY+14,0xff jz status_ok # 0 Status?
|
||||
mvi INTSTAT,BAD_STATUS # let driver know
|
||||
test FLAGS,SENSE jz status_ok
|
||||
jmp p_mesgin_done
|
||||
|
||||
status_ok:
|
||||
|
||||
# First, mark this target as free.
|
||||
test SCBARRAY+0,0x20 jnz complete # Tagged command
|
||||
and FUNCTION1,0x70,SCBARRAY+1
|
||||
@ -639,9 +648,20 @@ clear_a:
|
||||
|
||||
complete:
|
||||
mov QOUTFIFO,SCBPTR
|
||||
mvi INTSTAT,0x02 # CMDCMPLT
|
||||
mvi INTSTAT,CMDCMPLT
|
||||
jmp p_mesgin_done
|
||||
|
||||
# If we have a residual count, interrupt and tell the host. Other
|
||||
# alternatives are to pause the sequencer on all command completes (yuck),
|
||||
# dma the resid directly to the host (slick, but a ton of instructions), or
|
||||
# have the sequencer pause itself when it encounters a non-zero resid
|
||||
# (unecessary pause just to flag the command -- yuck, but takes few instructions
|
||||
# and since it shouldn't happen that offten is good enough for our purposes).
|
||||
|
||||
resid:
|
||||
mvi INTSTAT,RESIDUAL
|
||||
jmp check_status
|
||||
|
||||
# Is it an extended message? We only support the synchronous and wide data
|
||||
# transfer request messages, which will probably be in response to
|
||||
# WDTR or SDTR message outs from us. If it's not SDTR or WDTR, reject it -
|
||||
@ -836,6 +856,16 @@ bcopy_4:
|
||||
mov DINDIR,SINDIR
|
||||
mov DINDIR,SINDIR ret
|
||||
|
||||
bcopy_3_dfdat:
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT ret
|
||||
|
||||
bcopy_4_dfdat:
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT ret
|
||||
|
||||
# Locking the driver out, build a one-byte message passed in SINDEX
|
||||
# if there is no active message already. SINDEX is returned intact.
|
||||
@ -966,6 +996,14 @@ dma6:
|
||||
|
||||
ret
|
||||
|
||||
dma_finish:
|
||||
test DFSTATUS,0x8 jz dma_finish # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
dma_finish2:
|
||||
test DFCNTRL,0x8 jnz dma_finish2 # HDMAENACK
|
||||
ret
|
||||
|
||||
# Common SCSI initialization for selection and reselection. Expects
|
||||
# the target SCSI ID to be in the upper four bits of SINDEX, and A's
|
||||
# contents are stomped on return.
|
||||
@ -1003,13 +1041,10 @@ initialize:
|
||||
# message.
|
||||
#
|
||||
assert:
|
||||
test FLAGS,RESELECTED jz assert1 # reselected?
|
||||
test FLAGS,IDENTIFY_SEEN jnz assert1 # seen IDENTIFY?
|
||||
test FLAGS,RESELECTED jz return # reselected?
|
||||
test FLAGS,IDENTIFY_SEEN jnz return # seen IDENTIFY?
|
||||
|
||||
mvi INTSTAT,NO_IDENT # no - cause a kernel panic
|
||||
|
||||
assert1:
|
||||
ret
|
||||
mvi INTSTAT,NO_IDENT ret # no - cause a kernel panic
|
||||
|
||||
# Find out if disconnection is ok from the information the BIOS has left
|
||||
# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
|
||||
@ -1067,11 +1102,8 @@ sg_scb2ram:
|
||||
mvi SCBARRAY+3 call bcopy_4
|
||||
|
||||
mvi SG_NOLOAD,0x80
|
||||
test SCBARRAY+0,0x10 jnz sg_scb2ram1 # don't reload s/g?
|
||||
clr SG_NOLOAD
|
||||
|
||||
sg_scb2ram1:
|
||||
ret
|
||||
test SCBARRAY+0,0x10 jnz return # don't reload s/g?
|
||||
clr SG_NOLOAD ret
|
||||
|
||||
# Copying RAM values back to SCB, for Save Data Pointers message.
|
||||
#
|
||||
@ -1082,11 +1114,8 @@ sg_ram2scb:
|
||||
mvi SG_NEXT call bcopy_4
|
||||
|
||||
and SCBARRAY+0,0xef,SCBARRAY+0
|
||||
test SG_NOLOAD,0x80 jz sg_ram2scb1 # reload s/g?
|
||||
or SCBARRAY+0,SG_LOAD
|
||||
|
||||
sg_ram2scb1:
|
||||
ret
|
||||
test SG_NOLOAD,0x80 jz return # reload s/g?
|
||||
or SCBARRAY+0,SG_LOAD ret
|
||||
|
||||
# Load a struct scatter if needed and set up the data address and
|
||||
# length. If the working value of the SG count is nonzero, then
|
||||
@ -1095,8 +1124,8 @@ sg_ram2scb1:
|
||||
# This, like the above DMA, assumes a little-endian host data storage.
|
||||
#
|
||||
sg_load:
|
||||
test SG_COUNT,0xff jz sg_load3 # SG being used?
|
||||
test SG_NOLOAD,0x80 jnz sg_load3 # don't reload s/g?
|
||||
test SG_COUNT,0xff jz return # SG being used?
|
||||
test SG_NOLOAD,0x80 jnz return # don't reload s/g?
|
||||
|
||||
clr HCNT+2
|
||||
clr HCNT+1
|
||||
@ -1110,12 +1139,8 @@ sg_load:
|
||||
# Wait for DMA from host memory to data FIFO to complete, then disable
|
||||
# DMA and wait for it to acknowledge that it's off.
|
||||
#
|
||||
sg_load1:
|
||||
test DFSTATUS,0x8 jz sg_load1 # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
sg_load2:
|
||||
test DFCNTRL,0x8 jnz sg_load2 # HDMAENACK
|
||||
call dma_finish
|
||||
|
||||
# Copy data from FIFO into SCB data pointer and data count. This assumes
|
||||
# that the struct scatterlist has this structure (this and sizeof(struct
|
||||
@ -1128,7 +1153,7 @@ sg_load2:
|
||||
# }
|
||||
#
|
||||
|
||||
# Not in FreeBSD. the scatter list is only 8 bytes.
|
||||
# Not in FreeBSD. the scatter list entry is only 8 bytes.
|
||||
#
|
||||
# struct ahc_dma_seg {
|
||||
# physaddr addr; /* four bytes, little-endian order */
|
||||
@ -1136,10 +1161,8 @@ sg_load2:
|
||||
# };
|
||||
#
|
||||
|
||||
mov SCBARRAY+19,DFDAT # new data address
|
||||
mov SCBARRAY+20,DFDAT
|
||||
mov SCBARRAY+21,DFDAT
|
||||
mov SCBARRAY+22,DFDAT
|
||||
mvi DINDEX, SCBARRAY+19
|
||||
call bcopy_4_dfdat
|
||||
|
||||
# For Linux, we must throw away four bytes since there is a 32bit gap
|
||||
# in the middle of a struct scatterlist
|
||||
@ -1148,11 +1171,7 @@ sg_load2:
|
||||
# mov NONE,DFDAT
|
||||
# mov NONE,DFDAT
|
||||
|
||||
mov SCBARRAY+23,DFDAT
|
||||
mov SCBARRAY+24,DFDAT
|
||||
mov SCBARRAY+25,DFDAT #Only support 24 bit length.
|
||||
|
||||
sg_load3:
|
||||
call bcopy_3_dfdat #Only support 24 bit length.
|
||||
ret
|
||||
|
||||
# Advance the scatter-gather pointers only IF NEEDED. If SG is enabled,
|
||||
@ -1163,7 +1182,7 @@ sg_load3:
|
||||
# next time.
|
||||
#
|
||||
sg_advance:
|
||||
test SG_COUNT,0xff jz sg_advance2 # s/g enabled?
|
||||
test SG_COUNT,0xff jz return # s/g enabled?
|
||||
|
||||
test STCNT+0,0xff jnz sg_advance1 # SCSI transfer count nonzero?
|
||||
test STCNT+1,0xff jnz sg_advance1
|
||||
@ -1179,9 +1198,7 @@ sg_advance:
|
||||
adc SG_NEXT+3,A,SG_NEXT+3 ret
|
||||
|
||||
sg_advance1:
|
||||
mvi SG_NOLOAD,0x80 # don't reload s/g next time
|
||||
sg_advance2:
|
||||
ret
|
||||
mvi SG_NOLOAD,0x80 ret # don't reload s/g next time
|
||||
|
||||
# Add the array base SYNCNEG to the target offset (the target address
|
||||
# is in SCSIID), and return the result in SINDEX. The accumulator
|
||||
@ -1204,10 +1221,27 @@ ndx_dtr_2:
|
||||
# reject, you wouldn't be able to tell which message was the culpret.
|
||||
#
|
||||
mk_dtr:
|
||||
mov DINDEX,SINDEX # save SINDEX
|
||||
|
||||
test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR
|
||||
test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
|
||||
jmp mk_sdtr
|
||||
or FLAGS, MAX_SYNC # Force an offset of 15
|
||||
|
||||
mk_sdtr:
|
||||
mvi DINDIR,1 # extended message
|
||||
mvi DINDIR,3 # extended message length = 3
|
||||
mvi DINDIR,1 # SDTR code
|
||||
call sdtr_to_rate
|
||||
mov DINDIR,RETURN_1 # REQ/ACK transfer period
|
||||
test FLAGS, MAX_SYNC jnz mk_sdtr_max_sync
|
||||
and DINDIR,0xf,SINDIR # Sync Offset
|
||||
|
||||
mk_sdtr_done:
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
mk_sdtr_max_sync:
|
||||
# We're initiating sync negotiation, so request the max offset we can (15)
|
||||
mvi DINDIR, 0x0f
|
||||
xor FLAGS, MAX_SYNC
|
||||
jmp mk_sdtr_done
|
||||
|
||||
mk_wdtr_16bit:
|
||||
mvi ARG_1,BUS_16_BIT
|
||||
@ -1219,16 +1253,6 @@ mk_wdtr:
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
mk_sdtr:
|
||||
mvi DINDIR,1 # extended message
|
||||
mvi DINDIR,3 # extended message length = 3
|
||||
mvi DINDIR,1 # SDTR code
|
||||
call sdtr_to_rate
|
||||
mov DINDIR,RETURN_1 # REQ/ACK transfer period
|
||||
and DINDIR,0xf,SINDIR # Sync Offset
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
# Set SCSI bus control signal state. This also saves the last-written
|
||||
# value into a location where the higher-level driver can read it - if
|
||||
# it has to send an ABORT or RESET message, then it needs to know this
|
||||
@ -1254,3 +1278,6 @@ sdtr_to_rate_loop:
|
||||
sdtr_to_rate_done:
|
||||
shr RETURN_1,0x2
|
||||
add RETURN_1,0x18 ret
|
||||
|
||||
return:
|
||||
ret
|
||||
|
@ -26,7 +26,7 @@
|
||||
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
|
||||
* are token separators.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.5 1995/01/22 00:46:52 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.6 1995/03/17 23:54:16 gibbs Exp $
|
||||
*/
|
||||
|
||||
/* #define _POSIX_SOURCE 1 */
|
||||
@ -38,7 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY 512 /* 2^9 29-bit words */
|
||||
#define MEMORY 448
|
||||
#define MAXLINE 1024
|
||||
#define MAXTOKEN 32
|
||||
#define ADOTOUT "a.out"
|
||||
@ -480,6 +480,9 @@ int crack(char **a, int n)
|
||||
I_dest = eval_sdi(a, instr[i].dest);
|
||||
I_addr = eval_addr(a, instr[i].addr);
|
||||
|
||||
if( LC >= MEMORY )
|
||||
error("Memory exhausted!\n");
|
||||
|
||||
switch (instr[i].fmt) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
@ -26,7 +26,7 @@
|
||||
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
|
||||
* are token separators.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.5 1995/01/22 00:46:52 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.6 1995/03/17 23:54:16 gibbs Exp $
|
||||
*/
|
||||
|
||||
/* #define _POSIX_SOURCE 1 */
|
||||
@ -38,7 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY 512 /* 2^9 29-bit words */
|
||||
#define MEMORY 448
|
||||
#define MAXLINE 1024
|
||||
#define MAXTOKEN 32
|
||||
#define ADOTOUT "a.out"
|
||||
@ -480,6 +480,9 @@ int crack(char **a, int n)
|
||||
I_dest = eval_sdi(a, instr[i].dest);
|
||||
I_addr = eval_addr(a, instr[i].addr);
|
||||
|
||||
if( LC >= MEMORY )
|
||||
error("Memory exhausted!\n");
|
||||
|
||||
switch (instr[i].fmt) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
@ -26,7 +26,7 @@
|
||||
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
|
||||
* are token separators.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.5 1995/01/22 00:46:52 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.6 1995/03/17 23:54:16 gibbs Exp $
|
||||
*/
|
||||
|
||||
/* #define _POSIX_SOURCE 1 */
|
||||
@ -38,7 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY 512 /* 2^9 29-bit words */
|
||||
#define MEMORY 448
|
||||
#define MAXLINE 1024
|
||||
#define MAXTOKEN 32
|
||||
#define ADOTOUT "a.out"
|
||||
@ -480,6 +480,9 @@ int crack(char **a, int n)
|
||||
I_dest = eval_sdi(a, instr[i].dest);
|
||||
I_addr = eval_addr(a, instr[i].addr);
|
||||
|
||||
if( LC >= MEMORY )
|
||||
error("Memory exhausted!\n");
|
||||
|
||||
switch (instr[i].fmt) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
@ -26,7 +26,7 @@
|
||||
* A <label> is an <undef-sym> ending in a colon. Spaces, tabs, and commas
|
||||
* are token separators.
|
||||
*
|
||||
* $Id: aic7xxx.c,v 1.5 1995/01/22 00:46:52 gibbs Exp $
|
||||
* $Id: aic7xxx.c,v 1.6 1995/03/17 23:54:16 gibbs Exp $
|
||||
*/
|
||||
|
||||
/* #define _POSIX_SOURCE 1 */
|
||||
@ -38,7 +38,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define MEMORY 512 /* 2^9 29-bit words */
|
||||
#define MEMORY 448
|
||||
#define MAXLINE 1024
|
||||
#define MAXTOKEN 32
|
||||
#define ADOTOUT "a.out"
|
||||
@ -480,6 +480,9 @@ int crack(char **a, int n)
|
||||
I_dest = eval_sdi(a, instr[i].dest);
|
||||
I_addr = eval_addr(a, instr[i].addr);
|
||||
|
||||
if( LC >= MEMORY )
|
||||
error("Memory exhausted!\n");
|
||||
|
||||
switch (instr[i].fmt) {
|
||||
case 1:
|
||||
case 2:
|
||||
|
@ -22,7 +22,7 @@
|
||||
# optimizations provided by Justin T. Gibbs (gibbs@FreeBSD.org)
|
||||
#
|
||||
|
||||
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.9 1995/03/07 09:00:44 gibbs Exp $"
|
||||
VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.10 1995/03/17 23:54:17 gibbs Exp $"
|
||||
|
||||
SCBMASK = 0x1f
|
||||
|
||||
@ -56,6 +56,9 @@ SINDIR = 0x6c
|
||||
DINDIR = 0x6d
|
||||
FUNCTION1 = 0x6e
|
||||
HADDR = 0x88
|
||||
HADDR+1 = 0x89
|
||||
HADDR+2 = 0x8a
|
||||
HADDR+3 = 0x8b
|
||||
HCNT = 0x8c
|
||||
HCNT+0 = 0x8c
|
||||
HCNT+1 = 0x8d
|
||||
@ -113,8 +116,12 @@ SCBARRAY+23 = 0xb7
|
||||
SCBARRAY+24 = 0xb8
|
||||
SCBARRAY+25 = 0xb9
|
||||
SCBARRAY+26 = 0xba
|
||||
SCBARRAY+27 = 0xbb
|
||||
SCBARRAY+28 = 0xbc
|
||||
SCBARRAY+29 = 0xbd
|
||||
|
||||
BAD_PHASE = 0x01 # unknown scsi bus phase
|
||||
CMDCMPLT = 0x02
|
||||
SEND_REJECT = 0x11 # sending a message reject
|
||||
NO_IDENT = 0x21 # no IDENTIFY after reconnect
|
||||
NO_MATCH = 0x31 # no cmd match for reconnect
|
||||
@ -122,6 +129,7 @@ MSG_SDTR = 0x41 # SDTR message recieved
|
||||
MSG_WDTR = 0x51 # WDTR message recieved
|
||||
MSG_REJECT = 0x61 # Reject message recieved
|
||||
BAD_STATUS = 0x71 # Bad status from target
|
||||
RESIDUAL = 0x81 # Residual byte count != 0
|
||||
|
||||
# The host adapter card (at least the BIOS) uses 20-2f for SCSI
|
||||
# device information, 32-33 and 5a-5f as well. As it turns out, the
|
||||
@ -164,7 +172,7 @@ MSG_START+2 = 0x37
|
||||
MSG_START+3 = 0x38
|
||||
MSG_START+4 = 0x39
|
||||
MSG_START+5 = 0x3a
|
||||
-MSG_START+0 = 0xcb # 2's complement of MSG_START+0
|
||||
-MSG_START+0 = 0xcc # 2's complement of MSG_START+0
|
||||
|
||||
ARG_1 = 0x4a # sdtr conversion args & return
|
||||
BUS_16_BIT = 0x01
|
||||
@ -189,6 +197,7 @@ SCBCOUNT = 0x52 # the actual number of SCBs
|
||||
FLAGS = 0x53 # Device configuration flags
|
||||
TWIN_BUS = 0x01
|
||||
WIDE_BUS = 0x02
|
||||
MAX_SYNC = 0x08
|
||||
SENSE = 0x10
|
||||
ACTIVE_MSG = 0x20
|
||||
IDENTIFY_SEEN = 0x40
|
||||
@ -236,34 +245,16 @@ test SCBARRAY+0,NEEDDMA jz test_busy
|
||||
# Wait for DMA from host memory to data FIFO to complete, then disable
|
||||
# DMA and wait for it to acknowledge that it's off.
|
||||
#
|
||||
scb_load1:
|
||||
test DFSTATUS,0x8 jz scb_load1 # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
scb_load2:
|
||||
test DFCNTRL,0x8 jnz scb_load2 # HDMAENACK
|
||||
call dma_finish
|
||||
|
||||
# Copy the SCB from the FIFO to the SCBARRAY
|
||||
|
||||
mov SCBARRAY+0, DFDAT
|
||||
mov SCBARRAY+1, DFDAT
|
||||
mov SCBARRAY+2, DFDAT
|
||||
mov SCBARRAY+3, DFDAT
|
||||
mov SCBARRAY+4, DFDAT
|
||||
mov SCBARRAY+5, DFDAT
|
||||
mov SCBARRAY+6, DFDAT
|
||||
mov SCBARRAY+7, DFDAT
|
||||
mov SCBARRAY+8, DFDAT
|
||||
mov SCBARRAY+9, DFDAT
|
||||
mov SCBARRAY+10, DFDAT
|
||||
mov SCBARRAY+11, DFDAT
|
||||
mov SCBARRAY+12, DFDAT
|
||||
mov SCBARRAY+13, DFDAT
|
||||
mov SCBARRAY+14, DFDAT
|
||||
mov SCBARRAY+15, DFDAT
|
||||
mov SCBARRAY+16, DFDAT
|
||||
mov SCBARRAY+17, DFDAT
|
||||
mov SCBARRAY+18, DFDAT
|
||||
mvi DINDEX, SCBARRAY+0
|
||||
call bcopy_3_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
call bcopy_4_dfdat
|
||||
|
||||
# See if there is not already an active SCB for this target. This code
|
||||
# locks out on a per target basis instead of target/lun. Although this
|
||||
@ -338,7 +329,6 @@ mk_tag:
|
||||
mov DINDIR,SCBPTR
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX # update message length
|
||||
jmp !message # Can't do DTR when taged
|
||||
|
||||
mk_tag_done:
|
||||
|
||||
@ -441,9 +431,17 @@ p_dataout:
|
||||
mvi DINDEX,STCNT
|
||||
mvi SCBARRAY+23 call bcopy_3
|
||||
|
||||
# If we are the last SG block, don't set wideodd.
|
||||
test SCBARRAY+18,0xff jnz p_dataout_wideodd
|
||||
mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
|
||||
# DIRECTION|FIFORESET
|
||||
jmp p_dataout_rest
|
||||
|
||||
p_dataout_wideodd:
|
||||
mvi 0xbd call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
|
||||
# DIRECTION|FIFORESET
|
||||
|
||||
p_dataout_rest:
|
||||
# After a DMA finishes, save the final transfer pointer and count
|
||||
# back into the SCB, in case a device disconnects in the middle of
|
||||
# a transfer. Use SHADDR and STCNT instead of HADDR and HCNT, since
|
||||
@ -475,8 +473,15 @@ p_datain:
|
||||
mvi DINDEX,STCNT
|
||||
mvi SCBARRAY+23 call bcopy_3
|
||||
|
||||
# If we are the last SG block, don't set wideodd.
|
||||
test SCBARRAY+18,0xff jnz p_datain_wideodd
|
||||
mvi 0x39 call dma # SCSIEN|SDMAEN|HDMAEN|
|
||||
# !DIRECTION|FIFORESET
|
||||
jmp p_datain_rest
|
||||
p_datain_wideodd:
|
||||
mvi 0xb9 call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
|
||||
# !DIRECTION|FIFORESET
|
||||
p_datain_rest:
|
||||
mvi DINDEX,SCBARRAY+23
|
||||
mvi STCNT call bcopy_3
|
||||
|
||||
@ -611,21 +616,25 @@ p_mesgin:
|
||||
# This allows the driver to interpret errors only when they occur
|
||||
# instead of always uploading the scb. If the status is SCSI_CHECK,
|
||||
# the driver will download a new scb requesting sense, to replace
|
||||
# the old one and the sequencer code will imediately jump to start
|
||||
# working on it. If the kernel driver does not wish to request sense,
|
||||
# the sequencer program counter is incremented by 1, preventing another run
|
||||
# on the current SCB and the command is allowed to complete. We don't
|
||||
# the old one and set the SENSE sequencer flag. If the sense flag is
|
||||
# set, the sequencer imediately jumps to start working on the sense
|
||||
# command. If the kernel driver does not wish to request sense, it need
|
||||
# do nothing, and the command is allowed to complete. We don't
|
||||
# bother to post to the QOUTFIFO in the error case since it would require
|
||||
# extra work in the kernel driver to ensure that the entry was removed
|
||||
# before the command complete code tried processing it.
|
||||
|
||||
test SCBARRAY+15,0xff jnz resid
|
||||
test SCBARRAY+16,0xff jnz resid
|
||||
test SCBARRAY+17,0xff jnz resid
|
||||
|
||||
check_status:
|
||||
test SCBARRAY+14,0xff jz status_ok # 0 Status?
|
||||
mvi INTSTAT,BAD_STATUS # let driver know
|
||||
test FLAGS,SENSE jz status_ok
|
||||
jmp p_mesgin_done
|
||||
|
||||
status_ok:
|
||||
|
||||
# First, mark this target as free.
|
||||
test SCBARRAY+0,0x20 jnz complete # Tagged command
|
||||
and FUNCTION1,0x70,SCBARRAY+1
|
||||
@ -639,9 +648,20 @@ clear_a:
|
||||
|
||||
complete:
|
||||
mov QOUTFIFO,SCBPTR
|
||||
mvi INTSTAT,0x02 # CMDCMPLT
|
||||
mvi INTSTAT,CMDCMPLT
|
||||
jmp p_mesgin_done
|
||||
|
||||
# If we have a residual count, interrupt and tell the host. Other
|
||||
# alternatives are to pause the sequencer on all command completes (yuck),
|
||||
# dma the resid directly to the host (slick, but a ton of instructions), or
|
||||
# have the sequencer pause itself when it encounters a non-zero resid
|
||||
# (unecessary pause just to flag the command -- yuck, but takes few instructions
|
||||
# and since it shouldn't happen that offten is good enough for our purposes).
|
||||
|
||||
resid:
|
||||
mvi INTSTAT,RESIDUAL
|
||||
jmp check_status
|
||||
|
||||
# Is it an extended message? We only support the synchronous and wide data
|
||||
# transfer request messages, which will probably be in response to
|
||||
# WDTR or SDTR message outs from us. If it's not SDTR or WDTR, reject it -
|
||||
@ -836,6 +856,16 @@ bcopy_4:
|
||||
mov DINDIR,SINDIR
|
||||
mov DINDIR,SINDIR ret
|
||||
|
||||
bcopy_3_dfdat:
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT ret
|
||||
|
||||
bcopy_4_dfdat:
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT
|
||||
mov DINDIR,DFDAT ret
|
||||
|
||||
# Locking the driver out, build a one-byte message passed in SINDEX
|
||||
# if there is no active message already. SINDEX is returned intact.
|
||||
@ -966,6 +996,14 @@ dma6:
|
||||
|
||||
ret
|
||||
|
||||
dma_finish:
|
||||
test DFSTATUS,0x8 jz dma_finish # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
dma_finish2:
|
||||
test DFCNTRL,0x8 jnz dma_finish2 # HDMAENACK
|
||||
ret
|
||||
|
||||
# Common SCSI initialization for selection and reselection. Expects
|
||||
# the target SCSI ID to be in the upper four bits of SINDEX, and A's
|
||||
# contents are stomped on return.
|
||||
@ -1003,13 +1041,10 @@ initialize:
|
||||
# message.
|
||||
#
|
||||
assert:
|
||||
test FLAGS,RESELECTED jz assert1 # reselected?
|
||||
test FLAGS,IDENTIFY_SEEN jnz assert1 # seen IDENTIFY?
|
||||
test FLAGS,RESELECTED jz return # reselected?
|
||||
test FLAGS,IDENTIFY_SEEN jnz return # seen IDENTIFY?
|
||||
|
||||
mvi INTSTAT,NO_IDENT # no - cause a kernel panic
|
||||
|
||||
assert1:
|
||||
ret
|
||||
mvi INTSTAT,NO_IDENT ret # no - cause a kernel panic
|
||||
|
||||
# Find out if disconnection is ok from the information the BIOS has left
|
||||
# us. The tcl from SCBARRAY+1 should be in SINDEX; A will
|
||||
@ -1067,11 +1102,8 @@ sg_scb2ram:
|
||||
mvi SCBARRAY+3 call bcopy_4
|
||||
|
||||
mvi SG_NOLOAD,0x80
|
||||
test SCBARRAY+0,0x10 jnz sg_scb2ram1 # don't reload s/g?
|
||||
clr SG_NOLOAD
|
||||
|
||||
sg_scb2ram1:
|
||||
ret
|
||||
test SCBARRAY+0,0x10 jnz return # don't reload s/g?
|
||||
clr SG_NOLOAD ret
|
||||
|
||||
# Copying RAM values back to SCB, for Save Data Pointers message.
|
||||
#
|
||||
@ -1082,11 +1114,8 @@ sg_ram2scb:
|
||||
mvi SG_NEXT call bcopy_4
|
||||
|
||||
and SCBARRAY+0,0xef,SCBARRAY+0
|
||||
test SG_NOLOAD,0x80 jz sg_ram2scb1 # reload s/g?
|
||||
or SCBARRAY+0,SG_LOAD
|
||||
|
||||
sg_ram2scb1:
|
||||
ret
|
||||
test SG_NOLOAD,0x80 jz return # reload s/g?
|
||||
or SCBARRAY+0,SG_LOAD ret
|
||||
|
||||
# Load a struct scatter if needed and set up the data address and
|
||||
# length. If the working value of the SG count is nonzero, then
|
||||
@ -1095,8 +1124,8 @@ sg_ram2scb1:
|
||||
# This, like the above DMA, assumes a little-endian host data storage.
|
||||
#
|
||||
sg_load:
|
||||
test SG_COUNT,0xff jz sg_load3 # SG being used?
|
||||
test SG_NOLOAD,0x80 jnz sg_load3 # don't reload s/g?
|
||||
test SG_COUNT,0xff jz return # SG being used?
|
||||
test SG_NOLOAD,0x80 jnz return # don't reload s/g?
|
||||
|
||||
clr HCNT+2
|
||||
clr HCNT+1
|
||||
@ -1110,12 +1139,8 @@ sg_load:
|
||||
# Wait for DMA from host memory to data FIFO to complete, then disable
|
||||
# DMA and wait for it to acknowledge that it's off.
|
||||
#
|
||||
sg_load1:
|
||||
test DFSTATUS,0x8 jz sg_load1 # HDONE
|
||||
|
||||
clr DFCNTRL # disable DMA
|
||||
sg_load2:
|
||||
test DFCNTRL,0x8 jnz sg_load2 # HDMAENACK
|
||||
call dma_finish
|
||||
|
||||
# Copy data from FIFO into SCB data pointer and data count. This assumes
|
||||
# that the struct scatterlist has this structure (this and sizeof(struct
|
||||
@ -1128,7 +1153,7 @@ sg_load2:
|
||||
# }
|
||||
#
|
||||
|
||||
# Not in FreeBSD. the scatter list is only 8 bytes.
|
||||
# Not in FreeBSD. the scatter list entry is only 8 bytes.
|
||||
#
|
||||
# struct ahc_dma_seg {
|
||||
# physaddr addr; /* four bytes, little-endian order */
|
||||
@ -1136,10 +1161,8 @@ sg_load2:
|
||||
# };
|
||||
#
|
||||
|
||||
mov SCBARRAY+19,DFDAT # new data address
|
||||
mov SCBARRAY+20,DFDAT
|
||||
mov SCBARRAY+21,DFDAT
|
||||
mov SCBARRAY+22,DFDAT
|
||||
mvi DINDEX, SCBARRAY+19
|
||||
call bcopy_4_dfdat
|
||||
|
||||
# For Linux, we must throw away four bytes since there is a 32bit gap
|
||||
# in the middle of a struct scatterlist
|
||||
@ -1148,11 +1171,7 @@ sg_load2:
|
||||
# mov NONE,DFDAT
|
||||
# mov NONE,DFDAT
|
||||
|
||||
mov SCBARRAY+23,DFDAT
|
||||
mov SCBARRAY+24,DFDAT
|
||||
mov SCBARRAY+25,DFDAT #Only support 24 bit length.
|
||||
|
||||
sg_load3:
|
||||
call bcopy_3_dfdat #Only support 24 bit length.
|
||||
ret
|
||||
|
||||
# Advance the scatter-gather pointers only IF NEEDED. If SG is enabled,
|
||||
@ -1163,7 +1182,7 @@ sg_load3:
|
||||
# next time.
|
||||
#
|
||||
sg_advance:
|
||||
test SG_COUNT,0xff jz sg_advance2 # s/g enabled?
|
||||
test SG_COUNT,0xff jz return # s/g enabled?
|
||||
|
||||
test STCNT+0,0xff jnz sg_advance1 # SCSI transfer count nonzero?
|
||||
test STCNT+1,0xff jnz sg_advance1
|
||||
@ -1179,9 +1198,7 @@ sg_advance:
|
||||
adc SG_NEXT+3,A,SG_NEXT+3 ret
|
||||
|
||||
sg_advance1:
|
||||
mvi SG_NOLOAD,0x80 # don't reload s/g next time
|
||||
sg_advance2:
|
||||
ret
|
||||
mvi SG_NOLOAD,0x80 ret # don't reload s/g next time
|
||||
|
||||
# Add the array base SYNCNEG to the target offset (the target address
|
||||
# is in SCSIID), and return the result in SINDEX. The accumulator
|
||||
@ -1204,10 +1221,27 @@ ndx_dtr_2:
|
||||
# reject, you wouldn't be able to tell which message was the culpret.
|
||||
#
|
||||
mk_dtr:
|
||||
mov DINDEX,SINDEX # save SINDEX
|
||||
|
||||
test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR
|
||||
test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
|
||||
jmp mk_sdtr
|
||||
or FLAGS, MAX_SYNC # Force an offset of 15
|
||||
|
||||
mk_sdtr:
|
||||
mvi DINDIR,1 # extended message
|
||||
mvi DINDIR,3 # extended message length = 3
|
||||
mvi DINDIR,1 # SDTR code
|
||||
call sdtr_to_rate
|
||||
mov DINDIR,RETURN_1 # REQ/ACK transfer period
|
||||
test FLAGS, MAX_SYNC jnz mk_sdtr_max_sync
|
||||
and DINDIR,0xf,SINDIR # Sync Offset
|
||||
|
||||
mk_sdtr_done:
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
mk_sdtr_max_sync:
|
||||
# We're initiating sync negotiation, so request the max offset we can (15)
|
||||
mvi DINDIR, 0x0f
|
||||
xor FLAGS, MAX_SYNC
|
||||
jmp mk_sdtr_done
|
||||
|
||||
mk_wdtr_16bit:
|
||||
mvi ARG_1,BUS_16_BIT
|
||||
@ -1219,16 +1253,6 @@ mk_wdtr:
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
mk_sdtr:
|
||||
mvi DINDIR,1 # extended message
|
||||
mvi DINDIR,3 # extended message length = 3
|
||||
mvi DINDIR,1 # SDTR code
|
||||
call sdtr_to_rate
|
||||
mov DINDIR,RETURN_1 # REQ/ACK transfer period
|
||||
and DINDIR,0xf,SINDIR # Sync Offset
|
||||
|
||||
add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
|
||||
|
||||
# Set SCSI bus control signal state. This also saves the last-written
|
||||
# value into a location where the higher-level driver can read it - if
|
||||
# it has to send an ABORT or RESET message, then it needs to know this
|
||||
@ -1254,3 +1278,6 @@ sdtr_to_rate_loop:
|
||||
sdtr_to_rate_done:
|
||||
shr RETURN_1,0x2
|
||||
add RETURN_1,0x18 ret
|
||||
|
||||
return:
|
||||
ret
|
||||
|
Loading…
Reference in New Issue
Block a user