Deleted Added
full compact
aic7xxx.seq (18762) aic7xxx.seq (19164)
1/*+M***********************************************************************
2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
3 *
4 *Copyright (c) 1994 John Aycock
5 * The University of Calgary Department of Computer Science.
6 * All rights reserved.
7 *
8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,

--- 25 unchanged lines hidden (view full) ---

34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 *SUCH DAMAGE.
39 *
40 *-M************************************************************************/
41
1/*+M***********************************************************************
2 *Adaptec 274x/284x/294x device driver for Linux and FreeBSD.
3 *
4 *Copyright (c) 1994 John Aycock
5 * The University of Calgary Department of Computer Science.
6 * All rights reserved.
7 *
8 *FreeBSD, Twin, Wide, 2 command per target support, tagged queuing,

--- 25 unchanged lines hidden (view full) ---

34 *OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 *HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 *LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 *OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
38 *SUCH DAMAGE.
39 *
40 *-M************************************************************************/
41
42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.42 1996/06/09 17:29:11 gibbs Exp $"
42VERSION AIC7XXX_SEQ_VER "$Id: aic7xxx.seq,v 1.42.2.2 1996/10/06 01:24:09 gibbs Exp $"
43
44#if defined(__NetBSD__)
45#include "../../../../dev/ic/aic7xxxreg.h"
46#include "../../../../scsi/scsi_message.h"
47#elif defined(__FreeBSD__)
48#include "../../dev/aic7xxx/aic7xxx_reg.h"
49#include "../../scsi/scsi_message.h"
50#endif
51
52/*
53 * We can't just use ACCUM in the sequencer code because it
54 * must be treated specially by the assembler, and it currently
55 * looks for the symbol 'A'. This is the only register defined in
56 * the assembler's symbol space.
57 */
58A = ACCUM
59
43
44#if defined(__NetBSD__)
45#include "../../../../dev/ic/aic7xxxreg.h"
46#include "../../../../scsi/scsi_message.h"
47#elif defined(__FreeBSD__)
48#include "../../dev/aic7xxx/aic7xxx_reg.h"
49#include "../../scsi/scsi_message.h"
50#endif
51
52/*
53 * We can't just use ACCUM in the sequencer code because it
54 * must be treated specially by the assembler, and it currently
55 * looks for the symbol 'A'. This is the only register defined in
56 * the assembler's symbol space.
57 */
58A = ACCUM
59
60/* After starting the selection hardware, we check for reconnecting targets
60/*
61 * A few words on the waiting SCB list:
62 * After starting the selection hardware, we check for reconnecting targets
61 * as well as for our selection to complete just in case the reselection wins
62 * bus arbitration. The problem with this is that we must keep track of the
63 * SCB that we've already pulled from the QINFIFO and started the selection
64 * on just in case the reselection wins so that we can retry the selection at
65 * a later time. This problem cannot be resolved by holding a single entry
66 * in scratch ram since a reconnecting target can request sense and this will
67 * create yet another SCB waiting for selection. The solution used here is to
68 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
63 * as well as for our selection to complete just in case the reselection wins
64 * bus arbitration. The problem with this is that we must keep track of the
65 * SCB that we've already pulled from the QINFIFO and started the selection
66 * on just in case the reselection wins so that we can retry the selection at
67 * a later time. This problem cannot be resolved by holding a single entry
68 * in scratch ram since a reconnecting target can request sense and this will
69 * create yet another SCB waiting for selection. The solution used here is to
70 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
69 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB offsets,
70 * SCB_LIST_NULL is 0xff which is out of range. The kernel driver must
71 * add an entry to this list everytime a request sense occurs. The sequencer
72 * will automatically consume the entries.
71 * of SCBs that are awaiting selection. Since 0-0xfe are valid SCB indexes,
72 * SCB_LIST_NULL is 0xff which is out of range. An entry is also added to
73 * this list everytime a request sense occurs or after completing a non-tagged
74 * command for which a second SCB has been queued. The sequencer will
75 * automatically consume the entries.
73 */
74
75/*
76 * We assume that the kernel driver may reset us at any time, even in the
77 * middle of a DMA, so clear DFCNTRL too.
78 */
79reset:
80 clr DFCNTRL
81 clr SCSISIGO /* De-assert BSY */
82/*
83 * We jump to start after every bus free.
84 */
85start:
76 */
77
78/*
79 * We assume that the kernel driver may reset us at any time, even in the
80 * middle of a DMA, so clear DFCNTRL too.
81 */
82reset:
83 clr DFCNTRL
84 clr SCSISIGO /* De-assert BSY */
85/*
86 * We jump to start after every bus free.
87 */
88start:
86 and FLAGS,0x0f /* clear target specific flags */
89 and FLAGS,0x07 /* clear target specific flags */
87 mvi SCSISEQ,ENRSELI /* Always allow reselection */
88 clr SCSIRATE /*
89 * We don't know the target we will
90 * connect to, so default to narrow
91 * transfers to avoid parity problems.
92 */
93poll_for_work:
94 /*
95 * Are we a twin channel device?
96 * For fairness, we check the other bus first,
97 * since we just finished a transaction on the
98 * current channel.
99 */
100 test FLAGS,TWIN_BUS jz start2
101 xor SBLKCTL,SELBUSB /* Toggle to the other bus */
102 test SSTAT0,SELDI jnz reselect
103 xor SBLKCTL,SELBUSB /* Toggle to the original bus */
104start2:
105 test SSTAT0,SELDI jnz reselect
90 mvi SCSISEQ,ENRSELI /* Always allow reselection */
91 clr SCSIRATE /*
92 * We don't know the target we will
93 * connect to, so default to narrow
94 * transfers to avoid parity problems.
95 */
96poll_for_work:
97 /*
98 * Are we a twin channel device?
99 * For fairness, we check the other bus first,
100 * since we just finished a transaction on the
101 * current channel.
102 */
103 test FLAGS,TWIN_BUS jz start2
104 xor SBLKCTL,SELBUSB /* Toggle to the other bus */
105 test SSTAT0,SELDI jnz reselect
106 xor SBLKCTL,SELBUSB /* Toggle to the original bus */
107start2:
108 test SSTAT0,SELDI jnz reselect
106 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting
109 cmp WAITING_SCBH,SCB_LIST_NULL je test_queue
110start_waiting:
111 /*
112 * Pull the first entry off of the waiting SCB list
113 * We don't have to "test_busy" because only transactions that
114 * have passed that test can be in the WAITING_SCB list.
115 */
116 mov SCBPTR,WAITING_SCBH
117 jmp start_scb2
118test_queue:
119 /* Has the driver posted any work for us? */
107 mov A, QCNTMASK
108 test QINCNT,A jz poll_for_work
109
110/*
111 * We have at least one queued SCB now and we don't have any
120 mov A, QCNTMASK
121 test QINCNT,A jz poll_for_work
122
123/*
124 * We have at least one queued SCB now and we don't have any
112 * SCBs in the list of SCBs awaiting selection. Set the SCB
113 * pointer from the FIFO so we see the right bank of SCB
114 * registers.
125 * SCBs in the list of SCBs awaiting selection. If we have
126 * any SCBs availible for use, pull the tag from the QINFIFO
127 * and get to work on it.
115 */
128 */
116 mov SCBPTR,QINFIFO
129 test FLAGS, PAGESCBS jz dequeue_scb
130 call get_free_or_disc_scb
131 cmp SINDEX, SCB_LIST_NULL je poll_for_work
132dequeue_scb:
133 mov CUR_SCBID,QINFIFO
134 test FLAGS, PAGESCBS jnz dma_queued_scb
135 /* In the non-paging case, the SCBID == hardware SCB index */
136 mov SCBPTR, CUR_SCBID
137dma_queued_scb:
138/*
139 * DMA the SCB from host ram into the current SCB location.
140 */
141 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
142 mov CUR_SCBID call dma_scb
117
118/*
119 * See if there is not already an active SCB for this target. This code
120 * locks out on a per target basis instead of target/lun. Although this
121 * is not ideal for devices that have multiple luns active at the same
122 * time, it is faster than looping through all SCB's looking for active
143
144/*
145 * See if there is not already an active SCB for this target. This code
146 * locks out on a per target basis instead of target/lun. Although this
147 * is not ideal for devices that have multiple luns active at the same
148 * time, it is faster than looping through all SCB's looking for active
123 * commands. It may be benificial to make findscb a more general procedure
124 * to see if the added cost of the search is negligible. This code also
125 * assumes that the kernel driver will clear the active flags on board
126 * initialization, board reset, and a target SELTO. Tagged commands
127 * don't set the active bits since you can queue more than one command
128 * at a time. We do, however, look to see if there are any non-tagged
129 * I/Os in progress, and requeue the command if there are. Tagged and
130 * non-tagged commands cannot be mixed to a single target.
149 * commands. We also don't have enough spare SCB space for to store the
150 * SCBID of the currently busy transaction for each target/lun making it
151 * impossible to link up the SCBs.
131 */
152 */
132
133test_busy:
153test_busy:
134 mov FUNCTION1,SCB_TCL
135 mov A,FUNCTION1
136 test SCB_TCL,0x88 jz test_a /* Id < 8 && A channel */
137
138 test ACTIVE_B,A jnz requeue
139 test SCB_CONTROL,TAG_ENB jnz start_scb
140 /* Mark the current target as busy */
141 or ACTIVE_B,A
142 jmp start_scb
143
144/* Place the currently active SCB back on the queue for later processing */
145requeue:
146 mov QINFIFO, SCBPTR
154 test SCB_CONTROL, TAG_ENB jnz start_scb
155 mov SAVED_SCBPTR, SCBPTR
156 call index_untagged_scb
157 mov ARG_1, SINDIR /*
158 * ARG_1 should
159 * now have the SCB ID of
160 * any active, non-tagged,
161 * command for this target.
162 */
163 cmp ARG_1, SCB_LIST_NULL je make_busy
164 test FLAGS, PAGESCBS jz simple_busy_link
165 /*
166 * Put this SCB back onto the free list. It
167 * may be necessary to satisfy the search for
168 * the active SCB.
169 */
170 call add_scb_to_free_list
171 /* Find the active SCB */
172 mov ALLZEROS call findSCB
173 /* Link us in */
174 mov SCB_LINKED_NEXT, CUR_SCBID
175 /* Put it back on the disconnected list */
176 call add_scb_to_disc_list
147 jmp poll_for_work
177 jmp poll_for_work
178simple_busy_link:
179 mov SCBPTR, ARG_1
180 mov SCB_LINKED_NEXT, CUR_SCBID
181 jmp poll_for_work
182make_busy:
183 mov DINDIR, CUR_SCBID
184 mov SCBPTR, SAVED_SCBPTR
148
185
149/*
150 * Pull the first entry off of the waiting for selection list
151 * We don't have to "test_busy" because only transactions that
152 * have passed that test can be in the waiting_scb list.
153 */
154start_waiting:
155 mov SCBPTR,WAITING_SCBH
156 jmp start_scb2
157
158test_a:
159 test ACTIVE_A,A jnz requeue
160 test SCB_CONTROL,TAG_ENB jnz start_scb
161 /* Mark the current target as busy */
162 or ACTIVE_A,A
163
164start_scb:
186start_scb:
187 /*
188 * Place us on the waiting list in case our selection
189 * doesn't win during bus arbitration.
190 */
165 mov SCB_NEXT,WAITING_SCBH
166 mov WAITING_SCBH, SCBPTR
167start_scb2:
168 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */
169 and A,0x08,SCB_TCL /* Get new channel bit */
170 or SINDEX,A
171 mov SBLKCTL,SINDEX /* select channel */
172 mov SCB_TCL call initialize_scsiid

