;BOOT4/ASM - LS-DOS 6.3 ; SUBTTL '' PAGE *MOD ; KEYIN EQU 40H NMIVECT EQU 66H DSPLY EQU 21BH BUFFER EQU 1200H BOOTBUF EQU 43FFH-9 ; ; Boot loader routine read in by ROM, along with ; the lowcore I/O drivers. ; This section loads in SYSRES ; LBOOT LD IY,DCT$ ;Set IY for FDCDVR use LD A,(IY+9) ;Directory track is LD (IY+5),A ; the current track LD A,4 LD (FLGTAB$+'R'-'A'),A ;Set retries LD A,0C9H LD (FDDINT$),A ;Return for disk driver LD A,18 ;5" sectors/track, dden BIT 5,(IY+4) ;Dbl sided? JR Z,NOTDBL ADD A,A ;Adjust to 36 sect/cyl NOTDBL LD (SECTRK),A ; ; Set up for a fragmented file ; EXX LD C,6 ;Sectors/gran CALL GETEXT ;Pick up extent 1 EXX ; CALL LOAD ;Read in sysres LD A,0FBH ;EI instruction LD (DISKEI),A ; stuffed into FDCDVR JP (HL) ;Continue system init ; LOAD CALL RDBYTE ;Get type code DEC A JR NZ,LOAD2 ;Bypass if not type 1 CALL GETADR ;Get blk len & load adr LOAD1 CALL RDBYTE ;Start reading the block LD (HL),A ;Stuff into memory INC HL ;Bump memory pointer DJNZ LOAD1 ;Loop for entire block JR LOAD ;Restart the process ; LOAD2 DEC A ;Test if type 2 (traadr) JR Z,GETADR ;Ah, go if transfer addr CALL RDBYTE ;Assume comment, LD B,A ; get comment length LOAD3 CALL RDBYTE ; & ignore it DJNZ LOAD3 JR LOAD ;Continue to read ; ; got the transfer address type code ; GETADR CALL RDBYTE ;Get block length LD B,A CALL RDBYTE ;Get lo-order load addr LD L,A DEC B ;Adj length for this byte CALL RDBYTE ;Get hi-order load addr LD H,A DEC B ;Adj length for this byte RET ; ; routine to read a byte ; RDBYTE EXX ;Switch memory/buf ptrs INC L ;Bump buf pointer JR NZ,RDB2 ;Bypass disk i/o if more PUSH BC LD B,9 ;Read sector function # CALL DCT$ ;Get another sector POP BC INC E ;Bump sector counter LD A,E SUB $-$ ;Is this the last sector SECTRK EQU $-1 JR NZ,RDB1 ; on the cylinder? LD E,A ;Yes, restart at 0 INC D ; & bump the cylinder up RDB1 DEC B ;Dec sectors this extent CALL Z,GETEXT ;Get next extent if 0 RDB2 LD A,(HL) ;P/u a byte EXX ;Exc mem/buf pointers RET ; ; Load DE track,sector, B sectors this extent ; GETEXT INC IX ;Index directory entry INC IX ;Pt at grans this ext. LD A,(IX) PUSH AF ;Save for later RLCA RLCA ;Normalize start gran RLCA AND 7 CALL MULTCA ;Start gran * grans/sec LD E,A ;This is start sector POP AF AND 00011111B ;Get total grans INC A ; this extent CALL MULTCA ; * sect/gran LD B,A ;Sectors this extent LD D,(IX-1) ;Cyl this extent RET ; ; Short multiply C * A ; MULTCA PUSH BC ;Save sect/gran in C LD D,A XOR A LD B,8 MLTCA ADD A,A SLA C JR NC,MLTCA1 ADD A,D MLTCA1 DJNZ MLTCA POP BC RET ; ; Initialize the CRTC ; INITCRTC LD BC,15<8!88H ;Count, CRTC address reg LD HL,CRTCTAB $?1 LD A,(HL) OUT (C),B ;Pass reg # to CRTC OUT (89H),A ;Pass value to CRTC reg DEC HL ;Backup to next value DEC B ;To next lower reg JP P,$?1 RET DB 99 ;Horiz total MD DB 80 ;Horiz displayed MD DB 85 ;Horiz sync position MD DB 10 ;Horiz sync width DB 25 ;Vertical total DB 4 ;Vertical total adjust DB 24 ;Vertical displayed DB 24 ;Vertical sync position DB 0 ;Interlace mode DB 9 ;Maximum scan line addr DB 65H ;Cursor start DB 9 ;Cursor end DB 0 ;Start address (H) DB 0 ;Start address (L) DB 0 ;Cursor (H) CRTCTAB DB 0 ;Cursor (L) DC -$&0FFH,0 ; ; System BOOT entry point, loaded by ROM ; CORE$ DEFL $ ORG 4300H BOOT NOP CP 14H ;Directory track location DIRTRK EQU $-1 DI LD A,86H ;Bring up the RAM OUT (@OPREG),A LD (OPREG$),A LD HL,CRTBGN$ ;Clear video RAM LD DE,CRTBGN$+1 LD BC,CRTSIZE-1 LD (HL),' ' LDIR LD HL,NMIRET ;Set NMI vector LD (NMIVECT+1),HL LD A,0C3H LD (NMIVECT),A LD A,0C9H ;Stuff return for ints LD (38H),A ; ; Read the first 16 sectors of track 0 ; LD HL,START$+200H ;Pt to page 2 LD D,L ;Init to track 0, sec 0 LD E,L RDBOOT CALL RDSEQ ;Read a sector INC H ;Bump to next page INC E ;Bump to next LD A,16 CP E ;Loop if more JR NZ,RDBOOT CALL INITCRTC ;Initialize the CRTC ; ; Now set up to load SYSRES ; LD A,(DIRTRK) ;P/u dir cyl LD (DCT$+9),A ;Update DCT to show DIR LD D,A ;Set starting track and LD E,0 ; init to read the GAT CALL RDSECT ; into BUFFER LD A,(BUFFER+0CDH) ;Update DCT$ to show AND 20H ; the # of sides LD HL,DCT$+4 OR (HL) LD (HL),A LD E,4 ;Pt to SYS0 dir sector CALL RDSECT ;Read the SYS0 dir sec LD A,(BUFFER) ;Test if system disk AND 10H JR Z,NOTSYS ;Go if not LD HL,BUFFER+21+8 ;SYS0 extent info LD DE,BOOTBUF ;Use 43FF-8 LD BC,8 LDDR ;Store 1st four extents PUSH DE ;Pt IX to 1 byte POP IX ; before extent info EXX LD HL,BUFFER+255 ;Init to buffer end EXX JP LBOOT ;Load SYSRES DB 0,0 ;Padding for posn ; ; routine to read a sector ; RDSECT LD HL,BUFFER ;Set buffer RDSEQ LD B,5 ;Init retry counter RDS1 PUSH BC ;Save counter PUSH HL ;Save for retries CALL READ ;Attempt read POP HL POP BC AND 1CH ;Mask status RET Z ;Return if no error DJNZ RDS1 ;Loop for retry GOTERR LD HL,DISKERR ;"Disk error" DB 0DDH ;Hide next instruction NOTSYS LD HL,NOSYS ;"No system" LD BC,ERRLEN LD DE,80*11+CRTBGN$+35 ;Middle of screen LDIR HALTS JR HALTS ;Wait for RESET ; READ LD BC,81F4H ;Set DDEN, DS1, d.s. port OUT (C),B ;Select it DEC C ;Point C to data reg LD A,18H ;Seek command (6 ms) BOOTST$ EQU $-1 ;Set for boot step rate IFNE BOOTST$,439DH ERR 'Boot step out of position' ENDIF OUT (C),D ;Set desired track CALL FDCMD ;Pass command & delay SEEK1 IN A,(0F0H) ;Get status BIT 0,A ;Busy? JR NZ,SEEK1 LD A,E ;Set sector register OUT (0F2H),A LD A,81H ;Set DDEN & DS1 OUT (0F4H),A PUSH DE LD DE,81H!40H<8!2 ;D=DS1 + DDEN + WSGEN ;E=Mask to see DRQ LD A,80H ;FDC READ command CALL FDCMD ;Pass to ctrlr & set B=0 LD A,0C0H ;Enable INTRQ & timeout OUT (0E4H),A READLP1 IN A,(0F0H) ;Grab status AND E ;Test bit 1 JR Z,READLP1 INI LD A,D ;Set DDEN & DS1 & WSGEN READLP2 OUT (0F4H),A ;Continue to select INI ; while inputting JR NZ,READLP2 JR $ ;Wait for NMI NMIRET POP DE ;Pop interrupt ret POP DE ;Restore DE XOR A ;Disable INTRQ & timeout OUT (0E4H),A LD A,81H ;Reselect drive OUT (0F4H),A IN A,(0F0H) ;Get status RET FDCMD OUT (0F0H),A ;Give cmd to ctrlr LD B,24 ;Time delay DJNZ $ RET DISKERR DB 'Disk error' NOSYS DB 'No system ' ERRLEN EQU $-NOSYS ;Length of error msg DC -$&0FFH,0 ORG CORE$+256 END