OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [aic7xxx/] [aic7xxx.seq] - Blame information for rev 1626

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
/*
2
 * Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
3
 *
4
 * Copyright (c) 1994-1998 Justin Gibbs.
5
 * All rights reserved.
6
 *
7
 * Redistribution and use in source and binary forms, with or without
8
 * modification, are permitted provided that the following conditions
9
 * are met:
10
 * 1. Redistributions of source code must retain the above copyright
11
 *    notice, this list of conditions, and the following disclaimer,
12
 *    without modification, immediately at the beginning of the file.
13
 * 2. The name of the author may not be used to endorse or promote products
14
 *    derived from this software without specific prior written permission.
15
 *
16
 * Where this Software is combined with software released under the terms of
17
 * the GNU Public License (GPL) and the terms of the GPL would require the
18
 * combined work to also be released under the terms of the GPL, the terms
19
 * and conditions of this License will apply in addition to those of the
20
 * GPL with the exception of any terms or conditions of this License that
21
 * conflict with, or are expressly prohibited by, the GPL.
22
 *
23
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
24
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
27
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33
 * SUCH DAMAGE.
34
 *
35
 *      $Id: aic7xxx.seq,v 1.1 2005-12-20 10:18:04 jcastillo Exp $
36
 */
37
 
38
#include "aic7xxx.reg"
39
#include "scsi_message.h"
40
 
41
/*
42
 * A few words on the waiting SCB list:
43
 * After starting the selection hardware, we check for reconnecting targets
44
 * as well as for our selection to complete just in case the reselection wins
45
 * bus arbitration.  The problem with this is that we must keep track of the
46
 * SCB that we've already pulled from the QINFIFO and started the selection
47
 * on just in case the reselection wins so that we can retry the selection at
48
 * a later time.  This problem cannot be resolved by holding a single entry
49
 * in scratch ram since a reconnecting target can request sense and this will
50
 * create yet another SCB waiting for selection.  The solution used here is to
51
 * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
52
 * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes,
53
 * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
54
 * this list everytime a request sense occurs or after completing a non-tagged
55
 * command for which a second SCB has been queued.  The sequencer will
56
 * automatically consume the entries.
57
 */
58
 
59
reset:
60
        clr     SCSISIGO;               /* De-assert BSY */
61
        /* Always allow reselection */
62
        if ((p->flags & AHC_TARGETMODE) != 0) {
63
                mvi     SCSISEQ, ENSELI|ENRSELI|ENAUTOATNP;
64
        } else {
65
                mvi     SCSISEQ, ENRSELI|ENAUTOATNP;
66
        }
67
 
68
        if ((p->features & AHC_CMD_CHAN) != 0) {
69
                /* Ensure that no DMA operations are in progress */
70
                clr     CCSGCTL;
71
                clr     CCSCBCTL;
72
        }
73
 
74
        call    clear_target_state;
75
        and     SXFRCTL0, ~SPIOEN;
76
poll_for_work:
77
        if ((p->features & AHC_QUEUE_REGS) == 0) {
78
                mov     A, QINPOS;
79
        }
80
poll_for_work_loop:
81
        if ((p->features & AHC_QUEUE_REGS) == 0) {
82
                and     SEQCTL, ~PAUSEDIS;
83
        }
84
        test    SSTAT0, SELDO|SELDI     jnz selection;
85
        test    SCSISEQ, ENSELO jnz poll_for_work;
86
        if ((p->features & AHC_TWIN) != 0) {
87
                /*
88
                 * Twin channel devices cannot handle things like SELTO
89
                 * interrupts on the "background" channel.  So, if we
90
                 * are selecting, keep polling the current channel util
91
                 * either a selection or reselection occurs.
92
                 */
93
                xor     SBLKCTL,SELBUSB;        /* Toggle to the other bus */
94
                test    SSTAT0, SELDO|SELDI     jnz selection;
95
                test    SCSISEQ, ENSELO jnz poll_for_work;
96
                xor     SBLKCTL,SELBUSB;        /* Toggle back */
97
        }
98
        cmp     WAITING_SCBH,SCB_LIST_NULL jne start_waiting;
99
test_queue:
100
        /* Has the driver posted any work for us? */
101
        if ((p->features & AHC_QUEUE_REGS) != 0) {
102
                test    QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
103
                mov     NONE, SNSCB_QOFF;
104
                inc     QINPOS;
105
        } else {
106
                or      SEQCTL, PAUSEDIS;
107
                cmp     KERNEL_QINPOS, A je poll_for_work_loop;
108
                inc     QINPOS;
109
                and     SEQCTL, ~PAUSEDIS;
110
        }
111
 
112
/*
113
 * We have at least one queued SCB now and we don't have any
114
 * SCBs in the list of SCBs awaiting selection.  If we have
115
 * any SCBs available for use, pull the tag from the QINFIFO
116
 * and get to work on it.
117
 */
118
        if ((p->flags & AHC_PAGESCBS) != 0) {
119
                mov     ALLZEROS        call    get_free_or_disc_scb;
120
        }
121
 
122
dequeue_scb:
123
        add     A, -1, QINPOS;
124
        mvi     QINFIFO_OFFSET call fetch_byte;
125
 
126
        if ((p->flags & AHC_PAGESCBS) == 0) {
127
                /* In the non-paging case, the SCBID == hardware SCB index */
128
                mov     SCBPTR, RETURN_2;
129
        }
130
dma_queued_scb:
131
/*
132
 * DMA the SCB from host ram into the current SCB location.
133
 */
134
        mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
135
        mov     RETURN_2         call dma_scb;
136
 
137
start_scb:
138
        /*
139
         * Place us on the waiting list in case our selection
140
         * doesn't win during bus arbitration.
141
         */
142
        mov     SCB_NEXT,WAITING_SCBH;
143
        mov     WAITING_SCBH, SCBPTR;
144
start_waiting:
145
        /*
146
         * Pull the first entry off of the waiting SCB list.
147
         */
148
        mov     SCBPTR, WAITING_SCBH;
149
        call    start_selection;
150
        jmp     poll_for_work;
151
 
152
start_selection:
153
        if ((p->features & AHC_TWIN) != 0) {
154
                and     SINDEX,~SELBUSB,SBLKCTL;/* Clear channel select bit */
155
                and     A,SELBUSB,SCB_TCL;      /* Get new channel bit */
156
                or      SINDEX,A;
157
                mov     SBLKCTL,SINDEX;         /* select channel */
158
        }
159
initialize_scsiid:
160
        if ((p->features & AHC_ULTRA2) != 0) {
161
                and     A, TID, SCB_TCL;        /* Get target ID */
162
                and     SCSIID_ULTRA2, OID;     /* Clear old target */
163
                or      SCSIID_ULTRA2, A;
164
        } else {
165
                and     A, TID, SCB_TCL;        /* Get target ID */
166
                and     SCSIID, OID;            /* Clear old target */
167
                or      SCSIID, A;
168
        }
169
        mvi     SCSISEQ, ENSELO|ENAUTOATNO|ENRSELI|ENAUTOATNP ret;
170
 
171
/*
172
 * Initialize Ultra mode setting and clear the SCSI channel.
173
 * SINDEX should contain any additional bit's the client wants
174
 * set in SXFRCTL0.
175
 */
176
initialize_channel:
177
        or      A, CLRSTCNT|CLRCHN, SINDEX;
178
        or      SXFRCTL0, A;
179
        if ((p->features & AHC_ULTRA) != 0) {
180
ultra:
181
                mvi     SINDEX, ULTRA_ENB+1;
182
                test    SAVED_TCL, 0x80         jnz ultra_2; /* Target ID > 7 */
183
                dec     SINDEX;
184
ultra_2:
185
                mov     FUNCTION1,SAVED_TCL;
186
                mov     A,FUNCTION1;
187
                test    SINDIR, A       jz ndx_dtr;
188
                or      SXFRCTL0, FAST20;
189
        }
190
/*
191
 * Initialize SCSIRATE with the appropriate value for this target.
192
 * The SCSIRATE settings for each target are stored in an array
193
 * based at TARG_SCSIRATE.
194
 */
195
ndx_dtr:
196
        shr     A,4,SAVED_TCL;
