diff options
Diffstat (limited to 'v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC')
| -rw-r--r-- | v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC | 553 |
1 files changed, 553 insertions, 0 deletions
diff --git a/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC new file mode 100644 index 0000000..4a87725 --- /dev/null +++ b/v4.0-ozzie/bin/DISK2/BIOS/BUGCODE.INC | |||
| @@ -0,0 +1,553 @@ | |||
| 1 | ;*** Bugcode.inc - Debug code for including into sysini.asm and ibmbio.asm | ||
| 2 | ; | ||
| 3 | ; Can't link in via buglib due to memory and relocation games played | ||
| 4 | ; by these modules. Each gets a private, local-only copy of these | ||
| 5 | ; modules. | ||
| 6 | |||
| 7 | |||
| 8 | IFDEF DEBUGFLG | ||
| 9 | |||
| 10 | |||
| 11 | ;** DPRINTF _ Debug Printf | ||
| 12 | ; | ||
| 13 | ; Dprintf is a kernel debug print formatting package. It is intended | ||
| 14 | ; to produce conviently formatted output. | ||
| 15 | ; | ||
| 16 | ; Dprintf is called, indirectly, by a macro: | ||
| 17 | ; | ||
| 18 | ; DEBUG n,m,"string",<a1,...,an> | ||
| 19 | ; | ||
| 20 | ; string = format string | ||
| 21 | ; a1 = first argument | ||
| 22 | ; an = last argument | ||
| 23 | ; | ||
| 24 | ; The format string is an ASCIZ string which can contain 2 types of | ||
| 25 | ; specifications: data-format specifications and literal characters. | ||
| 26 | ; Data format specifications always begin with a '$' character; all | ||
| 27 | ; characters not part of a data format specification are treated as | ||
| 28 | ; literal characters. | ||
| 29 | ; | ||
| 30 | ; Literal characters | ||
| 31 | ; - any character not part of a format specification. Special | ||
| 32 | ; non-printing characters are: | ||
| 33 | ; \n - CRLF | ||
| 34 | ; \t - tab | ||
| 35 | ; \b - bell | ||
| 36 | ; \\ - \ | ||
| 37 | ; \$ - $ | ||
| 38 | ; | ||
| 39 | ; Format Specifications | ||
| 40 | ; | ||
| 41 | ; A format specification takes the form: | ||
| 42 | ; $ [@] <char> | ||
| 43 | ; | ||
| 44 | ; where <char> = | ||
| 45 | ; | ||
| 46 | ; x - print argument as a hex word | ||
| 47 | ; d - print argument as decimal word | ||
| 48 | ; c - print argument as ascii character | ||
| 49 | ; b - print argument as hex byte | ||
| 50 | ; For each of the above formats, the supplied argument | ||
| 51 | ; is a 16-bit word - the value to be printed. The optional @ | ||
| 52 | ; (described below) allows a segmented address to be supplied, | ||
| 53 | ; instead. | ||
| 54 | ; | ||
| 55 | ; s[nn] - print argument as asciz string; if optional decimal | ||
| 56 | ; argument follows the format character this specifys | ||
| 57 | ; a maximum string length. Non printing characters are | ||
| 58 | ; printed in the form \nnn where "nnn" is the octal byte | ||
| 59 | ; value. | ||
| 60 | ; Note that this format character cannot be directly | ||
| 61 | ; followed by a digit unless that digit is to be taken | ||
| 62 | ; as the start of a length argument. | ||
| 63 | ; | ||
| 64 | ; Bnn - print argument as hex bytes. The required following | ||
| 65 | ; decimal argument is the number of bytes to print. | ||
| 66 | ; | ||
| 67 | ; Both of these formats take a long address as their argument. | ||
| 68 | ; The '@' character is thus invalid for these formats. | ||
| 69 | ; | ||
| 70 | ; WARNINGS | ||
| 71 | ; As befitting a debug routine, DPRINTF does not have a whole lot | ||
| 72 | ; of "failsafe" code in it. Supplying screwed up formats can | ||
| 73 | ; muck things up. Specifically: | ||
| 74 | ; The @ argument must NOT be specified with the 's' or 'B' | ||
| 75 | ; format | ||
| 76 | ; A string/byte-length argument of 0 is taken as 65536 | ||
| 77 | ; The string "%% BAD FMT %%" appears in the output when | ||
| 78 | ; 1) an illegal format specifier is given, or | ||
| 79 | ; 2) the B format is given a 0 or missing length | ||
| 80 | ; | ||
| 81 | ; ENTRY (sp+n ) = address of format string (offset from return cs value) | ||
| 82 | ; (sp+n-2) = first argument word | ||
| 83 | ; (sp+n-4) = second argument word | ||
| 84 | ; . | ||
| 85 | ; (sp+4 ) = last argument word | ||
| 86 | ; (sp+2 ) = seg of return address | ||
| 87 | ; (sp ) = offset of return address | ||
| 88 | ; (bp) = offset of format string on the stack | ||
| 89 | ; EXIT none | ||
| 90 | ; USES flags | ||
| 91 | |||
| 92 | PUBLIC DPRINTF | ||
| 93 | DPRINTF PROC near | ||
| 94 | |||
| 95 | push ds | ||
| 96 | push es | ||
| 97 | push bp | ||
| 98 | push di | ||
| 99 | push si | ||
| 100 | push dx | ||
| 101 | push cx | ||
| 102 | push bx | ||
| 103 | push ax ; save registers | ||
| 104 | cld | ||
| 105 | |||
| 106 | mov si,[bp] ; get address of format string | ||
| 107 | sub bp,2 | ||
| 108 | mov bx,sp | ||
| 109 | mov ds,ss:20[bx] ; (ds:si) = address of format string | ||
| 110 | push cs | ||
| 111 | pop ds | ||
| 112 | |||
| 113 | ; Scan format string for next character | ||
| 114 | ; | ||
| 115 | ; (ds:si) = address of format string | ||
| 116 | ; (ss:bp) = address of next argument | ||
| 117 | |||
| 118 | dpf1: lodsb ; (al) = format string byte | ||
| 119 | and al,al | ||
| 120 | je dpf3 ; all done | ||
| 121 | cmp al,'$' | ||
| 122 | je dpf4 ; is data escape | ||
| 123 | cmp al,'\' | ||
| 124 | jnz dpf2 ; got the character | ||
| 125 | |||
| 126 | ; it's an "\" escape code - crack the argument character | ||
| 127 | |||
| 128 | lodsb | ||
| 129 | and al,al | ||
| 130 | je dpf3 ; all done, ignore hanging \ | ||
| 131 | xchg ah,al | ||
| 132 | mov al,0Ch | ||
| 133 | cmp ah,'n' | ||
| 134 | jne dpf1$5 ; not \n | ||
| 135 | mov al,0dH | ||
| 136 | call putchar | ||
| 137 | mov al,0aH | ||
| 138 | jmp SHORT dpf2 ; print LF | ||
| 139 | |||
| 140 | dpf1$5: cmp ah,'t' | ||
| 141 | mov al,9 | ||
| 142 | je dpf2 ; is \t | ||
| 143 | cmp ah,'b' | ||
| 144 | mov al,7 | ||
| 145 | je dpf2 ; is \b | ||
| 146 | xchg ah,al | ||
| 147 | dpf2: call putchar | ||
| 148 | jmp dpf1 | ||
| 149 | |||
| 150 | ; have the end of the format string - exit | ||
| 151 | |||
| 152 | dpf3: pop ax | ||
| 153 | pop bx | ||
| 154 | pop cx | ||
| 155 | pop dx | ||
| 156 | pop si | ||
| 157 | pop di | ||
| 158 | pop bp | ||
| 159 | pop es | ||
| 160 | pop ds | ||
| 161 | ret | ||
| 162 | |||
| 163 | |||
| 164 | ;* Have a '$' character - is data format escape | ||
| 165 | ; | ||
| 166 | ; Get address of data into es:di | ||
| 167 | ; | ||
| 168 | ; (bp) = address of data value | ||
| 169 | |||
| 170 | dpf4: mov di,bp | ||
| 171 | push ss | ||
| 172 | pop es ; (es:di) = address of data value | ||
| 173 | sub bp,2 ; point to next argument | ||
| 174 | lodsb ; (al) = format specifier | ||
| 175 | cmp al,'@' | ||
| 176 | jne dpf5 ; not an indirect flag | ||
| 177 | les di,[bp] | ||
| 178 | sub bp,2 ; have an extra 2 for @ | ||
| 179 | lodsb | ||
| 180 | dpf5: cmp al,'x' | ||
| 181 | jne dpfd1 ; not 'x' | ||
| 182 | |||
| 183 | ; is 'x' format - print hex word | ||
| 184 | |||
| 185 | mov ax,es:[di] | ||
| 186 | call THW ; type hex word | ||
| 187 | jmp dpf1 | ||
| 188 | |||
| 189 | dpfd1: cmp al,'d' | ||
| 190 | jnz dpfc1 ; not 'd' | ||
| 191 | |||
| 192 | ; is 'd' format - print decimal word | ||
| 193 | |||
| 194 | mov ax,es:[di] | ||
| 195 | call TDW ; type decimal word | ||
| 196 | jmp dpf1 | ||
| 197 | |||
| 198 | dpfc1: cmp al,'c' | ||
| 199 | jne dpfb1 | ||
| 200 | |||
| 201 | ; is 'c' format - print character | ||
| 202 | |||
| 203 | mov al,es:[di] | ||
| 204 | call putchar | ||
| 205 | jmp dpf1 | ||
| 206 | |||
| 207 | dpfb1: cmp al,'b' | ||
| 208 | jne dpfs1 | ||
| 209 | |||
| 210 | ; is 'b' format - print hex byte | ||
| 211 | |||
| 212 | mov al,es:[di] | ||
| 213 | call THB ; type hex byte | ||
| 214 | jmp dpf1 | ||
| 215 | |||
| 216 | dpfs1: cmp al,'s' | ||
| 217 | jne dpfbb1 | ||
| 218 | |||
| 219 | ; is 's' format - print ASCIZ string. First, check for | ||
| 220 | ; optional decimal limit | ||
| 221 | |||
| 222 | public SSB | ||
| 223 | SSB: sub cx,cx ; set 65536 limit | ||
| 224 | les di,[bp] ; (es:DI) = fwa of string | ||
| 225 | sub bp,2 ; argument to 's' was two words | ||
| 226 | mov al,[si] | ||
| 227 | cmp al,'0' | ||
| 228 | jb dpfs2 ; not decimal | ||
| 229 | cmp al,'9' | ||
| 230 | ja dpfs2 ; not decimal | ||
| 231 | call atod ; (ax) = decimal value, (ds:si) updated | ||
| 232 | xchg cx,ax | ||
| 233 | |||
| 234 | ; print asciz string at es:di, max of (cx) characters | ||
| 235 | ; (cx) = 0 means max of 65536 | ||
| 236 | ; | ||
| 237 | ; Other sections of code in dpf jump here to print strings | ||
| 238 | |||
| 239 | dpfs2: mov al,es:[di] | ||
| 240 | inc di | ||
| 241 | and al,al | ||
| 242 | je dpfs3 | ||
| 243 | call putchar | ||
| 244 | loop dpfs2 ; continue if not at limit | ||
| 245 | dpfs3: jmp dpf1 | ||
| 246 | |||
| 247 | dpfbb1: cmp al,'B' | ||
| 248 | je dpfbb2 ; is 'B' format | ||
| 249 | |||
| 250 | ; error in format code - print message | ||
| 251 | |||
| 252 | dpferr: push cs | ||
| 253 | pop es | ||
| 254 | mov di,OFFSET dpfa ; (es:di) = error message | ||
| 255 | sub cx,cx | ||
| 256 | jmp dpfs2 | ||
| 257 | |||
| 258 | dpfa: DB '%% BAD FMT %%',0 | ||
| 259 | |||
| 260 | ; have B format | ||
| 261 | |||
| 262 | dpfbb2: call atod ; (ax) = length specifier | ||
| 263 | jc dpferr ; number not there - error | ||
| 264 | xchg cx,ax | ||
| 265 | jcxz dpferr ; number is 0 - error | ||
| 266 | les di,[bp] ; (es:DI) = fwa of string | ||
| 267 | sub bp,2 ; argument to 's' was two words | ||
| 268 | dpfbb3: mov al,es:[di] | ||
| 269 | call THB ; type hex byte | ||
| 270 | mov al,' ' | ||
| 271 | call putchar ; space em out | ||
| 272 | inc di | ||
| 273 | loop dpfbb3 ; do em all | ||
| 274 | jmp dpf1 | ||
| 275 | |||
| 276 | DPRINTF ENDP | ||
| 277 | |||
| 278 | |||
| 279 | ;** THB - Type Hex Byte | ||
| 280 | ; | ||
| 281 | ; THB types a hex byte (via "putchar") | ||
| 282 | ; | ||
| 283 | ; ENTRY (AL) = byte | ||
| 284 | ; EXIT none | ||
| 285 | ; USES ax, flags | ||
| 286 | |||
| 287 | THBA DB '0123456789abcdef' | ||
| 288 | |||
| 289 | PUBLIC THB | ||
| 290 | THB PROC near | ||
| 291 | |||
| 292 | push ax | ||
| 293 | shr al,1 | ||
| 294 | shr al,1 | ||
| 295 | shr al,1 | ||
| 296 | shr al,1 | ||
| 297 | and ax,0fH | ||
| 298 | xchg bx,ax | ||
| 299 | mov bl,CS:THBA[bx] | ||
| 300 | xchg ax,bx | ||
| 301 | call putchar ; put first character | ||
| 302 | pop ax | ||
| 303 | and ax,0fH | ||
| 304 | xchg bx,ax | ||
| 305 | mov bl,CS:THBA[bx] | ||
| 306 | xchg ax,bx | ||
| 307 | call putchar | ||
| 308 | ret | ||
| 309 | |||
| 310 | THB ENDP | ||
| 311 | |||
| 312 | |||
| 313 | |||
| 314 | |||
| 315 | ;** THW - Type Hex Word | ||
| 316 | ; | ||
| 317 | ; THW types a word in hex (via "putchar") | ||
| 318 | ; | ||
| 319 | ; ENTRY (AX) = word | ||
| 320 | ; EXIT none | ||
| 321 | ; USES AX, flags | ||
| 322 | |||
| 323 | PUBLIC THW | ||
| 324 | THW PROC near | ||
| 325 | |||
| 326 | push ax | ||
| 327 | xchg ah,al | ||
| 328 | call THB | ||
| 329 | pop ax | ||
| 330 | call THB | ||
| 331 | ret | ||
| 332 | |||
| 333 | THW ENDP | ||
| 334 | |||
| 335 | |||
| 336 | |||
| 337 | ;** TDW - Type Decimal Word | ||
| 338 | ; | ||
| 339 | ; TDW types (via "putchar") the unsigned decimal representation | ||
| 340 | ; of a 16-bit unsigned integer. Only significant digits are | ||
| 341 | ; printed; if the number is 0 a "0" is printed. | ||
| 342 | ; | ||
| 343 | ; ENTRY (AX) = number | ||
| 344 | ; EXIT none | ||
| 345 | ; USES AX, flags | ||
| 346 | |||
| 347 | PUBLIC TDW | ||
| 348 | TDW PROC near | ||
| 349 | |||
| 350 | push cx ; preserve registers | ||
| 351 | push dx | ||
| 352 | mov cx,10 | ||
| 353 | call tdw$ ; recurse cracking digits | ||
| 354 | pop dx | ||
| 355 | pop cx | ||
| 356 | ret | ||
| 357 | |||
| 358 | TDW ENDP | ||
| 359 | |||
| 360 | |||
| 361 | ;* tdw$ - crack number recursively | ||
| 362 | ; | ||
| 363 | ; tdw$ cracks the least significant decimal digit. If there | ||
| 364 | ; are no higher-significant digits, print and return. | ||
| 365 | ; else, recurse for higher digits | ||
| 366 | ; | ||
| 367 | ; (AX) = value | ||
| 368 | ; (CX) = 10 | ||
| 369 | |||
| 370 | tdw$ PROC NEAR | ||
| 371 | |||
| 372 | sub dx,dx | ||
| 373 | div cx ; (ax) = quotient, (dx) = remainder | ||
| 374 | and ax,ax | ||
| 375 | jz tdw$1 ; this is highest-order, do it | ||
| 376 | push dx | ||
| 377 | call tdw$ | ||
| 378 | pop dx | ||
| 379 | tdw$1: xchg ax,dx | ||
| 380 | add al,'0' | ||
| 381 | call putchar | ||
| 382 | ret | ||
| 383 | |||
| 384 | TDW$ ENDP | ||
| 385 | |||
| 386 | |||
| 387 | |||
| 388 | ;** ATOD - Convert ASCII string to decimal number | ||
| 389 | ; | ||
| 390 | ; ATOD is called to convert an ascii string of digits to a | ||
| 391 | ; decimal number. Digits are converted until we run out of them. | ||
| 392 | ; | ||
| 393 | ; ENTRY (DS:SI) = address of first digit | ||
| 394 | ; EXIT 'C' clear if OK | ||
| 395 | ; (AX) = value | ||
| 396 | ; (SI) updated to first non-digit | ||
| 397 | ; 'C' set if error - no digits, or result >65535 | ||
| 398 | ; (DS:SI) points to error character | ||
| 399 | ; USES AX, SI, FLAGS | ||
| 400 | |||
| 401 | PUBLIC ATOD | ||
| 402 | ATOD PROC near | ||
| 403 | |||
| 404 | push dx | ||
| 405 | push cx ; save registers | ||
| 406 | mov al,[si] | ||
| 407 | sub al,'0' | ||
| 408 | jc atod9 ; error - no digits | ||
| 409 | cmp al,10 | ||
| 410 | cmc | ||
| 411 | jc atod9 ; error - no digits | ||
| 412 | sub ax,ax ; clear accumulator | ||
| 413 | mov cx,10 ; base 10 | ||
| 414 | |||
| 415 | ; crack next digit | ||
| 416 | ; | ||
| 417 | ; (AX) = number accumulated so near | ||
| 418 | ; (CX) = 10 | ||
| 419 | ; (DS:SI) = next character | ||
| 420 | |||
| 421 | atod1: xchg dx,ax ; keep accum in dx for a while | ||
| 422 | lodsb ; (al) = character | ||
| 423 | sub al,'0' | ||
| 424 | jc atod7 ; not digit - all done | ||
| 425 | cmp al,9 | ||
| 426 | ja atod7 ; not digit - all done | ||
| 427 | sub ah,ah ; (ax) = digit value (0 - 9) | ||
| 428 | push ax | ||
| 429 | xchg ax,dx | ||
| 430 | mul cx ; (ax) = 10*accum | ||
| 431 | pop dx ; (dx) = digit to add | ||
| 432 | jo atod8 ; overflow | ||
| 433 | add ax,dx | ||
| 434 | jmp atod1 ; go back for more | ||
| 435 | |||
| 436 | ; Done with number, all OK | ||
| 437 | ; | ||
| 438 | ; (dx) = number | ||
| 439 | ; (ds:si) = address+1 of first unused character | ||
| 440 | |||
| 441 | atod7: clc | ||
| 442 | |||
| 443 | ; Done with number, error | ||
| 444 | ; 'C' set | ||
| 445 | |||
| 446 | atod8: dec si ; backup over non-decimal (or error) char | ||
| 447 | atod9: pop cx | ||
| 448 | xchg ax,dx ; (ax) = number iff no error | ||
| 449 | pop dx ; restore registers | ||
| 450 | ret ; exit | ||
| 451 | |||
| 452 | ATOD ENDP | ||
| 453 | |||
| 454 | ;** putchar - put a character on the console | ||
| 455 | ; | ||
| 456 | ; ENTRY (al) = character | ||
| 457 | ; EXIT none | ||
| 458 | ; USES ax,flags | ||
| 459 | |||
| 460 | |||
| 461 | UR_DAT = 02f8H ; COM1 = 03f8H, COM2 = 02f8H | ||
| 462 | UR_IEN = UR_DAT+1 ; Interrupt enable | ||
| 463 | UR_IER = UR_DAT+2 ; interrupt ID | ||
| 464 | UR_LCR = UR_DAT+3 ; line control registers | ||
| 465 | UR_MCR = UR_DAT+4 ; modem control register | ||
| 466 | UR_LSR = UR_DAT+5 ; line status register | ||
| 467 | UR_MSR = UR_DAT+6 ; modem status regiser | ||
| 468 | UR_DLL = UR_DAT ; divisor latch least sig | ||
| 469 | UR_DLM = UR_DAT+1 ; divisor latch most sig | ||
| 470 | |||
| 471 | iflag DB 0 ; != 0 when initialized 8250 | ||
| 472 | |||
| 473 | ;* inchr - input character | ||
| 474 | ; | ||
| 475 | ; EXIT 'z' set if no character | ||
| 476 | ; 'z' clear if char | ||
| 477 | ; (al) = char | ||
| 478 | |||
| 479 | inchr: mov dx,UR_LSR | ||
| 480 | in al,dx | ||
| 481 | and al,1 | ||
| 482 | jz inchr1 | ||
| 483 | mov dx,UR_DAT | ||
| 484 | in al,dx | ||
| 485 | and al,07fh | ||
| 486 | inchr1: ret | ||
| 487 | |||
| 488 | |||
| 489 | PUBLIC putchar | ||
| 490 | putchar PROC NEAR | ||
| 491 | pushf | ||
| 492 | cli | ||
| 493 | push dx | ||
| 494 | push cx | ||
| 495 | push bx | ||
| 496 | push ax ; (al) = character | ||
| 497 | test iflag,255 | ||
| 498 | jnz putc1 ; is initialized | ||
| 499 | inc iflag | ||
| 500 | |||
| 501 | ; program the usart | ||
| 502 | |||
| 503 | mov dx,UR_LCR | ||
| 504 | mov al,80h | ||
| 505 | out dx,al ; command it | ||
| 506 | sub al,al | ||
| 507 | mov dx,UR_DLM | ||
| 508 | out dx,al | ||
| 509 | mov dx,UR_DLL | ||
| 510 | mov al,12 ; 9600 baud = 12, 19.2 Kbaud = 6 | ||
| 511 | out dx,al | ||
| 512 | mov al,3 | ||
| 513 | mov dx,UR_LCR | ||
| 514 | out dx,al ; command normal mode | ||
| 515 | |||
| 516 | ; see if CTL-Q or CTL-S | ||
| 517 | |||
| 518 | putc1: pushf | ||
| 519 | cli | ||
| 520 | call inchr | ||
| 521 | jz putc3 ; no characters incomming | ||
| 522 | cmp al,19 ; ctl-S? | ||
| 523 | jnz putc3 ; no, ignore | ||
| 524 | |||
| 525 | ; have ctl-s. wait till we see ctl-Q | ||
| 526 | |||
| 527 | putc2: call inchr | ||
| 528 | jz putc2 | ||
| 529 | cmp al,17 | ||
| 530 | jnz putc2 | ||
| 531 | |||
| 532 | putc3: popf | ||
| 533 | mov dx,UR_LSR | ||
| 534 | putc4: in al,dx | ||
| 535 | test al,020h | ||
| 536 | jz putc4 | ||
| 537 | |||
| 538 | ; ready. crank it out! | ||
| 539 | |||
| 540 | mov dx,UR_DAT | ||
| 541 | |||
| 542 | pop ax | ||
| 543 | out dx,al | ||
| 544 | |||
| 545 | pop bx | ||
| 546 | pop cx | ||
| 547 | pop dx | ||
| 548 | popf | ||
| 549 | ret | ||
| 550 | |||
| 551 | putchar ENDP | ||
| 552 | |||
| 553 | ENDIF | ||