--- 12 unchanged lines hidden (view full) ---

185 * into the message out phase since we have ATN asserted. Prepare
186 * the message to send.
187 *
188 * Messages are stored in scratch RAM starting with a length byte
189 * followed by the message itself.
190 */
191
192mk_identify:
191 mov SCB_NEXT,WAITING_SCBH
192 mov WAITING_SCBH, SCBPTR
193start_scb2:
194 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */
195 and A,0x08,SCB_TCL /* Get new channel bit */
196 or SINDEX,A
197 mov SBLKCTL,SINDEX /* select channel */
198 mov SCB_TCL call initialize_scsiid

--- 12 unchanged lines hidden (view full) ---

211 * into the message out phase since we have ATN asserted. Prepare
212 * the message to send.
213 *
214 * Messages are stored in scratch RAM starting with a length byte
215 * followed by the message itself.
216 */
217
218mk_identify:
193 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */
194
195 and MSG0,0x7,SCB_TCL /* lun */
219 and MSG0,0x7,SCB_TCL /* lun */
220 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */
196 or MSG0,A /* or in disconnect privledge */
197 or MSG0,MSG_IDENTIFYFLAG
198 mvi MSG_LEN, 1
199
200/*
201 * Send a tag message if TAG_ENB is set in the SCB control block.
202 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
203 */
204mk_tag:
205 test SCB_CONTROL,TAG_ENB jz mk_message
221 or MSG0,A /* or in disconnect privledge */
222 or MSG0,MSG_IDENTIFYFLAG
223 mvi MSG_LEN, 1
224
225/*
226 * Send a tag message if TAG_ENB is set in the SCB control block.
227 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
228 */
229mk_tag:
230 test SCB_CONTROL,TAG_ENB jz mk_message
206 mvi DINDEX, MSG1
207 and DINDIR,0x23,SCB_CONTROL
208 mov DINDIR,SCB_TAG
231 and MSG1,0x23,SCB_CONTROL
232 mov MSG2,SCB_TAG
233 add MSG_LEN,2 /* update message length */
209
234
210 add MSG_LEN,COMP_MSG0,DINDEX /* update message length */
211
212/*
213 * Interrupt the driver, and allow it to tweak the message buffer
214 * if it asks.
215 */
216mk_message:
217 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection
218
219 mvi INTSTAT,AWAITING_MSG
220
221wait_for_selection:
222 test SSTAT0,SELDO jnz select
223 test SSTAT0,SELDI jz wait_for_selection
224
225/*
226 * Reselection has been initiated by a target. Make a note that we've been
235/*
236 * Interrupt the driver, and allow it to tweak the message buffer
237 * if it asks.
238 */
239mk_message:
240 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection
241
242 mvi INTSTAT,AWAITING_MSG
243
244wait_for_selection:
245 test SSTAT0,SELDO jnz select
246 test SSTAT0,SELDI jz wait_for_selection
247
248/*
249 * Reselection has been initiated by a target. Make a note that we've been
227 * reselected, but haven't seen an IDENTIFY message from the target
228 * yet.
250 * reselected, but haven't seen an IDENTIFY message from the target yet.
229 */
230reselect:
231 clr MSG_LEN /* Don't have anything in the mesg buffer */
232 mov SELID call initialize_scsiid
233 or FLAGS,RESELECTED
234 jmp select2
235
236/*
251 */
252reselect:
253 clr MSG_LEN /* Don't have anything in the mesg buffer */
254 mov SELID call initialize_scsiid
255 or FLAGS,RESELECTED
256 jmp select2
257
258/*
237 * After the selection, remove this SCB from the "waiting for selection"
259 * After the selection, remove this SCB from the "waiting SCB"
238 * list. This is achieved by simply moving our "next" pointer into
239 * WAITING_SCBH. Our next pointer will be set to null the next time this
240 * SCB is used, so don't bother with it now.
241 */
242select:
243 mov WAITING_SCBH,SCB_NEXT
260 * list. This is achieved by simply moving our "next" pointer into
261 * WAITING_SCBH. Our next pointer will be set to null the next time this
262 * SCB is used, so don't bother with it now.
263 */
264select:
265 mov WAITING_SCBH,SCB_NEXT
244 or FLAGS,SELECTED
245select2:
246/*
266select2:
267/*
247 * Set CLRCHN here before the target has entered a data transfer mode -
248 * with synchronous SCSI, if you do it later, you blow away some
249 * data in the SCSI FIFO that the target has already sent to you.
250 */
251 or SXFRCTL0,CLRCHN
252/*
253 * Initialize SCSIRATE with the appropriate value for this target.
268 * Initialize SCSIRATE with the appropriate value for this target.
269 * The SCSIRATE settings for each target are stored in an array
270 * based at TARG_SCRATCH.
254 */
271 */
255 call ndx_dtr
272ndx_dtr:
273 shr A,SCSIID,4
274 test SBLKCTL,SELBUSB jz ndx_dtr_2
275 or SAVED_TCL, SELBUSB /* Add the channel bit while we're here */
276 or A,0x08 /* Channel B entries add 8 */
277ndx_dtr_2:
278 add SINDEX,TARG_SCRATCH,A
256 mov SCSIRATE,SINDIR
257
258/*
279 mov SCSIRATE,SINDIR
280
281/*
259 * Initialize Ultra mode setting.
282 * Initialize Ultra mode setting and clear the SCSI channel.
260 */
283 */
261 mov FUNCTION1,SCSIID
262 mov A,FUNCTION1
263 and SINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */
264 test SCSIID, 0x80 jnz ultra_b /* Target ID > 7 */
265 test SBLKCTL, SELBUSB jnz ultra_b /* Second channel device */
266 test ULTRA_ENB,A jz set_sxfrctl0
267 or SINDEX, ULTRAEN jmp set_sxfrctl0
268ultra_b:
269 test ULTRA_ENB_B,A jz set_sxfrctl0
270 or SINDEX, ULTRAEN
271
284ultra:
285 and DINDEX,0xdf,SXFRCTL0 /* default to Ultra disabled */
286 /*
287 * Set CLRCHN here before the target has entered a data transfer mode -
288 * with synchronous SCSI, if you do it later, you blow away some
289 * data in the SCSI FIFO that the target has already sent to you.
290 */
291 or DINDEX, CLRCHN
292 mvi SINDEX, ULTRA_ENB_B
293 test SCSIID, 0x80 jnz ultra_2 /* Target ID > 7 */
294 test SBLKCTL, SELBUSB jnz ultra_2 /* Second channel device */
295 dec SINDEX
296ultra_2:
297 mov FUNCTION1,SCSIID
298 mov A,FUNCTION1
299 test SINDIR, A jz set_sxfrctl0
300 or DINDEX, ULTRAEN
301
272set_sxfrctl0:
302set_sxfrctl0:
273 mov SXFRCTL0,SINDEX
303 mov SXFRCTL0,DINDEX
274
275 mvi SCSISEQ,ENAUTOATNP /*
276 * ATN on parity errors
277 * for "in" phases
278 */
279 mvi CLRSINT1,CLRBUSFREE
280 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
281/*

--- 39 unchanged lines hidden (view full) ---

321 jmp data_phase_loop
322
323p_datain:
324 mvi DMAPARAMS,0x79 /*
325 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
326 * !DIRECTION|FIFORESET
327 */
328data_phase_init:
304
305 mvi SCSISEQ,ENAUTOATNP /*
306 * ATN on parity errors
307 * for "in" phases
308 */
309 mvi CLRSINT1,CLRBUSFREE
310 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
311/*

--- 39 unchanged lines hidden (view full) ---

351 jmp data_phase_loop
352
353p_datain:
354 mvi DMAPARAMS,0x79 /*
355 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
356 * !DIRECTION|FIFORESET
357 */
358data_phase_init:
329 call assert
359 call assert /*
360 * Ensure entering a data
361 * phase is okay - seen identify, etc.
362 */
330
331 test FLAGS, DPHASE jnz data_phase_reinit
363
364 test FLAGS, DPHASE jnz data_phase_reinit
332 call sg_scb2ram
333 or FLAGS, DPHASE /* We have seen a data phase */
334
365
366 /*
367 * Initialize the DMA address and counter from the SCB.
368 * Also set SG_COUNT and SG_NEXT in memory since we cannot
369 * modify the values in the SCB itself until we see a
370 * save data pointers message.
371 */
372 mvi DINDEX, HADDR0
373 mvi SCB_DATAPTR call bcopy_7
374
375 call set_stcnt_from_hcnt
376
377 mov SG_COUNT,SCB_SGCOUNT
378
379 mvi DINDEX, SG_NEXT
380 mvi SCB_SGPTR call bcopy_4
381
382 /* We have seen a data phase */
383 or FLAGS, DPHASE
384
335data_phase_loop:
336/* Guard against overruns */
337 test SG_COUNT, 0xff jnz data_phase_inbounds
338/*
339 * Turn on 'Bit Bucket' mode, set the transfer count to
340 * 16meg and let the target run until it changes phase.
341 * When the transfer completes, notify the host that we
342 * had an overrun.
343 */
344 or SXFRCTL1,BITBUCKET
345 mvi STCNT0,0xff
346 mvi STCNT1,0xff
347 mvi STCNT2,0xff
348
349data_phase_inbounds:
385data_phase_loop:
386/* Guard against overruns */
387 test SG_COUNT, 0xff jnz data_phase_inbounds
388/*
389 * Turn on 'Bit Bucket' mode, set the transfer count to
390 * 16meg and let the target run until it changes phase.
391 * When the transfer completes, notify the host that we
392 * had an overrun.
393 */
394 or SXFRCTL1,BITBUCKET
395 mvi STCNT0,0xff
396 mvi STCNT1,0xff
397 mvi STCNT2,0xff
398
399data_phase_inbounds:
350/* If we are the last SG block, don't set wideodd. */
400/* If we are the last SG block, ensure wideodd is off. */
351 cmp SG_COUNT,0x01 jne data_phase_wideodd
352 and DMAPARAMS, 0xbf /* Turn off WIDEODD */
353data_phase_wideodd:
354 mov DMAPARAMS call dma
355
356/* Go tell the host about any overruns */
357 test SXFRCTL1,BITBUCKET jnz data_phase_overrun
358

