diff options
| author | 1982-03-03 16:51:26 -0800 | |
|---|---|---|
| committer | 2018-09-21 17:51:26 -0700 | |
| commit | fce0f75959b9806f4016beb7b19e19b37cc97b6c (patch) | |
| tree | 758374b64f03e049ca9cfb8cae2674ec5b72cd2b /v1.25/source/IO.ASM | |
| parent | Initial commit (diff) | |
| download | ms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.tar.gz ms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.tar.xz ms-dos-fce0f75959b9806f4016beb7b19e19b37cc97b6c.zip | |
MS-DOS v1.25 Release
Diffstat (limited to 'v1.25/source/IO.ASM')
| -rw-r--r-- | v1.25/source/IO.ASM | 1934 |
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. | ||
| 7 | INTINP: 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. | ||
| 11 | PARALLELAUX: EQU 1 | ||
| 12 | SERIALAUX: 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. | ||
| 17 | PARALLELPRN: EQU 1 | ||
| 18 | SERIALPRN: 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. | ||
| 23 | PRNBAUD:EQU 7 ; 1200 baud | ||
| 24 | AUXBAUD:EQU 0FH ; 19200 baud | ||
| 25 | ; | ||
| 26 | ; Select disk controller here. | ||
| 27 | SCP: EQU 1 | ||
| 28 | TARBELLSD: EQU 0 | ||
| 29 | TARBELLDD: EQU 0 | ||
| 30 | CROMEMCO4FDC: EQU 0 | ||
| 31 | CROMEMCO16FDC: 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. | ||
| 39 | CONVERT:EQU 1 | ||
| 40 | ; | ||
| 41 | ; Select disk configuration: | ||
| 42 | LARGE: EQU 1 ; Large drives. | ||
| 43 | COMBIN: EQU 0 ; Two 8-inch and one 5.25-inch. | ||
| 44 | SMALL: EQU 0 ; Three 5.25-inch drives. | ||
| 45 | CUSTOM: EQU 0 ; User defined. | ||
| 46 | ; | ||
| 47 | ; If 8-inch drives are PerSci, select FASTSEEK here: | ||
| 48 | ; (Fastseek with Tarbell controllers doesn't work yet). | ||
| 49 | FASTSEEK: EQU 1 | ||
| 50 | ; | ||
| 51 | ; For double-density controllers, select double-sided operation of | ||
| 52 | ; 8-inch disks in double-density mode. | ||
| 53 | LARGEDS: EQU 0 | ||
| 54 | ; | ||
| 55 | ; For double-density controllers, select double-sided operation of | ||
| 56 | ; 5.25-inch disks in double-density mode. | ||
| 57 | SMALLDS: 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 | ; | ||
| 70 | STPSPD: EQU 0 | ||
| 71 | ; | ||
| 72 | ; ****** End of selections ******************************************** | ||
| 73 | ; | ||
| 74 | BIOSSEG:EQU 40H ; I/O system segment. | ||
| 75 | BIOSLEN:EQU 2048 ; Maximum length of I/O system. | ||
| 76 | DOSLEN: EQU 8192 ; Maximum length of MS-DOS. | ||
| 77 | QSIZE: EQU 80 ; Input queue size. | ||
| 78 | PBUFSIZ:EQU 128 ; Size of print buffer | ||
| 79 | BASE: EQU 0F0H ; CPU Support card base port number. | ||
| 80 | SIOBASE:EQU 10H ; Base port number of Multiport Serial card. | ||
| 81 | STAT: EQU BASE+7 ; Serial I/O status port. | ||
| 82 | DATA: EQU BASE+6 ; Serial I/O data port. | ||
| 83 | DAV: EQU 2 ; Data available bit. | ||
| 84 | TBMT: EQU 1 ; Transmitter buffer empty bit. | ||
| 85 | SERIAL: EQU SERIALPRN+SERIALAUX | ||
| 86 | STCDATA:EQU BASE+4 ; Ports for 9513 Timer chip. | ||
| 87 | STCCOM: EQU BASE+5 | ||
| 88 | |||
| 89 | IF SERIALAUX | ||
| 90 | AUXSTAT:EQU SIOBASE+3 | ||
| 91 | AUXDATA:EQU SIOBASE+2 | ||
| 92 | ENDIF | ||
| 93 | |||
| 94 | IF PARALLELAUX | ||
| 95 | AUXSTAT:EQU BASE+13 | ||
| 96 | AUXDATA:EQU BASE+12 | ||
| 97 | ENDIF | ||
| 98 | |||
| 99 | IF SERIALPRN | ||
| 100 | PRNSTAT:EQU SIOBASE+1 | ||
| 101 | PRNDATA:EQU SIOBASE+0 | ||
| 102 | ENDIF | ||
| 103 | |||
| 104 | IF PARALLELPRN | ||
| 105 | PRNSTAT:EQU BASE+13 | ||
| 106 | PRNDATA: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 | ||
| 127 | MAPDEV: | ||
| 128 | RET L | ||
| 129 | |||
| 130 | INIT: | ||
| 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 | ||
| 157 | INITSTC: | ||
| 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 | ||
| 168 | SERINIT: | ||
| 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 | |||
| 242 | COMERR: | ||
| 243 | MOV DX,BADCOM | ||
| 244 | MOV AH,9 ;Print string | ||
| 245 | INT 33 | ||
| 246 | EI | ||
| 247 | STALL: JP STALL | ||
| 248 | |||
| 249 | STCTAB: 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 | |||
| 262 | BADCOM: DB 13,10,"Error in loading Command Interpreter",13,10,"$" | ||
| 263 | FCB: DB 1,"COMMAND COM" | ||
| 264 | DS 25 | ||
| 265 | ; | ||
| 266 | ; ************ Time and Date ************ | ||
| 267 | ; | ||
| 268 | GETTIME: | ||
| 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 | |||
| 285 | STCTIME: | ||
| 286 | CALL STCBYTE | ||
| 287 | MOV CL,AH | ||
| 288 | STCBYTE: | ||
| 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 | |||
| 301 | SETTIME: | ||
| 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 | |||
| 317 | LOAD0: | ||
| 318 | XOR CX,CX | ||
| 319 | MOV DX,CX | ||
| 320 | LOAD: | ||
| 321 | MOV AL,09 ;Counter 1 load register | ||
| 322 | CALL OUTDX | ||
| 323 | MOV AL,0AH ;Counter 2 load register | ||
| 324 | MOV DX,CX | ||
| 325 | OUTDX: | ||
| 326 | OUT STCCOM ;Select a load register | ||
| 327 | MOV AL,DL | ||
| 328 | CALL OUTBCD | ||
| 329 | MOV AL,DH | ||
| 330 | OUTBCD: | ||
| 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 | |||
| 340 | SETDATE: | ||
| 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 | ||
| 350 | POINTSTAT: | ||
| 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. | ||
| 361 | STATUS: | ||
| 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 | ||
| 372 | NOTHING: | ||
| 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 | |||
| 382 | INP: | ||
| 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. | ||
| 388 | INLOOP: | ||
| 389 | IN STAT ; Wait till a character is available. | ||
| 390 | AND AL,DAV | ||
| 391 | JZ INLOOP | ||
| 392 | IN DATA | ||
| 393 | AND AL,7FH | ||
| 394 | INRET: | ||
| 395 | FLUSH: | ||
| 396 | RET L | ||
| 397 | |||
| 398 | QUEUE: 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 | ; | ||
| 405 | KBINT: | ||
| 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 | ||
| 418 | FLSH: | ||
| 419 | CALL 13*3,BIOSSEG ; Call I/O system keyboard buffer flush. | ||
| 420 | SAVKY: | ||
| 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 | ||
| 431 | LEAVINT: | ||
| 432 | POP SI | ||
| 433 | POP AX | ||
| 434 | IRET | ||
| 435 | QFULL: | ||
| 436 | MOV AL,7 ; BELL character. | ||
| 437 | CALL 3*3,BIOSSEG ; Call I/O system console output function. | ||
| 438 | JMPS LEAVINT | ||
| 439 | |||
| 440 | STATUS: | ||
| 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 | ||
| 475 | NOTEOF: | ||
| 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 | ||
| 491 | SENDPRN: | ||
| 492 | CALL INCPQ | ||
| 493 | SEG CS | ||
| 494 | MOV [PFRONT],SI | ||
| 495 | SEG CS | ||
| 496 | LODSB ;Get character to print | ||
| 497 | OUT PRNDATA | ||
| 498 | NOPRN: | ||
| 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 | ||
| 509 | NOCHR: | ||
| 510 | EI | ||
| 511 | POP SI | ||
| 512 | RET L ;Zero clear if we have a character | ||
| 513 | |||
| 514 | INP: | ||
| 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 | |||
| 528 | FLUSH: | ||
| 529 | DI | ||
| 530 | SEG CS | ||
| 531 | MOV [REAR],QUEUE | ||
| 532 | SEG CS | ||
| 533 | MOV [FRONT],QUEUE | ||
| 534 | EI | ||
| 535 | RET L | ||
| 536 | |||
| 537 | INCQ: | ||
| 538 | INC SI | ||
| 539 | CMP SI,ENDQ ;Exceeded length of queue? | ||
| 540 | JB RET | ||
| 541 | MOV SI,QUEUE | ||
| 542 | RET | ||
| 543 | |||
| 544 | INCPQ: | ||
| 545 | INC SI | ||
| 546 | CMP SI,ENDPQ ;Exceeded length of queue? | ||
| 547 | JB RET | ||
| 548 | MOV SI,PQUEUE | ||
| 549 | RET | ||
| 550 | |||
| 551 | FRONT: DW QUEUE | ||
| 552 | REAR: DW QUEUE | ||
| 553 | QUEUE: DS QSIZE | ||
| 554 | ENDQ: EQU $ | ||
| 555 | PFRONT: DW PQUEUE | ||
| 556 | PREAR: DW PQUEUE | ||
| 557 | PQUEUE: DS PBUFSIZ | ||
| 558 | ENDPQ: EQU $ | ||
| 559 | PRNFCB: DB -1 | ||
| 560 | DS 36 | ||
| 561 | ENDIF | ||
| 562 | |||
| 563 | ; | ||
| 564 | ; ************ Console and Printer Output ************ | ||
| 565 | ; | ||
| 566 | OUTP: | ||
| 567 | PUSH AX | ||
| 568 | OUTLP: | ||
| 569 | IN STAT | ||
| 570 | AND AL,TBMT | ||
| 571 | JZ OUTLP | ||
| 572 | POP AX | ||
| 573 | OUT DATA | ||
| 574 | RET L | ||
| 575 | |||
| 576 | PRINT: | ||
| 577 | PUSH SI | ||
| 578 | SEG CS | ||
| 579 | MOV SI,[PREAR] | ||
| 580 | CALL INCPQ | ||
| 581 | PRINLP: | ||
| 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 | ||
| 590 | PRNCHR: | ||
| 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 | ; | ||
| 600 | AUXIN: | ||
| 601 | IN AUXSTAT | ||
| 602 | AND AL,DAV | ||
| 603 | JZ AUXIN | ||
| 604 | IN AUXDATA | ||
| 605 | RET L | ||
| 606 | |||
| 607 | AUXOUT: | ||
| 608 | PUSH AX | ||
| 609 | AUXLP: | ||
| 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 | ; | ||
| 619 | TARBELL:EQU TARBELLSD+TARBELLDD | ||
| 620 | CROMEMCO:EQU CROMEMCO4FDC+CROMEMCO16FDC | ||
| 621 | |||
| 622 | WD1791: EQU SCP+TARBELLDD+CROMEMCO16FDC | ||
| 623 | WD1771: EQU TARBELLSD+CROMEMCO4FDC | ||
| 624 | |||
| 625 | IF WD1791 | ||
| 626 | READCOM:EQU 80H | ||
| 627 | WRITECOM:EQU 0A0H | ||
| 628 | ENDIF | ||
| 629 | |||
| 630 | IF WD1771 | ||
| 631 | READCOM:EQU 88H | ||
| 632 | WRITECOM:EQU 0A8H | ||
| 633 | ENDIF | ||
| 634 | |||
| 635 | IF SCP | ||
| 636 | SMALLBIT:EQU 10H | ||
| 637 | BACKBIT:EQU 04H | ||
| 638 | DDENBIT:EQU 08H | ||
| 639 | DONEBIT:EQU 01H | ||
| 640 | DISK: EQU 0E0H | ||
| 641 | ENDIF | ||
| 642 | |||
| 643 | IF TARBELL | ||
| 644 | BACKBIT:EQU 40H | ||
| 645 | DDENBIT:EQU 08H | ||
| 646 | DONEBIT:EQU 80H | ||
| 647 | DISK: EQU 78H | ||
| 648 | ENDIF | ||
| 649 | |||
| 650 | IF CROMEMCO | ||
| 651 | SMALLBIT:EQU 10H | ||
| 652 | BACKBIT:EQU 0FDH ; Send this to port 4 to select back. | ||
| 653 | DDENBIT:EQU 40H | ||
| 654 | DONEBIT:EQU 01H | ||
| 655 | DISK: EQU 30H | ||
| 656 | ENDIF | ||
| 657 | |||
| 658 | IF SMALLDS-1 | ||
| 659 | SMALLDDSECT: EQU 8 | ||
| 660 | ENDIF | ||
| 661 | |||
| 662 | IF SMALLDS | ||
| 663 | SMALLDDSECT: EQU 16 | ||
| 664 | ENDIF | ||
| 665 | |||
| 666 | IF LARGEDS-1 | ||
| 667 | LARGEDDSECT: EQU 8 | ||
| 668 | ENDIF | ||
| 669 | |||
| 670 | IF LARGEDS | ||
| 671 | LARGEDDSECT: 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 | ||
| 689 | DSKCHG: | ||
| 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. | ||
| 708 | RETL: | ||
| 709 | CLC ; No disk error. | ||
| 710 | RET L | ||
| 711 | ENDIF ; End of 1771 DSKCHG. | ||
| 712 | |||
| 713 | IF WD1791 | ||
| 714 | DSKCHG: | ||
| 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 | ||
| 738 | DENSCHK: | ||
| 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. | ||
| 745 | CHKDENS: | ||
| 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 | |||
| 770 | HAVDENS: | ||
| 771 | SEG CS | ||
| 772 | LODSB ; AL = disk I/O driver number. | ||
| 773 | CLC ; No disk error. | ||
| 774 | RET L | ||
| 775 | |||
| 776 | PREVDENS:DB 1,3,5,7,9,11,13 ; Table of previous disk I/O driver numbers. | ||
| 777 | ENDIF ; End of 1793 DSKCHG function. | ||
| 778 | |||
| 779 | CHKNEW: | ||
| 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 | ||
| 797 | MOTOR: | ||
| 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. | ||
| 807 | MOTORDELAY: ; (8 MHz, 16-bit memory). | ||
| 808 | AAM ; 83 clocks. | ||
| 809 | AAM ; 83 clocks. | ||
| 810 | LOOP MOTORDELAY ; 17 clocks. | ||
| 811 | POP CX | ||
| 812 | MOTORSON: | ||
| 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 | ; | ||
| 838 | READ: | ||
| 839 | CALL SEEK ;Position head | ||
| 840 | JC ERROR | ||
| 841 | PUSH ES ; Make ES same as DS. | ||
| 842 | MOV BX,DS | ||
| 843 | MOV ES,BX | ||
| 844 | RDLP: | ||
| 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 | ; | ||
| 856 | WRITE: | ||
| 857 | CALL SEEK ;Position head | ||
| 858 | JC ERROR | ||
| 859 | WRTLP: | ||
| 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. | ||
| 865 | WRITERET: | ||
| 866 | RET L | ||
| 867 | |||
| 868 | POPESERROR: | ||
| 869 | POP ES ; Restore ES register. | ||
| 870 | ERROR: | ||
| 871 | MOV BL,-1 | ||
| 872 | SEG CS | ||
| 873 | MOV [DI],BL ; Indicate we don't know where head is. | ||
| 874 | MOV SI,ERRTAB | ||
| 875 | GETCOD: | ||
| 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 | |||
| 886 | ERRTAB: | ||
| 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 | ; | ||
| 908 | DIRECTREAD: | ||
| 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 | |||
| 918 | DIRECTWRITE: | ||
| 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. | ||
| 926 | DIRECTRET: | ||
| 927 | SEG CS | ||
| 928 | MOV B,[CURDRV],-1 ; Force DSKCHG to do density check. | ||
| 929 | RET L | ||
| 930 | |||
| 931 | IF WD1791 | ||
| 932 | GETIODRIVER: | ||
| 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 | ; | ||
| 955 | SEEK: | ||
| 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 | ||
| 990 | BIGONE: | ||
| 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 | ||
| 1016 | BIGONE: | ||
| 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 | |||
| 1022 | HAVSECT: | ||
| 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 | ||
| 1039 | TRYSK: | ||
| 1040 | CALL HOME | ||
| 1041 | JC SEEKERR | ||
| 1042 | NOHOME: | ||
| 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 | ||
| 1052 | SEEKERR: | ||
| 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 | |||
| 1060 | SETUP: | ||
| 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 | ||
| 1134 | CHECKSMALL: | ||
| 1135 | TEST AH,SMALLBIT ; See if big disk. | ||
| 1136 | JZ CHECK26 ; Jump if big. | ||
| 1137 | ENDIF | ||
| 1138 | |||
| 1139 | IF CROMEMCO | ||
| 1140 | CHECKSMALL: | ||
| 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 | |||
| 1150 | CHECK26: | ||
| 1151 | CMP BL,26 ; See if legal large SD/SS sector. | ||
| 1152 | JBE PUTSEC ; Jump if ok. | ||
| 1153 | STEP: | ||
| 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. | ||
| 1161 | PUTSEC: | ||
| 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 | |||
| 1180 | READSECT: | ||
| 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. | ||
| 1186 | RDAGN: | ||
| 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 | ||
| 1197 | RLOOP: | ||
| 1198 | STOB ; Write into memory. | ||
| 1199 | RLOOPENTRY: | ||
| 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 | ||
| 1232 | RDPOP: | ||
| 1233 | POP DX ; Get back track & sector number. | ||
| 1234 | XCHG SI,DI ; Address back to SI. | ||
| 1235 | |||
| 1236 | IF TARBELL | ||
| 1237 | FORCINT: | ||
| 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 | ||
| 1241 | INTDLY: ; 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 | |||
| 1248 | WRITESECT: | ||
| 1249 | CALL SETUP | ||
| 1250 | MOV BL,10 | ||
| 1251 | PUSH DX ; Save track & sector number. | ||
| 1252 | MOV DL,DISK+3 ; Disk controller data port. | ||
| 1253 | WRTAGN: | ||
| 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 | ||
| 1263 | WRLOOP: | ||
| 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 | ||
| 1299 | WRPOP: | ||
| 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) | ||
| 1313 | HOME: | ||
| 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 | ||
| 1322 | TRYHOM: | ||
| 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 | ||
| 1345 | HOMERR: | ||
| 1346 | STC | ||
| 1347 | RET | ||
| 1348 | ; | ||
| 1349 | ; RESTORE for PerSci drives. | ||
| 1350 | ; Doesn't exist yet for Tarbell controllers. | ||
| 1351 | ; | ||
| 1352 | IF FASTSEEK*TARBELL | ||
| 1353 | HOME: | ||
| 1354 | RESTORE: | ||
| 1355 | RET | ||
| 1356 | ENDIF | ||
| 1357 | |||
| 1358 | IF FASTSEEK*CROMEMCO4FDC | ||
| 1359 | RESTORE: | ||
| 1360 | MOV AL,0C4H ;READ ADDRESS command to keep head loaded | ||
| 1361 | OUT DISK | ||
| 1362 | MOV AL,77H | ||
| 1363 | OUT 4 | ||
| 1364 | CHKRES: | ||
| 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 | ||
| 1373 | RESDONE: | ||
| 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 | ||
| 1383 | RESTORE: | ||
| 1384 | MOV AL,0D7H ; Turn on Drive-Select and Restore. | ||
| 1385 | OUTB 4 | ||
| 1386 | PUSH AX | ||
| 1387 | AAM ; 10 uS delay. | ||
| 1388 | POP AX | ||
| 1389 | RESWAIT: | ||
| 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) | ||
| 1405 | MOVHEAD: | ||
| 1406 | ENDIF | ||
| 1407 | |||
| 1408 | IF CROMEMCO*FASTSEEK | ||
| 1409 | TEST AH,SMALLBIT ; Check for PerSci. | ||
| 1410 | JNZ FASTSK | ||
| 1411 | ENDIF | ||
| 1412 | |||
| 1413 | DCOM: | ||
| 1414 | OUT DISK | ||
| 1415 | PUSH AX | ||
| 1416 | AAM ;Delay 10 microseconds | ||
| 1417 | POP AX | ||
| 1418 | GETSTAT: | ||
| 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 | ||
| 1437 | MOVHEAD: | ||
| 1438 | FASTSK: | ||
| 1439 | RET | ||
| 1440 | ENDIF | ||
| 1441 | |||
| 1442 | IF FASTSEEK*CROMEMCO | ||
| 1443 | FASTSK: | ||
| 1444 | MOV AL,6FH | ||
| 1445 | OUT 4 | ||
| 1446 | MOV AL,18H | ||
| 1447 | CALL DCOM | ||
| 1448 | SKWAIT: | ||
| 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 | |||
| 1458 | CURDRV: 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 | ; | ||
| 1488 | DRVTAB: DB 00H,08H,01H,09H,10H,18H,00H,08H,01H,09H | ||
| 1489 | TRKPT: DB 0,0,0,0,1,1,0,0,0,0 | ||
| 1490 | TRKTAB: DB -1,-1 | ||
| 1491 | INITTAB: | ||
| 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 | ; | ||
| 1529 | DRVTAB: DB 00H,08H,01H,09H,00H,08H,01H,09H | ||
| 1530 | TRKPT: DB 0,0,0,0,0,0,0,0 | ||
| 1531 | TRKTAB: DB -1 | ||
| 1532 | INITTAB: | ||
| 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 | ; | ||
| 1566 | DRVTAB: DB 0,8,10H,18H,0,8,10H,18H | ||
| 1567 | TRKPT: DB 0,0,1,1,0,0,1,1 | ||
| 1568 | TRKTAB: DB -1,-1 | ||
| 1569 | INITTAB: | ||
| 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 | ; | ||
| 1604 | DRVTAB: DB 0F2H,0E2H,0F2H,0E2H | ||
| 1605 | TRKPT: DB 0,1,0,1 | ||
| 1606 | TRKTAB: DB -1,-1 | ||
| 1607 | INITTAB: | ||
| 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 | ; | ||
| 1644 | DRVTAB: DB 31H,32H,31H,32H | ||
| 1645 | TRKPT: DB 0,0,0,0 | ||
| 1646 | TRKTAB: DB -1 | ||
| 1647 | INITTAB: | ||
| 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 | ; | ||
| 1674 | DRVTAB: DB 31H,32H,24H,31H,32H | ||
| 1675 | TRKPT: DB 0,0,1,0,0 | ||
| 1676 | TRKTAB: DB -1,-1 | ||
| 1677 | INITTAB: | ||
| 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 | ; | ||
| 1706 | DRVTAB: DB 21H,22H,24H | ||
| 1707 | TRKPT: DB 0,1,2 | ||
| 1708 | TRKTAB: DB -1,-1,-1 | ||
| 1709 | INITTAB: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 | ; | ||
| 1722 | DRVTAB: DB 31H,32H,31H,32H | ||
| 1723 | TRKPT: DB 0,1,0,1 | ||
| 1724 | TRKTAB: DB -1,-1 | ||
| 1725 | INITTAB: | ||
| 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 | ; | ||
| 1751 | DRVTAB: DB 21H,61H,22H,62H,24H,64H | ||
| 1752 | TRKPT: DB 0,0,1,1,2,2 | ||
| 1753 | TRKTAB: DB -1,-1,-1 | ||
| 1754 | INITTAB: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 | ; | ||
| 1773 | DRVTAB: DB 31H,71H,32H,72H,24H,64H,31H,71H,32H,72H | ||
| 1774 | TRKPT: DB 0,0,0,0,1,1,0,0,0,0 | ||
| 1775 | TRKTAB: DB -1,-1 | ||
| 1776 | INITTAB: | ||
| 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 | ; | ||
| 1814 | DRVTAB: DB 31H,71H,32H,72H,31H,71H,32H,72H | ||
| 1815 | TRKPT: DB 0,0,0,0,0,0,0,0 | ||
| 1816 | TRKTAB: DB -1 | ||
| 1817 | INITTAB: | ||
| 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 | ||
| 1848 | SSDRIVE: | ||
| 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 | ||
| 1857 | SDDRIVE: ; 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 | ||
| 1867 | SDDRIVE: | ||
| 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 | ||
| 1878 | LSDRIVE: | ||
| 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 | ||
| 1887 | OLDLSDRIVE: | ||
| 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 | ||
| 1897 | OLDLDDRIVE: | ||
| 1898 | LDDRIVE: | ||
| 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 | ||
| 1908 | LDDRIVE: | ||
| 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 | ||
| 1917 | OLDLDDRIVE: | ||
| 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 | |||
| 1929 | DOSSEG: EQU ($+15)/16+BIOSSEG ; Compute segment to use for 86-DOS. | ||
| 1930 | DOSDIF: EQU 16*(DOSSEG-BIOSSEG) | ||
| 1931 | STKSAV: EQU 1701H+DOSDIF | ||
| 1932 | DMAADD: EQU 15B4H+DOSDIF | ||
| 1933 | END | ||
| 1934 | \ No newline at end of file | ||