197
        if ((p->features & AHC_TWIN) != 0) {
198
                test    SBLKCTL,SELBUSB jz ndx_dtr_2;
199
                or      SAVED_TCL, SELBUSB;
200
                or      A,0x08;                 /* Channel B entries add 8 */
201
ndx_dtr_2:
202
        }
203
 
204
        if ((p->features & AHC_ULTRA2) != 0) {
205
                add     SINDEX, TARG_OFFSET, A;
206
                mov     SCSIOFFSET, SINDIR;
207
        }
208
 
209
        add     SINDEX,TARG_SCSIRATE,A;
210
        mov     SCSIRATE,SINDIR ret;
211
 
212
 
213
selection:
214
        test    SSTAT0,SELDO    jnz select_out;
215
select_in:
216
        if ((p->flags & AHC_TARGETMODE) != 0) {
217
                test    SSTAT0, TARGET  jz initiator_reselect;
218
                /*
219
                 * We've just been selected.  Assert BSY and
220
                 * setup the phase for receiving the messages
221
                 * from the target.
222
                 */
223
                mvi     SCSISIGO, P_MESGOUT|BSYO;
224
                mvi     CLRSINT0, CLRSELDO;
225
 
226
                /*
227
                 * If ATN isn't asserted, go directly to bus free.
228
                 */
229
                test    SCSISIGI, ATNI  jz      target_busfree;
230
 
231
                /*
232
                 * Setup the DMA for sending the identify and
233
                 * command information.
234
                 */
235
                mov     A, TMODE_CMDADDR_NEXT;
236
                mvi     DINDEX, HADDR;
237
                mvi     TMODE_CMDADDR call set_32byte_addr;
238
                mvi     DFCNTRL, FIFORESET;
239
 
240
                clr     SINDEX;
241
                /* Watch ATN closely now */
242
message_loop:
243
                or      SXFRCTL0, SPIOEN;
244
                test    SSTAT0, SPIORDY jz .;
245
                and     SXFRCTL0, ~SPIOEN;
246
                mov     DINDEX, SCSIDATL;
247
                mov     DFDAT, DINDEX;
248
                inc     SINDEX;
249
 
250
                /* Message Testing... */
251
                test    DINDEX, MSG_IDENTIFYFLAG jz . + 2;
252
                mov     ARG_1, DINDEX;
253
 
254
                test    SCSISIGI, ATNI  jnz     message_loop;
255
                add     A, -4, SINDEX;
256
                jc      target_cmdphase;
257
                mvi     DFDAT, SCB_LIST_NULL;   /* Terminate the message list */
258
 
259
target_cmdphase:
260
                add     HCNT[0], 1, A;
261
                clr     HCNT[1];
262
                clr     HCNT[2];
263
                mvi     SCSISIGO, P_COMMAND|BSYO;
264
                or      SXFRCTL0, SPIOEN;
265
                test    SSTAT0, SPIORDY jz .;
266
                mov     A, SCSIDATL;
267
                mov     DFDAT, A;       /* Store for host */
268
 
269
                /*
270
                 * Determine the number of bytes to read
271
                 * based on the command group code.  Count is
272
                 * one less than the total since we've already
273
                 * fetched the first byte.
274
                 */
275
                clr     SINDEX;
276
                shr     A, CMD_GROUP_CODE_SHIFT;
277
                add     SEQADDR0, A;
278
 
279
                add     SINDEX, CMD_GROUP0_BYTE_DELTA;
280
                nop;    /* Group 1 and 2 are the same */
281
                add     SINDEX, CMD_GROUP2_BYTE_DELTA;
282
                nop;    /* Group 3 is reserved */
283
                add     SINDEX, CMD_GROUP4_BYTE_DELTA;
284
                add     SINDEX, CMD_GROUP5_BYTE_DELTA;
285
                /* Group 6 and 7 are not handled yet */
286
 
287
                mov     A, SINDEX;
288
                add     HCNT[0], A;
289
 
290
command_loop:
291
                test    SSTAT0, SPIORDY jz .;
292
                cmp     SINDEX, 1 jne . + 2;
293
                and     SXFRCTL0, ~SPIOEN;      /* Last Byte */
294
                mov     DFDAT, SCSIDATL;
295
                dec     SINDEX;
296
                test    SINDEX, 0xFF jnz command_loop;
297
 
298
                or      DFCNTRL, HDMAEN|FIFOFLUSH;
299
 
300
                call    dma_finish;
301
 
302
                test    ARG_1, MSG_IDENTIFY_DISCFLAG jz selectin_post;
303
 
304
                mvi     SCSISIGO, P_MESGIN|BSYO;
305
 
306
                or      SXFRCTL0, SPIOEN;
307
 
308
                mvi     MSG_DISCONNECT call target_outb;
309
 
310
selectin_post:
311
                inc     TMODE_CMDADDR_NEXT;
312
                cmp     TMODE_CMDADDR_NEXT, TMODE_NUMCMDS jne . + 2;
313
                clr     TMODE_CMDADDR_NEXT;
314
                mvi     QOUTFIFO, SCB_LIST_NULL;
315
                mvi     INTSTAT,CMDCMPLT;
316
 
317
                test    ARG_1, MSG_IDENTIFY_DISCFLAG jnz target_busfree;
318
 
319
                /* Busy loop on something then go to data or status phase */
320
 
321
target_busfree:
322
                clr     SCSISIGO;
323
                jmp     poll_for_work;
324
 
325
        }
326
 
327
/*
328
 * Reselection has been initiated by a target. Make a note that we've been
329
 * reselected, but haven't seen an IDENTIFY message from the target yet.
330
 */
331
initiator_reselect:
332
        mvi     CLRSINT0, CLRSELDI;
333
        /* XXX test for and handle ONE BIT condition */
334
        and     SAVED_TCL, SELID_MASK, SELID;
335
        mvi     CLRSINT1,CLRBUSFREE;
336
        or      SIMODE1, ENBUSFREE;             /*
337
                                                 * We aren't expecting a
338
                                                 * bus free, so interrupt
339
                                                 * the kernel driver if it
340
                                                 * happens.
341
                                                 */
342
        mvi     SPIOEN call     initialize_channel;
343
        mvi     MSG_OUT, MSG_NOOP;              /* No message to send */
344
        jmp     ITloop;
345
 
346
/*
347
 * After the selection, remove this SCB from the "waiting SCB"
348
 * list.  This is achieved by simply moving our "next" pointer into
349
 * WAITING_SCBH.  Our next pointer will be set to null the next time this
350
 * SCB is used, so don't bother with it now.
351
 */
352
select_out:
353
        /* Turn off the selection hardware */
354
        mvi     SCSISEQ, ENRSELI|ENAUTOATNP;    /*
355
                                                 * ATN on parity errors
356
                                                 * for "in" phases
357
                                                 */
358
        mvi     CLRSINT0, CLRSELDO;
359
        mov     SCBPTR, WAITING_SCBH;
360
        mov     WAITING_SCBH,SCB_NEXT;
361
        mov     SAVED_TCL, SCB_TCL;
362
        mvi     CLRSINT1,CLRBUSFREE;
363
        or      SIMODE1, ENBUSFREE;             /*
364
                                                 * We aren't expecting a
365
                                                 * bus free, so interrupt
366
                                                 * the kernel driver if it
367
                                                 * happens.
368
                                                 */
369
        mvi     SPIOEN call     initialize_channel;
370
/*
371
 * As soon as we get a successful selection, the target should go
372
 * into the message out phase since we have ATN asserted.
373
 */
374
        mvi     MSG_OUT, MSG_IDENTIFYFLAG;
375
        or      SEQ_FLAGS, IDENTIFY_SEEN;
376
 
377
/*
378
 * Main loop for information transfer phases.  Wait for the target
379
 * to assert REQ before checking MSG, C/D and I/O for the bus phase.
380
 */
381
ITloop:
382
        call    phase_lock;
383
 
384
        mov     A, LASTPHASE;
385
 
386
        test    A, ~P_DATAIN    jz p_data;
387
        cmp     A,P_COMMAND     je p_command;
388
        cmp     A,P_MESGOUT     je p_mesgout;
389
        cmp     A,P_STATUS      je p_status;
390
        cmp     A,P_MESGIN      je p_mesgin;
391
 
392
        mvi     INTSTAT,BAD_PHASE;      /* unknown phase - signal driver */
393
        jmp     ITloop;                 /* Try reading the bus again. */
394
 
