Deleted Added
full compact
aic7xxx.seq (23168) aic7xxx.seq (23925)
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,
9 *SCB paging and other optimizations:
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,
9 *SCB paging and other optimizations:
10 *Copyright (c) 1994, 1995, 1996 Justin Gibbs. All rights reserved.
10 *Copyright (c) 1994, 1995, 1996, 1997 Justin Gibbs. All rights reserved.
11 *
12 *Redistribution and use in source and binary forms, with or without
13 *modification, are permitted provided that the following conditions
14 *are met:
15 *1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer.
17 *2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the

--- 15 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
11 *
12 *Redistribution and use in source and binary forms, with or without
13 *modification, are permitted provided that the following conditions
14 *are met:
15 *1. Redistributions of source code must retain the above copyright
16 * notice, this list of conditions, and the following disclaimer.
17 *2. Redistributions in binary form must reproduce the above copyright
18 * notice, this list of conditions and the following disclaimer in the

--- 15 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.62 1997/02/25 03:02:56 gibbs Exp$"
42#include <dev/aic7xxx/aic7xxx.reg>
43#include <scsi/scsi_message.h>
43
44
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/*
45/*
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/*
61 * A few words on the waiting SCB list:
62 * After starting the selection hardware, we check for reconnecting targets
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

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

75 * automatically consume the entries.
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:
46 * A few words on the waiting SCB list:
47 * After starting the selection hardware, we check for reconnecting targets
48 * as well as for our selection to complete just in case the reselection wins
49 * bus arbitration. The problem with this is that we must keep track of the
50 * SCB that we've already pulled from the QINFIFO and started the selection
51 * on just in case the reselection wins so that we can retry the selection at
52 * a later time. This problem cannot be resolved by holding a single entry
53 * in scratch ram since a reconnecting target can request sense and this will

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

60 * automatically consume the entries.
61 */
62
63/*
64 * We assume that the kernel driver may reset us at any time, even in the
65 * middle of a DMA, so clear DFCNTRL too.
66 */
67reset:
83 clr SCSISIGO /* De-assert BSY */
84 mvi SCSISEQ,0x12 /* Always allow reselection
85 * ENRSELI|ENAUTOATNP
86 */
87p_busfree:
88 clr DFCNTRL
89 clr SCSIRATE /*
90 * We don't know the target we will
91 * connect to, so default to narrow
92 * transfers to avoid parity problems.
93 */
94 and SXFRCTL0, 0xdf /* ~FAST20*/
95 mvi LASTPHASE, P_BUSFREE
96 and FLAGS,0x07 /* clear target specific flags */
68 clr SCSISIGO; /* De-assert BSY */
69 /* Always allow reselection */
70 mvi SCSISEQ, ENRSELI|ENAUTOATNP;
71 call clear_target_state;
97poll_for_work:
72poll_for_work:
73 test SSTAT0,SELDI|SELDO jnz selection;
74 test SCSISEQ, ENSELO jnz poll_for_work;
75.if ( TWIN_CHANNEL )
98 /*
76 /*
99 * Are we a twin channel device?
100 * For fairness, we check the other bus first,
101 * since we just finished a transaction on the
102 * current channel.
77 * Twin channel devices cannot handle things like SELTO
78 * interrupts on the "background" channel. So, if we
79 * are selecting, keep polling the current channel util
80 * either a selection or reselection occurs.
103 */
81 */
104 test FLAGS,TWIN_BUS jz start2
105 xor SBLKCTL,SELBUSB /* Toggle to the other bus */
106 test SSTAT0,SELDI jnz reselect
107 xor SBLKCTL,SELBUSB /* Toggle to the original bus */
108start2:
109 test SSTAT0,SELDI jnz reselect
110 cmp WAITING_SCBH,SCB_LIST_NULL je test_queue
111start_waiting:
112 /*
113 * Pull the first entry off of the waiting SCB list
114 * We don't have to "test_busy" because only transactions that
115 * have passed that test can be in the WAITING_SCB list.
116 */
117 mov SCBPTR,WAITING_SCBH
118 jmp start_scb2
82 xor SBLKCTL,SELBUSB; /* Toggle to the other bus */
83 test SSTAT0,SELDI|SELDO jnz selection;
84 test SCSISEQ, ENSELO jnz poll_for_work;
85 xor SBLKCTL,SELBUSB; /* Toggle back */
86.endif
87 cmp WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
119test_queue:
120 /* Has the driver posted any work for us? */
88test_queue:
89 /* Has the driver posted any work for us? */
121 mov A, QCNTMASK
122 test QINCNT,A jz poll_for_work
90 mov A, QCNTMASK;
91 test QINCNT,A jz poll_for_work;
123
124/*
125 * We have at least one queued SCB now and we don't have any
126 * SCBs in the list of SCBs awaiting selection. If we have
92
93/*
94 * We have at least one queued SCB now and we don't have any
95 * SCBs in the list of SCBs awaiting selection. If we have
127 * any SCBs availible for use, pull the tag from the QINFIFO
96 * any SCBs available for use, pull the tag from the QINFIFO
128 * and get to work on it.
129 */
97 * and get to work on it.
98 */
130 test FLAGS, PAGESCBS jz dequeue_scb
131 mov ALLZEROS call get_free_or_disc_scb
132 cmp SINDEX, SCB_LIST_NULL je poll_for_work
99.if ( SCB_PAGING )
100 mov ALLZEROS call get_free_or_disc_scb;
101 cmp SINDEX, SCB_LIST_NULL je poll_for_work;
102.endif
133dequeue_scb:
103dequeue_scb:
134 mov CUR_SCBID,QINFIFO
135 test FLAGS, PAGESCBS jnz dma_queued_scb
104 mov CUR_SCBID,QINFIFO;
105.if !( SCB_PAGING )
136 /* In the non-paging case, the SCBID == hardware SCB index */
106 /* In the non-paging case, the SCBID == hardware SCB index */
137 mov SCBPTR, CUR_SCBID
107 mov SCBPTR, CUR_SCBID;
108.endif
138dma_queued_scb:
139/*
140 * DMA the SCB from host ram into the current SCB location.
141 */
109dma_queued_scb:
110/*
111 * DMA the SCB from host ram into the current SCB location.
112 */
142 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
143 mov CUR_SCBID call dma_scb
113 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
114 mov CUR_SCBID call dma_scb;
144
145/*
146 * See if there is not already an active SCB for this target. This code
147 * locks out on a per target basis instead of target/lun. Although this
148 * is not ideal for devices that have multiple luns active at the same
149 * time, it is faster than looping through all SCB's looking for active
150 * commands. We also don't have enough spare SCB space for us to store the
151 * SCBID of the currently busy transaction for each target/lun making it
152 * impossible to link up the SCBs.
153 */
154test_busy:
115
116/*
117 * See if there is not already an active SCB for this target. This code
118 * locks out on a per target basis instead of target/lun. Although this
119 * is not ideal for devices that have multiple luns active at the same
120 * time, it is faster than looping through all SCB's looking for active
121 * commands. We also don't have enough spare SCB space for us to store the
122 * SCBID of the currently busy transaction for each target/lun making it
123 * impossible to link up the SCBs.
124 */
125test_busy:
155 test SCB_CONTROL, TAG_ENB jnz start_scb
156 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
157 mov SAVED_SCBPTR, SCBPTR
158 mov SCB_TCL call index_untagged_scb
159 mov ARG_1, SINDIR /*
126 test SCB_CONTROL, TAG_ENB|ABORT_SCB jnz start_scb;
127 mvi SEQCTL, PAUSEDIS|FASTMODE;
128 mov SAVED_SCBPTR, SCBPTR;
129 mov SCB_TCL call index_untagged_scb;
130 mov ARG_1, SINDIR; /*
160 * ARG_1 should
161 * now have the SCB ID of
162 * any active, non-tagged,
163 * command for this target.
164 */
131 * ARG_1 should
132 * now have the SCB ID of
133 * any active, non-tagged,
134 * command for this target.
135 */
165 cmp ARG_1, SCB_LIST_NULL je make_busy
166 test FLAGS, PAGESCBS jz simple_busy_link
136 cmp ARG_1, SCB_LIST_NULL je make_busy;
137.if ( SCB_PAGING )
167 /*
168 * Put this SCB back onto the free list. It
169 * may be necessary to satisfy the search for
170 * the active SCB.
171 */
138 /*
139 * Put this SCB back onto the free list. It
140 * may be necessary to satisfy the search for
141 * the active SCB.
142 */
172 mov SCBPTR, SAVED_SCBPTR
173 call add_scb_to_free_list
143 mov SCBPTR, SAVED_SCBPTR;
144 call add_scb_to_free_list;
174 /* Find the active SCB */
145 /* Find the active SCB */
175 mov ALLZEROS call findSCB
146 mov ALLZEROS call findSCB;
176 /*
177 * If we couldn't find it, tell the kernel. This should
178 * never happen.
179 */
147 /*
148 * If we couldn't find it, tell the kernel. This should
149 * never happen.
150 */
180 cmp SINDEX, SCB_LIST_NULL jne paged_busy_link
181 mvi INTSTAT, NO_MATCH_BUSY
151 cmp SINDEX, SCB_LIST_NULL jne paged_busy_link;
152 mvi INTSTAT, NO_MATCH_BUSY;
182paged_busy_link:
183 /* Link us in */
153paged_busy_link:
154 /* Link us in */
184 mov SCB_LINKED_NEXT, CUR_SCBID
155 mov SCB_LINKED_NEXT, CUR_SCBID;
185 /* Put it back on the disconnected list */
156 /* Put it back on the disconnected list */
186 call add_scb_to_disc_list
187 mvi SEQCTL,0x10 /* FASTMODE */
188 jmp poll_for_work
157 call add_scb_to_disc_list;
158 mvi SEQCTL, FASTMODE;
159 jmp poll_for_work;
160.endif
189simple_busy_link:
161simple_busy_link:
190 mov SCBPTR, ARG_1
191 mov SCB_LINKED_NEXT, CUR_SCBID
192 mvi SEQCTL,0x10 /* FASTMODE */
193 jmp poll_for_work
162 mov SCBPTR, ARG_1;
163 mov SCB_LINKED_NEXT, CUR_SCBID;
164 mvi SEQCTL, FASTMODE;
165 jmp poll_for_work;
194make_busy:
166make_busy:
195 mov DINDIR, CUR_SCBID
196 mov SCBPTR, SAVED_SCBPTR
197 mvi SEQCTL,0x10 /* FASTMODE */
167 mov DINDIR, CUR_SCBID;
168 mov SCBPTR, SAVED_SCBPTR;
169 mvi SEQCTL, FASTMODE;
198
199start_scb:
200 /*
201 * Place us on the waiting list in case our selection
202 * doesn't win during bus arbitration.
203 */
170
171start_scb:
172 /*
173 * Place us on the waiting list in case our selection
174 * doesn't win during bus arbitration.
175 */
204 mov SCB_NEXT,WAITING_SCBH
205 mov WAITING_SCBH, SCBPTR
206start_scb2:
207 and SINDEX,0xf7,SBLKCTL /* Clear the channel select bit */
208 and A,0x08,SCB_TCL /* Get new channel bit */
209 or SINDEX,A
210 mov SBLKCTL,SINDEX /* select channel */
211 mov SCB_TCL call initialize_scsiid
176 mov SCB_NEXT,WAITING_SCBH;
177 mov WAITING_SCBH, SCBPTR;
178start_waiting:
179 /*
180 * Pull the first entry off of the waiting SCB list
181 * We don't have to "test_busy" because only transactions that
182 * have passed that test can be in the WAITING_SCB list.
183 */
184 mov SCBPTR, WAITING_SCBH;
185 call start_selection;
186 jmp poll_for_work;
212
187
188start_selection:
189 and SINDEX,~SELBUSB,SBLKCTL;/* Clear the channel select bit */
190 and A,SELBUSB,SCB_TCL; /* Get new channel bit */
191 or SINDEX,A;
192 mov SBLKCTL,SINDEX; /* select channel */
193initialize_scsiid:
194 and A, TID, SCB_TCL; /* Get target ID */
195 and SCSIID, OID; /* Clear old target */
196 or SCSIID, A;
197 mvi SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
213/*
198/*
214 * Enable selection phase as an initiator, and do automatic ATN
215 * after the selection. We do this now so that we can overlap the
216 * rest of our work to set up this target with the arbitration and
217 * selection bus phases.
199 * Reselection has been initiated by a target. Make a note that we've been
200 * reselected, but haven't seen an IDENTIFY message from the target yet.
218 */
201 */
219start_selection:
220 mvi SCSISEQ,0x5a /* ENSELO|ENAUTOATNO|ENRSELI
221 * |ENAUTOATNP
222 */
202selection:
203 test SSTAT0, SELDI jz select;
204reselect:
205 clr MSG_LEN; /* Don't have anything in the mesg buffer */
206 mvi CLRSINT0, CLRSELDI;
207 /* XXX test for and handle ONE BIT condition */
208 and SAVED_TCL, SELID_MASK, SELID;
209 or SEQ_FLAGS,RESELECTED;
210 jmp select2;
223
224/*
211
212/*
213 * After the selection, remove this SCB from the "waiting SCB"
214 * list. This is achieved by simply moving our "next" pointer into
215 * WAITING_SCBH. Our next pointer will be set to null the next time this
216 * SCB is used, so don't bother with it now.
217 */
218select:
219 /* Turn off the selection hardware */
220 mvi SCSISEQ, ENRSELI|ENAUTOATNP; /*
221 * ATN on parity errors
222 * for "in" phases
223 */
224 mvi CLRSINT0, CLRSELDO;
225 mov SCBPTR, WAITING_SCBH;
226 mov WAITING_SCBH,SCB_NEXT;
227 mov SAVED_TCL, SCB_TCL;
228/*
225 * As soon as we get a successful selection, the target should go
226 * into the message out phase since we have ATN asserted. Prepare
227 * the message to send.
228 *
229 * Messages are stored in scratch RAM starting with a length byte
230 * followed by the message itself.
231 */
232
233mk_identify:
229 * As soon as we get a successful selection, the target should go
230 * into the message out phase since we have ATN asserted. Prepare
231 * the message to send.
232 *
233 * Messages are stored in scratch RAM starting with a length byte
234 * followed by the message itself.
235 */
236
237mk_identify:
234 and MSG0,0x7,SCB_TCL /* lun */
235 and A,DISCENB,SCB_CONTROL /* mask off disconnect privledge */
236 or MSG0,A /* or in disconnect privledge */
237 or MSG0,MSG_IDENTIFYFLAG
238 mvi MSG_LEN, 1
238 and MSG_OUT,0x7,SCB_TCL; /* lun */
239 and A,DISCENB,SCB_CONTROL; /* mask off disconnect privledge */
240 or MSG_OUT,A; /* or in disconnect privledge */
241 or MSG_OUT,MSG_IDENTIFYFLAG;
242 mvi MSG_LEN, 1;
239
240/*
241 * Send a tag message if TAG_ENB is set in the SCB control block.
242 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
243 */
244mk_tag:
243
244/*
245 * Send a tag message if TAG_ENB is set in the SCB control block.
246 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
247 */
248mk_tag:
245 test SCB_CONTROL,TAG_ENB jz mk_message
246 and MSG1,0x23,SCB_CONTROL
247 mov MSG2,SCB_TAG
248 add MSG_LEN,2 /* update message length */
249 test SCB_CONTROL,TAG_ENB jz mk_message;
250 and MSG_OUT[1],TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
251 mov MSG_OUT[2],SCB_TAG;
252 add MSG_LEN,2; /* update message length */
249
250/*
251 * Interrupt the driver, and allow it to tweak the message buffer
252 * if it asks.
253 */
254mk_message:
253
254/*
255 * Interrupt the driver, and allow it to tweak the message buffer
256 * if it asks.
257 */
258mk_message:
255 test SCB_CONTROL,MK_MESSAGE jz wait_for_selection
259 test SCB_CONTROL,MK_MESSAGE jz select2;
260 mvi INTSTAT,AWAITING_MSG;
256
261
257 mvi INTSTAT,AWAITING_MSG
258
259wait_for_selection:
260 test SSTAT0,SELDO jnz select
261 test SSTAT0,SELDI jz wait_for_selection
262
263/*
264 * Reselection has been initiated by a target. Make a note that we've been
265 * reselected, but haven't seen an IDENTIFY message from the target yet.
266 */
267reselect:
268 clr MSG_LEN /* Don't have anything in the mesg buffer */
269 /* XXX test for and handle ONE BIT condition */
270 and SAVED_TCL, 0xf0, SELID
271 or FLAGS,RESELECTED
272 jmp select2
273
274/*
275 * After the selection, remove this SCB from the "waiting SCB"
276 * list. This is achieved by simply moving our "next" pointer into
277 * WAITING_SCBH. Our next pointer will be set to null the next time this
278 * SCB is used, so don't bother with it now.
279 */
280select:
281 mov WAITING_SCBH,SCB_NEXT
282select2:
262select2:
283 /* Turn off the selection hardware */
284 mvi SCSISEQ, 0x12 /* ENRSELI|ENAUTOATNP
285 * ATN on parity errors
286 * for "in" phases
287 */
288 mvi CLRSINT0,0x60 /* CLRSELDI|CLRSELDO */
289 mvi CLRSINT1,CLRBUSFREE
290 or SIMODE1, ENBUSFREE /*
263 mvi CLRSINT1,CLRBUSFREE;
264 or SIMODE1, ENBUSFREE; /*
291 * We aren't expecting a
292 * bus free, so interrupt
293 * the kernel driver if it
294 * happens.
295 */
296/*
297 * Initialize Ultra mode setting and clear the SCSI channel.
298 */
265 * We aren't expecting a
266 * bus free, so interrupt
267 * the kernel driver if it
268 * happens.
269 */
270/*
271 * Initialize Ultra mode setting and clear the SCSI channel.
272 */
299 or SXFRCTL0, 0x1a /* CLRSTCNT|SPIOEN|CLRCHN */
273 or SXFRCTL0, CLRSTCNT|SPIOEN|CLRCHN;
274.if ( ULTRA )
300ultra:
275ultra:
301 mvi SINDEX, ULTRA_ENB_B
302 test SAVED_TCL, 0x80 jnz ultra_2 /* Target ID > 7 */
303 test SBLKCTL, SELBUSB jnz ultra_2 /* Second channel */
304 dec SINDEX
276 mvi SINDEX, ULTRA_ENB+1;
277 test SAVED_TCL, 0x80 jnz ultra_2; /* Target ID > 7 */
278 dec SINDEX;
305ultra_2:
279ultra_2:
306 mov FUNCTION1,SAVED_TCL
307 mov A,FUNCTION1
308 test SINDIR, A jz ndx_dtr
309 or SXFRCTL0, FAST20
280 mov FUNCTION1,SAVED_TCL;
281 mov A,FUNCTION1;
282 test SINDIR, A jz ndx_dtr;
283 or SXFRCTL0, FAST20;
284.endif
310
311/*
312 * Initialize SCSIRATE with the appropriate value for this target.
313 * The SCSIRATE settings for each target are stored in an array
314 * based at TARG_SCRATCH.
315 */
316ndx_dtr:
285
286/*
287 * Initialize SCSIRATE with the appropriate value for this target.
288 * The SCSIRATE settings for each target are stored in an array
289 * based at TARG_SCRATCH.
290 */
291ndx_dtr:
317 shr A,SAVED_TCL,4
318 test SBLKCTL,SELBUSB jz ndx_dtr_2
319 or SAVED_TCL, SELBUSB /* Add the channel bit while we're here */
320 or A,0x08 /* Channel B entries add 8 */
292 shr A,4,SAVED_TCL;
293 test SBLKCTL,SELBUSB jz ndx_dtr_2;
294 or SAVED_TCL, SELBUSB; /* Add the channel bit while we're here */
295 or A,0x08; /* Channel B entries add 8 */
321ndx_dtr_2:
296ndx_dtr_2:
322 add SINDEX,TARG_SCRATCH,A
323 mov SCSIRATE,SINDIR
297 add SINDEX,TARG_SCRATCH,A;
298 mov SCSIRATE,SINDIR;
324
325
326/*
327 * Main loop for information transfer phases. If BSY is false, then
328 * we have a bus free condition, expected or not. Otherwise, wait
329 * for the target to assert REQ before checking MSG, C/D and I/O
330 * for the bus phase.
331 *
332 */
333ITloop:
299
300
301/*
302 * Main loop for information transfer phases. If BSY is false, then
303 * we have a bus free condition, expected or not. Otherwise, wait
304 * for the target to assert REQ before checking MSG, C/D and I/O
305 * for the bus phase.
306 *
307 */
308ITloop:
334 test SSTAT1,0x9 jz ITloop /* REQINIT|BUSFREE */
335 test SSTAT1,BUSFREE jnz p_busfree
309 test SSTAT1,REQINIT jz ITloop;
336
310
337 and A,PHASE_MASK,SCSISIGI
338 mov LASTPHASE,A
339 mov SCSISIGO,A
311 and A,PHASE_MASK,SCSISIGI;
312 mov LASTPHASE,A;
313 mov SCSISIGO,A;
340
314
341 cmp ALLZEROS,A je p_dataout
342 cmp A,P_DATAIN je p_datain
343 cmp A,P_COMMAND je p_command
344 cmp A,P_MESGOUT je p_mesgout
345 cmp A,P_STATUS je p_status
346 cmp A,P_MESGIN je p_mesgin
315 cmp ALLZEROS,A je p_dataout;
316 cmp A,P_DATAIN je p_datain;
317 cmp A,P_COMMAND je p_command;
318 cmp A,P_MESGOUT je p_mesgout;
319 cmp A,P_STATUS je p_status;
320 cmp A,P_MESGIN je p_mesgin;
347
321
348 mvi INTSTAT,BAD_PHASE /* unknown phase - signal driver */
349 jmp ITloop /* Try reading the bus again. */
322 mvi INTSTAT,BAD_PHASE; /* unknown phase - signal driver */
323 jmp ITloop; /* Try reading the bus again. */
350
324
325await_busfree:
326 and SIMODE1, ~ENBUSFREE;
327 mov NONE, SCSIDATL; /* Ack the last byte */
328 call clear_target_state;
329 test SSTAT1,REQINIT|BUSFREE jz .;
330 test SSTAT1, BUSFREE jnz poll_for_work;
331 mvi INTSTAT, BAD_PHASE;
332
333clear_target_state:
334 clr DFCNTRL;
335 clr SCSIRATE; /*
336 * We don't know the target we will
337 * connect to, so default to narrow
338 * transfers to avoid parity problems.
339 */
340 and SXFRCTL0, ~FAST20;
341 mvi LASTPHASE, P_BUSFREE;
342 /* clear target specific flags */
343 and SEQ_FLAGS,~(RESELECTED|IDENTIFY_SEEN|TAGGED_SCB|DPHASE) ret;
344
351p_dataout:
345p_dataout:
352 mvi DMAPARAMS,0x7d /*
353 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
354 * DIRECTION|FIFORESET
355 */
356 jmp data_phase_init
346 mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET;
347 jmp data_phase_init;
357
358/*
359 * If we re-enter the data phase after going through another phase, the
360 * STCNT may have been cleared, so restore it from the residual field.
361 */
362data_phase_reinit:
348
349/*
350 * If we re-enter the data phase after going through another phase, the
351 * STCNT may have been cleared, so restore it from the residual field.
352 */
353data_phase_reinit:
363 mvi DINDEX, STCNT0
364 mvi SCB_RESID_DCNT0 call bcopy_3
365 jmp data_phase_loop
354 mvi DINDEX, STCNT;
355 mvi SCB_RESID_DCNT call bcopy_3;
356 jmp data_phase_loop;
366
367p_datain:
357
358p_datain:
368 mvi DMAPARAMS,0x79 /*
369 * WIDEODD|SCSIEN|SDMAEN|HDMAEN|
370 * !DIRECTION|FIFORESET
371 */
359 mvi DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
372data_phase_init:
360data_phase_init:
373 call assert /*
361 call assert; /*
374 * Ensure entering a data
375 * phase is okay - seen identify, etc.
376 */
377
362 * Ensure entering a data
363 * phase is okay - seen identify, etc.
364 */
365
378 test FLAGS, DPHASE jnz data_phase_reinit
366 test SEQ_FLAGS, DPHASE jnz data_phase_reinit;
379
380 /*
381 * Initialize the DMA address and counter from the SCB.
382 * Also set SG_COUNT and SG_NEXT in memory since we cannot
383 * modify the values in the SCB itself until we see a
384 * save data pointers message.
385 */
367
368 /*
369 * Initialize the DMA address and counter from the SCB.
370 * Also set SG_COUNT and SG_NEXT in memory since we cannot
371 * modify the values in the SCB itself until we see a
372 * save data pointers message.
373 */
386 mvi DINDEX, HADDR0
387 mvi SCB_DATAPTR call bcopy_7
374 mvi DINDEX, HADDR;
375 mvi SCB_DATAPTR call bcopy_7;
388
376
389 call set_stcnt_from_hcnt
377 call set_stcnt_from_hcnt;
390
378
391 mov SG_COUNT,SCB_SGCOUNT
379 mov SG_COUNT,SCB_SGCOUNT;
392
380
393 mvi DINDEX, SG_NEXT
394 mvi SCB_SGPTR call bcopy_4
381 mvi DINDEX, SG_NEXT;
382 mvi SCB_SGPTR call bcopy_4;
395
396data_phase_loop:
397/* Guard against overruns */
383
384data_phase_loop:
385/* Guard against overruns */
398 test SG_COUNT, 0xff jnz data_phase_inbounds
386 test SG_COUNT, 0xff jnz data_phase_inbounds;
399/*
400 * Turn on 'Bit Bucket' mode, set the transfer count to
401 * 16meg and let the target run until it changes phase.
402 * When the transfer completes, notify the host that we
403 * had an overrun.
404 */
387/*
388 * Turn on 'Bit Bucket' mode, set the transfer count to
389 * 16meg and let the target run until it changes phase.
390 * When the transfer completes, notify the host that we
391 * had an overrun.
392 */
405 or SXFRCTL1,BITBUCKET
406 mvi HCNT0, 0xff
407 mvi HCNT1, 0xff
408 mvi HCNT2, 0xff
409 call set_stcnt_from_hcnt
393 or SXFRCTL1,BITBUCKET;
394 mvi HCNT[0], 0xff;
395 mvi HCNT[1], 0xff;
396 mvi HCNT[2], 0xff;
397 call set_stcnt_from_hcnt;
410
411data_phase_inbounds:
412/* If we are the last SG block, ensure wideodd is off. */
398
399data_phase_inbounds:
400/* If we are the last SG block, ensure wideodd is off. */
413 cmp SG_COUNT,0x01 jne data_phase_wideodd
414 and DMAPARAMS, 0xbf /* Turn off WIDEODD */
401 cmp SG_COUNT,0x01 jne data_phase_wideodd;
402 and DMAPARAMS, ~WIDEODD;
415data_phase_wideodd:
403data_phase_wideodd:
416 mov DMAPARAMS call dma
404 mov DMAPARAMS call dma;
417
418/* Go tell the host about any overruns */
405
406/* Go tell the host about any overruns */
419 test SXFRCTL1,BITBUCKET jnz data_phase_overrun
407 test SXFRCTL1,BITBUCKET jnz data_phase_overrun;
420
421/* Exit if we had an underrun. dma clears SINDEX in this case. */
408
409/* Exit if we had an underrun. dma clears SINDEX in this case. */
422 test SINDEX,0xff jz data_phase_finish
410 test SINDEX,0xff jz data_phase_finish;
423
424/*
425 * Advance the scatter-gather pointers if needed
426 */
427sg_advance:
411
412/*
413 * Advance the scatter-gather pointers if needed
414 */
415sg_advance:
428 dec SG_COUNT /* one less segment to go */
416 dec SG_COUNT; /* one less segment to go */
429
417
430 test SG_COUNT, 0xff jz data_phase_finish /* Are we done? */
418 test SG_COUNT, 0xff jz data_phase_finish; /* Are we done? */
431
419
432 clr A /* add sizeof(struct scatter) */
433 add SG_NEXT0,SG_SIZEOF,SG_NEXT0
434 adc SG_NEXT1,A,SG_NEXT1
420 clr A; /* add sizeof(struct scatter) */
421 add SG_NEXT[0],SG_SIZEOF;
422 adc SG_NEXT[1],A;
435
436/*
437 * Load a struct scatter and set up the data address and length.
438 * If the working value of the SG count is nonzero, then
439 * we need to load a new set of values.
440 *
441 * This, like all DMA's, assumes little-endian host data storage.
442 */
443sg_load:
423
424/*
425 * Load a struct scatter and set up the data address and length.
426 * If the working value of the SG count is nonzero, then
427 * we need to load a new set of values.
428 *
429 * This, like all DMA's, assumes little-endian host data storage.
430 */
431sg_load:
444 mvi DINDEX, HADDR0
445 mvi SG_NEXT0 call bcopy_4
432 mvi DINDEX, HADDR;
433 mvi SG_NEXT call bcopy_4;
446
434
447 mvi HCNT0,SG_SIZEOF
448 clr HCNT1
449 clr HCNT2
435 mvi HCNT[0],SG_SIZEOF;
436 clr HCNT[1];
437 clr HCNT[2];
450
438
451 or DFCNTRL,0xd /* HDMAEN|DIRECTION|FIFORESET */
439 or DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
452
440
453 call dma_finish
441 call dma_finish;
454
455/*
456 * Copy data from FIFO into SCB data pointer and data count. This assumes
457 * that the SG segments are of the form:
458 *
459 * struct ahc_dma_seg {
460 * u_int32_t addr; four bytes, little-endian order
461 * u_int32_t len; four bytes, little endian order
462 * };
463 */
442
443/*
444 * Copy data from FIFO into SCB data pointer and data count. This assumes
445 * that the SG segments are of the form:
446 *
447 * struct ahc_dma_seg {
448 * u_int32_t addr; four bytes, little-endian order
449 * u_int32_t len; four bytes, little endian order
450 * };
451 */
464 mvi HADDR0 call dfdat_in_7
452 mvi HADDR call dfdat_in_7;
465
466/* Load STCNT as well. It is a mirror of HCNT */
453
454/* Load STCNT as well. It is a mirror of HCNT */
467 call set_stcnt_from_hcnt
468 test SSTAT1,PHASEMIS jz data_phase_loop
455 call set_stcnt_from_hcnt;
456 test SSTAT1,PHASEMIS jz data_phase_loop;
469
470data_phase_finish:
471/*
472 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
473 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
474 * were transferred on the SCSI (as opposed to the host) bus.
475 */
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 */
476 mov SCB_RESID_DCNT0,STCNT0
477 mov SCB_RESID_DCNT1,STCNT1
478 mov SCB_RESID_DCNT2,STCNT2
479 mov SCB_RESID_SGCNT, SG_COUNT
464 mov SCB_RESID_DCNT[0],STCNT[0];
465 mov SCB_RESID_DCNT[1],STCNT[1];
466 mov SCB_RESID_DCNT[2],STCNT[2];
467 mov SCB_RESID_SGCNT, SG_COUNT;
480
481 /* We have seen a data phase */
468
469 /* We have seen a data phase */
482 or FLAGS, DPHASE
470 or SEQ_FLAGS, DPHASE;
483
471
484 jmp ITloop
472 jmp ITloop;
485
486data_phase_overrun:
487/*
488 * Turn off BITBUCKET mode and notify the host
489 */
473
474data_phase_overrun:
475/*
476 * Turn off BITBUCKET mode and notify the host
477 */
490 and SXFRCTL1,0x7f /* ~BITBUCKET */
491 mvi INTSTAT,DATA_OVERRUN
492 jmp ITloop
478 and SXFRCTL1, ~BITBUCKET;
479 mvi INTSTAT,DATA_OVERRUN;
480 jmp ITloop;
493
494/*
495 * Command phase. Set up the DMA registers and let 'er rip.
496 */
497p_command:
481
482/*
483 * Command phase. Set up the DMA registers and let 'er rip.
484 */
485p_command:
498 call assert
486 call assert;
499
500/*
501 * Load HADDR and HCNT.
502 */
487
488/*
489 * Load HADDR and HCNT.
490 */
503 mvi DINDEX, HADDR0
504 mvi SCB_CMDPTR call bcopy_5
505 clr HCNT1
506 clr HCNT2
491 mvi DINDEX, HADDR;
492 mvi SCB_CMDPTR call bcopy_5;
493 clr HCNT[1];
494 clr HCNT[2];
507
495
508 call set_stcnt_from_hcnt
496 call set_stcnt_from_hcnt;
509
497
510 mvi 0x3d call dma /* SCSIEN|SDMAEN|HDMAEN
511 * |DIRECTION|FIFORESET
512 */
513 jmp ITloop
498 mvi (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;
499 jmp ITloop;
514
515/*
516 * Status phase. Wait for the data byte to appear, then read it
517 * and store it into the SCB.
518 */
519p_status:
500
501/*
502 * Status phase. Wait for the data byte to appear, then read it
503 * and store it into the SCB.
504 */
505p_status:
520 call assert
506 call assert;
521
507
522 mov SCB_TARGET_STATUS, SCSIDATL
523 jmp ITloop
508 mov SCB_TARGET_STATUS, SCSIDATL;
509 jmp ITloop;
524
525/*
526 * Message out phase. If there is not an active message, but the target
527 * took us into this phase anyway, build a no-op message and send it.
528 */
529p_mesgout:
510
511/*
512 * Message out phase. If there is not an active message, but the target
513 * took us into this phase anyway, build a no-op message and send it.
514 */
515p_mesgout:
530 test MSG_LEN, 0xff jnz p_mesgout_start
531 mvi MSG_NOOP call mk_mesg /* build NOP message */
516 test MSG_LEN, 0xff jnz p_mesgout_start;
517 mvi MSG_NOOP call mk_mesg; /* build NOP message */
532p_mesgout_start:
533/*
518p_mesgout_start:
519/*
534 * Set up automatic PIO transfer from MSG0. Bit 3 in
520 * Set up automatic PIO transfer from MSG_OUT. Bit 3 in
535 * SXFRCTL0 (SPIOEN) is already on.
536 */
521 * SXFRCTL0 (SPIOEN) is already on.
522 */
537 mvi SINDEX,MSG0
538 mov DINDEX,MSG_LEN
523 mvi SINDEX,MSG_OUT;
524 mov DINDEX,MSG_LEN;
539
540/*
541 * When target asks for a byte, drop ATN if it's the last one in
542 * the message. Otherwise, keep going until the message is exhausted.
525
526/*
527 * When target asks for a byte, drop ATN if it's the last one in
528 * the message. Otherwise, keep going until the message is exhausted.
529 * ATN must be dropped *at least* 90ns before we ack the last byte, so
530 * the code is aranged to execute two instructions before the byte is
531 * transferred to give a good margin of safety
543 *
544 * Keep an eye out for a phase change, in case the target issues
545 * a MESSAGE REJECT.
546 */
547p_mesgout_loop:
532 *
533 * Keep an eye out for a phase change, in case the target issues
534 * a MESSAGE REJECT.
535 */
536p_mesgout_loop:
548 test SSTAT1, REQINIT jz p_mesgout_loop
549 and LASTPHASE, PHASE_MASK, SCSISIGI
550 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done
537 test SSTAT1, REQINIT jz p_mesgout_loop;
538 and LASTPHASE, PHASE_MASK, SCSISIGI;
539 cmp LASTPHASE, P_MESGOUT jne p_mesgout_done;
551/*
552 * If the next bus phase after ATN drops is a message out, it means
553 * that the target is requesting that the last message(s) be resent.
554 */
540/*
541 * If the next bus phase after ATN drops is a message out, it means
542 * that the target is requesting that the last message(s) be resent.
543 */
555p_mesgout_testretry:
556 test DINDEX,0xff jnz p_mesgout_dropatn
557 or SCSISIGO,ATNO,LASTPHASE /* turn on ATN for the retry */
558 jmp p_mesgout_start
559p_mesgout_dropatn:
544p_mesgout_dropatn:
560 cmp DINDEX,1 jne p_mesgout_outb /* last byte? */
561 mvi CLRSINT1,CLRATNO /* drop ATN */
545 cmp DINDEX,1 jne p_mesgout_testretry;/* last byte? */
546 mvi CLRSINT1,CLRATNO; /* drop ATN */
547p_mesgout_testretry:
548 test DINDEX,0xff jnz p_mesgout_outb;
549 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
550 jmp p_mesgout_start;
562p_mesgout_outb:
551p_mesgout_outb:
563 mov SCSIDATL,SINDIR
564 dec DINDEX
565 jmp p_mesgout_loop
552 dec DINDEX;
553 mov SCSIDATL,SINDIR;
554 jmp p_mesgout_loop;
566
567p_mesgout_done:
555
556p_mesgout_done:
568 mvi CLRSINT1,CLRATNO /* Be sure to turn ATNO off */
569 clr MSG_LEN /* no active msg */
570 jmp ITloop
557 mvi CLRSINT1,CLRATNO; /* Be sure to turn ATNO off */
558 clr MSG_LEN; /* no active msg */
559 jmp ITloop;
571
572/*
573 * Message in phase. Bytes are read using Automatic PIO mode.
574 */
575p_mesgin:
560
561/*
562 * Message in phase. Bytes are read using Automatic PIO mode.
563 */
564p_mesgin:
576 mvi A call inb_first /* read the 1st message byte */
577 mov REJBYTE,A /* save it for the driver */
565 mvi ACCUM call inb_first; /* read the 1st message byte */
566 mov REJBYTE,A; /* save it for the driver */
578
567
579 test A,MSG_IDENTIFYFLAG jnz mesgin_identify
580 cmp A,MSG_DISCONNECT je mesgin_disconnect
581 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs
582 cmp ALLZEROS,A je mesgin_complete
583 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs
584 cmp A,MSG_EXTENDED je mesgin_extended
585 cmp A,MSG_MESSAGE_REJECT je mesgin_reject
586 cmp A,MSG_NOOP je mesgin_done
568 test A,MSG_IDENTIFYFLAG jnz mesgin_identify;
569 cmp A,MSG_DISCONNECT je mesgin_disconnect;
570 cmp A,MSG_SAVEDATAPOINTER je mesgin_sdptrs;
571 cmp ALLZEROS,A je mesgin_complete;
572 cmp A,MSG_RESTOREPOINTERS je mesgin_rdptrs;
573 cmp A,MSG_EXTENDED je mesgin_extended;
574 cmp A,MSG_MESSAGE_REJECT je mesgin_reject;
575 cmp A,MSG_NOOP je mesgin_done;
587
588rej_mesgin:
589/*
590 * We have no idea what this message in is, so we issue a message reject
591 * and hope for the best. In any case, rejection should be a rare
592 * occurrence - signal the driver when it happens.
593 */
576
577rej_mesgin:
578/*
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.
582 */
594 mvi INTSTAT,SEND_REJECT /* let driver know */
583 mvi INTSTAT,SEND_REJECT; /* let driver know */
595
584
596 mvi MSG_MESSAGE_REJECT call mk_mesg
585 mvi MSG_MESSAGE_REJECT call mk_mesg;
597
598mesgin_done:
586
587mesgin_done:
599 call inb_last
600 jmp ITloop
588 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
589 jmp ITloop;
601
602
603mesgin_complete:
604/*
605 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
606 * and trigger a completion interrupt. Before doing so, check to see if there
607 * is a residual or the status byte is something other than NO_ERROR (0). In
608 * either of these conditions, we upload the SCB back to the host so it can

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

615 * If the kernel driver does not wish to request sense, it need only clear
616 * RETURN_1, and the command is allowed to complete normally. We don't bother
617 * to post to the QOUTFIFO in the error cases since it would require extra
618 * work in the kernel driver to ensure that the entry was removed before the
619 * command complete code tried processing it.
620 */
621
622/*
590
591
592mesgin_complete:
593/*
594 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
595 * and trigger a completion interrupt. Before doing so, check to see if there
596 * is a residual or the status byte is something other than NO_ERROR (0). In
597 * either of these conditions, we upload the SCB back to the host so it can

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

604 * If the kernel driver does not wish to request sense, it need only clear
605 * RETURN_1, and the command is allowed to complete normally. We don't bother
606 * to post to the QOUTFIFO in the error cases since it would require extra
607 * work in the kernel driver to ensure that the entry was removed before the
608 * command complete code tried processing it.
609 */
610
611/*
623 * We expect to go to bus free after this message.
624 */
625 and SIMODE1, 0xf7 /* ~ENBUSFREE */
626/*
627 * First check for residuals
628 */
612 * First check for residuals
613 */
629 test SCB_RESID_SGCNT,0xff jnz upload_scb
630 test SCB_TARGET_STATUS,0xff jz status_ok /* Good Status? */
614 test SCB_RESID_SGCNT,0xff jnz upload_scb;
615 test SCB_TARGET_STATUS,0xff jz status_ok; /* Good Status? */
631upload_scb:
616upload_scb:
632 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/
633 mov SCB_TAG call dma_scb
617 mvi DMAPARAMS, FIFORESET;
618 mov SCB_TAG call dma_scb;
634check_status:
619check_status:
635 test SCB_TARGET_STATUS,0xff jz status_ok /* Just a residual? */
636 mvi INTSTAT,BAD_STATUS /* let driver know */
637 cmp RETURN_1, SEND_SENSE jne status_ok
620 test SCB_TARGET_STATUS,0xff jz status_ok; /* Just a residual? */
621 mvi INTSTAT,BAD_STATUS; /* let driver know */
622 cmp RETURN_1, SEND_SENSE jne status_ok;
638 /* This SCB becomes the next to execute as it will retrieve sense */
623 /* This SCB becomes the next to execute as it will retrieve sense */
639 mov SCB_LINKED_NEXT, SCB_TAG
640 jmp dma_next_scb
624 mov SCB_LINKED_NEXT, SCB_TAG;
625 jmp dma_next_scb;
641
642status_ok:
643/* First, mark this target as free. */
626
627status_ok:
628/* First, mark this target as free. */
644 test SCB_CONTROL,TAG_ENB jnz complete /*
629 test SCB_CONTROL,TAG_ENB jnz complete; /*
645 * Tagged commands
646 * don't busy the
647 * target.
648 */
630 * Tagged commands
631 * don't busy the
632 * target.
633 */
649 mov SAVED_SCBPTR, SCBPTR
650 mov SAVED_LINKPTR, SCB_LINKED_NEXT
651 mov SCB_TCL call index_untagged_scb
652 mov DINDIR, SAVED_LINKPTR
653 mov SCBPTR, SAVED_SCBPTR
634 mov SAVED_SCBPTR, SCBPTR;
635 mov SAVED_LINKPTR, SCB_LINKED_NEXT;
636 mov SCB_TCL call index_untagged_scb;
637 mov DINDIR, SAVED_LINKPTR;
638 mov SCBPTR, SAVED_SCBPTR;
654
655complete:
656 /* Post the SCB and issue an interrupt */
639
640complete:
641 /* Post the SCB and issue an interrupt */
657 mov QOUTFIFO,SCB_TAG
658 mvi INTSTAT,CMDCMPLT
659 test SCB_CONTROL, ABORT_SCB jz dma_next_scb
660 mvi INTSTAT ABORT_CMDCMPLT
642 mov QOUTFIFO,SCB_TAG;
643 mvi INTSTAT,CMDCMPLT;
644 test SCB_CONTROL, ABORT_SCB jz dma_next_scb;
645 mvi INTSTAT, ABORT_CMDCMPLT;
661
662dma_next_scb:
646
647dma_next_scb:
663 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je add_to_free_list
664 test FLAGS, PAGESCBS jnz dma_next_scb2
648 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je add_to_free_list;
649.if !( SCB_PAGING )
665 /* Only DMA on top of ourselves if we are the SCB to download */
650 /* Only DMA on top of ourselves if we are the SCB to download */
666 mov A, SCB_LINKED_NEXT
667 cmp SCB_TAG, A je dma_next_scb2
668 mov SCBPTR, A
669 jmp add_to_waiting_list
651 mov A, SCB_LINKED_NEXT;
652 cmp SCB_TAG, A je dma_next_scb2;
653 mov SCBPTR, A;
654 jmp add_to_waiting_list;
655.endif
670dma_next_scb2:
656dma_next_scb2:
671 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
672 mov SCB_LINKED_NEXT call dma_scb
657 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
658 mov SCB_LINKED_NEXT call dma_scb;
673add_to_waiting_list:
659add_to_waiting_list:
674 mov SCB_NEXT,WAITING_SCBH
675 mov WAITING_SCBH, SCBPTR
676 jmp mesgin_done
660 mov SCB_NEXT,WAITING_SCBH;
661 mov WAITING_SCBH, SCBPTR;
662 /*
663 * Prepare our selection hardware before the busfree so we have a
664 * high probability of winning arbitration.
665 */
666 call start_selection;
667 jmp await_busfree;
677add_to_free_list:
668add_to_free_list:
678 call add_scb_to_free_list
679 jmp mesgin_done
669 call add_scb_to_free_list;
670 jmp await_busfree;
680
681/*
682 * Is it an extended message? Copy the message to our message buffer and
683 * notify the host. The host will tell us whether to reject this message,
684 * respond to it with the message that the host placed in our message buffer,
685 * or simply to do nothing.
686 */
687mesgin_extended:
671
672/*
673 * Is it an extended message? Copy the message to our message buffer and
674 * notify the host. The host will tell us whether to reject this message,
675 * respond to it with the message that the host placed in our message buffer,
676 * or simply to do nothing.
677 */
678mesgin_extended:
688 mvi MSGIN_EXT_LEN call inb_next
689 mov A, MSGIN_EXT_LEN
679 mvi MSGIN_EXT_LEN call inb_next;
680 mov A, MSGIN_EXT_LEN;
690mesgin_extended_loop:
681mesgin_extended_loop:
691 mov DINDEX call inb_next
692 dec A
693 cmp DINDEX, MSGIN_EXT_LASTBYTE jne mesgin_extended_loop_test
694 dec DINDEX /* dump by repeatedly filling the last byte */
682 mov DINDEX call inb_next;
683 dec A;
684 cmp DINDEX, MSGIN_EXT_BYTES+3 jne mesgin_extended_loop_test;
685 dec DINDEX; /* dump by repeatedly filling the last byte */
695mesgin_extended_loop_test:
686mesgin_extended_loop_test:
696 test A, 0xFF jnz mesgin_extended_loop
687 test A, 0xFF jnz mesgin_extended_loop;
697mesgin_extended_intr:
688mesgin_extended_intr:
698 mvi INTSTAT,EXTENDED_MSG /* let driver know */
699 cmp RETURN_1,SEND_REJ je rej_mesgin
700 cmp RETURN_1,SEND_MSG jne mesgin_done
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;
701/* The kernel has setup a message to be sent */
692/* The kernel has setup a message to be sent */
702 or SCSISIGO,ATNO,LASTPHASE /* turn on ATNO */
703 jmp mesgin_done
693 or SCSISIGO,ATNO,LASTPHASE; /* turn on ATNO */
694 jmp mesgin_done;
704
705/*
706 * Is it a disconnect message? Set a flag in the SCB to remind us
707 * and await the bus going free.
708 */
709mesgin_disconnect:
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:
710 and SIMODE1, 0xf7 /* ~ENBUSFREE */
711 or SCB_CONTROL,DISCONNECTED
712 test FLAGS, PAGESCBS jz mesgin_done
713 call add_scb_to_disc_list
714 jmp mesgin_done
701 or SCB_CONTROL,DISCONNECTED;
702.if ( SCB_PAGING )
703 call add_scb_to_disc_list;
704.endif
705 jmp await_busfree;
715
716/*
717 * Save data pointers message:
718 * Copying RAM values back to SCB, for Save Data Pointers message, but
719 * only if we've actually been into a data phase to change them. This
720 * protects against bogus data in scratch ram and the residual counts
721 * since they are only initialized when we go into data_in or data_out.
722 */
723mesgin_sdptrs:
706
707/*
708 * Save data pointers message:
709 * Copying RAM values back to SCB, for Save Data Pointers message, but
710 * only if we've actually been into a data phase to change them. This
711 * protects against bogus data in scratch ram and the residual counts
712 * since they are only initialized when we go into data_in or data_out.
713 */
714mesgin_sdptrs:
724 test FLAGS, DPHASE jz mesgin_done
725 mov SCB_SGCOUNT,SG_COUNT
715 test SEQ_FLAGS, DPHASE jz mesgin_done;
716 mov SCB_SGCOUNT,SG_COUNT;
726
727 /* The SCB SGPTR becomes the next one we'll download */
717
718 /* The SCB SGPTR becomes the next one we'll download */
728 mvi DINDEX, SCB_SGPTR
729 mvi SG_NEXT0 call bcopy_4
719 mvi DINDEX, SCB_SGPTR;
720 mvi SG_NEXT call bcopy_4;
730
731 /* The SCB DATAPTR0 becomes the current SHADDR */
721
722 /* The SCB DATAPTR0 becomes the current SHADDR */
732 mvi DINDEX, SCB_DATAPTR0
733 mvi SHADDR0 call bcopy_4
723 mvi DINDEX, SCB_DATAPTR;
724 mvi SHADDR call bcopy_4;
734
735/*
736 * Use the residual number since STCNT is corrupted by any message transfer.
737 */
725
726/*
727 * Use the residual number since STCNT is corrupted by any message transfer.
728 */
738 mvi SCB_RESID_DCNT0 call bcopy_3
729 mvi SCB_RESID_DCNT call bcopy_3;
739
730
740 jmp mesgin_done
731 jmp mesgin_done;
741
742/*
743 * Restore pointers message? Data pointers are recopied from the
744 * SCB anytime we enter a data phase for the first time, so all
745 * we need to do is clear the DPHASE flag and let the data phase
746 * code do the rest.
747 */
748mesgin_rdptrs:
732
733/*
734 * Restore pointers message? Data pointers are recopied from the
735 * SCB anytime we enter a data phase for the first time, so all
736 * we need to do is clear the DPHASE flag and let the data phase
737 * code do the rest.
738 */
739mesgin_rdptrs:
749 and FLAGS,0xef /*
750 * !DPHASE we'll reload them
740 and SEQ_FLAGS, ~DPHASE; /*
741 * We'll reload them
751 * the next time through
742 * the next time through
743 * the dataphase.
752 */
744 */
753 jmp mesgin_done
745 jmp mesgin_done;
754
755/*
756 * Identify message? For a reconnecting target, this tells us the lun
757 * that the reconnection is for - find the correct SCB and switch to it,
758 * clearing the "disconnected" bit so we don't "find" it by accident later.
759 */
760mesgin_identify:
746
747/*
748 * Identify message? For a reconnecting target, this tells us the lun
749 * that the reconnection is for - find the correct SCB and switch to it,
750 * clearing the "disconnected" bit so we don't "find" it by accident later.
751 */
752mesgin_identify:
761 test A,0x78 jnz rej_mesgin /*!DiscPriv|!LUNTAR|!Reserved*/
762 and A,0x07 /* lun in lower three bits */
763 or SAVED_TCL,A /* SAVED_TCL should be complete now */
764 mov SAVED_TCL call index_untagged_scb
765 mov ARG_1, SINDIR
766 cmp ARG_1,SCB_LIST_NULL jne use_findSCB
753 test A,0x78 jnz rej_mesgin; /*!DiscPriv|!LUNTAR|!Reserved*/
754 and A,0x07; /* lun in lower three bits */
755 or SAVED_TCL,A; /* SAVED_TCL should be complete now */
756 mov SAVED_TCL call index_untagged_scb;
757 mov ARG_1, SINDIR;
758 /* XXX Directly index in the non paging case */
759 cmp ARG_1,SCB_LIST_NULL jne use_findSCB;
767/*
768 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
769 * If we get one, we use the tag returned to find the proper
770 * SCB. With SCB paging, this requires using findSCB for both tagged
771 * and non-tagged transactions since the SCB may exist in any slot.
772 * If we're not using SCB paging, we can use the tag as the direct
773 * index to the SCB.
774 */
760/*
761 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
762 * If we get one, we use the tag returned to find the proper
763 * SCB. With SCB paging, this requires using findSCB for both tagged
764 * and non-tagged transactions since the SCB may exist in any slot.
765 * If we're not using SCB paging, we can use the tag as the direct
766 * index to the SCB.
767 */
775 call inb_last /* ACK Identify MSG */
768 mov NONE,SCSIDATL; /* ACK Identify MSG */
776snoop_tag_loop:
769snoop_tag_loop:
777 test SSTAT1,REQINIT jz snoop_tag_loop
778 and LASTPHASE, PHASE_MASK, SCSISIGI
779 cmp LASTPHASE, P_MESGIN jne not_found
780 cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found
770 test SSTAT1,REQINIT jz snoop_tag_loop;
771 and LASTPHASE, PHASE_MASK, SCSISIGI;
772 cmp LASTPHASE, P_MESGIN jne not_found;
773 cmp SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
781get_tag:
774get_tag:
782 or FLAGS, TAGGED_SCB
783 mvi ARG_1 call inb_next /* tag value */
775 or SEQ_FLAGS, TAGGED_SCB;
776 mvi ARG_1 call inb_next; /* tag value */
784/*
785 * See if the tag is in range. The tag is < SCBCOUNT if we add
786 * the complement of SCBCOUNT to the incomming tag and there is
787 * no carry.
788 */
777/*
778 * See if the tag is in range. The tag is < SCBCOUNT if we add
779 * the complement of SCBCOUNT to the incomming tag and there is
780 * no carry.
781 */
789 mov A,COMP_SCBCOUNT
790 add SINDEX,A,ARG_1
791 jc not_found
782 mov A,COMP_SCBCOUNT;
783 add SINDEX,A,ARG_1;
784 jc not_found;
792
785
786.if ! ( SCB_PAGING )
787 jmp index_by_tag;
788.endif
793/*
794 * Ensure that the SCB the tag points to is for an SCB transaction
795 * to the reconnecting target.
796 */
789/*
790 * Ensure that the SCB the tag points to is for an SCB transaction
791 * to the reconnecting target.
792 */
797 test FLAGS, PAGESCBS jz index_by_tag
798use_findSCB:
793use_findSCB:
799 mov ALLZEROS call findSCB /* Have to search */
800 cmp SINDEX, SCB_LIST_NULL, je not_found
794 mov ALLZEROS call findSCB; /* Have to search */
795 cmp SINDEX, SCB_LIST_NULL je not_found;
801setup_SCB:
796setup_SCB:
802 and SCB_CONTROL,0xfb /* clear disconnect bit in SCB */
803 or FLAGS,IDENTIFY_SEEN /* make note of IDENTIFY */
804 jmp mesgin_done
797 and SCB_CONTROL,~DISCONNECTED;
798 or SEQ_FLAGS,IDENTIFY_SEEN; /* make note of IDENTIFY */
799 jmp mesgin_done;
805index_by_tag:
800index_by_tag:
806 mov SCBPTR,ARG_1
807 mov A, SAVED_TCL
808 cmp SCB_TCL,A jne not_found
809 test SCB_CONTROL,TAG_ENB jz not_found
810 test SCB_CONTROL,DISCONNECTED jz not_found
811 jmp setup_SCB
801 mov SCBPTR,ARG_1;
802 mov A, SAVED_TCL;
803 cmp SCB_TCL,A jne not_found;
804 test SCB_CONTROL,TAG_ENB jz not_found;
805 test SCB_CONTROL,DISCONNECTED jz not_found;
806 jmp setup_SCB;
812
813not_found:
807
808not_found:
814 mvi INTSTAT, NO_MATCH
809 mvi INTSTAT, NO_MATCH;
815send_abort_msg:
810send_abort_msg:
816 test FLAGS, TAGGED_SCB jnz send_abort_tag_msg
817 mvi MSG_ABORT call mk_mesg
818 jmp send_abort_done
811 test SEQ_FLAGS, TAGGED_SCB jnz send_abort_tag_msg;
812 mvi MSG_ABORT call mk_mesg;
813 jmp send_abort_done;
819send_abort_tag_msg:
814send_abort_tag_msg:
820 mvi MSG_ABORT_TAG call mk_mesg /* ABORT TAG message */
815 mvi MSG_ABORT_TAG call mk_mesg; /* ABORT TAG message */
821send_abort_done:
822 /* If we don't have the tag ID yet, we're "looking ahead" at state
823 * that hasn't been processed, so don't ack.
824 */
816send_abort_done:
817 /* If we don't have the tag ID yet, we're "looking ahead" at state
818 * that hasn't been processed, so don't ack.
819 */
825 cmp ARG_1, SCB_LIST_NULL je ITloop
826 jmp mesgin_done
820 cmp ARG_1, SCB_LIST_NULL je ITloop;
821 jmp mesgin_done;
827
828/*
829 * Message reject? Let the kernel driver handle this. If we have an
830 * outstanding WDTR or SDTR negotiation, assume that it's a response from
831 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
832 * it since we have no clue what it pertains to.
833 */
834mesgin_reject:
822
823/*
824 * Message reject? Let the kernel driver handle this. If we have an
825 * outstanding WDTR or SDTR negotiation, assume that it's a response from
826 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
827 * it since we have no clue what it pertains to.
828 */
829mesgin_reject:
835 mvi INTSTAT, REJECT_MSG
836 jmp mesgin_done
830 mvi INTSTAT, REJECT_MSG;
831 jmp mesgin_done;
837
838/*
839 * [ ADD MORE MESSAGE HANDLING HERE ]
840 */
841
842/*
843 * Locking the driver out, build a one-byte message passed in SINDEX
844 * if there is no active message already. SINDEX is returned intact.
845 */
846mk_mesg:
832
833/*
834 * [ ADD MORE MESSAGE HANDLING HERE ]
835 */
836
837/*
838 * Locking the driver out, build a one-byte message passed in SINDEX
839 * if there is no active message already. SINDEX is returned intact.
840 */
841mk_mesg:
847 mvi SEQCTL,0x50 /* PAUSEDIS|FASTMODE */
848 test MSG_LEN,0xff jz mk_mesg1 /* Should always succeed */
842 mvi SEQCTL, PAUSEDIS|FASTMODE;
843 test MSG_LEN,0xff jz mk_mesg1; /* Should always succeed */
849
850 /*
851 * Hmmm. For some reason the mesg buffer is in use.
852 * Tell the driver. It should look at SINDEX to find
853 * out what we wanted to use the buffer for and resolve
854 * the conflict.
855 */
844
845 /*
846 * Hmmm. For some reason the mesg buffer is in use.
847 * Tell the driver. It should look at SINDEX to find
848 * out what we wanted to use the buffer for and resolve
849 * the conflict.
850 */
856 mvi SEQCTL,0x10 /* !PAUSEDIS|FASTMODE */
857 mvi INTSTAT,MSG_BUFFER_BUSY
851 mvi SEQCTL,FASTMODE;
852 mvi INTSTAT,MSG_BUFFER_BUSY;
858
859mk_mesg1:
853
854mk_mesg1:
860 or SCSISIGO,ATNO,LASTPHASE /* turn on ATNO */
861 mvi MSG_LEN,1 /* length = 1 */
862 mov MSG0,SINDEX /* 1-byte message */
863 mvi SEQCTL,0x10 ret /* !PAUSEDIS|FASTMODE */
855 or SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
856 mvi MSG_LEN,1; /* length = 1 */
857 mov MSG_OUT,SINDEX; /* 1-byte message */
858 mvi SEQCTL,FASTMODE ret;
864
865/*
866 * Functions to read data in Automatic PIO mode.
867 *
868 * According to Adaptec's documentation, an ACK is not sent on input from
869 * the target until SCSIDATL is read from. So we wait until SCSIDATL is
870 * latched (the usual way), then read the data byte directly off the bus
871 * using SCSIBUSL. When we have pulled the ATN line, or we just want to
872 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
873 * spec guarantees that the target will hold the data byte on the bus until
874 * we send our ACK.
875 *
876 * The assumption here is that these are called in a particular sequence,
877 * and that REQ is already set when inb_first is called. inb_{first,next}
878 * use the same calling convention as inb.
879 */
880
881inb_next:
859
860/*
861 * Functions to read data in Automatic PIO mode.
862 *
863 * According to Adaptec's documentation, an ACK is not sent on input from
864 * the target until SCSIDATL is read from. So we wait until SCSIDATL is
865 * latched (the usual way), then read the data byte directly off the bus
866 * using SCSIBUSL. When we have pulled the ATN line, or we just want to
867 * acknowledge the byte, then we do a dummy read from SCISDATL. The SCSI
868 * spec guarantees that the target will hold the data byte on the bus until
869 * we send our ACK.
870 *
871 * The assumption here is that these are called in a particular sequence,
872 * and that REQ is already set when inb_first is called. inb_{first,next}
873 * use the same calling convention as inb.
874 */
875
876inb_next:
882 mov NONE,SCSIDATL /*dummy read from latch to ACK*/
877 mov NONE,SCSIDATL; /*dummy read from latch to ACK*/
883inb_next_wait:
884 /*
885 * If there is a parity error, wait for the kernel to
886 * see the interrupt and prepare our message response
887 * before continuing.
888 */
878inb_next_wait:
879 /*
880 * If there is a parity error, wait for the kernel to
881 * see the interrupt and prepare our message response
882 * before continuing.
883 */
889 test SSTAT1, REQINIT jz inb_next_wait
890 test SSTAT1, SCSIPERR jnz inb_next_wait
891 and LASTPHASE, PHASE_MASK, SCSISIGI
892 cmp LASTPHASE, P_MESGIN jne mesgin_phasemis
884 test SSTAT1, REQINIT jz inb_next_wait;
885 test SSTAT1, SCSIPERR jnz inb_next_wait;
886 and LASTPHASE, PHASE_MASK, SCSISIGI;
887 cmp LASTPHASE, P_MESGIN jne mesgin_phasemis;
893inb_first:
888inb_first:
894 mov DINDEX,SINDEX
895 mov DINDIR,SCSIBUSL ret /*read byte directly from bus*/
889 mov DINDEX,SINDEX;
890 mov DINDIR,SCSIBUSL ret; /*read byte directly from bus*/
896inb_last:
891inb_last:
897 mov NONE,SCSIDATL ret /*dummy read from latch to ACK*/
892 mov NONE,SCSIDATL ret; /*dummy read from latch to ACK*/
898
899mesgin_phasemis:
900/*
901 * We expected to receive another byte, but the target changed phase
902 */
893
894mesgin_phasemis:
895/*
896 * We expected to receive another byte, but the target changed phase
897 */
903 mvi INTSTAT, MSGIN_PHASEMIS
904 jmp ITloop
898 mvi INTSTAT, MSGIN_PHASEMIS;
899 jmp ITloop;
905
906/*
907 * DMA data transfer. HADDR and HCNT must be loaded first, and
908 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
909 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
910 * during initialization.
911 */
912dma:
900
901/*
902 * DMA data transfer. HADDR and HCNT must be loaded first, and
903 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
904 * host->scsi, or 0x39 for scsi->host. The SCSI channel is cleared
905 * during initialization.
906 */
907dma:
913 mov DFCNTRL,SINDEX
908 mov DFCNTRL,SINDEX;
914dma_loop:
909dma_loop:
915 test SSTAT0,DMADONE jnz dma_dmadone
916 test SSTAT1,PHASEMIS jz dma_loop /* ie. underrun */
910 test SSTAT0,DMADONE jnz dma_dmadone;
911 test SSTAT1,PHASEMIS jz dma_loop; /* ie. underrun */
917dma_phasemis:
912dma_phasemis:
918 test SSTAT0,SDONE jnz dma_checkfifo
919 mov SINDEX,ALLZEROS /* Notify caller of phasemiss */
913 test SSTAT0,SDONE jnz dma_checkfifo;
914 mov SINDEX,ALLZEROS; /* Notify caller of phasemiss */
920
921/*
922 * We will be "done" DMAing when the transfer count goes to zero, or
923 * the target changes the phase (in light of this, it makes sense that
924 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
925 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
926 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
927 * status.
928 */
929dma_checkfifo:
915
916/*
917 * We will be "done" DMAing when the transfer count goes to zero, or
918 * the target changes the phase (in light of this, it makes sense that
919 * the DMA circuitry doesn't ACK when PHASEMIS is active). If we are
920 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
921 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
922 * status.
923 */
924dma_checkfifo:
930 test DFCNTRL,DIRECTION jnz dma_fifoempty
925 test DFCNTRL,DIRECTION jnz dma_fifoempty;
931dma_fifoflush:
926dma_fifoflush:
932 test DFSTATUS,FIFOEMP jz dma_fifoflush
927 test DFSTATUS,FIFOEMP jz dma_fifoflush;
933
934dma_fifoempty:
935 /* Don't clobber an inprogress host data transfer */
928
929dma_fifoempty:
930 /* Don't clobber an inprogress host data transfer */
936 test DFSTATUS, MREQPEND jnz dma_fifoempty
931 test DFSTATUS, MREQPEND jnz dma_fifoempty;
937/*
938 * Now shut the DMA enables off and make sure that the DMA enables are
939 * actually off first lest we get an ILLSADDR.
940 */
941dma_dmadone:
932/*
933 * Now shut the DMA enables off and make sure that the DMA enables are
934 * actually off first lest we get an ILLSADDR.
935 */
936dma_dmadone:
942 and DFCNTRL, 0xc7 /* ~(SCSIEN|SDMAEN|HDMAEN) */
937 and DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
943dma_halt:
938dma_halt:
944 test DFCNTRL, 0x38 jnz dma_halt /* (SCSIEN|SDMAEN|HDMAEN) */
939 test DFCNTRL, (SCSIEN|SDMAEN|HDMAEN) jnz dma_halt;
945return:
940return:
946 ret
941 ret;
947
948/*
942
943/*
949 * Common SCSI initialization for selection and reselection. Expects
950 * the target SCSI ID to be in the upper four bits of SINDEX, and A's
951 * contents are stomped on return.
952 */
953initialize_scsiid:
954 and SINDEX,0xf0 /* Get target ID */
955 mov SAVED_TCL, SINDEX /* Update the target portion of this */
956 and A,0x0f,SCSIID
957 or SINDEX,A
958 mov SCSIID,SINDEX ret
959
960/*
961 * Assert that if we've been reselected, then we've seen an IDENTIFY
962 * message.
963 */
964assert:
944 * Assert that if we've been reselected, then we've seen an IDENTIFY
945 * message.
946 */
947assert:
965 test FLAGS,RESELECTED jz return /* reselected? */
966 test FLAGS,IDENTIFY_SEEN jnz return /* seen IDENTIFY? */
948 test SEQ_FLAGS,RESELECTED jz return; /* reselected? */
949 test SEQ_FLAGS,IDENTIFY_SEEN jnz return; /* seen IDENTIFY? */
967
950
968 mvi INTSTAT,NO_IDENT ret /* no - tell the kernel */
951 mvi INTSTAT,NO_IDENT ret; /* no - tell the kernel */
969
970/*
971 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
972 * or by the SCBIDn ARG_1. The search begins at the SCB index passed in
973 * via SINDEX. If the SCB cannot be found, SINDEX will be SCB_LIST_NULL,
974 * otherwise, SCBPTR is set to the proper SCB.
975 */
976findSCB:
952
953/*
954 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
955 * or by the SCBIDn ARG_1. The search begins at the SCB index passed in
956 * via SINDEX. If the SCB cannot be found, SINDEX will be SCB_LIST_NULL,
957 * otherwise, SCBPTR is set to the proper SCB.
958 */
959findSCB:
977 mov SCBPTR,SINDEX /* switch to next SCB */
978 mov A, ARG_1 /* Tag passed in ARG_1 */
979 cmp SCB_TAG,A jne findSCB_loop
980 test SCB_CONTROL,DISCONNECTED jnz foundSCB /*should be disconnected*/
960 mov SCBPTR,SINDEX; /* switch to next SCB */
961 mov A, ARG_1; /* Tag passed in ARG_1 */
962 cmp SCB_TAG,A jne findSCB_loop;
963 test SCB_CONTROL,DISCONNECTED jnz foundSCB;/*should be disconnected*/
981findSCB_loop:
964findSCB_loop:
982 inc SINDEX
983 mov A,SCBCOUNT
984 cmp SINDEX,A jne findSCB
965 inc SINDEX;
966 mov A,SCBCOUNT;
967 cmp SINDEX,A jne findSCB;
985/*
986 * We didn't find it. If we're paging, pull an SCB and DMA down the
987 * one we want. If we aren't paging or the SCB we dma down has the
988 * abort flag set, return not found.
989 */
968/*
969 * We didn't find it. If we're paging, pull an SCB and DMA down the
970 * one we want. If we aren't paging or the SCB we dma down has the
971 * abort flag set, return not found.
972 */
990 test FLAGS, PAGESCBS jz find_error
991 mov ALLZEROS call get_free_or_disc_scb
992 mvi DMAPARAMS, 0xd /* HDMAEN|DIRECTION|FIFORESET */
993 mov ARG_1 call dma_scb
994 test SCB_CONTROL, ABORT_SCB jz return
973.if ( SCB_PAGING )
974 mov ALLZEROS call get_free_or_disc_scb;
975 mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
976 mov ARG_1 call dma_scb;
977 test SCB_CONTROL, ABORT_SCB jz return;
978.endif
995find_error:
979find_error:
996 mvi SINDEX, SCB_LIST_NULL ret
980 mvi SINDEX, SCB_LIST_NULL ret;
997foundSCB:
981foundSCB:
998 test SCB_CONTROL, ABORT_SCB jnz find_error
999 test FLAGS,PAGESCBS jz return
982 test SCB_CONTROL, ABORT_SCB jnz find_error;
983.if ( SCB_PAGING )
1000rem_scb_from_disc_list:
1001/* Remove this SCB from the disconnection list */
984rem_scb_from_disc_list:
985/* Remove this SCB from the disconnection list */
1002 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev
1003 mov SAVED_LINKPTR, SCB_PREV
1004 mov SCBPTR, SCB_NEXT
1005 mov SCB_PREV, SAVED_LINKPTR
1006 mov SCBPTR, SINDEX
986 cmp SCB_NEXT,SCB_LIST_NULL je unlink_prev;
987 mov SAVED_LINKPTR, SCB_PREV;
988 mov SCBPTR, SCB_NEXT;
989 mov SCB_PREV, SAVED_LINKPTR;
990 mov SCBPTR, SINDEX;
1007unlink_prev:
991unlink_prev:
1008 cmp SCB_PREV,SCB_LIST_NULL je rHead/* At the head of the list */
1009 mov SAVED_LINKPTR, SCB_NEXT
1010 mov SCBPTR, SCB_PREV
1011 mov SCB_NEXT, SAVED_LINKPTR
1012 mov SCBPTR, SINDEX ret
992 cmp SCB_PREV,SCB_LIST_NULL je rHead;/* At the head of the list */
993 mov SAVED_LINKPTR, SCB_NEXT;
994 mov SCBPTR, SCB_PREV;
995 mov SCB_NEXT, SAVED_LINKPTR;
996 mov SCBPTR, SINDEX ret;
1013rHead:
997rHead:
1014 mov DISCONNECTED_SCBH,SCB_NEXT ret
998 mov DISCONNECTED_SCBH,SCB_NEXT ret;
999.else
1000 ret;
1001.endif
1015
1016set_stcnt_from_hcnt:
1002
1003set_stcnt_from_hcnt:
1017 mov STCNT0, HCNT0
1018 mov STCNT1, HCNT1
1019 mov STCNT2, HCNT2 ret
1004 mov STCNT[0], HCNT[0];
1005 mov STCNT[1], HCNT[1];
1006 mov STCNT[2], HCNT[2] ret;
1020
1021bcopy_7:
1007
1008bcopy_7:
1022 mov DINDIR, SINDIR
1023 mov DINDIR, SINDIR
1009 mov DINDIR, SINDIR;
1010 mov DINDIR, SINDIR;
1024bcopy_5:
1011bcopy_5:
1025 mov DINDIR, SINDIR
1012 mov DINDIR, SINDIR;
1026bcopy_4:
1013bcopy_4:
1027 mov DINDIR, SINDIR
1014 mov DINDIR, SINDIR;
1028bcopy_3:
1015bcopy_3:
1029 mov DINDIR, SINDIR
1030 mov DINDIR, SINDIR
1031 mov DINDIR, SINDIR ret
1016 mov DINDIR, SINDIR;
1017 mov DINDIR, SINDIR;
1018 mov DINDIR, SINDIR ret;
1032
1033dma_scb:
1034 /*
1035 * SCB index is in SINDEX. Determine the physical address in
1036 * the host where this SCB is located and load HADDR with it.
1037 */
1019
1020dma_scb:
1021 /*
1022 * SCB index is in SINDEX. Determine the physical address in
1023 * the host where this SCB is located and load HADDR with it.
1024 */
1038 shr DINDEX, SINDEX, 3
1039 shl A, SINDEX, 5
1040 add HADDR0, A, HSCB_ADDR0
1041 mov A, DINDEX
1042 adc HADDR1, A, HSCB_ADDR1
1043 clr A
1044 adc HADDR2, A, HSCB_ADDR2
1045 adc HADDR3, A, HSCB_ADDR3
1025 shr DINDEX, 3, SINDEX;
1026 shl A, 5, SINDEX;
1027 add HADDR[0], A, HSCB_ADDR[0];
1028 mov A, DINDEX;
1029 adc HADDR[1], A, HSCB_ADDR[1];
1030 clr A;
1031 adc HADDR[2], A, HSCB_ADDR[2];
1032 adc HADDR[3], A, HSCB_ADDR[3];
1046 /* Setup Count */
1033 /* Setup Count */
1047 mvi HCNT0, 28
1048 clr HCNT1
1049 clr HCNT2
1050 mov DFCNTRL, DMAPARAMS
1051 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost
1034 mvi HCNT[0], 28;
1035 clr HCNT[1];
1036 clr HCNT[2];
1037 mov DFCNTRL, DMAPARAMS;
1038 test DMAPARAMS, DIRECTION jnz dma_scb_fromhost;
1052 /* Fill it with the SCB data */
1039 /* Fill it with the SCB data */
1053 call copy_scb_tofifo
1054 mvi DFCNTRL, 0xa /* HDMAEN | FIFOFLUSH */
1040 call copy_scb_tofifo;
1041 or DFCNTRL, HDMAEN|FIFOFLUSH;
1055dma_scb_fromhost:
1042dma_scb_fromhost:
1056 call dma_finish
1043 call dma_finish;
1057 /* If we were putting the SCB, we are done */
1044 /* If we were putting the SCB, we are done */
1058 test DMAPARAMS, DIRECTION jz return
1059 mvi SCBARRAY call dfdat_in_7
1060 call dfdat_in_7_continued
1061 call dfdat_in_7_continued
1062 jmp dfdat_in_7_continued
1045 test DMAPARAMS, DIRECTION jz return;
1046 mvi SCB_CONTROL call dfdat_in_7;
1047 call dfdat_in_7_continued;
1048 call dfdat_in_7_continued;
1049 jmp dfdat_in_7_continued;
1063dfdat_in_7:
1050dfdat_in_7:
1064 mov DINDEX,SINDEX
1051 mov DINDEX,SINDEX;
1065dfdat_in_7_continued:
1052dfdat_in_7_continued:
1066 mov DINDIR,DFDAT
1067 mov DINDIR,DFDAT
1068 mov DINDIR,DFDAT
1069 mov DINDIR,DFDAT
1070 mov DINDIR,DFDAT
1071 mov DINDIR,DFDAT
1072 mov DINDIR,DFDAT ret
1053 mov DINDIR,DFDAT;
1054 mov DINDIR,DFDAT;
1055 mov DINDIR,DFDAT;
1056 mov DINDIR,DFDAT;
1057 mov DINDIR,DFDAT;
1058 mov DINDIR,DFDAT;
1059 mov DINDIR,DFDAT ret;
1073
1074copy_scb_tofifo:
1060
1061copy_scb_tofifo:
1075 mvi SCBARRAY call dfdat_out_7
1076 call dfdat_out_7
1077 call dfdat_out_7
1062 mvi SCB_CONTROL call dfdat_out_7;
1063 call dfdat_out_7;
1064 call dfdat_out_7;
1078dfdat_out_7:
1065dfdat_out_7:
1079 mov DFDAT,SINDIR
1080 mov DFDAT,SINDIR
1081 mov DFDAT,SINDIR
1082 mov DFDAT,SINDIR
1083 mov DFDAT,SINDIR
1084 mov DFDAT,SINDIR
1085 mov DFDAT,SINDIR ret
1066 mov DFDAT,SINDIR;
1067 mov DFDAT,SINDIR;
1068 mov DFDAT,SINDIR;
1069 mov DFDAT,SINDIR;
1070 mov DFDAT,SINDIR;
1071 mov DFDAT,SINDIR;
1072 mov DFDAT,SINDIR ret;
1086
1087/*
1088 * Wait for DMA from host memory to data FIFO to complete, then disable
1089 * DMA and wait for it to acknowledge that it's off.
1090 */
1091dma_finish:
1073
1074/*
1075 * Wait for DMA from host memory to data FIFO to complete, then disable
1076 * DMA and wait for it to acknowledge that it's off.
1077 */
1078dma_finish:
1092 test DFSTATUS,HDONE jz dma_finish
1079 test DFSTATUS,HDONE jz dma_finish;
1093 /* Turn off DMA */
1080 /* Turn off DMA */
1094 and DFCNTRL, 0xf7 ret # ~HDMAEN
1081 and DFCNTRL, ~HDMAEN;
1082 test DFCNTRL, HDMAEN jnz .;
1083 ret;
1095
1096index_untagged_scb:
1084
1085index_untagged_scb:
1097 mov DINDEX, SINDEX
1098 shr DINDEX, 4
1099 and DINDEX, 0x03 /* Bottom two bits of tid */
1100 add DINDEX, SCB_ACTIVE0
1101 shr A, SINDEX, 6 /* Target ID divided by 4 */
1102 test SINDEX, SELBUSB jz index_untagged_scb2
1103 add A, 2 /* Add 2 positions */
1086 mov DINDEX, SINDEX;
1087 shr DINDEX, 4;
1088 and DINDEX, 0x03; /* Bottom two bits of tid */
1089 add DINDEX, SCB_BUSYTARGETS;
1090 shr A, 6, SINDEX; /* Target ID divided by 4 */
1091 test SINDEX, SELBUSB jz index_untagged_scb2;
1092 add A, 2; /* Add 2 positions */
1104index_untagged_scb2:
1093index_untagged_scb2:
1105 mov SCBPTR, A /*
1094 mov SCBPTR, A; /*
1106 * Select the SCB with this
1107 * target's information.
1108 */
1095 * Select the SCB with this
1096 * target's information.
1097 */
1109 mov SINDEX, DINDEX ret
1098 mov SINDEX, DINDEX ret;
1110
1099
1100add_scb_to_free_list:
1101 mov SCB_NEXT, FREE_SCBH;
1102 mvi SCB_TAG, SCB_LIST_NULL;
1103 mov FREE_SCBH, SCBPTR ret;
1111
1104
1105.if ( SCB_PAGING )
1112get_free_or_disc_scb:
1106get_free_or_disc_scb:
1113 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb
1114 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb
1107 cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
1108 cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
1115return_error:
1109return_error:
1116 mvi SINDEX, SCB_LIST_NULL ret
1110 mvi SINDEX, SCB_LIST_NULL ret;
1117dequeue_disc_scb:
1111dequeue_disc_scb:
1118 mov SCBPTR, DISCONNECTED_SCBH
1112 mov SCBPTR, DISCONNECTED_SCBH;
1119/*
1120 * If we have a residual, then we are in the middle of some I/O
1121 * and we have to send this SCB back up to the kernel so that the
1122 * saved data pointers and residual information isn't lost.
1123 */
1113/*
1114 * If we have a residual, then we are in the middle of some I/O
1115 * and we have to send this SCB back up to the kernel so that the
1116 * saved data pointers and residual information isn't lost.
1117 */
1124 test SCB_RESID_SGCNT,0xff jz unlink_disc_scb
1125 mvi DMAPARAMS, 0x9 /* HDMAEN | FIFORESET*/
1126 mov SCB_TAG call dma_scb
1118 test SCB_RESID_SGCNT,0xff jnz dma_up_scb;
1119 cmp SCB_LINKED_NEXT, SCB_LIST_NULL je unlink_disc_scb;
1120dma_up_scb:
1121 mvi DMAPARAMS, FIFORESET;
1122 mov SCB_TAG call dma_scb;
1127unlink_disc_scb:
1128 /* jmp instead of call since we want to return anyway */
1123unlink_disc_scb:
1124 /* jmp instead of call since we want to return anyway */
1129 mov SCBPTR jmp rem_scb_from_disc_list
1125 mov SCBPTR jmp rem_scb_from_disc_list;
1130dequeue_free_scb:
1126dequeue_free_scb:
1131 mov SCBPTR, FREE_SCBH
1132 mov FREE_SCBH, SCB_NEXT ret
1127 mov SCBPTR, FREE_SCBH;
1128 mov FREE_SCBH, SCB_NEXT ret;
1133
1129
1134add_scb_to_free_list:
1135 mov SCB_NEXT, FREE_SCBH
1136 mvi SCB_TAG, SCB_LIST_NULL
1137 mov FREE_SCBH, SCBPTR ret
1138
1139add_scb_to_disc_list:
1140/*
1141 * Link this SCB into the DISCONNECTED list. This list holds the
1142 * candidates for paging out an SCB if one is needed for a new command.
1143 * Modifying the disconnected list is a critical(pause dissabled) section.
1144 */
1130add_scb_to_disc_list:
1131/*
1132 * Link this SCB into the DISCONNECTED list. This list holds the
1133 * candidates for paging out an SCB if one is needed for a new command.
1134 * Modifying the disconnected list is a critical(pause dissabled) section.
1135 */
1145 mvi SCB_PREV, SCB_LIST_NULL
1146 mov SCB_NEXT, DISCONNECTED_SCBH
1147 mov DISCONNECTED_SCBH, SCBPTR
1148 cmp SCB_NEXT,SCB_LIST_NULL je return
1149 mov SCBPTR,SCB_NEXT
1150 mov SCB_PREV,DISCONNECTED_SCBH
1151 mov SCBPTR,DISCONNECTED_SCBH ret
1152
1136 mvi SCB_PREV, SCB_LIST_NULL;
1137 mov SCB_NEXT, DISCONNECTED_SCBH;
1138 mov DISCONNECTED_SCBH, SCBPTR;
1139 cmp SCB_NEXT,SCB_LIST_NULL je return;
1140 mov SCBPTR,SCB_NEXT;
1141 mov SCB_PREV,DISCONNECTED_SCBH;
1142 mov SCBPTR,DISCONNECTED_SCBH ret;
1143.endif