--- 19 unchanged lines hidden (view full) ---

378 *
379 * This, like all DMA's, assumes little-endian host data storage.
380 */
381sg_load:
382 clr HCNT2
383 clr HCNT1
384 mvi HCNT0,SG_SIZEOF
385
401 cmp SG_COUNT,0x01 jne data_phase_wideodd
402 and DMAPARAMS, 0xbf /* Turn off WIDEODD */
403data_phase_wideodd:
404 mov DMAPARAMS call dma
405
406/* Go tell the host about any overruns */
407 test SXFRCTL1,BITBUCKET jnz data_phase_overrun
408

--- 19 unchanged lines hidden (view full) ---

428 *
429 * This, like all DMA's, assumes little-endian host data storage.
430 */
431sg_load:
432 clr HCNT2
433 clr HCNT1
434 mvi HCNT0,SG_SIZEOF
435
386 mov HADDR0,SG_NEXT0
387 mov HADDR1,SG_NEXT1
388 mov HADDR2,SG_NEXT2
389 mov HADDR3,SG_NEXT3
436 mvi DINDEX, HADDR0
437 mvi SG_NEXT0 call bcopy_4
390
391 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */
392
438
439 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */
440
393/*
394 * Wait for DMA from host memory to data FIFO to complete, then disable
395 * DMA and wait for it to acknowledge that it's off.
396 */
397dma_finish:
398 test DFSTATUS,HDONE jz dma_finish
399 /* Turn off DMA preserving WIDEODD */
400 and DFCNTRL,WIDEODD
401dma_finish2:
402 test DFCNTRL,HDMAENACK jnz dma_finish2
441 call dma_finish
403
404/*
405 * Copy data from FIFO into SCB data pointer and data count. This assumes
442
443/*
444 * Copy data from FIFO into SCB data pointer and data count. This assumes
406 * that the struct scatterlist has this structure (this and sizeof(struct
407 * scatterlist) == 12 are asserted in aic7xxx.c for the Linux driver):
445 * that the SG segments are of the form:
408 *
446 *
409 * struct scatterlist {
410 * char *address; four bytes, little-endian order
411 * ... four bytes, ignored
412 * unsigned short length; two bytes, little-endian order
413 * }
414 *
415 *
416 * In FreeBSD, the scatter list entry is only 8 bytes.
417 *
418 * struct ahc_dma_seg {
447 * struct ahc_dma_seg {
419 * physaddr addr; four bytes, little-endian order
420 * long len; four bytes, little endian order
448 * u_int32_t addr; four bytes, little-endian order
449 * u_int32_t len; four bytes, little endian order
421 * };
422 */
450 * };
451 */
452 mvi HADDR0 call dfdat_in_7
423
453
424 mov HADDR0,DFDAT
425 mov HADDR1,DFDAT
426 mov HADDR2,DFDAT
427 mov HADDR3,DFDAT
428/*
429 * For Linux, we must throw away four bytes since there is a 32bit gap
430 * in the middle of a struct scatterlist.
431 */
432#ifdef __linux__
433 mov NONE,DFDAT
434 mov NONE,DFDAT
435 mov NONE,DFDAT
436 mov NONE,DFDAT
437#endif
438 mov HCNT0,DFDAT
439 mov HCNT1,DFDAT
440 mov HCNT2,DFDAT
441
442/* Load STCNT as well. It is a mirror of HCNT */
454/* Load STCNT as well. It is a mirror of HCNT */
443 mov STCNT0,HCNT0
444 mov STCNT1,HCNT1
445 mov STCNT2,HCNT2
446 test SSTAT1,PHASEMIS jz data_phase_loop
455 call set_stcnt_from_hcnt
456 test SSTAT1,PHASEMIS jz data_phase_loop
447
448data_phase_finish:
449/*
450 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
451 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
452 * were transferred on the SCSI (as opposed to the host) bus.
453 */
454 mov SCB_RESID_DCNT0,STCNT0