395
await_busfree:
396
        and     SIMODE1, ~ENBUSFREE;
397
        call    clear_target_state;
398
        mov     NONE, SCSIDATL;         /* Ack the last byte */
399
        and     SXFRCTL0, ~SPIOEN;
400
        test    SSTAT1,REQINIT|BUSFREE  jz .;
401
        test    SSTAT1, BUSFREE jnz poll_for_work;
402
        mvi     INTSTAT, BAD_PHASE;
403
 
404
clear_target_state:
405
        clr     DFCNTRL;                /*
406
                                         * We assume that the kernel driver
407
                                         * may reset us at any time, even
408
                                         * in the middle of a DMA, so clear
409
                                         * DFCNTRL too.
410
                                         */
411
        clr     SCSIRATE;               /*
412
                                         * We don't know the target we will
413
                                         * connect to, so default to narrow
414
                                         * transfers to avoid parity problems.
415
                                         */
416
        and     SXFRCTL0, ~(FAST20);
417
        mvi     LASTPHASE, P_BUSFREE;
418
        /* clear target specific flags */
419
        and     SEQ_FLAGS, (WIDE_BUS|TWIN_BUS) ret;
420
 
421
/*
422
 * If we re-enter the data phase after going through another phase, the
423
 * STCNT may have been cleared, so restore it from the residual field.
424
 */
425
data_phase_reinit:
426
        mvi     DINDEX, STCNT;
427
        mvi     SCB_RESID_DCNT  call bcopy_3;
428
        jmp     data_phase_loop;
429
 
430
p_data:
431
        if ((p->features & AHC_ULTRA2) != 0) {
432
                mvi     DMAPARAMS, PRELOADEN|SCSIEN|HDMAEN;
433
        } else {
434
                mvi     DMAPARAMS, WIDEODD|SCSIEN|SDMAEN|HDMAEN|FIFORESET;
435
        }
436
        test    LASTPHASE, IOI jnz . + 2;
437
        or      DMAPARAMS, DIRECTION;
438
        call    assert;                 /*
439
                                         * Ensure entering a data
440
                                         * phase is okay - seen identify, etc.
441
                                         */
442
        if ((p->features & AHC_CMD_CHAN) != 0) {
443
                mvi     CCSGADDR, CCSGADDR_MAX;
444
        }
445
        test    SEQ_FLAGS, DPHASE       jnz data_phase_reinit;
446
 
447
        /* We have seen a data phase */
448
        or      SEQ_FLAGS, DPHASE;
449
 
450
        /*
451
         * Initialize the DMA address and counter from the SCB.
452
         * Also set SG_COUNT and SG_NEXT in memory since we cannot
453
         * modify the values in the SCB itself until we see a
454
         * save data pointers message.
455
         */
456
        if ((p->features & AHC_CMD_CHAN) != 0) {
457
                bmov    HADDR, SCB_DATAPTR, 7;
458
        } else {
459
                mvi     DINDEX, HADDR;
460
                mvi     SCB_DATAPTR     call bcopy_7;
461
        }
462
 
463
        if ((p->features & AHC_ULTRA2) == 0) {
464
                call    set_stcnt_from_hcnt;
465
        }
466
 
467
        mov     SG_COUNT,SCB_SGCOUNT;
468
 
469
        mvi     DINDEX, SG_NEXT;
470
        mvi     SCB_SGPTR       call bcopy_4;
471
 
472
data_phase_loop:
473
/* Guard against overruns */
474
        test    SG_COUNT, 0xff jnz data_phase_inbounds;
475
/*
476
 * Turn on 'Bit Bucket' mode, set the transfer count to
477
 * 16meg and let the target run until it changes phase.
478
 * When the transfer completes, notify the host that we
479
 * had an overrun.
480
 */
481
        or      SXFRCTL1,BITBUCKET;
482
        and     DMAPARAMS, ~(HDMAEN|SDMAEN);
483
        if ((p->features & AHC_ULTRA2) != 0) {
484
                bmov    HCNT, ALLONES, 3;
485
        } else {
486
                mvi     STCNT[0], 0xFF;
487
                mvi     STCNT[1], 0xFF;
488
                mvi     STCNT[2], 0xFF;
489
        }
490
data_phase_inbounds:
491
/* If we are the last SG block, tell the hardware. */
492
        cmp     SG_COUNT,0x01 jne data_phase_wideodd;
493
        if ((p->features & AHC_ULTRA2) != 0) {
494
                or      SG_CACHEPTR, LAST_SEG;
495
        } else {
496
                and     DMAPARAMS, ~WIDEODD;
497
        }
498
data_phase_wideodd:
499
        if ((p->features & AHC_ULTRA2) != 0) {
500
                mov     SINDEX, ALLONES;
501
                mov     DFCNTRL, DMAPARAMS;
502
                test    SSTAT0, SDONE jnz .;/* Wait for preload to complete */
503
data_phase_dma_loop:
504
                test    SSTAT0, SDONE jnz data_phase_dma_done;
505
                test    SSTAT1,PHASEMIS jz data_phase_dma_loop; /* ie. underrun */
506
data_phase_dma_phasemis:
507
                test    SSTAT0,SDONE    jnz . + 2;
508
                mov     SINDEX,ALLZEROS;        /* Remeber the phasemiss */
509
        } else {
510
                mov     DMAPARAMS  call dma;
511
        }
512
 
513
data_phase_dma_done:
514
/* Go tell the host about any overruns */
515
        test    SXFRCTL1,BITBUCKET jnz data_phase_overrun;
516
 
517
/* Exit if we had an underrun.  dma clears SINDEX in this case. */
518
        test    SINDEX,0xff     jz data_phase_finish;
519
 
520
/*
521
 * Advance the scatter-gather pointers if needed
522
 */
523
sg_advance:
524
        dec     SG_COUNT;       /* one less segment to go */
525
 
526
        test    SG_COUNT, 0xff  jz data_phase_finish; /* Are we done? */
527
/*
528
 * Load a struct scatter and set up the data address and length.
529
 * If the working value of the SG count is nonzero, then
530
 * we need to load a new set of values.
531
 *
532
 * This, like all DMA's, assumes little-endian host data storage.
533
 */
534
sg_load:
535
        if ((p->features & AHC_CMD_CHAN) != 0) {
536
                /*
537
                 * Do we have any prefetch left???
538
                 */
539
                cmp     CCSGADDR, CCSGADDR_MAX jne prefetched_segs_avail;
540
 
541
                /*
542
                 * Fetch MIN(CCSGADDR_MAX, (SG_COUNT * 8)) bytes.
543
                 */
544
                add     A, -(CCSGRAM_MAXSEGS + 1), SG_COUNT;
545
                mvi     A, CCSGADDR_MAX;
546
                jc      . + 2;
547
                shl     A, 3, SG_COUNT;
548
                mov     CCHCNT, A;
549
                bmov    CCHADDR, SG_NEXT, 4;
550
                mvi     CCSGCTL, CCSGEN|CCSGRESET;
551
                test    CCSGCTL, CCSGDONE jz .;
552
                and     CCSGCTL, ~CCSGEN;
553
                test    CCSGCTL, CCSGEN jnz .;
554
                mvi     CCSGCTL, CCSGRESET;
555
prefetched_segs_avail:
556
                bmov    HADDR, CCSGRAM, 8;
557
        } else {
558
                mvi     DINDEX, HADDR;
559
                mvi     SG_NEXT call bcopy_4;
560
 
561
                mvi     HCNT[0],SG_SIZEOF;
562
                clr     HCNT[1];
563
                clr     HCNT[2];
564
 
565
                or      DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
566
 
567
                call    dma_finish;
568
 
569
                /*
570
                 * Copy data from FIFO into SCB data pointer and data count.
571
                 * This assumes that the SG segments are of the form:
572
                 * struct ahc_dma_seg {
573
                 *      u_int32_t       addr;   four bytes, little-endian order
574
                 *      u_int32_t       len;    four bytes, little endian order
575
                 * };
576
                 */
577
                mvi     HADDR   call dfdat_in_7;
578
        }
579
 
580
        if ((p->features & AHC_ULTRA2) == 0) {
581
                /* Load STCNT as well.  It is a mirror of HCNT */
582
                call    set_stcnt_from_hcnt;
583
        }
584
 
585
/* Advance the SG pointer */
586
        clr     A;                      /* add sizeof(struct scatter) */
