home *** CD-ROM | disk | FTP | other *** search
/ Oakland CPM Archive / oakcpm.iso / cpmug / cpmug082.ark / SDNBIOS.ASM < prev    next >
Assembly Source File  |  1984-04-29  |  21KB  |  828 lines

  1.     TITLE    'SDNBIOS - N* SD CP/M 2.2 BIOS OF 06/19/81'
  2. ;
  3. ;  THIS BIOS CONTAINS ROUTINES TO SUPPORT THE
  4. ; FOLLOWING HARDWARE:
  5. ;
  6. ; DISK: NORTH STAR MDC-A4 SINGLE DENSITY 5.25"
  7. ;    FLOPPY DISK UNITS 1 AND 2 AS CP/M DRIVES
  8. ;    A: AND B:
  9. ;
  10. ;  CONSOLE AND LIST ROUTINES ARE LOCATED IN A
  11. ; SEPARATE MODULE LOADED BY THE BOOTSTRAP ROUTINE
  12. ; INTO HIGH MEMORY AT ADDRESS USER. THAT VALUE IS
  13. ; ASSUMED TO BE ON A 1K BOUNDARY, AND THE USER
  14. ; ROUTINES ARE RESTRICTED TO 2 PAGES (SEE BOOTSTRAP
  15. ; INFO BELOW), WITH 2 PAGES OF SCRATCH ABOVE AVAILABLE
  16. ; FOR USE. THIS BIOS USES THE 1ST OF THOSE SCRATCH
  17. ; PAGES FOR BDOS BUFFERS AND ITS OWN VARIABLES.
  18. ;
  19. ;  SINCE THIS BIOS IS SO LARGE, MOVCPM SHOULD BE
  20. ; RUN FOR TWO LESS THAN THE DESIRED SYSTEM SIZE
  21. ; IN K, I.E. SPECIFY 18 FOR A 20K SYSTEM.
  22. ;
  23. ;  ***    IMPORTANT BOOTSTRAP INFORMATION  ***
  24. ;
  25. ;  OUR WARM BOOT EXPECTS CCP TO RESIDE ON TRACK
  26. ; 1, SECTORS 0-7 INCLUSIVE. BDOS MUST BE ON TRACK
  27. ; 1, SECTORS 8-9, THEN CONTINUE ON TRACK 2, SECTORS
  28. ; 0-9, THEN FINISH ON TRACK 0, SECTORS 1 AND 9.
  29. ;
  30. ;  THE BOOTSTRAP BLOCK IS LOADED BY THE CONTROLLER
  31. ; PROM ROUTINES FROM TRACK 0, SECTOR 4 INTO MEMORY
  32. ; AT 2000H. THE BOOTSTRAP ROUTINE WILL THEN LOOK
  33. ; FOR THIS BIOS ON TRACK 0, SECTORS 5-8. THE USER
  34. ; ROUTINES FOR CONSOLE AND LIST ARE STORED ON TRACK
  35. ; 0, SECTORS 2-3. TRACK 0, SECTOR 0 IS RESERVED FOR
  36. ; LIFEBOAT-COMPATIBLE ID AND FUTURE EXPANSION.
  37. ;
  38. ;  DISK OPERATING SYSTEM ADDRESSES
  39. ;
  40. NKSYS    EQU    20        ;SYS SIZE IN K BYTES
  41. KBYTE    EQU    1024        ;1K BYTE SIZE
  42. CPMSZ    EQU    NKSYS*KBYTE    ;TOP SYSTEM ADDRESS
  43. CPMBS    EQU    CPMSZ-(22*KBYTE);CP/M BIAS VALUE
  44. CCP    EQU    CPMBS+3400H    ;ADDRESS OF CCP
  45. BDOS    EQU    CPMBS+3C00H    ;ADDRESS OF BDOS
  46. BIOS    EQU    CPMBS+4A00H    ;ADDRESS OF BIOS
  47. BIOSR    EQU    1F80H-BIOS+200H ;DDT LOAD OFFSET
  48.                 ; (LEAVES ROOM FOR "USER")
  49. USER    EQU    0A000H        ;NON-CONTIGUOUS 1K HIGH RAM
  50. IOBYTE    EQU    0003H        ;CP/M I/O BYTE ADDRESS
  51. TPA    EQU    100H        ;ADDRESS OF TPA
  52. SECSZ    EQU    128        ;BYTES PER SECTOR
  53. HSTSIZ    EQU    256*10        ;BYTES PER N* TRACK
  54. NDRVS    EQU    2        ;# DRIVES IN SYSTEM
  55. ;
  56. CR    EQU    0DH        ;ASCII CARRIAGE RETURN
  57. LF    EQU    0AH        ;ASCII LINE FEED
  58. ;
  59. ;  BDOS CONSTANTS ON ENTRY TO WRITE
  60. ;
  61. WRALL    EQU    0        ;WRITE TO ALLOCATED
  62. WRDIR    EQU    1        ;WRITE TO DIRECTORY
  63. WRUAL    EQU    2        ;WRITE TO UNALLOCATED
  64. ;
  65. ;  NORTH STAR MEMORY MAPPED I/O ADDRESSES
  66. ;
  67. WDATA    EQU    0EA00H        ;WRITE DATA. DATA IS
  68.                 ; LOW 8 ADRESS BITS.
  69. CCMND    EQU    0EB00H        ;CONTROLLER COMMAND
  70. ;
  71. ;  KEYPAD LIGHTS
  72. ;
  73. LHEX    EQU    0DFH        ;LEFT HEX LITES
  74. MHEX    EQU    0DDH        ;MIDDLE HEX LITES
  75. RHEX    EQU    0DBH        ;RIGHT HEX LITES
  76. ;
  77. ;  BIOS JUMP VECTOR TABLE
  78. ;
  79.     ORG    BIOS        ;START OF BIOS CODE
  80. ;
  81.     JMP    COLD        ;COLD BOOT FROM ROM
  82.     JMP    WARM        ;RELOAD CCP/BDOS
  83.     JMP    USER+3        ;GET CONSOLE STATUS
  84.     JMP    USER+6        ;CONSOLE INPUT
  85.     JMP    USER+9        ;CONSOLE OUTPUT
  86.     JMP    USER+12     ;PRINTER OUTPUT
  87.     JMP    USER+15     ;PUNCH OUTPUT
  88.     JMP    USER+18     ;READER INPUT
  89.     JMP    HOME        ;HOME SELECTED DRIVE
  90.     JMP    SELDSK        ;SELECT DISK DRIVE
  91.     JMP    SETTRK        ;SET TRACK NUMBER
  92.     JMP    SETSEC        ;SET SECTOR NUMBER
  93.     JMP    SETDMA        ;SET TRANSFER ADDRESS
  94.     JMP    DISKRD        ;PERFORM DISK READ
  95.     JMP    DISKWR        ;PERFORM DISK WRITE
  96.     JMP    USER+21     ;RETURN LIST STAT
  97.     JMP    SECTRN        ;TRANSLATE SECTOR
  98. ;
  99. MSGOT:    EQU    USER+24        ;MSG OUT ROUTINE
  100. HXBOT:    EQU    USER+27        ;HEX CONVERSION ROUTINE
  101. DISKER:    EQU    USER+30        ;DISK ERROR REPORTER
  102. ;
  103. ;  SELECT DRIVE
  104. ;
  105. SELDSK: LXI    H,0        ;ERROR RETURN CODE
  106.     MOV    A,C        ;PUT DRIVE # IN A
  107.     CPI    NDRVS        ;CHECK IF LEGAL DRIVE
  108.     RNC            ;NO CARRY IF ILLEGAL
  109.     STA    SEKDSK        ;STORE DRIVE NUMBER
  110.     MOV    L,C        ;L = DISK NUMBER
  111.     MVI    H,0        ;ZERO H REG
  112.     DAD    H        ; *2
  113.     DAD    H        ; *4
  114.     DAD    H        ; *8
  115.     DAD    H        ; *16 (SIZE OF HEADER)
  116.     LXI    D,D0DPH     ;DRIVE 0 DPH
  117.     DAD    D        ;HL = DRIVE N DPH
  118.     RET            ;RETURN THAT IN HL
  119. ;
  120. ;  HOME DRIVE
  121. ;
  122. HOME:    MVI    C,0        ;SET TRACK TO ZERO TO HOME
  123.     LDA    HSTWRT        ;CHECK FOR PENDING WRITE
  124.     ORA    A
  125.     JNZ    SETTRK
  126.     STA    HSTACT        ;CLEAR HOST ACTIVE IF NOT
  127. ;
  128. ;  SET TRACK
  129. ;
  130. SETTRK: MOV    A,C        ;MOVE TRACK NUMBER
  131.     STA    SEKTRK        ; THEN SAVE IT
  132.     RET            ;RETURN TO CALLER
  133. ;
  134. ;  SET SECTOR
  135. ;
  136. SETSEC: MOV    A,C        ;MOVE SECTOR NUMBER
  137.     STA    SEKSEC        ; THEN SAVE IT
  138.     RET            ;RETURN TO CALLER
  139. ;
  140. ;  SET TRANSFER ADDRESS
  141. ;
  142. SETDMA: MOV    H,B        ;MOVE ADDR TO HL
  143.     MOV    L,C
  144.     SHLD    DMAADR        ; THEN SAVE IT
  145.     RET            ;RETURN TO CALLER
  146. ;
  147. ;  SECTOR TRANSLATION
  148. ;
  149. SECTRN: MOV    H,B
  150.     MOV    L,C
  151.     INX    H        ;JUST ADD ONE TO SECNUM
  152.     RET            ; THEN DONE
  153. ;
  154. ;  DEBLOCKING DISK READ.  NOTE THAT ON DEBLOCKING READ
  155. ; AND WRITE, THE CALLER SECTOR NUMBERS RANGE FROM 1-XX
  156. ; DECIMAL. THIS IS FOR COMPATIBILITY WITH 8" FORMATS
  157. ; THAT ARE 1-ORIGIN. WE ADJUST FOR THIS THROUGHOUT THE
  158. ; DEBLOCKING ROUTINES BY SUBTRACTING 1 FROM SEKSEC
  159. ; BEFORE WE USE IT.
  160. ;
  161. ;  TRACK BUFFERING IS DONE HERE. A HOST BLOCK IS
  162. ; CONSIDERED THE ENTIRE HOST TRACK.
  163. ;
  164. DISKRD: XRA    A        ;END OF UNALLOC SECTORS
  165.     STA    UNACNT        ; AFTER READ
  166.     INR    A
  167.     STA    READOP        ;READ OPERATION
  168.     STA    RSFLAG        ;MUST READ DATA
  169.     MVI    A,WRUAL
  170.     STA    WRTYPE        ;TREAT AS UNALLOC
  171.     JMP    RWOPER        ;TO PERFORM THE READ
  172. ;
  173. ;  DEBLOCKING DISK WRITE
  174. ;
  175. DISKWR: XRA    A
  176.     STA    READOP        ;NOT A READ OPERATION
  177.     MOV    A,C        ;WRITE TYPE IN C
  178.     STA    WRTYPE
  179.     CPI    WRUAL        ;WRITE UNALLOCATED?
  180.     JNZ    CHKUNA        ;CHECK FOR UNALLOC
  181. ;
  182. ;  WRITE TO UNALLOCATED, SET PARAMETERS
  183. ;
  184.     LDA    BLKMSK        ;NEXT UNALLOC RECS
  185.     INR    A
  186.     STA    UNACNT
  187.     LDA    SEKDSK        ;DISK TO SEEK
  188.     STA    UNADSK        ;UNADSK = SEKDSK
  189.     LDA    SEKTRK
  190.     STA    UNATRK        ;UNATRK = SEKTRK
  191.     LDA    SEKSEC
  192.     STA    UNASEC        ;UNASEC = SEKSEC
  193. ;
  194. ;  CHECK FOR WRITE TO UNALLOCATED SECTOR
  195. ;
  196. CHKUNA: LDA    UNACNT        ;ANY UNALLOC REMAIN?
  197.     ORA    A
  198.     JZ    ALLOC        ;SKIP IF NOT
  199. ;
  200. ;  MORE UNALLOCATED RECORDS REMAIN
  201. ;
  202.     DCR    A        ;UNACNT = UNACNT - 1
  203.     STA    UNACNT
  204.     LDA    SEKDSK        ;SAME DISK?
  205.     LXI    H,UNADSK
  206.     CMP    M        ;SEKDSK = UNADSK?
  207.     JNZ    ALLOC        ;SKIP IF NOT
  208. ;
  209. ;  DISKS ARE THE SAME, CHECK TRACKS
  210. ;
  211.     LDA    SEKTRK
  212.     LXI    H,UNATRK
  213.     CMP    M        ;SEKTRK = UNATRK?
  214.     JNZ    ALLOC        ;SKIP IF NOT
  215. ;
  216. ;  TRACKS ARE THE SAME, CHECK SECTORS
  217. ;
  218.     LDA    SEKSEC
  219.     LXI    H,UNASEC
  220.     CMP    M        ;SEKSEC = UNASEC?
  221.     JNZ    ALLOC        ;SKIP IF NOT
  222. ;
  223. ;  MATCH, MOVE TO NEXT SECTOR FOR FUTURE REF
  224. ;
  225.     INR    M        ;UNASEC = UNASEC+1
  226.     LDA    DPBNSS        ;CHECK FOR END OF TRACK
  227.     CMP    M
  228.     JNC    NOOVF        ;SKIP IF STILL ON TRACK
  229. ;
  230. ;  OVERFLOW TO NEXT TRACK
  231. ;
  232.     MVI    M,1        ;UNASEC = 1
  233.     LXI    H,UNATRK
  234.     INR    M        ;UNATRK = UNATRK+1
  235. ;
  236. ;  MATCH FOUND, MARK AS UNNECESSARY READ
  237. ;
  238. NOOVF:    XRA    A
  239.     STA    RSFLAG        ;RSFLAG = 0
  240.     JMP    RWOPER        ;GO DO WRITE
  241. ;
  242. ;  NOT AN UNALLOCATED RECORD, REQUIRES PRE-READ
  243. ;
  244. ALLOC:    XRA    A
  245.     STA    UNACNT        ;UNACNT = 0
  246.     INR    A
  247.     STA    RSFLAG        ;RSFLAG = 1
  248. ;
  249. ;  COMMON CODE FOR READ AND WRITE FOLLOWS
  250. ;
  251. RWOPER: XRA    A
  252.     STA    ERFLAG        ;NO ERRORS (YET)
  253. ;
  254. ;  ACTIVE HOST TRACK?
  255. ;
  256.     LXI    H,HSTACT    ;HOST ACTIVE FLAG
  257.     MOV    A,M
  258.     MVI    M,1        ;ALWAYS BECOMES 1
  259.     ORA    A        ;WAS IT ALREADY?
  260.     JZ    FILHST        ;FILL HOST IF NOT
  261. ;
  262. ;  HOST BUFFER ACTIVE, SAME AS SEEK BUFFER?
  263. ;
  264.     LDA    SEKDSK
  265.     LXI    H,HSTDSK    ;SAME DISK?
  266.     CMP    M        ;SEKDSK = HSTDSK?
  267.     JNZ    NOMATCH
  268. ;
  269. ;  SAME DISK, CHECK TRACK
  270. ;
  271.     LDA    SEKTRK
  272.     LXI    H,HSTTRK
  273.     CMP    M        ;SEKTRK = HSTTRK?
  274.     JZ    MATCH        ;SKIP IF MATCH
  275. ;
  276. ;  MUST FLUSH HOST BUFFER FOR NEW TRACK
  277. ;
  278. NOMATCH: LDA    HSTWRT        ;HOST WRITTEN?
  279.     ORA    A
  280.     CNZ    WRITEHST    ;CLEAR HOST BUFFER
  281.     LDA    ERFLAG        ;CHECK FOR ERROR
  282.     ORA    A
  283.     RNZ            ;RETURN ERROR IF SO
  284. ;
  285. FILHST: LDA    SEKDSK        ;MAY HAVE TO FILL HOST BUFFER
  286.     STA    HSTDSK
  287.     LDA    SEKTRK
  288.     STA    HSTTRK
  289.     XRA    A
  290.     STA    HSTWRT        ;NO PENDING WRITE
  291.     LDA    RSFLAG        ;NEED TO READ?
  292.     ORA    A
  293.     JZ    MATCH        ;NO IF FLAG ZERO
  294.     CALL    READHST     ;READ HOST
  295.     LDA    ERFLAG        ;CHECK FOR ERRORS
  296.     ORA    A
  297.     RNZ            ;NO MORE IF SO
  298. ;
  299. ;  COPY DATA TO OR FROM BUFFER
  300. ;
  301. MATCH:    LDA    SEKSEC        ;GET SECTOR NUMBER
  302.     DCR    A        ;ADJUST FOR 1-ORIGIN
  303.     RAR            ;GET VALUE SHIFTED
  304.     MOV    H,A        ; LEFT 7 IN HL
  305.     MVI    A,0
  306.     RAR
  307.     MOV    L,A
  308. ;
  309. ;  HL CONTAINS RELATIVE HOST BUFFER ADDRESS
  310. ;
  311.     LXI    D,HSTBUF    ;PT TO TRACK BUFFER
  312.     DAD    D        ;HL = HOST ADDRESS
  313.     XCHG            ;NOW IN DE
  314.     LHLD    DMAADR        ;GET/PUT CP/M DATA
  315.     MVI    C,SECSZ     ;LENGTH OF MOVE
  316.     LDA    READOP        ;WHICH WAY?
  317.     ORA    A
  318.     JNZ    RWMOVE        ;SKIP IF READ
  319. ;
  320. ;  WRITE OPERATION, MARK AND SWITCH DIRECTION
  321. ;
  322.     INR    A        ;ACC KNOWN ZERO ABOVE
  323.     STA    HSTWRT        ;HSTWRT = 1
  324.     XCHG            ;SOURCE/DEST SWAP
  325. ;
  326. RWMOVE: LDAX    D        ;SOURCE CHARACTER
  327.     INX    D
  328.     MOV    M,A        ;TO DEST
  329.     INX    H
  330.     DCR    C        ;LOOP 128 TIMES
  331.     JNZ    RWMOVE
  332. ;
  333. ;  DATA HAS BEEN MOVED TO/FROM HOST BUFFER
  334. ;
  335.     LDA    WRTYPE        ;WRITE TYPE
  336.     CPI    WRDIR        ;TO DIRECTORY?
  337.     MVI    A,0        ;NO ERROR AT THIS PT
  338.     RNZ            ;RET IF NOT DIR WRITE
  339. ;
  340. ;  CLEAR HOST BUFFER FOR DIRECTORY WRITE
  341. ;
  342.     CALL    WRITEHST
  343.     LDA    ERFLAG
  344.     RET
  345. ;
  346. ;  WRITEHST PERFORMS THE PHYSICAL WRITE TO THE
  347. ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
  348. ; AND TRACK IS IN HSTTRK. ON EXIT, ERROR FLAG
  349. ; IS IN ERFLAG (ZERO IF NONE).
  350. ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
  351. ;
  352. ;  IT IS ASSUMED INTERRUPTS ARE DISABLED AT
  353. ; THIS POINT. IF NOT, I/O MAY BE DISRUPTED.
  354. ;
  355. WRITEHST:            ;WRITE HOST
  356.     XRA    A        ;BUFFER WILL BE CLEARED
  357.     STA    HSTWRT
  358.     STA    ERSEC        ;NO SECTOR IN ERROR YET
  359.     CALL    SETUP        ;SELECT DRIVE, SEEK, AND
  360.                 ; POSITION TO SECTOR ZERO
  361.     RNZ            ;SECTOR NOT FOUND IS FATAL
  362.     LHLD    HSTADR        ;GET ADDRESS TO WRITE FROM
  363.     MVI    A,10        ;INIT # BLKS TO WRITE
  364. ;
  365. ;  HERE TO WRITE NEXT SECTOR. WRITE-PROTECT CHECK IS
  366. ; DONE EVERY SECTOR TO HELP KILL TIME.
  367. ;
  368. WRIT5:    PUSH    PSW        ;SAVE # BLKS LEFT
  369.     LDA    CCMND+10H    ;GET A-STATUS
  370.     ANI    02H        ;IS DISK WRITE-PROTECTED?
  371.     MVI    A,6        ;ASSUME SO, ERROR CODE 6
  372.     JNZ    WPERR        ;WRITE ALWAYS FAILS IF SO
  373.     LDA    CCMND+04H    ;INITIATE SECTOR WRITE
  374. ;
  375. WRIT10: LDA    CCMND+10H    ;GET A-STATUS
  376.     ANI    08H        ;MUST LOOP UNTIL 96 USEC WINDOW
  377.     JZ    WRIT10        ; PAST, SO LOOP UNTIL WRT TRUE
  378. ;
  379. ;  NOW WRITE THE 15 BYTES OF LEADING ZEROES ON THE SECTOR
  380. ;
  381.     LXI    B,15        ;GET ZERO IN C-REG, AND
  382.                 ; LOAD CNT IN B-REG
  383. ;
  384. WRIT15: MOV    E,B        ;KILL TIME AND GET ZERO IN E-REG
  385.     MVI    D,WDATA SHR 8    ;KILL TIME BY LOADING D FOR LATER
  386.     LDAX    D        ;WRITE A ZERO BYTE
  387.     MOV    A,M        ;KILL MORE TIME
  388.     DCR    C        ;COUNT OFF A ZERO BYTE
  389.     JNZ    WRIT15        ;DO THEM ALL
  390. ;
  391. ;  FOLLOW WITH SYNCH BYTE
  392. ;
  393.     MOV    E,A        ;KILL TIME
  394.     MVI    E,0FBH        ;THIS IS THE SYNCH BYTE VALUE
  395.     LDAX    D        ;WRITE OUT SYNCH BYTE
  396.     MOV    A,M        ;KILL TIME
  397.     MOV    A,M
  398. ;
  399. ;  NOW WRITE OUT 256 BYTES. B IS ZERO FROM ABOVE TO INIT
  400. ; THE CRC BYTE. C IS ZERO FROM COUNTING OUT ABOVE TO INIT
  401. ; 256-BYTE COUNTER FOR HERE.
  402. ;
  403. WRIT20: MOV    A,M        ;GET NEXT BYTE TO OUTPUT
  404.     MOV    E,A        ; IN OUTPUT REG
  405.     XRA    B        ;ADD INTO CHECKSUM
  406.     RLC
  407.     MOV    B,A        ;LEAVE CHECKSUM IN B
  408.     LDAX    D        ;WRITE DATA BYTE TO DISK
  409.     INX    H        ;BOP BUF PTR
  410.     DCR    C        ;COUNT OFF LAST BYTE
  411.     JNZ    WRIT20        ;GO BACK IF MORE TO WRITE
  412.     MOV    E,B        ;IF NOT, TIME TO WRITE CHECKSUM
  413.     MOV    E,B        ;KILL TIME
  414.     INX    B        ;KILL MORE TIME
  415.     LDAX    D        ; THEN WRITE THE BYTE
  416.     CALL    WAIT1S        ;WAIT FOR NEXT SECTOR
  417.     POP    PSW        ;GET COUNT OFF STACK
  418.     DCR    A        ;COUNT OFF LAST SECTOR
  419.     JNZ    WRIT5        ;GO BACK IF MORE TO WRITE
  420.     STA    ERFLAG        ;FLAG NO ERRORS
  421.     RET            ; THEN RETURN TO CALLER
  422. ;
  423. WPERR:    STA    ERFLAG        ;STORE ERROR CODE
  424.     POP    PSW        ;CLEAN OFF STACK
  425.     LXI    H,WPEMSG    ;WRITE PROTECT ERROR
  426. ;
  427. DSKERR:    XCHG
  428.     LHLD    HSTDSK        ;PICK UP DISK AND TRACK
  429.     XCHG            ;LEAVE IN DE
  430.     LDA    ERSEC        ;GET SECTOR IN ERROR
  431.     JMP    DISKER        ;GO REPORT
  432. ;
  433. ;  READHST PERFORMS THE PHYSICAL READ FROM THE
  434. ; NORTH STAR DISK. ON ENTRY, DRIVE IS IN HSTDSK,
  435. ; TRACK IS IN HSTTRK, SECTOR IS IN HSTSEC. ON
  436. ; EXIT, ERROR FLAG IS IN ERFLAG (ZERO IF NONE).
  437. ;
  438. ;  ***    INTERRUPTS MUST BE DISABLED HERE  ***
  439. ;
  440. READHST:
  441.     MVI    A,10        ;RETRY COUNT ON ERROR
  442.     STA    RTCNT
  443. ;
  444. READRT: CALL    SETUP        ;SELECT DRIVE, SEEK, AND
  445.                 ; POSITION TO SECTOR ZERO
  446.     RNZ            ;SECTOR NOT FOUND IS FATAL
  447.     XRA    A
  448.     STA    ERFLAG        ;NO ERRORS YET
  449.     LHLD    HSTADR        ;READ INTO HERE
  450.     MVI    A,10        ;INIT # BLKS TO READ
  451. ;
  452. ;  HERE TO READ NEXT SECTOR. START BY LOOKING FOR
  453. ; SYNCH BYTE.
  454. ;
  455. RNEXTS:    PUSH    PSW        ;SAVE # BLKS LEFT TO READ
  456.     MVI    B,08CH        ;COUNT FOR SYNC CHAR LOOP
  457.     LXI    D,CCMND+50H    ;SET UP READ DATA REGS
  458.     MVI    C,0        ;LOAD COUNT OF 256 FOR READ
  459. ;
  460. ;  NOW WAIT FOR SYNC CHAR DETECTED. ERROR IF WE HAVE TO
  461. ; WAIT TOO LONG.
  462. ;
  463. READ5:    LDA    CCMND+10H    ;GET A-STATUS
  464.     ANI    04H        ;SYNCH CHAR DETECTED?
  465.     JNZ    READ15        ;OUT IF GOT IT
  466.     DCR    B        ;COUNT DOWN IF NOT
  467.     JNZ    READ5        ;GO BACK IF STILL OK
  468.     MVI    A,1        ;SYNC ERROR IF WAITED TOO LONG
  469.     LXI    H,SYEMSG    ;SYNC ERROR MESSAGE
  470. ;
  471. RERR:    STA    ERFLAG        ;STORE ERROR CODE
  472.     POP    B        ;GET BLK CNT IN B
  473.     MVI    A,10
  474.     SUB    B        ;CALC SECTOR # IN ERROR
  475.     STA    ERSEC        ;SAVE FOR REPORTING
  476.     LDA    RTCNT        ;COUNT OFF A RETRY
  477.     DCR    A
  478.     STA    RTCNT
  479.     JNZ    READRT        ;IF COUNT LEFT, GO RETRY
  480. ;
  481. ;  READ ERROR RETRIES FAILED. FLAG ERROR.
  482. ;
  483. FRERR:    JMP    DSKERR        ;TELL OPERATOR OF ERROR THEN OUT
  484. ;
  485. ;  READ THE DATA INTO HSTBUF
  486. ;
  487. READ15:    MOV    B,C        ;INIT CHECKSUM FROM ZERO IN C
  488. ;
  489. READ20: LDAX    D        ;READ NEXT DATA BYTE
  490.     MOV    M,A        ; AND PUT IT IN BUFFER
  491.     XRA    B        ;ADD TO CHECKSUM
  492.     RLC
  493.     MOV    B,A
  494.     INX    H        ;BOP BUFFER PTR
  495.     DCR    C        ;COUNT OFF LAST BYTE
  496.     JNZ    READ20        ;GO BACK IF MORE TO DO
  497.     LDAX    D        ; ELSE READ CRC BYTE
  498.     XRA    B        ; AND CHECK IT AGAINST OURS
  499.     JZ    READ25        ;GO ON IF READ OK
  500.     MVI    A,2        ;IF NOT, FLAG CHECKSUM ERROR
  501.     LXI    H,RERMSG    ;MESSAGE IF NEEDED
  502.     JMP    RERR        ;GO MAYBE RETRY
  503. ;
  504. READ25:    CALL    WAIT1S        ;WAIT FOR NEXT SECTOR
  505.     POP    PSW        ;GET # BLKS LEFT
  506.     DCR    A        ;COUNT ONE OFF
  507.     JNZ    RNEXTS        ;GO BACK IF MORE
  508.     STA    ERFLAG        ;IF DONE, FLAG NO ERROR
  509.     RET            ; THEN RETURN TO CALLER
  510. ;
  511. ;  SETUP SELECTS THE UNIT CORRESPONDING TO HSTDSK,
  512. ; THEN SEEKS TO THE TRACK SPECIFIED BY HSTTRK.
  513. ; ON RETURN, ERFLAG CONTAINS A NON-ZERO VALUE IF
  514. ; AN ERROR WAS DETECTED. ONLY UNITS 1 AND 2 ARE
  515. ; SUPPORTED TO SAVE CODE.
  516. ;
  517. SETUP:    LDA    HSTDSK        ;WANT THIS DISK
  518.     INR    A        ;REMAP TO CONTROLLER MASK
  519.     MOV    C,A        ;SAVE IN REG C
  520.     LDA    CCMND+90H    ;KICK MOTORS AND GET A-STATUS
  521.     ANI    10H        ;ARE MOTORS ALREADY ON?
  522.     JNZ    SET5        ;BRANCH IF SO
  523.     MVI    D,50        ;WAIT 1 SECOND FOR MOTORS TO
  524.     CALL    SCWAIT        ; COME UP TO SPEED IF NOT
  525.     JMP    SET10        ; THEN GO SELECT DRIVE
  526. ;
  527. SET5:    LDA    CURDSK        ;IS THIS THE CURRENT DISK?
  528.     CMP    C
  529.     JZ    SET20        ;GO SEEK TO TRACK IF SO
  530. ;
  531. ;  MUST SELECT NEW DISK
  532. ;
  533. SET10:    MOV    A,C
  534.     STA    CURDSK        ;NEW CURRENT DISK
  535.     MVI    B,CCMND SHR 8    ;SET UP FOR SELECT
  536.     LDAX    B        ; AND DO IT
  537.     MVI    D,13        ;WAIT 13 SECTOR TIMES AFTERWARDS
  538.     CALL    SCWAIT
  539. ;
  540. ;  SEEK TO TRACK SPECIFIED BY HSTTRK NOW.
  541. ;
  542. SET20:    LDA    HSTDSK        ;GET NSTRK INDEX
  543.     MOV    C,A
  544.     MVI    B,0
  545.     LXI    H,NSTRK     ;PT AT TABLE
  546.     DAD    B        ; THEN AT CORRECT ENTRY
  547.     MOV    A,M        ;GET CURRENT TRACK
  548.     XRI    59H        ;WAS DISK EVER ACCESSED?
  549.     PUSH    H        ;SAVE TABLE PTR
  550.     CZ    SEEK        ;HOME DISK IF 1ST SEEK
  551.     POP    H        ;RESTORE TABLE PTR
  552.     LDA    HSTTRK        ;GET DESIRED TRACK #
  553.     CALL    SEEK        ;SEEK TO HSTTRK
  554. ;
  555. ;  HERE TO POSITION TO SECTOR ZERO WITHIN THE
  556. ; CURRENT TRACK. ERROR IS RETURNED BY NON-ZERO
  557. ; IF WE CAN'T FIND THE SECTOR AFTER 30 TRIES.
  558. ;
  559.     MVI    B,30        ;LOOK AT THIS MANY SECTORS
  560. ;
  561. POSEC:    CALL    WAIT1S        ;WAIT FOR NEXT SECTOR
  562.     LDA    CCMND+030H    ;GET B-STATUS WITH SECTOR #
  563.     ANI    0FH        ;STRIP NON-SECTOR BITS
  564.     RZ            ;OUT IF GOT SECTOR ZERO
  565.     DCR    B        ;COUNT OFF IF DIDN'T
  566.     JNZ    POSEC        ;GO BACK IF NOT GIVING UP
  567.     MVI    A,1
  568.     STA    ERFLAG        ;SET ERROR FLAG
  569.     LXI    H,SNFMSG
  570.     CALL    DSKERR        ;REPORT ERROR
  571.     XRA    A
  572.     INR    A
  573.     RET            ;RETURN NON-ZERO TO CALLER
  574. ;
  575. ;  SEEK TO TRACK SPECIFIED BY ACC. CURRENT PTR INTO
  576. ; NSTRK TABLE IS IN HL.
  577. ;
  578. SEEK:    MVI    D,LHEX
  579.     MOV    E,A
  580.     STAX    D        ;DISPLAY TARGET TRK #
  581.     MVI    D,MHEX
  582.     MOV    E,M
  583.     STAX    D        ;DISPLAY SOURCE TRK #
  584.     MOV    C,A        ;SAVE TARGET # IN C
  585.     SUB    M        ;SEE HOW FAR AWAY WE ARE
  586.                 ; FROM TARGET TRACK
  587.     MOV    M,C        ; BUT ALWAYS SET NEW TRACK
  588.     MVI    D,RHEX
  589.     MOV    E,A
  590.     STAX    D        ;DISPLAY DIFF
  591.     RZ            ;IF THERE, DONE
  592.     LXI    H,CCMND+1DH    ;ASSUME STEPPING IN
  593.     MOV    C,A        ;SAVE STEP COUNT
  594.     JP    STEPIN        ;BRANCH IF RIGHT
  595.     CMA            ;IF WRONG, NEGATE COUNT
  596.     INR    A
  597.     MOV    C,A        ; THEN SAVE THAT
  598.     MOV    E,A
  599.     STAX    D        ;SHOW CORRECTED COUNT
  600.     LDA    CCMND+10H    ;GET A-STATUS
  601.     ANI    01H        ;ARE WE ON TRACK ZERO?
  602.     RNZ            ;MUST BE DONE IF SO
  603.     LXI    H,CCMND+1CH    ;IF NOT, STEPPING OUT
  604. ;
  605. STEPIN: MOV    A,M        ;SET STEP DIRECTION
  606. ;
  607. STEP:    LDA    CCMND+09H    ;SET STEP FLIP-FLOP
  608.     XTHL            ;DELAY AT LEAST 10 USEC
  609.     XTHL
  610.     LDA    CCMND+08H    ; THEN RESET FLIP-FLOP TO PULSE
  611.     MVI    D,2        ;NOW WAIT TWO SECTOR TIMES
  612.     CALL    SCWAIT        ; WHILE HEAD MOVES (40 MSEC)
  613.     LDA    CCMND+10H    ;GET A-STATUS
  614.     ANI    01H        ;ARE WE AT TRACK ZERO?
  615.     JZ    STEP5        ;PASS IF NOT
  616.     MVI    C,1        ;LAST STEP IF SO
  617. ;
  618. STEP5:    DCR    C        ;COUNT OFF LAST TRACK
  619.     JNZ    STEPIN        ;GO BACK IF MORE TO DO
  620.     RET            ; ELSE RETURN TO CALLER
  621. ;
  622. ;  SECTOR WAIT. ON ENTRY, # SECTORS TO WAIT IS IN D.
  623. ; ON EXIT, D=0 AND ACC=GARBAGE. CALL WAIT1S TO WAIT
  624. ; ONE SECTOR TIME.
  625. ;
  626. WAIT1S: MVI    D,1        ;WAIT ONE SECTOR TIME
  627. ;
  628. SCWAIT: LDA    CCMND+14H    ;RESET SECTOR FLAG
  629. SCW5:    LDA    CCMND+90H    ;GET A-STATUS AND KICK MOTORS
  630.     ANI    80H        ;CHECK SECTOR FLAG
  631.     JZ    SCW5        ;WAIT FOR IT IF NOT UP
  632.     DCR    D        ;COUNT DOWN WAIT COUNTER
  633.     RZ            ;RETURN IF DONE COUNTING
  634.     JMP    SCWAIT        ; ELSE GO COUNT MORE
  635. ;
  636. ;  BLOCK - BLOCK MOVE  (Z80 LDIR REGISTER USAGE)
  637. ;
  638. BLOCK:    MOV    A,M        ;GET BYTE
  639.     STAX    D        ;STORE IT
  640.     INX    H        ;BOP PTRS
  641.     INX    D
  642.     DCX    B        ;COUNT OFF BYTE
  643.     MOV    A,B        ;CHECK FOR DONE
  644.     ORA    C
  645.     JNZ    BLOCK        ;GO BACK IF NOT
  646.     RET
  647.  
  648.  
  649. ;
  650. ;  COLD BOOT ENTRY. SET UP FIRST-TIME BIOS STUFF.
  651. ;
  652. COLD:    LXI    SP,80H        ;SET SP TO SCRATCH AREA
  653.     LXI    H,CCP        ;WHERE TO START CP/M
  654.     PUSH    H
  655.     JMP    CPMLD        ;GO LOAD CCP/BDOS
  656. ;
  657. ;  WARM BOOT ENTRY. LOAD CCP/BDOS AND INITIALIZE
  658. ;
  659. WARM:    LDA    4        ;GET CURRENT DEFAULT DISK
  660.     MOV    B,A        ;SAVE IT
  661.     ANI    0F0H        ;GET USER #
  662.     MOV    C,A        ;SAVE THAT
  663.     MOV    A,B
  664.     ANI    00FH        ;ISOLATE DISK #
  665.     CPI    NDRVS        ;IS IT LEGAL?
  666.     JC    WRMOK        ;GO ON IF SO
  667.     XRA    A        ;BACK TO DRIVE ZERO IF NOT
  668.     MOV    C,A        ;USER # PROB BAD TOO
  669. WRMOK:    ORA    C        ;COMBINE WITH USER #
  670.     STA    DFIMG        ;PUT TO BASE PAGE IMAGE
  671.     LXI    SP,80H        ;SET SP TO SCRATCH RAM
  672.     LXI    H,CCP+3     ;CP/M WARM START ADDR
  673.     PUSH    H
  674. ;
  675. ;  MERGE HERE FROM COLD BOOT
  676. ;
  677. CPMLD:    LDA    IOBYTE        ;GET CURRENT IOBYTE
  678.     STA    IOIMG        ; INTO BASE PAGE IMAGE
  679.     LXI    B,8        ;MOVE ZERO PAGE STUFF
  680.     LXI    D,0        ; DOWN TO ZERO
  681.     LXI    H,BSIMG
  682.     CALL    BLOCK
  683.     LXI    H,05959H    ;FORCE HOME OF DRIVES
  684.     SHLD    NSTRK        ; A, B
  685.     MOV    A,H        ;MAKE SURE NEW DISK SELECTED
  686.     STA    CURDSK
  687.     XRA    A        ;DRIVE ZERO VALUE
  688.     STA    HSTDSK
  689.     STA    HSTACT        ;HOST BUFFER INACTIVE
  690.     STA    HSTWRT        ;NO HOST WRITE PENDING
  691.     STA    UNACNT        ;CLEAR UNALLOC COUNT
  692.     LXI    H,CCP        ;CP/M CCP ADDRESS
  693.     SHLD    HSTADR        ;READ INTO THERE
  694.     INR    A        ;GET 1 IN ACC
  695.     STA    HSTTRK        ;READ FROM TRACK ONE
  696.     CALL    WRMRD        ; RIGHT INTO MEMORY
  697.     LXI    H,CCP+HSTSIZ    ;NEXT CHUNK
  698.     SHLD    HSTADR
  699.     MVI    A,2        ; OFF OF TRACK TWO
  700.     STA    HSTTRK
  701.     CALL    WRMRD        ;READ IT
  702.     LXI    H,HSTBUF    ;NOW READ AND WRITE
  703.     SHLD    HSTADR        ; USING DEBLOCK BUFFER
  704.     XRA    A        ;READING TRACK ZERO
  705.     STA    HSTTRK
  706.     CALL    WRMRD        ;READ IT
  707.     LXI    H,HSTBUF+256    ;MOVE A SECTOR OF BDOS
  708.     LXI    D,CCP+(HSTSIZ*2); TO HERE
  709.     LXI    B,256
  710.     CALL    BLOCK
  711.     LXI    H,HSTBUF+(256*9);LAST BDOS SECTOR
  712.     LXI    D,CCP+(HSTSIZ*2)+256
  713.     LXI    B,256
  714.     CALL    BLOCK
  715.     LDA    DFIMG        ;RETRIEVE LAST USED DRIVE
  716.     MOV    C,A        ; FOR BDOS
  717.     RET            ; THEN GO TO CP/M
  718. ;
  719. WRMRD:    CALL    READHST     ;READ HOST TRACK
  720.     LDA    ERFLAG        ;CHECK FOR ERROR
  721.     ORA    A
  722.     RZ            ;RETURN IF NONE
  723.     LXI    H,MSGLE     ;GET ERROR MESSAGE
  724.     CALL    MSGOT        ;TYPE IT
  725.     HLT            ; THEN GIVE UP
  726. ;
  727. ;  DISK ERROR MESSAGES
  728. ;
  729. WPEMSG: DB    'Protec','t'+80H
  730. RERMSG: DB    'CR','C'+80H
  731. SNFMSG: DB    'Secto','r'+80H
  732. SYEMSG: DB    'Syn','c'+80H
  733. ;
  734. MSGLE:    DB    CR,LF,'Boot er','r'+80H
  735. ;
  736. ;  NORTH STAR SD DISK PARAMETER BLOCK
  737. ;
  738. DPBNSS: DW    20    ;SECTORS PER TRACK
  739.     DB    3    ;BLOCK SHIFT FACTOR
  740. BLKMSK: DB    07H    ;BLOCK MASK
  741.     DB    0    ;NULL MASK
  742.     DW    80-1    ;DISK SIZE - 1
  743.     DW    63    ;DIRECTORY MAX
  744.     DB    11000000B ;ALLOC 0
  745.     DB    0    ;ALLOC 1
  746.     DW    16    ;CHECK SIZE
  747.     DW    3    ;TRACK OFFSET
  748. ;
  749. ;  DRIVE PARAMETER HEADER AREA
  750. ;
  751. D0DPH:    DW    0    ;SECTOR TRAN TBL (NONE)
  752.     DW    0    ;SCRATCH
  753.     DW    0    ;SCRATCH
  754.     DW    0    ;SCRATCH
  755.     DW    DIRBF    ;DIRECTORY BUFFER
  756.     DW    DPBNSS    ;DRIVE PARAM BLK
  757.     DW    D0CHK    ;DRIVE CHANGE BLK
  758.     DW    D0ALL    ;DRIVE ALLOCATION
  759. ;
  760. D1DPH:    DW    0,0,0,0,DIRBF,DPBNSS,D1CHK,D1ALL
  761. ;
  762. ;  ZERO PAGE IMAGE -- BLOCK MOVED TO BASE PAGE
  763. ;
  764. BSIMG:    JMP    BIOS+03H    ;WARM BOOT VECTOR
  765. IOIMG:    DS    1        ;IOBYTE SET BY CPMLD
  766. DFIMG:    DB    0        ;DEFAULT DISK -- ZERO
  767.                 ; AFTER COLD BOOT
  768.     JMP    BDOS+06H    ;BDOS CALL VECTOR
  769. ;
  770. LASTG    EQU    $-1        ;LAST GENNED-IN BYTE
  771. ;
  772. ;  BDOS DIRECTORY BUFFER
  773. ;
  774. DIRBF:    EQU    USER+200H    ;ALLOCATED ABOVE USER ROUTINES
  775. ;
  776. ;  SCRATCH RAM FOR BDOS
  777. ;
  778. D0ALL:    EQU    DIRBF+SECSZ    ;A: ALLOCATION BUF
  779. D0CHK:    EQU    D0ALL+12    ;A: CHECK BUF
  780. D1ALL:    EQU    D0CHK+16    ;B: ALLOCATION BUF
  781. D1CHK:    EQU    D1ALL+12    ;B: CHECK BUF
  782. ;
  783. ;  BIOS VARIABLE STORAGE
  784. ;
  785. SEKDSK: EQU    D1CHK+16    ;DRIVE NUMBER
  786. SEKTRK: EQU    SEKDSK+1    ;TRACK NUMBER
  787. SEKSEC: EQU    SEKTRK+1    ;SECTOR NUMBER
  788. CURDSK: EQU    SEKSEC+1    ;CURRENT ACTIVE DISK,
  789.                 ; GENNED-IN FORCE SELECT
  790. ERSEC:    EQU    CURDSK+1    ;SECTOR IN ERROR
  791. HSTADR: EQU    ERSEC+1     ;HOST BUFFER ADDRESS, NORMALLY
  792.                 ; PTS TO HSTBUF UNLESS BOOTING
  793. ;
  794. ;  HSTDSK MUST BE IMMEDIATELY FOLLOWED BY HSTTRK
  795. ; FOR ERROR REPORTING, SO THEY CAN BE LOADED WITH
  796. ; A SINGLE LHLD.
  797. ;
  798. HSTDSK: EQU    HSTADR+2    ;HOST DISK NUMBER
  799. HSTTRK: EQU    HSTDSK+1    ;HOST TRACK NUMBER
  800. HSTACT: EQU    HSTTRK+1    ;HOST ACTIVE FLAG
  801. HSTWRT: EQU    HSTACT+1    ;HOST WRITTEN FLAG
  802. ERFLAG: EQU    HSTWRT+1    ;ERROR REPORTING
  803. RTCNT:    EQU    ERFLAG+1    ;ERROR RETRY COUNTER
  804. RSFLAG: EQU    RTCNT+1     ;READ SECTOR FLAG
  805. READOP: EQU    RSFLAG+1    ;1 IF READ OPERATION
  806. WRTYPE: EQU    READOP+1    ;WRITE OPERATION TYPE
  807. DMAADR: EQU    WRTYPE+1    ;LAST DMA ADDRESS
  808. ;
  809. UNACNT: EQU    DMAADR+2    ;UNALLOC REC CNT
  810. UNADSK: EQU    UNACNT+1    ;LAST UNALLOC DISK
  811. UNATRK: EQU    UNADSK+1    ;LAST UNALLOC TRACK
  812. UNASEC: EQU    UNATRK+1    ;LAST UNALLOC SECTOR
  813. ;
  814. ;  NORTH STAR CURRENT TRACK TABLE
  815. ;
  816. NSTRK:    EQU    UNASEC+1    ;NO CURRENT TRACK YET
  817. NSTRK1:    EQU    NSTRK+1     ;EACH ENTRY CONTAINS
  818.                 ; THE LAST TRACK POSITION
  819.                 ; FOR THE UNIT (1 OR 2)
  820. ;
  821. ;  NORTH STAR HOST SECTOR BUFFER
  822. ;
  823. HSTBUF: DS    HSTSIZ        ;HOST BUFFER
  824. ;
  825. LAST    EQU    $-1        ;LAST USED BYTE IN MEM
  826. ;
  827.     END
  828.