--- 14 unchanged lines hidden (view full) ---

469 * Command phase. Set up the DMA registers and let 'er rip.
470 */
471p_command:
472 call assert
473
474/*
475 * Load HADDR and HCNT.
476 */
457
458data_phase_finish:
459/*
460 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
461 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
462 * were transferred on the SCSI (as opposed to the host) bus.
463 */
464 mov SCB_RESID_DCNT0,STCNT0

--- 14 unchanged lines hidden (view full) ---

479 * Command phase. Set up the DMA registers and let 'er rip.
480 */
481p_command:
482 call assert
483
484/*
485 * Load HADDR and HCNT.
486 */
477 mov HADDR0, SCB_CMDPTR0
478 mov HADDR1, SCB_CMDPTR1
479 mov HADDR2, SCB_CMDPTR2
480 mov HADDR3, SCB_CMDPTR3
481 mov HCNT0, SCB_CMDLEN
487 mvi DINDEX, HADDR0
488 mvi SCB_CMDPTR call bcopy_5
482 clr HCNT1
483 clr HCNT2
484
489 clr HCNT1
490 clr HCNT2
491
485 mov STCNT0, HCNT0
486 mov STCNT1, HCNT1
487 mov STCNT2, HCNT2
492 call set_stcnt_from_hcnt
488
489 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
490 # DIRECTION|FIFORESET
491 jmp ITloop
492
493/*
494 * Status phase. Wait for the data byte to appear, then read it
495 * and store it into the SCB.

--- 4 unchanged lines hidden (view full) ---

500
501/*
502 * Message out phase. If there is not an active message, but the target
503 * took us into this phase anyway, build a no-op message and send it.
504 */
505p_mesgout:
506 test MSG_LEN, 0xff jnz p_mesgout_start
507 mvi MSG_NOOP call mk_mesg /* build NOP message */
493
494 mvi 0x3d call dma # SCSIEN|SDMAEN|HDMAEN|
495 # DIRECTION|FIFORESET
496 jmp ITloop
497
498/*
499 * Status phase. Wait for the data byte to appear, then read it
500 * and store it into the SCB.

--- 4 unchanged lines hidden (view full) ---

505
506/*
507 * Message out phase. If there is not an active message, but the target
508 * took us into this phase anyway, build a no-op message and send it.
509 */
510p_mesgout:
511 test MSG_LEN, 0xff jnz p_mesgout_start
512 mvi MSG_NOOP call mk_mesg /* build NOP message */
508
509p_mesgout_start:
510/*
511 * Set up automatic PIO transfer from MSG0. Bit 3 in
512 * SXFRCTL0 (SPIOEN) is already on.
513 */
514 mvi SINDEX,MSG0
515 mov DINDEX,MSG_LEN
516

--- 50 unchanged lines hidden (view full) ---

567 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs
568 cmp ALLZEROS,A je mesgin_complete
569 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs
570 cmp A,MSG_EXTENDED je mesgin_extended
571 cmp A,MSG_MESSAGE_REJECT je mesgin_reject
572
573rej_mesgin:
574/*
513p_mesgout_start:
514/*
515 * Set up automatic PIO transfer from MSG0. Bit 3 in
516 * SXFRCTL0 (SPIOEN) is already on.
517 */
518 mvi SINDEX,MSG0
519 mov DINDEX,MSG_LEN
520

--- 50 unchanged lines hidden (view full) ---