587
        add     SG_NEXT[0],SG_SIZEOF;
588
        adc     SG_NEXT[1],A;
589
 
590
        test    SSTAT1,PHASEMIS jz data_phase_loop;
591
        /* Ensure the last seg is visable at the shaddow layer */
592
        if ((p->features & AHC_ULTRA2) != 0) {
593
                or      DFCNTRL, PRELOADEN;
594
        }
595
 
596
data_phase_finish:
597
        if ((p->features & AHC_ULTRA2) != 0) {
598
                call    ultra2_dmafinish;
599
        }
600
/*
601
 * After a DMA finishes, save the SG and STCNT residuals back into the SCB
602
 * We use STCNT instead of HCNT, since it's a reflection of how many bytes
603
 * were transferred on the SCSI (as opposed to the host) bus.
604
 */
605
        mov     SCB_RESID_DCNT[0],STCNT[0];
606
        mov     SCB_RESID_DCNT[1],STCNT[1];
607
        mov     SCB_RESID_DCNT[2],STCNT[2];
608
        mov     SCB_RESID_SGCNT, SG_COUNT;
609
 
610
        if ((p->features & AHC_ULTRA2) != 0) {
611
                or      SXFRCTL0, CLRSTCNT|CLRCHN;
612
        }
613
 
614
        jmp     ITloop;
615
 
616
data_phase_overrun:
617
        if ((p->features & AHC_ULTRA2) != 0) {
618
                call    ultra2_dmafinish;
619
                or      SXFRCTL0, CLRSTCNT|CLRCHN;
620
        }
621
/*
622
 * Turn off BITBUCKET mode and notify the host
623
 */
624
        and     SXFRCTL1, ~BITBUCKET;
625
        mvi     INTSTAT,DATA_OVERRUN;
626
        jmp     ITloop;
627
 
628
ultra2_dmafinish:
629
        if ((p->features & AHC_ULTRA2) != 0) {
630
                test    DFCNTRL, DIRECTION jnz ultra2_dmahalt;
631
                and     DFCNTRL, ~SCSIEN;
632
                test    DFCNTRL, SCSIEN jnz .;
633
                or      DFCNTRL, FIFOFLUSH;
634
                test    DFSTATUS, FIFOEMP jz . - 1;
635
ultra2_dmahalt:
636
                and     DFCNTRL, ~(SCSIEN|HDMAEN);
637
                test    DFCNTRL, HDMAEN jnz .;
638
                ret;
639
        }
640
 
641
/*
642
 * Command phase.  Set up the DMA registers and let 'er rip.
643
 */
644
p_command:
645
        call    assert;
646
 
647
/*
648
 * Load HADDR and HCNT.
649
 */
650
        if ((p->features & AHC_ULTRA2) != 0) {
651
                or      SG_CACHEPTR, LAST_SEG;
652
        }
653
 
654
        if ((p->features & AHC_CMD_CHAN) != 0) {
655
                bmov    HADDR, SCB_CMDPTR, 5;
656
                bmov    HCNT[1], ALLZEROS, 2;
657
        } else {
658
                mvi     DINDEX, HADDR;
659
                mvi     SCB_CMDPTR      call bcopy_5;
660
                clr     HCNT[1];
661
                clr     HCNT[2];
662
        }
663
 
664
        if ((p->features & AHC_ULTRA2) == 0) {
665
                call    set_stcnt_from_hcnt;
666
                mvi     (SCSIEN|SDMAEN|HDMAEN|DIRECTION|FIFORESET) call dma;
667
        } else {
668
                mvi     (PRELOADEN|SCSIEN|HDMAEN|DIRECTION) call dma;
669
        }
670
        jmp     ITloop;
671
 
672
/*
673
 * Status phase.  Wait for the data byte to appear, then read it
674
 * and store it into the SCB.
675
 */
676
p_status:
677
        call    assert;
678
 
679
        mov     SCB_TARGET_STATUS, SCSIDATL;
680
        jmp     ITloop;
681
 
682
/*
683
 * Message out phase.  If MSG_OUT is 0x80, build I full indentify message
684
 * sequence and send it to the target.  In addition, if the MK_MESSAGE bit
685
 * is set in the SCB_CONTROL byte, interrupt the host and allow it to send
686
 * it's own message.
687
 *
688
 * If MSG_OUT is == HOST_MSG, also interrupt the host and take a message.
689
 * This is done to allow the hsot to send messages outside of an identify
690
 * sequence while protecting the seqencer from testing the MK_MESSAGE bit
691
 * on an SCB that might not be for the current nexus. (For example, a
692
 * BDR message in responce to a bad reselection would leave us pointed to
693
 * an SCB that doesn't have anything to do with the current target).
694
 * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
695
 * bus device reset).
696
 *
697
 * When there are no messages to send, MSG_OUT should be set to MSG_NOOP,
698
 * in case the target decides to put us in this phase for some strange
699
 * reason.
700
 */
701
p_mesgout:
702
        mov     SINDEX, MSG_OUT;
703
        cmp     SINDEX, MSG_IDENTIFYFLAG jne p_mesgout_from_host;
704
p_mesgout_identify:
705
        if ((p->features & AHC_WIDE) != 0) {
706
                and     SINDEX,0xf,SCB_TCL;     /* lun */
707
        } else {
708
                and     SINDEX,0x7,SCB_TCL;     /* lun */
709
        }
710
        and     A,DISCENB,SCB_CONTROL;  /* mask off disconnect privledge */
711
        or      SINDEX,A;               /* or in disconnect privledge */
712
        or      SINDEX,MSG_IDENTIFYFLAG;
713
p_mesgout_mk_message:
714
        test    SCB_CONTROL,MK_MESSAGE  jz p_mesgout_tag;
715
        mov     SCSIDATL, SINDEX;       /* Send the last byte */
716
        jmp     p_mesgout_from_host + 1;/* Skip HOST_MSG test */
717
/*
718
 * Send a tag message if TAG_ENB is set in the SCB control block.
719
 * Use SCB_TAG (the position in the kernel's SCB array) as the tag value.
720
 */
721
p_mesgout_tag:
722
        test    SCB_CONTROL,TAG_ENB jz  p_mesgout_onebyte;
723
        mov     SCSIDATL, SINDEX;       /* Send the identify message */
724
        call    phase_lock;
725
        cmp     LASTPHASE, P_MESGOUT    jne p_mesgout_done;
726
        and     SCSIDATL,TAG_ENB|SCB_TAG_TYPE,SCB_CONTROL;
727
        call    phase_lock;
728
        cmp     LASTPHASE, P_MESGOUT    jne p_mesgout_done;
729
        mov     SCB_TAG jmp p_mesgout_onebyte;
730
/*
731
 * Interrupt the driver, and allow it to send a message
732
 * if it asks.
733
 */
734
p_mesgout_from_host:
735
        cmp     SINDEX, HOST_MSG        jne p_mesgout_onebyte;
736
        mvi     INTSTAT,AWAITING_MSG;
737
        nop;
738
        /*
739
         * Did the host detect a phase change?
740
         */
741
        cmp     RETURN_1, MSGOUT_PHASEMIS je p_mesgout_done;
742
 
743
p_mesgout_onebyte:
744
        mvi     CLRSINT1, CLRATNO;
745
        mov     SCSIDATL, SINDEX;
746
 
747
/*
748
 * If the next bus phase after ATN drops is a message out, it means
749
 * that the target is requesting that the last message(s) be resent.
750
 */
751
        call    phase_lock;
752
        cmp     LASTPHASE, P_MESGOUT    jne p_mesgout_done;
753
        or      SCSISIGO,ATNO,LASTPHASE;/* turn on ATN for the retry */
754
        jmp     p_mesgout;
755
 
756
p_mesgout_done:
757
        mvi     CLRSINT1,CLRATNO;       /* Be sure to turn ATNO off */
758
        mov     LAST_MSG, MSG_OUT;
759
        cmp     MSG_OUT, MSG_IDENTIFYFLAG jne . + 2;
760
        and     SCB_CONTROL, ~MK_MESSAGE;
761
        mvi     MSG_OUT, MSG_NOOP;      /* No message left */
762
        jmp     ITloop;
763
 
764
/*
765
 * Message in phase.  Bytes are read using Automatic PIO mode.
766
 */
