From 8fb07c725b4e0a85f0a7317f72c9184821379429 Mon Sep 17 00:00:00 2001 From: lynchaj <86925539+lynchaj@users.noreply.github.com> Date: Tue, 6 Jul 2021 17:13:46 -0400 Subject: [PATCH] Create ppidetst.asm --- Source/Apps/ppidetst.asm | 1308 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 1308 insertions(+) create mode 100644 Source/Apps/ppidetst.asm diff --git a/Source/Apps/ppidetst.asm b/Source/Apps/ppidetst.asm new file mode 100644 index 00000000..7d534562 --- /dev/null +++ b/Source/Apps/ppidetst.asm @@ -0,0 +1,1308 @@ +; N8VEM PPI IDE test program for checkout of IDE drive connected to the 8255 PPI +; +; Written by Max Scane July 2009 +; Based on work by Paul Stoffregen (www.pjrc.com) +; +; Note: due to a known anomaly in the 8255, some signals ( all active low signals) on the IDE bus require an inverter (74LS04 or 74LS14) +; between the 8255 and the IDE drive. +; This is due to the 8255 returning all signals to 0 (low) when a mode change is performed (for read and write to IDE data bus). +; +; This test program will allow you to check out an attached IDE drive using the basic commands: +; +; u - Spin up the drive +; d - Spin down the drive +; s - Read and print out drive status +; i - Execute drive ID command and print result correctly +; r - Read the current LBA into the sector buffer and print status +; w - Write the sector buffer to the current LBA and print status +; l - Change the current LBA +; h - Dump the current sector buffer in hexdump format +; f - format drive for CP/M use (fill with 0xE5) +; e - Display drive error information +; x - Return to CP/M +; n - read and hexdump next LBA +; ? - Display command menu help +; p - set PPI port +; +; +; +; +; - Updated December 2014 MS - changed IO routines to support different PPI ports. +; - Updated July 2021 Andrew Lynch - Minor cosmetic updates + +;********************* HARDWARE IO ADR ************************************ + + +; +; Offsets to the various PPI registers + +IDELSB: EQU 0 ; LSB +IDEMSB: EQU 1 ; MSB +IDECTL: EQU 2 ; Control Signals +PIOCONT: EQU 3 ; CONTROL BYTE PIO 82C55 + +; PPI control bytes for read and write to IDE drive + +rd_ide_8255: EQU 10010010b ; ide_8255_ctl out, ide_8255_lsb/msb input +wr_ide_8255: EQU 10000000b ; all three ports output + +;IDE control lines for use with ide_8255_ctl. Change these 8 +;constants to reflect where each signal of the 8255 each of the +;IDE control signals is connected. All the control signals must +;be on the same port, but these 8 lines let you connect them to +;whichever pins on that port. + +ide_a0_line: EQU 01H ;direct from 8255 to IDE interface +ide_a1_line: EQU 02H ;direct from 8255 to IDE interface +ide_a2_line: EQU 04H ;direct from 8255 to IDE interface +ide_cs0_line: EQU 08H ;inverter between 8255 and IDE interface +ide_cs1_line: EQU 10H ;inverter between 8255 and IDE interface +ide_wr_line: EQU 20H ;inverter between 8255 and IDE interface +ide_rd_line: EQU 40H ;inverter between 8255 and IDE interface +ide_rst_line: EQU 80H ;inverter between 8255 and IDE interface + + +;------------------------------------------------------------------ +; More symbolic constants... these should not be changed, unless of +; course the IDE drive interface changes, perhaps when drives get +; to 128G and the PC industry will do yet another kludge. + +;some symbolic constants for the ide registers, which makes the +;code more readable than always specifying the address pins + +ide_data: EQU ide_cs0_line +ide_err: EQU ide_cs0_line + ide_a0_line +ide_sec_cnt: EQU ide_cs0_line + ide_a1_line +ide_sector: EQU ide_cs0_line + ide_a1_line + ide_a0_line +ide_cyl_lsb: EQU ide_cs0_line + ide_a2_line +ide_cyl_msb: EQU ide_cs0_line + ide_a2_line + ide_a0_line +ide_head: EQU ide_cs0_line + ide_a2_line + ide_a1_line +ide_command: EQU ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line +ide_status: EQU ide_cs0_line + ide_a2_line + ide_a1_line + ide_a0_line +ide_control: EQU ide_cs1_line + ide_a2_line + ide_a1_line +ide_astatus: EQU ide_cs1_line + ide_a2_line + ide_a1_line + ide_a0_line + + + + +;IDE Command Constants. These should never change. +ide_cmd_recal: EQU 10H +ide_cmd_read: EQU 20H +ide_cmd_write: EQU 30H +ide_cmd_init: EQU 91H +ide_cmd_id: EQU 0ECH +ide_cmd_spindown: EQU 0E0H +ide_cmd_spinup: EQU 0E1H + +CR: EQU 0Dh +LF: EQU 0Ah +BELL: EQU 07H + + +org 100H + +start: + +; save stack pointer so that we can return to calling program + + ld (savsp),sp + ld sp,stack + + call set_ppi_rd ; setup PPI chip to known state + + ld hl,lba1 ; zero LBA variables + call clrlba + + ld hl,lba2 + call clrlba + + ld hl,lba3 + call clrlba + + + call print + db "PPI IDE test program v0.6a",CR,LF,0 + + call prstatus + call prlba + + call ide_init + call prstatus + + call crlf + +menu: + call print ; display prompt + db "Enter command (u,d,s,i,r,w,l,h,f,e,n,p,?,x) > ",0 + + call cin ; get command from console in reg A + push af + call crlf + pop af + +mnu1: + cp 'd' ; spin down command + jr nz,mnu2 + call spindown + jr menu +mnu2: + cp 'u' ; spinup command + jr nz,mnu3 + call spinup + jr menu + +mnu3: + cp 's' ;print IDE status reg contents + jr nz,mnu4 + call prstatus + jr menu + +mnu4: + cp 'i' + jr nz,mnu5 ; drive ID command + call drive_id + jr menu + +mnu5: + cp 'r' + jr nz,mnu6 ; read command + call prlba ; print out the current LBA + call read_sector ; read current LBA + call prstatus + jr menu + +mnu6: + cp 'w' + jr nz,mnu7 ; write command + call prlba ; print out the current LBA + call write_sector ; write current LBA + call prstatus + jr menu + +mnu7: + cp 'l' + jr nz,mnu8 ; LBA command + call prlba ; print out the current LBA +mnu7a: + call print + db "Enter new LBA: ",0 + + ld de,lba1 ; get LBA in lba1 + call getlba + jp nc,menu ; valid, finished + + call print + db "Invalid LBA",CR,LF,0 + + jr mnu7a ; try again + + +mnu8: + cp 'h' + jr nz,mnu9 ; hexdump command + call hexdump ; hexdump the current sector buffer + jp menu + +mnu9: + cp 'f' + jr nz,mnua ; drive format + call format + jp menu + +mnua: + cp 'e' + jr nz,mnub ; get error register + call get_err + push af + call print + db "Error register is: ",0 + + pop af + call prhex + call crlf + + + ld a,ide_head + call ide_read + ld a,c + call prhex + + ld a,ide_cyl_msb + call ide_read + ld a,c + call prhex + + ld a,ide_cyl_lsb + call ide_read + ld a,c + call prhex + + + ld a,ide_sector + call ide_read + ld a,c + call prhex + + call crlf + + ld a,ide_sec_cnt + call ide_read + ld a,c + call prhex + call crlf + + jp menu + + +mnub: + cp 'n' + jr nz,mnuc + ld hl,lba1 + call inclba + call prlba + call read_sector + call hexdump + jp menu + +mnuc: + cp 'p' + jr nz,mnux + call crlf + call print + db "Please enter new PPI base port: ",0 +; get a hex number + ld (ppibase),a ; save it + call crlf + jp menu + +mnux: + cp 'x' ; exit command + jp nz,mnuhlp + ld sp,(savsp) + ret + + + + +mnuhlp: + call print + db "Commands available:",CR,LF,LF + db "u - Spin Up drive",CR,LF + db "d - Spin Down drive",CR,LF + db "s - Print drive Status",CR,LF + db "i - Query drive using ID command",CR,LF + db "r - Read a sector addressed by the lba variable",CR,LF + db "w - Write a sector adresses by the lba variable",CR,LF + db "l - Change the current LBA variable",CR,LF + db "h - Hexdump the current buffer",CR,LF + db "f - Format the drive for CP/M use (fill with 0xE5)",CR,LF + db "e - Display drive Error information",CR,LF + db "p - Change base IO port",CR,LF + db "? - Display command menu help",CR,LF + db "x - eXit from this utility",CR,LF,LF,0 + jp menu + + +format: + call print + db "Warning - this command will write data to the drive",CR,LF,LF + db "All existing data will be over written",CR,LF,LF + db "Is that what you want to do ? ",0 + + call cin ; get answer + cp 'y' + jr z,fmt1 ; if yes then continue + call print + db " Command aborted",CR,LF,0 + ret + +fmt1: + ld a,0E5h + call fillbuf ; setup sector buffer +fmt2: + + call print + db CR,LF,"Enter starting LBA: ",0 + + ld de,lba2 ; starting LBA + call getlba + jr nc,fmt3 + + call print + db "Invalid LBA",CR,LF,0 + jr fmt2 ; try again + +fmt3: + + call crlf + +fmt4: + call print + db "Enter ending LBA: ",0 + + ld de,lba3 ; ending LBA + call getlba + jr nc,fmt5 + + call print + db "Invalid LBA",CR,LF,0 + + jr fmt4 ; try again + +fmt5: + call crlf + + call print ; say what is going to happen + db "Format will start at LBA ",0 + + ld a,(lba2+3) + call prhex + ld a,(lba2+2) + call prhex + ld a,(lba2+1) + call prhex + ld a,(lba2) + call prhex + + call print + db " and finish at LBA ",0 + ld a,(lba3+3) + call prhex + ld a,(lba3+2) + call prhex + ld a,(lba3+1) + call prhex + ld a,(lba3) + call prhex + + + call crlf + call print + db "Type y to continue or any other key to abort ",0 + + call cin + cp 'y' + jp nz,fmtx + call crlf + + + ; add the actual format code here + ; get starting LBA + ; get ending LBA + ; fill buffer with E5 + + ld hl,lba2 + ld de,lba1 + call cpylba ; copy start LBA to LBA + call inclba + + +fmt6: + push hl + call print ; display progress + db "Writing LBN: ",0 + ld a,(lba1+3) + call prhex + ld a,(lba1+2) + call prhex + ld a,(lba1+1) + call prhex + ld a,(lba1) + call prhex + ld a,CR + call cout + pop hl + + +; do some stuff to format here + call write_sector + +; need to check status after each call and check for errors +; + ld hl,lba1 ; LBA for disk operation + call inclba + + ld hl,lba1 + ld de,lba3 + call cplba + + jp nz,fmt6 + + call crlf + +fmtx: + call print ; finished + db "Format complete",CR,LF,0 + ret + + + +getlba: ; get an LBA value from the console and validate it + push de ; save LBA variable + ld c,0ah ; bdos read console buffer + ld de,conbuf + call 5 ; get edited string + + call crlf + + ; ok we now have an ascii string representing the LBA. now we have to validate it + + pop de + ld hl,conbuf + inc hl + ld b,(hl) ; get character count +glba1: + inc hl ; HL = address of buffer + ld a,(hl) ; get next character + + call ishex + ret c ; return with carry set if any char is invalid + + ; ok we are here when we have a valid character (0-9,A-F,a-f) need to convert to binary + ; character is still in A + + cp 3AH ; test for 0-9 + jp m,glba4 + cp 47H ; test for A-F + jp m,glba3 + cp 67H ; test for a-f + jp m,glba2 + +glba2: + sub 20H ; character is a-f +glba3: + sub 07h ; character is A-F +glba4: + sub 030H ; character is 0-9 + + ld (hl),a ; save back in buffer as binary + djnz glba1 ; continue checking the buffer + +; need to pack bytes into the destination LBA which is in de and points to the LSB + +glba5: + +; - need to change the endian-ness + push de + ex de,hl ; clear LBA ready +; push de ; address of LBA +; pop hl ; address of input buffer + ld a,0 ; zero existing LBA variable + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + inc hl + ld (hl),a + + ex de,hl ; de now positioned at end of LBA + pop de ; restore LBA + ; de still contains dest address + ; now pack and store LBA + + + ld hl,conbuf+1 ; get character count + ld b,(hl) + inc hl ; point to first character in buffer + +glba6: + push de ; save starting address for next subsequent rotations + ld a,(hl) ; get next char from buffer + inc hl ; next character + ex de,hl ; switch to LBA + rld ; shift nibble into LBA + inc hl + rld + inc hl + rld + inc hl + rld + ex de,hl ; back to console buffer + pop de ; restore address of LBA + djnz glba6 ; process next character + + scf + ccf ; exit with carry clear = success + ret + + + + +ishex: + cp 30h ; check if less than character 0 + jp m,nothex + cp 3Ah ; check for > 9 + jp m,ishx1 ; ok, character is 1-9 + + cp 41h ; check for character less than A + jp m,nothex + cp 47H ; check for characters > F + jp m,ishx1 + + cp 61H ; check for characters < a + jp m,nothex + + cp 67H ; check for character > f + jp m,ishx1 +nothex: + scf ; set carry to indicate fail + ret + +ishx1: + scf + ccf + ret + + + +fillbuf: + ; fill sector buffer with character specified in A + ld hl,buffer + ld b,0 +fb1: + ld (hl),a ;store character in buffer + inc hl + ld (hl),a + inc hl + djnz fb1 + ret + + +hexdump: + + call print ; print heading + db "Current sector buffer contents:",CR,LF,LF,0 + + ld b,32 ; line counter + ld hl,buffer ; address of buffer to dump +hxd1: + + push bc ; save loop counter + push hl ; save address pointer + + push hl + ld a,h + call prhex ; print hi byte of address + pop hl + + push hl + ld a,l + call prhex ; print lo byte of address + ld a,' ' + call cout + pop hl + + + ld b,16 ; how many characters do we display +hxd2: + push bc + + ld a,(hl) ; get byte from buffer + inc hl + push hl + + call prhex ; display it in hex + ld a,' ' + call cout + + pop hl + pop bc + djnz hxd2 + + pop hl + + ld b,16 ; how many characters do we display +hxd3: + push bc + + ld a,(hl) ; get byte from buffer + inc hl + push hl + + call prascii ; display it in ASCII + + pop hl + pop bc + djnz hxd3 + + push hl + call crlf + + pop hl + pop bc + + ld a,b ; check for screen pause + cp 16 + jp nz,hxd4 + + push hl + push bc + call cin ; wait for a character + pop bc + pop hl + +hxd4: + djnz hxd1 ; continue if not at end of buffer + + call crlf + call crlf + ret + +prascii: + + cp 20H + jp m,pra1 ; anything less than 20H is non-printable + cp 7fH ; anything greater than 7E is non-printable + jp m,pra2 +pra1: + ld a,'.' +pra2: + call cout + ret +; +; +; +; ------------------------------------------------------------------------- +; +; LBA manipulation routines; +; +cpylba: + ; copy LBA to LBA + ; source = HL, Destination = DE + ld bc,04H + ldir + ret + +; ------------------------------------------------------------------------- + +inclba: + ld a,(hl) ; first byte + add a,1 + ld (hl),a + ret nc + + inc hl ;second byte + ld a,(hl) + add a,1 + ld (hl),a + ret nc + + inc hl ; third byte + ld a,(hl) + add a,1 + ld (hl),a + ret nc + + inc hl ; fourth byte (MSB) + ld a,(hl) + add a,1 + ld (hl),a + + ret + +; ------------------------------------------------------------------------- + +cplba: ; compare LBA + ; addresses by HL and DE + + ld a,(hl) ; start at LSB + inc hl + ex de,hl + cp (hl) + ret nz + inc hl + ex de,hl + + ld a,(hl) + inc hl + ex de,hl + cp (hl) + ret nz + inc hl + ex de,hl + + ld a,(hl) + inc hl + ex de,hl + cp (hl) + ret nz + inc hl + ex de,hl + + ld a,(hl) + inc hl + ex de,hl + cp (hl) + ret + + ret nz + inc hl + ex de,hl + + ret + +; ------------------------------------------------------------------------- + +prlba: + + call print + db "Current LBA = ",0 + ld a,(lba1+3) + call prhex + ld a,(lba1+2) + call prhex + ld a,(lba1+1) + call prhex + ld a,(lba1) + call prhex + call crlf + call crlf + ret + + + +clrlba: + ld a,0 + ld b,4 +clr32b1: + ld (hl),a + inc hl + djnz clr32b1 + ret + + +; ------------------------------------------------------------------------- + +prstatus: + call print + db "status = ",0 + + + ld a,ide_status ;read IDE status register + call ide_read + ld a,c ; returned value + call prhex + + call crlf + ret + + + + +print: + pop hl ; get address of text + ld a,(hl) ; get next character + inc hl + push hl + cp 0 + ret z ; end of text found + call cout ; output character + jp print + + +; ------------------------------------------------------------------------- + +prhex: ; proint hexadecimal digit in A + push af + srl a ; move high nibble to low + srl a + srl a + srl a + call hexnib ; convert to ASCII Hex + call cout ; send character to output device + pop af + call hexnib + call cout ; send character to output device + ret + + + +hexnib: + and 0fh ; strip high order nibble + add a,30H ; add ASCII ofset + cp 3ah ; correction necessary? + ret m + add a,7 ; correction for A to F + ret + +; ------------------------------------------------------------------------- + +cout: + ld e,a + ld c,02h ; Console output byte call + call 5 + ret + +; ------------------------------------------------------------------------- + +cin: + ld c,01h ; BDOS console function + call 5 + ret + +; ------------------------------------------------------------------------- + +crlf: + ld a,CR + call cout + ld a,LF + call cout + ret + +;------------------------------------------------------------------ +; Routines that talk with the IDE drive, these should be called by +; the main program. + + + ;read a sector, specified by the 4 bytes in "lba", + ;Return, acc is zero on success, non-zero for an error +read_sector: + call ide_wait_not_busy ;make sure drive is ready + call wr_lba ;tell it which sector we want + + ld a, ide_command + ld c, ide_cmd_read + call ide_write ; ask the drive to read it + + call ide_wait_drq ;wait until it's got the data + + bit 0,a + jp nz, get_err + ld hl, buffer + call read_data ;grab the data + ld a,0 + ret + + + ;when an error occurs, we get acc.0 set from a call to ide_drq + ;or ide_wait_not_busy (which read the drive's status register). If + ;that error bit is set, we should jump here to read the drive's + ;explanation of the error, to be returned to the user. If for + ;some reason the error code is zero (shouldn't happen), we'll + ;return 255, so that the main program can always depend on a + ;return of zero to indicate success. +get_err: + ld a,ide_err + call ide_read + ld a,c + jp z,gerr2 + ret +gerr2: + ld a, 255 + ret + + + ;write a sector, specified by the 4 bytes in "lba", + ;whatever is in the buffer gets written to the drive! + ;Return, acc is zero on success, non-zero for an error +write_sector: + call ide_wait_not_busy ;make sure drive is ready + call wr_lba ;tell it which sector we want + ld a, ide_command + ld c, ide_cmd_write + + call ide_write ;tell drive to write a sector + call ide_wait_drq ;wait unit it wants the data + bit 0,a ; check for error returned + jp nz,get_err + + ld hl, buffer + call write_data ;give the data to the drive + call ide_wait_not_busy ;wait until the write is complete + + bit 0,a + jp nz,get_err + + ld a,0 + ret + + + ;do the identify drive command, and return with the buffer + ;filled with info about the drive +drive_id: + call ide_wait_not_busy + ld a,ide_head + ld c,10100000b + call ide_write ;select the master device + call ide_wait_ready + ld a,ide_command + ld c,0ech + call ide_write ;issue the command + call ide_wait_drq + ld hl, buffer + call read_data + ret + + + ;tell the drive to spin up +spinup: + ld c,ide_cmd_spinup + ld a,ide_command + call ide_write + call ide_wait_not_busy + ret + + ;tell the drive to spin down +spindown: + call ide_wait_not_busy + ld c,ide_cmd_spindown + ld a,ide_command + call ide_write + call ide_wait_not_busy + ret + + ;initialize the IDE drive +ide_init: + ld a, ide_head + ld b, 0 + ld c, 10100000b ;select the master device + call ide_write +init1: + ld a, ide_status + call ide_read + ld a, c + + ;should probably check for a timeout here + bit 6,a ; wait for RDY bit to be set + jp z,init1 + bit 7,a + jp nz,init1 ;wait for BSY bit to be clear + + ret + + + +; IDE Status Register: +; bit 7: Busy 1=busy, 0=not busy +; bit 6: Ready 1=ready for command, 0=not ready yet +; bit 5: DF 1=fault occured inside drive +; bit 4: DSC 1=seek complete +; bit 3: DRQ 1=data request ready, 0=not ready to xfer yet +; bit 2: CORR 1=correctable error occured +; bit 1: IDX vendor specific +; bit 0: ERR 1=error occured + + + + + +;------------------------------------------------------------------ +; Not quite as low, low level I/O. These routines talk to the drive, +; using the low level I/O. Normally a main program should not call +; directly to these. + + + ;Read a block of 512 bytes (one sector) from the drive + ;and store it in memory @ HL +read_data: + ld b, 0 +rdblk2: + push bc + push hl + ld a, ide_data + call ide_read + pop hl + ld a, c + ld (hl), a + inc hl + ld a, b + ld (hl), a + inc hl + pop bc + djnz rdblk2 + ret + + + ;Write a block of 512 bytes (at HL) to the drive +write_data: + ld b,0 +wrblk2: + push bc + ld a,(hl) + ld c, a ; LSB + inc hl + ld a,(hl) + ld b, a ; MSB + inc hl + push hl + + ld a, ide_data + call ide_write + pop hl + pop bc + djnz wrblk2 + ret + + + + ;write the logical block address to the drive's registers +wr_lba: + ld a,(lba1+3) ; MSB + and 0fh + or 0e0h + ld c,a + ld a,ide_head + call ide_write + + ld a,(lba1+2) + ld c,a + ld a,ide_cyl_msb + call ide_write + + ld a,(lba1+1) + ld c,a + ld a,ide_cyl_lsb + call ide_write + + ld a,(lba1+0) ; LSB + ld c,a + ld a,ide_sector + call ide_write + + ld c,1 + ld a,ide_sec_cnt + call ide_write + + + ret + + +ide_wait_not_busy: + ld a,ide_status ;wait for RDY bit to be set + call ide_read + bit 7,c + jp nz,ide_wait_not_busy + ;should probably check for a timeout here + + ret + + +ide_wait_ready: + ld a,ide_status ;wait for RDY bit to be set + call ide_read + bit 6,c ; test for XXX + jp z,ide_wait_ready + bit 7,c + jp nz,ide_wait_ready + + ;should probably check for a timeout here + ret + + + + ;Wait for the drive to be ready to transfer data. + ;Returns the drive's status in Acc +ide_wait_drq: + ld a,ide_status ;wait for DRQ bit to be set + call ide_read + bit 7,c + jp nz,ide_wait_drq ; check for busy + bit 3,c ; wait for DRQ + jp z,ide_wait_drq + + ;should probably check for a timeout here + + ret + + + +;----------------------------------------------------------------------------- +; Low Level I/O to the drive. These are the routines that talk +; directly to the drive, via the 8255 chip. Normally a main +; program would not call to these. + + ;Do a read bus cycle to the drive, using the 8255. + ;input acc = IDE register address + ;output C = lower byte read from IDE drive + ;output B = upper byte read from IDE drive + + + + +ide_read: + push af ; save register value + push bc + call set_ppi_rd ; setup for a read cycle + pop bc + + pop af ; restore register value + call wrppictl ; write to control sigs + + or ide_rd_line ; assert RD pin + call wrppictl ; write to control sigs + + push af ; save register value + call rdppilsb ; read LSB register into A + ld c,a ; save in reg C + + call rdppimsb ; read MSB register into A + ld b,a ; save in reg C + + + pop af ; restore register value + xor ide_rd_line ; de-assert RD signal + call wrppictl ; write to control sigs + + ld a,0 + call wrppictl ; write to control sigs + ret + + + + ;Do a write bus cycle to the drive, via the 8255 + ;input acc = IDE register address + ;input register C = LSB to write + ;input register B = MSB to write + ; + + +ide_write: + push af ; save IDE register value + + push bc + call set_ppi_wr ; setup for a write cycle + pop bc + + ld a,c ; get value to be written + call wrppilsb + + ld a,b ; get value to be written + call wrppimsb + + pop af ; get saved IDE register + call wrppictl ; write to control sigs + + or ide_wr_line ; assert write pin + call wrppictl ; write to control sigs + + xor ide_wr_line ; de assert WR pin + call wrppictl ; write to control sigs + + ld a,0 + call wrppictl ; write to control sigs + ret + + +;------------------------------------------------------------------------------------------- + +ide_hard_reset: + call set_ppi_rd + ld a,ide_rst_line + call wrppictl ; write to control register + ld bc,0 +rstdly: + djnz rstdly + ld a,0 + call wrppictl ; write to control registers + ret + +;----------------------------------------------------------------------------------- +; PPI setup routine to configure the appropriate PPI mode +; +;------------------------------------------------------------------------------------ + +set_ppi_rd: + ld a,(ppibase) + add a,PIOCONT ; select Control register + ld c,a + ld a,rd_ide_8255 ;configure 8255 chip, read mode + out (c),a + ret + +set_ppi_wr: + ld a,(ppibase) + add a,PIOCONT ; select Control register + ld c,a + ld a,wr_ide_8255 ;configure 8255 chip, write mode + out (c),a + ret + +;------------------------------------------------------------------------------------ + +rdppilsb: ; read LSB + ; returns data in A + push bc + ld a,(ppibase) + add a,IDELSB ; select Control register + ld c,a + in a,(c) + pop bc + ret + + +wrppilsb: ; write LSB + ; data to be written in A + push bc + push af + ld a,(ppibase) + add a,IDELSB ; select Control register + ld c,a + pop af + out (c),a + pop bc + ret + +;-------------------------------------------------------------------------- + +rdppimsb: ; read MSB + ; returns data in A + push bc + ld a,(ppibase) + add a,IDEMSB ; select MSB Register + ld c,a + in a,(c) + pop bc + ret + + +wrppimsb: ; write LSB + ; data to be written in A + push bc + push af + ld a,(ppibase) + add a,IDEMSB ; select MSB Register + ld c,a + pop af + out (c),a + pop bc + ret + +;-------------------------------------------------------------------------- + +wrppictl: ; write to control signals + ; data to be written in A + push bc + push af + ld a,(ppibase) + add a,IDECTL ; select CTL Register + ld c,a + pop af + out (c),a + pop bc + ret + +;-------------------------------------------------------------------------- +; Storage area follows + +savsp: ds 2 ; saved stack pointer +lba1: ds 4 ; LBA used for read/write operations +lba2: ds 4 ; Start LBA for format +lba3: ds 4 ; End LBA for format +ppibase: db 60h ; base address of PPI chip to be used, default to Z80 SBC / Z80 MBC +;ppibase db 44h ; base address of PPI chip to be used + + +org 0b00h +buffer: ds 512 ; sector buffer for IDE transfers +conbuf: + db 8 ; maximum chars + db 0 ; count + ds 8 ; size of buffer + + ds 100 +stack: + + + end +