571 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs
572 cmp ALLZEROS,A je mesgin_complete
573 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs
574 cmp A,MSG_EXTENDED je mesgin_extended
575 cmp A,MSG_MESSAGE_REJECT je mesgin_reject
576
577rej_mesgin:
578/*
575 * We have no idea what this message in is, and there's no way
576 * to pass it up to the kernel, so we issue a message reject and
577 * hope for the best. Since we're now using manual PIO mode to
578 * read in the message, there should no longer be a race condition
579 * present when we assert ATN. In any case, rejection should be a
580 * rare occurrence - signal the driver when it happens.
579 * We have no idea what this message in is, so we issue a message reject
580 * and hope for the best. In any case, rejection should be a rare
581 * occurrence - signal the driver when it happens.
581 */
582 or SCSISIGO,ATNO /* turn on ATNO */
583 mvi INTSTAT,SEND_REJECT /* let driver know */
584
585 mvi MSG_MESSAGE_REJECT call mk_mesg
586
587mesgin_done:
588 call inb_last /*ack & turn auto PIO back on*/
589 jmp ITloop
590
591
592mesgin_complete:
593/*
582 */
583 or SCSISIGO,ATNO /* turn on ATNO */
584 mvi INTSTAT,SEND_REJECT /* let driver know */
585
586 mvi MSG_MESSAGE_REJECT call mk_mesg
587
588mesgin_done:
589 call inb_last /*ack & turn auto PIO back on*/
590 jmp ITloop
591
592
593mesgin_complete:
594/*
594 * We got a "command complete" message, so put the SCB_TAG into QUEUEOUT,
595 * and trigger a completion interrupt. Check status for non zero return
596 * and interrupt driver if needed. This allows the driver to interpret
597 * errors only when they occur instead of always uploading the scb. If
598 * the status is SCSI_CHECK, the driver will download a new scb requesting
599 * sense to replace the old one, modify the "waiting for selection" SCB list
600 * and set RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE the
601 * sequencer imediately jumps to main loop where it will run down the waiting
602 * SCB list and process the sense request. If the kernel driver does not
603 * wish to request sense, it need only clear RETURN_1, and the command is
604 * allowed to complete. We don't bother to post to the QOUTFIFO in the
605 * error case since it would require extra work in the kernel driver to
606 * ensure that the entry was removed before the command complete code tried
607 * processing it.
608 *
609 * First check for residuals
595 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
596 * and trigger a completion interrupt. Before doing so, check to see if there
597 * is a residual or the status byte is something other than NO_ERROR (0). In
598 * either of these conditions, we upload the SCB back to the host so it can
599 * process this information. In the case of a non zero status byte, we
600 * additionally interrupt the kernel driver synchronously, allowing it to
601 * decide if sense should be retrieved. If the kernel driver wishes to request
602 * sense, it will fill the kernel SCB with a request sense command and set
603 * RETURN_1 to SEND_SENSE. If RETURN_1 is set to SEND_SENSE we redownload
604 * the SCB, and process it as the next command by adding it to the waiting list.
605 * If the kernel driver does not wish to request sense, it need only clear
606 * RETURN_1, and the command is allowed to complete normally. We don't bother
607 * to post to the QOUTFIFO in the error cases since it would require extra
608 * work in the kernel driver to ensure that the entry was removed before the
609 * command complete code tried processing it.
610 */
610 */
611 test SCB_RESID_SGCNT,0xff jz check_status
611
612/*
612/*
613 * If we have a residual count, interrupt and tell the host. Other
614 * alternatives are to pause the sequencer on all command completes (yuck),
615 * dma the resid directly to the host (slick, we may have space to do it now)
616 * or have the sequencer pause itself when it encounters a non-zero resid
617 * (unecessary pause just to flag the command -yuck-, but takes one instruction
618 * and since it shouldn't happen that often is good enough for our purposes).
613 * First check for residuals
619 */
614 */
620resid:
621 mvi INTSTAT,RESIDUAL
622
623check_status:
615 test SCB_RESID_SGCNT,0xff jnz upload_scb
624 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */
616 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */
617upload_scb:
618 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/
619 mov SCB_TAG call dma_scb
620check_status:
621 test SCB_TARGET_STATUS,0xff jz status_ok /* Just a residual? */
625 mvi INTSTAT,BAD_STATUS /* let driver know */
626 cmp RETURN_1, SEND_SENSE jne status_ok
622 mvi INTSTAT,BAD_STATUS /* let driver know */
623 cmp RETURN_1, SEND_SENSE jne status_ok
627 jmp mesgin_done
624 /* This SCB becomes the next to execute as it will retrieve sense */
625 mov SCB_LINKED_NEXT, SCB_TAG
626 jmp dma_next_scb
628
629status_ok:
630/* First, mark this target as free. */
631 test SCB_CONTROL,TAG_ENB jnz test_immediate /*
632 * Tagged commands
633 * don't busy the
634 * target.
635 */
627
628status_ok:
629/* First, mark this target as free. */
630 test SCB_CONTROL,TAG_ENB jnz test_immediate /*
631 * Tagged commands
632 * don't busy the
633 * target.
634 */
636 mov FUNCTION1,SCB_TCL
637 mov A,FUNCTION1
638 test SCB_TCL,0x88 jz clear_a
639 xor ACTIVE_B,A
640 jmp test_immediate
635 mov SAVED_SCBPTR, SCBPTR
636 mov SAVED_LINKPTR, SCB_LINKED_NEXT
637 call index_untagged_scb
638 mov DINDIR, SAVED_LINKPTR
639 mov SCBPTR, SAVED_SCBPTR
641
640
642clear_a:
643 xor ACTIVE_A,A
644
645test_immediate:
646 test SCB_CMDLEN,0xff jnz complete /* Immediate message complete */
647/*
648 * Pause the sequencer until the driver gets around to handling the command
649 * complete. This is so that any action that might require carefull timing
650 * with the completion of this command can occur.
651 */
652 mvi INTSTAT,IMMEDDONE
641test_immediate:
642 test SCB_CMDLEN,0xff jnz complete /* Immediate message complete */
643/*
644 * Pause the sequencer until the driver gets around to handling the command
645 * complete. This is so that any action that might require carefull timing
646 * with the completion of this command can occur.
647 */
648 mvi INTSTAT,IMMEDDONE
653 jmp start
649 jmp dma_next_scb
654complete:
650complete:
651 test FLAGS, PAGESCBS jz complete_post
652 /* Wait for a free slot - we may need to wait only in the paging case */
653 mov A, QOUTCNT
654 cmp QFULLCNT, A je complete
655complete_post:
656 /* Post the SCB and issue an interrupt */
655 mov QOUTFIFO,SCB_TAG
656 mvi INTSTAT,CMDCMPLT
657 mov QOUTFIFO,SCB_TAG
658 mvi INTSTAT,CMDCMPLT
659
660dma_next_scb:
661 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je mesgin_done
662 test FLAGS, PAGESCBS jnz dma_next_scb2
663 /* Only DMA on top of ourselves if we are the SCB to download */
664 mov A, SCB_LINKED_NEXT
665 cmp SCB_TAG, A je dma_next_scb2
666 mov SCBPTR, A
667 jmp add_to_waiting_list
668dma_next_scb2:
669 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
670 mov SCB_TAG call dma_scb
671add_to_waiting_list:
672 mov SCB_NEXT,WAITING_SCBH
673 mov WAITING_SCBH, SCBPTR
674 or FLAGS, SCB_LISTED
657 jmp mesgin_done
658
675 jmp mesgin_done
676
659
660/*
661 * Is it an extended message? Copy the message to our message buffer and
662 * notify the host. The host will tell us whether to reject this message,
663 * respond to it with the message that the host placed in our message buffer,
664 * or simply to do nothing.
665 */
666mesgin_extended:
667 mvi MSGIN_EXT_LEN call inb_next
677/*
678 * Is it an extended message? Copy the message to our message buffer and
679 * notify the host. The host will tell us whether to reject this message,
680 * respond to it with the message that the host placed in our message buffer,
681 * or simply to do nothing.
682 */
683mesgin_extended:
684 mvi MSGIN_EXT_LEN call inb_next
668 mvi MSGIN_EXT_OPCODE call inb_next
669 mov A, MSGIN_EXT_LEN
685 mov A, MSGIN_EXT_LEN
670 dec A /* Length counts the op code */
671 mvi SINDEX, MSGIN_EXT_BYTE0
672mesgin_extended_loop:
686mesgin_extended_loop:
673 test A, 0xFF jz mesgin_extended_intr
674 cmp SINDEX, MSGIN_EXT_LASTBYTE je mesgin_extended_dump
675 call inb_next
687 mov DINDEX call inb_next
676 dec A
688 dec A
677/*
678 * We pass the arg to inb in SINDEX, but DINDEX is the one incremented
679 * so update SINDEX with DINDEX's value before looping again.
680 */
681 mov DINDEX jmp mesgin_extended_loop
682mesgin_extended_dump:
683/* We have no more storage space, so dump the rest */
684 test A, 0xFF jz mesgin_extended_intr
685 mvi NONE call inb_next
686 dec A
687 jmp mesgin_extended_dump
689 cmp DINDEX, MSGIN_EXT_LASTBYTE jne mesgin_extended_loop_test
690 dec DINDEX /* dump by repeatedly filling the last byte */
691mesgin_extended_loop_test:
692 test A, 0xFF jnz mesgin_extended_loop
688mesgin_extended_intr:
689 mvi INTSTAT,EXTENDED_MSG /* let driver know */
690 cmp RETURN_1,SEND_REJ je rej_mesgin
691 cmp RETURN_1,SEND_MSG jne mesgin_done
692/* The kernel has setup a message to be sent */
693 or SCSISIGO,ATNO /* turn on ATNO */
694 jmp mesgin_done
695
696/*
697 * Is it a disconnect message? Set a flag in the SCB to remind us
698 * and await the bus going free.
699 */
700mesgin_disconnect:
701 or SCB_CONTROL,DISCONNECTED
702 test FLAGS, PAGESCBS jz mesgin_done
693mesgin_extended_intr:
694 mvi INTSTAT,EXTENDED_MSG /* let driver know */
695 cmp RETURN_1,SEND_REJ je rej_mesgin
696 cmp RETURN_1,SEND_MSG jne mesgin_done
697/* The kernel has setup a message to be sent */
698 or SCSISIGO,ATNO /* turn on ATNO */
699 jmp mesgin_done
700
701/*
702 * Is it a disconnect message? Set a flag in the SCB to remind us
703 * and await the bus going free.
704 */
705mesgin_disconnect:
706 or SCB_CONTROL,DISCONNECTED
707 test FLAGS, PAGESCBS jz mesgin_done
703/*
704 * Link this SCB into the DISCONNECTED list. This list holds the
705 * candidates for paging out an SCB if one is needed for a new command.
706 * Modifying the disconnected list is a critical(pause dissabled) section.
707 */
708 mvi SCB_PREV, SCB_LIST_NULL
709 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
710 mov SCB_NEXT, DISCONNECTED_SCBH
711 mov DISCONNECTED_SCBH, SCBPTR
712 cmp SCB_NEXT,SCB_LIST_NULL je linkdone
713 mov SCBPTR,SCB_NEXT
714 mov SCB_PREV,DISCONNECTED_SCBH
715 mov SCBPTR,DISCONNECTED_SCBH
716linkdone:
717 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
708 call add_scb_to_disc_list
709 or FLAGS, SCB_LISTED
718 jmp mesgin_done
719
720/*
710 jmp mesgin_done
711
712/*
721 * Save data pointers message? Copy working values into the SCB,
722 * usually in preparation for a disconnect.
713 * Save data pointers message:
714 * Copying RAM values back to SCB, for Save Data Pointers message, but
715 * only if we've actually been into a data phase to change them. This
716 * protects against bogus data in scratch ram and the residual counts
717 * since they are only initialized when we go into data_in or data_out.
723 */
724mesgin_sdptrs:
718 */
719mesgin_sdptrs:
725 call sg_ram2scb
720 test FLAGS, DPHASE jz mesgin_done
721 mov SCB_SGCOUNT,SG_COUNT
722
723 /* The SCB SGPTR becomes the next one we'll download */
724 mvi DINDEX, SCB_SGPTR
725 mvi SG_NEXT0 call bcopy_4
726
727 /* The SCB DATAPTR0 becomes the current SHADDR */
728 mvi DINDEX, SCB_DATAPTR0
729 mvi SHADDR0 call bcopy_4
730
731/*
732 * Use the residual number since STCNT is corrupted by any message transfer.
733 */
734 mvi SCB_RESID_DCNT0 call bcopy_3
735
726 jmp mesgin_done
727
728/*
729 * Restore pointers message? Data pointers are recopied from the
730 * SCB anytime we enter a data phase for the first time, so all
731 * we need to do is clear the DPHASE flag and let the data phase
732 * code do the rest.
733 */