767
p_mesgin:
768
        mvi     ACCUM           call inb_first; /* read the 1st message byte */
769
 
770
        test    A,MSG_IDENTIFYFLAG      jnz mesgin_identify;
771
        cmp     A,MSG_DISCONNECT        je mesgin_disconnect;
772
        cmp     A,MSG_SAVEDATAPOINTER   je mesgin_sdptrs;
773
        cmp     ALLZEROS,A              je mesgin_complete;
774
        cmp     A,MSG_RESTOREPOINTERS   je mesgin_rdptrs;
775
        cmp     A,MSG_EXTENDED          je mesgin_extended;
776
        cmp     A,MSG_MESSAGE_REJECT    je mesgin_reject;
777
        cmp     A,MSG_NOOP              je mesgin_done;
778
 
779
rej_mesgin:
780
/*
781
 * We have no idea what this message in is, so we issue a message reject
782
 * and hope for the best.  In any case, rejection should be a rare
783
 * occurrence - signal the driver when it happens.
784
 */
785
        mvi     INTSTAT,SEND_REJECT;            /* let driver know */
786
 
787
        mvi     MSG_MESSAGE_REJECT      call mk_mesg;
788
 
789
mesgin_done:
790
        mov     NONE,SCSIDATL;          /*dummy read from latch to ACK*/
791
        jmp     ITloop;
792
 
793
 
794
mesgin_complete:
795
/*
796
 * We got a "command complete" message, so put the SCB_TAG into the QOUTFIFO,
797
 * and trigger a completion interrupt.  Before doing so, check to see if there
798
 * is a residual or the status byte is something other than STATUS_GOOD (0).
799
 * In either of these conditions, we upload the SCB back to the host so it can
800
 * process this information.  In the case of a non zero status byte, we
801
 * additionally interrupt the kernel driver synchronously, allowing it to
802
 * decide if sense should be retrieved.  If the kernel driver wishes to request
803
 * sense, it will fill the kernel SCB with a request sense command and set
804
 * RETURN_1 to SEND_SENSE.  If RETURN_1 is set to SEND_SENSE we redownload
805
 * the SCB, and process it as the next command by adding it to the waiting list.
806
 * If the kernel driver does not wish to request sense, it need only clear
807
 * RETURN_1, and the command is allowed to complete normally.  We don't bother
808
 * to post to the QOUTFIFO in the error cases since it would require extra
809
 * work in the kernel driver to ensure that the entry was removed before the
810
 * command complete code tried processing it.
811
 */
812
 
813
/*
814
 * First check for residuals
815
 */
816
        test    SCB_RESID_SGCNT,0xff    jnz upload_scb;
817
        test    SCB_TARGET_STATUS,0xff  jz complete;    /* Good Status? */
818
upload_scb:
819
        mvi     DMAPARAMS, FIFORESET;
820
        mov     SCB_TAG         call dma_scb;
821
check_status:
822
        test    SCB_TARGET_STATUS,0xff  jz complete;    /* Just a residual? */
823
        mvi     INTSTAT,BAD_STATUS;                     /* let driver know */
824
        nop;
825
        cmp     RETURN_1, SEND_SENSE    jne complete;
826
        /* This SCB becomes the next to execute as it will retrieve sense */
827
        mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
828
        mov     SCB_TAG         call dma_scb;
829
add_to_waiting_list:
830
        mov     SCB_NEXT,WAITING_SCBH;
831
        mov     WAITING_SCBH, SCBPTR;
832
        /*
833
         * Prepare our selection hardware before the busfree so we have a
834
         * high probability of winning arbitration.
835
         */
836
        call    start_selection;
837
        jmp     await_busfree;
838
 
839
complete:
840
        /* If we are untagged, clear our address up in host ram */
841
        test    SCB_CONTROL, TAG_ENB jnz complete_post;
842
        mov     A, SAVED_TCL;
843
        mvi     UNTAGGEDSCB_OFFSET call post_byte_setup;
844
        mvi     SCB_LIST_NULL call post_byte;
845
 
846
complete_post:
847
        /* Post the SCB and issue an interrupt */
848
        if ((p->features & AHC_QUEUE_REGS) != 0) {
849
                mov     A, SDSCB_QOFF;
850
        } else {
851
                mov     A, QOUTPOS;
852
        }
853
        mvi     QOUTFIFO_OFFSET call post_byte_setup;
854
        mov     SCB_TAG call post_byte;
855
        if ((p->features & AHC_QUEUE_REGS) == 0) {
856
                inc     QOUTPOS;
857
        }
858
        mvi     INTSTAT,CMDCMPLT;
859
 
860
add_to_free_list:
861
        call    add_scb_to_free_list;
862
        jmp     await_busfree;
863
 
864
/*
865
 * Is it an extended message?  Copy the message to our message buffer and
866
 * notify the host.  The host will tell us whether to reject this message,
867
 * respond to it with the message that the host placed in our message buffer,
868
 * or simply to do nothing.
869
 */
870
mesgin_extended:
871
        mvi     INTSTAT,EXTENDED_MSG;           /* let driver know */
872
        jmp     ITloop;
873
 
874
/*
875
 * Is it a disconnect message?  Set a flag in the SCB to remind us
876
 * and await the bus going free.
877
 */
878
mesgin_disconnect:
879
        or      SCB_CONTROL,DISCONNECTED;
880
        call    add_scb_to_disc_list;
881
        jmp     await_busfree;
882
 
883
/*
884
 * Save data pointers message:
885
 * Copying RAM values back to SCB, for Save Data Pointers message, but
886
 * only if we've actually been into a data phase to change them.  This
887
 * protects against bogus data in scratch ram and the residual counts
888
 * since they are only initialized when we go into data_in or data_out.
889
 */
890
mesgin_sdptrs:
891
        test    SEQ_FLAGS, DPHASE       jz mesgin_done;
892
        mov     SCB_SGCOUNT,SG_COUNT;
893
 
894
        /* The SCB SGPTR becomes the next one we'll download */
895
        mvi     DINDEX, SCB_SGPTR;
896
        mvi     SG_NEXT call bcopy_4;
897
 
898
        /* The SCB DATAPTR0 becomes the current SHADDR */
899
        mvi     DINDEX, SCB_DATAPTR;
900
        mvi     SHADDR          call bcopy_4;
901
 
902
/*
903
 * Use the residual number since STCNT is corrupted by any message transfer.
904
 */
905
        mvi     SCB_RESID_DCNT  call    bcopy_3;
906
 
907
        jmp     mesgin_done;
908
 
909
/*
910
 * Restore pointers message?  Data pointers are recopied from the
911
 * SCB anytime we enter a data phase for the first time, so all
912
 * we need to do is clear the DPHASE flag and let the data phase
913
 * code do the rest.
914
 */
915
mesgin_rdptrs:
916
        and     SEQ_FLAGS, ~DPHASE;             /*
917
                                                 * We'll reload them
918
                                                 * the next time through
919
                                                 * the dataphase.
920
                                                 */
921
        jmp     mesgin_done;
922
 
923
/*
924
 * Identify message?  For a reconnecting target, this tells us the lun
925
 * that the reconnection is for - find the correct SCB and switch to it,
926
 * clearing the "disconnected" bit so we don't "find" it by accident later.
927
 */
928
mesgin_identify:
929
 
930
        if ((p->features & AHC_WIDE) != 0) {
931
                and     A,0x0f;         /* lun in lower four bits */
932
        } else {
933
                and     A,0x07;         /* lun in lower three bits */
934
        }
935
        or      SAVED_TCL,A;            /* SAVED_TCL should be complete now */
936
 
937
        call    get_untagged_SCBID;
938
        cmp     ARG_1, SCB_LIST_NULL    je snoop_tag;
939
        if ((p->flags & AHC_PAGESCBS) != 0) {
940
                test    SEQ_FLAGS, SCBPTR_VALID jz use_retrieveSCB;
941
        }
942
        /*
943
         * If the SCB was found in the disconnected list (as is
944
         * always the case in non-paging scenarios), SCBPTR is already
945
         * set to the correct SCB.  So, simply setup the SCB and get
946
         * on with things.
947
         */
948
        mov     SCBPTR  call rem_scb_from_disc_list;
949
        jmp     setup_SCB;
