aic7xxx.seq revision 1.1 1 1.1 mycroft ##+M#########################################################################
2 1.1 mycroft # Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
3 1.1 mycroft #
4 1.1 mycroft # Copyright (c) 1994 John Aycock
5 1.1 mycroft # The University of Calgary Department of Computer Science.
6 1.1 mycroft # All rights reserved.
7 1.1 mycroft #
8 1.1 mycroft # Modifications/enhancements:
9 1.1 mycroft # Copyright (c) 1994, 1995 Justin Gibbs. All rights reserved.
10 1.1 mycroft #
11 1.1 mycroft # Redistribution and use in source and binary forms, with or without
12 1.1 mycroft # modification, are permitted provided that the following conditions
13 1.1 mycroft # are met:
14 1.1 mycroft # 1. Redistributions of source code must retain the above copyright
15 1.1 mycroft # notice, this list of conditions, and the following disclaimer.
16 1.1 mycroft # 2. Redistributions in binary form must reproduce the above copyright
17 1.1 mycroft # notice, this list of conditions and the following disclaimer in the
18 1.1 mycroft # documentation and/or other materials provided with the distribution.
19 1.1 mycroft # 3. All advertising materials mentioning features or use of this software
20 1.1 mycroft # must display the following acknowledgement:
21 1.1 mycroft # This product includes software developed by the University of Calgary
22 1.1 mycroft # Department of Computer Science and its contributors.
23 1.1 mycroft # 4. Neither the name of the University nor the names of its contributors
24 1.1 mycroft # may be used to endorse or promote products derived from this software
25 1.1 mycroft # without specific prior written permission.
26 1.1 mycroft #
27 1.1 mycroft # THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
28 1.1 mycroft # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 1.1 mycroft # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 1.1 mycroft # ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
31 1.1 mycroft # FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 1.1 mycroft # DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 1.1 mycroft # OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 1.1 mycroft # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 1.1 mycroft # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 1.1 mycroft # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 1.1 mycroft # SUCH DAMAGE.
38 1.1 mycroft #
39 1.1 mycroft # FreeBSD, Twin, Wide, 2 command per target support, tagged queuing and other
40 1.1 mycroft # optimizations provided by Justin T. Gibbs (gibbs (at] FreeBSD.org)
41 1.1 mycroft #
42 1.1 mycroft ##-M#########################################################################
43 1.1 mycroft
44 1.1 mycroft VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.1 1995/10/09 09:49:37 mycroft Exp $"
45 1.1 mycroft
46 1.1 mycroft SCBMASK = 0x1f
47 1.1 mycroft
48 1.1 mycroft SCSISEQ = 0x00
49 1.1 mycroft ENRSELI = 0x10
50 1.1 mycroft SXFRCTL0 = 0x01
51 1.1 mycroft SXFRCTL1 = 0x02
52 1.1 mycroft SCSISIGI = 0x03
53 1.1 mycroft SCSISIGO = 0x03
54 1.1 mycroft SCSIRATE = 0x04
55 1.1 mycroft SCSIID = 0x05
56 1.1 mycroft SCSIDATL = 0x06
57 1.1 mycroft STCNT = 0x08
58 1.1 mycroft STCNT+0 = 0x08
59 1.1 mycroft STCNT+1 = 0x09
60 1.1 mycroft STCNT+2 = 0x0a
61 1.1 mycroft CLRSINT0 = 0x0b
62 1.1 mycroft SSTAT0 = 0x0b
63 1.1 mycroft SELDO = 0x40
64 1.1 mycroft SELDI = 0x20
65 1.1 mycroft CLRSINT1 = 0x0c
66 1.1 mycroft SSTAT1 = 0x0c
67 1.1 mycroft SIMODE1 = 0x11
68 1.1 mycroft SCSIBUSL = 0x12
69 1.1 mycroft SHADDR = 0x14
70 1.1 mycroft SELID = 0x19
71 1.1 mycroft SBLKCTL = 0x1f
72 1.1 mycroft SEQCTL = 0x60
73 1.1 mycroft A = 0x64 # == ACCUM
74 1.1 mycroft SINDEX = 0x65
75 1.1 mycroft DINDEX = 0x66
76 1.1 mycroft ALLZEROS = 0x6a
77 1.1 mycroft NONE = 0x6a
78 1.1 mycroft SINDIR = 0x6c
79 1.1 mycroft DINDIR = 0x6d
80 1.1 mycroft FUNCTION1 = 0x6e
81 1.1 mycroft HADDR = 0x88
82 1.1 mycroft HADDR+1 = 0x89
83 1.1 mycroft HADDR+2 = 0x8a
84 1.1 mycroft HADDR+3 = 0x8b
85 1.1 mycroft HCNT = 0x8c
86 1.1 mycroft HCNT+0 = 0x8c
87 1.1 mycroft HCNT+1 = 0x8d
88 1.1 mycroft HCNT+2 = 0x8e
89 1.1 mycroft SCBPTR = 0x90
90 1.1 mycroft INTSTAT = 0x91
91 1.1 mycroft DFCNTRL = 0x93
92 1.1 mycroft DFSTATUS = 0x94
93 1.1 mycroft DFDAT = 0x99
94 1.1 mycroft QINFIFO = 0x9b
95 1.1 mycroft QINCNT = 0x9c
96 1.1 mycroft QOUTFIFO = 0x9d
97 1.1 mycroft
98 1.1 mycroft SCSICONF_A = 0x5a
99 1.1 mycroft SCSICONF_B = 0x5b
100 1.1 mycroft
101 1.1 mycroft # The two reserved bytes at SCBARRAY+1[23] are expected to be set to
102 1.1 mycroft # zero, and the reserved bit in SCBARRAY+0 is used as an internal flag
103 1.1 mycroft # to indicate whether or not to reload scatter-gather parameters after
104 1.1 mycroft # a disconnect. We also use bits 6 & 7 to indicate whether or not to
105 1.1 mycroft # initiate SDTR or WDTR repectively when starting this command.
106 1.1 mycroft #
107 1.1 mycroft SCBARRAY+0 = 0xa0
108 1.1 mycroft
109 1.1 mycroft DISCONNECTED = 0x04
110 1.1 mycroft NEEDDMA = 0x08
111 1.1 mycroft SG_LOAD = 0x10
112 1.1 mycroft TAG_ENB = 0x20
113 1.1 mycroft NEEDSDTR = 0x40
114 1.1 mycroft NEEDWDTR = 0x80
115 1.1 mycroft
116 1.1 mycroft SCBARRAY+1 = 0xa1
117 1.1 mycroft SCBARRAY+2 = 0xa2
118 1.1 mycroft SCBARRAY+3 = 0xa3
119 1.1 mycroft SCBARRAY+4 = 0xa4
120 1.1 mycroft SCBARRAY+5 = 0xa5
121 1.1 mycroft SCBARRAY+6 = 0xa6
122 1.1 mycroft SCBARRAY+7 = 0xa7
123 1.1 mycroft SCBARRAY+8 = 0xa8
124 1.1 mycroft SCBARRAY+9 = 0xa9
125 1.1 mycroft SCBARRAY+10 = 0xaa
126 1.1 mycroft SCBARRAY+11 = 0xab
127 1.1 mycroft SCBARRAY+12 = 0xac
128 1.1 mycroft SCBARRAY+13 = 0xad
129 1.1 mycroft SCBARRAY+14 = 0xae
130 1.1 mycroft SCBARRAY+15 = 0xaf
131 1.1 mycroft SCBARRAY+16 = 0xb0
132 1.1 mycroft SCBARRAY+17 = 0xb1
133 1.1 mycroft SCBARRAY+18 = 0xb2
134 1.1 mycroft SCBARRAY+19 = 0xb3
135 1.1 mycroft SCBARRAY+20 = 0xb4
136 1.1 mycroft SCBARRAY+21 = 0xb5
137 1.1 mycroft SCBARRAY+22 = 0xb6
138 1.1 mycroft SCBARRAY+23 = 0xb7
139 1.1 mycroft SCBARRAY+24 = 0xb8
140 1.1 mycroft SCBARRAY+25 = 0xb9
141 1.1 mycroft SCBARRAY+26 = 0xba
142 1.1 mycroft SCBARRAY+27 = 0xbb
143 1.1 mycroft SCBARRAY+28 = 0xbc
144 1.1 mycroft SCBARRAY+29 = 0xbd
145 1.1 mycroft SCBARRAY+30 = 0xbe
146 1.1 mycroft
147 1.1 mycroft BAD_PHASE = 0x01 # unknown scsi bus phase
148 1.1 mycroft CMDCMPLT = 0x02 # Command Complete
149 1.1 mycroft SEND_REJECT = 0x11 # sending a message reject
150 1.1 mycroft NO_IDENT = 0x21 # no IDENTIFY after reconnect
151 1.1 mycroft NO_MATCH = 0x31 # no cmd match for reconnect
152 1.1 mycroft MSG_SDTR = 0x41 # SDTR message recieved
153 1.1 mycroft MSG_WDTR = 0x51 # WDTR message recieved
154 1.1 mycroft MSG_REJECT = 0x61 # Reject message recieved
155 1.1 mycroft BAD_STATUS = 0x71 # Bad status from target
156 1.1 mycroft RESIDUAL = 0x81 # Residual byte count != 0
157 1.1 mycroft ABORT_TAG = 0x91 # Sent an ABORT_TAG message
158 1.1 mycroft
159 1.1 mycroft # The host adapter card (at least the BIOS) uses 20-2f for SCSI
160 1.1 mycroft # device information, 32-33 and 5a-5f as well. As it turns out, the
161 1.1 mycroft # BIOS trashes 20-2f, writing the synchronous negotiation results
162 1.1 mycroft # on top of the BIOS values, so we re-use those for our per-target
163 1.1 mycroft # scratchspace (actually a value that can be copied directly into
164 1.1 mycroft # SCSIRATE). The kernel driver will enable synchronous negotiation
165 1.1 mycroft # for all targets that have a value other than 0 in the lower four
166 1.1 mycroft # bits of the target scratch space. This should work irregardless of
167 1.1 mycroft # whether the bios has been installed. NEEDWDTR and NEEDSDTR are the top
168 1.1 mycroft # two bits of the SCB control byte. The kernel driver will set these
169 1.1 mycroft # when a WDTR or SDTR message should be sent to the target the SCB's
170 1.1 mycroft # command references.
171 1.1 mycroft #
172 1.1 mycroft # REJBYTE contains the first byte of a MESSAGE IN message, so the driver
173 1.1 mycroft # can report an intelligible error if a message is rejected.
174 1.1 mycroft #
175 1.1 mycroft # FLAGS's high bit is true if we are currently handling a reselect;
176 1.1 mycroft # its next-highest bit is true ONLY IF we've seen an IDENTIFY message
177 1.1 mycroft # from the reselecting target. If we haven't had IDENTIFY, then we have
178 1.1 mycroft # no idea what the lun is, and we can't select the right SCB register
179 1.1 mycroft # bank, so force a kernel panic if the target attempts a data in/out or
180 1.1 mycroft # command phase instead of corrupting something. FLAGS also contains
181 1.1 mycroft # configuration bits so that we can optimize for TWIN and WIDE controllers
182 1.1 mycroft # as well as the MAX_SYNC bit which we set when we want to negotiate for
183 1.1 mycroft # 10MHz irregardless of what the per target scratch space says.
184 1.1 mycroft #
185 1.1 mycroft # Note that SG_NEXT occupies four bytes.
186 1.1 mycroft #
187 1.1 mycroft SYNCNEG = 0x20
188 1.1 mycroft
189 1.1 mycroft REJBYTE = 0x31
190 1.1 mycroft DISC_DSB_A = 0x32
191 1.1 mycroft DISC_DSB_B = 0x33
192 1.1 mycroft
193 1.1 mycroft MSG_LEN = 0x34
194 1.1 mycroft MSG_START+0 = 0x35
195 1.1 mycroft MSG_START+1 = 0x36
196 1.1 mycroft MSG_START+2 = 0x37
197 1.1 mycroft MSG_START+3 = 0x38
198 1.1 mycroft MSG_START+4 = 0x39
199 1.1 mycroft MSG_START+5 = 0x3a
200 1.1 mycroft -MSG_START+0 = 0xcb # 2's complement of MSG_START+0
201 1.1 mycroft
202 1.1 mycroft ARG_1 = 0x4a # sdtr conversion args & return
203 1.1 mycroft BUS_16_BIT = 0x01
204 1.1 mycroft RETURN_1 = 0x4a
205 1.1 mycroft
206 1.1 mycroft SIGSTATE = 0x4b # value written to SCSISIGO
207 1.1 mycroft
208 1.1 mycroft # Linux users should use 0xc (12) for SG_SIZEOF
209 1.1 mycroft SG_SIZEOF = 0x8 # sizeof(struct ahc_dma)
210 1.1 mycroft #SG_SIZEOF = 0xc # sizeof(struct scatterlist)
211 1.1 mycroft SCB_SIZEOF = 0x13 # sizeof SCB to DMA (19 bytes)
212 1.1 mycroft
213 1.1 mycroft SG_NOLOAD = 0x4c # load SG pointer/length?
214 1.1 mycroft SG_COUNT = 0x4d # working value of SG count
215 1.1 mycroft SG_NEXT = 0x4e # working value of SG pointer
216 1.1 mycroft SG_NEXT+0 = 0x4e
217 1.1 mycroft SG_NEXT+1 = 0x4f
218 1.1 mycroft SG_NEXT+2 = 0x50
219 1.1 mycroft SG_NEXT+3 = 0x51
220 1.1 mycroft
221 1.1 mycroft SCBCOUNT = 0x52 # the actual number of SCBs
222 1.1 mycroft FLAGS = 0x53 # Device configuration flags
223 1.1 mycroft TWIN_BUS = 0x01
224 1.1 mycroft WIDE_BUS = 0x02
225 1.1 mycroft MAX_SYNC = 0x08
226 1.1 mycroft ACTIVE_MSG = 0x20
227 1.1 mycroft IDENTIFY_SEEN = 0x40
228 1.1 mycroft RESELECTED = 0x80
229 1.1 mycroft
230 1.1 mycroft ACTIVE_A = 0x54
231 1.1 mycroft ACTIVE_B = 0x55
232 1.1 mycroft SAVED_TCL = 0x56 # Temporary storage for the
233 1.1 mycroft # target/channel/lun of a
234 1.1 mycroft # reconnecting target
235 1.1 mycroft
236 1.1 mycroft # After starting the selection hardware, we return to the "poll_for_work"
237 1.1 mycroft # loop so that we can check for reconnecting targets as well as for our
238 1.1 mycroft # selection to complete just in case the reselection wins bus arbitration.
239 1.1 mycroft # The problem with this is that we must keep track of the SCB that we've
240 1.1 mycroft # already pulled from the QINFIFO and started the selection on just in case
241 1.1 mycroft # the reselection wins so that we can retry the selection at a later time.
242 1.1 mycroft # This problem cannot be resolved by holding a single entry in scratch
243 1.1 mycroft # ram since a reconnecting target can request sense and this will create
244 1.1 mycroft # yet another SCB waiting for selection. The solution used here is to
245 1.1 mycroft # use byte 31 of the SCB as a psuedo-next pointer and to thread a list
246 1.1 mycroft # of SCBs that are awaiting selection. Since 0 is a valid SCB offset,
247 1.1 mycroft # SCB_LIST_NULL is 0x10 which is out of range. The kernel driver must
248 1.1 mycroft # add an entry to this list everytime a request sense occurs. The sequencer
249 1.1 mycroft # will automatically consume the entries.
250 1.1 mycroft
251 1.1 mycroft WAITING_SCBH = 0x57 # head of list of SCBs awaiting
252 1.1 mycroft # selection
253 1.1 mycroft WAITING_SCBT = 0x58 # tail of list of SCBs awaiting
254 1.1 mycroft # selection
255 1.1 mycroft SCB_LIST_NULL = 0x10
256 1.1 mycroft
257 1.1 mycroft
258 1.1 mycroft # Poll QINCNT for work - the lower bits contain
259 1.1 mycroft # the number of entries in the Queue In FIFO.
260 1.1 mycroft #
261 1.1 mycroft start:
262 1.1 mycroft test WAITING_SCBH,SCB_LIST_NULL jz start_waiting
263 1.1 mycroft poll_for_work:
264 1.1 mycroft test FLAGS,TWIN_BUS jz start2 # Are we a twin channel device?
265 1.1 mycroft # For fairness, we check the other bus first, since we just finished a
266 1.1 mycroft # transaction on the current channel.
267 1.1 mycroft xor SBLKCTL,0x08 # Toggle to the other bus
268 1.1 mycroft test SSTAT0,SELDI jnz reselect
269 1.1 mycroft test SSTAT0,SELDO jnz select
270 1.1 mycroft xor SBLKCTL,0x08 # Toggle to the original bus
271 1.1 mycroft start2:
272 1.1 mycroft test SSTAT0,SELDI jnz reselect
273 1.1 mycroft test SSTAT0,SELDO jnz select
274 1.1 mycroft test WAITING_SCBH,SCB_LIST_NULL jz start_waiting
275 1.1 mycroft test QINCNT,SCBMASK jz poll_for_work
276 1.1 mycroft
277 1.1 mycroft # We have at least one queued SCB now and we don't have any
278 1.1 mycroft # SCBs in the list of SCBs awaiting selection. Set the SCB
279 1.1 mycroft # pointer from the FIFO so we see the right bank of SCB
280 1.1 mycroft # registers, then set SCSI options and set the initiator and
281 1.1 mycroft # target SCSI IDs.
282 1.1 mycroft #
283 1.1 mycroft mov SCBPTR,QINFIFO
284 1.1 mycroft
285 1.1 mycroft # If the control byte of this SCB has the NEEDDMA flag set, we have
286 1.1 mycroft # yet to DMA it from host memory
287 1.1 mycroft
288 1.1 mycroft test SCBARRAY+0,NEEDDMA jz test_busy
289 1.1 mycroft clr HCNT+2
290 1.1 mycroft clr HCNT+1
291 1.1 mycroft mvi HCNT+0,SCB_SIZEOF
292 1.1 mycroft
293 1.1 mycroft mvi DINDEX,HADDR
294 1.1 mycroft mvi SCBARRAY+26 call bcopy_4
295 1.1 mycroft
296 1.1 mycroft mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET
297 1.1 mycroft
298 1.1 mycroft # Wait for DMA from host memory to data FIFO to complete, then disable
299 1.1 mycroft # DMA and wait for it to acknowledge that it's off.
300 1.1 mycroft #
301 1.1 mycroft call dma_finish
302 1.1 mycroft
303 1.1 mycroft # Copy the SCB from the FIFO to the SCBARRAY
304 1.1 mycroft
305 1.1 mycroft mvi DINDEX, SCBARRAY+0
306 1.1 mycroft call bcopy_3_dfdat
307 1.1 mycroft call bcopy_4_dfdat
308 1.1 mycroft call bcopy_4_dfdat
309 1.1 mycroft call bcopy_4_dfdat
310 1.1 mycroft call bcopy_4_dfdat
311 1.1 mycroft
312 1.1 mycroft # See if there is not already an active SCB for this target. This code
313 1.1 mycroft # locks out on a per target basis instead of target/lun. Although this
314 1.1 mycroft # is not ideal for devices that have multiple luns active at the same
315 1.1 mycroft # time, it is faster than looping through all SCB's looking for active
316 1.1 mycroft # commands. It may be benificial to make findscb a more general procedure
317 1.1 mycroft # to see if the added cost of the search is negligible. This code also
318 1.1 mycroft # assumes that the kernel driver will clear the active flags on board
319 1.1 mycroft # initialization, board reset, and a target's SELTO.
320 1.1 mycroft
321 1.1 mycroft test_busy:
322 1.1 mycroft test SCBARRAY+0,0x20 jnz start_scb
323 1.1 mycroft and FUNCTION1,0x70,SCBARRAY+1
324 1.1 mycroft mov A,FUNCTION1
325 1.1 mycroft test SCBARRAY+1,0x88 jz test_a # Id < 8 && A channel
326 1.1 mycroft
327 1.1 mycroft test ACTIVE_B,A jnz requeue
328 1.1 mycroft or ACTIVE_B,A # Mark the current target as busy
329 1.1 mycroft jmp start_scb
330 1.1 mycroft
331 1.1 mycroft # Place the currently active back on the queue for later processing
332 1.1 mycroft requeue:
333 1.1 mycroft mov QINFIFO, SCBPTR
334 1.1 mycroft jmp poll_for_work
335 1.1 mycroft
336 1.1 mycroft # Pull the first entry off of the waiting for selection list
337 1.1 mycroft start_waiting:
338 1.1 mycroft mov SCBPTR,WAITING_SCBH
339 1.1 mycroft jmp start_scb
340 1.1 mycroft
341 1.1 mycroft test_a:
342 1.1 mycroft test ACTIVE_A,A jnz requeue
343 1.1 mycroft or ACTIVE_A,A # Mark the current target as busy
344 1.1 mycroft
345 1.1 mycroft start_scb:
346 1.1 mycroft and SINDEX,0xf7,SBLKCTL #Clear the channel select bit
347 1.1 mycroft and A,0x08,SCBARRAY+1 #Get new channel bit
348 1.1 mycroft or SINDEX,A
349 1.1 mycroft mov SBLKCTL,SINDEX # select channel
350 1.1 mycroft mov SCBARRAY+1 call initialize_scsiid
351 1.1 mycroft
352 1.1 mycroft # Enable selection phase as an initiator, and do automatic ATN
353 1.1 mycroft # after the selection. We do this now so that we can overlap the
354 1.1 mycroft # rest of our work to set up this target with the arbitration and
355 1.1 mycroft # selection bus phases.
356 1.1 mycroft #
357 1.1 mycroft start_selection:
358 1.1 mycroft or SCSISEQ,0x48 # ENSELO|ENAUTOATNO
359 1.1 mycroft mov WAITING_SCBH, SCBPTR
360 1.1 mycroft clr SG_NOLOAD
361 1.1 mycroft and FLAGS,0x3f # !RESELECTING
362 1.1 mycroft
363 1.1 mycroft # As soon as we get a successful selection, the target should go
364 1.1 mycroft # into the message out phase since we have ATN asserted. Prepare
365 1.1 mycroft # the message to send, locking out the device driver. If the device
366 1.1 mycroft # driver hasn't beaten us with an ABORT or RESET message, then tack
367 1.1 mycroft # on an SDTR negotiation if required.
368 1.1 mycroft #
369 1.1 mycroft # Messages are stored in scratch RAM starting with a flag byte (high bit
370 1.1 mycroft # set means active message), one length byte, and then the message itself.
371 1.1 mycroft #
372 1.1 mycroft mov SCBARRAY+1 call disconnect # disconnect ok?
373 1.1 mycroft
374 1.1 mycroft and SINDEX,0x7,SCBARRAY+1 # lun
375 1.1 mycroft or SINDEX,A # return value from disconnect
376 1.1 mycroft or SINDEX,0x80 call mk_mesg # IDENTIFY message
377 1.1 mycroft
378 1.1 mycroft mov A,SINDEX
379 1.1 mycroft test SCBARRAY+0,0xe0 jz !message # WDTR, SDTR or TAG??
380 1.1 mycroft cmp MSG_START+0,A jne !message # did driver beat us?
381 1.1 mycroft
382 1.1 mycroft # Tag Message if Tag enabled in SCB control block. Use SCBPTR as the tag
383 1.1 mycroft # value
384 1.1 mycroft
385 1.1 mycroft mk_tag:
386 1.1 mycroft mvi DINDEX, MSG_START+1
387 1.1 mycroft test SCBARRAY+0,TAG_ENB jz mk_tag_done
388 1.1 mycroft and A,0x23,SCBARRAY+0
389 1.1 mycroft mov DINDIR,A
390 1.1 mycroft mov DINDIR,SCBPTR
391 1.1 mycroft
392 1.1 mycroft add MSG_LEN,-MSG_START+0,DINDEX # update message length
393 1.1 mycroft
394 1.1 mycroft mk_tag_done:
395 1.1 mycroft
396 1.1 mycroft mov DINDEX call mk_dtr # build DTR message if needed
397 1.1 mycroft
398 1.1 mycroft !message:
399 1.1 mycroft jmp poll_for_work
400 1.1 mycroft
401 1.1 mycroft # Reselection has been initiated by a target. Make a note that we've been
402 1.1 mycroft # reselected, but haven't seen an IDENTIFY message from the target
403 1.1 mycroft # yet.
404 1.1 mycroft #
405 1.1 mycroft reselect:
406 1.1 mycroft mov SELID call initialize_scsiid
407 1.1 mycroft and FLAGS,0x3f # reselected, no IDENTIFY
408 1.1 mycroft or FLAGS,RESELECTED jmp select2
409 1.1 mycroft
410 1.1 mycroft # After the selection, remove this SCB from the "waiting for selection"
411 1.1 mycroft # list. This is achieved by simply moving our "next" pointer into
412 1.1 mycroft # WAITING_SCBH and setting our next pointer to null so that the next
413 1.1 mycroft # time this SCB is used, we don't get confused.
414 1.1 mycroft #
415 1.1 mycroft select:
416 1.1 mycroft or SCBARRAY+0,NEEDDMA
417 1.1 mycroft mov WAITING_SCBH,SCBARRAY+30
418 1.1 mycroft mvi SCBARRAY+30,SCB_LIST_NULL
419 1.1 mycroft select2:
420 1.1 mycroft call initialize_for_target
421 1.1 mycroft mvi SCSISEQ,ENRSELI
422 1.1 mycroft mvi CLRSINT0,0x60 # CLRSELDI|CLRSELDO
423 1.1 mycroft mvi CLRSINT1,0x8 # CLRBUSFREE
424 1.1 mycroft
425 1.1 mycroft # Main loop for information transfer phases. If BSY is false, then
426 1.1 mycroft # we have a bus free condition, expected or not. Otherwise, wait
427 1.1 mycroft # for the target to assert REQ before checking MSG, C/D and I/O
428 1.1 mycroft # for the bus phase.
429 1.1 mycroft #
430 1.1 mycroft # We can't simply look at the values of SCSISIGI here (if we want
431 1.1 mycroft # to do synchronous data transfer), because the target won't assert
432 1.1 mycroft # REQ if it's already sent us some data that we haven't acknowledged
433 1.1 mycroft # yet.
434 1.1 mycroft #
435 1.1 mycroft ITloop:
436 1.1 mycroft test SSTAT1,0x8 jnz p_busfree # BUSFREE
437 1.1 mycroft test SSTAT1,0x1 jz ITloop # REQINIT
438 1.1 mycroft
439 1.1 mycroft and A,0xe0,SCSISIGI # CDI|IOI|MSGI
440 1.1 mycroft
441 1.1 mycroft cmp ALLZEROS,A je p_dataout
442 1.1 mycroft cmp A,0x40 je p_datain
443 1.1 mycroft cmp A,0x80 je p_command
444 1.1 mycroft cmp A,0xc0 je p_status
445 1.1 mycroft cmp A,0xa0 je p_mesgout
446 1.1 mycroft cmp A,0xe0 je p_mesgin
447 1.1 mycroft
448 1.1 mycroft mvi INTSTAT,BAD_PHASE # unknown - signal driver
449 1.1 mycroft
450 1.1 mycroft p_dataout:
451 1.1 mycroft mvi 0 call scsisig # !CDO|!IOO|!MSGO
452 1.1 mycroft call assert
453 1.1 mycroft call sg_load
454 1.1 mycroft
455 1.1 mycroft mvi DINDEX,HADDR
456 1.1 mycroft mvi SCBARRAY+19 call bcopy_4
457 1.1 mycroft
458 1.1 mycroft # mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
459 1.1 mycroft mvi SCBARRAY+23 call bcopy_3
460 1.1 mycroft
461 1.1 mycroft mvi DINDEX,STCNT
462 1.1 mycroft mvi SCBARRAY+23 call bcopy_3
463 1.1 mycroft
464 1.1 mycroft # If we are the last SG block, don't set wideodd.
465 1.1 mycroft test SCBARRAY+18,0xff jnz p_dataout_wideodd
466 1.1 mycroft mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
467 1.1 mycroft # DIRECTION|FIFORESET
468 1.1 mycroft jmp p_dataout_rest
469 1.1 mycroft
470 1.1 mycroft p_dataout_wideodd:
471 1.1 mycroft mvi 0xbd call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
472 1.1 mycroft # DIRECTION|FIFORESET
473 1.1 mycroft
474 1.1 mycroft p_dataout_rest:
475 1.1 mycroft # After a DMA finishes, save the final transfer pointer and count
476 1.1 mycroft # back into the SCB, in case a device disconnects in the middle of
477 1.1 mycroft # a transfer. Use SHADDR and STCNT instead of HADDR and HCNT, since
478 1.1 mycroft # it's a reflection of how many bytes were transferred on the SCSI
479 1.1 mycroft # (as opposed to the host) bus.
480 1.1 mycroft #
481 1.1 mycroft mvi DINDEX,SCBARRAY+23
482 1.1 mycroft mvi STCNT call bcopy_3
483 1.1 mycroft
484 1.1 mycroft mvi DINDEX,SCBARRAY+19
485 1.1 mycroft mvi SHADDR call bcopy_4
486 1.1 mycroft
487 1.1 mycroft call sg_advance
488 1.1 mycroft mov SCBARRAY+18,SG_COUNT # residual S/G count
489 1.1 mycroft
490 1.1 mycroft jmp ITloop
491 1.1 mycroft
492 1.1 mycroft p_datain:
493 1.1 mycroft mvi 0x40 call scsisig # !CDO|IOO|!MSGO
494 1.1 mycroft call assert
495 1.1 mycroft call sg_load
496 1.1 mycroft
497 1.1 mycroft mvi DINDEX,HADDR
498 1.1 mycroft mvi SCBARRAY+19 call bcopy_4
499 1.1 mycroft
500 1.1 mycroft # mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
501 1.1 mycroft mvi SCBARRAY+23 call bcopy_3
502 1.1 mycroft
503 1.1 mycroft mvi DINDEX,STCNT
504 1.1 mycroft mvi SCBARRAY+23 call bcopy_3
505 1.1 mycroft
506 1.1 mycroft # If we are the last SG block, don't set wideodd.
507 1.1 mycroft test SCBARRAY+18,0xff jnz p_datain_wideodd
508 1.1 mycroft mvi 0x39 call dma # SCSIEN|SDMAEN|HDMAEN|
509 1.1 mycroft # !DIRECTION|FIFORESET
510 1.1 mycroft jmp p_datain_rest
511 1.1 mycroft p_datain_wideodd:
512 1.1 mycroft mvi 0xb9 call dma # WIDEODD|SCSIEN|SDMAEN|HDMAEN|
513 1.1 mycroft # !DIRECTION|FIFORESET
514 1.1 mycroft p_datain_rest:
515 1.1 mycroft mvi DINDEX,SCBARRAY+23
516 1.1 mycroft mvi STCNT call bcopy_3
517 1.1 mycroft
518 1.1 mycroft mvi DINDEX,SCBARRAY+19
519 1.1 mycroft mvi SHADDR call bcopy_4
520 1.1 mycroft
521 1.1 mycroft call sg_advance
522 1.1 mycroft mov SCBARRAY+18,SG_COUNT # residual S/G count
523 1.1 mycroft
524 1.1 mycroft jmp ITloop
525 1.1 mycroft
526 1.1 mycroft # Command phase. Set up the DMA registers and let 'er rip - the
527 1.1 mycroft # two bytes after the SCB SCSI_cmd_length are zeroed by the driver,
528 1.1 mycroft # so we can copy those three bytes directly into HCNT.
529 1.1 mycroft #
530 1.1 mycroft p_command:
531 1.1 mycroft mvi 0x80 call scsisig # CDO|!IOO|!MSGO
532 1.1 mycroft call assert
533 1.1 mycroft
534 1.1 mycroft mvi DINDEX,HADDR
535 1.1 mycroft mvi SCBARRAY+7 call bcopy_4
536 1.1 mycroft
537 1.1 mycroft # mvi DINDEX,HCNT # implicit since HCNT is next to HADDR
538 1.1 mycroft mvi SCBARRAY+11 call bcopy_3
539 1.1 mycroft
540 1.1 mycroft mvi DINDEX,STCNT
541 1.1 mycroft mvi SCBARRAY+11 call bcopy_3
542 1.1 mycroft
543 1.1 mycroft mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
544 1.1 mycroft # DIRECTION|FIFORESET
545 1.1 mycroft jmp ITloop
546 1.1 mycroft
547 1.1 mycroft # Status phase. Wait for the data byte to appear, then read it
548 1.1 mycroft # and store it into the SCB.
549 1.1 mycroft #
550 1.1 mycroft p_status:
551 1.1 mycroft mvi 0xc0 call scsisig # CDO|IOO|!MSGO
552 1.1 mycroft
553 1.1 mycroft mvi SCBARRAY+14 call inb_first
554 1.1 mycroft jmp p_mesgin_done
555 1.1 mycroft
556 1.1 mycroft # Message out phase. If there is no active message, but the target
557 1.1 mycroft # took us into this phase anyway, build a no-op message and send it.
558 1.1 mycroft #
559 1.1 mycroft p_mesgout:
560 1.1 mycroft mvi 0xa0 call scsisig # CDO|!IOO|MSGO
561 1.1 mycroft mvi 0x8 call mk_mesg # build NOP message
562 1.1 mycroft
563 1.1 mycroft clr STCNT+2
564 1.1 mycroft clr STCNT+1
565 1.1 mycroft
566 1.1 mycroft # Set up automatic PIO transfer from MSG_START. Bit 3 in
567 1.1 mycroft # SXFRCTL0 (SPIOEN) is already on.
568 1.1 mycroft #
569 1.1 mycroft mvi SINDEX,MSG_START+0
570 1.1 mycroft mov DINDEX,MSG_LEN
571 1.1 mycroft
572 1.1 mycroft # When target asks for a byte, drop ATN if it's the last one in
573 1.1 mycroft # the message. Otherwise, keep going until the message is exhausted.
574 1.1 mycroft # (We can't use outb for this since it wants the input in SINDEX.)
575 1.1 mycroft #
576 1.1 mycroft # Keep an eye out for a phase change, in case the target issues
577 1.1 mycroft # a MESSAGE REJECT.
578 1.1 mycroft #
579 1.1 mycroft p_mesgout2:
580 1.1 mycroft test SSTAT0,0x2 jz p_mesgout2 # SPIORDY
581 1.1 mycroft test SSTAT1,0x10 jnz p_mesgout6 # PHASEMIS
582 1.1 mycroft
583 1.1 mycroft cmp DINDEX,1 jne p_mesgout3 # last byte?
584 1.1 mycroft mvi CLRSINT1,0x40 # CLRATNO - drop ATN
585 1.1 mycroft
586 1.1 mycroft # Write a byte to the SCSI bus. The AIC-7770 refuses to automatically
587 1.1 mycroft # send ACKs in automatic PIO or DMA mode unless you make sure that the
588 1.1 mycroft # "expected" bus phase in SCSISIGO matches the actual bus phase. This
589 1.1 mycroft # behaviour is completely undocumented and caused me several days of
590 1.1 mycroft # grief.
591 1.1 mycroft #
592 1.1 mycroft # After plugging in different drives to test with and using a longer
593 1.1 mycroft # SCSI cable, I found that I/O in Automatic PIO mode ceased to function,
594 1.1 mycroft # especially when transferring >1 byte. It seems to be much more stable
595 1.1 mycroft # if STCNT is set to one before the transfer, and SDONE (in SSTAT0) is
596 1.1 mycroft # polled for transfer completion - for both output _and_ input. The
597 1.1 mycroft # only theory I have is that SPIORDY doesn't drop right away when SCSIDATL
598 1.1 mycroft # is accessed (like the documentation says it does), and that on a longer
599 1.1 mycroft # cable run, the sequencer code was fast enough to loop back and see
600 1.1 mycroft # an SPIORDY that hadn't dropped yet.
601 1.1 mycroft #
602 1.1 mycroft p_mesgout3:
603 1.1 mycroft mvi STCNT+0, 0x01
604 1.1 mycroft mov SCSIDATL,SINDIR
605 1.1 mycroft
606 1.1 mycroft p_mesgout4:
607 1.1 mycroft test SSTAT0,0x4 jz p_mesgout4 # SDONE
608 1.1 mycroft dec DINDEX
609 1.1 mycroft test DINDEX,0xff jnz p_mesgout2
610 1.1 mycroft
611 1.1 mycroft # If the next bus phase after ATN drops is a message out, it means
612 1.1 mycroft # that the target is requesting that the last message(s) be resent.
613 1.1 mycroft #
614 1.1 mycroft p_mesgout5:
615 1.1 mycroft test SSTAT1,0x8 jnz p_mesgout6 # BUSFREE
616 1.1 mycroft test SSTAT1,0x1 jz p_mesgout5 # REQINIT
617 1.1 mycroft
618 1.1 mycroft and A,0xe0,SCSISIGI # CDI|IOI|MSGI
619 1.1 mycroft cmp A,0xa0 jne p_mesgout6
620 1.1 mycroft mvi 0x10 call scsisig # ATNO - re-assert ATN
621 1.1 mycroft
622 1.1 mycroft jmp ITloop
623 1.1 mycroft
624 1.1 mycroft p_mesgout6:
625 1.1 mycroft mvi CLRSINT1,0x40 # CLRATNO - in case of PHASEMIS
626 1.1 mycroft and FLAGS,0xdf # no active msg
627 1.1 mycroft jmp ITloop
628 1.1 mycroft
629 1.1 mycroft # Message in phase. Bytes are read using Automatic PIO mode, but not
630 1.1 mycroft # using inb. This alleviates a race condition, namely that if ATN had
631 1.1 mycroft # to be asserted under Automatic PIO mode, it had to beat the SCSI
632 1.1 mycroft # circuitry sending an ACK to the target. This showed up under heavy
633 1.1 mycroft # loads and really confused things, since ABORT commands wouldn't be
634 1.1 mycroft # seen by the drive after an IDENTIFY message in until it had changed
635 1.1 mycroft # to a data I/O phase.
636 1.1 mycroft #
637 1.1 mycroft p_mesgin:
638 1.1 mycroft mvi 0xe0 call scsisig # CDO|IOO|MSGO
639 1.1 mycroft mvi A call inb_first # read the 1st message byte
640 1.1 mycroft mvi REJBYTE,A # save it for the driver
641 1.1 mycroft
642 1.1 mycroft cmp ALLZEROS,A jne p_mesgin1
643 1.1 mycroft
644 1.1 mycroft # We got a "command complete" message, so put the SCB pointer
645 1.1 mycroft # into the Queue Out, and trigger a completion interrupt.
646 1.1 mycroft # Check status for non zero return and interrupt driver if needed
647 1.1 mycroft # This allows the driver to interpret errors only when they occur
648 1.1 mycroft # instead of always uploading the scb. If the status is SCSI_CHECK,
649 1.1 mycroft # the driver will download a new scb requesting sense to replace
650 1.1 mycroft # the old one, modify the "waiting for selection" SCB list and set
651 1.1 mycroft # RETURN_1 to 0x80. If RETURN_1 is set to 0x80 the sequencer imediately
652 1.1 mycroft # jumps to main loop where it will run down the waiting SCB list.
653 1.1 mycroft # If the kernel driver does not wish to request sense, it need
654 1.1 mycroft # only clear RETURN_1, and the command is allowed to complete. We don't
655 1.1 mycroft # bother to post to the QOUTFIFO in the error case since it would require
656 1.1 mycroft # extra work in the kernel driver to ensure that the entry was removed
657 1.1 mycroft # before the command complete code tried processing it.
658 1.1 mycroft
659 1.1 mycroft # First check for residuals
660 1.1 mycroft test SCBARRAY+15,0xff jnz resid
661 1.1 mycroft test SCBARRAY+16,0xff jnz resid
662 1.1 mycroft test SCBARRAY+17,0xff jnz resid
663 1.1 mycroft
664 1.1 mycroft check_status:
665 1.1 mycroft test SCBARRAY+14,0xff jz status_ok # 0 Status?
666 1.1 mycroft mvi INTSTAT,BAD_STATUS # let driver know
667 1.1 mycroft test RETURN_1, 0x80 jz status_ok
668 1.1 mycroft jmp p_mesgin_done
669 1.1 mycroft
670 1.1 mycroft status_ok:
671 1.1 mycroft # First, mark this target as free.
672 1.1 mycroft test SCBARRAY+0,0x20 jnz complete # Tagged command
673 1.1 mycroft and FUNCTION1,0x70,SCBARRAY+1
674 1.1 mycroft mov A,FUNCTION1
675 1.1 mycroft test SCBARRAY+1,0x88 jz clear_a
676 1.1 mycroft xor ACTIVE_B,A
677 1.1 mycroft jmp complete
678 1.1 mycroft
679 1.1 mycroft clear_a:
680 1.1 mycroft xor ACTIVE_A,A
681 1.1 mycroft
682 1.1 mycroft complete:
683 1.1 mycroft mov QOUTFIFO,SCBPTR
684 1.1 mycroft mvi INTSTAT,CMDCMPLT
685 1.1 mycroft jmp p_mesgin_done
686 1.1 mycroft
687 1.1 mycroft # If we have a residual count, interrupt and tell the host. Other
688 1.1 mycroft # alternatives are to pause the sequencer on all command completes (yuck),
689 1.1 mycroft # dma the resid directly to the host (slick, but a ton of instructions), or
690 1.1 mycroft # have the sequencer pause itself when it encounters a non-zero resid
691 1.1 mycroft # (unecessary pause just to flag the command -- yuck, but takes few instructions
692 1.1 mycroft # and since it shouldn't happen that often is good enough for our purposes).
693 1.1 mycroft
694 1.1 mycroft resid:
695 1.1 mycroft mvi INTSTAT,RESIDUAL
696 1.1 mycroft jmp check_status
697 1.1 mycroft
698 1.1 mycroft # Is it an extended message? We only support the synchronous and wide data
699 1.1 mycroft # transfer request messages, which will probably be in response to
700 1.1 mycroft # WDTR or SDTR message outs from us. If it's not SDTR or WDTR, reject it -
701 1.1 mycroft # apparently this can be done after any message in byte, according
702 1.1 mycroft # to the SCSI-2 spec.
703 1.1 mycroft #
704 1.1 mycroft p_mesgin1:
705 1.1 mycroft cmp A,1 jne p_mesgin2 # extended message code?
706 1.1 mycroft
707 1.1 mycroft mvi ARG_1 call inb_next # extended message length
708 1.1 mycroft mvi A call inb_next # extended message code
709 1.1 mycroft
710 1.1 mycroft cmp A,1 je p_mesginSDTR # Syncronous negotiation message
711 1.1 mycroft cmp A,3 je p_mesginWDTR # Wide negotiation message
712 1.1 mycroft jmp p_mesginN
713 1.1 mycroft
714 1.1 mycroft p_mesginWDTR:
715 1.1 mycroft cmp ARG_1,2 jne p_mesginN # extended mesg length = 2
716 1.1 mycroft mvi A call inb_next # Width of bus
717 1.1 mycroft mvi INTSTAT,MSG_WDTR # let driver know
718 1.1 mycroft test RETURN_1,0x80 jz p_mesgin_done# Do we need to send WDTR?
719 1.1 mycroft
720 1.1 mycroft # We didn't initiate the wide negotiation, so we must respond to the request
721 1.1 mycroft and RETURN_1,0x7f # Clear the SEND_WDTR Flag
722 1.1 mycroft or FLAGS,ACTIVE_MSG
723 1.1 mycroft mvi DINDEX,MSG_START+0
724 1.1 mycroft mvi MSG_START+0 call mk_wdtr # build WDTR message
725 1.1 mycroft or SINDEX,0x10,SIGSTATE # turn on ATNO
726 1.1 mycroft call scsisig
727 1.1 mycroft jmp p_mesgin_done
728 1.1 mycroft
729 1.1 mycroft p_mesginSDTR:
730 1.1 mycroft cmp ARG_1,3 jne p_mesginN # extended mesg length = 3
731 1.1 mycroft mvi ARG_1 call inb_next # xfer period
732 1.1 mycroft mvi A call inb_next # REQ/ACK offset
733 1.1 mycroft mvi INTSTAT,MSG_SDTR # call driver to convert
734 1.1 mycroft
735 1.1 mycroft test RETURN_1,0xc0 jz p_mesgin_done# Do we need to mk_sdtr or rej?
736 1.1 mycroft test RETURN_1,0x40 jnz p_mesginN # Requested SDTR too small - rej
737 1.1 mycroft or FLAGS,ACTIVE_MSG
738 1.1 mycroft mvi DINDEX, MSG_START+0
739 1.1 mycroft mvi MSG_START+0 call mk_sdtr
740 1.1 mycroft or SINDEX,0x10,SIGSTATE # turn on ATNO
741 1.1 mycroft call scsisig
742 1.1 mycroft jmp p_mesgin_done
743 1.1 mycroft
744 1.1 mycroft # Is it a disconnect message? Set a flag in the SCB to remind us
745 1.1 mycroft # and await the bus going free.
746 1.1 mycroft #
747 1.1 mycroft p_mesgin2:
748 1.1 mycroft cmp A,4 jne p_mesgin3 # disconnect code?
749 1.1 mycroft
750 1.1 mycroft or SCBARRAY+0,0x4 # set "disconnected" bit
751 1.1 mycroft jmp p_mesgin_done
752 1.1 mycroft
753 1.1 mycroft # Save data pointers message? Copy working values into the SCB,
754 1.1 mycroft # usually in preparation for a disconnect.
755 1.1 mycroft #
756 1.1 mycroft p_mesgin3:
757 1.1 mycroft cmp A,2 jne p_mesgin4 # save data pointers code?
758 1.1 mycroft
759 1.1 mycroft call sg_ram2scb
760 1.1 mycroft jmp p_mesgin_done
761 1.1 mycroft
762 1.1 mycroft # Restore pointers message? Data pointers are recopied from the
763 1.1 mycroft # SCB anyway at the start of any DMA operation, so the only thing
764 1.1 mycroft # to copy is the scatter-gather values.
765 1.1 mycroft #
766 1.1 mycroft p_mesgin4:
767 1.1 mycroft cmp A,3 jne p_mesgin5 # restore pointers code?
768 1.1 mycroft
769 1.1 mycroft call sg_scb2ram
770 1.1 mycroft jmp p_mesgin_done
771 1.1 mycroft
772 1.1 mycroft # Identify message? For a reconnecting target, this tells us the lun
773 1.1 mycroft # that the reconnection is for - find the correct SCB and switch to it,
774 1.1 mycroft # clearing the "disconnected" bit so we don't "find" it by accident later.
775 1.1 mycroft #
776 1.1 mycroft p_mesgin5:
777 1.1 mycroft test A,0x80 jz p_mesgin6 # identify message?
778 1.1 mycroft
779 1.1 mycroft test A,0x78 jnz p_mesginN # !DiscPriv|!LUNTAR|!Reserved
780 1.1 mycroft
781 1.1 mycroft and A,0x07 # lun in lower three bits
782 1.1 mycroft or SAVED_TCL,A,SELID
783 1.1 mycroft and SAVED_TCL,0xf7
784 1.1 mycroft and A,0x08,SBLKCTL # B Channel??
785 1.1 mycroft or SAVED_TCL,A
786 1.1 mycroft call inb_last # ACK
787 1.1 mycroft mov ALLZEROS call findSCB
788 1.1 mycroft setup_SCB:
789 1.1 mycroft and SCBARRAY+0,0xfb # clear disconnect bit in SCB
790 1.1 mycroft or FLAGS,IDENTIFY_SEEN # make note of IDENTIFY
791 1.1 mycroft
792 1.1 mycroft call sg_scb2ram # implied restore pointers
793 1.1 mycroft # required on reselect
794 1.1 mycroft jmp ITloop
795 1.1 mycroft get_tag:
796 1.1 mycroft mvi A call inb_first
797 1.1 mycroft cmp A,0x20 jne return # Simple Tag message?
798 1.1 mycroft mvi A call inb_next
799 1.1 mycroft call inb_last
800 1.1 mycroft test A,0xf0 jnz abort_tag # Tag in range?
801 1.1 mycroft mov SCBPTR,A
802 1.1 mycroft mov A,SAVED_TCL
803 1.1 mycroft cmp SCBARRAY+1,A jne abort_tag
804 1.1 mycroft test SCBARRAY+0,TAG_ENB jz abort_tag
805 1.1 mycroft ret
806 1.1 mycroft abort_tag:
807 1.1 mycroft or SINDEX,0x10,SIGSTATE # turn on ATNO
808 1.1 mycroft call scsisig
809 1.1 mycroft mvi INTSTAT,ABORT_TAG # let driver know
810 1.1 mycroft mvi 0xd call mk_mesg # ABORT TAG message
811 1.1 mycroft ret
812 1.1 mycroft
813 1.1 mycroft # Message reject? Let the kernel driver handle this. If we have an
814 1.1 mycroft # outstanding WDTR or SDTR negotiation, assume that it's a response from
815 1.1 mycroft # the target selecting 8bit or asynchronous transfer, otherwise just ignore
816 1.1 mycroft # it since we have no clue what it pertains to.
817 1.1 mycroft #
818 1.1 mycroft p_mesgin6:
819 1.1 mycroft cmp A,7 jne p_mesgin7 # message reject code?
820 1.1 mycroft
821 1.1 mycroft mvi INTSTAT, MSG_REJECT
822 1.1 mycroft jmp p_mesgin_done
823 1.1 mycroft
824 1.1 mycroft # [ ADD MORE MESSAGE HANDLING HERE ]
825 1.1 mycroft #
826 1.1 mycroft p_mesgin7:
827 1.1 mycroft
828 1.1 mycroft # We have no idea what this message in is, and there's no way
829 1.1 mycroft # to pass it up to the kernel, so we issue a message reject and
830 1.1 mycroft # hope for the best. Since we're now using manual PIO mode to
831 1.1 mycroft # read in the message, there should no longer be a race condition
832 1.1 mycroft # present when we assert ATN. In any case, rejection should be a
833 1.1 mycroft # rare occurrence - signal the driver when it happens.
834 1.1 mycroft #
835 1.1 mycroft p_mesginN:
836 1.1 mycroft or SINDEX,0x10,SIGSTATE # turn on ATNO
837 1.1 mycroft call scsisig
838 1.1 mycroft mvi INTSTAT,SEND_REJECT # let driver know
839 1.1 mycroft
840 1.1 mycroft mvi 0x7 call mk_mesg # MESSAGE REJECT message
841 1.1 mycroft
842 1.1 mycroft p_mesgin_done:
843 1.1 mycroft call inb_last # ack & turn auto PIO back on
844 1.1 mycroft jmp ITloop
845 1.1 mycroft
846 1.1 mycroft
847 1.1 mycroft # Bus free phase. It might be useful to interrupt the device
848 1.1 mycroft # driver if we aren't expecting this. For now, make sure that
849 1.1 mycroft # ATN isn't being asserted and look for a new command.
850 1.1 mycroft #
851 1.1 mycroft p_busfree:
852 1.1 mycroft mvi CLRSINT1,0x40 # CLRATNO
853 1.1 mycroft clr SIGSTATE
854 1.1 mycroft jmp start
855 1.1 mycroft
856 1.1 mycroft # Instead of a generic bcopy routine that requires an argument, we unroll
857 1.1 mycroft # the two cases that are actually used, and call them explicitly. This
858 1.1 mycroft # not only reduces the overhead of doing a bcopy by 2/3rds, but ends up
859 1.1 mycroft # saving space in the program since you don't have to put the argument
860 1.1 mycroft # into the accumulator before the call. Both functions expect DINDEX to
861 1.1 mycroft # contain the destination address and SINDEX to contain the source
862 1.1 mycroft # address.
863 1.1 mycroft bcopy_3:
864 1.1 mycroft mov DINDIR,SINDIR
865 1.1 mycroft mov DINDIR,SINDIR
866 1.1 mycroft mov DINDIR,SINDIR ret
867 1.1 mycroft
868 1.1 mycroft bcopy_4:
869 1.1 mycroft mov DINDIR,SINDIR
870 1.1 mycroft mov DINDIR,SINDIR
871 1.1 mycroft mov DINDIR,SINDIR
872 1.1 mycroft mov DINDIR,SINDIR ret
873 1.1 mycroft
874 1.1 mycroft bcopy_3_dfdat:
875 1.1 mycroft mov DINDIR,DFDAT
876 1.1 mycroft mov DINDIR,DFDAT
877 1.1 mycroft mov DINDIR,DFDAT ret
878 1.1 mycroft
879 1.1 mycroft bcopy_4_dfdat:
880 1.1 mycroft mov DINDIR,DFDAT
881 1.1 mycroft mov DINDIR,DFDAT
882 1.1 mycroft mov DINDIR,DFDAT
883 1.1 mycroft mov DINDIR,DFDAT ret
884 1.1 mycroft
885 1.1 mycroft # Locking the driver out, build a one-byte message passed in SINDEX
886 1.1 mycroft # if there is no active message already. SINDEX is returned intact.
887 1.1 mycroft #
888 1.1 mycroft mk_mesg:
889 1.1 mycroft mvi SEQCTL,0x50 # PAUSEDIS|FASTMODE
890 1.1 mycroft test FLAGS,ACTIVE_MSG jnz mk_mesg1 # active message?
891 1.1 mycroft
892 1.1 mycroft or FLAGS,ACTIVE_MSG # if not, there is now
893 1.1 mycroft mvi MSG_LEN,1 # length = 1
894 1.1 mycroft mov MSG_START+0,SINDEX # 1-byte message
895 1.1 mycroft
896 1.1 mycroft mk_mesg1:
897 1.1 mycroft mvi SEQCTL,0x10 ret # !PAUSEDIS|FASTMODE
898 1.1 mycroft
899 1.1 mycroft # Carefully read data in Automatic PIO mode. I first tried this using
900 1.1 mycroft # Manual PIO mode, but it gave me continual underrun errors, probably
901 1.1 mycroft # indicating that I did something wrong, but I feel more secure leaving
902 1.1 mycroft # Automatic PIO on all the time.
903 1.1 mycroft #
904 1.1 mycroft # According to Adaptec's documentation, an ACK is not sent on input from
905 1.1 mycroft # the target until SCSIDATL is read from. So we wait until SCSIDATL is
906 1.1 mycroft # latched (the usual way), then read the data byte directly off the bus
907 1.1 mycroft # using SCSIBUSL. When we have pulled the ATN line, or we just want to
908 1.1 mycroft # acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
909 1.1 mycroft # spec guarantees that the target will hold the data byte on the bus until
910 1.1 mycroft # we send our ACK.
911 1.1 mycroft #
912 1.1 mycroft # The assumption here is that these are called in a particular sequence,
913 1.1 mycroft # and that REQ is already set when inb_first is called. inb_{first,next}
914 1.1 mycroft # use the same calling convention as inb.
915 1.1 mycroft #
916 1.1 mycroft inb_first:
917 1.1 mycroft clr STCNT+2
918 1.1 mycroft clr STCNT+1
919 1.1 mycroft mov DINDEX,SINDEX
920 1.1 mycroft mov DINDIR,SCSIBUSL ret # read byte directly from bus
921 1.1 mycroft
922 1.1 mycroft inb_next:
923 1.1 mycroft mov DINDEX,SINDEX # save SINDEX
924 1.1 mycroft
925 1.1 mycroft mvi STCNT+0,1 # xfer one byte
926 1.1 mycroft mov NONE,SCSIDATL # dummy read from latch to ACK
927 1.1 mycroft inb_next1:
928 1.1 mycroft test SSTAT0,0x4 jz inb_next1 # SDONE
929 1.1 mycroft inb_next2:
930 1.1 mycroft test SSTAT0,0x2 jz inb_next2 # SPIORDY - wait for next byte
931 1.1 mycroft mov DINDIR,SCSIBUSL ret # read byte directly from bus
932 1.1 mycroft
933 1.1 mycroft inb_last:
934 1.1 mycroft mvi STCNT+0,1 # ACK with dummy read
935 1.1 mycroft mov NONE,SCSIDATL
936 1.1 mycroft inb_last1:
937 1.1 mycroft test SSTAT0,0x4 jz inb_last1 # wait for completion
938 1.1 mycroft ret
939 1.1 mycroft
940 1.1 mycroft # DMA data transfer. HADDR and HCNT must be loaded first, and
941 1.1 mycroft # SINDEX should contain the value to load DFCNTRL with - 0x3d for
942 1.1 mycroft # host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
943 1.1 mycroft # during initialization.
944 1.1 mycroft #
945 1.1 mycroft dma:
946 1.1 mycroft mov DFCNTRL,SINDEX
947 1.1 mycroft dma1:
948 1.1 mycroft dma2:
949 1.1 mycroft test SSTAT0,0x1 jnz dma3 # DMADONE
950 1.1 mycroft test SSTAT1,0x10 jz dma1 # PHASEMIS, ie. underrun
951 1.1 mycroft
952 1.1 mycroft # We will be "done" DMAing when the transfer count goes to zero, or
953 1.1 mycroft # the target changes the phase (in light of this, it makes sense that
954 1.1 mycroft # the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
955 1.1 mycroft # doing a SCSI->Host transfer, the data FIFO should be flushed auto-
956 1.1 mycroft # magically on STCNT=0 or a phase change, so just wait for FIFO empty
957 1.1 mycroft # status.
958 1.1 mycroft #
959 1.1 mycroft dma3:
960 1.1 mycroft test SINDEX,0x4 jnz dma5 # DIRECTION
961 1.1 mycroft dma4:
962 1.1 mycroft test DFSTATUS,0x1 jz dma4 # !FIFOEMP
963 1.1 mycroft
964 1.1 mycroft # Now shut the DMA enables off, and copy STCNT (ie. the underrun
965 1.1 mycroft # amount, if any) to the SCB registers; SG_COUNT will get copied to
966 1.1 mycroft # the SCB's residual S/G count field after sg_advance is called. Make
967 1.1 mycroft # sure that the DMA enables are actually off first lest we get an ILLSADDR.
968 1.1 mycroft #
969 1.1 mycroft dma5:
970 1.1 mycroft clr DFCNTRL # disable DMA
971 1.1 mycroft dma6:
972 1.1 mycroft test DFCNTRL,0x38 jnz dma6 # SCSIENACK|SDMAENACK|HDMAENACK
973 1.1 mycroft
974 1.1 mycroft mvi DINDEX,SCBARRAY+15
975 1.1 mycroft mvi STCNT call bcopy_3
976 1.1 mycroft
977 1.1 mycroft ret
978 1.1 mycroft
979 1.1 mycroft dma_finish:
980 1.1 mycroft test DFSTATUS,0x8 jz dma_finish # HDONE
981 1.1 mycroft
982 1.1 mycroft clr DFCNTRL # disable DMA
983 1.1 mycroft dma_finish2:
984 1.1 mycroft test DFCNTRL,0x8 jnz dma_finish2 # HDMAENACK
985 1.1 mycroft ret
986 1.1 mycroft
987 1.1 mycroft # Common SCSI initialization for selection and reselection. Expects
988 1.1 mycroft # the target SCSI ID to be in the upper four bits of SINDEX, and A's
989 1.1 mycroft # contents are stomped on return.
990 1.1 mycroft #
991 1.1 mycroft initialize_scsiid:
992 1.1 mycroft and SINDEX,0xf0 # Get target ID
993 1.1 mycroft and A,0x0f,SCSIID
994 1.1 mycroft or SINDEX,A
995 1.1 mycroft mov SCSIID,SINDEX ret
996 1.1 mycroft
997 1.1 mycroft initialize_for_target:
998 1.1 mycroft # Turn on Automatic PIO mode now, before we expect to see a REQ
999 1.1 mycroft # from the target. It shouldn't hurt anything to leave it on. Set
1000 1.1 mycroft # CLRCHN here before the target has entered a data transfer mode -
1001 1.1 mycroft # with synchronous SCSI, if you do it later, you blow away some
1002 1.1 mycroft # data in the SCSI FIFO that the target has already sent to you.
1003 1.1 mycroft #
1004 1.1 mycroft clr SIGSTATE
1005 1.1 mycroft
1006 1.1 mycroft mvi SXFRCTL0,0x8a # DFON|SPIOEN|CLRCHN
1007 1.1 mycroft
1008 1.1 mycroft # Initialize scatter-gather pointers by setting up the working copy
1009 1.1 mycroft # in scratch RAM.
1010 1.1 mycroft #
1011 1.1 mycroft call sg_scb2ram
1012 1.1 mycroft
1013 1.1 mycroft # Initialize SCSIRATE with the appropriate value for this target.
1014 1.1 mycroft #
1015 1.1 mycroft call ndx_dtr
1016 1.1 mycroft mov SCSIRATE,SINDIR ret
1017 1.1 mycroft
1018 1.1 mycroft # Assert that if we've been reselected, then we've seen an IDENTIFY
1019 1.1 mycroft # message.
1020 1.1 mycroft #
1021 1.1 mycroft assert:
1022 1.1 mycroft test FLAGS,RESELECTED jz return # reselected?
1023 1.1 mycroft test FLAGS,IDENTIFY_SEEN jnz return # seen IDENTIFY?
1024 1.1 mycroft
1025 1.1 mycroft mvi INTSTAT,NO_IDENT ret # no - cause a kernel panic
1026 1.1 mycroft
1027 1.1 mycroft # Find out if disconnection is ok from the information the BIOS has left
1028 1.1 mycroft # us. The tcl from SCBARRAY+1 should be in SINDEX; A will
1029 1.1 mycroft # contain either 0x40 (disconnection ok) or 0x00 (disconnection not ok)
1030 1.1 mycroft # on exit.
1031 1.1 mycroft #
1032 1.1 mycroft # To allow for wide or twin busses, we check the upper bit of the target ID
1033 1.1 mycroft # and the channel ID and look at the appropriate disconnect register.
1034 1.1 mycroft #
1035 1.1 mycroft disconnect:
1036 1.1 mycroft and FUNCTION1,0x70,SINDEX # strip off extra just in case
1037 1.1 mycroft mov A,FUNCTION1
1038 1.1 mycroft test SINDEX, 0x88 jz disconnect_a
1039 1.1 mycroft
1040 1.1 mycroft test DISC_DSB_B,A jz disconnect1 # bit nonzero if DISabled
1041 1.1 mycroft clr A ret
1042 1.1 mycroft
1043 1.1 mycroft disconnect_a:
1044 1.1 mycroft test DISC_DSB_A,A jz disconnect1 # bit nonzero if DISabled
1045 1.1 mycroft clr A ret
1046 1.1 mycroft
1047 1.1 mycroft disconnect1:
1048 1.1 mycroft mvi A,0x40 ret
1049 1.1 mycroft
1050 1.1 mycroft # Locate the SCB matching the target ID/channel/lun in SAVED_TCL and switch
1051 1.1 mycroft # the SCB to it. Have the kernel print a warning message if it can't be
1052 1.1 mycroft # found, and generate an ABORT message to the target. SINDEX should be
1053 1.1 mycroft # cleared on call.
1054 1.1 mycroft #
1055 1.1 mycroft findSCB:
1056 1.1 mycroft mov A,SAVED_TCL
1057 1.1 mycroft mov SCBPTR,SINDEX # switch to new SCB
1058 1.1 mycroft cmp SCBARRAY+1,A jne findSCB1 # target ID/channel/lun match?
1059 1.1 mycroft test SCBARRAY+0,0x4 jz findSCB1 # should be disconnected
1060 1.1 mycroft test SCBARRAY+0,TAG_ENB jnz get_tag
1061 1.1 mycroft ret
1062 1.1 mycroft
1063 1.1 mycroft findSCB1:
1064 1.1 mycroft inc SINDEX
1065 1.1 mycroft mov A,SCBCOUNT
1066 1.1 mycroft cmp SINDEX,A jne findSCB
1067 1.1 mycroft
1068 1.1 mycroft mvi INTSTAT,NO_MATCH # not found - signal kernel
1069 1.1 mycroft mvi 0x6 call mk_mesg # ABORT message
1070 1.1 mycroft
1071 1.1 mycroft or SINDEX,0x10,SIGSTATE # assert ATNO
1072 1.1 mycroft call scsisig
1073 1.1 mycroft ret
1074 1.1 mycroft
1075 1.1 mycroft # Make a working copy of the scatter-gather parameters in the SCB.
1076 1.1 mycroft #
1077 1.1 mycroft sg_scb2ram:
1078 1.1 mycroft mov SG_COUNT,SCBARRAY+2
1079 1.1 mycroft
1080 1.1 mycroft mvi DINDEX,SG_NEXT
1081 1.1 mycroft mvi SCBARRAY+3 call bcopy_4
1082 1.1 mycroft
1083 1.1 mycroft mvi SG_NOLOAD,0x80
1084 1.1 mycroft test SCBARRAY+0,0x10 jnz return # don't reload s/g?
1085 1.1 mycroft clr SG_NOLOAD ret
1086 1.1 mycroft
1087 1.1 mycroft # Copying RAM values back to SCB, for Save Data Pointers message.
1088 1.1 mycroft #
1089 1.1 mycroft sg_ram2scb:
1090 1.1 mycroft mov SCBARRAY+2,SG_COUNT
1091 1.1 mycroft
1092 1.1 mycroft mvi DINDEX,SCBARRAY+3
1093 1.1 mycroft mvi SG_NEXT call bcopy_4
1094 1.1 mycroft
1095 1.1 mycroft and SCBARRAY+0,0xef,SCBARRAY+0
1096 1.1 mycroft test SG_NOLOAD,0x80 jz return # reload s/g?
1097 1.1 mycroft or SCBARRAY+0,SG_LOAD ret
1098 1.1 mycroft
1099 1.1 mycroft # Load a struct scatter if needed and set up the data address and
1100 1.1 mycroft # length. If the working value of the SG count is nonzero, then
1101 1.1 mycroft # we need to load a new set of values.
1102 1.1 mycroft #
1103 1.1 mycroft # This, like the above DMA, assumes a little-endian host data storage.
1104 1.1 mycroft #
1105 1.1 mycroft sg_load:
1106 1.1 mycroft test SG_COUNT,0xff jz return # SG being used?
1107 1.1 mycroft test SG_NOLOAD,0x80 jnz return # don't reload s/g?
1108 1.1 mycroft
1109 1.1 mycroft clr HCNT+2
1110 1.1 mycroft clr HCNT+1
1111 1.1 mycroft mvi HCNT+0,SG_SIZEOF
1112 1.1 mycroft
1113 1.1 mycroft mvi DINDEX,HADDR
1114 1.1 mycroft mvi SG_NEXT call bcopy_4
1115 1.1 mycroft
1116 1.1 mycroft mvi DFCNTRL,0xd # HDMAEN|DIRECTION|FIFORESET
1117 1.1 mycroft
1118 1.1 mycroft # Wait for DMA from host memory to data FIFO to complete, then disable
1119 1.1 mycroft # DMA and wait for it to acknowledge that it's off.
1120 1.1 mycroft #
1121 1.1 mycroft
1122 1.1 mycroft call dma_finish
1123 1.1 mycroft
1124 1.1 mycroft # Copy data from FIFO into SCB data pointer and data count. This assumes
1125 1.1 mycroft # that the struct scatterlist has this structure (this and sizeof(struct
1126 1.1 mycroft # scatterlist) == 12 are asserted in aic7xxx.c):
1127 1.1 mycroft #
1128 1.1 mycroft # struct scatterlist {
1129 1.1 mycroft # char *address; /* four bytes, little-endian order */
1130 1.1 mycroft # ... /* four bytes, ignored */
1131 1.1 mycroft # unsigned short length; /* two bytes, little-endian order */
1132 1.1 mycroft # }
1133 1.1 mycroft #
1134 1.1 mycroft
1135 1.1 mycroft # Not in FreeBSD. the scatter list entry is only 8 bytes.
1136 1.1 mycroft #
1137 1.1 mycroft # struct ahc_dma_seg {
1138 1.1 mycroft # physaddr addr; /* four bytes, little-endian order */
1139 1.1 mycroft # long len; /* four bytes, little endian order */
1140 1.1 mycroft # };
1141 1.1 mycroft #
1142 1.1 mycroft
1143 1.1 mycroft mvi DINDEX, SCBARRAY+19
1144 1.1 mycroft call bcopy_4_dfdat
1145 1.1 mycroft
1146 1.1 mycroft # For Linux, we must throw away four bytes since there is a 32bit gap
1147 1.1 mycroft # in the middle of a struct scatterlist
1148 1.1 mycroft # mov NONE,DFDAT
1149 1.1 mycroft # mov NONE,DFDAT
1150 1.1 mycroft # mov NONE,DFDAT
1151 1.1 mycroft # mov NONE,DFDAT
1152 1.1 mycroft
1153 1.1 mycroft call bcopy_3_dfdat #Only support 24 bit length.
1154 1.1 mycroft ret
1155 1.1 mycroft
1156 1.1 mycroft # Advance the scatter-gather pointers only IF NEEDED. If SG is enabled,
1157 1.1 mycroft # and the SCSI transfer count is zero (note that this should be called
1158 1.1 mycroft # right after a DMA finishes), then move the working copies of the SG
1159 1.1 mycroft # pointer/length along. If the SCSI transfer count is not zero, then
1160 1.1 mycroft # presumably the target is disconnecting - do not reload the SG values
1161 1.1 mycroft # next time.
1162 1.1 mycroft #
1163 1.1 mycroft sg_advance:
1164 1.1 mycroft test SG_COUNT,0xff jz return # s/g enabled?
1165 1.1 mycroft
1166 1.1 mycroft test STCNT+0,0xff jnz sg_advance1 # SCSI transfer count nonzero?
1167 1.1 mycroft test STCNT+1,0xff jnz sg_advance1
1168 1.1 mycroft test STCNT+2,0xff jnz sg_advance1
1169 1.1 mycroft
1170 1.1 mycroft clr SG_NOLOAD # reload s/g next time
1171 1.1 mycroft dec SG_COUNT # one less segment to go
1172 1.1 mycroft
1173 1.1 mycroft clr A # add sizeof(struct scatter)
1174 1.1 mycroft add SG_NEXT+0,SG_SIZEOF,SG_NEXT+0
1175 1.1 mycroft adc SG_NEXT+1,A,SG_NEXT+1
1176 1.1 mycroft adc SG_NEXT+2,A,SG_NEXT+2
1177 1.1 mycroft adc SG_NEXT+3,A,SG_NEXT+3 ret
1178 1.1 mycroft
1179 1.1 mycroft sg_advance1:
1180 1.1 mycroft mvi SG_NOLOAD,0x80 ret # don't reload s/g next time
1181 1.1 mycroft
1182 1.1 mycroft # Add the array base SYNCNEG to the target offset (the target address
1183 1.1 mycroft # is in SCSIID), and return the result in SINDEX. The accumulator
1184 1.1 mycroft # contains the 3->8 decoding of the target ID on return.
1185 1.1 mycroft #
1186 1.1 mycroft ndx_dtr:
1187 1.1 mycroft shr A,SCSIID,4
1188 1.1 mycroft test SBLKCTL,0x08 jz ndx_dtr_2
1189 1.1 mycroft or A,0x08 # Channel B entries add 8
1190 1.1 mycroft ndx_dtr_2:
1191 1.1 mycroft add SINDEX,SYNCNEG,A
1192 1.1 mycroft
1193 1.1 mycroft and FUNCTION1,0x70,SCSIID # 3-bit target address decode
1194 1.1 mycroft mov A,FUNCTION1 ret
1195 1.1 mycroft
1196 1.1 mycroft # If we need to negotiate transfer parameters, build the WDTR or SDTR message
1197 1.1 mycroft # starting at the address passed in SINDEX. DINDEX is modified on return.
1198 1.1 mycroft # The SCSI-II spec requires that Wide negotiation occur first and you can
1199 1.1 mycroft # only negotiat one or the other at a time otherwise in the event of a message
1200 1.1 mycroft # reject, you wouldn't be able to tell which message was the culpret.
1201 1.1 mycroft #
1202 1.1 mycroft mk_dtr:
1203 1.1 mycroft test SCBARRAY+0,0xc0 jz return # NEEDWDTR|NEEDSDTR
1204 1.1 mycroft test SCBARRAY+0,NEEDWDTR jnz mk_wdtr_16bit
1205 1.1 mycroft or FLAGS, MAX_SYNC # Force an offset of 15
1206 1.1 mycroft
1207 1.1 mycroft mk_sdtr:
1208 1.1 mycroft mvi DINDIR,1 # extended message
1209 1.1 mycroft mvi DINDIR,3 # extended message length = 3
1210 1.1 mycroft mvi DINDIR,1 # SDTR code
1211 1.1 mycroft call sdtr_to_rate
1212 1.1 mycroft mov DINDIR,RETURN_1 # REQ/ACK transfer period
1213 1.1 mycroft test FLAGS, MAX_SYNC jnz mk_sdtr_max_sync
1214 1.1 mycroft and DINDIR,0xf,SINDIR # Sync Offset
1215 1.1 mycroft
1216 1.1 mycroft mk_sdtr_done:
1217 1.1 mycroft add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
1218 1.1 mycroft
1219 1.1 mycroft mk_sdtr_max_sync:
1220 1.1 mycroft # We're initiating sync negotiation, so request the max offset we can (15)
1221 1.1 mycroft mvi DINDIR, 0x0f
1222 1.1 mycroft xor FLAGS, MAX_SYNC
1223 1.1 mycroft jmp mk_sdtr_done
1224 1.1 mycroft
1225 1.1 mycroft mk_wdtr_16bit:
1226 1.1 mycroft mvi ARG_1,BUS_16_BIT
1227 1.1 mycroft mk_wdtr:
1228 1.1 mycroft mvi DINDIR,1 # extended message
1229 1.1 mycroft mvi DINDIR,2 # extended message length = 2
1230 1.1 mycroft mvi DINDIR,3 # WDTR code
1231 1.1 mycroft mov DINDIR,ARG_1 # bus width
1232 1.1 mycroft
1233 1.1 mycroft add MSG_LEN,-MSG_START+0,DINDEX ret # update message length
1234 1.1 mycroft
1235 1.1 mycroft # Set SCSI bus control signal state. This also saves the last-written
1236 1.1 mycroft # value into a location where the higher-level driver can read it - if
1237 1.1 mycroft # it has to send an ABORT or RESET message, then it needs to know this
1238 1.1 mycroft # so it can assert ATN without upsetting SCSISIGO. The new value is
1239 1.1 mycroft # expected in SINDEX. Change the actual state last to avoid contention
1240 1.1 mycroft # from the driver.
1241 1.1 mycroft #
1242 1.1 mycroft scsisig:
1243 1.1 mycroft mov SIGSTATE,SINDEX
1244 1.1 mycroft mov SCSISIGO,SINDEX ret
1245 1.1 mycroft
1246 1.1 mycroft sdtr_to_rate:
1247 1.1 mycroft call ndx_dtr # index scratch space for target
1248 1.1 mycroft shr A,SINDIR,0x4
1249 1.1 mycroft dec SINDEX #Preserve SINDEX
1250 1.1 mycroft and A,0x7
1251 1.1 mycroft clr RETURN_1
1252 1.1 mycroft sdtr_to_rate_loop:
1253 1.1 mycroft test A,0x0f jz sdtr_to_rate_done
1254 1.1 mycroft add RETURN_1,0x18
1255 1.1 mycroft dec A
1256 1.1 mycroft jmp sdtr_to_rate_loop
1257 1.1 mycroft sdtr_to_rate_done:
1258 1.1 mycroft shr RETURN_1,0x2
1259 1.1 mycroft add RETURN_1,0x18 ret
1260 1.1 mycroft
1261 1.1 mycroft return:
1262 1.1 mycroft ret
1263