; CPM disk loader for my 8080 microcomputer ; JWD - v1.0 06/11/2024 ; ; Does not require CBIOS in memory ; ; CPU 8080 ; Specify architecture PAGE 0 ; ; ; Initial stack ; STACK equ 0FFFFh ;Initial stack at top of RAM ; ; BIOS parameters ; DRIVES equ 4 ;Number of drives in the system MEMSTART equ 0df00h ;Destination of CP/M image SECTORS equ 36h ;Number of sectors to load SECSIZE equ 80h ;CP/M sector size MONITOR equ 100h ;System monitor start address CPMCOLD equ 0f500h ;Address of CP/M Cold Start ; ; Equates for I/O mapped 8250 or 16450 serial port ; S16450 equ 0 ;base of 16450 UART RXR equ 0 ;Receiver buffer register TXR equ 0 ;Transmitter buffer register IER equ 1 ;Interrupt enable register LCR equ 3 ;Line control register MCR equ 4 ;Modem control register LSR equ 5 ;Line status register ; ; Define monitor serial port ; SER_STATUS equ S16450+LSR SER_DATA equ S16450+RXR SER_RXRDY equ 1 ;Mask for rx buffer full SER_TXRDY equ 32 ;Mask for tx buffer empty ; ; ATA Drive Definitions ; ATA_CS1 equ 40h ;ATA Drive CS1 address ATA_CS2 equ 80h ;ATA Drive CS2 address ATA_DATA equ ATA_CS1 ;ATA Drive Data Register ATA_ERROR equ ATA_CS1+1 ;ATA Drive Error Register (Read Only) ATA_FEATURES equ ATA_CS1+1 ;ATA Drive Feature Register (Write Only) ATA_SEC_COUNT equ ATA_CS1+2 ;ATA Drive Sector Count Register ATA_SEC equ ATA_CS1+3 ;ATA Drive Sector Number Register ATA_CYL_LOW equ ATA_CS1+4 ;ATA Drive Cylinder LSB Register ATA_CYL_HI equ ATA_CS1+5 ;ATA Drive Cylinder MSB Register ATA_DRV_HEAD equ ATA_CS1+6 ;ATA Drive Device/Head Register ATA_STATUS equ ATA_CS1+7 ;ATA Drive Status Register (Read Only) ATA_COMMAND equ ATA_CS1+7 ;ATA Drive Command Register (Write Only) ; ATA_LBA_BYTE1 equ ATA_CS1+3 ;ATA Bytes 0 through 7 in LBA mode ATA_LBA_BYTE2 equ ATA_CS1+4 ;ATA Bytes 8 through 15 in LBA mode ATA_LBA_BYTE3 equ ATA_CS1+5 ;ATA Bytes 16 through 23 in LBA mode ATA_LBA_BYTE4 equ ATA_CS1+6 ;ATA Bytes 24 through 27 in LBA mode ; ATA_ALT_STATUS equ ATA_CS2+6 ;ATA Drive Alternate Status Register ATA_DEV_CTRL equ ATA_CS2+6 ;ATA Drive Control Register ATA_DEV_ADDRESS equ ATA_CS2+7 ;ATA Drive Address Register ; ATA_LBA0_7 equ ATA_CS1+3 ;ATA Drive LBA Bits 0-7 ATA_LBA8_15 equ ATA_CS1+4 ;ATA Drive LBA Bits 8-15 ATA_LBA16_23 equ ATA_CS1+5 ;ATA Drive LBA Bits 16-23 ATA_LBA24_27 equ ATA_CS1+6 ;ATA Drive LBA Bits 24-27 ; ; ATA Command Options ; CMD_RETRY equ 0 CMD_NO_RETRY equ 1 ; ; ATA Read/Write Commands ; CMD_READ_SECTOR_RETRY equ 20h ;Read sectors in sector count register - retry enabled CMD_READ_SECTOR_NORETRY equ 21h ;Read sectors in sector count register - retry disabled CMD_READ_LONG_RETRY equ 22h ;Reads one sector with ECC bytes, retry enabled CMD_READ_LONG_NORETRY equ 23h ;Reads one sector with ECC bytes, retry disabled CMD_WRITE_SECTOR_RETRY equ 30h ;Write sectors in sector count register - retry enabled CMD_WRITE_SECTOR_NORETRY equ 31h ;Write sectors in sector count register - retry disabled CMD_WRITE_LONG_RETRY equ 32h ;Writes one sector with ECC bytes, retry enabled CMD_WRITE_LONG_NORETRY equ 33h ;Writes one sector with ECC bytes, retry disabled CMD_WRITE_VERIFY equ 3Ch ;Write sectors in sector count register - verify after writing CMD_VERIFY_SECTOR_RETRY equ 40h ;Verify sectors in sector count register - retry enabled, no data CMD_VERIFY_SECTOR_NORETRY equ 41h ;Verify sectors in sector count register - retry disabled, no data CMD_READ_MULTIPLE equ 0C4h ;Read multiple sectors - interrupt when finished CMD_WRITE_MULTIPLE equ 0C5h ;Write multiple sectors - interrupt when finished CMD_READ_BUFFER equ 0E4h ;Read contents of sector buffer CMD_WRITE_BUFFER equ 0E8h ;Write to sector buffer ; ;ATA Control Commands ; CMD_REQUEST_SENSE equ 3 ;Gets extended error for previous command CMD_RECALIBRATE equ 10h ;Reinitialize ATA controller (does nothing with CF) CMD_SEEK equ 70h ;Moves head to track specified (does nothing with CF) CMD_DIAGNOSTIC equ 90h ;Check power mode of the card CMD_INITIALIZE equ 91h ;Allows change to sectors per track and heads per cylinder CMD_STANDBY_IMMEDIATE equ 94h ;Puts card in standby mode without idle timer CMD_STANDBY equ 96h ;Puts card in standby mode after idle until timer expired CMD_CHECK_POWER equ 98h ;Returns power status of the card CMD_SLEEP equ 99h ;Puts card in sleep mode until hardware/software reset CMD_MULTIPLE equ 0C6h ;Enable read/write multiple operations CMD_IDENTIFY equ 0ECh ;Performs self diagnostics on the card CMD_SET_FEATURES equ 0EFh ;Set card features (aka 8-bit mode) ; ;ATA Control Settings ; DEV_CONTROL_SRST equ 04h ;Device Control Register Software Reset DEV_CONTROL_NIEN equ 02h ;Device Control Register Interrupt Enable ; DHR_SLAVE_SELECT equ 10h ;DHR Register select slave (default is master) DHR_LBA_MODE equ 40h ;DHR Register enable LBA mode (default is CHS) ; ;ATA Error Register Flags ; ERROR_BBK equ 80h ;Bad Block Mark (Always 0, not supported on CF) ERROR_UNC equ 40h ;Uncorrectable Data Error ERROR_MC equ 20h ;Media Changed (Always 0) ERROR_IDNF equ 10h ;Sector ID Field Not Found ERROR_MCR equ 08h ;Media Change Requested (Always 0) ERROR_ABRT equ 04h ;Status error or Invalid Command Aborted ERROR_TKN0NF equ 02h ;Track 0 Not Found (Not supported on CF) ERROR_AMNF equ 01h ;Address Mark Not Found (Not supported on CF) ; ;ATA Status Register Flage ; STATUS_BSY equ 80h ;Device Busy STATUS_DRDY equ 40h ;Device Ready STATUS_DWF equ 20h ;Device Write Fault STATUS_DSC equ 10h ;Device Seek Complete STATUS_DRQ equ 08h ;Data Request STATUS_CORR equ 04h ;Corrected Data STATUS_IDX equ 02h ;Index (Not used on CF, Always 0) STATUS_ERR equ 01h ;Command Error ; ;ATA Feature Codes ; FEATURE_8BIT_ON equ 01h ;Enable 8-bit transfers in LBA mode FEATURE_LOOKAHEAD_OFF equ 55h ;Disable read lookahead FEATURE_DEFAULTS_OFF equ 66h ;Disable power-on defaults FEATURE_8BIT_OFF equ 81h ;Disable 8-bit transfers in LBA mode FEATURE_ECC_ON equ 0BBh ;Enable 4 bytes ECC on read/write long FEATURE_DEFAULTS_ON equ 0CCh ;Enable power-on defaults ; msize equ 63 ;cp/m version memory size in kilobytes ; ;***************************************************** ;* * ;* CP/M to host disk constants * ;* * ;***************************************************** blksiz equ 4096 ;CP/M allocation size hstsiz equ 512 ;host disk sector size hstspt equ 64 ;host disk sectors/trk hstblk equ hstsiz/SECSIZE ;CP/M sects/host buff cpmspt equ hstblk * hstspt ;CP/M sectors/track secmsk equ hstblk-1 ;sector mask secshf equ 2 ; ;***************************************************** ;* * ;* BDOS constants on entry to write * ;* * ;***************************************************** wrall equ 0 ;write to allocated wrdir equ 1 ;write to directory wrual equ 2 ;write to unallocated ; org 1000h ;origin of this program ; ; individual subroutines to perform each function ; lxi sp, STACK ;set stack pointer xra a ;zero in the accum sta hstact ;host buffer inactive sta unacnt ;clear unalloc count sta disk00 ;default physical to logigical disk map inr a sta disk01 inr a sta disk02 inr a sta disk03 ; ; Initialize S16450 UART ; ; access baud generator, no parity, 1 stop bit, 8 data bits ; mvi a, 83h out S16450+LCR ; ; fixed baud rate of 19200: crystal is 1.843200 Mhz. ; Divisor is 1843200/(16*19200) = 6 ; mvi a, 6 ;fix at 19.2 kbaud out S16450+RXR ;lsb xra a out S16450+RXR+1 ;msb=0 ; ; access data registers, no parity, 1 stop bits, 8 data bits ; mvi a, 3 out S16450+LCR ; ; no loopback, OUT2 on, OUT1 on, RTS on, DTR (LED) on ; mvi a, 0fH out S16450+MCR ; ; disable all interrupts: modem, receive error, transmit, and receive ; xra a out S16450+IER ; ; print bios boot message ; lxi d, bios_boot ;point to boot message call bios_print ;print it ; ; ; Check that ATA controller is presenrt ; mvi a, 0aah ;get test signature out ATA_SEC_COUNT ;store in sector count register xra a in ATA_SEC_COUNT ;retrieve test signature cpi 0aah ;is it correct? jz init ;move along if it is lxi d, bios_nodrv ;otherwise print error call bios_print jmp MONITOR ;Exit to monitor ; ; Initialize ATA Controller ; ; Software reset the drive, disable interrupts ; init: call ataready ;Wait for drive ready in case of power reset in ATA_DEV_CTRL ;Get the ATA device control bits ani DEV_CONTROL_SRST+DEV_CONTROL_NIEN ;Enable software reset, disable interrupts out ATA_DEV_CTRL ;Store in device control register in ATA_DEV_CTRL ;Get the ATA device control bits ani DEV_CONTROL_NIEN ;Turn off software reset out ATA_DEV_CTRL ;Store in device control register call ataready ;Wait for drive to be ready ; ; Set drive for LBA mode ; in ATA_DRV_HEAD ;Get current DHR bits ori DHR_LBA_MODE ;Set the LBA mode bit out ATA_DRV_HEAD ;Write bits to the DHR register ; ; Enable 8-bit data transfers ; mvi a, FEATURE_8BIT_ON ;Get feature code for 8-bit mode out ATA_FEATURES ;Write 8-bit feature code to features register mvi a, CMD_SET_FEATURES ;Get ready for Features command out ATA_COMMAND ;Request Set Features command call atabusy ;Wait for command completion ; ; Set drive to sector zero and seek ; xra a ;zero accumulator out ATA_LBA0_7 ;save in LBA out ATA_LBA8_15 out ATA_LBA16_23 in ATA_LBA24_27 ;get mode control and final lba ani 0f0h ;mask off lba bits out ATA_LBA24_27 ;save everything but lba mvi a, 1 ;set for one sector out ATA_SEC_COUNT mvi a, CMD_SEEK out ATA_COMMAND ;Request Set Features command call atabusy ;Wait for command completion ; ; Check that ATA init completed without errors ; call ataerror ;Check ATA error status jz initok ;Boot is good? lxi d, bios_err ;Point to init error message call bios_print ;Print it jmp MONITOR ;Exit to monitor ; initok: lxi d, bios_msg ;Point to boot start message call bios_print ;Print it ; load: mvi c, 0 ;Select drive 0 call seldsk mvi c, 0 ;Select track 0 call settrk mvi c, 4 ;Select sector 4 call setsec lxi h, MEMSTART ;Get dma position shld dmaadr ;Save dma position mvi a, SECTORS ;Sector counter sta seccnt ;Store it in memory load01: call read ;read the first block lda seksec ;Get current sector inr a ;Point to next sector mov c, a ;Transfer to c register call setsec ;Set next sector ; lhld dmaadr ;Get DMA address lxi b, SECSIZE ;Get sector size dad b ;Add byte increment shld dmaadr ;Save DMA address ; lda seccnt ;Get sector counter dcr a ;Decrement the sector count sta seccnt ;Save sector counter jnz load01 ;If not zero, do next sector ; lxi d, bios_end ;Point to end message call bios_print ;Print it ; jmp CPMCOLD ;Exit to CPM cold start; jmp MONITOR ;Used for debugging ; ; BIOS messages ; bios_boot: db 'JWD 8080 CP/M Disk Loader v1.0' dw 0d0ah db 0 bios_nodrv: db 'No ATA Controller Detected' dw 0d0ah db 0 bios_err: db 'ATA Controller Error' dw 0d0ah db 0 bios_msg: db 'Loading CP/M from ATA drive 0' dw 0d0ah db 0 bios_end: db 'CP/M load completed' dw 0d0ah db 0; ; ; I/O Handlers ; const: ;console status, return 0ffh if character ready, 00h if not in SER_STATUS ;read device status ani SER_RXRDY ;rx ready ? jz conno ;exit if not mvi a, 0ffh ;raise signal if ready conno: ret ; conin: ;console character into register a in SER_STATUS ;read device status ani SER_RXRDY ;rx ready? jz conin ;repeat if no in SER_DATA ;get character if ready ani 7fh ;strip parity bit ret ; conout: ;console character output from register c in SER_STATUS ;read device status ani SER_TXRDY ;tx ready? jz conout ;repeat if no mov a, c ;get character to accumulator out SER_DATA ;send it ret ; list: ;list character from register c mov a, c ;character to register a ret ;null subroutine ; listst: ;return list status (0 if not ready, 1 if ready) xra a ;0 is always ok to return ret ; punch: ;punch character from register C mov a, c ;character to register a ret ;null subroutine ; ; reader: ;reader character into register a from reader device mvi a, 1ah ;enter end of file for now (replace later) ani 7fh ;remember to strip parity bit ret ; ; ; Disk I/O Operations ; home: lda hstwrt ;check for pending write ora a jnz homed sta hstact ;clear host active flag homed: ret ; seldsk: ;select disk lxi h, 0000h ;Error return code mov a,c ;selected disk number cpi DRIVES ;Must be between 0 and DRIVES-1 rnc ;Return if carry clear (invalid drive) sta sekdsk ;seek disk number ret ; settrk: ;set track given by registers BC mov h,b mov l,c shld sektrk ;track to seek ret ; setsec: ;set sector given by register c mov a,c sta seksec ;sector to seek ret ; setdma: ;set dma address given by BC mov h,b mov l,c shld dmaadr ret ; sectran: ;translate the sector given by bc using the ;translate table given by de ;JWD - no translation xchg ;hl=.trans dad b ;hl=.trans (sector) ret ;with value in hl ; ; ;***************************************************** ;* * ;* The READ entry point takes the place of * ;* the previous BIOS defintion for READ. * ;* * ;***************************************************** read: ;read the selected CP/M sector xra a sta unacnt mvi a,1 sta readop ;read operation sta rsflag ;must read data mvi a,wrual sta wrtype ;treat as unalloc jmp rwoper ;to perform the read ; ;***************************************************** ;* * ;* The WRITE entry point takes the place of * ;* the previous BIOS defintion for WRITE. * ;* * ;***************************************************** write: ;write the selected CP/M sector xra a ;0 to accumulator sta readop ;not a read operation mov a,c ;write type in c sta wrtype cpi wrual ;write unallocated? jnz chkuna ;check for unalloc ; ; write to unallocated, set parameters mvi a,blksiz/128 ;next unalloc recs sta unacnt lda sekdsk ;disk to seek sta unadsk ;unadsk = sekdsk lhld sektrk shld unatrk ;unatrk = sectrk lda seksec sta unasec ;unasec = seksec ; chkuna: ;check for write to unallocated sector lda unacnt ;any unalloc remain? ora a jz alloc ;skip if not ; ; more unallocated records remain dcr a ;unacnt = unacnt-1 sta unacnt lda sekdsk ;same disk? lxi h,unadsk cmp m ;sekdsk = unadsk? jnz alloc ;skip if not ; ; disks are the same lxi h,unatrk call sektrkcmp ;sektrk = unatrk? jnz alloc ;skip if not ; ; tracks are the same lda seksec ;same sector? lxi h,unasec cmp m ;seksec = unasec? jnz alloc ;skip if not ; ; match, move to next sector for future ref inr m ;unasec = unasec+1 mov a,m ;end of track? cpi 0 ;check CP/M sectors jnz noovf ;skip if no overflow ; ; overflow to next track mvi m,0 ;unasec = 0 lhld unatrk inx h shld unatrk ;unatrk = unatrk+1 ; noovf: ;match found, mark as unnecessary read xra a ;0 to accumulator sta rsflag ;rsflag = 0 jmp rwoper ;to perform the write ; alloc: ;not an unallocated record, requires pre-read xra a ;0 to accum sta unacnt ;unacnt = 0 inr a ;1 to accum sta rsflag ;rsflag = 1 ; ;***************************************************** ;* * ;* Common code for READ and WRITE follows * ;* * ;***************************************************** rwoper: ;enter here to perform the read/write xra a ;zero to accum sta erflag ;no errors (yet) lda seksec ;compute host sector rept secshf ora a ;carry = 0 rar ;shift right endm sta sekhst ;host sector to seek ; ; active host sector? lxi h,hstact ;host active flag mov a,m mvi m,1 ;always becomes 1 ora a ;was it already? jz filhst ;fill host if not ; ; host buffer active, same as seek buffer? lda sekdsk lxi h,hstdsk ;same disk? cmp m ;sekdsk = hstdsk? jnz nomatch ; ; same disk, same track? lxi h,hsttrk call sektrkcmp ;sektrk = hsttrk? jnz nomatch ; ; same disk, same track, same buffer? lda sekhst lxi h,hstsec ;sekhst = hstsec? cmp m jz match ;skip if match ; nomatch: ;proper disk, but not correct sector lda hstwrt ;host written? ora a cnz writehst ;clear host buff ; filhst: ;may have to fill the host buffer lda sekdsk sta hstdsk lhld sektrk shld hsttrk lda sekhst sta hstsec lda rsflag ;need to read? ora a cnz readhst ;yes, if 1 xra a ;0 to accum sta hstwrt ;no pending write ; match: ;copy data to or from buffer lda seksec ;mask buffer number ani secmsk ;least signif bits mov l,a ;ready to shift mvi h,0 ;double count rept 7 ;shift left 7 dad h endm ; hl has relative host buffer address lxi d,hstbuf dad d ;hl = host address xchg ;now in DE lhld dmaadr ;get/put CP/M data mvi c,128 ;length of move lda readop ;which way? ora a jnz rwmove ;skip if read ; ; write operation, mark and switch direction mvi a,1 sta hstwrt ;hstwrt = 1 xchg ;source/dest swap ; rwmove: ;C initially 128, DE is source, HL is dest ldax d ;source character inx d mov m,a ;to dest inx h dcr c ;loop 128 times jnz rwmove ; ; data has been moved to/from host buffer lda wrtype ;write type cpi wrdir ;to directory? lda erflag ;in case of errors rnz ;no further processing ; ; clear host buffer for directory write ora a ;errors? rnz ;skip if so xra a ;0 to accum sta hstwrt ;buffer written call writehst lda erflag ret ; ;***************************************************** ;* * ;* Utility subroutine for 16-bit compare * ;* * ;***************************************************** sektrkcmp: ;HL = .unatrk or .hsttrk, compare with sektrk xchg lxi h,sektrk ldax d ;low byte compare cmp m ;same? rnz ;return if not ; low bytes equal, test high 1s inx d inx h ldax d cmp m ;sets flags ret ; ;***************************************************** ;* * ;* WRITEHST performs the physical write to * ;* the host disk, READHST reads the physical * ;* disk. * ;* * ;***************************************************** ; ; ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. read "hstsiz" bytes ;into hstbuf and return error flag in erflag. ; readhst: ;perform read operation ; ;Do DTS conversion to LBA here ; mvi a, CMD_READ_SECTOR_RETRY ;Set up for sector read call doatacmd ;Execute the read command jz rdhst01 ;Signal read error mvi a, 1 ;error condition sta erflag ;flag an error ret ; rdhst01: lxi b, hstbuf ;Point to sector buffer rdhst02: in ATA_DATA ;Get data byte stax b ;Store data in sector buffer inx b ;Point to next buffer byte in ATA_STATUS ;Check card status ani STATUS_DRQ ;Get data ready status bit jnz rdhst02 ;Get another byte from the card xra a ;Signal no error sta erflag ;save it ret ; ;hstdsk = host disk #, hsttrk = host track #, ;hstsec = host sect #. write "hstsiz" bytes ;from hstbuf and return error flag in erflag. ;return erflag non-zero if error ; writehst: ;perform a write operation ; ;Do DTS conversion to LBA here ; mvi a, CMD_WRITE_SECTOR_RETRY ;Set up for sector write call doatacmd ;Execute the read command jz wrhst01 ;Signal read error mvi a, 1 ;error condition sta erflag ;flag an error ret ; wrhst01: lxi b, hstbuf ;Point to sector buffer wrhst02: ldax b ;Get data byte from sector buffer out ATA_DATA ;Send data byte to ATA drive inx b ;Point to next buffer byte in ATA_STATUS ;Check drive status ani STATUS_DRQ ;Get data ready status bit jnz wrhst02 ;Get another byte from the card xra a ;Signal no error sta erflag ;Save it ret ; ; doatacmd: ;Execute ATA READ/Write Command mov b, a ;Save A temporarially call atabusy ;Wait for command completion ; ;Set disk number MSB in LBA ; doata01: lda hstdsk ;Get current host disk number lxi h, disk00 ;Point to physical/logical disk map dcr a ;Decrement host disk number jm doata02 ;Last drive? inx h ;Point to next map jmp doata01 ;Do again doata02: mov a, m ;Get actual drive from map ora a ;Clear carry rar ;Remove lsb of disk number ora a ;Clear carry rar ;Remove lsb of disk number out ATA_LBA16_23 ;Save it in ATA_LBA16-23 mov a, m ;Get actual drive from map ani 3 ;Get two lsb of disk number rrc ;Put them in msb rrc mov c, a ;Save it in C ; ;Set disk number LSB and track MSB in LBA ; lda hsttrk ;Get current host track number ani 0fch ;Remove two lsb bits rrc ;Move over two bits rrc ora c ;Add in drive lsb bits out ATA_LBA8_15 ;Set it in ATA_LBA8_15 lda hsttrk ;Get current host track number ani 3 ;Get two lsb bits of track rrc ;Put them in msb rrc ; ;Set track number LSB and sector in LBA ; mov c, a ;Save it in C lda hstsec ;Get current host sector number ani 3fh ;Remove msb bits just in case ora c ;Add in sector bits out ATA_LBA0_7 ;Set it in ATA_LBA0_7 ; ;Set sector count to 1 ; mvi a, 01 ;Read/Write one sector out ATA_SEC_COUNT ;Set it in ATA drive in ATA_LBA24_27 ;Make sure all other LBA bits are zero ani 0f0h out ATA_LBA24_27 ;set it in ATA_LBA24_27 ; ;Set Read/Write command code ; mov a, b ;restore A out ATA_COMMAND ;Read sector with retry call atabusy ;Wait for command completion call ataready ;Wait for data buffer ready call ataerror ;Check for error condition ret ; ; atabusy: ;Wait for the ATA adapter to complete a command in ATA_STATUS ;Get ATA status ani STATUS_BSY ;Mask on busy bit jnz atabusy ;If busy check again ret ;And exit ; ; ataready: ;Wait for ATA to become ready to execute commands in ATA_STATUS ;Get ATA status ani STATUS_DRDY ;Mask on data ready bit jz ataready ;Check again if not ready ret ;And exit ; ; ataerror: ;Check for ATA error status (not zero on error) in ATA_STATUS ;Get ATA status ani STATUS_ERR ;Mask on command error bit (sets flags) ret ;And exit ; ; ; JWD - Miscellaneous support routines ; ; bios_print: ;Print a message on the console ldax d ;Get char pointed to by D into A cpi 0 ;End of string? jz bios_pend ;Exit if end of string mov c, a ;Move shar into C for console out call conout ;Print it inx d ;Point to next character jmp bios_print ;Repeat bios_pend: ret ;And exit ; ; ;***************************************************** ;* * ;* Unitialized RAM data areas * ;* * ;***************************************************** ; begdat equ $ ;beginning of data area ; sekdsk: ds 1 ;seek disk number sektrk: ds 2 ;seek track number seksec: ds 1 ;seek sector number ; hstdsk: ds 1 ;host disk number hsttrk: ds 2 ;host track number hstsec: ds 1 ;host sector number ; sekhst: ds 1 ;seek shr secshf hstact: ds 1 ;host active flag hstwrt: ds 1 ;host written flag ; unacnt: ds 1 ;unalloc rec cnt unadsk: ds 1 ;last unalloc disk unatrk: ds 2 ;last unalloc track unasec: ds 1 ;last unalloc sector ; erflag: ds 1 ;error reporting rsflag: ds 1 ;read sector flag readop: ds 1 ;1 if read operation wrtype: ds 1 ;write operation type dmaadr: ds 2 ;last dma address ; seccnt: ds 1 ;sector counter for CP/M loader disk00: ds 1 ;physical disk to virtual disk translation disk01: ds 1 ;physical disk to virtual disk translation disk02: ds 1 ;physical disk to virtual disk translation disk03: ds 1 ;physical disk to virtual disk translation ; ; Sector buffer ; hstbuf: ds hstsiz ;host buffer ; ; enddat equ $ ;end of data area datsiz equ $-begdat; ;size of data area ; ; end