950
/*
951
 * Here we "snoop" the bus looking for a SIMPLE QUEUE TAG message.
952
 * If we get one, we use the tag returned to find the proper
953
 * SCB.  With SCB paging, this requires using search for both tagged
954
 * and non-tagged transactions since the SCB may exist in any slot.
955
 * If we're not using SCB paging, we can use the tag as the direct
956
 * index to the SCB.
957
 */
958
snoop_tag:
959
        mov     NONE,SCSIDATL;          /* ACK Identify MSG */
960
snoop_tag_loop:
961
        call    phase_lock;
962
        cmp     LASTPHASE, P_MESGIN     jne not_found;
963
        cmp     SCSIBUSL,MSG_SIMPLE_Q_TAG jne not_found;
964
get_tag:
965
        mvi     ARG_1   call inb_next;  /* tag value */
966
 
967
        if ((p->flags & AHC_PAGESCBS) == 0) {
968
index_by_tag:
969
                mov     SCBPTR,ARG_1;
970
                test    SCB_CONTROL,TAG_ENB     jz  not_found;
971
                mov     SCBPTR  call rem_scb_from_disc_list;
972
        } else {
973
                /*
974
                 * Ensure that the SCB the tag points to is for
975
                 * an SCB transaction to the reconnecting target.
976
                 */
977
use_retrieveSCB:
978
                call    retrieveSCB;
979
        }
980
setup_SCB:
981
        mov     A, SAVED_TCL;
982
        cmp     SCB_TCL, A      jne not_found_cleanup_scb;
983
        test    SCB_CONTROL,DISCONNECTED jz not_found_cleanup_scb;
984
        and     SCB_CONTROL,~DISCONNECTED;
985
        or      SEQ_FLAGS,IDENTIFY_SEEN;          /* make note of IDENTIFY */
986
        /* See if the host wants to send a message upon reconnection */
987
        test    SCB_CONTROL, MK_MESSAGE jz mesgin_done;
988
        and     SCB_CONTROL, ~MK_MESSAGE;
989
        mvi     HOST_MSG        call mk_mesg;
990
        jmp     mesgin_done;
991
 
992
not_found_cleanup_scb:
993
        test    SCB_CONTROL, DISCONNECTED jz . + 3;
994
        call    add_scb_to_disc_list;
995
        jmp     not_found;
996
        call    add_scb_to_free_list;
997
not_found:
998
        mvi     INTSTAT, NO_MATCH;
999
        mvi     MSG_BUS_DEV_RESET       call mk_mesg;
1000
        jmp     mesgin_done;
1001
 
1002
/*
1003
 * Message reject?  Let the kernel driver handle this.  If we have an
1004
 * outstanding WDTR or SDTR negotiation, assume that it's a response from
1005
 * the target selecting 8bit or asynchronous transfer, otherwise just ignore
1006
 * it since we have no clue what it pertains to.
1007
 */
1008
mesgin_reject:
1009
        mvi     INTSTAT, REJECT_MSG;
1010
        jmp     mesgin_done;
1011
 
1012
/*
1013
 * [ ADD MORE MESSAGE HANDLING HERE ]
1014
 */
1015
 
1016
/*
1017
 * Locking the driver out, build a one-byte message passed in SINDEX
1018
 * if there is no active message already.  SINDEX is returned intact.
1019
 */
1020
mk_mesg:
1021
        or      SCSISIGO,ATNO,LASTPHASE;/* turn on ATNO */
1022
        mov     MSG_OUT,SINDEX ret;
1023
 
1024
/*
1025
 * Functions to read data in Automatic PIO mode.
1026
 *
1027
 * According to Adaptec's documentation, an ACK is not sent on input from
1028
 * the target until SCSIDATL is read from.  So we wait until SCSIDATL is
1029
 * latched (the usual way), then read the data byte directly off the bus
1030
 * using SCSIBUSL.  When we have pulled the ATN line, or we just want to
1031
 * acknowledge the byte, then we do a dummy read from SCISDATL.  The SCSI
1032
 * spec guarantees that the target will hold the data byte on the bus until
1033
 * we send our ACK.
1034
 *
1035
 * The assumption here is that these are called in a particular sequence,
1036
 * and that REQ is already set when inb_first is called.  inb_{first,next}
1037
 * use the same calling convention as inb.
1038
 */
1039
 
1040
inb_next:
1041
        mov     NONE,SCSIDATL;          /*dummy read from latch to ACK*/
1042
inb_next_wait:
1043
        /*
1044
         * If there is a parity error, wait for the kernel to
1045
         * see the interrupt and prepare our message response
1046
         * before continuing.
1047
         */
1048
        test    SSTAT1, REQINIT jz inb_next_wait;
1049
        test    SSTAT1, SCSIPERR jnz inb_next_wait;
1050
        and     LASTPHASE, PHASE_MASK, SCSISIGI;
1051
        cmp     LASTPHASE, P_MESGIN jne mesgin_phasemis;
1052
inb_first:
1053
        mov     DINDEX,SINDEX;
1054
        mov     DINDIR,SCSIBUSL ret;            /*read byte directly from bus*/
1055
inb_last:
1056
        mov     NONE,SCSIDATL ret;              /*dummy read from latch to ACK*/
1057
 
1058
if ((p->flags & AHC_TARGETMODE) != 0) {
1059
        /*
1060
         * Send a byte to an initiator in Automatic PIO mode.
1061
         * SPIOEN must be on prior to calling this routine.
1062
         */
1063
target_outb:
1064
        mov     SCSIDATL, SINDEX;
1065
        test    SSTAT0, SPIORDY jz .;
1066
        ret;
1067
}
1068
 
1069
mesgin_phasemis:
1070
/*
1071
 * We expected to receive another byte, but the target changed phase
1072
 */
1073
        mvi     INTSTAT, MSGIN_PHASEMIS;
1074
        jmp     ITloop;
1075
 
1076
/*
1077
 * DMA data transfer.  HADDR and HCNT must be loaded first, and
1078
 * SINDEX should contain the value to load DFCNTRL with - 0x3d for
1079
 * host->scsi, or 0x39 for scsi->host.  The SCSI channel is cleared
1080
 * during initialization.
1081
 */
1082
dma:
1083
        mov     DFCNTRL,SINDEX;
1084
dma_loop:
1085
        test    SSTAT0,DMADONE  jnz dma_dmadone;
1086
        test    SSTAT1,PHASEMIS jz dma_loop;    /* ie. underrun */
1087
dma_phasemis:
1088
        test    SSTAT0,SDONE    jnz dma_checkfifo;
1089
        mov     SINDEX,ALLZEROS;                /* Notify caller of phasemiss */
1090
 
1091
/*
1092
 * We will be "done" DMAing when the transfer count goes to zero, or
1093
 * the target changes the phase (in light of this, it makes sense that
1094
 * the DMA circuitry doesn't ACK when PHASEMIS is active).  If we are
1095
 * doing a SCSI->Host transfer, the data FIFO should be flushed auto-
1096
 * magically on STCNT=0 or a phase change, so just wait for FIFO empty
1097
 * status.
1098
 */
1099
dma_checkfifo:
1100
        test    DFCNTRL,DIRECTION       jnz dma_fifoempty;
1101
dma_fifoflush:
1102
        test    DFSTATUS,FIFOEMP        jz dma_fifoflush;
1103
 
1104
dma_fifoempty:
1105
        /* Don't clobber an inprogress host data transfer */
1106
        test    DFSTATUS, MREQPEND      jnz dma_fifoempty;
1107
/*
1108
 * Now shut the DMA enables off and make sure that the DMA enables are
1109
 * actually off first lest we get an ILLSADDR.
1110
 */
1111
dma_dmadone:
1112
        and     DFCNTRL, ~(SCSIEN|SDMAEN|HDMAEN);
1113
dma_halt:
1114
        /*
1115
         * Some revisions of the aic7880 have a problem where, if the
1116
         * data fifo is full, but the PCI input latch is not empty,
1117
         * HDMAEN cannot be cleared.  The fix used here is to attempt
1118
         * to drain the data fifo until there is space for the input
1119
         * latch to drain and HDMAEN de-asserts.
1120
         */
1121
        if ((p->features & AHC_ULTRA2) == 0) {
1122
                mov     NONE, DFDAT;
1123
        }
1124
        test    DFCNTRL, HDMAEN jnz dma_halt;
1125
return:
1126
        ret;
1127
 