--- 6 unchanged lines hidden (view full) ---

740
741/*
742 * Identify message? For a reconnecting target, this tells us the lun
743 * that the reconnection is for - find the correct SCB and switch to it,
744 * clearing the "disconnected" bit so we don't "find" it by accident later.
745 */
746mesgin_identify:
747 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/
736 jmp mesgin_done
737
738/*
739 * Restore pointers message? Data pointers are recopied from the
740 * SCB anytime we enter a data phase for the first time, so all
741 * we need to do is clear the DPHASE flag and let the data phase
742 * code do the rest.
743 */

--- 6 unchanged lines hidden (view full) ---

750
751/*
752 * Identify message? For a reconnecting target, this tells us the lun
753 * that the reconnection is for - find the correct SCB and switch to it,
754 * clearing the "disconnected" bit so we don't "find" it by accident later.
755 */
756mesgin_identify:
757 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/
748
749 and A,0x07 /* lun in lower three bits */
758 and A,0x07 /* lun in lower three bits */
750 or SAVED_TCL,A,SELID
751 and SAVED_TCL,0xf7
752 and A,SELBUSB,SBLKCTL /* B Channel?? */
753 or SAVED_TCL,A
759 or SAVED_TCL,A /* SAVED_TCL should be complete now */
754 call inb_last /* ACK */
755
756/*
757 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
758 * If we get one, we use the tag returned to switch to find the proper
759 * SCB. With SCB paging, this requires using findSCB for both tagged
760 * and non-tagged transactions since the SCB may exist in any slot.
761 * If we're not using SCB paging, we can use the tag as the direct

--- 17 unchanged lines hidden (view full) ---

779 add SINDEX,A,ARG_1
780 jc abort_tag
781
782/*
783 * Ensure that the SCB the tag points to is for an SCB transaction
784 * to the reconnecting target.
785 */
786 test FLAGS, PAGESCBS jz index_by_tag
760 call inb_last /* ACK */
761
762/*
763 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
764 * If we get one, we use the tag returned to switch to find the proper
765 * SCB. With SCB paging, this requires using findSCB for both tagged
766 * and non-tagged transactions since the SCB may exist in any slot.
767 * If we're not using SCB paging, we can use the tag as the direct

--- 17 unchanged lines hidden (view full) ---

785 add SINDEX,A,ARG_1
786 jc abort_tag
787
788/*
789 * Ensure that the SCB the tag points to is for an SCB transaction
790 * to the reconnecting target.
791 */
792 test FLAGS, PAGESCBS jz index_by_tag
787 call inb_last /* Ack Tag */
788use_findSCB:
789 mov ALLZEROS call findSCB /* Have to search */
790setup_SCB:
791 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
792 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
793use_findSCB:
794 mov ALLZEROS call findSCB /* Have to search */
795setup_SCB:
796 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
797 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
798 test SCB_CONTROL,TAG_ENB jnz mesgin_done /* Ack Tag */
793 jmp ITloop
794index_by_tag:
795 mov SCBPTR,ARG_1
796 mov A,SAVED_TCL
797 cmp SCB_TCL,A jne abort_tag
798 test SCB_CONTROL,TAG_ENB jz abort_tag
799 jmp ITloop
800index_by_tag:
801 mov SCBPTR,ARG_1
802 mov A,SAVED_TCL
803 cmp SCB_TCL,A jne abort_tag
804 test SCB_CONTROL,TAG_ENB jz abort_tag
799 call inb_last /* Ack Successful tag */
800 jmp setup_SCB
801
802abort_tag:
803 or SCSISIGO,ATNO /* turn on ATNO */
805 jmp setup_SCB
806
807abort_tag:
808 or SCSISIGO,ATNO /* turn on ATNO */
804 mvi INTSTAT,ABORT_TAG /* let driver know */
809abort_tag_msg:
805 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */
806 jmp mesgin_done
807
808/*
809 * Message reject? Let the kernel driver handle this. If we have an
810 * outstanding WDTR or SDTR negotiation, assume that it's a response from
811 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
812 * it since we have no clue what it pertains to.

--- 15 unchanged lines hidden (view full) ---

828 mvi CLRSINT1,CLRATNO
829 clr LASTPHASE
830
831/*
832 * if this is an immediate command, perform a psuedo command complete to
833 * notify the driver.
834 */
835 test SCB_CMDLEN,0xff jz status_ok
810 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */
811 jmp mesgin_done
812
813/*
814 * Message reject? Let the kernel driver handle this. If we have an
815 * outstanding WDTR or SDTR negotiation, assume that it's a response from
816 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
817 * it since we have no clue what it pertains to.

--- 15 unchanged lines hidden (view full) ---

833 mvi CLRSINT1,CLRATNO
834 clr LASTPHASE
835
836/*
837 * if this is an immediate command, perform a psuedo command complete to
838 * notify the driver.
839 */
840 test SCB_CMDLEN,0xff jz status_ok
841 test FLAGS, SCB_LISTED jnz start
842 /*
843 * This SCB didn't disconnect or have a command complete,
844 * so put it on the free queue. It was probably the
845 * result of an abort of some sort. This prevents us
846 * from "leaking" SCBs.
847 */
848 call add_scb_to_free_list
836 jmp start
837
838/*
839 * Locking the driver out, build a one-byte message passed in SINDEX
840 * if there is no active message already. SINDEX is returned intact.
841 */
842mk_mesg:
843 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */

--- 88 unchanged lines hidden (view full) ---

