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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [drivers/] [scsi/] [53c7,8xx.scr] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1626 jcastillo
#undef DEBUG
2
#undef EVENTS
3
; NCR 53c810 driver, main script
4
; Sponsored by
5
;       iX Multiuser Multitasking Magazine
6
;       hm@ix.de
7
;
8
; Copyright 1993, 1994, 1995 Drew Eckhardt
9
;      Visionary Computing
10
;      (Unix and Linux consulting and custom programming)
11
;      drew@PoohSticks.ORG
12
;      +1 (303) 786-7975
13
;
14
; TolerANT and SCSI SCRIPTS are registered trademarks of NCR Corporation.
15
;
16
; PRE-ALPHA
17
;
18
; For more information, please consult
19
;
20
; NCR 53C810
21
; PCI-SCSI I/O Processor
22
; Data Manual
23
;
24
; NCR 53C710
25
; SCSI I/O Processor
26
; Programmers Guide
27
;
28
; NCR Microelectronics
29
; 1635 Aeroplaza Drive
30
; Colorado Springs, CO 80916
31
; 1+ (719) 578-3400
32
;
33
; Toll free literature number
34
; +1 (800) 334-5454
35
;
36
; IMPORTANT : This code is self modifying due to the limitations of
37
;       the NCR53c7,8xx series chips.  Persons debugging this code with
38
;       the remote debugger should take this into account, and NOT set
39
;       breakpoints in modified instructions.
40
;
41
; Design:
42
; The NCR53c7,8xx family of SCSI chips are busmasters with an onboard
43
; microcontroller using a simple instruction set.
44
;
45
; So, to minimize the effects of interrupt latency, and to maximize
46
; throughput, this driver offloads the practical maximum amount
47
; of processing to the SCSI chip while still maintaining a common
48
; structure.
49
;
50
; Where tradeoffs were needed between efficiency on the older
51
; chips and the newer NCR53c800 series, the NCR53c800 series
52
; was chosen.
53
;
54
; While the NCR53c700 and NCR53c700-66 lacked the facilities to fully
55
; automate SCSI transfers without host processor intervention, this
56
; isn't the case with the NCR53c710 and newer chips which allow
57
;
58
; - reads and writes to the internal registers from within the SCSI
59
;       scripts, allowing the SCSI SCRIPTS(tm) code to save processor
60
;       state so that multiple threads of execution are possible, and also
61
;       provide an ALU for loop control, etc.
62
;
63
; - table indirect addressing for some instructions. This allows
64
;       pointers to be located relative to the DSA ((Data Structure
65
;       Address) register.
66
;
67
; These features make it possible to implement a mailbox style interface,
68
; where the same piece of code is run to handle I/O for multiple threads
69
; at once minimizing our need to relocate code.  Since the NCR53c700/
70
; NCR53c800 series have a unique combination of features, making a
71
; a standard ingoing/outgoing mailbox system, costly, I've modified it.
72
;
73
; - Mailboxes are a mixture of code and data.  This lets us greatly
74
;       simplify the NCR53c810 code and do things that would otherwise
75
;       not be possible.
76
;
77
; The saved data pointer is now implemented as follows :
78
;
79
;       Control flow has been architected such that if control reaches
80
;       munge_save_data_pointer, on a restore pointers message or
81
;       reconnection, a jump to the address formerly in the TEMP register
82
;       will allow the SCSI command to resume execution.
83
;
84
 
85
;
86
; Note : the DSA structures must be aligned on 32 bit boundaries,
87
; since the source and destination of MOVE MEMORY instructions
88
; must share the same alignment and this is the alignment of the
89
; NCR registers.
90
;
91
 
92
ABSOLUTE dsa_temp_lun = 0               ; Patch to lun for current dsa
93
ABSOLUTE dsa_temp_next = 0              ; Patch to dsa next for current dsa
94
ABSOLUTE dsa_temp_addr_next = 0         ; Patch to address of dsa next address
95
                                        ;       for current dsa
96
ABSOLUTE dsa_temp_sync = 0              ; Patch to address of per-target
97
                                        ;       sync routine
98
ABSOLUTE dsa_temp_target = 0            ; Patch to id for current dsa
99
ABSOLUTE dsa_temp_addr_saved_pointer = 0; Patch to address of per-command
100
                                        ;       saved data pointer
101
ABSOLUTE dsa_temp_addr_residual = 0     ; Patch to address of per-command
102
                                        ;       current residual code
103
ABSOLUTE dsa_temp_addr_saved_residual = 0; Patch to address of per-command
104
                                        ; saved residual code
105
ABSOLUTE dsa_temp_addr_new_value = 0    ; Address of value for JUMP operand
106
ABSOLUTE dsa_temp_addr_array_value = 0  ; Address to copy to
107
ABSOLUTE dsa_temp_addr_dsa_value = 0    ; Address of this DSA value
108
 
109
;
110
; Once a device has initiated reselection, we need to compare it
111
; against the singly linked list of commands which have disconnected
112
; and are pending reselection.  These commands are maintained in
113
; an unordered singly linked list of DSA structures, through the
114
; DSA pointers at their 'centers' headed by the reconnect_dsa_head
115
; pointer.
116
;
117
; To avoid complications in removing commands from the list,
118
; I minimize the amount of expensive (at eight operations per
119
; addition @ 500-600ns each) pointer operations which must
120
; be done in the NCR driver by precomputing them on the
121
; host processor during dsa structure generation.
122
;
123
; The fixed-up per DSA code knows how to recognize the nexus
124
; associated with the corresponding SCSI command, and modifies
125
; the source and destination pointers for the MOVE MEMORY
126
; instruction which is executed when reselected_ok is called
127
; to remove the command from the list.  Similarly, DSA is
128
; loaded with the address of the next DSA structure and
129
; reselected_check_next is called if a failure occurs.
130
;
131
; Perhaps more concisely, the net effect of the mess is
132
;
133
; for (dsa = reconnect_dsa_head, dest = &reconnect_dsa_head,
134
;     src = NULL; dsa; dest = &dsa->next, dsa = dsa->next) {
135
;       src = &dsa->next;
136
;       if (target_id == dsa->id && target_lun == dsa->lun) {
137
;               *dest = *src;
138
;               break;
139
;         }
140
; }
141
;
142
; if (!dsa)
143
;           error (int_err_unexpected_reselect);
144
; else
145
;     longjmp (dsa->jump_resume, 0);
146
;
147
;
148
 
149
#if (CHIP != 700) && (CHIP != 70066)
150
; Define DSA structure used for mailboxes
151
ENTRY dsa_code_template
152
dsa_code_template:
153
ENTRY dsa_code_begin
154
dsa_code_begin:
155
        MOVE dmode_memory_to_ncr TO DMODE
156
        MOVE MEMORY 4, dsa_temp_addr_dsa_value, addr_scratch
157
        MOVE dmode_memory_to_memory TO DMODE
158
        CALL scratch_to_dsa
159
        CALL select
160
; Handle the phase mismatch which may have resulted from the
161
; MOVE FROM dsa_msgout if we returned here.  The CLEAR ATN
162
; may or may not be necessary, and we should update script_asm.pl
163
; to handle multiple pieces.
164
    CLEAR ATN
165
    CLEAR ACK
166
 
167
; Replace second operand with address of JUMP instruction dest operand
168
; in schedule table for this DSA.  Becomes dsa_jump_dest in 53c7,8xx.c.
169
ENTRY dsa_code_fix_jump
170
dsa_code_fix_jump:
171
        MOVE MEMORY 4, NOP_insn, 0
172
        JUMP select_done
173
 
174
; wrong_dsa loads the DSA register with the value of the dsa_next
175
; field.
176
;
177
wrong_dsa:
178
;               Patch the MOVE MEMORY INSTRUCTION such that
179
;               the destination address is the address of the OLD
180
;               next pointer.
181
;
182
        MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 8
183
        MOVE dmode_memory_to_ncr TO DMODE
184
;
185
;       Move the _contents_ of the next pointer into the DSA register as
186
;       the next I_T_L or I_T_L_Q tupple to check against the established
187
;       nexus.
188
;
189
        MOVE MEMORY 4, dsa_temp_next, addr_scratch
190
        MOVE dmode_memory_to_memory TO DMODE
191
        CALL scratch_to_dsa
192
        JUMP reselected_check_next
193
 
194
ABSOLUTE dsa_save_data_pointer = 0
195
ENTRY dsa_code_save_data_pointer
196
dsa_code_save_data_pointer:
197
        MOVE dmode_ncr_to_memory TO DMODE
198
        MOVE MEMORY 4, addr_temp, dsa_temp_addr_saved_pointer
199
        MOVE dmode_memory_to_memory TO DMODE
200
; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
201
        MOVE MEMORY 24, dsa_temp_addr_residual, dsa_temp_addr_saved_residual
202
        CLEAR ACK
203
#ifdef DEBUG
204
        INT int_debug_saved
205
#endif
206
        RETURN
207
ABSOLUTE dsa_restore_pointers = 0
208
ENTRY dsa_code_restore_pointers
209
dsa_code_restore_pointers:
210
        MOVE dmode_memory_to_ncr TO DMODE
211
        MOVE MEMORY 4, dsa_temp_addr_saved_pointer, addr_temp
212
        MOVE dmode_memory_to_memory TO DMODE
213
; HARD CODED : 24 bytes needs to agree with 53c7,8xx.h
214
        MOVE MEMORY 24, dsa_temp_addr_saved_residual, dsa_temp_addr_residual
215
        CLEAR ACK
216
#ifdef DEBUG
217
        INT int_debug_restored
218
#endif
219
        RETURN
220
 
221
ABSOLUTE dsa_check_reselect = 0
222
; dsa_check_reselect determines whether or not the current target and
223
; lun match the current DSA
224
ENTRY dsa_code_check_reselect
225
dsa_code_check_reselect:
226
        MOVE SSID TO SFBR               ; SSID contains 3 bit target ID
227
; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
228
        JUMP REL (wrong_dsa), IF NOT dsa_temp_target, AND MASK 0xf8
229
;
230
; Hack - move to scratch first, since SFBR is not writeable
231
;       via the CPU and hence a MOVE MEMORY instruction.
232
;
233
        MOVE dmode_memory_to_ncr TO DMODE
234
        MOVE MEMORY 1, reselected_identify, addr_scratch
235
        MOVE dmode_memory_to_memory TO DMODE
236
        MOVE SCRATCH0 TO SFBR
237
; FIXME : we need to accommodate bit fielded and binary here for '7xx/'8xx chips
238
        JUMP REL (wrong_dsa), IF NOT dsa_temp_lun, AND MASK 0xf8
239
;               Patch the MOVE MEMORY INSTRUCTION such that
240
;               the source address is the address of this dsa's
241
;               next pointer.
242
        MOVE MEMORY 4, dsa_temp_addr_next, reselected_ok + 4
243
        CALL reselected_ok
244
        CALL dsa_temp_sync
245
; Release ACK on the IDENTIFY message _after_ we've set the synchronous
246
; transfer parameters!
247
        CLEAR ACK
248
; Implicitly restore pointers on reselection, so a RETURN
249
; will transfer control back to the right spot.
250
        CALL REL (dsa_code_restore_pointers)
251
        RETURN
252
ENTRY dsa_zero
253
dsa_zero:
254
ENTRY dsa_code_template_end
255
dsa_code_template_end:
256
 
257
; Perform sanity check for dsa_fields_start == dsa_code_template_end -
258
; dsa_zero, puke.
259
 
260
ABSOLUTE dsa_fields_start =  0  ; Sanity marker
261
                                ;       pad 48 bytes (fix this RSN)
262
ABSOLUTE dsa_next = 48          ; len 4 Next DSA
263
                                ; del 4 Previous DSA address
264
ABSOLUTE dsa_cmnd = 56          ; len 4 Scsi_Cmnd * for this thread.
265
ABSOLUTE dsa_select = 60        ; len 4 Device ID, Period, Offset for
266
                                ;       table indirect select
267
ABSOLUTE dsa_msgout = 64        ; len 8 table indirect move parameter for
268
                                ;       select message
269
ABSOLUTE dsa_cmdout = 72        ; len 8 table indirect move parameter for
270
                                ;       command
271
ABSOLUTE dsa_dataout = 80       ; len 4 code pointer for dataout
272
ABSOLUTE dsa_datain = 84        ; len 4 code pointer for datain
273
ABSOLUTE dsa_msgin = 88         ; len 8 table indirect move for msgin
274
ABSOLUTE dsa_status = 96        ; len 8 table indirect move for status byte
275
ABSOLUTE dsa_msgout_other = 104 ; len 8 table indirect for normal message out
276
                                ; (Synchronous transfer negotiation, etc).
277
ABSOLUTE dsa_end = 112
278
 
279
ABSOLUTE schedule = 0           ; Array of JUMP dsa_begin or JUMP (next),
280
                                ; terminated by a call to JUMP wait_reselect
281
 
282
; Linked lists of DSA structures
283
ABSOLUTE reconnect_dsa_head = 0 ; Link list of DSAs which can reconnect
284
ABSOLUTE addr_reconnect_dsa_head = 0 ; Address of variable containing
285
                                ; address of reconnect_dsa_head
286
 
287
; These select the source and destination of a MOVE MEMORY instruction
288
ABSOLUTE dmode_memory_to_memory = 0x0
289
ABSOLUTE dmode_memory_to_ncr = 0x0
290
ABSOLUTE dmode_ncr_to_memory = 0x0
291
 
292
ABSOLUTE addr_scratch = 0x0
293
ABSOLUTE addr_temp = 0x0
294
#endif /* CHIP != 700 && CHIP != 70066 */
295
 
296
; Interrupts -
297
; MSB indicates type
298
; 0     handle error condition
299
; 1     handle message
300
; 2     handle normal condition
301
; 3     debugging interrupt
302
; 4     testing interrupt
303
; Next byte indicates specific error
304
 
305
; XXX not yet implemented, I'm not sure if I want to -
306
; Next byte indicates the routine the error occurred in
307
; The LSB indicates the specific place the error occurred
308
 
309
ABSOLUTE int_err_unexpected_phase = 0x00000000  ; Unexpected phase encountered
310
ABSOLUTE int_err_selected = 0x00010000          ; SELECTED (nee RESELECTED)
311
ABSOLUTE int_err_unexpected_reselect = 0x00020000
312
ABSOLUTE int_err_check_condition = 0x00030000
313
ABSOLUTE int_err_no_phase = 0x00040000
314
ABSOLUTE int_msg_wdtr = 0x01000000              ; WDTR message received
315
ABSOLUTE int_msg_sdtr = 0x01010000              ; SDTR received
316
ABSOLUTE int_msg_1 = 0x01020000                 ; single byte special message
317
                                                ; received
318
 
319
ABSOLUTE int_norm_select_complete = 0x02000000  ; Select complete, reprogram
320
                                                ; registers.
321
ABSOLUTE int_norm_reselect_complete = 0x02010000        ; Nexus established
322
ABSOLUTE int_norm_command_complete = 0x02020000 ; Command complete
323
ABSOLUTE int_norm_disconnected = 0x02030000     ; Disconnected
324
ABSOLUTE int_norm_aborted =0x02040000           ; Aborted *dsa
325
ABSOLUTE int_norm_reset = 0x02050000            ; Generated BUS reset.
326
ABSOLUTE int_debug_break = 0x03000000           ; Break point
327
#ifdef DEBUG
328
ABSOLUTE int_debug_scheduled = 0x03010000       ; new I/O scheduled
329
ABSOLUTE int_debug_idle = 0x03020000            ; scheduler is idle
330
ABSOLUTE int_debug_dsa_loaded = 0x03030000      ; dsa reloaded
331
ABSOLUTE int_debug_reselected = 0x03040000      ; NCR reselected
332
ABSOLUTE int_debug_head = 0x03050000            ; issue head overwritten
333
ABSOLUTE int_debug_disconnected = 0x03060000    ; disconnected
334
ABSOLUTE int_debug_disconnect_msg = 0x03070000  ; got message to disconnect
335
ABSOLUTE int_debug_dsa_schedule = 0x03080000    ; in dsa_schedule
336
ABSOLUTE int_debug_reselect_check = 0x03090000  ; Check for reselection of DSA
337
ABSOLUTE int_debug_reselected_ok = 0x030a0000   ; Reselection accepted
338
#endif
339
ABSOLUTE int_debug_panic = 0x030b0000           ; Panic driver
340
#ifdef DEBUG
341
ABSOLUTE int_debug_saved = 0x030c0000           ; save/restore pointers
342
ABSOLUTE int_debug_restored = 0x030d0000
343
ABSOLUTE int_debug_sync = 0x030e0000            ; Sanity check synchronous
344
                                                ; parameters.
345
ABSOLUTE int_debug_datain = 0x030f0000          ; going into data in phase
346
                                                ; now.
347
ABSOLUTE int_debug_check_dsa = 0x03100000       ; Sanity check DSA against
348
                                                ; SDID.
349
#endif
350
 
351
ABSOLUTE int_test_1 = 0x04000000                ; Test 1 complete
352
ABSOLUTE int_test_2 = 0x04010000                ; Test 2 complete
353
ABSOLUTE int_test_3 = 0x04020000                ; Test 3 complete
354
 
355
 
356
; These should start with 0x05000000, with low bits incrementing for
357
; each one.
358
 
359
#ifdef EVENTS
360
ABSOLUTE int_EVENT_SELECT = 0
361
ABSOLUTE int_EVENT_DISCONNECT = 0
362
ABSOLUTE int_EVENT_RESELECT = 0
363
ABSOLUTE int_EVENT_COMPLETE = 0
364
ABSOLUTE int_EVENT_IDLE = 0
365
ABSOLUTE int_EVENT_SELECT_FAILED = 0
366
ABSOLUTE int_EVENT_BEFORE_SELECT = 0
367
ABSOLUTE int_EVENT_RESELECT_FAILED = 0
368
#endif
369
 
370
ABSOLUTE NCR53c7xx_msg_abort = 0        ; Pointer to abort message
371
ABSOLUTE NCR53c7xx_msg_reject = 0       ; Pointer to reject message
372
ABSOLUTE NCR53c7xx_zero = 0             ; long with zero in it, use for source
373
ABSOLUTE NCR53c7xx_sink = 0             ; long to dump worthless data in
374
ABSOLUTE NOP_insn = 0                   ; NOP instruction
375
 
376
; Pointer to message, potentially multi-byte
377
ABSOLUTE msg_buf = 0
378
 
379
; Pointer to holding area for reselection information
380
ABSOLUTE reselected_identify = 0
381
ABSOLUTE reselected_tag = 0
382
 
383
; Request sense command pointer, it's a 6 byte command, should
384
; be constant for all commands since we always want 16 bytes of
385
; sense and we don't need to change any fields as we did under
386
; SCSI-I when we actually cared about the LUN field.
387
;EXTERNAL NCR53c7xx_sense               ; Request sense command
388
 
389
#if (CHIP != 700) && (CHIP != 70066)
390
; dsa_schedule
391
; PURPOSE : after a DISCONNECT message has been received, and pointers
392
;       saved, insert the current DSA structure at the head of the
393
;       disconnected queue and fall through to the scheduler.
394
;
395
; CALLS : OK
396
;
397
; INPUTS : dsa - current DSA structure, reconnect_dsa_head - list
398
;       of disconnected commands
399
;
400
; MODIFIES : SCRATCH, reconnect_dsa_head
401
;
402
; EXITS : always passes control to schedule
403
 
404
ENTRY dsa_schedule
405
dsa_schedule:
406
#if 0
407
    INT int_debug_dsa_schedule
408
#endif
409
 
410
;
411
; Calculate the address of the next pointer within the DSA
412
; structure of the command that is currently disconnecting
413
;
414
    CALL dsa_to_scratch
415
    MOVE SCRATCH0 + dsa_next TO SCRATCH0
416
    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
417
    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
418
    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
419
 
420
; Point the next field of this DSA structure at the current disconnected
421
; list
422
    MOVE dmode_ncr_to_memory TO DMODE
423
    MOVE MEMORY 4, addr_scratch, dsa_schedule_insert + 8
424
    MOVE dmode_memory_to_memory TO DMODE
425
dsa_schedule_insert:
426
    MOVE MEMORY 4, reconnect_dsa_head, 0
427
 
428
; And update the head pointer.
429
    CALL dsa_to_scratch
430
    MOVE dmode_ncr_to_memory TO DMODE
431
    MOVE MEMORY 4, addr_scratch, reconnect_dsa_head
432
    MOVE dmode_memory_to_memory TO DMODE
433
/* Temporarily, see what happens. */
434
#ifndef ORIGINAL
435
    MOVE SCNTL2 & 0x7f TO SCNTL2
436
    CLEAR ACK
437
#endif
438
    WAIT DISCONNECT
439
#ifdef EVENTS
440
    INT int_EVENT_DISCONNECT;
441
#endif
442
#if 0
443
    INT int_debug_disconnected
444
#endif
445
    JUMP schedule
446
#endif
447
 
448
;
449
; select
450
;
451
; PURPOSE : establish a nexus for the SCSI command referenced by DSA.
452
;       On success, the current DSA structure is removed from the issue
453
;       queue.  Usually, this is entered as a fall-through from schedule,
454
;       although the contingent allegiance handling code will write
455
;       the select entry address to the DSP to restart a command as a
456
;       REQUEST SENSE.  A message is sent (usually IDENTIFY, although
457
;       additional SDTR or WDTR messages may be sent).  COMMAND OUT
458
;       is handled.
459
;
460
; INPUTS : DSA - SCSI command, issue_dsa_head
461
;
462
; CALLS : NOT OK
463
;
464
; MODIFIES : SCRATCH, issue_dsa_head
465
;
466
; EXITS : on reselection or selection, go to select_failed
467
;       otherwise, RETURN so control is passed back to
468
;       dsa_begin.
469
;
470
 
471
ENTRY select
472
select:
473
 
474
#if 0
475
#ifdef EVENTS
476
    INT int_EVENT_BEFORE_SELECT
477
#endif
478
#endif
479
 
480
#if 0
481
#ifdef DEBUG
482
    INT int_debug_scheduled
483
#endif
484
#endif
485
    CLEAR TARGET
486
 
487
; XXX
488
;
489
; In effect, SELECTION operations are backgrounded, with execution
490
; continuing until code which waits for REQ or a fatal interrupt is
491
; encountered.
492
;
493
; So, for more performance, we could overlap the code which removes
494
; the command from the NCRs issue queue with the selection, but
495
; at this point I don't want to deal with the error recovery.
496
;
497
 
498
#if (CHIP != 700) && (CHIP != 70066)
499
    SELECT ATN FROM dsa_select, select_failed
500
    JUMP select_msgout, WHEN MSG_OUT
501
ENTRY select_msgout
502
select_msgout:
503
    MOVE FROM dsa_msgout, WHEN MSG_OUT
504
#else
505
ENTRY select_msgout
506
    SELECT ATN 0, select_failed
507
select_msgout:
508
    MOVE 0, 0, WHEN MSGOUT
509
#endif
510
 
511
#ifdef EVENTS
512
   INT int_EVENT_SELECT
513
#endif
514
   RETURN
515
 
516
;
517
; select_done
518
;
519
; PURPOSE: continue on to normal data transfer; called as the exit
520
;       point from dsa_begin.
521
;
522
; INPUTS: dsa
523
;
524
; CALLS: OK
525
;
526
;
527
 
528
select_done:
529
 
530
#ifdef DEBUG
531
ENTRY select_check_dsa
532
select_check_dsa:
533
    INT int_debug_check_dsa
534
#endif
535
 
536
; After a successful selection, we should get either a CMD phase or
537
; some transfer request negotiation message.
538
 
539
    JUMP cmdout, WHEN CMD
540
    INT int_err_unexpected_phase, WHEN NOT MSG_IN
541
 
542
select_msg_in:
543
    CALL msg_in, WHEN MSG_IN
544
    JUMP select_msg_in, WHEN MSG_IN
545
 
546
cmdout:
547
    INT int_err_unexpected_phase, WHEN NOT CMD
548
#if (CHIP == 700)
549
    INT int_norm_selected
550
#endif
551
ENTRY cmdout_cmdout
552
cmdout_cmdout:
553
#if (CHIP != 700) && (CHIP != 70066)
554
    MOVE FROM dsa_cmdout, WHEN CMD
555
#else
556
    MOVE 0, 0, WHEN CMD
557
#endif /* (CHIP != 700) && (CHIP != 70066) */
558
 
559
;
560
; data_transfer
561
; other_out
562
; other_in
563
; other_transfer
564
;
565
; PURPOSE : handle the main data transfer for a SCSI command in
566
;       several parts.  In the first part, data_transfer, DATA_IN
567
;       and DATA_OUT phases are allowed, with the user provided
568
;       code (usually dynamically generated based on the scatter/gather
569
;       list associated with a SCSI command) called to handle these
570
;       phases.
571
;
572
;       After control has passed to one of the user provided
573
;       DATA_IN or DATA_OUT routines, back calls are made to
574
;       other_transfer_in or other_transfer_out to handle non-DATA IN
575
;       and DATA OUT phases respectively, with the state of the active
576
;       data pointer being preserved in TEMP.
577
;
578
;       On completion, the user code passes control to other_transfer
579
;       which causes DATA_IN and DATA_OUT to result in unexpected_phase
580
;       interrupts so that data overruns may be trapped.
581
;
582
; INPUTS : DSA - SCSI command
583
;
584
; CALLS : OK in data_transfer_start, not ok in other_out and other_in, ok in
585
;       other_transfer
586
;
587
; MODIFIES : SCRATCH
588
;
589
; EXITS : if STATUS IN is detected, signifying command completion,
590
;       the NCR jumps to command_complete.  If MSG IN occurs, a
591
;       CALL is made to msg_in.  Otherwise, other_transfer runs in
592
;       an infinite loop.
593
;
594
 
595
ENTRY data_transfer
596
data_transfer:
597
    JUMP cmdout_cmdout, WHEN CMD
598
    CALL msg_in, WHEN MSG_IN
599
    INT int_err_unexpected_phase, WHEN MSG_OUT
600
    JUMP do_dataout, WHEN DATA_OUT
601
    JUMP do_datain, WHEN DATA_IN
602
    JUMP command_complete, WHEN STATUS
603
    JUMP data_transfer
604
ENTRY end_data_transfer
605
end_data_transfer:
606
 
607
;
608
; FIXME: On NCR53c700 and NCR53c700-66 chips, do_dataout/do_datain
609
; should be fixed up whenever the nexus changes so it can point to the
610
; correct routine for that command.
611
;
612
 
613
#if (CHIP != 700) && (CHIP != 70066)
614
; Nasty jump to dsa->dataout
615
do_dataout:
616
    CALL dsa_to_scratch
617
    MOVE SCRATCH0 + dsa_dataout TO SCRATCH0
618
    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
619
    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
620
    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
621
    MOVE dmode_ncr_to_memory TO DMODE
622
    MOVE MEMORY 4, addr_scratch, dataout_to_jump + 4
623
    MOVE dmode_memory_to_memory TO DMODE
624
dataout_to_jump:
625
    MOVE MEMORY 4, 0, dataout_jump + 4
626
dataout_jump:
627
    JUMP 0
628
 
629
; Nasty jump to dsa->dsain
630
do_datain:
631
    CALL dsa_to_scratch
632
    MOVE SCRATCH0 + dsa_datain TO SCRATCH0
633
    MOVE SCRATCH1 + 0 TO SCRATCH1 WITH CARRY
634
    MOVE SCRATCH2 + 0 TO SCRATCH2 WITH CARRY
635
    MOVE SCRATCH3 + 0 TO SCRATCH3 WITH CARRY
636
    MOVE dmode_ncr_to_memory TO DMODE
637
    MOVE MEMORY 4, addr_scratch, datain_to_jump + 4
638
    MOVE dmode_memory_to_memory TO DMODE
639
ENTRY datain_to_jump
640
datain_to_jump:
641
    MOVE MEMORY 4, 0, datain_jump + 4
642
#if 0
643
    INT int_debug_datain
644
#endif
645
datain_jump:
646
    JUMP 0
647
#endif /* (CHIP != 700) && (CHIP != 70066) */
648
 
649
 
650
; Note that other_out and other_in loop until a non-data phase
651
; is discovered, so we only execute return statements when we
652
; can go on to the next data phase block move statement.
653
 
654
ENTRY other_out
655
other_out:
656
#if 0
657
    INT 0x03ffdead
658
#endif
659
    INT int_err_unexpected_phase, WHEN CMD
660
    JUMP msg_in_restart, WHEN MSG_IN
661
    INT int_err_unexpected_phase, WHEN MSG_OUT
662
    INT int_err_unexpected_phase, WHEN DATA_IN
663
    JUMP command_complete, WHEN STATUS
664
    JUMP other_out, WHEN NOT DATA_OUT
665
    RETURN
666
 
667
ENTRY other_in
668
other_in:
669
#if 0
670
    INT 0x03ffdead
671
#endif
672
    INT int_err_unexpected_phase, WHEN CMD
673
    JUMP msg_in_restart, WHEN MSG_IN
674
    INT int_err_unexpected_phase, WHEN MSG_OUT
675
    INT int_err_unexpected_phase, WHEN DATA_OUT
676
    JUMP command_complete, WHEN STATUS
677
    JUMP other_in, WHEN NOT DATA_IN
678
    RETURN
679
 
680
 
681
ENTRY other_transfer
682
other_transfer:
683
    INT int_err_unexpected_phase, WHEN CMD
684
    CALL msg_in, WHEN MSG_IN
685
    INT int_err_unexpected_phase, WHEN MSG_OUT
686
    INT int_err_unexpected_phase, WHEN DATA_OUT
687
    INT int_err_unexpected_phase, WHEN DATA_IN
688
    JUMP command_complete, WHEN STATUS
689
    JUMP other_transfer
690
 
691
;
692
; msg_in_restart
693
; msg_in
694
; munge_msg
695
;
696
; PURPOSE : process messages from a target.  msg_in is called when the
697
;       caller hasn't read the first byte of the message.  munge_message
698
;       is called when the caller has read the first byte of the message,
699
;       and left it in SFBR.  msg_in_restart is called when the caller
700
;       hasn't read the first byte of the message, and wishes RETURN
701
;       to transfer control back to the address of the conditional
702
;       CALL instruction rather than to the instruction after it.
703
;
704
;       Various int_* interrupts are generated when the host system
705
;       needs to intervene, as is the case with SDTR, WDTR, and
706
;       INITIATE RECOVERY messages.
707
;
708
;       When the host system handles one of these interrupts,
709
;       it can respond by reentering at reject_message,
710
;       which rejects the message and returns control to
711
;       the caller of msg_in or munge_msg, accept_message
712
;       which clears ACK and returns control, or reply_message
713
;       which sends the message pointed to by the DSA
714
;       msgout_other table indirect field.
715
;
716
;       DISCONNECT messages are handled by moving the command
717
;       to the reconnect_dsa_queue.
718
;
719
; INPUTS : DSA - SCSI COMMAND, SFBR - first byte of message (munge_msg
720
;       only)
721
;
722
; CALLS : NO.  The TEMP register isn't backed up to allow nested calls.
723
;
724
; MODIFIES : SCRATCH, DSA on DISCONNECT
725
;
726
; EXITS : On receipt of SAVE DATA POINTER, RESTORE POINTERS,
727
;       and normal return from message handlers running under
728
;       Linux, control is returned to the caller.  Receipt
729
;       of DISCONNECT messages pass control to dsa_schedule.
730
;
731
ENTRY msg_in_restart
732
msg_in_restart:
733
; XXX - hackish
734
;
735
; Since it's easier to debug changes to the statically
736
; compiled code, rather than the dynamically generated
737
; stuff, such as
738
;
739
;       MOVE x, y, WHEN data_phase
740
;       CALL other_z, WHEN NOT data_phase
741
;       MOVE x, y, WHEN data_phase
742
;
743
; I'd like to have certain routines (notably the message handler)
744
; restart on the conditional call rather than the next instruction.
745
;
746
; So, subtract 8 from the return address
747
 
748
    MOVE TEMP0 + 0xf8 TO TEMP0
749
    MOVE TEMP1 + 0xff TO TEMP1 WITH CARRY
750
    MOVE TEMP2 + 0xff TO TEMP2 WITH CARRY
751
    MOVE TEMP3 + 0xff TO TEMP3 WITH CARRY
752
 
753
ENTRY msg_in
754
msg_in:
755
    MOVE 1, msg_buf, WHEN MSG_IN
756
 
757
munge_msg:
758
    JUMP munge_extended, IF 0x01                ; EXTENDED MESSAGE
759
    JUMP munge_2, IF 0x20, AND MASK 0xdf        ; two byte message
760
;
761
; XXX - I've seen a handful of broken SCSI devices which fail to issue
762
;       a SAVE POINTERS message before disconnecting in the middle of
763
;       a transfer, assuming that the DATA POINTER will be implicitly
764
;       restored.
765
;
766
; Historically, I've often done an implicit save when the DISCONNECT
767
; message is processed.  We may want to consider having the option of
768
; doing that here.
769
;
770
    JUMP munge_save_data_pointer, IF 0x02       ; SAVE DATA POINTER
771
    JUMP munge_restore_pointers, IF 0x03        ; RESTORE POINTERS
772
    JUMP munge_disconnect, IF 0x04              ; DISCONNECT
773
    INT int_msg_1, IF 0x07                      ; MESSAGE REJECT
774
    INT int_msg_1, IF 0x0f                      ; INITIATE RECOVERY
775
#ifdef EVENTS
776
    INT int_EVENT_SELECT_FAILED
777
#endif
778
    JUMP reject_message
779
 
780
munge_2:
781
    JUMP reject_message
782
;
783
; The SCSI standard allows targets to recover from transient
784
; error conditions by backing up the data pointer with a
785
; RESTORE POINTERS message.
786
;
787
; So, we must save and restore the _residual_ code as well as
788
; the current instruction pointer.  Because of this messiness,
789
; it is simpler to put dynamic code in the dsa for this and to
790
; just do a simple jump down there.
791
;
792
 
793
munge_save_data_pointer:
794
    MOVE DSA0 + dsa_save_data_pointer TO SFBR
795
    MOVE SFBR TO SCRATCH0
796
    MOVE DSA1 + 0xff TO SFBR WITH CARRY
797
    MOVE SFBR TO SCRATCH1
798
    MOVE DSA2 + 0xff TO SFBR WITH CARRY
799
    MOVE SFBR TO SCRATCH2
800
    MOVE DSA3 + 0xff TO SFBR WITH CARRY
801
    MOVE SFBR TO SCRATCH3
802
 
803
    MOVE dmode_ncr_to_memory TO DMODE
804
    MOVE MEMORY 4, addr_scratch, jump_dsa_save + 4
805
    MOVE dmode_memory_to_memory TO DMODE
806
jump_dsa_save:
807
    JUMP 0
808
 
809
munge_restore_pointers:
810
    MOVE DSA0 + dsa_restore_pointers TO SFBR
811
    MOVE SFBR TO SCRATCH0
812
    MOVE DSA1 + 0xff TO SFBR WITH CARRY
813
    MOVE SFBR TO SCRATCH1
814
    MOVE DSA2 + 0xff TO SFBR WITH CARRY
815
    MOVE SFBR TO SCRATCH2
816
    MOVE DSA3 + 0xff TO SFBR WITH CARRY
817
    MOVE SFBR TO SCRATCH3
818
 
819
    MOVE dmode_ncr_to_memory TO DMODE
820
    MOVE MEMORY 4, addr_scratch, jump_dsa_restore + 4
821
    MOVE dmode_memory_to_memory TO DMODE
822
jump_dsa_restore:
823
    JUMP 0
824
 
825
 
826
munge_disconnect:
827
#if 0
828
    INT int_debug_disconnect_msg
829
#endif
830
 
831
/*
832
 * Before, we overlapped processing with waiting for disconnect, but
833
 * debugging was beginning to appear messy.  Temporarily move things
834
 * to just before the WAIT DISCONNECT.
835
 */
836
 
837
#ifdef ORIGINAL
838
    MOVE SCNTL2 & 0x7f TO SCNTL2
839
    CLEAR ACK
840
#endif
841
 
842
#if (CHIP != 700) && (CHIP != 70066)
843
    JUMP dsa_schedule
844
#else
845
    WAIT DISCONNECT
846
    INT int_norm_disconnected
847
#endif
848
 
849
munge_extended:
850
    CLEAR ACK
851
    INT int_err_unexpected_phase, WHEN NOT MSG_IN
852
    MOVE 1, msg_buf + 1, WHEN MSG_IN
853
    JUMP munge_extended_2, IF 0x02
854
    JUMP munge_extended_3, IF 0x03
855
    JUMP reject_message
856
 
857
munge_extended_2:
858
    CLEAR ACK
859
    MOVE 1, msg_buf + 2, WHEN MSG_IN
860
    JUMP reject_message, IF NOT 0x02    ; Must be WDTR
861
    CLEAR ACK
862
    MOVE 1, msg_buf + 3, WHEN MSG_IN
863
    INT int_msg_wdtr
864
 
865
munge_extended_3:
866
    CLEAR ACK
867
    MOVE 1, msg_buf + 2, WHEN MSG_IN
868
    JUMP reject_message, IF NOT 0x01    ; Must be SDTR
869
    CLEAR ACK
870
    MOVE 2, msg_buf + 3, WHEN MSG_IN
871
    INT int_msg_sdtr
872
 
873
ENTRY reject_message
874
reject_message:
875
    SET ATN
876
    CLEAR ACK
877
    MOVE 1, NCR53c7xx_msg_reject, WHEN MSG_OUT
878
    RETURN
879
 
880
ENTRY accept_message
881
accept_message:
882
    CLEAR ATN
883
    CLEAR ACK
884
    RETURN
885
 
886
ENTRY respond_message
887
respond_message:
888
    SET ATN
889
    CLEAR ACK
890
    MOVE FROM dsa_msgout_other, WHEN MSG_OUT
891
    RETURN
892
 
893
;
894
; command_complete
895
;
896
; PURPOSE : handle command termination when STATUS IN is detected by reading
897
;       a status byte followed by a command termination message.
898
;
899
;       Normal termination results in an INTFLY instruction, and
900
;       the host system can pick out which command terminated by
901
;       examining the MESSAGE and STATUS buffers of all currently
902
;       executing commands;
903
;
904
;       Abnormal (CHECK_CONDITION) termination results in an
905
;       int_err_check_condition interrupt so that a REQUEST SENSE
906
;       command can be issued out-of-order so that no other command
907
;       clears the contingent allegiance condition.
908
;
909
;
910
; INPUTS : DSA - command
911
;
912
; CALLS : OK
913
;
914
; EXITS : On successful termination, control is passed to schedule.
915
;       On abnormal termination, the user will usually modify the
916
;       DSA fields and corresponding buffers and return control
917
;       to select.
918
;
919
 
920
ENTRY command_complete
921
command_complete:
922
    MOVE FROM dsa_status, WHEN STATUS
923
#if (CHIP != 700) && (CHIP != 70066)
924
    MOVE SFBR TO SCRATCH0               ; Save status
925
#endif /* (CHIP != 700) && (CHIP != 70066) */
926
ENTRY command_complete_msgin
927
command_complete_msgin:
928
    MOVE FROM dsa_msgin, WHEN MSG_IN
929
; Indicate that we should be expecting a disconnect
930
    MOVE SCNTL2 & 0x7f TO SCNTL2
931
    CLEAR ACK
932
#if (CHIP != 700) && (CHIP != 70066)
933
    WAIT DISCONNECT
934
 
935
;
936
; The SCSI specification states that when a UNIT ATTENTION condition
937
; is pending, as indicated by a CHECK CONDITION status message,
938
; the target shall revert to asynchronous transfers.  Since
939
; synchronous transfers parameters are maintained on a per INITIATOR/TARGET
940
; basis, and returning control to our scheduler could work on a command
941
; running on another lun on that target using the old parameters, we must
942
; interrupt the host processor to get them changed, or change them ourselves.
943
;
944
; Once SCSI-II tagged queueing is implemented, things will be even more
945
; hairy, since contingent allegiance conditions exist on a per-target/lun
946
; basis, and issuing a new command with a different tag would clear it.
947
; In these cases, we must interrupt the host processor to get a request
948
; added to the HEAD of the queue with the request sense command, or we
949
; must automatically issue the request sense command.
950
 
951
#if 0
952
    MOVE SCRATCH0 TO SFBR
953
    JUMP command_failed, IF 0x02
954
#endif
955
    INTFLY
956
#endif /* (CHIP != 700) && (CHIP != 70066) */
957
#ifdef EVENTS
958
    INT int_EVENT_COMPLETE
959
#endif
960
#if (CHIP != 700) && (CHIP != 70066)
961
    JUMP schedule
962
command_failed:
963
    INT int_err_check_condition
964
#else
965
    INT int_norm_command_complete
966
#endif
967
 
968
;
969
; wait_reselect
970
;
971
; PURPOSE : This is essentially the idle routine, where control lands
972
;       when there are no new processes to schedule.  wait_reselect
973
;       waits for reselection, selection, and new commands.
974
;
975
;       When a successful reselection occurs, with the aid
976
;       of fixed up code in each DSA, wait_reselect walks the
977
;       reconnect_dsa_queue, asking each dsa if the target ID
978
;       and LUN match its.
979
;
980
;       If a match is found, a call is made back to reselected_ok,
981
;       which through the miracles of self modifying code, extracts
982
;       the found DSA from the reconnect_dsa_queue and then
983
;       returns control to the DSAs thread of execution.
984
;
985
; INPUTS : NONE
986
;
987
; CALLS : OK
988
;
989
; MODIFIES : DSA,
990
;
991
; EXITS : On successful reselection, control is returned to the
992
;       DSA which called reselected_ok.  If the WAIT RESELECT
993
;       was interrupted by a new commands arrival signaled by
994
;       SIG_P, control is passed to schedule.  If the NCR is
995
;       selected, the host system is interrupted with an
996
;       int_err_selected which is usually responded to by
997
;       setting DSP to the target_abort address.
998
 
999
ENTRY wait_reselect
1000
wait_reselect:
1001
#ifdef EVENTS
1002
    int int_EVENT_IDLE
1003
#endif
1004
#if 0
1005
    int int_debug_idle
1006
#endif
1007
    WAIT RESELECT wait_reselect_failed
1008
 
1009
reselected:
1010
#ifdef EVENTS
1011
    int int_EVENT_RESELECT
1012
#endif
1013
    CLEAR TARGET
1014
    MOVE dmode_memory_to_memory TO DMODE
1015
    ; Read all data needed to reestablish the nexus -
1016
    MOVE 1, reselected_identify, WHEN MSG_IN
1017
    ; We used to CLEAR ACK here.
1018
#if (CHIP != 700) && (CHIP != 70066)
1019
#if 0
1020
    int int_debug_reselected
1021
#endif
1022
 
1023
    ; Point DSA at the current head of the disconnected queue.
1024
    MOVE dmode_memory_to_ncr  TO DMODE
1025
    MOVE MEMORY 4, reconnect_dsa_head, addr_scratch
1026
    MOVE dmode_memory_to_memory TO DMODE
1027
    CALL scratch_to_dsa
1028
 
1029
    ; Fix the update-next pointer so that the reconnect_dsa_head
1030
    ; pointer is the one that will be updated if this DSA is a hit
1031
    ; and we remove it from the queue.
1032
 
1033
    MOVE MEMORY 4, addr_reconnect_dsa_head, reselected_ok + 8
1034
 
1035
ENTRY reselected_check_next
1036
reselected_check_next:
1037
#if 0
1038
    INT int_debug_reselect_check
1039
#endif
1040
    ; Check for a NULL pointer.
1041
    MOVE DSA0 TO SFBR
1042
    JUMP reselected_not_end, IF NOT 0
1043
    MOVE DSA1 TO SFBR
1044
    JUMP reselected_not_end, IF NOT 0
1045
    MOVE DSA2 TO SFBR
1046
    JUMP reselected_not_end, IF NOT 0
1047
    MOVE DSA3 TO SFBR
1048
    JUMP reselected_not_end, IF NOT 0
1049
    INT int_err_unexpected_reselect
1050
 
1051
reselected_not_end:
1052
    ;
1053
    ; XXX the ALU is only eight bits wide, and the assembler
1054
    ; wont do the dirt work for us.  As long as dsa_check_reselect
1055
    ; is negative, we need to sign extend with 1 bits to the full
1056
    ; 32 bit width of the address.
1057
    ;
1058
    ; A potential work around would be to have a known alignment
1059
    ; of the DSA structure such that the base address plus
1060
    ; dsa_check_reselect doesn't require carrying from bytes
1061
    ; higher than the LSB.
1062
    ;
1063
 
1064
    MOVE DSA0 TO SFBR
1065
    MOVE SFBR + dsa_check_reselect TO SCRATCH0
1066
    MOVE DSA1 TO SFBR
1067
    MOVE SFBR + 0xff TO SCRATCH1 WITH CARRY
1068
    MOVE DSA2 TO SFBR
1069
    MOVE SFBR + 0xff TO SCRATCH2 WITH CARRY
1070
    MOVE DSA3 TO SFBR
1071
    MOVE SFBR + 0xff TO SCRATCH3 WITH CARRY
1072
 
1073
    MOVE dmode_ncr_to_memory TO DMODE
1074
    MOVE MEMORY 4, addr_scratch, reselected_check + 4
1075
    MOVE dmode_memory_to_memory TO DMODE
1076
reselected_check:
1077
    JUMP 0
1078
 
1079
 
1080
;
1081
;
1082
ENTRY reselected_ok
1083
reselected_ok:
1084
    MOVE MEMORY 4, 0, 0                         ; Patched : first word
1085
                                                ;       is address of
1086
                                                ;       successful dsa_next
1087
                                                ; Second word is last
1088
                                                ;       unsuccessful dsa_next,
1089
                                                ;       starting with
1090
                                                ;       dsa_reconnect_head
1091
    ; We used to CLEAR ACK here.
1092
#if 0
1093
    INT int_debug_reselected_ok
1094
#endif
1095
#ifdef DEBUG
1096
    INT int_debug_check_dsa
1097
#endif
1098
    RETURN                                      ; Return control to where
1099
#else
1100
    INT int_norm_reselected
1101
#endif /* (CHIP != 700) && (CHIP != 70066) */
1102
 
1103
selected:
1104
    INT int_err_selected;
1105
 
1106
;
1107
; A select or reselect failure can be caused by one of two conditions :
1108
; 1.  SIG_P was set.  This will be the case if the user has written
1109
;       a new value to a previously NULL head of the issue queue.
1110
;
1111
; 2.  The NCR53c810 was selected or reselected by another device.
1112
;
1113
; 3.  The bus was already busy since we were selected or reselected
1114
;       before starting the command.
1115
 
1116
wait_reselect_failed:
1117
#ifdef EVENTS
1118
        INT int_EVENT_RESELECT_FAILED
1119
#endif
1120
; Check selected bit.
1121
    MOVE SIST0 & 0x20 TO SFBR
1122
    JUMP selected, IF 0x20
1123
; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
1124
    MOVE CTEST2 & 0x40 TO SFBR
1125
    JUMP schedule, IF 0x40
1126
; Check connected bit.
1127
; FIXME: this needs to change if we support target mode
1128
    MOVE ISTAT & 0x08 TO SFBR
1129
    JUMP reselected, IF 0x08
1130
; FIXME : Something bogus happened, and we shouldn't fail silently.
1131
#if 0
1132
    JUMP schedule
1133
#else
1134
    INT int_debug_panic
1135
#endif
1136
 
1137
 
1138
select_failed:
1139
#ifdef EVENTS
1140
  int int_EVENT_SELECT_FAILED
1141
#endif
1142
; Otherwise, mask the selected and reselected bits off SIST0
1143
    MOVE SIST0 & 0x30 TO SFBR
1144
    JUMP selected, IF 0x20
1145
    JUMP reselected, IF 0x10
1146
; If SIGP is set, the user just gave us another command, and
1147
; we should restart or return to the scheduler.
1148
; Reading CTEST2 clears the SIG_P bit in the ISTAT register.
1149
    MOVE CTEST2 & 0x40 TO SFBR
1150
    JUMP select, IF 0x40
1151
; Check connected bit.
1152
; FIXME: this needs to change if we support target mode
1153
; FIXME: is this really necessary?
1154
    MOVE ISTAT & 0x08 TO SFBR
1155
    JUMP reselected, IF 0x08
1156
; FIXME : Something bogus happened, and we shouldn't fail silently.
1157
#if 0
1158
    JUMP schedule
1159
#else
1160
    INT int_debug_panic
1161
#endif
1162
 
1163
;
1164
; test_1
1165
; test_2
1166
;
1167
; PURPOSE : run some verification tests on the NCR.  test_1
1168
;       copies test_src to test_dest and interrupts the host
1169
;       processor, testing for cache coherency and interrupt
1170
;       problems in the processes.
1171
;
1172
;       test_2 runs a command with offsets relative to the
1173
;       DSA on entry, and is useful for miscellaneous experimentation.
1174
;
1175
 
1176
; Verify that interrupts are working correctly and that we don't
1177
; have a cache invalidation problem.
1178
 
1179
ABSOLUTE test_src = 0, test_dest = 0
1180
ENTRY test_1
1181
test_1:
1182
    MOVE MEMORY 4, test_src, test_dest
1183
    INT int_test_1
1184
 
1185
;
1186
; Run arbitrary commands, with test code establishing a DSA
1187
;
1188
 
1189
ENTRY test_2
1190
test_2:
1191
    CLEAR TARGET
1192
    SELECT ATN FROM 0, test_2_fail
1193
    JUMP test_2_msgout, WHEN MSG_OUT
1194
ENTRY test_2_msgout
1195
test_2_msgout:
1196
    MOVE FROM 8, WHEN MSG_OUT
1197
    MOVE FROM 16, WHEN CMD
1198
    MOVE FROM 24, WHEN DATA_IN
1199
    MOVE FROM 32, WHEN STATUS
1200
    MOVE FROM 40, WHEN MSG_IN
1201
    MOVE SCNTL2 & 0x7f TO SCNTL2
1202
    CLEAR ACK
1203
    WAIT DISCONNECT
1204
test_2_fail:
1205
    INT int_test_2
1206
 
1207
ENTRY debug_break
1208
debug_break:
1209
    INT int_debug_break
1210
 
1211
;
1212
; initiator_abort
1213
; target_abort
1214
;
1215
; PURPOSE : Abort the currently established nexus from with initiator
1216
;       or target mode.
1217
;
1218
;
1219
 
1220
ENTRY target_abort
1221
target_abort:
1222
    SET TARGET
1223
    DISCONNECT
1224
    CLEAR TARGET
1225
    JUMP schedule
1226
 
1227
ENTRY initiator_abort
1228
initiator_abort:
1229
    SET ATN
1230
;
1231
; The SCSI-I specification says that targets may go into MSG out at
1232
; their leisure upon receipt of the ATN single.  On all versions of the
1233
; specification, we can't change phases until REQ transitions true->false,
1234
; so we need to sink/source one byte of data to allow the transition.
1235
;
1236
; For the sake of safety, we'll only source one byte of data in all
1237
; cases, but to accommodate the SCSI-I dain bramage, we'll sink an
1238
; arbitrary number of bytes.
1239
    JUMP spew_cmd, WHEN CMD
1240
    JUMP eat_msgin, WHEN MSG_IN
1241
    JUMP eat_datain, WHEN DATA_IN
1242
    JUMP eat_status, WHEN STATUS
1243
    JUMP spew_dataout, WHEN DATA_OUT
1244
    JUMP sated
1245
spew_cmd:
1246
    MOVE 1, NCR53c7xx_zero, WHEN CMD
1247
    JUMP sated
1248
eat_msgin:
1249
    MOVE 1, NCR53c7xx_sink, WHEN MSG_IN
1250
    JUMP eat_msgin, WHEN MSG_IN
1251
    JUMP sated
1252
eat_status:
1253
    MOVE 1, NCR53c7xx_sink, WHEN STATUS
1254
    JUMP eat_status, WHEN STATUS
1255
    JUMP sated
1256
eat_datain:
1257
    MOVE 1, NCR53c7xx_sink, WHEN DATA_IN
1258
    JUMP eat_datain, WHEN DATA_IN
1259
    JUMP sated
1260
spew_dataout:
1261
    MOVE 1, NCR53c7xx_zero, WHEN DATA_OUT
1262
sated:
1263
    MOVE SCNTL2 & 0x7f TO SCNTL2
1264
    MOVE 1, NCR53c7xx_msg_abort, WHEN MSG_OUT
1265
    WAIT DISCONNECT
1266
    INT int_norm_aborted
1267
 
1268
;
1269
; dsa_to_scratch
1270
; scratch_to_dsa
1271
;
1272
; PURPOSE :
1273
;       The NCR chips cannot do a move memory instruction with the DSA register
1274
;       as the source or destination.  So, we provide a couple of subroutines
1275
;       that let us switch between the DSA register and scratch register.
1276
;
1277
;       Memory moves to/from the DSPS  register also don't work, but we
1278
;       don't use them.
1279
;
1280
;
1281
 
1282
 
1283
dsa_to_scratch:
1284
    MOVE DSA0 TO SFBR
1285
    MOVE SFBR TO SCRATCH0
1286
    MOVE DSA1 TO SFBR
1287
    MOVE SFBR TO SCRATCH1
1288
    MOVE DSA2 TO SFBR
1289
    MOVE SFBR TO SCRATCH2
1290
    MOVE DSA3 TO SFBR
1291
    MOVE SFBR TO SCRATCH3
1292
    RETURN
1293
 
1294
scratch_to_dsa:
1295
    MOVE SCRATCH0 TO SFBR
1296
    MOVE SFBR TO DSA0
1297
    MOVE SCRATCH1 TO SFBR
1298
    MOVE SFBR TO DSA1
1299
    MOVE SCRATCH2 TO SFBR
1300
    MOVE SFBR TO DSA2
1301
    MOVE SCRATCH3 TO SFBR
1302
    MOVE SFBR TO DSA3
1303
    RETURN
1304
 

powered by: WebSVN 2.1.0

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