1128
/*
1129
 * Assert that if we've been reselected, then we've seen an IDENTIFY
1130
 * message.
1131
 */
1132
assert:
1133
        test    SEQ_FLAGS,IDENTIFY_SEEN jnz return;     /* seen IDENTIFY? */
1134
 
1135
        mvi     INTSTAT,NO_IDENT        ret;    /* no - tell the kernel */
1136
 
1137
/*
1138
 * Locate a disconnected SCB either by SAVED_TCL (ARG_1 is SCB_LIST_NULL)
1139
 * or by the SCBID ARG_1.  The search begins at the SCB index passed in
1140
 * via SINDEX which is an SCB that must be on the disconnected list.  If
1141
 * the SCB cannot be found, SINDEX will be SCB_LIST_NULL, otherwise, SCBPTR
1142
 * is set to the proper SCB.
1143
 */
1144
findSCB:
1145
        mov     SCBPTR,SINDEX;                  /* Initialize SCBPTR */
1146
        cmp     ARG_1, SCB_LIST_NULL    jne findSCB_by_SCBID;
1147
        mov     A, SAVED_TCL;
1148
        mvi     SCB_TCL jmp findSCB_loop;       /* &SCB_TCL -> SINDEX */
1149
findSCB_by_SCBID:
1150
        mov     A, ARG_1;                       /* Tag passed in ARG_1 */
1151
        mvi     SCB_TAG jmp findSCB_loop;       /* &SCB_TAG -> SINDEX */
1152
findSCB_next:
1153
        cmp     SCB_NEXT, SCB_LIST_NULL je notFound;
1154
        mov     SCBPTR,SCB_NEXT;
1155
        dec     SINDEX;         /* Last comparison moved us too far */
1156
findSCB_loop:
1157
        cmp     SINDIR, A       jne findSCB_next;
1158
        mov     SINDEX, SCBPTR  ret;
1159
notFound:
1160
        mvi     SINDEX, SCB_LIST_NULL   ret;
1161
 
1162
/*
1163
 * Retrieve an SCB by SCBID first searching the disconnected list falling
1164
 * back to DMA'ing the SCB down from the host.  This routine assumes that
1165
 * ARG_1 is the SCBID of interrest and that SINDEX is the position in the
1166
 * disconnected list to start the search from.  If SINDEX is SCB_LIST_NULL,
1167
 * we go directly to the host for the SCB.
1168
 */
1169
retrieveSCB:
1170
        test    SEQ_FLAGS, SCBPTR_VALID jz retrieve_from_host;
1171
        mov     SCBPTR  call findSCB;   /* Continue the search */
1172
        cmp     SINDEX, SCB_LIST_NULL   je retrieve_from_host;
1173
 
1174
/*
1175
 * This routine expects SINDEX to contain the index of the SCB to be
1176
 * removed and SCBPTR to be pointing to that SCB.
1177
 */
1178
rem_scb_from_disc_list:
1179
/* Remove this SCB from the disconnection list */
1180
        cmp     SCB_NEXT,SCB_LIST_NULL je unlink_prev;
1181
        mov     DINDEX, SCB_PREV;
1182
        mov     SCBPTR, SCB_NEXT;
1183
        mov     SCB_PREV, DINDEX;
1184
        mov     SCBPTR, SINDEX;
1185
unlink_prev:
1186
        cmp     SCB_PREV,SCB_LIST_NULL  je rHead;/* At the head of the list */
1187
        mov     DINDEX, SCB_NEXT;
1188
        mov     SCBPTR, SCB_PREV;
1189
        mov     SCB_NEXT, DINDEX;
1190
        mov     SCBPTR, SINDEX ret;
1191
rHead:
1192
        mov     DISCONNECTED_SCBH,SCB_NEXT ret;
1193
 
1194
retrieve_from_host:
1195
/*
1196
 * We didn't find it.  Pull an SCB and DMA down the one we want.
1197
 * We should never get here in the non-paging case.
1198
 */
1199
        mov     ALLZEROS        call    get_free_or_disc_scb;
1200
        mvi     DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
1201
        /* Jump instead of call as we want to return anyway */
1202
        mov     ARG_1   jmp dma_scb;
1203
 
1204
/*
1205
 * Determine whether a target is using tagged or non-tagged transactions
1206
 * by first looking for a matching transaction based on the TCL and if
1207
 * that fails, looking up this device in the host's untagged SCB array.
1208
 * The TCL to search for is assumed to be in SAVED_TCL.  The value is
1209
 * returned in ARG_1 (SCB_LIST_NULL for tagged, SCBID for non-tagged).
1210
 * The SCBPTR_VALID bit is set in SEQ_FLAGS if we found the information
1211
 * in an SCB instead of having to go to the host.
1212
 */
1213
get_untagged_SCBID:
1214
        cmp     DISCONNECTED_SCBH, SCB_LIST_NULL je get_SCBID_from_host;
1215
        mvi     ARG_1, SCB_LIST_NULL;
1216
        mov     DISCONNECTED_SCBH call findSCB;
1217
        cmp     SINDEX, SCB_LIST_NULL   je get_SCBID_from_host;
1218
        or      SEQ_FLAGS, SCBPTR_VALID;/* Was in disconnected list */
1219
        test    SCB_CONTROL, TAG_ENB    jnz . + 2;
1220
        mov     ARG_1, SCB_TAG  ret;
1221
        mvi     ARG_1, SCB_LIST_NULL ret;
1222
 
1223
/*
1224
 * Fetch a byte from host memory given an index of (A + (256 * SINDEX))
1225
 * and a base address of SCBID_ADDR.  The byte is returned in RETURN_2.
1226
 */
1227
fetch_byte:
1228
        mov     ARG_2, SINDEX;
1229
        if ((p->features & AHC_CMD_CHAN) != 0) {
1230
                mvi     DINDEX, CCHADDR;
1231
                mvi     SCBID_ADDR call set_1byte_addr;
1232
                mvi     CCHCNT, 1;
1233
                mvi     CCSGCTL, CCSGEN|CCSGRESET;
1234
                test    CCSGCTL, CCSGDONE jz .;
1235
                mvi     CCSGCTL, CCSGRESET;
1236
                bmov    RETURN_2, CCSGRAM, 1 ret;
1237
        } else {
1238
                mvi     DINDEX, HADDR;
1239
                mvi     SCBID_ADDR call set_1byte_addr;
1240
                mvi     HCNT[0], 1;
1241
                clr     HCNT[1];
1242
                clr     HCNT[2];
1243
                mvi     DFCNTRL, HDMAEN|DIRECTION|FIFORESET;
1244
                call    dma_finish;
1245
                mov     RETURN_2, DFDAT ret;
1246
        }
1247
 
1248
/*
1249
 * Prepare the hardware to post a byte to host memory given an
1250
 * index of (A + (256 * SINDEX)) and a base address of SCBID_ADDR.
1251
 */
1252
post_byte_setup:
1253
        mov     ARG_2, SINDEX;
1254
        if ((p->features & AHC_CMD_CHAN) != 0) {
1255
                mvi     DINDEX, CCHADDR;
1256
                mvi     SCBID_ADDR call set_1byte_addr;
1257
                mvi     CCHCNT, 1;
1258
                mvi     CCSCBCTL, CCSCBRESET ret;
1259
        } else {
1260
                mvi     DINDEX, HADDR;
1261
                mvi     SCBID_ADDR call set_1byte_addr;
1262
                mvi     HCNT[0], 1;
1263
                clr     HCNT[1];
1264
                clr     HCNT[2];
1265
                mvi     DFCNTRL, FIFORESET ret;
1266
        }
1267
 
1268
post_byte:
1269
        if ((p->features & AHC_CMD_CHAN) != 0) {
1270
                bmov    CCSCBRAM, SINDEX, 1;
1271
                or      CCSCBCTL, CCSCBEN|CCSCBRESET;
1272
                test    CCSCBCTL, CCSCBDONE jz .;
1273
                clr     CCSCBCTL ret;
1274
        } else {
1275
                mov     DFDAT, SINDEX;
1276
                or      DFCNTRL, HDMAEN|FIFOFLUSH;
1277
                jmp     dma_finish;
1278
        }
1279
 
1280
get_SCBID_from_host:
1281
        mov     A, SAVED_TCL;
1282
        mvi     UNTAGGEDSCB_OFFSET call fetch_byte;