932
933/*
934 * Common SCSI initialization for selection and reselection. Expects
935 * the target SCSI ID to be in the upper four bits of SINDEX, and A's
936 * contents are stomped on return.
937 */
938initialize_scsiid:
939 and SINDEX,0xf0 /* Get target ID */
849 jmp start
850
851/*
852 * Locking the driver out, build a one-byte message passed in SINDEX
853 * if there is no active message already. SINDEX is returned intact.
854 */
855mk_mesg:
856 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */

--- 88 unchanged lines hidden (view full) ---

945
946/*
947 * Common SCSI initialization for selection and reselection. Expects
948 * the target SCSI ID to be in the upper four bits of SINDEX, and A's
949 * contents are stomped on return.
950 */
951initialize_scsiid:
952 and SINDEX,0xf0 /* Get target ID */
953 mov SAVED_TCL, SINDEX /* Update the target portion of this */
940 and A,0x0f,SCSIID
941 or SINDEX,A
942 mov SCSIID,SINDEX ret
943
944/*
945 * Assert that if we've been reselected, then we've seen an IDENTIFY
946 * message.
947 */
948assert:
949 test FLAGS,RESELECTED jz return /* reselected? */
950 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */
951
954 and A,0x0f,SCSIID
955 or SINDEX,A
956 mov SCSIID,SINDEX ret
957
958/*
959 * Assert that if we've been reselected, then we've seen an IDENTIFY
960 * message.
961 */
962assert:
963 test FLAGS,RESELECTED jz return /* reselected? */
964 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */
965
952 mvi INTSTAT,NO_IDENT ret /* no - cause a kernel panic */
966 mvi INTSTAT,NO_IDENT ret /* no - tell the kernel */
953
954/*
955 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
956 * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
957 * SCB. Have the kernel print a warning message if it can't be found, and
958 * generate an ABORT/ABORT_TAG message to the target. SINDEX should be
959 * cleared on call.
960 */
961findSCB:
962 mov A,SAVED_TCL
963 mov SCBPTR,SINDEX /* switch to next SCB */
967
968/*
969 * Locate the SCB matching the target ID/channel/lun in SAVED_TCL, and the tag
970 * value in ARG_1. If ARG_1 == SCB_LIST_NULL, we're looking for a non-tagged
971 * SCB. Have the kernel print a warning message if it can't be found, and
972 * generate an ABORT/ABORT_TAG message to the target. SINDEX should be
973 * cleared on call.
974 */
975findSCB:
976 mov A,SAVED_TCL
977 mov SCBPTR,SINDEX /* switch to next SCB */
964 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
965 cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */
966 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
967 test SCB_CONTROL,TAG_ENB jnz findTaggedSCB
968 cmp ARG_1,SCB_LIST_NULL je foundSCB
978 cmp SCB_TCL,A jne findSCB1 /* target ID/channel/lun match? */
979 test SCB_CONTROL,DISCONNECTED jz findSCB1 /*should be disconnected*/
980 test SCB_CONTROL,TAG_ENB jnz findTaggedSCB
981 cmp ARG_1,SCB_LIST_NULL je foundSCB
969 jmp findSCB1
982findSCB1:
983 inc SINDEX
984 mov A,SCBCOUNT
985 cmp SINDEX,A jne findSCB
986/*
987 * We didn't find it. If we're paging, pull an SCB and DMA down the
988 * one we want. If we aren't paging or the SCB we dma down has the
989 * abort flag set, alert the kernel and send an abort message.
990 */
991 test FLAGS, PAGESCBS jz find_abort
992 call get_free_or_disc_scb
993 mov CUR_SCBID, ARG_1
994 cmp CUR_SCBID, SCB_LIST_NULL jne find_dma_scb
995 call index_untagged_scb
996 mov CUR_SCBID, SINDIR
997find_dma_scb:
998 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
999 mov CUR_SCBID call dma_scb
1000 test SCB_CONTROL, ABORT_SCB jz return
1001find_abort:
1002 mvi INTSTAT,NO_MATCH /* not found - signal kernel */
1003 or SCSISIGO,ATNO /* assert ATNO */
1004 cmp ARG_1,SCB_LIST_NULL jne abort_tag_msg
1005 mvi MSG_ABORT call mk_mesg
1006 jmp ITloop
970findTaggedSCB:
971 mov A, ARG_1 /* Tag passed in ARG_1 */
972 cmp SCB_TAG,A jne findSCB1 /* Found it? */
973foundSCB:
1007findTaggedSCB:
1008 mov A, ARG_1 /* Tag passed in ARG_1 */
1009 cmp SCB_TAG,A jne findSCB1 /* Found it? */
1010foundSCB:
974 test FLAGS,PAGESCBS jz foundSCB_ret
1011 test SCB_CONTROL, ABORT_SCB jnz find_abort
1012 test FLAGS,PAGESCBS jz return
1013rem_scb_from_disc_list:
975/* Remove this SCB from the disconnection list */
976 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev
977 mov SAVED_LINKPTR, SCB_PREV
978 mov SCBPTR, SCB_NEXT
979 mov SCB_PREV, SAVED_LINKPTR
980 mov SCBPTR, SINDEX
981unlink_prev:
982 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */
983 mov SAVED_LINKPTR, SCB_NEXT
984 mov SCBPTR, SCB_PREV
985 mov SCB_NEXT, SAVED_LINKPTR
1014/* Remove this SCB from the disconnection list */
1015 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev
1016 mov SAVED_LINKPTR, SCB_PREV
1017 mov SCBPTR, SCB_NEXT
1018 mov SCB_PREV, SAVED_LINKPTR
1019 mov SCBPTR, SINDEX
1020unlink_prev:
1021 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */
1022 mov SAVED_LINKPTR, SCB_NEXT
1023 mov SCBPTR, SCB_PREV
1024 mov SCB_NEXT, SAVED_LINKPTR
986 mov SCBPTR, SINDEX
987 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
1025 mov SCBPTR, SINDEX ret
988rHead:
1026rHead:
989 mov DISCONNECTED_SCBH,SCB_NEXT
990foundSCB_ret:
991 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
1027 mov DISCONNECTED_SCBH,SCB_NEXT ret
992
1028
993findSCB1:
994 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
995 inc SINDEX
996 mov A,SCBCOUNT
997 cmp SINDEX,A jne findSCB
998
999 mvi INTSTAT,NO_MATCH /* not found - signal kernel */
1000 cmp RETURN_1,SCB_PAGEDIN je return
1001 or SCSISIGO,ATNO /* assert ATNO */
1002 cmp ARG_1,SCB_LIST_NULL jne find_abort_tag
1003 mvi MSG_ABORT call mk_mesg
1004 jmp ITloop
1005find_abort_tag:
1006 mvi MSG_ABORT_TAG call mk_mesg
1007 jmp ITloop
1008
1009/*
1010 * Make a working copy of the scatter-gather parameters from the SCB.
1011 */
1012sg_scb2ram:
1013 mov HADDR0, SCB_DATAPTR0
1014 mov HADDR1, SCB_DATAPTR1
1015 mov HADDR2, SCB_DATAPTR2
1016 mov HADDR3, SCB_DATAPTR3
1017 mov HCNT0, SCB_DATACNT0
1018 mov HCNT1, SCB_DATACNT1
1019 mov HCNT2, SCB_DATACNT2
1020
1029set_stcnt_from_hcnt:
1021 mov STCNT0, HCNT0
1022 mov STCNT1, HCNT1
1030 mov STCNT0, HCNT0
1031 mov STCNT1, HCNT1
1023 mov STCNT2, HCNT2
1032 mov STCNT2, HCNT2 ret
1024
1033
1025 mov SG_COUNT,SCB_SGCOUNT
1034bcopy_7:
1035 mov DINDIR, SINDIR
1036 mov DINDIR, SINDIR
1037bcopy_5:
1038 mov DINDIR, SINDIR
1039bcopy_4:
1040 mov DINDIR, SINDIR
1041bcopy_3:
1042 mov DINDIR, SINDIR
1043 mov DINDIR, SINDIR
1044 mov DINDIR, SINDIR ret
1026
1045
1027 mov SG_NEXT0, SCB_SGPTR0
1028 mov SG_NEXT1, SCB_SGPTR1
1029 mov SG_NEXT2, SCB_SGPTR2
1030 mov SG_NEXT3, SCB_SGPTR3 ret
1046dma_scb:
1047 /*
1048 * SCB index is in SINDEX. Determine the physical address in
1049 * the host where this SCB is located and load HADDR with it.
1050 */
1051 shr DINDEX, SINDEX, 3
1052 shl A, SINDEX, 5
1053 add HADDR0, A, HSCB_ADDR0
1054 mov A, DINDEX
1055 adc HADDR1, A, HSCB_ADDR1
1056 clr A
1057 adc HADDR2, A, HSCB_ADDR2
1058 adc HADDR3, A, HSCB_ADDR3
1059 /* Setup Count */
1060 mvi HCNT0, 28
1061 clr HCNT1
1062 clr HCNT2
1063 mov DFCNTRL, DMAPARAMS
1064 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost
1065 /* Fill it with the SCB data */
1066 call copy_scb_tofifo
1067 mvi DFCNTRL, 0xa /* HDMAEN | FIFOFLUSH */
1068dma_scb_fromhost:
1069 call dma_finish
1070 /* If we were putting the SCB, we are done */
1071 test DMAPARAMS, DIRECTION jz return
1072 mvi SCBARRAY call dfdat_in_7
1073 call dfdat_in_7_continued
1074 call dfdat_in_7_continued
1075 jmp dfdat_in_7_continued
1076dfdat_in_7:
1077 mov DINDEX,SINDEX
1078dfdat_in_7_continued:
1079 mov DINDIR,DFDAT
1080 mov DINDIR,DFDAT
1081 mov DINDIR,DFDAT
1082 mov DINDIR,DFDAT
1083 mov DINDIR,DFDAT
1084 mov DINDIR,DFDAT
1085 mov DINDIR,DFDAT ret
1031
1086
1087copy_scb_tofifo:
1088 mvi SCBARRAY call dfdat_out_7
1089 call dfdat_out_7
1090 call dfdat_out_7
1091dfdat_out_7:
1092 mov DFDAT,SINDIR
1093 mov DFDAT,SINDIR
1094 mov DFDAT,SINDIR
1095 mov DFDAT,SINDIR
1096 mov DFDAT,SINDIR
1097 mov DFDAT,SINDIR
1098 mov DFDAT,SINDIR ret
1099
1032/*
1100/*
1033 * Copying RAM values back to SCB, for Save Data Pointers message, but
1034 * only if we've actually been into a data phase to change them. This
1035 * protects against bogus data in scratch ram and the residual counts
1036 * since they are only initialized when we go into data_in or data_out.
1101 * Wait for DMA from host memory to data FIFO to complete, then disable
1102 * DMA and wait for it to acknowledge that it's off.
1037 */
1103 */
1038sg_ram2scb:
1039 test FLAGS, DPHASE jz return
1040 mov SCB_SGCOUNT,SG_COUNT
1104dma_finish:
1105 test DFSTATUS,HDONE jz dma_finish
1106 /* Turn off DMA preserving WIDEODD */
1107 and DFCNTRL,WIDEODD
1108dma_finish2:
1109 test DFCNTRL,HDMAENACK jnz dma_finish2
1110 ret
1041
1111
1042 mov SCB_SGPTR0,SG_NEXT0
1043 mov SCB_SGPTR1,SG_NEXT1
1044 mov SCB_SGPTR2,SG_NEXT2
1045 mov SCB_SGPTR3,SG_NEXT3
1046
1047 mov SCB_DATAPTR0,SHADDR0
1048 mov SCB_DATAPTR1,SHADDR1
1049 mov SCB_DATAPTR2,SHADDR2
1050 mov SCB_DATAPTR3,SHADDR3
1112index_untagged_scb:
1113 shr SINDEX, SCB_TCL, 4
1114 and SINDEX, 0x03 /* Bottom two bits of tid */
1115 add SINDEX, SCB_ACTIVE0
1116 shr A, SCB_TCL, 6 /* Target ID divided by 4 */
1117 test SCB_TCL, SELBUSB jz index_untagged_scb2
1118 or A, 2 /* Add 2 positions */
1119index_untagged_scb2:
1120 mov SCBPTR, A /*
1121 * Select the SCB with this
1122 * target's information.
1123 */
1124 mov DINDEX, SINDEX ret
1051
1125
1126
1127get_free_or_disc_scb:
1128 mov SINDEX, ALLZEROS
1129 cmp FREE_SCBH, SCB_LIST_NULL jne get_free_scb
1130 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je return_error
1131 mov SCBPTR, DISCONNECTED_SCBH
1052/*
1132/*
1053 * Use the residual number since STCNT is corrupted by any message transfer
1133 * If we are starting a new transaction, we have to ensure that
1134 * there is at least one SCB left in case a reselection wins out.
1054 */
1135 */
1055 mov SCB_DATACNT0,SCB_RESID_DCNT0
1056 mov SCB_DATACNT1,SCB_RESID_DCNT1
1057 mov SCB_DATACNT2,SCB_RESID_DCNT2 ret
1136 test FLAGS, RESELECTED jnz dequeue_disc_scb
1137 cmp SCB_NEXT, SCB_LIST_NULL je return_error
1138dequeue_disc_scb:
1139/*
1140 * If we have a residual, then we are in the middle of some I/O
1141 * and we have to send this SCB back up to the kernel so that the
1142 * saved data pointers and residual information isn't lost.
1143 */
1144 test SCB_RESID_SGCNT,0xff jz unlink_disc_scb
1145 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/
1146 mov SCB_TAG call dma_scb
1147unlink_disc_scb:
1148 call rem_scb_from_disc_list
1149 ret
1150get_free_scb:
1151/*
1152 * If we are starting a new transaction, we have to ensure that
1153 * there is at least one SCB left in case a reselection wins out.
1154 */
1155 test FLAGS, RESELECTED jnz dequeue_free_scb
1156 cmp SCB_NEXT, SCB_LIST_NULL jne dequeue_free_scb
1157 cmp DISCONNECTED_SCBH, SCB_LIST_NULL je return_error
1158dequeue_free_scb:
1159 mov SCBPTR, FREE_SCBH
1160 mov FREE_SCBH, SCB_NEXT ret
1161return_error:
1162 mvi SINDEX, SCB_LIST_NULL ret
1058
1163
1164add_scb_to_free_list:
1165 mov SCB_NEXT, FREE_SCBH
1166 mov FREE_SCBH, SCBPTR ret
1167
1168add_scb_to_disc_list:
1059/*
1169/*
1060 * Add the array base TARG_SCRATCH to the target offset (the target address
1061 * is in SCSIID), and return the result in SINDEX. The accumulator
1062 * contains the 3->8 decoding of the target ID on return.
1170 * Link this SCB into the DISCONNECTED list. This list holds the
1171 * candidates for paging out an SCB if one is needed for a new command.
1172 * Modifying the disconnected list is a critical(pause dissabled) section.
1063 */
1173 */
1064ndx_dtr:
1065 shr A,SCSIID,4
1066 test SBLKCTL,SELBUSB jz ndx_dtr_2
1067 or A,0x08 /* Channel B entries add 8 */
1068ndx_dtr_2:
1069 add SINDEX,TARG_SCRATCH,A ret
1174 mvi SCB_PREV, SCB_LIST_NULL
1175 mov SCB_NEXT, DISCONNECTED_SCBH
1176 mov DISCONNECTED_SCBH, SCBPTR
1177 cmp SCB_NEXT,SCB_LIST_NULL je return
1178 mov SCBPTR,SCB_NEXT
1179 mov SCB_PREV,DISCONNECTED_SCBH
1180 mov SCBPTR,DISCONNECTED_SCBH ret
1181