From 20c5e655720c69111a04a95c51b1cb7dee46b81a Mon Sep 17 00:00:00 2001 From: "Justin T. Gibbs" Date: Fri, 13 Jan 1995 02:22:11 +0000 Subject: [PATCH] Full support for 294x and Wide devices. Fixed month old bug in the SCSI sense retrieval code that messed up CDROM devices. This code will also responde correctly to SDTR and WDTR messages from devices that start a negotiation sequence. --- sys/dev/aic7xxx/aic7xxx.seq | 258 +++++++++++++++++++++---------- sys/gnu/misc/aic7xxx/aic7xxx.seq | 258 +++++++++++++++++++++---------- 2 files changed, 350 insertions(+), 166 deletions(-) diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq index a11203357e25..d1ed1e1c80a9 100644 --- a/sys/dev/aic7xxx/aic7xxx.seq +++ b/sys/dev/aic7xxx/aic7xxx.seq @@ -1,6 +1,6 @@ -# @(#)aic7xxx.seq 1.31 94/11/25 jda +# @(#)aic7xxx.seq 1.32 94/11/29 jda # -# Adaptec 274x device driver for Linux. +# Adaptec 274x/284x/294x device driver for Linux. # Copyright (c) 1994 The University of Calgary Department of Computer Science. # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -VERSION AIC7XXX_SEQ_VERSION 1.31 +VERSION AIC7XXX_SEQ_VERSION 1.32 SCBMASK = 0x1f @@ -97,6 +97,7 @@ SIGNAL_2 = 0x21 # no IDENTIFY after reconnect SIGNAL_3 = 0x31 # no cmd match for reconnect SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion STATUS_ERROR = 0x51 +SIGNAL_WDTR = 0x61 # 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 @@ -116,7 +117,7 @@ STATUS_ERROR = 0x51 # message, so the driver can report an intelligible error if a message is # rejected. # -# RESELECT's high bit is true if we are currently handling a reselect; +# FLAGS's high bit is true if we are currently handling a reselect; # its next-highest bit is true ONLY IF we've seen an IDENTIFY message # from the reselecting target. If we haven't had IDENTIFY, then we have # no idea what the lun is, and we can't select the right SCB register @@ -131,9 +132,10 @@ DROPATN = 0x30 REJBYTE = 0x31 DISC_DSB_A = 0x32 DISC_DSB_B = 0x33 -RESELECT = 0x34 -MSG_FLAGS = 0x35 +NEEDWDTR_A = 0x34 +NEEDWDTR_B = 0x35 + MSG_LEN = 0x36 MSG_START+0 = 0x37 MSG_START+1 = 0x38 @@ -163,6 +165,11 @@ SCBCOUNT = 0x56 # the actual number of SCBs FLAGS = 0x57 # Device configuration flags TWIN_BUS = 0x01 WIDE_BUS = 0x02 +CHECK_DTR = 0x08 +SENSE = 0x10 +ACTIVE_MSG = 0x20 +IDENTIFY_SEEN = 0x40 +RESELECTED = 0x80 ACTIVE_A = 0x58 ACTIVE_B = 0x59 @@ -171,6 +178,7 @@ ACTIVE_B = 0x59 # the number of entries in the Queue In FIFO. # start: + test FLAGS,SENSE jnz start_sense test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device? # For fairness, we check the other bus first, since we just finished a # transaction on the current channel. @@ -205,6 +213,11 @@ start2: or ACTIVE_B,A # Mark the current target as busy jmp start_scb +start_sense: +# Clear the SENSE flag first, then do a normal start_scb + and FLAGS,0xef + jmp start_scb + # Place the currently active back on the queue for later processing requeue: mov QINFIFO, SCBPTR @@ -215,11 +228,13 @@ test_a: or ACTIVE_A,A # Mark the current target as busy start_scb: - and A,0x08,SCBARRAY+1 - mov SBLKCTL,A # select channel, !wide + and SINDEX,0x08,SCBARRAY+1 + and A,WIDE_BUS,FLAGS # Wide bus? + or SINDEX,A + mov SBLKCTL,SINDEX # select channel, bus width mov SCBARRAY+1 call initialize clr SG_NOLOAD - clr RESELECT + and FLAGS,0x3f # !RESELECTING # As soon as we get a successful selection, the target should go # into the message out phase since we have ATN asserted. Prepare @@ -238,7 +253,8 @@ start_scb: mov A,SINDEX cmp MSG_START+0,A jne !message # did driver beat us? - mvi MSG_START+1 call mk_sdtr # build SDTR message if needed + test FLAGS,CHECK_DTR jz !message # Don't even bother with DTR? + mvi MSG_START+1 call mk_dtr # build DTR message if needed !message: @@ -286,7 +302,8 @@ reselect1: test SSTAT0,0x20 jz reselect1 # SELDI mov SELID call initialize - mvi RESELECT,0x80 # reselected, no IDENTIFY + and FLAGS,0x3f # reselected, no IDENTIFY + or FLAGS,RESELECTED # After the [re]selection, make sure that the [re]selection enable # bit is off. This chip is flaky enough without extra things @@ -495,7 +512,7 @@ p_mesgout5: p_mesgout6: mvi CLRSINT1,0x40 # CLRATNO - in case of PHASEMIS - clr MSG_FLAGS # no active msg + and FLAGS,0xdf # no active msg jmp ITloop # Message in phase. Bytes are read using Automatic PIO mode, but not @@ -528,9 +545,9 @@ p_mesgin: # before the command complete code tried processing it. test SCBARRAY+14,0xff jz status_ok # 0 Status? - call inb_last # ack & turn auto PIO back on mvi INTSTAT,STATUS_ERROR # let driver know - jmp start_scb + test FLAGS,SENSE jz status_ok + jmp p_mesgin_done status_ok: @@ -549,50 +566,48 @@ complete: mvi INTSTAT,0x02 # CMDCMPLT jmp p_mesgin_done -# Is it an extended message? We only support the synchronous data -# transfer request message, which will probably be in response to -# an SDTR message out from us. If it's not an SDTR, reject it - +# 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 - # apparently this can be done after any message in byte, according # to the SCSI-2 spec. # -# XXX - we should really reject this if we didn't initiate the SDTR -# negotiation; this may cause problems with unusual devices. -# p_mesgin1: cmp A,1 jne p_mesgin2 # extended message code? - mvi A call inb_next - cmp A,3 jne p_mesginN # extended mesg length = 3 - mvi A call inb_next - cmp A,1 jne p_mesginN # SDTR code + mvi ARG_1 call inb_next # extended message length + mvi A call inb_next # extended message code + cmp A,1 je p_mesginSDTR # Syncronous negotiation message + cmp A,3 je p_mesginWDTR # Wide negotiation message + jmp p_mesginN + +p_mesginWDTR: + cmp ARG_1,2 jne p_mesginN # extended mesg length = 2 + mvi A call inb_next # Width of bus + mvi INTSTAT,SIGNAL_WDTR # let driver know + test RETURN_1,0x80 jz p_mesgin_done# Do we need to send WDTR? + +# We didn't initiate the wide negotiation, so we must respond to the request + and RETURN_1,0x7f # Clear the SEND_WDTR Flag + or FLAGS,ACTIVE_MSG + mvi MSG_START+0 call mk_wdtr # build WDTR message + or SINDEX,0x10,SIGSTATE # turn on ATNO + call scsisig + jmp p_mesgin_done + +p_mesginSDTR: + cmp ARG_1,3 jne p_mesginN # extended mesg length = 3 mvi ARG_1 call inb_next # xfer period mvi A call inb_next # REQ/ACK offset mvi INTSTAT,SIGNAL_4 # call driver to convert - call ndx_sdtr # index sync config for target - mov DINDEX,SINDEX - not A # turn off "need sdtr" flag - test SBLKCTL,0x08 jnz p_mesgin1_b - test SCSIID,0x80 jnz p_mesgin1_b - and NEEDSDTR_A,A - jmp p_mesgin1_save + test RETURN_1,0x80 jz p_mesgin_done# Do we need to mk_sdtr? -p_mesgin1_b: - and NEEDSDTR_B,A - -p_mesgin1_save: - and A,0x80,SINDIR # get the WIDEXFER flag - or RETURN_1,A # Set WIDEXFER if necessary - mov DINDIR,RETURN_1 # save returned value - -# Even though the SCSI-2 specification says that a device responding -# to our SDTR message should honor our parameters for transmitting -# to us, it doesn't seem to work too well in real life. In particular, -# a lot of CD-ROM and tape units don't function: try using the SDTR -# parameters the device sent us for both transmitting and receiving. -# - mov SCSIRATE,RETURN_1 + or FLAGS,ACTIVE_MSG + mvi MSG_START+0 call mk_sdtr + or SINDEX,0x10,SIGSTATE # turn on ATNO + call scsisig jmp p_mesgin_done # Is it a disconnect message? Set a flag in the SCB to remind us @@ -638,17 +653,17 @@ p_mesgin5: # or the driver is trying to abort the command. Either way, something # untoward has happened and we should just leave it alone. # - test MSG_FLAGS,0x80 jnz p_mesgin_done + test FLAGS,ACTIVE_MSG jnz p_mesgin_done and SCBARRAY+0,0xfb # clear disconnect bit in SCB - mvi RESELECT,0xc0 # make note of IDENTIFY + or FLAGS,0xc0 # make note of IDENTIFY call sg_scb2ram # implied restore pointers # required on reselect jmp p_mesgin_done -# Message reject? If we have an outstanding SDTR negotiation, assume -# that it's a response from the target selecting asynchronous transfer, +# Message reject? If we have an outstanding WDTR or SDTR negotiation, assume +# that it's a response from the target selecting 8bit or asynchronous transfer, # otherwise just ignore it since we have no clue what it pertains to. # # XXX - I don't have a device that responds this way. Does this code @@ -662,27 +677,55 @@ p_mesgin6: test SBLKCTL,0x08 jnz p_mesgin6_b test SCSIID,0x80 jnz p_mesgin6_b - test NEEDSDTR_A,A jz p_mesgin_done # no - ignore rejection - call ndx_sdtr # note use of asynch xfer + test NEEDWDTR_A,A jnz clear_wdtr_a + test NEEDSDTR_A,A jnz clear_sdtr_a + jmp p_mesgin_done # no - ignore rejection + +clear_sdtr_a: + call ndx_dtr # note use of asynch xfer mov DINDEX,SINDEX - clr DINDIR + and DINDIR,0x80,SINDIR not A and NEEDSDTR_A,A - jmp p_mesgin6_done + jmp clear_sdtr_done + +clear_wdtr_a: + call ndx_dtr # note use of 8bit xfer + mov DINDEX,SINDEX + and DINDIR,0x7f,SINDIR + + not A + and NEEDWDTR_A,A + jmp clear_wdtr_done p_mesgin6_b: - test NEEDSDTR_B,A jz p_mesgin_done # no - ignore rejection - call ndx_sdtr # note use of asynch xfer + test NEEDWDTR_B,A jnz clear_wdtr_b + test NEEDSDTR_B,A jnz clear_sdtr_b + jmp p_mesgin_done # no - ignore rejection + +clear_wdtr_b: + call ndx_dtr # note use of 8bit xfer mov DINDEX,SINDEX - clr DINDIR + and DINDIR,0x7f,SINDIR + + not A + and NEEDWDTR_B,A + +clear_wdtr_done: + and SCSIRATE,0x7f # select 8bit xfer + jmp p_mesgin_done + +clear_sdtr_b: + call ndx_dtr # note use of asynch xfer + mov DINDEX,SINDEX + and DINDIR,0x80,SINDIR not A and NEEDSDTR_B,A -p_mesgin6_done: - - clr SCSIRATE # select asynch xfer +clear_sdtr_done: + and SCSIRATE,0xf0 # select asynch xfer jmp p_mesgin_done # [ ADD MORE MESSAGE HANDLING HERE ] @@ -731,9 +774,9 @@ bcopy: # mk_mesg: mvi SEQCTL,0x50 # PAUSEDIS|FASTMODE - test MSG_FLAGS,0x80 jnz mk_mesg1 # active message? + test FLAGS,ACTIVE_MSG jnz mk_mesg1 # active message? - mvi MSG_FLAGS,0x80 # if not, there is now + or FLAGS,ACTIVE_MSG # if not, there is now mvi MSG_LEN,1 # length = 1 mov MSG_START+0,SINDEX # 1-byte message @@ -839,7 +882,7 @@ dma2: dma3: test SINDEX,0x4 jnz dma5 # DIRECTION dma4: - test DFSTATUS,0x1 jz dma4 # FIFOEMP + test DFSTATUS,0x1 jz dma4 # !FIFOEMP # Now shut the DMA enables off, and copy STCNT (ie. the underrun # amount, if any) to the SCB registers; SG_COUNT will get copied to @@ -873,7 +916,7 @@ initialize_b: mvi SCSICONF_B jmp initialize_2 initialize_wide: - and A, 0xf,SCSICONF_B + and A,0x0f,SCSICONF_B # SCSI_ID_B[210] initialize_2: or SCSIID,A @@ -900,7 +943,7 @@ initialize_2: # STPWEN is 7870-specific, enabling an external termination power source. # and A,0x38,SINDIR # PARITY_ENB|SEL_TIM[10] - or SXFRCTL1,0x7,A # ENSTIMER|ACTNEGEN|STPWEN + or SXFRCTL1,0x7,A # ENSTIMER|ACTBEGEB|STPWEN mvi SIMODE1,0x84 # ENSELTIMO|ENSCSIPERR # Initialize scatter-gather pointers by setting up the working copy @@ -910,7 +953,7 @@ initialize_2: # Initialize SCSIRATE with the appropriate value for this target. # - call ndx_sdtr + call ndx_dtr mov SCSIRATE,SINDIR ret @@ -918,8 +961,8 @@ initialize_2: # message. # assert: - test RESELECT,0x80 jz assert1 # reselected? - test RESELECT,0x40 jnz assert1 # seen IDENTIFY? + test FLAGS,RESELECTED jz assert1 # reselected? + test FLAGS,IDENTIFY_SEEN jnz assert1 # seen IDENTIFY? mvi INTSTAT,SIGNAL_2 # no - cause a kernel panic @@ -1111,39 +1154,73 @@ sg_advance2: # is in SCSIID), and return the result in SINDEX. The accumulator # contains the 3->8 decoding of the target ID on return. # -ndx_sdtr: +ndx_dtr: shr A,SCSIID,4 - test SBLKCTL,0x08 jz ndx_sdtr_2 + test SBLKCTL,0x08 jz ndx_dtr_2 or A,0x08 # Channel B entries add 8 -ndx_sdtr_2: +ndx_dtr_2: add SINDEX,SYNCNEG,A and FUNCTION1,0x70,SCSIID # 3-bit target address decode mov A,FUNCTION1 ret -# If we need to negotiate transfer parameters, build the SDTR message +# If we need to negotiate transfer parameters, build the WDTR or SDTR message # starting at the address passed in SINDEX. DINDEX is modified on return. +# The SCSI-II spec requires that Wide negotiation occur first and you can +# only negotiat one or the other at a time otherwise in the event of a message +# reject, you wouldn't be able to tell which message was the culpret. # -mk_sdtr: +mk_dtr: mov DINDEX,SINDEX # save SINDEX - call ndx_sdtr - test SCBARRAY+1,0x88 jz mk_sdtr1_a - test NEEDSDTR_B,A jnz mk_sdtr1 # do we need negotiation? + call ndx_dtr + test SCBARRAY+1,0x88 jz mk_dtr_a + test NEEDWDTR_B,A jnz mk_wdtr_16 # do we need negotiation? + test NEEDSDTR_B,A jnz mk_sdtr ret -mk_sdtr1_a: - test NEEDSDTR_A,A jnz mk_sdtr1 # do we need negotiation? +mk_dtr_a: + test NEEDWDTR_A,A jnz mk_wdtr_16 # do we need negotiation? + test NEEDSDTR_A,A jnz mk_sdtr ret -mk_sdtr1: +mk_wdtr_16: + mvi ARG_1,1 # 16bit wide bus + +mk_wdtr: mvi DINDIR,1 # extended message - mvi DINDIR,3 # extended message length = 3 - mvi DINDIR,1 # SDTR code - mvi DINDIR,25 # REQ/ACK transfer period - mvi DINDIR,15 # REQ/ACK offset + mvi DINDIR,2 # extended message length = 2 + mvi DINDIR,3 # WDTR code + mov DINDIR,ARG_1 # bus width add MSG_LEN,-MSG_START+0,DINDEX # update message length ret + +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 # update message length + ret + +# Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag +# value + +#mk_tag: +# test SCBARRAY+0,0x10 jz mk_tag_done # Tag Enabled? +# and A,0x03,SCBARRYA+0 +# or A,0x20 +# mov DINDIR,A +# mov DINDIR,SCBPTR +# +# add MSG_LEN,-MSG_START+0,DINDEX # update message length + +#mk_tag_done: +# ret + # 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 @@ -1155,3 +1232,18 @@ mk_sdtr1: scsisig: mov SIGSTATE,SINDEX mov SCSISIGO,SINDEX ret + +sdtr_to_rate: + call ndx_dtr # index scratch space for target + shr A,SINDIR,0x4 + dec SINDEX #Preserve SINDEX + and A,0x7 + clr RETURN_1 +sdtr_to_rate_loop: + test A,0x0f jz sdtr_to_rate_done + add RETURN_1,0x18 + dec A + jmp sdtr_to_rate_loop +sdtr_to_rate_done: + shr RETURN_1,0x2 + add RETURN_1,0x18 ret diff --git a/sys/gnu/misc/aic7xxx/aic7xxx.seq b/sys/gnu/misc/aic7xxx/aic7xxx.seq index a11203357e25..d1ed1e1c80a9 100644 --- a/sys/gnu/misc/aic7xxx/aic7xxx.seq +++ b/sys/gnu/misc/aic7xxx/aic7xxx.seq @@ -1,6 +1,6 @@ -# @(#)aic7xxx.seq 1.31 94/11/25 jda +# @(#)aic7xxx.seq 1.32 94/11/29 jda # -# Adaptec 274x device driver for Linux. +# Adaptec 274x/284x/294x device driver for Linux. # Copyright (c) 1994 The University of Calgary Department of Computer Science. # # This program is free software; you can redistribute it and/or modify @@ -17,7 +17,7 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. -VERSION AIC7XXX_SEQ_VERSION 1.31 +VERSION AIC7XXX_SEQ_VERSION 1.32 SCBMASK = 0x1f @@ -97,6 +97,7 @@ SIGNAL_2 = 0x21 # no IDENTIFY after reconnect SIGNAL_3 = 0x31 # no cmd match for reconnect SIGNAL_4 = 0x41 # SDTR -> SCSIRATE conversion STATUS_ERROR = 0x51 +SIGNAL_WDTR = 0x61 # 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 @@ -116,7 +117,7 @@ STATUS_ERROR = 0x51 # message, so the driver can report an intelligible error if a message is # rejected. # -# RESELECT's high bit is true if we are currently handling a reselect; +# FLAGS's high bit is true if we are currently handling a reselect; # its next-highest bit is true ONLY IF we've seen an IDENTIFY message # from the reselecting target. If we haven't had IDENTIFY, then we have # no idea what the lun is, and we can't select the right SCB register @@ -131,9 +132,10 @@ DROPATN = 0x30 REJBYTE = 0x31 DISC_DSB_A = 0x32 DISC_DSB_B = 0x33 -RESELECT = 0x34 -MSG_FLAGS = 0x35 +NEEDWDTR_A = 0x34 +NEEDWDTR_B = 0x35 + MSG_LEN = 0x36 MSG_START+0 = 0x37 MSG_START+1 = 0x38 @@ -163,6 +165,11 @@ SCBCOUNT = 0x56 # the actual number of SCBs FLAGS = 0x57 # Device configuration flags TWIN_BUS = 0x01 WIDE_BUS = 0x02 +CHECK_DTR = 0x08 +SENSE = 0x10 +ACTIVE_MSG = 0x20 +IDENTIFY_SEEN = 0x40 +RESELECTED = 0x80 ACTIVE_A = 0x58 ACTIVE_B = 0x59 @@ -171,6 +178,7 @@ ACTIVE_B = 0x59 # the number of entries in the Queue In FIFO. # start: + test FLAGS,SENSE jnz start_sense test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device? # For fairness, we check the other bus first, since we just finished a # transaction on the current channel. @@ -205,6 +213,11 @@ start2: or ACTIVE_B,A # Mark the current target as busy jmp start_scb +start_sense: +# Clear the SENSE flag first, then do a normal start_scb + and FLAGS,0xef + jmp start_scb + # Place the currently active back on the queue for later processing requeue: mov QINFIFO, SCBPTR @@ -215,11 +228,13 @@ test_a: or ACTIVE_A,A # Mark the current target as busy start_scb: - and A,0x08,SCBARRAY+1 - mov SBLKCTL,A # select channel, !wide + and SINDEX,0x08,SCBARRAY+1 + and A,WIDE_BUS,FLAGS # Wide bus? + or SINDEX,A + mov SBLKCTL,SINDEX # select channel, bus width mov SCBARRAY+1 call initialize clr SG_NOLOAD - clr RESELECT + and FLAGS,0x3f # !RESELECTING # As soon as we get a successful selection, the target should go # into the message out phase since we have ATN asserted. Prepare @@ -238,7 +253,8 @@ start_scb: mov A,SINDEX cmp MSG_START+0,A jne !message # did driver beat us? - mvi MSG_START+1 call mk_sdtr # build SDTR message if needed + test FLAGS,CHECK_DTR jz !message # Don't even bother with DTR? + mvi MSG_START+1 call mk_dtr # build DTR message if needed !message: @@ -286,7 +302,8 @@ reselect1: test SSTAT0,0x20 jz reselect1 # SELDI mov SELID call initialize - mvi RESELECT,0x80 # reselected, no IDENTIFY + and FLAGS,0x3f # reselected, no IDENTIFY + or FLAGS,RESELECTED # After the [re]selection, make sure that the [re]selection enable # bit is off. This chip is flaky enough without extra things @@ -495,7 +512,7 @@ p_mesgout5: p_mesgout6: mvi CLRSINT1,0x40 # CLRATNO - in case of PHASEMIS - clr MSG_FLAGS # no active msg + and FLAGS,0xdf # no active msg jmp ITloop # Message in phase. Bytes are read using Automatic PIO mode, but not @@ -528,9 +545,9 @@ p_mesgin: # before the command complete code tried processing it. test SCBARRAY+14,0xff jz status_ok # 0 Status? - call inb_last # ack & turn auto PIO back on mvi INTSTAT,STATUS_ERROR # let driver know - jmp start_scb + test FLAGS,SENSE jz status_ok + jmp p_mesgin_done status_ok: @@ -549,50 +566,48 @@ complete: mvi INTSTAT,0x02 # CMDCMPLT jmp p_mesgin_done -# Is it an extended message? We only support the synchronous data -# transfer request message, which will probably be in response to -# an SDTR message out from us. If it's not an SDTR, reject it - +# 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 - # apparently this can be done after any message in byte, according # to the SCSI-2 spec. # -# XXX - we should really reject this if we didn't initiate the SDTR -# negotiation; this may cause problems with unusual devices. -# p_mesgin1: cmp A,1 jne p_mesgin2 # extended message code? - mvi A call inb_next - cmp A,3 jne p_mesginN # extended mesg length = 3 - mvi A call inb_next - cmp A,1 jne p_mesginN # SDTR code + mvi ARG_1 call inb_next # extended message length + mvi A call inb_next # extended message code + cmp A,1 je p_mesginSDTR # Syncronous negotiation message + cmp A,3 je p_mesginWDTR # Wide negotiation message + jmp p_mesginN + +p_mesginWDTR: + cmp ARG_1,2 jne p_mesginN # extended mesg length = 2 + mvi A call inb_next # Width of bus + mvi INTSTAT,SIGNAL_WDTR # let driver know + test RETURN_1,0x80 jz p_mesgin_done# Do we need to send WDTR? + +# We didn't initiate the wide negotiation, so we must respond to the request + and RETURN_1,0x7f # Clear the SEND_WDTR Flag + or FLAGS,ACTIVE_MSG + mvi MSG_START+0 call mk_wdtr # build WDTR message + or SINDEX,0x10,SIGSTATE # turn on ATNO + call scsisig + jmp p_mesgin_done + +p_mesginSDTR: + cmp ARG_1,3 jne p_mesginN # extended mesg length = 3 mvi ARG_1 call inb_next # xfer period mvi A call inb_next # REQ/ACK offset mvi INTSTAT,SIGNAL_4 # call driver to convert - call ndx_sdtr # index sync config for target - mov DINDEX,SINDEX - not A # turn off "need sdtr" flag - test SBLKCTL,0x08 jnz p_mesgin1_b - test SCSIID,0x80 jnz p_mesgin1_b - and NEEDSDTR_A,A - jmp p_mesgin1_save + test RETURN_1,0x80 jz p_mesgin_done# Do we need to mk_sdtr? -p_mesgin1_b: - and NEEDSDTR_B,A - -p_mesgin1_save: - and A,0x80,SINDIR # get the WIDEXFER flag - or RETURN_1,A # Set WIDEXFER if necessary - mov DINDIR,RETURN_1 # save returned value - -# Even though the SCSI-2 specification says that a device responding -# to our SDTR message should honor our parameters for transmitting -# to us, it doesn't seem to work too well in real life. In particular, -# a lot of CD-ROM and tape units don't function: try using the SDTR -# parameters the device sent us for both transmitting and receiving. -# - mov SCSIRATE,RETURN_1 + or FLAGS,ACTIVE_MSG + mvi MSG_START+0 call mk_sdtr + or SINDEX,0x10,SIGSTATE # turn on ATNO + call scsisig jmp p_mesgin_done # Is it a disconnect message? Set a flag in the SCB to remind us @@ -638,17 +653,17 @@ p_mesgin5: # or the driver is trying to abort the command. Either way, something # untoward has happened and we should just leave it alone. # - test MSG_FLAGS,0x80 jnz p_mesgin_done + test FLAGS,ACTIVE_MSG jnz p_mesgin_done and SCBARRAY+0,0xfb # clear disconnect bit in SCB - mvi RESELECT,0xc0 # make note of IDENTIFY + or FLAGS,0xc0 # make note of IDENTIFY call sg_scb2ram # implied restore pointers # required on reselect jmp p_mesgin_done -# Message reject? If we have an outstanding SDTR negotiation, assume -# that it's a response from the target selecting asynchronous transfer, +# Message reject? If we have an outstanding WDTR or SDTR negotiation, assume +# that it's a response from the target selecting 8bit or asynchronous transfer, # otherwise just ignore it since we have no clue what it pertains to. # # XXX - I don't have a device that responds this way. Does this code @@ -662,27 +677,55 @@ p_mesgin6: test SBLKCTL,0x08 jnz p_mesgin6_b test SCSIID,0x80 jnz p_mesgin6_b - test NEEDSDTR_A,A jz p_mesgin_done # no - ignore rejection - call ndx_sdtr # note use of asynch xfer + test NEEDWDTR_A,A jnz clear_wdtr_a + test NEEDSDTR_A,A jnz clear_sdtr_a + jmp p_mesgin_done # no - ignore rejection + +clear_sdtr_a: + call ndx_dtr # note use of asynch xfer mov DINDEX,SINDEX - clr DINDIR + and DINDIR,0x80,SINDIR not A and NEEDSDTR_A,A - jmp p_mesgin6_done + jmp clear_sdtr_done + +clear_wdtr_a: + call ndx_dtr # note use of 8bit xfer + mov DINDEX,SINDEX + and DINDIR,0x7f,SINDIR + + not A + and NEEDWDTR_A,A + jmp clear_wdtr_done p_mesgin6_b: - test NEEDSDTR_B,A jz p_mesgin_done # no - ignore rejection - call ndx_sdtr # note use of asynch xfer + test NEEDWDTR_B,A jnz clear_wdtr_b + test NEEDSDTR_B,A jnz clear_sdtr_b + jmp p_mesgin_done # no - ignore rejection + +clear_wdtr_b: + call ndx_dtr # note use of 8bit xfer mov DINDEX,SINDEX - clr DINDIR + and DINDIR,0x7f,SINDIR + + not A + and NEEDWDTR_B,A + +clear_wdtr_done: + and SCSIRATE,0x7f # select 8bit xfer + jmp p_mesgin_done + +clear_sdtr_b: + call ndx_dtr # note use of asynch xfer + mov DINDEX,SINDEX + and DINDIR,0x80,SINDIR not A and NEEDSDTR_B,A -p_mesgin6_done: - - clr SCSIRATE # select asynch xfer +clear_sdtr_done: + and SCSIRATE,0xf0 # select asynch xfer jmp p_mesgin_done # [ ADD MORE MESSAGE HANDLING HERE ] @@ -731,9 +774,9 @@ bcopy: # mk_mesg: mvi SEQCTL,0x50 # PAUSEDIS|FASTMODE - test MSG_FLAGS,0x80 jnz mk_mesg1 # active message? + test FLAGS,ACTIVE_MSG jnz mk_mesg1 # active message? - mvi MSG_FLAGS,0x80 # if not, there is now + or FLAGS,ACTIVE_MSG # if not, there is now mvi MSG_LEN,1 # length = 1 mov MSG_START+0,SINDEX # 1-byte message @@ -839,7 +882,7 @@ dma2: dma3: test SINDEX,0x4 jnz dma5 # DIRECTION dma4: - test DFSTATUS,0x1 jz dma4 # FIFOEMP + test DFSTATUS,0x1 jz dma4 # !FIFOEMP # Now shut the DMA enables off, and copy STCNT (ie. the underrun # amount, if any) to the SCB registers; SG_COUNT will get copied to @@ -873,7 +916,7 @@ initialize_b: mvi SCSICONF_B jmp initialize_2 initialize_wide: - and A, 0xf,SCSICONF_B + and A,0x0f,SCSICONF_B # SCSI_ID_B[210] initialize_2: or SCSIID,A @@ -900,7 +943,7 @@ initialize_2: # STPWEN is 7870-specific, enabling an external termination power source. # and A,0x38,SINDIR # PARITY_ENB|SEL_TIM[10] - or SXFRCTL1,0x7,A # ENSTIMER|ACTNEGEN|STPWEN + or SXFRCTL1,0x7,A # ENSTIMER|ACTBEGEB|STPWEN mvi SIMODE1,0x84 # ENSELTIMO|ENSCSIPERR # Initialize scatter-gather pointers by setting up the working copy @@ -910,7 +953,7 @@ initialize_2: # Initialize SCSIRATE with the appropriate value for this target. # - call ndx_sdtr + call ndx_dtr mov SCSIRATE,SINDIR ret @@ -918,8 +961,8 @@ initialize_2: # message. # assert: - test RESELECT,0x80 jz assert1 # reselected? - test RESELECT,0x40 jnz assert1 # seen IDENTIFY? + test FLAGS,RESELECTED jz assert1 # reselected? + test FLAGS,IDENTIFY_SEEN jnz assert1 # seen IDENTIFY? mvi INTSTAT,SIGNAL_2 # no - cause a kernel panic @@ -1111,39 +1154,73 @@ sg_advance2: # is in SCSIID), and return the result in SINDEX. The accumulator # contains the 3->8 decoding of the target ID on return. # -ndx_sdtr: +ndx_dtr: shr A,SCSIID,4 - test SBLKCTL,0x08 jz ndx_sdtr_2 + test SBLKCTL,0x08 jz ndx_dtr_2 or A,0x08 # Channel B entries add 8 -ndx_sdtr_2: +ndx_dtr_2: add SINDEX,SYNCNEG,A and FUNCTION1,0x70,SCSIID # 3-bit target address decode mov A,FUNCTION1 ret -# If we need to negotiate transfer parameters, build the SDTR message +# If we need to negotiate transfer parameters, build the WDTR or SDTR message # starting at the address passed in SINDEX. DINDEX is modified on return. +# The SCSI-II spec requires that Wide negotiation occur first and you can +# only negotiat one or the other at a time otherwise in the event of a message +# reject, you wouldn't be able to tell which message was the culpret. # -mk_sdtr: +mk_dtr: mov DINDEX,SINDEX # save SINDEX - call ndx_sdtr - test SCBARRAY+1,0x88 jz mk_sdtr1_a - test NEEDSDTR_B,A jnz mk_sdtr1 # do we need negotiation? + call ndx_dtr + test SCBARRAY+1,0x88 jz mk_dtr_a + test NEEDWDTR_B,A jnz mk_wdtr_16 # do we need negotiation? + test NEEDSDTR_B,A jnz mk_sdtr ret -mk_sdtr1_a: - test NEEDSDTR_A,A jnz mk_sdtr1 # do we need negotiation? +mk_dtr_a: + test NEEDWDTR_A,A jnz mk_wdtr_16 # do we need negotiation? + test NEEDSDTR_A,A jnz mk_sdtr ret -mk_sdtr1: +mk_wdtr_16: + mvi ARG_1,1 # 16bit wide bus + +mk_wdtr: mvi DINDIR,1 # extended message - mvi DINDIR,3 # extended message length = 3 - mvi DINDIR,1 # SDTR code - mvi DINDIR,25 # REQ/ACK transfer period - mvi DINDIR,15 # REQ/ACK offset + mvi DINDIR,2 # extended message length = 2 + mvi DINDIR,3 # WDTR code + mov DINDIR,ARG_1 # bus width add MSG_LEN,-MSG_START+0,DINDEX # update message length ret + +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 # update message length + ret + +# Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag +# value + +#mk_tag: +# test SCBARRAY+0,0x10 jz mk_tag_done # Tag Enabled? +# and A,0x03,SCBARRYA+0 +# or A,0x20 +# mov DINDIR,A +# mov DINDIR,SCBPTR +# +# add MSG_LEN,-MSG_START+0,DINDEX # update message length + +#mk_tag_done: +# ret + # 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 @@ -1155,3 +1232,18 @@ mk_sdtr1: scsisig: mov SIGSTATE,SINDEX mov SCSISIGO,SINDEX ret + +sdtr_to_rate: + call ndx_dtr # index scratch space for target + shr A,SINDIR,0x4 + dec SINDEX #Preserve SINDEX + and A,0x7 + clr RETURN_1 +sdtr_to_rate_loop: + test A,0x0f jz sdtr_to_rate_done + add RETURN_1,0x18 + dec A + jmp sdtr_to_rate_loop +sdtr_to_rate_done: + shr RETURN_1,0x2 + add RETURN_1,0x18 ret