1283
        mov     RETURN_1,  RETURN_2 ret;
1284
 
1285
phase_lock:
1286
        test    SSTAT1, REQINIT jz phase_lock;
1287
        test    SSTAT1, SCSIPERR jnz phase_lock;
1288
        and     LASTPHASE, PHASE_MASK, SCSISIGI;
1289
        mov     SCSISIGO, LASTPHASE ret;
1290
 
1291
set_stcnt_from_hcnt:
1292
        mov     STCNT[0], HCNT[0];
1293
        mov     STCNT[1], HCNT[1];
1294
        mov     STCNT[2], HCNT[2] ret;
1295
 
1296
bcopy_7:
1297
        mov     DINDIR, SINDIR;
1298
        mov     DINDIR, SINDIR;
1299
bcopy_5:
1300
        mov     DINDIR, SINDIR;
1301
bcopy_4:
1302
        mov     DINDIR, SINDIR;
1303
bcopy_3:
1304
        mov     DINDIR, SINDIR;
1305
        mov     DINDIR, SINDIR;
1306
        mov     DINDIR, SINDIR ret;
1307
 
1308
/*
1309
 * Setup addr assuming that A is an index into
1310
 * an array of 32byte objects, SINDEX contains
1311
 * the base address of that array, and DINDEX
1312
 * contains the base address of the location
1313
 * to store the indexed address.
1314
 */
1315
set_32byte_addr:
1316
        shr     ARG_2, 3, A;
1317
        shl     A, 5;
1318
/*
1319
 * Setup addr assuming that A + (ARG_1 * 256) is an
1320
 * index into an array of 1byte objects, SINDEX contains
1321
 * the base address of that array, and DINDEX contains
1322
 * the base address of the location to store the computed
1323
 * address.
1324
 */
1325
set_1byte_addr:
1326
        add     DINDIR, A, SINDIR;
1327
        mov     A, ARG_2;
1328
        adc     DINDIR, A, SINDIR;
1329
        clr     A;
1330
        adc     DINDIR, A, SINDIR;
1331
        adc     DINDIR, A, SINDIR ret;
1332
 
1333
/*
1334
 * Either post or fetch and SCB from host memory based on the
1335
 * DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
1336
 */
1337
dma_scb:
1338
        mov     A, SINDEX;
1339
        if ((p->features & AHC_CMD_CHAN) != 0) {
1340
                mvi     DINDEX, CCHADDR;
1341
                mvi     HSCB_ADDR call set_32byte_addr;
1342
                mov     CCSCBPTR, SCBPTR;
1343
                mvi     CCHCNT, 32;
1344
                test    DMAPARAMS, DIRECTION jz dma_scb_tohost;
1345
                mvi     CCSCBCTL, CCARREN|CCSCBEN|CCSCBDIR|CCSCBRESET;
1346
                cmp     CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN|CCSCBDIR jne .;
1347
                jmp     dma_scb_finish;
1348
dma_scb_tohost:
1349
                if ((p->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1350
                        mvi     CCSCBCTL, CCSCBRESET;
1351
                        bmov    CCSCBRAM, SCB_CONTROL, 32;
1352
                        or      CCSCBCTL, CCSCBEN|CCSCBRESET;
1353
                        test    CCSCBCTL, CCSCBDONE jz .;
1354
                } else {
1355
                        mvi     CCSCBCTL, CCARREN|CCSCBEN|CCSCBRESET;
1356
                        cmp     CCSCBCTL, CCSCBDONE|ARRDONE|CCARREN|CCSCBEN jne .;
1357
                }
1358
dma_scb_finish:
1359
                clr     CCSCBCTL;
1360
                test    CCSCBCTL, CCARREN|CCSCBEN jnz .;
1361
                ret;
1362
        } else {
1363
                mvi     DINDEX, HADDR;
1364
                mvi     HSCB_ADDR call set_32byte_addr;
1365
                mvi     HCNT[0], 32;
1366
                clr     HCNT[1];
1367
                clr     HCNT[2];
1368
                mov     DFCNTRL, DMAPARAMS;
1369
                test    DMAPARAMS, DIRECTION    jnz dma_scb_fromhost;
1370
                /* Fill it with the SCB data */
1371
copy_scb_tofifo:
1372
                mvi     SINDEX, SCB_CONTROL;
1373
                add     A, 32, SINDEX;
1374
copy_scb_tofifo_loop:
1375
                mov     DFDAT,SINDIR;
1376
                mov     DFDAT,SINDIR;
1377
                mov     DFDAT,SINDIR;
1378
                mov     DFDAT,SINDIR;
1379
                mov     DFDAT,SINDIR;
1380
                mov     DFDAT,SINDIR;
1381
                mov     DFDAT,SINDIR;
1382
                mov     DFDAT,SINDIR;
1383
                cmp     SINDEX, A jne copy_scb_tofifo_loop;
1384
                or      DFCNTRL, HDMAEN|FIFOFLUSH;
1385
dma_scb_fromhost:
1386
                call    dma_finish;
1387
                /* If we were putting the SCB, we are done */
1388
                test    DMAPARAMS, DIRECTION    jz      return;
1389
                mvi     SCB_CONTROL  call dfdat_in_7;
1390
                call    dfdat_in_7_continued;
1391
                call    dfdat_in_7_continued;
1392
                jmp     dfdat_in_7_continued;
1393
dfdat_in_7:
1394
                mov     DINDEX,SINDEX;
1395
dfdat_in_7_continued:
1396
                mov     DINDIR,DFDAT;
1397
                mov     DINDIR,DFDAT;
1398
                mov     DINDIR,DFDAT;
1399
                mov     DINDIR,DFDAT;
1400
                mov     DINDIR,DFDAT;
1401
                mov     DINDIR,DFDAT;
1402
                mov     DINDIR,DFDAT ret;
1403
        }
1404
 
1405
 
1406
/*
1407
 * Wait for DMA from host memory to data FIFO to complete, then disable
1408
 * DMA and wait for it to acknowledge that it's off.
1409
 */
1410
dma_finish:
1411
        test    DFSTATUS,HDONE  jz dma_finish;
1412
        /* Turn off DMA */
1413
        and     DFCNTRL, ~HDMAEN;
1414
        test    DFCNTRL, HDMAEN jnz .;
1415
        ret;
1416
 
1417
add_scb_to_free_list:
1418
        if ((p->flags & AHC_PAGESCBS) != 0) {
1419
                mov     SCB_NEXT, FREE_SCBH;
1420
                mov     FREE_SCBH, SCBPTR;
1421
        }
1422
        mvi     SCB_TAG, SCB_LIST_NULL ret;
1423
 
1424
if ((p->flags & AHC_PAGESCBS) != 0) {
1425
get_free_or_disc_scb:
1426
        cmp     FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
1427
        cmp     DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
1428
return_error:
1429
        mvi     SINDEX, SCB_LIST_NULL   ret;
1430
dequeue_disc_scb:
1431
        mov     SCBPTR, DISCONNECTED_SCBH;
1432
dma_up_scb:
1433
        mvi     DMAPARAMS, FIFORESET;
1434
        mov     SCB_TAG         call dma_scb;
1435
unlink_disc_scb:
1436
        /* jmp instead of call since we want to return anyway */
1437
        mov     SCBPTR  jmp rem_scb_from_disc_list;
1438
dequeue_free_scb:
1439
        mov     SCBPTR, FREE_SCBH;
1440
        mov     FREE_SCBH, SCB_NEXT ret;
1441
}
1442
 
1443
add_scb_to_disc_list:
1444
/*
1445
 * Link this SCB into the DISCONNECTED list.  This list holds the
1446
 * candidates for paging out an SCB if one is needed for a new command.
1447
 * Modifying the disconnected list is a critical(pause dissabled) section.
1448
 */
1449
        mvi     SCB_PREV, SCB_LIST_NULL;
1450
        mov     SCB_NEXT, DISCONNECTED_SCBH;
1451
        mov     DISCONNECTED_SCBH, SCBPTR;
1452
        cmp     SCB_NEXT,SCB_LIST_NULL je return;
1453
        mov     SCBPTR,SCB_NEXT;
1454
        mov     SCB_PREV,DISCONNECTED_SCBH;
1455
        mov     SCBPTR,DISCONNECTED_SCBH ret;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.