summaryrefslogtreecommitdiff
path: root/v1.25/source/IO.ASM
diff options
context:
space:
mode:
Diffstat (limited to 'v1.25/source/IO.ASM')
-rw-r--r--v1.25/source/IO.ASM1934
1 files changed, 1934 insertions, 0 deletions
diff --git a/v1.25/source/IO.ASM b/v1.25/source/IO.ASM
new file mode 100644
index 0000000..3b9f181
--- /dev/null
+++ b/v1.25/source/IO.ASM
@@ -0,0 +1,1934 @@
1; I/O System for 86-DOS version 1.20 and later. Revised 8-02-82.
2;
3; Assumes a CPU Support card at F0 hex for character I/O,
4; with disk drivers for SCP, Tarbell, or Cromemco controllers.
5;
6; Select whether console input is interrupt-driven or polled.
7INTINP: EQU 1
8;
9; Select whether the auxiliary port is the Support Card parallel port
10; or on channel 1 of a Multiport Serial card addressed at 10H.
11PARALLELAUX: EQU 1
12SERIALAUX: EQU 0
13;
14; Select whether the printer is connected to the Support card parallel
15; output port (standard) or channel 0 of a Multiport Serial card
16; addressed at 10H.
17PARALLELPRN: EQU 1
18SERIALPRN: EQU 0
19;
20; If the Multiport Serial was chosen for either the auxiliary or the
21; printer, select the baud rate here. Refer to Multiport Serial manual
22; page 11 to pick the correct value for a given baud rate.
23PRNBAUD:EQU 7 ; 1200 baud
24AUXBAUD:EQU 0FH ; 19200 baud
25;
26; Select disk controller here.
27SCP: EQU 1
28TARBELLSD: EQU 0
29TARBELLDD: EQU 0
30CROMEMCO4FDC: EQU 0
31CROMEMCO16FDC: EQU 0
32;
33; Select if you want a special conversion version which can read/write
34; both the new Microsoft format and the old SCP format.
35; For a two drive system, drives A and B are the new Microsoft format,
36; and drives C and D are the old SCP format (where C is the same physical
37; drive as A, and D is the same drive as B). CONVERT has no effect
38; on 5.25-inch drives.
39CONVERT:EQU 1
40;
41; Select disk configuration:
42LARGE: EQU 1 ; Large drives.
43COMBIN: EQU 0 ; Two 8-inch and one 5.25-inch.
44SMALL: EQU 0 ; Three 5.25-inch drives.
45CUSTOM: EQU 0 ; User defined.
46;
47; If 8-inch drives are PerSci, select FASTSEEK here:
48; (Fastseek with Tarbell controllers doesn't work yet).
49FASTSEEK: EQU 1
50;
51; For double-density controllers, select double-sided operation of
52; 8-inch disks in double-density mode.
53LARGEDS: EQU 0
54;
55; For double-density controllers, select double-sided operation of
56; 5.25-inch disks in double-density mode.
57SMALLDS: EQU 0
58;
59; Use table below to select head step speed. Step times for 5" drives
60; are double that shown in the table. Times for Fast Seek mode (using
61; PerSci drives) is very small - 200-400 microseconds.
62;
63; Step value 1771 1793
64;
65; 0 6ms 3ms
66; 1 6ms 6ms
67; 2 10ms 10ms
68; 3 20ms 15ms
69;
70STPSPD: EQU 0
71;
72; ****** End of selections ********************************************
73;
74BIOSSEG:EQU 40H ; I/O system segment.
75BIOSLEN:EQU 2048 ; Maximum length of I/O system.
76DOSLEN: EQU 8192 ; Maximum length of MS-DOS.
77QSIZE: EQU 80 ; Input queue size.
78PBUFSIZ:EQU 128 ; Size of print buffer
79BASE: EQU 0F0H ; CPU Support card base port number.
80SIOBASE:EQU 10H ; Base port number of Multiport Serial card.
81STAT: EQU BASE+7 ; Serial I/O status port.
82DATA: EQU BASE+6 ; Serial I/O data port.
83DAV: EQU 2 ; Data available bit.
84TBMT: EQU 1 ; Transmitter buffer empty bit.
85SERIAL: EQU SERIALPRN+SERIALAUX
86STCDATA:EQU BASE+4 ; Ports for 9513 Timer chip.
87STCCOM: EQU BASE+5
88
89 IF SERIALAUX
90AUXSTAT:EQU SIOBASE+3
91AUXDATA:EQU SIOBASE+2
92 ENDIF
93
94 IF PARALLELAUX
95AUXSTAT:EQU BASE+13
96AUXDATA:EQU BASE+12
97 ENDIF
98
99 IF SERIALPRN
100PRNSTAT:EQU SIOBASE+1
101PRNDATA:EQU SIOBASE+0
102 ENDIF
103
104 IF PARALLELPRN
105PRNSTAT:EQU BASE+13
106PRNDATA:EQU BASE+12
107 ENDIF
108
109 ORG 0
110 PUT 100H
111
112 JMP INIT
113 JMP STATUS
114 JMP INP
115 JMP OUTP
116 JMP PRINT
117 JMP AUXIN
118 JMP AUXOUT
119 JMP READ
120 JMP WRITE
121 JMP DSKCHG
122 JMP SETDATE
123 JMP SETTIME
124 JMP GETTIME
125 JMP FLUSH
126 JMP MAPDEV
127MAPDEV:
128 RET L
129
130INIT:
131 XOR BP,BP ; Set up stack just below I/O system.
132 MOV SS,BP
133 MOV SP,BIOSSEG*16
134
135 IF INTINP-1
136 MOV AL,0FFH ; Mask all interrupts.
137 OUTB BASE+3
138 ENDIF
139
140 IF INTINP
141 DI ; Set up keyboard interrupt vector.
142 MOV [BP+64H],KBINT
143 MOV [BP+66H],CS
144 EI
145 ENDIF
146
147 MOV [BP+4*38H],PRNFCB
148 MOV [BP+4*38H+2],CS
149 PUSH CS
150 POP DS
151;
152; Initialize time-of-day clock.
153;
154 MOV SI,STCTAB
155 MOV CX,4 ;Initialize 4 registers
156 UP
157INITSTC:
158 LODB
159 OUT STCCOM ;Select register to initialize
160 LODB
161 OUT STCDATA
162 LODB
163 OUT STCDATA
164 LOOP INITSTC
165
166 IF SERIAL
167 MOV CX,4
168SERINIT:
169 LODB
170 OUT SIOBASE+1
171 OUT SIOBASE+3
172 LOOP SERINIT
173 LODB ;Baud rate for channel 0
174 OUT SIOBASE+8
175 LODB ;Baud rate for channel 1
176 OUT SIOBASE+9
177 ENDIF
178;
179; Move MS-DOS down to the first segment just above the I/O system.
180;
181 MOV SI,BIOSLEN ; Source points to where MS-DOS currently is.
182 MOV AX,DOSSEG ; Destination is beginning of DOSSEG.
183 MOV ES,AX
184 SUB DI,DI
185 MOV CX,DOSLEN/2 ; CX is number of words to move.
186 REP
187 MOVSW
188
189 MOV SI,INITTAB
190 MOV DX,1 ; Do auto memory scan.
191 CALL 0,DOSSEG
192;
193; Change disk read and write vectors (INT 37 and INT 38) to go to
194; DIRECTREAD and DIRECTWRITE rather than READ and WRITE.
195;
196 SUB BP,BP
197 MOV W,[BP+37*4],DIRECTREAD
198 MOV W,[BP+38*4],DIRECTWRITE
199
200 MOV DX,100H
201 MOV AH,26 ;Set DMA address
202 INT 33
203 MOV CX,[6] ;Get size of segment
204 MOV BX,DS ;Save segment for later
205;
206; DS must be set to CS so we can point to the FCB.
207;
208 MOV AX,CS
209 MOV DS,AX
210 MOV DX,FCB ;File Control Block for COMMAND.COM
211 MOV AH,15
212 INT 33 ;Open COMMAND.COM
213 OR AL,AL
214 JNZ COMERR ;Error if file not found
215 XOR AX,AX
216 MOV [FCB+33],AX ; Set 4-byte Random Record field to
217 MOV [FCB+35],AX ; beginning of file.
218 INC AX
219 MOV [FCB+14],AX ;Set record length field
220 MOV AH,39 ;Block read (CX already set)
221 INT 33
222 JCXZ COMERR ;Error if no records read
223 TEST AL,1
224 JZ COMERR ;Error if not end-of-file
225;
226; Make all segment registers the same.
227;
228 MOV DS,BX
229 MOV ES,BX
230 MOV SS,BX
231 MOV SP,5CH ;Set stack to standard value
232 XOR AX,AX
233 PUSH AX ;Put zero on top of stack for return
234 MOV DX,80H
235 MOV AH,26
236 INT 33 ;Set default transfer address (DS:0080)
237 PUSH BX ;Put segment on stack
238 MOV AX,100H
239 PUSH AX ;Put address to execute within segment on stack
240 RET L ;Jump to COMMAND
241
242COMERR:
243 MOV DX,BADCOM
244 MOV AH,9 ;Print string
245 INT 33
246 EI
247STALL: JP STALL
248
249STCTAB: DB 17H ;Select master mode register
250 DW 84F3H ;Enable time-of-day
251 DB 1 ;Counter 1 mode register
252 DW 0138H
253 DB 2
254 DW 0038H
255 DB 3
256 DW 0008H ;Set counter 3 to count days
257
258 IF SERIAL
259 DB 0B7H, 77H, 4EH, 37H, PRNBAUD, AUXBAUD
260 ENDIF
261
262BADCOM: DB 13,10,"Error in loading Command Interpreter",13,10,"$"
263FCB: DB 1,"COMMAND COM"
264 DS 25
265;
266; ************ Time and Date ************
267;
268GETTIME:
269 MOV AL,0A7H ;Save counters 1,2,3
270 OUT STCCOM
271 MOV AL,0E0H ;Enable data pointer sequencing
272 OUT STCCOM
273 MOV AL,19H ;Select hold 1 / hold cycle
274 OUT STCCOM
275 CALL STCTIME ;Get seconds & 1/100's
276 XCHG AX,DX
277 CALL STCTIME ;Get hours & minutes
278 XCHG AX,CX
279 IN STCDATA
280 MOV AH,AL
281 IN STCDATA
282 XCHG AL,AH ;Count of days
283 JP POINTSTAT
284
285STCTIME:
286 CALL STCBYTE
287 MOV CL,AH
288STCBYTE:
289 IN STCDATA
290 MOV AH,AL
291 SHR AH
292 SHR AH
293 SHR AH
294 SHR AH
295 AND AL,0FH ;Unpack BCD digits
296 AAD ;Convert to binary
297 MOV AH,AL
298 MOV AL,CL
299 RET
300
301SETTIME:
302 PUSH CX
303 PUSH DX
304 CALL LOAD0 ;Put 0 into load registers to condition timer
305 MOV AL,43H ;Load counters 1 & 2
306 OUT STCCOM
307 POP DX
308 POP CX
309 CALL LOAD
310 MOV AL,43H
311 OUT STCCOM ;Load counters 1&2
312 CALL LOAD0
313 MOV AL,27H ;Arm counters 1,2,3
314 OUT STCCOM
315 JP POINTSTAT
316
317LOAD0:
318 XOR CX,CX
319 MOV DX,CX
320LOAD:
321 MOV AL,09 ;Counter 1 load register
322 CALL OUTDX
323 MOV AL,0AH ;Counter 2 load register
324 MOV DX,CX
325OUTDX:
326 OUT STCCOM ;Select a load register
327 MOV AL,DL
328 CALL OUTBCD
329 MOV AL,DH
330OUTBCD:
331 AAM ;Convert binary to unpacked BCD
332 SHL AH
333 SHL AH
334 SHL AH
335 SHL AH
336 OR AL,AH ;Packed BCD
337 OUT STCDATA
338 RET
339
340SETDATE:
341 XCHG AX,DX ;Put date in DX
342 MOV AL,0BH ;Select Counter 3 load register
343 OUT STCCOM
344 XCHG AX,DX
345 OUT STCDATA
346 MOV AL,AH
347 OUT STCDATA
348 MOV AL,44H ;Load counter 3
349 OUT STCCOM
350POINTSTAT:
351 PUSH AX
352 MOV AL,1FH ;Point to status register
353 OUT STCCOM ; so power-off glitches won't hurt
354 POP AX
355 RET L
356;
357; ************ CONSOLE INPUT ************
358;
359
360 IF INTINP-1 ; Non-interrupt driven input.
361STATUS:
362 IN STAT
363 AND AL,DAV
364 JZ NOTHING ; Jump if nothing there.
365 PUSHF ; Save Z flag.
366 INB DATA
367 AND AL,7FH
368 SEG CS
369 MOV [QUEUE],AL ; Put new character in buffer.
370 POPF ; Return with Z flag clear.
371 RET L
372NOTHING:
373 SEG CS
374 MOV AL,[QUEUE] ; See if there's anything in the buffer.
375 NOT AL ; Set up the Z flag.
376 TEST AL,80H
377 PUSHF
378 NOT AL
379 POPF
380 RET L
381
382INP:
383 MOV AL,-1
384 SEG CS
385 XCHG AL,[QUEUE] ; Remove the character from the buffer.
386 AND AL,AL
387 JNS INRET ; Return if we have a character.
388INLOOP:
389 IN STAT ; Wait till a character is available.
390 AND AL,DAV
391 JZ INLOOP
392 IN DATA
393 AND AL,7FH
394INRET:
395FLUSH:
396 RET L
397
398QUEUE: DB -1 ; For storing characters from STATUS to INP.
399 ENDIF
400
401 IF INTINP ; Interrupt-driven input.
402;
403; Console keyboard interrupt handler.
404;
405KBINT:
406 PUSH AX
407 PUSH SI
408 MOV AL,20H ;End of Interrupt command
409 OUT BASE+2 ;Send to slave
410 IN DATA ;Get the character
411 AND AL,7FH
412 CMP AL,"C"-"@"
413 JZ FLSH
414 CMP AL,"S"-"@"
415 JZ FLSH
416 CMP AL,"F"-"@"
417 JNZ SAVKY
418FLSH:
419 CALL 13*3,BIOSSEG ; Call I/O system keyboard buffer flush.
420SAVKY:
421 SEG CS
422 MOV SI,[REAR] ;Pointer to rear of queue
423 CALL INCQ
424 SEG CS
425 CMP SI,[FRONT] ;Any room in queue?
426 JZ QFULL
427 SEG CS
428 MOV [SI],AL ;Put character in queue
429 SEG CS
430 MOV [REAR],SI ;Save pointer
431LEAVINT:
432 POP SI
433 POP AX
434 IRET
435QFULL:
436 MOV AL,7 ; BELL character.
437 CALL 3*3,BIOSSEG ; Call I/O system console output function.
438 JMPS LEAVINT
439
440STATUS:
441 PUSH SI
442;See if printer ready
443 IN PRNSTAT
444 AND AL,TBMT
445 JZ NOPRN
446 SEG CS
447 MOV SI,[PFRONT]
448 SEG CS
449 CMP SI,[PREAR] ;Anything in print queue?
450 JNZ SENDPRN
451 SEG CS
452 CMP B,[PRNFCB],-1 ;Print spooling in progress?
453 JZ NOPRN ;If not, nothing to print
454;Print spooling in progress. Get next buffer
455 PUSH DS
456 PUSH CS
457 POP DS
458 PUSH AX
459 PUSH CX
460 PUSH DX
461 PUSH [STKSAV]
462 PUSH [STKSAV+2]
463 PUSH [DMAADD]
464 PUSH [DMAADD+2]
465 MOV DX,PQUEUE
466 MOV AH,26 ;Set DMA address
467 INT 33
468 MOV DX,PRNFCB
469 MOV CX,PBUFSIZ
470 MOV AH,39 ;Read buffer
471 INT 33
472 OR AL,AL
473 JZ NOTEOF
474 MOV B,[PRNFCB],-1 ;Turn off print spooling at EOF
475NOTEOF:
476 POP [DMAADD+2]
477 POP [DMAADD]
478 POP [STKSAV+2]
479 POP [STKSAV]
480 MOV SI,CX
481 POP DX
482 POP CX
483 POP AX
484 POP DS
485 OR SI,SI
486 JZ NOPRN
487 ADD SI,PQUEUE-1
488 SEG CS
489 MOV [PREAR],SI
490 MOV SI,ENDPQ-1
491SENDPRN:
492 CALL INCPQ
493 SEG CS
494 MOV [PFRONT],SI
495 SEG CS
496 LODSB ;Get character to print
497 OUT PRNDATA
498NOPRN:
499 DI ; Disable interrupts while checking queue.
500 SEG CS
501 MOV SI,[FRONT]
502 SEG CS
503 CMP SI,[REAR] ; Anything in queue?
504 JZ NOCHR ; Jump if nothing in queue.
505 CALL INCQ
506 SEG CS
507 LODSB ;Get character (if there is one)
508 OR SI,SI ;Reset zero flag
509NOCHR:
510 EI
511 POP SI
512 RET L ;Zero clear if we have a character
513
514INP:
515 CALL STATUS,BIOSSEG ; Get I/O system console input status.
516 JZ INP
517 PUSH SI
518 DI ; Disable interrupts while changing queue pointers.
519 SEG CS
520 MOV SI,[FRONT]
521 CALL INCQ ; Permanently remove char from queue
522 SEG CS
523 MOV [FRONT],SI
524 EI
525 POP SI
526 RET L
527
528FLUSH:
529 DI
530 SEG CS
531 MOV [REAR],QUEUE
532 SEG CS
533 MOV [FRONT],QUEUE
534 EI
535 RET L
536
537INCQ:
538 INC SI
539 CMP SI,ENDQ ;Exceeded length of queue?
540 JB RET
541 MOV SI,QUEUE
542 RET
543
544INCPQ:
545 INC SI
546 CMP SI,ENDPQ ;Exceeded length of queue?
547 JB RET
548 MOV SI,PQUEUE
549 RET
550
551FRONT: DW QUEUE
552REAR: DW QUEUE
553QUEUE: DS QSIZE
554ENDQ: EQU $
555PFRONT: DW PQUEUE
556PREAR: DW PQUEUE
557PQUEUE: DS PBUFSIZ
558ENDPQ: EQU $
559PRNFCB: DB -1
560 DS 36
561 ENDIF
562
563;
564; ************ Console and Printer Output ************
565;
566OUTP:
567 PUSH AX
568OUTLP:
569 IN STAT
570 AND AL,TBMT
571 JZ OUTLP
572 POP AX
573 OUT DATA
574 RET L
575
576PRINT:
577 PUSH SI
578 SEG CS
579 MOV SI,[PREAR]
580 CALL INCPQ
581PRINLP:
582 SEG CS
583 CMP SI,[PFRONT]
584 JNZ PRNCHR
585;Print queue is full
586 PUSH AX
587 CALL STATUS,BIOSSEG ;Poll and maybe print something
588 POP AX
589 JMPS PRINLP
590PRNCHR:
591 SEG CS
592 MOV [PREAR],SI
593 SEG CS
594 MOV [SI],AL
595 POP SI
596 RET L
597;
598; ************ Auxiliary I/O ************
599;
600AUXIN:
601 IN AUXSTAT
602 AND AL,DAV
603 JZ AUXIN
604 IN AUXDATA
605 RET L
606
607AUXOUT:
608 PUSH AX
609AUXLP:
610 IN AUXSTAT
611 AND AL,TBMT
612 JZ AUXLP
613 POP AX
614 OUT AUXDATA
615 RET L
616;
617; ************ 1771/1793-type controller disk I/O ************
618;
619TARBELL:EQU TARBELLSD+TARBELLDD
620CROMEMCO:EQU CROMEMCO4FDC+CROMEMCO16FDC
621
622WD1791: EQU SCP+TARBELLDD+CROMEMCO16FDC
623WD1771: EQU TARBELLSD+CROMEMCO4FDC
624
625 IF WD1791
626READCOM:EQU 80H
627WRITECOM:EQU 0A0H
628 ENDIF
629
630 IF WD1771
631READCOM:EQU 88H
632WRITECOM:EQU 0A8H
633 ENDIF
634
635 IF SCP
636SMALLBIT:EQU 10H
637BACKBIT:EQU 04H
638DDENBIT:EQU 08H
639DONEBIT:EQU 01H
640DISK: EQU 0E0H
641 ENDIF
642
643 IF TARBELL
644BACKBIT:EQU 40H
645DDENBIT:EQU 08H
646DONEBIT:EQU 80H
647DISK: EQU 78H
648 ENDIF
649
650 IF CROMEMCO
651SMALLBIT:EQU 10H
652BACKBIT:EQU 0FDH ; Send this to port 4 to select back.
653DDENBIT:EQU 40H
654DONEBIT:EQU 01H
655DISK: EQU 30H
656 ENDIF
657
658 IF SMALLDS-1
659SMALLDDSECT: EQU 8
660 ENDIF
661
662 IF SMALLDS
663SMALLDDSECT: EQU 16
664 ENDIF
665
666 IF LARGEDS-1
667LARGEDDSECT: EQU 8
668 ENDIF
669
670 IF LARGEDS
671LARGEDDSECT: EQU 16
672 ENDIF
673;
674; Disk change function.
675; On entry:
676; AL = disk drive number.
677; On exit:
678; AH = -1 (FF hex) if disk is changed.
679; AH = 0 if don't know.
680; AH = 1 if not changed.
681;
682; CF clear if no disk error.
683; AL = disk I/O driver number.
684;
685; CF set if disk error.
686; AL = disk error code (see disk read below).
687;
688 IF WD1771
689DSKCHG:
690 MOV AH,0 ; AH = 0 in case we don't know.
691 SEG CS
692 CMP AL,[CURDRV]
693 JNZ RETL
694 PUSH AX ; Save drive number.
695
696 IF CROMEMCO
697 INB DISK+4
698 ENDIF
699
700 IF TARBELL
701 INB DISK
702 ENDIF
703
704 AND AL,20H ; Look at head load bit
705 POP AX
706 JZ RETL
707 MOV AH,1 ; AH = 1, disk not changed.
708RETL:
709 CLC ; No disk error.
710 RET L
711 ENDIF ; End of 1771 DSKCHG.
712
713 IF WD1791
714DSKCHG:
715 MOV AH,0 ; AH = 0 in case we don't know.
716 SEG CS
717 CMP AL,[CURDRV]
718 JNZ DENSCHK ; Check density if not same drive.
719 PUSH AX
720
721 IF SCP+CROMEMCO
722 INB DISK+4
723 ENDIF
724
725 IF TARBELL
726 INB DISK
727 ENDIF
728
729 AND AL,20H ; Look at head load bit
730 POP AX
731 JZ DENSCHK ; Check density if head not loaded.
732 MOV AH,1 ; AH = 1, disk not changed.
733 MOV BX,PREVDENS
734 SEG CS
735 XLAT ; Get previous density
736 CLC ; No disk error.
737 RET L
738DENSCHK:
739 CALL CHKNEW ; Unload head if selecting new drive.
740 CBW
741 XCHG AX,SI
742 ADD SI,PREVDENS
743 MOV CX,4 ; Try each density twice
744 MOV AH,0 ; Disk may not have been changed.
745CHKDENS:
746 SEG CS
747 MOV AL,[SI] ; Get previous disk I/O driver number.
748 MOV BX,DRVTAB
749 SEG CS
750 XLAT ; Get drive select byte for previous density
751
752 IF CROMEMCO16FDC
753 CALL MOTOR ; Wait for motor to come up to speed.
754 ENDIF
755
756 OUT DISK+4 ; Select disk
757 MOV AL,0C4H ; READ ADDRESS command
758 CALL DCOM
759 AND AL,98H
760 IN DISK+3 ; Eat last byte to reset DRQ
761 JZ HAVDENS ; Jump if no error in reading address.
762 NOT AH ; AH = -1 (disk changed) if new density works.
763 SEG CS
764 XOR B,[SI],1 ; Try other density
765 LOOP CHKDENS
766 MOV AX,2 ; Couldn't read disk at all, AH = 0 for don't
767 STC ; know if disk changed, AL = error code 2 -
768 RET L ; disk not ready, carry set to indicate error.
769
770HAVDENS:
771 SEG CS
772 LODSB ; AL = disk I/O driver number.
773 CLC ; No disk error.
774 RET L
775
776PREVDENS:DB 1,3,5,7,9,11,13 ; Table of previous disk I/O driver numbers.
777 ENDIF ; End of 1793 DSKCHG function.
778
779CHKNEW:
780 MOV AH,AL ; Save disk drive number in AH.
781 SEG CS ; AL = previous disk drive number,
782 XCHG AL,[CURDRV] ; make new drive current.
783 CMP AL,AH ; Changing drives?
784 JZ RET
785;
786; If changing drives, unload head so the head load delay one-shot will
787; fire again. Do it by seeking to the same track with the H bit reset.
788;
789 IN DISK+1 ; Get current track number
790 OUT DISK+3 ; Make it the track to seek to
791 MOV AL,10H ; Seek and unload head
792 CALL DCOM
793 MOV AL,AH ; Restore current drive number
794 RET
795
796 IF CROMEMCO16FDC
797MOTOR:
798 PUSH AX
799 MOV AH,AL
800 IN DISK+4 ; See if the motor is on.
801 TEST AL,08H
802 MOV AL,AH
803 OUTB DISK+4 ; Select drive & start motor.
804 JNZ MOTORSON ; No delay if motors already on.
805 PUSH CX
806 MOV CX,43716 ; Loop count for 1 second.
807MOTORDELAY: ; (8 MHz, 16-bit memory).
808 AAM ; 83 clocks.
809 AAM ; 83 clocks.
810 LOOP MOTORDELAY ; 17 clocks.
811 POP CX
812MOTORSON:
813 POP AX
814 RET
815 ENDIF
816;
817; Disk read function.
818;
819; On entry:
820; AL = Disk I/O driver number
821; BX = Disk transfer address in DS
822; CX = Number of sectors to transfer
823; DX = Logical record number of transfer
824; On exit:
825; CF clear if transfer complete
826;
827; CF set if hard disk error.
828; CX = number of sectors left to transfer.
829; AL = disk error code
830; 0 = write protect error
831; 2 = not ready error
832; 4 = "data" (CRC) error
833; 6 = seek error
834; 8 = sector not found
835; 10 = write fault
836; 12 = "disk" (none of the above) error
837;
838READ:
839 CALL SEEK ;Position head
840 JC ERROR
841 PUSH ES ; Make ES same as DS.
842 MOV BX,DS
843 MOV ES,BX
844RDLP:
845 CALL READSECT ;Perform sector read
846 JC POPESERROR
847 INC DH ;Next sector number
848 LOOP RDLP ;Read each sector requested
849 CLC ; No errors.
850 POP ES ; Restore ES register.
851 RET L
852;
853; Disk write function.
854; Registers same on entry and exit as read above.
855;
856WRITE:
857 CALL SEEK ;Position head
858 JC ERROR
859WRTLP:
860 CALL WRITESECT ;Perform sector write
861 JC ERROR
862 INC DH ;Bump sector counter
863 LOOP WRTLP ;Write CX sectors
864 CLC ; No errors.
865WRITERET:
866 RET L
867
868POPESERROR:
869 POP ES ; Restore ES register.
870ERROR:
871 MOV BL,-1
872 SEG CS
873 MOV [DI],BL ; Indicate we don't know where head is.
874 MOV SI,ERRTAB
875GETCOD:
876 INC BL ; Increment to next error code.
877 SEG CS
878 LODB
879 TEST AH,AL ; See if error code matches disk status.
880 JZ GETCOD ; Try another if not.
881 MOV AL,BL ; Now we've got the code.
882 SHL AL ; Multiply by two.
883 STC
884 RET L
885
886ERRTAB:
887 DB 40H ;Write protect error
888 DB 80H ;Not ready error
889 DB 8 ;CRC error
890 DB 2 ;Seek error
891 DB 10H ;Sector not found
892 DB 20H ;Write fault
893 DB 7 ;"Disk" error
894;
895; Direct disk read and write from INT 37 and INT 38. Subroutine GETIODRIVER
896; calls DSKCHG to convert disk drive number to I/O driver number.
897;
898; Setting CURDRV to -1 before calling DSKCHG forces DSKCHG to check the disk's
899; density before returning the I/O driver number. This is necessary because
900; programs such as FORMAT could change the density of a disk and leave the
901; head loaded. If the head is loaded DSKCHG assumes the disk hasn't been
902; changed and returns the old I/O driver number which could be wrong.
903;
904; CURDRV is set to -1 before returning so when DSKCHG is called by the
905; operating system, it will tell the operating system the disk may have
906; been changed (because it may have been).
907;
908DIRECTREAD:
909
910 IF WD1791
911 CALL GETIODRIVER ; Convert drive number to I/O driver number.
912 JC DIRECTRET ; Return if DSKCHG returned error.
913 ENDIF
914
915 CALL 7*3,BIOSSEG ; Call READ.
916 JMPS DIRECTRET
917
918DIRECTWRITE:
919
920 IF WD1791
921 CALL GETIODRIVER ; Convert drive number to I/O driver number.
922 JC DIRECTRET ; Return if DSKCHG returned error.
923 ENDIF
924
925 CALL 8*3,BIOSSEG ; Call WRITE.
926DIRECTRET:
927 SEG CS
928 MOV B,[CURDRV],-1 ; Force DSKCHG to do density check.
929 RET L
930
931 IF WD1791
932GETIODRIVER:
933 SEG CS
934 MOV B,[CURDRV],-1 ; Force DSKCHG to do density check.
935 PUSH BX
936 PUSH CX
937 CALL 9*3,BIOSSEG ; Call DSKCHG.
938 POP CX
939 POP BX
940 RET
941 ENDIF
942;
943; Function:
944; Seeks to proper track.
945; On entry:
946; Same as for disk read or write above.
947; On exit:
948; AH = Drive select byte
949; DL = Track number
950; DH = Sector number
951; SI = Disk transfer address in DS
952; DI = pointer to drive's track counter in CS
953; CX unchanged (number of sectors)
954;
955SEEK:
956 MOV SI,BX ; Save transfer address
957 CBW
958 MOV BX,AX ; Prepare to index on drive number
959
960 IF WD1791 ; If two disk formats per drive.
961 SHR AL ; Convert to physical disk drive number.
962 ENDIF
963
964 CALL CHKNEW ; Unload head if changing drives.
965 SEG CS
966 MOV AL,[BX+DRVTAB] ; Get drive-select byte.
967
968 IF CROMEMCO16FDC
969 CALL MOTOR ; Wait for the motors to come up to speed.
970 ENDIF
971
972 OUTB DISK+4 ; Select drive.
973
974 IF CROMEMCO
975 OR AL,80H ; Set auto-wait bit.
976 ENDIF
977
978 MOV AH,AL ; Save drive-select byte in AH.
979 XCHG AX,DX ; AX = logical sector number.
980 MOV DL,26 ; 26 sectors/track unless changed below
981
982 IF SCP
983 TEST DH,SMALLBIT ; Check if small disk.
984 JZ BIGONE ; Jump if big disk.
985 MOV DL,18 ; Assume 18 sectors on small track.
986 TEST DH,DDENBIT ; Check if double-density.
987 JZ HAVSECT ; Jump if not.
988 MOV DL,SMALLDDSECT ; Number of sectors on small DD track.
989 JP HAVSECT
990BIGONE:
991 TEST DH,DDENBIT ; Check if double-density.
992 JZ HAVSECT ; Jump if not.
993 MOV DL,LARGEDDSECT ; Number of sectors on big DD track.
994 ENDIF
995
996 IF TARBELLDD ; Tarbell DD controller.
997 TEST DH,DDENBIT ; Check for double-density.
998 JZ HAVSECT
999 MOV DL,LARGEDDSECT ; Number of sectors on DD track.
1000 ENDIF
1001
1002 IF CROMEMCO4FDC
1003 TEST DH,SMALLBIT ; Check if small disk.
1004 JNZ HAVSECT ; Jump if not.
1005 MOV DL,18 ; 18 sectors on small disk track.
1006 ENDIF
1007
1008 IF CROMEMCO16FDC
1009 TEST DH,SMALLBIT ; Check if small disk.
1010 JNZ BIGONE ; Jump if big disk.
1011 MOV DL,18 ; Assume 18 sectors on small track.
1012 TEST DH,DDENBIT ; Check if double-density.
1013 JZ HAVSECT ; Jump if not.
1014 MOV DL,SMALLDDSECT ; Number of sectors on small DD track.
1015 JP HAVSECT
1016BIGONE:
1017 TEST DH,DDENBIT ; Check if double-density.
1018 JZ HAVSECT ; Jump if not.
1019 MOV DL,LARGEDDSECT ; Number of sectors on big DD track.
1020 ENDIF
1021
1022HAVSECT:
1023 DIV AL,DL ; AL = track, AH = sector.
1024 XCHG AX,DX ; AH has drive-select byte, DX = track & sector.
1025 INC DH ; Sectors start at one, not zero.
1026 SEG CS
1027 MOV BL,[BX+TRKPT] ; Get this drive's displacement into track table.
1028 ADD BX,TRKTAB ; BX now points to track counter for this drive.
1029 MOV DI,BX
1030 MOV AL,DL ; Move new track number into AL.
1031 SEG CS
1032 XCHG AL,[DI] ; Xchange current track with desired track
1033 OUT DISK+1 ; Inform controller chip of current track
1034 CMP AL,DL ; See if we're at the right track.
1035 JZ RET
1036 MOV BH,2 ; Seek retry count
1037 CMP AL,-1 ; Head position known?
1038 JNZ NOHOME ; If not, home head
1039TRYSK:
1040 CALL HOME
1041 JC SEEKERR
1042NOHOME:
1043 MOV AL,DL ; AL = new track number.
1044 OUT DISK+3
1045 MOV AL,1CH+STPSPD ; Seek command.
1046 CALL MOVHEAD
1047 AND AL,98H ; Accept not ready, seek, & CRC error bits.
1048 JZ RET
1049 JS SEEKERR ; No retries if not ready
1050 DEC BH
1051 JNZ TRYSK
1052SEEKERR:
1053 MOV AH,AL ; Put status in AH.
1054 TEST AL,80H ; See if it was a Not Ready error.
1055 STC
1056 JNZ RET ; Status is OK for Not Ready error.
1057 MOV AH,2 ; Everything else is seek error.
1058 RET
1059
1060SETUP:
1061 MOV BL,DH ; Move sector number to BL to play with
1062
1063 IF SCP+CROMEMCO16FDC
1064 TEST AH,DDENBIT ; Check for double density.
1065 JZ CHECKSMALL ; Not DD, check size for SD.
1066 ENDIF
1067
1068 IF TARBELLDD
1069 TEST AH,DDENBIT ; Check for double density.
1070 JZ CHECK26 ; Not DD.
1071 ENDIF
1072
1073 IF WD1791
1074
1075 IF (SCP+TARBELL)*LARGEDS+SCP*SMALLDS
1076 MOV AL,AH ; Select front side of disk.
1077 OUT DISK+4
1078 ENDIF
1079
1080 IF CROMEMCO*(LARGEDS+SMALLDS)
1081 MOV AL,0FFH ; Select front side of disk.
1082 OUT 04H
1083 ENDIF
1084
1085 CMP BL,8 ; See if legal DD sector number.
1086 JBE PUTSEC ; Jump if ok.
1087
1088 IF (LARGEDS-1)*((SMALLDS*(SCP+CROMEMCO))-1)
1089 JP STEP ; If only SS drives, we gotta step.
1090 ENDIF
1091
1092 IF SCP*LARGEDS*(SMALLDS-1)
1093 TEST AH,SMALLBIT ; Check for 5.25 inch disk.
1094 JNZ STEP ; Jump if small because SMALLDS is off.
1095 ENDIF
1096
1097 IF SCP*SMALLDS*(LARGEDS-1)
1098 TEST AH,SMALLBIT ; Check for 8 inch disk.
1099 JZ STEP ; Jump if large because LARGEDS is off.
1100 ENDIF
1101
1102 IF CROMEMCO16FDC*LARGEDS*(SMALLDS-1)
1103 TEST AH,SMALLBIT ; Check for 5.25 inch disk.
1104 JZ STEP ; Jump if small because SMALLDS is off.
1105 ENDIF
1106
1107 IF CROMEMCO16FDC*SMALLDS*(LARGEDS-1)
1108 TEST AH,SMALLBIT ; Check for 8 inch disk.
1109 JNZ STEP ; Jump if large because LARGEDS is off.
1110 ENDIF
1111
1112 IF LARGEDS+SMALLDS*(SCP+CROMEMCO)
1113 SUB BL,8 ; Find true sector for back side.
1114 CMP BL,8 ; See if ok now.
1115 JA STEP ; Have to step if still too big.
1116
1117 IF SCP+TARBELLDD
1118 MOV AL,AH ; Move drive select byte into AL.
1119 OR AL,BACKBIT ; Select back side.
1120 OUT DISK+4
1121 ENDIF
1122
1123 IF CROMEMCO16FDC
1124 MOV AL,BACKBIT ; Select back side.
1125 OUT 04H
1126 ENDIF
1127
1128 JP PUTSEC
1129 ENDIF
1130
1131 ENDIF
1132
1133 IF SCP
1134CHECKSMALL:
1135 TEST AH,SMALLBIT ; See if big disk.
1136 JZ CHECK26 ; Jump if big.
1137 ENDIF
1138
1139 IF CROMEMCO
1140CHECKSMALL:
1141 TEST AH,SMALLBIT ; See if big disk.
1142 JNZ CHECK26 ; Jump if big.
1143 ENDIF
1144
1145 IF SCP+CROMEMCO
1146 CMP BL,18 ; See if legal small SD/SS sector.
1147 JA STEP ; Jump if not.
1148 ENDIF
1149
1150CHECK26:
1151 CMP BL,26 ; See if legal large SD/SS sector.
1152 JBE PUTSEC ; Jump if ok.
1153STEP:
1154 INC DL ; Increment track number.
1155 MOV AL,58H ; Step in with update.
1156 CALL DCOM
1157 SEG CS
1158 INC B,[DI] ; Increment the track pointer.
1159 MOV DH,1 ; After step, do first sector.
1160 MOV BL,DH ; Fix temporary sector number also.
1161PUTSEC:
1162 MOV AL,BL ; Output sector number to controller.
1163 OUT DISK+2
1164 DI ; Interrupts not allowed until I/O done
1165
1166 IF SCP+CROMEMCO
1167 INB DISK+4 ; Get head-load bit.
1168 ENDIF
1169
1170 IF TARBELL
1171 INB DISK
1172 ENDIF
1173
1174 NOT AL
1175 AND AL,20H ; Check head load status
1176 JZ RET
1177 MOV AL,4
1178 RET
1179
1180READSECT:
1181 CALL SETUP
1182 MOV BL,10 ; Retry count for hard error.
1183 XCHG DI,SI ; Transfer address to DI.
1184 PUSH DX ; Save track & sector number.
1185 MOV DL,DISK+3 ; Disk controller data port.
1186RDAGN:
1187 OR AL,READCOM
1188 OUT DISK
1189
1190 IF CROMEMCO
1191 MOV AL,AH ; Turn on auto-wait.
1192 OUT DISK+4
1193 ENDIF
1194
1195 MOV BP,DI ; Save address for retry.
1196 JMPS RLOOPENTRY
1197RLOOP:
1198 STOB ; Write into memory.
1199RLOOPENTRY:
1200
1201 IF SCP
1202 IN DISK+5 ; Wait for DRQ or INTRQ.
1203 ENDIF
1204
1205 IF TARBELL+CROMEMCO
1206 IN DISK+4
1207 ENDIF
1208
1209 IF TARBELL
1210 SHL AL
1211 INB DX ; Read data from disk controller chip.
1212 JC RLOOP
1213 ENDIF
1214
1215 IF SCP+CROMEMCO
1216 SHR AL
1217 INB DX ; Read data from disk controller chip.
1218 JNC RLOOP
1219 ENDIF
1220
1221 EI ; Interrupts OK now
1222 CALL GETSTAT
1223 AND AL,9CH
1224 JZ RDPOP
1225 MOV DI,BP ; Get origainal address back for retry.
1226 MOV BH,AL ; Save error status for report
1227 MOV AL,0
1228 DEC BL
1229 JNZ RDAGN
1230 MOV AH,BH ; Put error status in AH.
1231 STC
1232RDPOP:
1233 POP DX ; Get back track & sector number.
1234 XCHG SI,DI ; Address back to SI.
1235
1236 IF TARBELL
1237FORCINT:
1238 MOV AL,0D0H ; Tarbell controllers need this Force Interrupt
1239 OUT DISK ; so that Type I status is always available
1240 MOV AL,10 ; at the 1771/1793 status port so we can find
1241INTDLY: ; out if the head is loaded. SCP and Cromemco
1242 DEC AL ; controllers have head-load status available
1243 JNZ INTDLY ; at the DISK+4 status port.
1244 ENDIF
1245
1246 RET
1247
1248WRITESECT:
1249 CALL SETUP
1250 MOV BL,10
1251 PUSH DX ; Save track & sector number.
1252 MOV DL,DISK+3 ; Disk controller data port.
1253WRTAGN:
1254 OR AL,WRITECOM
1255 OUT DISK
1256
1257 IF CROMEMCO
1258 MOV AL,AH ; Turn on auto-wait.
1259 OUT DISK+4
1260 ENDIF
1261
1262 MOV BP,SI
1263WRLOOP:
1264
1265 IF SCP
1266 INB DISK+5
1267 ENDIF
1268
1269 IF TARBELL+CROMEMCO
1270 INB DISK+4
1271 ENDIF
1272
1273 IF SCP+CROMEMCO
1274 SHR AL
1275 LODB ; Get data from memory.
1276 OUTB DX ; Write to disk.
1277 JNC WRLOOP
1278 ENDIF
1279
1280 IF TARBELL
1281 SHL AL
1282 LODB ; Get data from memory.
1283 OUTB DX ; Write to disk.
1284 JC WRLOOP
1285 ENDIF
1286
1287 EI ; Interrupts OK now.
1288 DEC SI
1289 CALL GETSTAT
1290 AND AL,0FCH
1291 JZ WRPOP
1292 MOV SI,BP
1293 MOV BH,AL
1294 MOV AL,0
1295 DEC BL
1296 JNZ WRTAGN
1297 MOV AH,BH ; Error status to AH.
1298 STC
1299WRPOP:
1300 POP DX ; Get back track & sector number.
1301
1302 IF TARBELL
1303 JMPS FORCINT
1304 ENDIF
1305
1306 IF SCP+CROMEMCO
1307 RET
1308 ENDIF
1309;
1310; Subroutine to restore the read/write head to track 0.
1311;
1312 IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1)
1313HOME:
1314 ENDIF
1315
1316 IF FASTSEEK*CROMEMCO
1317 TEST AH,SMALLBIT ; Check for large disk.
1318 JNZ RESTORE ; Big disks are fast seek PerSci.
1319 ENDIF
1320
1321 MOV BL,3
1322TRYHOM:
1323
1324 IF SCP*FASTSEEK
1325 MOV AL,AH ; Turn on Restore to PerSci.
1326 OR AL,80H
1327 OUTB DISK+4
1328 ENDIF
1329
1330 MOV AL,0CH+STPSPD ; Restore with verify command.
1331 CALL DCOM
1332 AND AL,98H
1333
1334 IF SCP*FASTSEEK
1335 MOV AL,AH ; Restore off.
1336 OUTB DISK+4
1337 ENDIF
1338
1339 JZ RET
1340 JS HOMERR ; No retries if not ready
1341 MOV AL,58H+STPSPD ; Step in with update
1342 CALL DCOM
1343 DEC BL
1344 JNZ TRYHOM
1345HOMERR:
1346 STC
1347 RET
1348;
1349; RESTORE for PerSci drives.
1350; Doesn't exist yet for Tarbell controllers.
1351;
1352 IF FASTSEEK*TARBELL
1353HOME:
1354RESTORE:
1355 RET
1356 ENDIF
1357
1358 IF FASTSEEK*CROMEMCO4FDC
1359RESTORE:
1360 MOV AL,0C4H ;READ ADDRESS command to keep head loaded
1361 OUT DISK
1362 MOV AL,77H
1363 OUT 4
1364CHKRES:
1365 IN 4
1366 AND AL,40H
1367 JZ RESDONE
1368 IN DISK+4
1369 TEST AL,DONEBIT
1370 JZ CHKRES
1371 IN DISK
1372 JP RESTORE ;Reload head
1373RESDONE:
1374 MOV AL,7FH
1375 OUT 4
1376 CALL GETSTAT
1377 MOV AL,0
1378 OUT DISK+1 ;Tell 1771 we're now on track 0
1379 RET
1380 ENDIF
1381
1382 IF FASTSEEK*CROMEMCO16FDC
1383RESTORE:
1384 MOV AL,0D7H ; Turn on Drive-Select and Restore.
1385 OUTB 4
1386 PUSH AX
1387 AAM ; 10 uS delay.
1388 POP AX
1389RESWAIT:
1390 INB 4 ; Wait till Seek Complete is active.
1391 TEST AL,40H
1392 JNZ RESWAIT
1393 MOV AL,0FFH ; Turn off Drive-Select and Restore.
1394 OUTB 4
1395 SUB AL,AL ; Tell 1793 we're on track 0.
1396 OUTB DISK+1
1397 RET
1398 ENDIF
1399;
1400; Subroutine to move the read/write head to the desired track.
1401; Usually falls through to DCOM unless special handling for
1402; PerSci drives is required in which case go to FASTSK.
1403;
1404 IF SCP+CROMEMCO+TARBELL*(FASTSEEK-1)
1405MOVHEAD:
1406 ENDIF
1407
1408 IF CROMEMCO*FASTSEEK
1409 TEST AH,SMALLBIT ; Check for PerSci.
1410 JNZ FASTSK
1411 ENDIF
1412
1413DCOM:
1414 OUT DISK
1415 PUSH AX
1416 AAM ;Delay 10 microseconds
1417 POP AX
1418GETSTAT:
1419 IN DISK+4
1420 TEST AL,DONEBIT
1421
1422 IF TARBELL
1423 JNZ GETSTAT
1424 ENDIF
1425
1426 IF SCP+CROMEMCO
1427 JZ GETSTAT
1428 ENDIF
1429
1430 IN DISK
1431 RET
1432;
1433; Fast seek code for PerSci drives.
1434; Tarbell not installed yet.
1435;
1436 IF FASTSEEK*TARBELL
1437MOVHEAD:
1438FASTSK:
1439 RET
1440 ENDIF
1441
1442 IF FASTSEEK*CROMEMCO
1443FASTSK:
1444 MOV AL,6FH
1445 OUT 4
1446 MOV AL,18H
1447 CALL DCOM
1448SKWAIT:
1449 IN 4
1450 TEST AL,40H
1451 JNZ SKWAIT
1452 MOV AL,7FH
1453 OUT 4
1454 MOV AL,0
1455 RET
1456 ENDIF
1457
1458CURDRV: DB -1
1459;
1460; Explanation of tables below.
1461;
1462; DRVTAB is a table of bytes which are sent to the disk controller as drive-
1463; select bytes to choose which physical drive is selected for each disk I/O
1464; driver. It also selects whether the disk is 5.25-inch or 8-inch, single-
1465; density or double-density. Always select side 0 in the drive-select byte if
1466; a side-select bit is available. There should be one entry in the DRVTAB
1467; table for each disk I/O driver. Exactly which bits in the drive-select byte
1468; do what depends on which disk controller is used.
1469;
1470; TRKTAB is a table of bytes used to store which track the read/write
1471; head of each drive is on. Each physical drive should have its own
1472; entry in TRKTAB.
1473;
1474; TRKPT is a table of bytes which indicates which TRKTAB entry each
1475; disk I/O driver should use. Since each physical drive may be used for
1476; more than one disk I/O driver, more than one entry in TRKPT may point
1477; to the same entry in TRKTAB. Drives such as PerSci 277s which use
1478; the same head positioner for more than one drive should share entrys
1479; in TRKTAB.
1480;
1481; INITTAB is the initialization table for 86-DOS as described in the
1482; 86-DOS Programer's Manual under "Customizing the I/O System."
1483;
1484 IF SCP*COMBIN*FASTSEEK
1485;
1486; A PerSci 277 or 299 and one 5.25-inch drive.
1487;
1488DRVTAB: DB 00H,08H,01H,09H,10H,18H,00H,08H,01H,09H
1489TRKPT: DB 0,0,0,0,1,1,0,0,0,0
1490TRKTAB: DB -1,-1
1491INITTAB:
1492 IF CONVERT-1
1493 DB 6 ; Number of disk I/O drivers.
1494 ENDIF
1495
1496 IF CONVERT
1497 DB 10
1498 ENDIF
1499
1500 DB 0 ; Disk I/O driver 0 uses disk drive 0.
1501 DW LSDRIVE ; Disk I/O driver 0 is 8-inch single-density.
1502 DB 0 ; Disk I/O driver 1 uses disk drive 0.
1503 DW LDDRIVE ; Disk I/O driver 1 is 8-inch double-density.
1504 DB 1 ; Etc.
1505 DW LSDRIVE
1506 DB 1
1507 DW LDDRIVE
1508 DB 2
1509 DW SSDRIVE
1510 DB 2
1511 DW SDDRIVE
1512
1513 IF CONVERT
1514 DB 3
1515 DW OLDLSDRIVE
1516 DB 3
1517 DW OLDLDDRIVE
1518 DB 4
1519 DW OLDLSDRIVE
1520 DB 4
1521 DW OLDLDDRIVE
1522 ENDIF
1523 ENDIF
1524
1525 IF SCP*LARGE*FASTSEEK
1526;
1527; PerSci 277 or 299.
1528;
1529DRVTAB: DB 00H,08H,01H,09H,00H,08H,01H,09H
1530TRKPT: DB 0,0,0,0,0,0,0,0
1531TRKTAB: DB -1
1532INITTAB:
1533 IF CONVERT-1
1534 DB 4
1535 ENDIF
1536
1537 IF CONVERT
1538 DB 8
1539 ENDIF
1540
1541 DB 0
1542 DW LSDRIVE
1543 DB 0
1544 DW LDDRIVE
1545 DB 1
1546 DW LSDRIVE
1547 DB 1
1548 DW LDDRIVE
1549
1550 IF CONVERT
1551 DB 2
1552 DW OLDLSDRIVE
1553 DB 2
1554 DW OLDLDDRIVE
1555 DB 3
1556 DW OLDLSDRIVE
1557 DB 3
1558 DW OLDLDDRIVE
1559 ENDIF
1560 ENDIF
1561
1562 IF TARBELLDD
1563;
1564; Two 8-inch Shugart-type drives.
1565;
1566DRVTAB: DB 0,8,10H,18H,0,8,10H,18H
1567TRKPT: DB 0,0,1,1,0,0,1,1
1568TRKTAB: DB -1,-1
1569INITTAB:
1570
1571 IF CONVERT-1
1572 DB 4
1573 ENDIF
1574
1575 IF CONVERT
1576 DB 8
1577 ENDIF
1578
1579 DB 0
1580 DW LSDRIVE
1581 DB 0
1582 DW LDDRIVE
1583 DB 1
1584 DW LSDRIVE
1585 DB 1
1586 DW LDDRIVE
1587
1588 IF CONVERT
1589 DB 2
1590 DW OLDLSDRIVE
1591 DB 2
1592 DW OLDLDDRIVE
1593 DB 3
1594 DW OLDLSDRIVE
1595 DB 3
1596 DW OLDLDDRIVE
1597 ENDIF
1598 ENDIF
1599
1600 IF TARBELLSD
1601;
1602; Four 8-inch Shugart-type drives.
1603;
1604DRVTAB: DB 0F2H,0E2H,0F2H,0E2H
1605TRKPT: DB 0,1,0,1
1606TRKTAB: DB -1,-1
1607INITTAB:
1608
1609 IF CONVERT-1
1610 DB 2
1611 ENDIF
1612
1613 IF CONVERT
1614 DB 4
1615 ENDIF
1616
1617 DB 0
1618 DW LSDRIVE
1619 DB 1
1620 DW LSDRIVE
1621
1622 IF CONVERT
1623 DB 2
1624 DW OLDLSDRIVE
1625 DB 3
1626 DW OLDLSDRIVE
1627 ENDIF
1628 ENDIF
1629;
1630; Cromemco drive select byte is derived as follows:
1631; Bit 7 = 0
1632; Bit 6 = 1 if double density (if 16FDC)
1633; Bit 5 = 1 (motor on)
1634; Bit 4 = 0 for 5", 1 for 8" drives
1635; Bit 3 = 1 for drive 3
1636; Bit 2 = 1 for drive 2
1637; Bit 1 = 1 for drive 1
1638; Bit 0 = 1 for drive 0
1639;
1640 IF CROMEMCO4FDC*LARGE
1641;
1642; PerSci 277 drive.
1643;
1644DRVTAB: DB 31H,32H,31H,32H
1645TRKPT: DB 0,0,0,0
1646TRKTAB: DB -1
1647INITTAB:
1648
1649 IF CONVERT-1
1650 DB 2
1651 ENDIF
1652
1653 IF CONVERT
1654 DB 4
1655 ENDIF
1656
1657 DB 0
1658 DW LSDRIVE
1659 DB 1
1660 DW LSDRIVE
1661
1662 IF CONVERT
1663 DB 2
1664 DW OLDLSDRIVE
1665 DB 3
1666 DW OLDLSDRIVE
1667 ENDIF
1668 ENDIF
1669
1670 IF CROMEMCO4FDC*COMBIN
1671;
1672; A PerSci 277 and one 5.25-inch drive.
1673;
1674DRVTAB: DB 31H,32H,24H,31H,32H
1675TRKPT: DB 0,0,1,0,0
1676TRKTAB: DB -1,-1
1677INITTAB:
1678
1679 IF CONVERT-1
1680 DB 3
1681 ENDIF
1682
1683 IF CONVERT
1684 DB 5
1685 ENDIF
1686
1687 DB 0
1688 DW LSDRIVE
1689 DB 1
1690 DW LSDRIVE
1691 DB 2
1692 DW SSDRIVE
1693
1694 IF CONVERT
1695 DB 3
1696 DW OLDLSDRIVE
1697 DB 4
1698 DW OLDLSDRIVE
1699 ENDIF
1700 ENDIF
1701
1702 IF CROMEMCO4FDC*SMALL
1703;
1704; Three 5.25-inch drives.
1705;
1706DRVTAB: DB 21H,22H,24H
1707TRKPT: DB 0,1,2
1708TRKTAB: DB -1,-1,-1
1709INITTAB:DB 3
1710 DB 0
1711 DW SSDRIVE
1712 DB 1
1713 DW SSDRIVE
1714 DB 2
1715 DW SSDRIVE
1716 ENDIF
1717
1718 IF CUSTOM
1719;
1720; Cromemco 4FDC with two 8-inch Shugart-type drives.
1721;
1722DRVTAB: DB 31H,32H,31H,32H
1723TRKPT: DB 0,1,0,1
1724TRKTAB: DB -1,-1
1725INITTAB:
1726 IF CONVERT-1
1727 DB 2
1728 ENDIF
1729
1730 IF CONVERT
1731 DB 4
1732 ENDIF
1733
1734 DB 0
1735 DW LSDRIVE
1736 DB 1
1737 DW LSDRIVE
1738
1739 IF CONVERT
1740 DB 2
1741 DW OLDLSDRIVE
1742 DB 3
1743 DW OLDLSDRIVE
1744 ENDIF
1745 ENDIF
1746
1747 IF CROMEMCO16FDC*SMALL
1748;
1749; Three 5.25-inch drives.
1750;
1751DRVTAB: DB 21H,61H,22H,62H,24H,64H
1752TRKPT: DB 0,0,1,1,2,2
1753TRKTAB: DB -1,-1,-1
1754INITTAB:DB 6
1755 DB 0
1756 DW SSDRIVE
1757 DB 0
1758 DW SDDRIVE
1759 DB 1
1760 DW SSDRIVE
1761 DB 1
1762 DW SDDRIVE
1763 DB 2
1764 DW SSDRIVE
1765 DB 2
1766 DW SDDRIVE
1767 ENDIF
1768
1769 IF CROMEMCO16FDC*COMBIN
1770;
1771; A PerSci 277 or 299 and one 5.25-inch drive.
1772;
1773DRVTAB: DB 31H,71H,32H,72H,24H,64H,31H,71H,32H,72H
1774TRKPT: DB 0,0,0,0,1,1,0,0,0,0
1775TRKTAB: DB -1,-1
1776INITTAB:
1777 IF CONVERT-1
1778 DB 6
1779 ENDIF
1780
1781 IF CONVERT
1782 DB 10
1783 ENDIF
1784
1785 DB 0
1786 DW LSDRIVE
1787 DB 0
1788 DW LDDRIVE
1789 DB 1
1790 DW LSDRIVE
1791 DB 1
1792 DW LDDRIVE
1793 DB 2
1794 DW SSDRIVE
1795 DB 2
1796 DW SDDRIVE
1797
1798 IF CONVERT
1799 DB 3
1800 DW OLDLSDRIVE
1801 DB 3
1802 DW OLDLDDRIVE
1803 DB 4
1804 DW OLDLSDRIVE
1805 DB 4
1806 DW OLDLDDRIVE
1807 ENDIF
1808 ENDIF
1809
1810 IF CROMEMCO16FDC*LARGE
1811;
1812; A PerSci 277 or 299.
1813;
1814DRVTAB: DB 31H,71H,32H,72H,31H,71H,32H,72H
1815TRKPT: DB 0,0,0,0,0,0,0,0
1816TRKTAB: DB -1
1817INITTAB:
1818 IF CONVERT-1
1819 DB 4
1820 ENDIF
1821
1822 IF CONVERT
1823 DB 8
1824 ENDIF
1825
1826 DB 0
1827 DW LSDRIVE
1828 DB 0
1829 DW LDDRIVE
1830 DB 1
1831 DW LSDRIVE
1832 DB 1
1833 DW LDDRIVE
1834
1835 IF CONVERT
1836 DB 2
1837 DW OLDLSDRIVE
1838 DB 2
1839 DW OLDLDDRIVE
1840 DB 3
1841 DW OLDLSDRIVE
1842 DB 3
1843 DW OLDLDDRIVE
1844 ENDIF
1845 ENDIF
1846
1847 IF SMALL+COMBIN
1848SSDRIVE:
1849 DW 128 ; Sector size in bytes.
1850 DB 2 ; Sector per allocation unit.
1851 DW 54 ; Reserved sectors.
1852 DB 2 ; Number of allocation tables.
1853 DW 64 ; Number of directory entrys.
1854 DW 720 ; Number of sectors on the disk.
1855
1856 IF SMALLDS-1
1857SDDRIVE: ; This is the IBM Personal Computer
1858 DW 512 ; disk format.
1859 DB 1
1860 DW 1
1861 DB 2
1862 DW 64
1863 DW 320
1864 ENDIF
1865
1866 IF SMALLDS
1867SDDRIVE:
1868 DW 512
1869 DB 2
1870 DW 1
1871 DB 2
1872 DW 112
1873 DW 640
1874 ENDIF
1875 ENDIF ; End of small drive DPTs.
1876
1877 IF COMBIN+LARGE
1878LSDRIVE:
1879 DW 128 ; Size of sector in bytes.
1880 DB 4 ; Sectors per allocation unit.
1881 DW 1 ; Number of reserved sectors.
1882 DB 2 ; Number of File Allocation Tables.
1883 DW 68 ; Number of directory entrys.
1884 DW 77*26 ; Number of sectors on the disk.
1885
1886 IF CONVERT
1887OLDLSDRIVE:
1888 DW 128
1889 DB 4
1890 DW 52 ; Old format had two tracks reserved.
1891 DB 2
1892 DW 64 ; 64 directory entrys.
1893 DW 77*26
1894 ENDIF
1895
1896 IF LARGEDS-1
1897OLDLDDRIVE:
1898LDDRIVE:
1899 DW 1024
1900 DB 1
1901 DW 1
1902 DB 2
1903 DW 96
1904 DW 77*8
1905 ENDIF
1906
1907 IF LARGEDS
1908LDDRIVE:
1909 DW 1024
1910 DB 1
1911 DW 1
1912 DB 2
1913 DW 192 ; 192 directory entrys in new 8-inch DD/DS format.
1914 DW 77*8*2
1915
1916 IF CONVERT
1917OLDLDDRIVE:
1918 DW 1024
1919 DB 1
1920 DW 1
1921 DB 2
1922 DW 128 ; 128 directory entrys in old 8-inch DD/DS format.
1923 DW 77*8*2
1924 ENDIF
1925 ENDIF
1926
1927 ENDIF ; End of large drive DPTs.
1928
1929DOSSEG: EQU ($+15)/16+BIOSSEG ; Compute segment to use for 86-DOS.
1930DOSDIF: EQU 16*(DOSSEG-BIOSSEG)
1931STKSAV: EQU 1701H+DOSDIF
1932DMAADD: EQU 15B4H+DOSDIF
1933 END
1934 \ No newline at end of file