; FPGA Disk Controller Board Monitor ; ; 4/4/2021 @ 4:75$ ; ; This is a very modified version of the main FPGA Z80 SBC Monitor programs. Much code ; was needed and added to implement the IDE/CF Cards and SD cards. ; It will not work with other Z80 CPU Boards without mojor modifications. ; ; Assemble and SLR's Z80ASM Assembler (Can also use the Cromemco Assembler) ; Use:- Z80ASM SBC-MON FH ; ; NOTE. This board initially utilizes an 32K FPGA ROM module (which behaves the same as a "real" 28C256 EEPROM) ; The monitor starts at 0H and can run up to 7FFFH. ; ; To assemble under windows... ; Load Altair.EXE in Windows CMD box ; do cpm3 ; I: ; I:>Submit FPFGA_DC.SUB etc. (or a shortcut xxx.sub) ; ; FPFGA_DC.HEX is written back to the same windows folder that the PC file "altair.exe" is in. ; This HEX file must be converted to base 0000H to be loaded by Quartus ; Please see here for a discription as to how to do this. ; http://s100computers.com/My%20System%20Pages/FPGA%20Z80%20SBC/FPGA%20Z80%20SBC.htm ; ; Recent History... ; ; V0.0 4/30/2019 Started with the modified FPGA Z80 SBC Monitor. Removed the page switching menu option. ; V0.1 10/17/2020 Internal ROM IDE and SD cards menu added ; V0.2 11/07/2020 Remover Floppy Disks/WD2793 interface ; V0.21 11/16/2020 Disk copy not working, On-board menu only 3 card options ; V0.24 12/14/2020 All SD Drives working using slave CS addressing in FPGA SD Card module ; V0.25 12/14/2020 All SD Cards present flags working ; V0.26 1/9/2021 Add a variable number of sectors/track for IDE/CF drives ; V0.3 3/22/2021 Major overhaul, external IDE interface. ; V0.4 4/5/2021 Added SD card modules ; V0.5 4/28/2021 Added interrupts to monitor the old IDE/CF Card BIOS for Trk/Sec etc. ; V0.6 5/19/2012 First CPM3 Working version of Disks A,B,C,D ; V0.7 7/22/2021 Major re-write to accomidate Floppy disks etc. Remove SD card specific code ; V1.8 9/8/2021 Still problems withtype of 8255A for IDE initilization timing ; V1.8 9/14/2021 Changed polarity of floppy density and size bit ; V1.91 9/25/2021 Adapted to IDE+FDC Board ; V1.92 9/28/2021 Corrected Sector range for Floppy Disks ; V2.00 12/2/2021 Modify to allow an extarnel Dual IDE/CF Card board to subsitute for onboard FPGA IDE circuit ; >>>>>>> Remember ANY Read or Write to a sector requires that the current drive, track ; >>>>>>> and sector is already setup in the IX drive table. ; FALSE EQU 0 TRUE EQU NOT FALSE DEBUG EQU FALSE ;For a display of error codes returned from CF-Card drive ; ; H_TEST1 EQU FALSE ;Test USB output for IDE H_TEST1A EQU FALSE ;Test USB output for FDC H_TEST2 EQU FALSE ;Test RAM H_TEST3 EQU FALSE ;Test Console IO routine FORCE_COLD_BOOT EQU TRUE ;If TRUE each reset will assume a cold start setup of drive paramater tables. DISPLAY_SEC EQU FALSE ;If TRUE the sector R/W routines will be displayed over the USB port. ;Used for debugging CMDs, slows interface down. (Direct monitor commands are uneffected) MONITOR_BASE EQU 0000H ;Start of monitor after a reset RAM_BASE EQU 8000H ;Default location of RAM buffer area for IDE/CF card diagnostic routines STACK EQU 0FFF0H ;Top of available RAM MAX_TRACK_SIZE EQU 3000H ;Maximum number of bytes there will be on a track. Used for formatting a disk ;and reading a disk track SCROLL EQU 01H BELL EQU 07H SPACE EQU 20H TAB EQU 09H ;TAB ACROSS (8 SPACES FOR SD-BOARD) CR EQU 0DH LF EQU 0AH FF EQU 0CH QUIT EQU 11H ;Turns off any screen enhancements (flashing, underline etc). NO_ENH EQU 17H ;Turns off whatever is on FAST EQU 10H ;High speed scroll ESC EQU 1BH DELETE EQU 7FH BACKS EQU 08H CLEAR EQU 1AH ;TO CLEAR SCREEN RST7 EQU 38H ;RST 7 (LOCATION FOR TRAP) NN EQU 0H ;[I] INITIAL VALUE SOH EQU 1 ;For XModem etc. EOT EQU 4 ACK EQU 6 NAK EQU 15H ; ; Note on the mapping below: The DIP switches on the physical board connect to GND with pull up resistors ; OPEN/OFF switches are '1's and CLOSED/ON DIP switches are '0's ; ; BIT MAP OF IOBYTE BASE_PORT + 6H:- X X X X X X X X (if xxxxxxx0 = No USB CONSOLE IN/OUT DATA) ; Note only lowest 8 bits used |.................(if xxxx0xxx = JMP directly to onboard monitor on reset ; ; ; ; ; ;---------- 20H IDE/CF Card Interface------------------------------------------- IDE_BASE_PORT EQU 20H IDEPORTA EQU IDE_BASE_PORT ; 20H, Lower 8 bits of IDE interface (8255) IDEPORTB EQU IDE_BASE_PORT+1H ; 21H, Upper 8 bits of IDE interface IDEPORTC EQU IDE_BASE_PORT+2H ; 22H, Control lines for IDE interface IDEPORTCTRL EQU IDE_BASE_PORT+3H ; 23H, 8255 configuration port IDE_SWITCH_PORT EQU IDE_BASE_PORT+4H ; 24H, Switch for Local/External IDE Ports S100_WAIT_PORT EQU IDE_BASE_PORT+6H ; 26H Bit 0 = 0 sets S100 Bus in a wait state IDE_CS_PORT EQU IDE_BASE_PORT+7H ; 27H, Port to select IDE Drive A: or B: EXT$IDE$MODE EQU 00H ;MODE 0, FPGA IDE mode set to external IDE ports etc, [Intererupt driven Hex display/info] LOCAL$IDE$MODE EQU 01H ;MODE 1, FPGA Local IDE CMD mode [CMD driven Hex display/info] EXT$IDE$INFO$MODE EQU 02H ;MODE 2, FPGA External IDE [CMD driven Hex display/info] READCFG8255 EQU 10010010b ;Set 8255 IDEportC to output, IDEportA/B input WRITECFG8255 EQU 10000000b ;Set all three 8255 ports to output mode IDE_RESET_DELAY EQU 0F0H ;<--- Time delay to hold IDE reset line for a reset (25MHz FPGA Z80) IDE_SPEED_DELAY EQU 20 ;Time for HD to get up to speed. ;IDE control lines for use with IDEportC. IDEA0LINE EQU 01H ;direct from 8255 to IDE interface IDEA1LINE EQU 02H ;direct from 8255 to IDE interface IDEA2LINE EQU 04H ;direct from 8255 to IDE interface IDECS0LINE EQU 08H ;inverter between 8255 and IDE interface IDECS1LINE EQU 10H ;inverter between 8255 and IDE interface IDEWRLINE EQU 20H ;inverter between 8255 and IDE interface IDERDLINE EQU 40H ;inverter between 8255 and IDE interface IDERSTLINE EQU 80H ;inverter between 8255 and IDE interface ;Symbolic constants for the IDE Drive registers, which makes the ;code more readable than always specifying the address bits REGDATA EQU IDEcs0line ;01H REGERR EQU IDEcs0line + IDEa0line REGSECCNT EQU IDEcs0line + IDEa1line REGSECTOR EQU IDEcs0line + IDEa1line + IDEa0line REGCYLINDERLSB EQU IDEcs0line + IDEa2line REGCYLINDERMSB EQU IDEcs0line + IDEa2line + IDEa0line REGSHD EQU IDEcs0line + IDEa2line + IDEa1line ;(0EH) REGCOMMAND EQU IDEcs0line + IDEa2line + IDEa1line + IDEa0line ;(0FH) REGSTATUS EQU IDEcs0line + IDEa2line + IDEa1line + IDEa0line ;(0FH) REGCONTROL EQU IDEcs1line + IDEa2line + IDEa1line REGASTATUS EQU IDEcs1line + IDEa2line + IDEa1line + IDEa0line ;IDE Command Constants. These should never change. COMMANDrecal EQU 10H COMMANDread EQU 20H COMMANDwrite EQU 30H COMMANDinit EQU 91H COMMANDid EQU 0ECH COMMANDspindown EQU 0E0H COMMANDspinup EQU 0E1H ; 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 ;---------- 0F0H FLOPPY/WD2793 Interface---------------------------- FLOPPY_BASE EQU 0F0H WD2793_CMD EQU FLOPPY_BASE ;F0H, CMD register of WD 2793 WD2793_STATUS EQU FLOPPY_BASE ;F0H, Status register of WD 2793 WD2793_TRACK EQU FLOPPY_BASE + 1H ;F1H, Track Register of WD 2793 WD2793_SECTOR EQU FLOPPY_BASE + 2H ;F2H, Sector Register of WD 2793 WD2793_DATA EQU FLOPPY_BASE + 3H ;F3H, Data Register of WD 2793 WD2793_RESET EQU FLOPPY_BASE + 4H ;F4H, Reset the WD 2793 CPU_SPEED_PORT EQU FLOPPY_BASE + 6H ;F6H Port 87 Bit 7 = 0 for High Speed. Bit 7 = 1 for Low Speed CPU FDC_SELECT_PORT EQU FLOPPY_BASE + 7H ;F6H, Will contain bit flags for:- ;Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ;Bit 2, 1 if side A is selected, 0 if Side B ;Bit 3, 0 if 8" disk, 1 = 5" disk ;Bit 4, 0 if Single density, 1 = Double density (PUMP) ;Bit 5 WD2793 INTRQ 1=ON, 0=OFF ;Bit 6 Write protect flag 0 = ON, 1 = OFF ;Bit 7 Drive Head load (currently unused) DRIVE_CPM_DRIVE EQU 03H ;Bits (0,1)uses to designate the drive select. (0,1,2,3) DIRECTION_BIT EQU 7 ;Bits for the above flags 0 = BOARD DATA IN, 1 = BOARD DATA OUT WP_BIT EQU 6 ;Bit to set Write protect LED (D17) WD_INTRQ_BIT EQU 5 ;High allows WD2793 INTRQ to trigger NMI's (V2 Board) DENSITY_BIT EQU 4 SIZE_BIT EQU 3 SIDE_BIT EQU 2 ;04H STATUS_DELAY EQU 5 ;Time-out for waiting for WD2793 status port to go not busy. (~5 seconds @ 6MHz) ;Western Digital Chip 2793 Commands:- ;The 2793 chip for most commands used bits 0&1 to set the head ;motor stepping rate. 00 being 3ms (@2MH clock, to chip),11 being 15 ms. ;My Tandon 8" drives take the fastest rate. Older drives may not. RSCMD EQU 00001000B ;(0CH), RESTORE CMD <--- (Some drives require a slower stepping rate r1,r0) ; Note the V bit (bit 3) is 0, sometimes this CMD will be used to format a disk SKNCMD EQU 00011000B ;(18H), SEEK NO VERIFY CMD <-- SKCMD EQU 00011100B ;(1CH), SEEK WITH VERIFY CMD <--- RDACMD EQU 11000100B ;(C0H), READ TRACK/SECTOR ID CMD STEPIN EQU 01001000B ;(A8H), Step-in NO verify on destination track, NO update TRK register STEPOUT EQU 01111000B ;(E8H), Step-out NO verify on destination RDCMD93 EQU 10000000B ;(80H), READ SECTOR CMD WD2793 chip WRCMD93 EQU 10100000B ;(A0H), WRITE SECTOR CMD WRTCMD EQU 11110100B ;(F4H), Write a whole track command RDTCMD EQU 11100100B ;(E4H), Read a whole track command RESET_CMD EQU 11010000B ;(D0H), Reset completely the WD2793 chip ;ERROR Code masks for the WD2793 Status Register. SECTOR_RETRY_MAX EQU 4 ;Number of times to try R/W a sector before returning an error SEEK_RETRY_MAX EQU 3 ;Number of times to try seek a track before returning an error HOME_ERR_MASK EQU 80H ;Error mask for Type I Home CMD SIN_ERR_MASK EQU 90H ;Step head in one track command error bits SOUT_ERR_MASK EQU 90H ;Step head out one track command error bits SK_ERR_MASK EQU 90H ;Track Seek error bits ID_ERR_MASK EQU 9FH ;Sector ID read error mask RS_ERR_MASK EQU 0BFH ;Read sector data error mask MRS_ERR_MASK EQU 0AFH ;Multi-sector Read data error mask (not currently used) WS_ERR_MASK EQU 0EFh ;Write sector data error mask MWS_ERR_MASK EQU 0EFh ;Multi-sector Write data error mask (not currently used) RT_ERR_MASK EQU 80H ;Read Track error mask WT_ERR_MASK EQU 0E0H ;Write Track error mask ;-------- 40H S100 Bus Ports Interface and USB Port Interface --- BASE_PORT1 EQU 40H STATUS_BUS_PORT EQU BASE_PORT1 ;40H DATA_BUS_PORT EQU BASE_PORT1+1H ;41H Z80_BOARD_RESET EQU BASE_PORT1+2H ;42H To reset Z80, outputting anything hardware resets the FPGA Z80 SET_ERROR_FLAG_PORT EQU BASE_PORT1+3H ;43H 04H is sent to this port if the is a sector R/W error USB_STATUS_PORT EQU BASE_PORT1+4H ;44H Status port for USB console input port USB_DATA_PORT EQU BASE_PORT1+5H ;45H Data port for USB console port IOBYTE EQU BASE_PORT1+6H ;46H Configuration port ;---------- 50H RTC Port Interface------------------------------- BASE_PORT2 EQU 50H RTC_ADDRESS EQU BASE_PORT2 ;50H SPI data to RTC (16 bits wide) RTC_DATA_OUT EQU BASE_PORT2+1H ;51H SPI data to RTC (8 bits) RTC_DATA_IN EQU BASE_PORT2+1H ;51H SPI data from RTC RTC_CS EQU BASE_PORT2+2H ;52H RTC Chip Select RTC_STATUS EQU BASE_PORT2+2H ;52H 00H or FFH RTC_READ EQU BASE_PORT2+3H ;53H Read pulse to SPI module RTC_WRITE EQU BASE_PORT2+3H ;53H Write pulse to SPI module CONFIGURATION_PORT EQU BASE_PORT2+5H ;55H Bit 0 = 0 if Card A:, Bit 1 = 0 if Card B: ; Bits 2,3,4,5 = 0 for a Floppy disk selected ; Bit 6 = 1 if FDC Circuit present ; Bit 7 = 1 if IDE circuit present LEDS_PORT EQU BASE_PORT2+6H ;56H 6 LED's RTC_CS_LOW EQU 00H ; Bit 0 has CS (Note, HIGH to select chip) RTC_CS_HIGH EQU 01H RTC_SECONDS EQU 0H ;All registers OR 80H for WRITE Address RTC_MINUTES EQU 1H RTC_HOURS EQU 2H RTC_DAY EQU 3H RTC_DATE EQU 4H RTC_MONTH EQU 5H RTC_YEAR EQU 6H RTC_CTL_REG EQU 0FH RTC_STATUS_REG EQU 10H RTC_RAM EQU 20H ;20H -- 7FH ENABLE_OSC EQU 80H ;Bit to enable/start the RTC chip (0=start, 1=stop) WP EQU 40H ;Write Protect. Bit must be 0 to alter any other register. ;Note alarms etc are not implemented in this simple example. ;---------80H IDE Ports that interface with the CPU on the S100 bus.--------------- BASE_PORT3 EQU 80H IDE_CMD EQU BASE_PORT3 ;Status for HEX LED refresh/update SECTOR_DISPLAY EQU BASE_PORT3 + 1H TRACK_DISPLAY EQU BASE_PORT3 + 2H CMD_DISPLAY EQU BASE_PORT3 + 3H HEX_DISPLAY_PORT EQU BASE_PORT3 + 5H ;85H For HEX track/Sector HEX displays DRIVE_HEX_DISPLAY EQU BASE_PORT3 + 6H ;86H Bit0 high to this port latches drive number into HEX display FPGA_RTS EQU 01H ;01H if DC Board is reqesting to send data S100_RTS EQU 80H ;80H if S100 Bus is requesting to send data CPM_MAX_TRK EQU 0FFH ;CPM3 allows up to 8MG so 0-256 "tracks" CPM_FORMAT_BYTE EQU 0E5H ;CPM disk sector format byte ;-------------------------------------- IX OFFSET EQUATES for Disk Tables ------------------------------------- ; ; ; EQUATES FOR [IX] REGISTER OFFSETS INTO DISK FORMAT PARAMATER TABLES ; Each of the many disk formats have their own table with things like sector size, tracks/disk, sectors/track etc. ; You can add more. (Noter this table is similar but slightly different from the one used with the the ZFDC Board). ; DISK_TYPE EQU 0 ;0 0FFH for all IDE Drives, Different for 0FEH, 0FDH...Floppy disks NO_DRIVE_PRESENT EQU 1H ;1 BYTE 1 if No Card Present DRIVE_ADDR EQU 2H ;2 BYTE Byte output for Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=C, 01=D,10=E,11=F) ; Bit 2, 1 if side A is selected, 0 if Side B ; ; Bit 3, 1 if 8" disk, 0 = 5" disk ; ; Bit 4, 1 if Single Density, 0 = Double Density ; Bit 3, 1 if 8" disk, 0 = 5" disk ; Bit 4, 1 if Single Density, 0 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DRIVE_NUMBER EQU 3H ;3 BYTE Drive Number (0,1,2,3,4,5 for display) INITILIZED EQU 4H ;4 BYTE Drive itilized flag, 0 = un-initilized SEC_SIZE_FLAG EQU 5H ;5 BYTE 0=128 Byte sectors, 1 = 256, 2 = 512, 4=1024 Byte sectors SYS_TRKS EQU 6H ;6 BYTE How many tracks for system DRIVE_LETTER EQU 7H ;7 BYTE HEX of Drive Letter DRIVE_ASCII EQU 8H ;8 BYTE ASCII character of Drive # FIRST_SEC EQU 9H ;9 BYTE Number of first sector, 0 for IDE, 1 for floppies SEC_SIZE_BYTES EQU 0AH ;10 WORD (128,256,512 or 1024) NSCTRS EQU 0CH ;12 WORD Sectors/Track +1 for this disk format NTRKS EQU 0EH ;14 WORD MAX+1 Tracks/disk TRK EQU 10H ;16 WORD Current Track SEC EQU 12H ;18 WORD Current Sector SIDE EQU 14H ;20 BYTE Floppy Side 0=A, 1=B HEADR EQU 15H ;21 BYTE For Formatting GAP1 EQU 16H ;22 BYTE " GAP2 EQU 17H ;23 BYTE " GAP3 EQU 18H ;24 BYTE " GAP4 EQU 19H ;25 BYTE " GAP4R EQU 1AH ;26 BYTE " GAP_FILL_CHAR EQU 1BH ;27 BYTE Byte used in disk formating DATA_FILL_CHAR EQU 1CH ;28 BYTE " " " SPECIAL_FLAG EQU 1DH ;29 BYTE Flag byte for cases where after formatting Normally 0, CPM86_FLAG = 1 SEC_SKEW_TABLE EQU 1EH ;30 WORD Two Bytes. Address of sector skew table FORMAT_NUM EQU 20H ;32 BYTE Each format will have a unique number in the table list below. TRACK_SIZE EQU 21H ;33 WORD Two Bytes. (Used in formatting disk) SIDES_NUMBER EQU 23H ;35 BYTE Number of sides for a floppy disk (1,2) TITLE EQU 24H ;36 Text string describing the disk format (must end with 0, total table size < 80H) IDE_CS_1 EQU 00000000B ; CS* select bit for IDE Card drive 1 IDE_CS_2 EQU 00000001B ; CS* select bit for IDE Card drive 2 FL_CS_1 EQU 01111100B ; Floppy select bits for 8" DSSD Floppy drive 1, Side A, No WP (IBM System 3740) FL_CS_2 EQU 01111101B ; Floppy select bits for 8" DSSD Floppy drive 2, Side A, No WP (IBM System 3740) FL_CS_3 EQU 01101110B ; Floppy select bist for 8" DSDD Floppy drive 3, Side A, No WP (IMB System 34) FL_CS_4 EQU 01101111B ; Floppy select bits for 3.5" DSDD Floppy drive 4, Side A, No WP (IBM_PC 1.44MB Disk) FL_CS_5 EQU 01101100B ; Floppy select bits for 8" DSDD Floppy drive 4, Side A, No WP (IBM_System 34 in A: Drive port) CFCARD EQU 0FFH ; All CF & CF Card type in IX table IBM3740 EQU 080H ; Disk hardware type 8" SS DD 128 Byte sectors IBM34 EQU 060H ; Disk hardware type 8" DS DD 256 byte Sectors IBM144 EQU 040H ; Disk hardware type 3.5" DS DD 512 byte Sectors ; Commands to the FPGA_DC Board:- ; Note these commands are a sub-set of the old ZFDC and ZFDC_II Board commands CMD$SEL$DRIVE EQU 5H ;**** (Re)select an already initilized drive CMD$SET$SIDE EQU 8H ;**** This will set the active side for a floppy disk CMD$SET$TRK$SEC EQU 35H ;Set new current TRACK+SECTOR on current drive (new) CMD$READ$SECTOR EQU 10H ;**** Read data from the CURRENT sector (on current track,drive). CMD$WRITE$SECTOR EQU 11H ;**** Write data to the CURRENT sector (on current track,drive). CMD$HANDSHAKE EQU 21H ;**** Handshake command only sent during board initilization/testing CMD$SET$IDE$MODE EQU 38H ;Set IDE drive hardware mode on FPG_DC Board (Internal or External) ;Second Byte 0 = External IDE mode + Interrupt driven info (Default Mode). ;Second Byte 1 = External IDE mode + CMD driven info ;Second Byte 2 = Local FPGA Board IDE mode + CMD driven info CMD$FAST$COPY$AB EQU 39H ;Special CMD to fast copy CF Card A:->B: (All within FPGA_DC Board software) CMD$SET$HOME EQU 0AH ;This will set floppy disk head request to Track 0 of CURRENT drive CMD$GET$TRACK$ID EQU 0FH ;Read the CURRENT TRACK ID CMD$STEP$IN EQU 0BH ;Step head in one track of CURRENT drive CMD$STEP$OUT EQU 0CH ;Step head out one track of CURRENT drive CMD$SEEK$NV EQU 0DH ;Seek to track with NO verify of CURRENT drive CMD$SEEK$TRACK EQU 0EH ;Seek to track to (IX+TRK) with the track verify bit set on CURRENT drive/format CMD$TRACK$DUMP EQU 15H ;Dump complete CURRENT track to S-100 system INFO$READ$SECTOR EQU 42H ;Send info, read sector (Actual Sec Read done externally) INFO$WRITE$SECTOR EQU 43H ;Send info, write sector CMD$FORMAT$DISK EQU 44H ;Format the disk in the of the CURRENT drive CMD$FDC$COPY EQU 45H ;Fast Copy Disk C:->D: CMD$GET$DRIVE EQU 46H ;Get the current selected drive INFO$SEL$DRIVE EQU 40H ;Send info, drive select ;INFO$SET$TRK$SEC EQU 41H ;Send info, set track,sector INFO$POST$MSG EQU 41H ;Post a message on the USB Port Terminal CMD$BOARD$CONFIG EQU 52H ;Get FPGA_DC Board hardware configuration CMD$GET$TIME EQU 80H ;Get Time and Data from FPGA DC Board RTC CMD$SET$TIME EQU 81H ;Set Time and Data on FPGA DC Board RTC ;Bits 7&6 contain IDE & FDC circuit flags ;Bits 1&0 contain IDE Mode (0,1,2) CMD$FAILED EQU 0FFH ;CMD failed to exicute completely CMD$COMPLETE EQU 0F0H ;Flag returned by DC board to signal the previous CMD was completed OK CMD$ABORT EQU 0E0H ;CMD to abort the current process ;=============================================================================================================== ORG MONITOR_BASE ;<--------<<<<<< LOCATION OF START OF MONITOR (000H) >>>>>>>>>>>>>>>>> IF H_TEST1 ZAPPLE1: OUT (HEX_DISPLAY_PORT),A ;The number '33' should appear on the Sector HEX display OUT (USB_DATA_PORT),A ;And USB port device JR ZAPPLE1 ENDIF ;------------------------------------------------------------------------------------------------------------- SETUP_STACK: LD SP,STACK ;Stack always at 0FFF0H (must be valid for debugging) IF H_TEST1A LD C,0 ZAPPLE1: LD A,33H OUT (USB_DATA_PORT),A ;And USB port device LD A,C CALL DISPLAY_HEX_TRACK ;Need RAM/Stack INC C JR ZAPPLE1 ENDIF BEGIN: ;Can use the next 3 lines initially to debug hardware IM1 ;Set Z80 to Interrupt mode 1 XOR A LD I,A ;Set Interrupt Reg to 0H for any Interrupes (Currently not uesd) DI ;Disable for now LD HL,DEFAULT_NMI LD (@NMI_ADDRESS),HL ;Setup the default NMI Interrupt jump address LD HL,DEFAULT_INTERRUPT LD (@INTR_ADDRESS),HL ;Setup the default Interrupt jump address JP SETUP ;Jump over interrupt vector routines ;------------------------------------------------------------------------------------------------------------ ; <<<< Be sure the code above does not overflow past 38H >>>> ORG 38H MODE_1_INTERRUPT: DI ;<-- DISABLLE INTERRUPTS -- Must be enabled later EX AF,AF' ;So as not to mess up any of the main registers EXX LD HL,(@INTR_ADDRESS) ;Jump to the interrupt routine required for that timeout condition JP (HL) DEFAULT_INTERRUPT: PUSH IX PUSH IY LD A,(@CURRENT_IDE_MODE) ;Only IDE Mode 0 for interrupt driven updates here. CP A,EXT$IDE$MODE JR NZ,DONE_INT LD A,0 ;Set S100 bus in a wait state OUT (S100_WAIT_PORT),A ;26H CALL INT_UPDATE_HEX_DISPLAY ;An interrupt from the External IDE circuit triggered (For non-FPGA_DC BIOS's) CALL INT_UPDATE_USB_PORT_DISPLAY ;Update the USB Port output as well LD A,1 ;Remove S100 bus wait state OUT (S100_WAIT_PORT),A DONE_INT: POP IY POP IX EXX EX AF,AF' ;Return to "normal" register set EI RET ORG 66H ;<<<<< Z80 will also jump here for all NMI's NMI_INT: LD HL,(@NMI_ADDRESS) ;Jump to the interrupt routine required for that timeout condition EX (SP),HL RETN ;Jump to new location DEFAULT_NMI: ;For debugging, trap any unwanted NMI's here EX AF,AF' ;So as not to mess up any of the main registers EXX LD C,'N' CALL ZCO LD C,'M' CALL ZCO LD C,'I' CALL ZCO LD C,'?' CALL ZCO LD C,'?' CALL ZCO LD C,'?' CALL ZCO EXX EX AF,AF' ;Return to "normal" register set ;------------------------------------------------------------------------------------------------------------ ORG MONITOR_BASE +100H ;<<<<<<<< The EEPROM code will go directly to here (0100H) >>>>>>>> SETUP: IF H_TEST2 LD SP,0FFF0H ;For initial hardware debugging LD C,34H ;Test RAM. Stack is called. Will return if RAM is OK LD A,C ZAPPLE: OUT (USB_DATA_PORT),A ;And USB port device PUSH AF CALL DELAY_X ;Check RAM POP AF JR ZAPPLE DELAY_X: ;Call to here checks RAM/Stack LD B,0 XX1: DJNZ XX1 RET ENDIF IF H_TEST3 ;Test Console I/O to USB port LD SP,0FFF0H ;For initial hardware debugging LD C,30H LD A,C LD A,1 OUT (USB_STATUS_PORT),A ;Raise bit 0 to activate USB terminal ZAPPLE: AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;The number '0...F' should appear Low Sector HEX display PUSH AF LD C,'@' CALL ZCO ;Consol should show '@,char,@,char,@,char.... CALL ZCI ;The low sector Hex display should show '0,1,2...E,F,0,1... LD C,A CALL ZCO CALL DELAY_X ;Check RAM as well POP AF INC A JR ZAPPLE DELAY_X: ;Call to here checks RAM/Stack LD B,0 XX1: DJNZ XX1 RET ENDIF ; ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; ; Normal start of Monitor ; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; LD A,0 OUT (CPU_SPEED_PORT),A ;Start with LOW speed CPU (25MHz) LD (@CURRENT_CPU_SPEED),A LD A,1 ;Allow all Consol output to appear on USB port/terminal OUT (USB_STATUS_PORT),A ;Raise bit 0 to activate USB terminal CALL CRLF LD DE,SIGNON_MSG ;'FPGA DC BOARD MONITOR (@ 0000H) V0.1D J.Monahan, 4/1/2021$' CALL PRINT_STRING ;Have a valid Stack, so now we can use CALL CALL MOVE_DISK_TABLES ;Move disk table pointers to RAM XOR A LD IX,@DRIVE_1_TABLE ;CF Drive 1: selected as default LD HL,SECTOR_BUFFER ;Set default DMA address (9000H) LD (@DMA),HL ; JP Z80_MENU INITILIZE: DI ;Do not do INT's LD A,0 OUT (LEDS_PORT),A ;No drives initilized at the start IN A,(CONFIGURATION_PORT) AND A,11000000B JR NZ,BOARD_OK LD DE,NO_CIRCUITS_MSG ;Serious error, could not detect IDE or FDC circuits CALL PRINT_STRING JP Z80_MENU BOARD_OK: BIT 7,A JR NZ,IDE_CIRCUIT_ACTIVE ;If bit 7 is 1 then IDE circuit is present/active LD DE,NO_IDE_CIRCUIT_MSG CALL PRINT_STRING IN A,(CONFIGURATION_PORT) BIT 6,A JP NZ,FLOPPYS_INITILIZATION ;If bit 6 is 1 then FDC circuit is present/active IDE_CIRCUIT_ACTIVE: ; LD A,WRITECFG8255 ;10000000b, 80H, Set all three 8255 ports to output mode (For testing only!) ; LD A,READCFG8255 ;10010010b, 92H, Set 8255 IDEportC to output, IDEportA/B input (Normal mode) ; OUT (IDEportCtrl),a ;Config 8255 chip, READ mode LD A,LOCAL$IDE$MODE ;1, Select Internal IDE FPGA circuit for drive A: or B: access OUT (IDE_SWITCH_PORT),A ;Bit 0 = 1 LD DE,WILL_IDE_A_MSG ;Will inititilize IDE card A: CALL PRINT_STRING CALL CRLF LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) ;0 for drive I: OUT (IDE_CS_PORT),A ;Select drive in hardware CALL IDE_init ;Do ONE TIME init of hardware here. Any Error message will be posted from IDEinit JR Z,INIT_1_OK XOR A ;Flag as IDE Drive A inactive drive LD (IX+INITILIZED),A ;Flag as un-initilized JR IDE_2_INIT INIT_1_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag IDE drive as initilized IN A,(LEDS_PORT) SET 0,A ;Turn on LED A: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid CALL HHEXOUT XOR A ;Note for now assume 256 X 256 Tracks X Sectors for CPM/MSDOS LD (IX+TRK),A ;Set pointer to Track 0, Sec 1 LD A,1 LD (IX+SEC),A CALL INT_UPDATE_HEX_DISPLAY ;Will skip in routine if IDE+FLOPPY Board. ;----------------------------------------- IDE_2_INIT: LD DE,WILL_IDE_B_MSG ;Will inititilize IDE card b: CALL PRINT_STRING CALL CRLF LD IX,@DRIVE_2_TABLE ;IDE Drive B will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) ;1 for drive 2: OUT (IDE_CS_PORT),A ;Select drive in hardware CALL IDE_init ;Do ONE TIME init of hardware here. Any Error message will be posted from IDEinit JR Z,INIT_2_OK XOR A ;Flag as IDE Drive B inactive drive LD (IX+INITILIZED),A ;Flag as un-initilized LD DE,DISABLLE_IDE_B_MSG ;'The IDE/CF Card B: is moved offline. Only the IDE/CF Card A: is active).$' CALL PRINT_STRING JR FLOPPYS_INITILIZATION INIT_2_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag IDE drive as initilized IN A,(LEDS_PORT) SET 1,A ;Turn on LED B: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid CALL HHEXOUT XOR A ;Note for now assume 256 X 256 Tracks X Sectors for CPM/MSDOS LD (IX+TRK),A ;Set pointer to Track 0, Sec 1 LD A,1 LD (IX+SEC),A CALL INT_UPDATE_HEX_DISPLAY ;Will skip in routine if IDE+FLOPPY Board. ;-------------------------------------- FLOPPYS_INITILIZATION: IN A,(CONFIGURATION_PORT) ;Is the FDC Circuits active BIT 6,A JP NZ,HAS_FLOPPIES LD DE,NO_FLOPPY2_MSG ;Floppy Disks not detected CALL PRINT_STRING JP FLOPPYS_ALL_DONE ;Skip over floppy tables HAS_FLOPPIES: LD DE,WILL_FLOPPY_MSG ;Will Init Floppy Disks CALL PRINT_STRING LD IX,@DRIVE_3_TABLE ;Floppy Drive C will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) ;2 for drive C: OUT (FDC_SELECT_PORT),A ;Select drive in hardware ; CALL CORE_RESTORE ;Restore Head to Track 0 ; JR NZ,NO_FLOPPY_3 FLOPPY_3_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag Floppy drive C: as initilized IN A,(LEDS_PORT) SET 2,A ;Turn on LED C: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING XOR A ;0H, Flag as having a disk LD (IX+NO_DRIVE_PRESENT),A LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG ;' Tracks, Sec/Track = 0$' CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JR FLOPPY_4_INIT NO_FLOPPY_3: LD DE,NO_FLOPPY_C_MSG ;No Floppy C: was detected CALL PRINT_STRING XOR A ;Flag as Floppy Drive C as an inactive drive LD (IX+INITILIZED),A ;Flag as un-initilized DEC A LD (IX+NO_DRIVE_PRESENT),A ;FF= No card JR FLOPPY_4_INIT ;----------------------------------------------------------------------------- FLOPPY_4_INIT: CALL CRLF LD IX,@DRIVE_4_TABLE ;Floppy Drive D: will always be @DRIVE_4_TABLE LD A,(IX+DRIVE_ADDR) ;5 for drive D: OUT (FDC_SELECT_PORT),A ;Select drive in hardware ; CALL CORE_RESTORE ;Restore Head to Track 0 ; JR NZ,NO_FLOPPY_4 FLOPPY_4_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag Floppy drive as initilized IN A,(LEDS_PORT) SET 3,A ;Turn on LED C: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING XOR A ;Flag as having a disk LD (IX+NO_DRIVE_PRESENT),A LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JR FLOPPY_5_INIT NO_FLOPPY_4: LD DE,NO_FLOPPY_D_MSG ;No Floppy disk D: was detected CALL PRINT_STRING XOR A ;Flag as NOT having a disk LD (IX+INITILIZED),A ;Flag as un-initilized DEC A LD (IX+NO_DRIVE_PRESENT),A ;FF= No card JR FLOPPY_5_INIT ;------------------------------------------------------------------------------ FLOPPY_5_INIT: CALL CRLF LD IX,@DRIVE_5_TABLE ;Floppy Drive E will always be @DRIVE_5_TABLE LD A,(IX+DRIVE_ADDR) ;5 for drive E: OUT (FDC_SELECT_PORT),A ;Select drive in hardware ; CALL CORE_RESTORE ;Restore Head to Track 0 ; JR NZ,NO_FLOPPY_5 FLOPPY_5_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag Floppy drive as initilized IN A,(LEDS_PORT) SET 4,A ;Turn on LED C: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING XOR A ;Flag as having a disk LD (IX+NO_DRIVE_PRESENT),A LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JR FLOPPY_6_INIT NO_FLOPPY_5: LD DE,NO_FLOPPY_E_MSG ;No Floppy E: was detected CALL PRINT_STRING XOR A ;Flag as NOT having a disk LD (IX+INITILIZED),A ;Flag as un-initilized DEC A LD (IX+NO_DRIVE_PRESENT),A ;FF= No card JR FLOPPY_6_INIT ;-------------------------------------- FLOPPY_6_INIT: CALL CRLF LD IX,@DRIVE_6_TABLE ;Floppy drive F: will always be @DRIVE_6_TABLE LD A,(IX+DRIVE_ADDR) ;6 for drive F: OUT (FDC_SELECT_PORT),A ;Select drive in hardware ; CALL CORE_RESTORE ;Restore Head to Track 0 ; JR NZ,NO_FLOPPY_6 FLOPPY_6_OK: LD A,(IX+DRIVE_NUMBER) LD (IX+INITILIZED),A ;Flag Floppy drive as initilized IN A,(LEDS_PORT) SET 5,A ;Turn on LED C: OUT (LEDS_PORT),A CALL QUICK_DRIVE_NAME LD DE,INIT_OK_MSG ;Initilized OK CALL PRINT_STRING XOR A ;Flag as having a disk LD (IX+NO_DRIVE_PRESENT),A LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JR FLOPPYS_ALL_DONE NO_FLOPPY_6: LD DE,NO_FLOPPY_F_MSG ;No FLOPPY Card F: was detected CALL PRINT_STRING XOR A ;Flag as NOT having a card LD (IX+INITILIZED),A ;Flag as un-initilized DEC A LD (IX+NO_DRIVE_PRESENT),A ;FF= No card JR FLOPPYS_ALL_DONE FLOPPYS_ALL_DONE: LD A,1 ;Turn off S100 bus wait state (if on) OUT (S100_WAIT_PORT),A ;26H IN A,(IOBYTE) ;Default mode: is behave as a dual IDE/CF card board BIT 4,A JP Z,FLOPPY_MENU_INIT ;Force test of 8" SSSD floppy BIT 7,A ;Note IDE drives will be local for monitor JP Z,MONITOR_MENU CALL CRLF IN A,(CONFIGURATION_PORT) AND A,11000000B CP A,11000000B JP Z,BOTH_CIRCUITS BIT 7,A JP Z,FLOPPIES_CIRCUIT ;IF NO IDE CIRCUIT SKIP IDE SETUP IDE_CIRCUIT: LD IX,@DRIVE_1_TABLE ;Start with IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) ;0 for drive A: OUT (IDE_CS_PORT),A ;Select drive in hardware LD A,11111110B OUT (CONFIGURATION_PORT),A ;Update current drive CALL INT_UPDATE_HEX_DISPLAY XOR A ;Note for now assume 256 X 256 Tracks X Sectors for CPM/MSDOS LD (IX+TRK),A ;Set pointer to Track 0, Sec 1 LD A,1 LD (IX+SEC),A LD HL,SECTOR_BUFFER LD (@DMA),HL CALL LOCAL_IDE_READ_SECTOR ;See if there is a CPM Boot loader on IDE/CF card A: TRK 0, Sec 1 JR NZ,SKIP_CPM_LDR LD HL,SECTOR_BUFFER LD A,(HL) CP A,31H ;Most CPM3 Loaders will first set the Stack 31H, XXH,XXH JR NZ,SKIP_CPM_LDR LD DE,POSSIBLE_CPM_MSG ;Possible CPM3 Loader starting on IDE/CF card Track 0, Sector 0 CALL PRINT_STRING SKIP_CPM_LDR: XOR A LD (IX+TRK),A LD (IX+SEC),A ;Always begin Track 0, Sec 0. Default to the old Dual IDE/CF card S100 Board LD A,EXT$IDE$MODE ;0H, Select External IDE FPGA circuit for drive A: or B: access, Interrupt driven OUT (IDE_SWITCH_PORT),A ;Bit 0 = 0 LD (@CURRENT_IDE_MODE),A CALL CRLF LD DE,EXT_IDE0_MODE_MSG ;FPGA Set to External S100 Bus control of the IDE/CF Card Ports. (Limited USB Port Info). CALL PRINT_STRING EI ;Enable Interrupts ------------- FROM NOW ON --------------- IN A,(IOBYTE) ;FLOPPY BOARD How much info to display on USB terminal? BIT 0,A ;Note IDE drives will be local for monitor JP Z,ALL_DONE1 LD DE,IDE_3_MSG ;'IOBYTE SW1 bit 0 is HIGH so this board will update HEX LED Displays and ' CALL PRINT_STRING ;'only provide critical data to the UART-USB Terminal.$ JR DISPLAY_LOOP ALL_DONE1: LD DE,IDE_4_MSG ;'IOBYTE SW1 bit 0 is LOW so this board will update the HEX LED Displays and ' CALL PRINT_STRING ;'send info to the UART-USB terminal.$ JR DISPLAY_LOOP BOTH_CIRCUITS: ;IDE AND FDC CIRCUITS ON BOARD IN A,(IOBYTE) ;How much info to display on USB terminal? BIT 0,A ;Note IDE drives will be local for monitor JP Z,ALL_DONE2 LD DE,IDE_1_MSG ;'IOBYTE SW1 bit 0 is HIGH so this board will update the UART-USB Terminal.$' CALL PRINT_STRING ;'only provide critical data to the UART-USB Terminal.$ JP IDE_CIRCUIT ;If IDE Circuit present then we will ALWAYS boot from it ALL_DONE2: LD DE,IDE_2_MSG ;'IOBYTE SW1 bit 0 is LOW so this board will only provide critical data ' CALL PRINT_STRING ;'to the UART-USB Terminal.$' JP IDE_CIRCUIT ;If IDE Circuit present then we will ALWAYS boot from it ;----------------------------------------------------------------- FLOPPIES_CIRCUIT: ;No A: (IDE drive) so go directly to floppy disks LD IX,@DRIVE_3_TABLE ;Start with Drive 3 will always be @DRIVE_3_TABLE (C:) LD A,(IX+DRIVE_ADDR) ;FL_CS_1 for drive C: OUT (IDE_CS_PORT),A ;Select drive in hardware LD A,0D0H ;Note: This will stop any current WD2793 chip process OUT (WD2793_CMD),A XOR A ;Pulse Reset pin 19 before beginning OUT (WD2793_RESET),A INC A OUT (WD2793_RESET),A XOR A OUT (WD2793_RESET),A CALL CORE_RESTORE ;Force a restore XOR A,A OUT (WD2793_TRACK),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct INC A OUT (WD2793_SECTOR),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct CALL CRLF ; JP MONITOR_MENU IN A,(IOBYTE) ;How much info to display on USB terminal? BIT 0,A ;Note IDE drives will be local for monitor JP Z,ALL_FDC_DONE2 LD DE,IDE_3_MSG ;'IOBYTE SW1 bit 0 is HIGH so this board will update HEX LED Displays and ' CALL PRINT_STRING ;'only provide critical data to the UART-USB Terminal.$ JP DISPLAY_LOOP ALL_FDC_DONE2: LD DE,IDE_4_MSG ;'IOBYTE SW1 bit 0 is LOW so this board will update the HEX LED Displays and ' CALL PRINT_STRING ;'send info to the UART-USB terminal.$ JP DISPLAY_LOOP ;========================================================================================================================= ; ; COMMANDS ; ;========================================================================================================================= DISPLAY_LOOP: ;THE MAIN COMMAND LOOP CALL CRLF ;From now on IOBYTE bit 0 (DIP-SW1)determines if status/messages appear on the USB Treminal ; XOR A ; OUT (USB_STATUS_PORT),A ;Lower bit 0, If High this inhibits the IOBYTE bit 0 overide control of the USB terminal ;From now on IOBYTE bit 0 determines if status/messages appear on the USB Treminal EI ;Enable Interrupts by default and on startup START_CMD: ;THE MAIN COMMAND LOOP LD SP,STACK ;Just in case of a software stack imbalance/screw-up. Reset each time CALL GET_S100_STATUS JP Z,START_CMD ;<<<<<<<<<<<< Do any requested SD Card S100 Bus commands first. CALL GET_S100_TO_FPGA ;Get the actual command OR A JR Z,START_CMD LD B,A ;Store it in B IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,SKIP_CMD_DISPLAY ;Back to main loop to save time LD DE,CMD_MSG ;CR,LF,'CMD= CALL PRINT_STRING LD A,B ;Show the CMD CALL HEXOUT LD DE,H_MSG ;'H ' CALL PRINT_STRING SKIP_CMD_DISPLAY: LD A,B ;Get the command CP A,CMD$SET$IDE$MODE ;>>>>>>>>>>>>>>>>>> 38H set IDE internal/external mode JP Z,DO_SET_IDE_MODE CP CMD$BOARD$CONFIG ;<<<<<<<<<<<<<<<<< 52H Get FPGA_DC Board hardware configuration JP Z,DO_BOARD_CONFIG ; CP A,INFO$SEL$DRIVE ;<<<<<<<<<<<<<<<<< 40H Inform a drive select cmd was implemented (no more) ; JP Z,DO_INFO_SELECT_DRIVE CP A,CMD$READ$SECTOR ;<<<<<<<<<<<<<<<<< 10H, Read CF or SD card from a specified Sector JP Z,DO_CMD_RD_SECTOR CP CMD$WRITE$SECTOR ;<<<<<<<<<<<<<<<<< 11H Write data to a specified sector JP Z,DO_CMD_WR_SECTOR CP A,CMD$SET$TRK$SEC ;<<<<<<<<<<<<<<<<< 35H Set new current TRACK/SECTOR on current drive JP Z,DO_CMD_SET_TRK_SEC ;Update HEX display but no sector read/writes CP A,CMD$SEL$DRIVE ;<<<<<<<<<<<<<<<<< 05H (Re)select an already initilized CF or SD Card JP Z,DO_CMD_SELECT_DRIVE CP A,INFO$READ$SECTOR ;<<<<<<<<<<<<<<<<< 42H, Read CF or SD card from a specified Sector JP Z,DO_INFO_RD_SECTOR CP A,INFO$WRITE$SECTOR ;<<<<<<<<<<<<<<<<< 43H, Read CF or SD card from a specified Sector JP Z,DO_INFO_WR_SECTOR CP A,CMD$SET$SIDE ;<<<<<<<<<<<<<<<<< 8H This will set the active side for a floppy disk JP Z,DO_SET_SIDE CP CMD$GET$DRIVE ;<<<<<<<<<<<<<<<<< 46H Get the current selected drive JP Z,DO_CMD_GET_DRIVE CP A,CMD$FAST$COPY$AB ;<<<<<<<<<<<<<<<<< 39H Fast copy CF Card A:->B: JP Z,DO_FAST_IDE_COPY CP A,CMD$GET$TIME ;<<<<<<<<<<<<<<<<< 80H Get Time CMD JP Z,DO_GET_TIME CP CMD$SET$TIME ;<<<<<<<<<<<<<<<<< 81H Set Time and Data JP Z,DO_SET_TIME CP INFO$POST$MSG JP Z,DO_POST_MSG ;<<<<<<<<<<<<<<<<< 41H Post a message on the USB Port Terminal CP CMD$SET$HOME ;<<<<<<<<<<<<<<<<< 0AH This will set floppy disk head request to Track 0 of CURRENT drive JP Z,DO_SET_HOME CP CMD$GET$TRACK$ID ;<<<<<<<<<<<<<<<<< ;0FH Read the CURRENT TRACK ID JP Z,DO_GET_TRK_ID CP CMD$STEP$IN ;<<<<<<<<<<<<<<<<< ;0BH ;Step head in one track of CURRENT drive JP Z,DO_STEP_IN CP CMD$STEP$OUT ;<<<<<<<<<<<<<<<<< ;0CH ;Step head out one track of CURRENT drive JP Z,DO_STEP_OUT CP CMD$FORMAT$DISK ;<<<<<<<<<<<<<<<<< ;44H ;Format the disk in the of the CURRENT drive JP Z,DO_FORMAT_FDC_DISK CP A,CMD$HANDSHAKE ;<<<<<<<<<<<<<<<<< 21H ; Reply back to acknowledge board is active JP Z,DO_CMD_HANDSHAKE CP A,CMD$TRACK$DUMP ;<<<<<<<<<<<<<<<<< 15H ;Dump complete CURRENT track to S-100 system JP Z,DO_CMD_TRACK$DUMP CP A,CMD$FDC$COPY ;<<<<<<<<<<<<<<<<< 45H ;Fast Copy Disk C:->D: JP Z,DO_CMD_FDC_COPY LD DE,UNKNOWN_CMD_MSG CALL PRINT_STRING JP START_CMD ;-------------------------------------- S100 BUS REQUESTED COMMNDS ---------------------------------------- ;Second Byte 0 = External IDE mode + Interrupt driven info (Default Mode). ;Second Byte 1 = External IDE mode + CMD driven info ;Second Byte 2 = Local FPGA Board CMD driven IDE mode + CMD driven info DO_SET_IDE_MODE: CALL GET_S100_TO_FPGA ;Get IDE mode internal or external (0,1,2) PUSH AF LD A,0 ;Set S100 bus in a wait state while processing otherewise INTs break in here. OUT (S100_WAIT_PORT),A ;26H POP AF SET_IDE_0_MODE: OR A JR NZ,ISIT_1_MODE LD A,EXT$IDE$MODE ;Select External IDE FPGA circuit for drive A: or B: access LD (@CURRENT_IDE_MODE),A ;Set to the old Duel IDE/CF card interface OUT (IDE_SWITCH_PORT),A ;Bit 0 = 0 (External hardware) LD DE,EXT_IDE0_MODE_MSG ;FPGA Set to External IDE MODE CALL PRINT_STRING LD DE,IDE_1_MSG ;HEX LED displays update only CALL PRINT_STRING LD A,1 ;Release S100 bus wait state OUT (S100_WAIT_PORT),A ;26H EI ;Enable Interrupts/S100 Bus wait states JP START_CMD ;Back to main loop ISIT_1_MODE CP A,1 JR NZ,MUST_BE_2_MODE DI ;No need for interrupts/S100 bus wait state LD A,LOCAL$IDE$MODE ;1H, FPGA Local IDE CMD mode + CMD Info. LD (@CURRENT_IDE_MODE),A ;Set to the FPGA_DC Local IDE mode + CMDs OUT (IDE_SWITCH_PORT),A ;Bit 0 = 1 Local IDE Ports Hardware LD DE,EXT_IDE1_MODE_MSG ;FPGA Set to Internal IDE MODE + CMDs CALL PRINT_STRING LD DE,IDE_1_MSG ;HEX LED displays update only CALL PRINT_STRING LD A,1 ;Release S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD MUST_BE_2_MODE: DI ;No need for interrupts/S100 bus wait state LD A,EXT$IDE$INFO$MODE ;Select External IDE FPGA circuit + CMD Info LD (@CURRENT_IDE_MODE),A ;Set to the FPGA_DC Board OUT (IDE_SWITCH_PORT),A ;Bit 0 = 0 (External hardware) LD DE,EXT_IDE2_MODE_MSG ;FPGA Set to External IDE MODE + CMDs CALL PRINT_STRING LD DE,IDE_1_MSG ;HEX LED displays update only CALL PRINT_STRING LD A,1 ;Release S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD ;--------------------------------------------------------------------------- DO_CMD_HANDSHAKE: ;Return the initilization Handshake CMS back to the S100 bus LD C,CMD$HANDSHAKE CALL SEND_FPGA_TO_S100 ;Send CMD_HANDSHAKE in [C] back to S100 JP START_CMD ;--------------------------------------------------------------------------- DO_CMD_SELECT_DRIVE CALL GET_S100_TO_FPGA ;05H Get the requested drive CP A,'A' JR Z,SEL_CF_A CP A,IDE_CS_1 ;<<<< TEMPORY PATCH FOR CPM BIOS JR Z,SEL_CF_A CP A,'B' JR Z,SEL_CF_B CP A,IDE_CS_2 ;;<<<< TEMPORY PATCH JR Z,SEL_CF_B CP A,'C' JP Z,SEL_FLOPPY_C ;FLOPPY card C: CP A,'D' JP Z,SEL_FLOPPY_D ;FLOPPY Card D: CP A,'E' JP Z,SEL_FLOPPY_E ;FLOPPY card E: CP A,'F' JP Z,SEL_FLOPPY_F ;FLOPPY Card F: PUSH AF LD DE,INVALID_DR_MSG ;Invalid Drive CALL PRINT_STRING POP AF CALL HHEXOUT ;Show selected drive # LD IX,@DRIVE_0_TABLE ;Set to invalid drive LD C,0FFH CALL SEND_FPGA_TO_S100 ;Return error - no drive JP START_CMD ;Back to main loop SEL_CF_A: LD IX,@DRIVE_1_TABLE ;Get from RAM store the current drive type for hardware Drive [A:] LD A,(IX+INITILIZED) OR A JP Z,CF_A_NOT_INITILIZED ;Not initilized LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware A_ALREADY_SELECTED: LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter CALL REFRESH_TRK_SEC ;Update HEX display (using current stored values) IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,CF_A_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop SEL_CF_B: LD IX,@DRIVE_2_TABLE ;Get from RAM store the current drive type for hardware Drive [B:] LD A,(IX+INITILIZED) OR A JP Z,CF_B_NOT_INITILIZED ;Not initilized LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware B_ALREADY_SELECTED: LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter CALL REFRESH_TRK_SEC ;Update HEX display (using current stored values) IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,CF_B_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop SEL_FLOPPY_C: LD IX,@DRIVE_3_TABLE ;Get from RAM store the current drive type for hardware Drive [C:] LD A,(IX+INITILIZED) OR A JP Z,FL_C_NOT_INITILIZED ;Not previously initilized LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card C: CALL FDC_INITILIZE_NO_WAIT ;Initilize a new floppy disk LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,FLOPPY_C_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop SEL_FLOPPY_D: LD IX,@DRIVE_4_TABLE ;Get from RAM store the current drive type for hardware Drive [D] LD A,(IX+INITILIZED) OR A JP Z,FL_D_NOT_INITILIZED ;Not previously initilized LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: CALL FDC_INITILIZE_NO_WAIT ;Initilize a new floppy disk LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,FLOPPY_D_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop SEL_FLOPPY_E: LD IX,@DRIVE_5_TABLE ;Get from RAM store the current drive type for hardware Drive [E] LD A,(IX+INITILIZED) OR A JP Z,FL_E_NOT_INITILIZED ;Not previously initilized LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card E: CALL FDC_INITILIZE_NO_WAIT ;Initilize a new floppy disk LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,FLOPPY_E_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop SEL_FLOPPY_F: LD IX,@DRIVE_6_TABLE ;Get from RAM store the current drive type for hardware Drive [D] LD A,(IX+INITILIZED) OR A JP Z,FL_F_NOT_INITILIZED ;Not previously initilized LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card F: CALL FDC_INITILIZE_NO_WAIT ;Initilize a new floppy disk LD A,(IX+DRIVE_ASCII) LD C,A CALL SEND_FPGA_TO_S100 ;Return confirmation drive letter IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop if no display req LD DE,FLOPPY_F_SELECTED_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop CF_A_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,CF_A_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop CF_B_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,CF_B_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop FL_C_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,FLOPPY_C_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop FL_D_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,FLOPPY_D_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop FL_E_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,FLOPPY_E_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop FL_F_NOT_INITILIZED: LD C,0 CALL SEND_FPGA_TO_S100 ;Return failed confirmation drive number 0 LD DE,FLOPPY_F_NOT_INIT_MSG ;Say so CALL PRINT_STRING JP START_CMD ;Back to main loop ;--------------------------------------------------------------------------- DO_CMD_GET_DRIVE: ;Return the current drive ASCII letter LD C,(IX+DRIVE_LETTER) CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop ;--------------------------------------------------------------------------- DO_INFO_SELECT_DRIVE: ;Just update USB Display about new drive select ALREADY DONE CALL QUICK_DRIVE_NAME ;Show drive type+name LD DE,SELECTED_MSG ;Selected CALL PRINT_STRING JP START_CMD ;Back to main loop ;--------------------------------------------------------------------------------------------------------------- DO_CMD_RD_SECTOR: ;10H, READ A CF/SD CARD OR FLOPPY DISK AND UPDATE THE HEX DISPLAY & INFO CALL GET_S100_TO_FPGA ;Get DMA Address LD H,A CALL GET_S100_TO_FPGA LD L,A LD (@DMA_DISPLAY),HL ;Store here for later info display CALL GET_S100_TO_FPGA ;Get the required Track LD (IX+TRK),A LD H,A CALL GET_S100_TO_FPGA ;Get the requested Sector LD (IX+SEC),A LD H,A LD A,(IX+DISK_TYPE) ;SD or CF card CP A,0FFH JR NZ,IS_FLOPPY_READ ;---------------------------------- IS_IDE_READ: CALL S100_IDE_READ_SECTOR ;Read CF/SD card sector LOCALLY and send data to S100 bus JP NZ,RD_SEC_ERROR ;Abort, Tell S100 Bus a sector read error was recieved JR CARD_READ_DONE IS_FLOPPY_READ: LD HL,SECTOR_BUFFER LD (@DMA),HL CALL S100_FDC_READ_SECTOR ;<<<<<<<<<<< Read Floppy sector and send data to S100 bus JP NZ,RD_SEC_ERROR ;Abort, Tell S100 Bus a sector read error was recieved LD HL,SECTOR_BUFFER LD E,(IX+SEC_SIZE_BYTES) ;Bytes/sector LD D,(IX+SEC_SIZE_BYTES+1) S100_READ_FLOPPY: ;Send data to S100 BUS LD C,(HL) CALL SEND_FPGA_TO_S100 ;Send data in [C] back to S100 INC HL DEC DE LD A,E OR A,D JR NZ,S100_READ_FLOPPY ;---------------------------------- CARD_READ_DONE: LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 LD A,(IX+DRIVE_LETTER) ;Update the board HEX displays (Note HEX not ASCII) OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track LD A,(IX+SEC) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop to save time LD A,0 ;Set S100 bus in a wait state (Don't want INT's messing things up) OUT (S100_WAIT_PORT),A ;26H CALL QUICK_DRIVE_NAME ;'IDE/SD Drive or Floppy $' LD DE,DMA_H_MSG ;' DMA= $ CALL PRINT_STRING LD HL,(@DMA_DISPLAY) LD A,H CALL HEXOUT LD A,L CALL HHEXOUT LD DE,READ_MSG ;' READ Sector, Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT LD A,(IX+DISK_TYPE) ;Update the board HEX displays (Note HEX not ASCII) CP A,CFCARD JR Z,RD_SKIP_SIDES LD DE,CURRENT_SIDE_MSG CALL PRINT_STRING CALL GET_CURRENT_SIDE JR NZ,RD_SHOW_A_SIDE LD C,'B' CALL ZCO JR RD_SKIP_SIDES RD_SHOW_A_SIDE: LD C,'A' CALL ZCO RD_SKIP_SIDES: LD A,1 ;Turn off S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD ;to indicate an error. Back to main loop RD_SEC_ERROR: LD DE,SEC_RD_ERR_SENT ;'A sector read error notice was sent to the S100 bus CALL PRINT_STRING CALL SET_ERROR_FLAG ;Flag the S100 Bus (currently stuck in a loop) there is a problem JP START_CMD ;Back to main loop ;------------------------------------------------------------------------------------------------------ DO_INFO_RD_SECTOR: ;42H, Display Sector Read Info for non CMD drive IDE/CF card Sector reads CALL GET_S100_TO_FPGA ;Get DMA Address LD H,A CALL GET_S100_TO_FPGA LD L,A LD (@DMA_DISPLAY),HL CALL GET_S100_TO_FPGA ;from 10H Read sector CMD get the requested Card Track LD (IX+TRK),A CALL GET_S100_TO_FPGA ;Get the requested Card Sector LD (IX+SEC),A LD A,(IX+DRIVE_LETTER) ;Update the board HEX displays (Note HEX not ASCII) OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track LD A,(IX+SEC) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop to save time LD A,0 ;Set S100 bus in a wait state (Don't want INT's messing things up) OUT (S100_WAIT_PORT),A ;26H CALL QUICK_DRIVE_NAME LD DE,DMA_H_MSG ;' DMA= $ CALL PRINT_STRING LD HL,(@DMA_DISPLAY) LD A,H CALL HEXOUT LD A,L CALL HHEXOUT LD DE,READ_MSG ;' READ Sector, Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT LD A,(IX+DISK_TYPE) ;Update the board HEX displays (Note HEX not ASCII) CP A,CFCARD JR Z,INFO_RD_SKIP_SIDES LD DE,CURRENT_SIDE_MSG CALL PRINT_STRING CALL GET_CURRENT_SIDE JR NZ,INFO_RD_SHOW_A_SIDE LD C,'B' CALL ZCO JR INFO_RD_SKIP_SIDES INFO_RD_SHOW_A_SIDE: LD C,'A' CALL ZCO INFO_RD_SKIP_SIDES: LD A,1 ;Turn off S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD ;to indicate an error. Back to main loop ;------------------------------------------------------------------------------------------------------------------------ DO_CMD_WR_SECTOR: ;11H, WRITE TO A CF/SD OR FLOPPY DISK AND UPDATE THE HEX DISPLAY CALL GET_S100_TO_FPGA ;Get DMA Address LD H,A CALL GET_S100_TO_FPGA LD L,A LD (@DMA_DISPLAY),HL CALL GET_S100_TO_FPGA ;Get the requested SD Card Track LD (IX+TRK),A CALL GET_S100_TO_FPGA ;Get the requested SD Card Sector LD (IX+SEC),A LD A,(IX+DISK_TYPE) ;SD or CF card CP A,0FFH JR NZ,IS_FLOPPY_WRITE ;------------------- IS_IDE_WRITE: CALL S100_IDE_WRITE_SECTOR ;<<<<<<<<<<<<<<< Write CD card sector to local RAM JP NZ,WR_SEC_ERROR ;Abort, Tell S100 Bus a sector read error was recieved JR CARD_WRITE_DONE IS_FLOPPY_WRITE: LD HL,SECTOR_BUFFER ;Actual SD card read was OK so is safe to send to S100 bus LD (@DMA),HL LD E,(IX+SEC_SIZE_BYTES) ;Bytes/sector LD D,(IX+SEC_SIZE_BYTES+1) S100_WRITE_FLOPPY: ;Get data from S100 BUS CALL GET_S100_TO_FPGA ;Get data in [A] from S100 LD (HL),A INC HL DEC DE LD A,E OR A,D JR NZ,S100_WRITE_FLOPPY CALL S100_FDC_WRITE_SECTOR ;<<<<<<<<< Write floppy sector and send data to S100 bus from @DMA JP NZ,WR_SEC_ERROR ;Abort, Tell S100 Bus a sector Write error was recieved ;------------------- CARD_WRITE_DONE: LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 LD A,(IX+DRIVE_LETTER) ;Update the board HEX displays OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track LD A,(IX+SEC) LD C,A ;store it43 RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop to save time LD A,0 ;Set S100 bus in a wait state (Don't want INT's messing things up) OUT (S100_WAIT_PORT),A ;26H CALL QUICK_DRIVE_NAME ;'IDE/SD Drive or Floppy $' LD DE,DMA_H_MSG ;' DMA= $ CALL PRINT_STRING LD HL,(@DMA_DISPLAY) LD A,H CALL HEXOUT LD A,L CALL HHEXOUT LD DE,WRITE_MSG ;': WRITE Sector, Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT LD A,(IX+DISK_TYPE) ;Update the board HEX displays (Note HEX not ASCII) CP A,CFCARD JR Z,WR_SKIP_SIDES LD DE,CURRENT_SIDE_MSG CALL PRINT_STRING CALL GET_CURRENT_SIDE JR NZ,WR_SHOW_A_SIDE LD C,'B' CALL ZCO JR WR_SKIP_SIDES WR_SHOW_A_SIDE: LD C,'A' CALL ZCO WR_SKIP_SIDES: LD A,1 ;Turn off S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD ;Back to main loop WR_SEC_ERROR: LD DE,SEC_WR_ERR_SENT ;'A sector write error notice was sent to the S100 bus CALL PRINT_STRING CALL SET_ERROR_FLAG ;Flag the S100 Bus (currently stuck in a loop) there is a problem JP START_CMD ;Back to main loop DO_INFO_WR_SECTOR: CALL GET_S100_TO_FPGA ;Get DMA Address LD H,A CALL GET_S100_TO_FPGA LD L,A LD (@DMA_DISPLAY),HL CALL GET_S100_TO_FPGA ;from 10H Read sector CMD get the requested Card Track LD (IX+TRK),A CALL GET_S100_TO_FPGA ;Get the requested Card Sector LD (IX+SEC),A LD A,(IX+DRIVE_LETTER) ;Update the board HEX displays (Note HEX not ASCII) OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track LD A,(IX+SEC) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track IN A,(IOBYTE) ;Is runtime Track/Sec displays requested BIT 0,A JP NZ,START_CMD ;Back to main loop to save time LD A,0 ;Set S100 bus in a wait state (Don't want INT's messing things up) OUT (S100_WAIT_PORT),A ;26H CALL QUICK_DRIVE_NAME LD DE,DMA_H_MSG ;' DMA= $ CALL PRINT_STRING LD HL,(@DMA_DISPLAY) LD A,H CALL HEXOUT LD A,L CALL HHEXOUT LD DE,WRITE_MSG ;' WRITE Sector, Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT CALL CRLF LD A,1 ;Turn off S100 bus wait state OUT (S100_WAIT_PORT),A ;26H JP START_CMD ;Back to main loop ;----------------------------------------------------------------------------------------------------------- DO_FAST_IDE_COPY: ;39H Fast copy A:->B: LD DE,FAST_COPY_MSG ;'Fast Copy of CF Card A: -> B: At Track ' CALL PRINT_STRING PUSH IX ;Store Current IX Table Pointer LD A,(@CURRENT_IDE_MODE) LD (@MODE_STORE),A LD A,LOCAL$IDE$MODE ;1H, Select Local IDE FPGA circuit for drive A: & B: access OUT (IDE_SWITCH_PORT),A ;All internal no need for messages etc. LD IX,@DRIVE_2_TABLE ;IDE destination Drive will always be @DRIVE_2_TABLE XOR A LD (IX+TRK),A LD (IX+SEC),A LD IX,@DRIVE_1_TABLE ;IDE source Drive will always be @DRIVE_1_TABLE XOR A LD (IX+TRK),A LD (IX+SEC),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA FAST_DRIVE_COPY_LOOP: LD HL,(@DMA_STORE) ;Start Buffer DMA ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware IN A,(CONFIGURATION_PORT) AND 11000000B CP 11000000B JR OVER_DISPLAY CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display OVER_DISPLAY: call LOCAL_IDE_READ_SECTOR ;<<<<<< Read actual sector at @DMA >>>>>>> JP Z,DR1_FAST_COPY_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF JP FAST_COPY_ERROR DR1_FAST_COPY_OK: CALL SEC_BUMP ;Point to next sector LD HL,(@DMA_STORE) ;Start Buffer DMA ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_2_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware call LOCAL_IDE_WRITE_SECTOR ;<<<<<<<<< write actual sector at @DMA >>>>>> jp z,DR2_FAST_COPY_OK1 ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort JP FAST_COPY_ERROR DR2_FAST_COPY_OK1: CALL GET_S100_STATUS ;Any keyboard character from S100 Bus to stop the process JP Z,FAST_DRIVE_BUMP CALL GET_S100_TO_FPGA ;Get the 2nd command CP A,CMD$ABORT JP Z,ABORT_FAST_COPY FAST_DRIVE_BUMP: LD C,BACKS ;Backspsce 3 spaces CALL ZCO CALL ZCO CALl ZCO LD A,(IX+TRK) CALL HHEXOUT ;Track XXH CALL SEC_BUMP ;Point to next sector JP NZ,FAST_DRIVE_COPY_LOOP FAST_COPY_DONE: ld de,DRIVE_COPY_OK_MSG ;Card copy complete call PRINT_STRING LD C,CMD$COMPLETE ;Tell S100 Bus we are done CALL SEND_FPGA_TO_S100 JP FAST_FINISH_COPY ABORT_FAST_COPY: LD DE,FAST_ABORT_MSG ;Fast Copy of CF card A:->B: Aborted call PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus we had an error CALL SEND_FPGA_TO_S100 JP FAST_FINISH_COPY FAST_COPY_ERROR: LD DE,FAST_RW_ERROR_MSG ;Fast Copy of CF card A:->B: R/W Error call PRINT_STRING JP FAST_FINISH_COPY FAST_FINISH_COPY: LD A,(@MODE_STORE) LD (@CURRENT_IDE_MODE),A OUT (IDE_SWITCH_PORT),A POP IX ;Get back the origional Drive Table LD HL,SECTOR_BUFFER LD (@DMA),HL call CRLF ;NZ Abort JP START_CMD ;Back to main loop ;---------------------- POST A LOCAL MESSAGE FROM THE S100 BUS ------------------------------------------------- DO_POST_MSG: CALL GET_S100_TO_FPGA ;Get string characters up to 0H OR A JP Z,START_CMD LD C,A CALL ZCO JR DO_POST_MSG ;--------------------------------GET THE CURRENT BOARD HARDWARE CONFIGURATION ------------------------------ DO_BOARD_CONFIG: LD DE,CONFIG_MSG ;Send back the Boards hardware configuration CALL PRINT_STRING IN A,(CONFIGURATION_PORT) AND A,11000000B LD B,A LD A,(@CURRENT_IDE_MODE) ;Get to the IDE/CF Mode AND A,00000011B OR A,B LD C,A CALL HHEXOUT CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_CMD_SET_TRK_SEC ;Update HEX display but no sector read or write LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select Floppy D:--F: CALL GET_S100_TO_FPGA ;Get the requested SD Card Track LD (IX+TRK),A CALL GET_S100_TO_FPGA ;Get the requested SD Card Sector LD (IX+SEC),A CALL QUICK_DRIVE_NAME ;'IDE or SD Drive $' LD DE,SET_TRK_SEC_MSG ;' Set Trk/Sec $' CALL PRINT_STRING LD DE,TRK_MSG ;' Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT CALL CRLF CALL REFRESH_TRK_SEC JP START_CMD ;Back to main loop REFRESH_TRK_SEC: LD A,(IX+DRIVE_LETTER) ;Hex of drive letter (A,B...F) OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track LD A,(IX+SEC) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;High Nibble of Track LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;Low nibble of track RET ;-------------------------------------------------------------------------------------------------------- DO_SET_HOME LD A,(IX+DISK_TYPE) ;Floppy drives letter (C...F) CP A,CFCARD JR Z,CF_RESTORE FL_RESTORE: XOR A LD (IX+TRK),A LD A,1 LD (IX+SEC),A ;Always begin Track 0, Sec 1. CALL SET_A_SIDE ;Set pointer to Side A if Floppy CALL CORE_RESTORE JR NZ,RESTORE_CMD_ERR CALL LED_TRK_SEC ; LD DE,SET_FDC_HOME_MSG ;' Restore Disk head to Track 0$' CALL PRINT_STRING LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop CF_RESTORE: XOR A LD (IX+TRK),A LD (IX+SEC),A ;Always begin Track 0, Sec 0. LD DE,SET_CF_HOME_MSG ;'Set IDE/CF Card to Track 0$' CALL PRINT_STRING LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop RESTORE_CMD_ERR: LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;to indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_GET_TRK_ID LD DE,GET_TRK_ID_MSG ;' Track ID = $' CALL PRINT_STRING CALL CORE_GET_TRACK_ID ;Get 6 Bytes to ID_BUFFER PUSH AF ;Save Erropr Flag LD HL,ID_BUFFER ;Get Location of ID Buffer LD B,6 ;Six bytes total TRK_ID1: LD A,(HL) CALL HEXOUT ;Send 6 bytes to USB Terminal LD C,A CALL SEND_FPGA_TO_S100 INC HL DJNZ TRK_ID1 POP AF ;Get error flag JR NZ,TRK_ID_ERR LD HL,ID_BUFFER ;Get Location of ID Buffer LD A,(HL) LD (IX+TRK),A ;Update HEX Display and pointer CALL LED_TRK_SEC LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop TRK_ID_ERR: LD DE,TRK_ID_ERR_MSG ;' Track ID Error $' CALL PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_STEP_IN: LD DE,STEP_IN_MSG ;' Step Head in one Track' CALL PRINT_STRING CALL CORE_STEP_IN LD A,(IX+TRK) INC A CP A,(IX+NTRKS) JR Z,AT_INSIDE LD (IX+TRK),A CALL LED_TRK_SEC LD C,(IX+TRK) CALL SEND_FPGA_TO_S100 ;Send updated track LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop AT_INSIDE: LD DE,FULL_IN_MSG ;' Head in at Max Track Number' CALL PRINT_STRING LD C,(IX+TRK) CALL SEND_FPGA_TO_S100 ;Send updated track LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_STEP_OUT: LD A,(IX+TRK) OR A,A JR Z,AT_ZERO DEC A LD (IX+TRK),A LD DE,STEP_OUT_MSG ;' Step Head out one Track' CALL PRINT_STRING CALL CORE_STEP_OUT CALL LED_TRK_SEC LD C,(IX+TRK) CALL SEND_FPGA_TO_S100 ;Send updated track LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop AT_ZERO:CALL LED_TRK_SEC LD DE,FULL_OUT_MSG ;' Head is at Track 0.$' CALL PRINT_STRING LD C,0 CALL SEND_FPGA_TO_S100 ;Send updated track 0 LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_SET_SIDE: ; 8H This will set the active side for a floppy disk LD DE,DO_SIDE_MSG ;'Set active side of current Floppy disk to Side ' CALL PRINT_STRING CALL GET_S100_TO_FPGA ;Get the required Side CALL HEXOUT OR A,A JR Z,DO_SIDE_B CP A,1 JR Z,DO_SIDE_A JR INVALID_SIDE ;Must be 0 or 1 DO_SIDE_A: LD C,'A' CALL ZCO LD C,'-' CALL ZCO LD C,'-' CALL ZCO CALL SET_A_SIDE LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop DO_SIDE_B: LD C,'B' CALL ZCO LD A,(IX+SIDES_NUMBER) CP A,2 ;Is it a two sided disk JP NZ,INVALID_SIDE CALL SET_B_SIDE LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop INVALID_SIDE: LD DE,BAD_SIDE_MSG ;'Invalid active side selected for the current Floppy disk.' CALL PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_FORMAT_FDC_DISK: ;CMD 44H Format the current floppy disk CALL CORE_RESTORE ;Lower head/Start Motor. Must be done here/early. Absolutly critical the disk ;is up to speed. If not Track 0, Sec 2 is not written correctly. ;Took two days to figure this out! IN A,(STATUS_BUS_PORT) ;The CORE_RESTORE loop will continue until the disk format byte type is AND A,S100_RTS ;sent. There must be a fraction of a second delay. Normally its JP Z,DO_FORMAT_FDC_DISK ;a user entered confirm to format the disk. Head Load should be configured ;on the drive to start the motor. CALL GET_S100_TO_FPGA ;Get the requested disk format type CALL HEXOUT CP A,1 JR Z,FORMAT$1 CP A,2 JR Z,FORMAT$2 CP A,3 JR Z,FORMAT$3 CP A,4 JR Z,FORMAT$4 JP FORMAT_FDC_SELECT_PORT_ERROR FORMAT$1: LD (@DISK_FORMAT),A LD A,(IX+DISK_TYPE) ;Check its not a 3.25" disk CP A,IBM144 JP Z,BAD_FORMAT_ERROR LD A,1 LD (@SIDE_COUNT),A ;One side only LD DE,FORMAT_DISK1_MSG ;'Formatting SDSS 8" IBM 3740 Disk$ CALL PRINT_STRING JP GOT_FORMAT FORMAT$2: LD (@DISK_FORMAT),A LD A,(IX+DISK_TYPE) ;Check its not a 3.25" disk CP A,IBM144 JP Z,BAD_FORMAT_ERROR LD A,2 LD (@SIDE_COUNT),A ;Two sides LD DE,FORMAT_DISK2_MSG ;'Formatting SDDS 8" Disk$ CALL PRINT_STRING JP GOT_FORMAT FORMAT$3: LD (@DISK_FORMAT),A LD A,(IX+DISK_TYPE) ;Check its a 3.25" disk CP A,IBM144 JP Z,BAD_FORMAT_ERROR LD A,2 LD (@SIDE_COUNT),A ;Two sides LD DE,FORMAT_DISK3_MSG ;'Formatting DDDS 3.25" Disk$ CALL PRINT_STRING JP GOT_FORMAT FORMAT$4: LD (@DISK_FORMAT),A LD A,(IX+DISK_TYPE) ;Check its a 3.25" disk CP A,IBM144 JP NZ,BAD_FORMAT_ERROR LD A,2 LD (@SIDE_COUNT),A ;Two sides LD DE,FORMAT_DISK4_MSG ;'Formatting DDDS 3.25" Disk$ CALL PRINT_STRING JP GOT_FORMAT GOT_FORMAT: CALL CORE_RESTORE XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) LD A,1 LD (IX+SEC),A CALL SET_A_SIDE CMD_FORMAT_FDC_DISK: LD DE,FORMAT_TRK_MSG ;'Format Track = $' CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT LD A,(IX+TRK) OUT (WD2793_DATA),A ;Put required track# in data register CALL BUILD_TRACK ;<<<<<<< Build a complete track image in RAM @ SECTOR_BUFFER LD HL,SECTOR_BUFFER ;To start of Buffer LD E,(IX+TRACK_SIZE) LD D,(IX+TRACK_SIZE+1) DI ;Disable Interrupts -- just in case LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,(IX+TRK) OUT (WD2793_DATA),A ;Put required track# in data register LD A,WRTCMD ;Send the Write Track CMD OUT (WD2793_CMD),A LD C,WD2793_DATA ;Data port in [C] below CALL DELAY_30uS ; <<<<<<<<<<<<<<<<<<<<< WRITE_TRACK - SIDE A >>>>>>>>>>>>>>>>>>>>> DWT2: IN A,(WD2793_Status) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,DWT2 ;if no data LD A,(HL) OUT (C),A INC HL DEC DE LD A,E OR A,D JR NZ,DWT2 LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,WT_ERR_MASK CALL WD2793_WAIT ;Wait until chip is ready JR NZ,FORMAT_CMD_ERROR LD A,(IX+TRK) INC A CP A,(IX+NTRKS) JP Z,CMD_FORMAT_SIDE_DONE LD (IX+TRK),A LD A,STEPIN OUT (WD2793_CMD),A ;No need to check, always works CALL LED_TRK_SEC ;Update LED HEX display IN A,(STATUS_BUS_PORT) ;Was an abort requested from the S100 Bus BIT 6,A JP NZ,ABORT_FORMAT JP CMD_FORMAT_FDC_DISK ;Do the next track CMD_FORMAT_SIDE_DONE: LD A,(@SIDE_COUNT) ;Is it for two sides DEC A LD (@SIDE_COUNT),A JP Z,FINISH_DISK_FORMAT ;No then we are done LD DE,FORMATING_B_SIDE ;'Formating B side$' CALL PRINT_STRING CALL CORE_RESTORE ;Lower head/Start Motor. Must be done here/early. Absolutly critical the disk XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) LD A,1 LD (IX+SEC),A CALL SET_B_SIDE ;<-- SET B SIDE CALL LED_TRK_SEC ;Update LED HEX display JP CMD_FORMAT_FDC_DISK ;Repeat the whole process on side 2 FINISH_DISK_FORMAT: LD C,CMD$COMPLETE ;Tell S100 Bus the wait is over and read was OK CALL SEND_FPGA_TO_S100 XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) LD A,1 LD (IX+SEC),A CALL SET_A_SIDE CALL LED_TRK_SEC ;Update LED HEX display LD DE,FORMAT_DISK_DONE ;'Format Disk Complete' CALL PRINT_STRING JP START_CMD ;Back to main loop FORMAT_CMD_ERROR: LD DE,FORMAT_ERR1_MSG ;'Format Error detected for Track $' CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop FORMAT_FDC_SELECT_PORT_ERROR: LD DE,FDC_SELECT_PORT_MSG ;'Unknown disk type request$' CALL PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop BAD_FORMAT_ERROR: LD DE,FDC_BAD_FORMAT_MSG ;'Incorrect Disk Format request$' CALL PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ABORT_FORMAT: LD DE,FORMAT_ABORT_MSG ;'Abort Format requested$' CALL PRINT_STRING JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_CMD_TRACK$DUMP: LD DE,TRACK_DATA_MSG ;15H, Complete contents of Track CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT PUSH AF CALL CORE_RESTORE POP AF LD (IX+TRK),A CALL CORE_SEEK ;<<<<<<<< Track is in [A] LD HL,SECTOR_BUFFER ;Will will load the complete track image here (9000H) LD BC,MAX_TRACK_SIZE ;so for debugging it can be seen with the monitor command what was read XOR A,A TRK_FILL: LD (HL),A ;Fill the whole Buffer area with "blank" bytes INC HL DEC C JR NZ,TRK_FILL DEC B JR NZ,TRK_FILL ;Do 4K, (should be overkill)! DI ;Just in case LD E,(IX+TRACK_SIZE) ;Total number of bytes on a track LD D,(IX+TRACK_SIZE+1) LD HL,SECTOR_BUFFER ;Will will build the complete track image here LD C,WD2793_DATA ;Data port for collection LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,RDTCMD ;Send the Read Track CMD OUT (WD2793_CMD),A CALL DELAY_30uS DUMP_TRK_RD: IN A,(WD2793_STATUS) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,DUMP_TRK_RD ;if no data IN A,(C) LD [HL],A ;For some reason INI does NOT work. Seems too fast! INC HL DEC DE LD A,E OR A,D JR NZ,DUMP_TRK_RD LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,RT_ERR_MASK CALL WD2793_WAIT ;Wait 30uS, then check status and return JR Z,DUMP_TRACK_OK LD DE,TRACK_DATA_ERR ;Read Track Error was detected CALL PRINT_STRING LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop DUMP_TRACK_OK: LD HL,SECTOR_BUFFER ;Will will load the complete track image here (9000H) LD DE,MAX_TRACK_SIZE ;Worse case scenerio. SEND_DUMP_RD: LD C,(HL) CALL SEND_FPGA_TO_S100 ;Send one byte at a time back INC HL DEC DE LD A,E OR A,D JR NZ,SEND_DUMP_RD LD C,CMD$COMPLETE ;Tell S100 Bus there was no error CALL SEND_FPGA_TO_S100 JP START_CMD ;--------------------------------- DO_CMD_FDC_COPY ----------------------------------------------------------------- DO_CMD_FDC_COPY LD DE,FDC_COPY_MSG ;45H, Copy Floppy C:->D: CALL PRINT_STRING CALL CRLF XOR A ;;;; LD A,4AH ;For testing to speed things up start from Track 4AH LD (@CURRENT_TRACK),A LD A,1 LD (@CURRENT_SECTOR),A LD IX,@DRIVE_4_TABLE ;Get from RAM store the current drive type for hardware Drive [D] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL SET_A_SIDE LD IX,@DRIVE_3_TABLE ;Get from RAM store the current drive type for hardware Drive [C] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,0 LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL SET_A_SIDE LD HL,SECTOR_BUFFER ;Load up a Track worth of sectors (26), starting here. ld (@DMA),HL ;Point to buffer CMD_FDC_FAST_COPY_LOOP: LD IX,@DRIVE_3_TABLE ;Floppy Drive C: will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware CALL SET_CURRENT_SIDE CALL CRLF CMD_MORE_TRACK_READ: ;Next sector on same track IN A,(STATUS_BUS_PORT) ;Was an abort requested from the S100 Bus BIT 6,A JP NZ,CMD_FDC_ABORT_DISK_COPY LD DE,READING_TRACK_MSG ;Reading Sectors on Track: $' CALL PRINT_STRING LD A,(@CURRENT_TRACK) CALL HEXOUT CMD2_MORE_TRACK_READ: LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;Read actual Floppy sector at @DMA jp z,CMD_FDC_DISK_READ_SEC_OK ;Z means the sector read was OK LD DE,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD (@DMA),HL call CRLF JP CMD_FDC_COPY_ERROR CMD_FDC_DISK_READ_SEC_OK: LD (@DMA),HL ;Save current pointer LD A,(@CURRENT_SECTOR) INC A LD C,(IX+NSCTRS) CP A,C JP Z,CMD_FDC_WRITE1 ;Last sec on track, then done LD (@CURRENT_SECTOR),A JP CMD2_MORE_TRACK_READ ;Next sector on same track CMD_FDC_WRITE1: LD A,1 LD (@CURRENT_SECTOR),A CALL CRLF LD DE,WRITEING_TRACK_MSG ;Reading Sectors on Track: $' CALL PRINT_STRING LD A,(@CURRENT_TRACK) CALL HEXOUT CMD_FDC_TRACK_WRITE: ;-------------Write to second disk ---------------- LD HL,SECTOR_BUFFER ;Load up a Track worth of sectors (26), starting here. ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_4_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware CALL SET_CURRENT_SIDE LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display CMD_MORE_TRACK_WRITE: IN A,(STATUS_BUS_PORT) ;Was an abort requested from the S100 Bus BIT 6,A JP NZ,CMD_FDC_ABORT_DISK_COPY CALL FDC_RDY ;WriteRead actual Floppy sector at @DMA CALL CORE_FLOPPY_WRITE_SECTOR ;Write actual Floppy sector at @DMA JP Z,CMD_FDC_DISK_WRITE_SEC_OK ;Z means the sector read was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD (@DMA),HL call CRLF ;NZ Abort JP CMD_FDC_COPY_ERROR CMD_FDC_DISK_WRITE_SEC_OK: LD (@DMA),HL LD A,(@CURRENT_SECTOR) INC A LD C,(IX+NSCTRS) CP A,C JP Z,CMD_TRACK_WRITTEN ;Last sec on track, then done LD (@CURRENT_SECTOR),A JP CMD_FDC_TRACK_WRITE ;Next sector on same track CMD_TRACK_WRITTEN: LD A,1 LD (@CURRENT_SECTOR),A LD A,(@CURRENT_TRACK) INC A CP A,(IX+NTRKS) ;e.g. For 8", 76 tracks JP Z,CMD_FDC_COPY_DONE ;At last sector+1 LD (@CURRENT_TRACK),A JP CMD_FDC_FAST_COPY_LOOP CMD_FDC_COPY_DONE: LD A,(IX+SIDES_NUMBER) ;Is it a double sided disk CP A,2 JP NZ,CMD_FDC_FINISH_COPY ;No then we are done LD A,(IX+DRIVE_ADDR) BIT 2,A JP Z,CMD_FDC_FINISH_COPY ;We have done with side B as well LD DE,COPYING_B_SIDE ;'Copying B side$' CALL PRINT_STRING CALL CORE_RESTORE ;Lower head/Start Motor. Must be done here/early. Absolutly critical the disk XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) XOR A ;;;; LD A,4AH ;For testing to speed things up start from Track 4AH LD (@CURRENT_TRACK),A CALL SET_B_SIDE ;@CURRENT_SIDE is changed to B side CALL LED_TRK_SEC ;Update LED HEX display JP CMD_FDC_FAST_COPY_LOOP ;Repeat the whole process on side 2 CMD_FDC_FINISH_COPY: ld de,FDC_DRIVE_OK_MSG ;Floppy Disk copy complete call PRINT_STRING LD HL,SECTOR_BUFFER LD (@DMA),HL call CRLF ;NZ Abort LD IX,@DRIVE_3_TABLE ;Floppy Drive C: will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware CALL CORE_RESTORE XOR A,A LD (IX+TRK),A LD A,(@CURRENT_TRACK) LD (IX+SEC),A LD (@CURRENT_SECTOR),A CALL SET_A_SIDE CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display LD C,CMD$COMPLETE ;Tell S100 Bus there was no error CALL SEND_FPGA_TO_S100 JP START_CMD CMD_FDC_ABORT_DISK_COPY: LD DE,FDC_FAST_ABORT_MSG ;Fast Copy of Disk C:->D: Aborted call PRINT_STRING JP CMD_FDC_FINISH_COPY CMD_FDC_COPY_ERROR: LD DE,FDC_FAST_RW_ERROR_MSG ;Fast Copy of Disk C:->D: R/W Error call PRINT_STRING LD HL,SECTOR_BUFFER LD (@DMA),HL call CRLF ;NZ Abort LD IX,@DRIVE_3_TABLE ;Floppy Drive C: will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware CALL CORE_RESTORE XOR A,A LD (IX+TRK),A LD A,(@CURRENT_TRACK) LD A,1 LD (IX+SEC),A LD (@CURRENT_SECTOR),A CALL SET_A_SIDE CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display LD C,CMD$FAILED ;Tell S100 Bus there was an error CALL SEND_FPGA_TO_S100 JP START_CMD ;To indicate an error. Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_GET_TIME: ;Return Date and Time to S100 Bus LD DE,GET_DATE_TIME_MSG ;' Date and Time to S100 Bus$' CALL PRINT_STRING LD C,20H ;Force 20xx CALL SEND_FPGA_TO_S100 LD B,RTC_YEAR ; Year Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 LD C,'/' CALL ZCO LD B,RTC_MONTH ; Month Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 LD C,'/' CALL ZCO LD B,RTC_DATE ; Date Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 LD C,' ' CALL ZCO CALL ZCO CALL ZCO LD B,RTC_HOURS ; Hours Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 LD C,':' CALL ZCO LD B,RTC_MINUTES ; Minutes Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 LD C,':' CALL ZCO LD B,RTC_SECONDS ; Seconds Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,A CALL SEND_FPGA_TO_S100 JP START_CMD ;Back to main loop ;-------------------------------------------------------------------------------------------------------- DO_SET_TIME: ;Return Date and Time to S100 Bus LD DE,SET_DATE_TIME_MSG ;' Date and Time from S100 Bus$' CALL PRINT_STRING CALL GET_S100_TO_FPGA ;Get Enter Year (00-99) LD (@YEAR),A CALL HEXOUT LD B,RTC_YEAR OR 80H ; RTC Register address + Write LD C,A ; DATA CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD C,'/' CALL ZCO CALL GET_S100_TO_FPGA ;Get Month (01-12) CALL HEXOUT LD B,RTC_MONTH OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD C,'/' CALL ZCO CALL GET_S100_TO_FPGA ;Get Date (01-31) CALL HEXOUT LD B,RTC_DATE OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD C,' ' CALL ZCO CALL ZCO CALL ZCO CALL GET_S100_TO_FPGA ;Get Hours (00-23) CALL HEXOUT LD B,RTC_HOURS OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD C,':' CALL ZCO CALL GET_S100_TO_FPGA ;Get Minutes (00-59) CALL HEXOUT LD B,RTC_MINUTES OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD C,':' CALL ZCO CALL GET_S100_TO_FPGA ;Get Seconds (00-59) CALL HEXOUT LD B,RTC_SECONDS OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) JP START_CMD ;Back to main loop ;========================================================================================================================= INT_UPDATE_HEX_DISPLAY: ;Uupdate the HEX displays first (NOTE ONLY FOR CF CARDS) ;Note assume the Alternative Z80 register set (EX & EXX) IN A,(CONFIGURATION_PORT) AND A,11000000B CP A,11000000B ;If both IDE and Floppies then no HEX Display circuit present RET Z IN A,(CONFIGURATION_PORT) ;Update the board HEX displays BIT 0,A ;0= A: IDE Drive LD C,0AH LD IX,@DRIVE_1_TABLE ;IDE Drive A: will always be @DRIVE_1_TABLE JR Z,DISPLAY_DRIVE BIT 1,A ;1 = B: IDE Drive LD IX,@DRIVE_2_TABLE ;IDE Drive B: will always be @DRIVE_2_TABLE LD C,0BH JR Z,DISPLAY_DRIVE LD C,00H ;Invalid Drive DISPLAY_DRIVE: LD A,C OUT (HEX_DISPLAY_PORT),A LD A,1 ;Needed to activate drive display OUT (DRIVE_HEX_DISPLAY),A ;Display on Hex display IN A,(SECTOR_DISPLAY) LD (IX+SEC),A IN A,(TRACK_DISPLAY) LD (IX+TRK),A LD A,(IX+SEC) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,20H OUT (HEX_DISPLAY_PORT),A ;HIGH Nibble of Sector LD A,C AND A,0FH OR A,10H OUT (HEX_DISPLAY_PORT),A ;LOW nibble of Sector LD A,(IX+TRK) LD C,A ;store it RRA ;Isolate low nibble RRA RRA RRA AND A,0FH OR A,80H ;This selects the high nibble of port OUT (HEX_DISPLAY_PORT),A ;HIGH Nibble of Track LD A,C AND A,0FH OR A,40H OUT (HEX_DISPLAY_PORT),A ;LOW nibble of Track RET INT_UPDATE_USB_PORT_DISPLAY: IN A,(IOBYTE) ;Is runtime Track/Sec USB Treminal displays requested BIT 0,A RET NZ ;Back to main loop to save time if xxxxxxxx1 IN A,(CONFIGURATION_PORTT) ;Update the board HEX displays BIT 0,A LD C,0AH LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE JR Z,GOT_DRIVE BIT 1,A LD IX,@DRIVE_2_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD C,0BH JR Z,GOT_DRIVE LD C,00H ;Invalid Drive GOT_DRIVE: IN A,(SECTOR_DISPLAY) ;Need to read the current Track/sector LD (IX+SEC),A IN A,(TRACK_DISPLAY) LD (IX+TRK),A LD A,(@CURRENT_IDE_MODE) CP A,EXT$IDE$MODE JR NZ,FULL_DISPLAY LD DE,INT_MSG ;'INT '. CALL PRINT_STRING CALL QUICK_DRIVE_NAME ;'IDE or Floppy Drive X:$' LD DE,R_W_SEC_MSG ;': R/W Sector, Track $ CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT RET FULL_DISPLAY: CALL QUICK_DRIVE_NAME ;'IDE or Floppy Drive X:$' LD A,(@CURRENT_CMD) ;Is it a sector read or write CP A,30H JR NZ,INT_IS_SEC_READ LD DE,WRITE_MSG ;': WRITE Sector, Track $ JP INT_DONE_TEXT INT_IS_SEC_READ: LD DE,READ_MSG ;': READ Sector, Track $ INT_DONE_TEXT: CALL PRINT_STRING LD A,(IX+TRK) CALL HEXOUT LD DE,SECT_MSG ;'H, Sector $' CALL PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT ; LD C,'-' ; CALL ZCO ; IN A,(IDE_CMD) ; CALL BITS RET ;=========================================================================================================== ;=========================================================================================================== ;======================================= MAIN MONITOR MENU ================================================= ;=========================================================================================================== ;=========================================================================================================== MONITOR_MENU: LD SP,STACK ;To be safe reset Stackat 0FFF0H (must be valid for debugging) LD A,1 OUT (USB_STATUS_PORT),A ;Raise bit 0 to overide IOBYTE control of the USB terminal IN A,(CONFIGURATION_PORT) ;Is it the FDC Board only AND A,11000000B CP A,01000000B JP Z,MONITOR_FLOPPY_ONLY CP A,10000000B JP Z,MONITOR_IDE_ONLY JP MONITOR_BOTH MONITOR_IDE_ONLY: LD DE,IDE_ONLY_MENU ;'Z80 Monitor + IDE/CF card Menu (IOBYTE=$' CALL PRINT_STRING IN A,(IOBYTE) CALL PRINT_BITS LD DE,IDE_BRACKET_MENU ;')',CR,LF,'$' CALL PRINT_STRING LD A,LOCAL$IDE$MODE ;Select Internal IDE FPGA circuit for IDE drive A: or B: access OUT (IDE_SWITCH_PORT),A LD IX,@DRIVE_1_TABLE LD DE,CURENT_A_MSG ;'A = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_2_TABLE LD DE,CURENT_B_MSG ;'B = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_1_TABLE ;Default LD DE,Z_MENU_MSG ;Z Go to Z80 Monitor CALL PRINT_STRING LD DE,DRIVE_MSG ;'Select Drive Sub-Menu:-$' CALL PRINT_STRING ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,INITILIZE LD C,A ;Echo character CALL ZCO CP A,'Z' JP Z,Z80_MENU CP A,'A' JP Z,IDE_SETUP_1 ;Setup IDE drive in[A] CP A,'B' JP Z,IDE_SETUP_2 ;Setup IDE drive in[B] JP BEGIN MONITOR_BOTH: LD DE,ALL_CARDS_MENU ;'Z80 Monitor + IDE/CF cards + Floppy Menu (IOBYTE=',CR,LF,'$' CALL PRINT_STRING IN A,(IOBYTE) CALL PRINT_BITS LD DE,IDE_BRACKET_MENU ;')',CR,LF,'$' CALL PRINT_STRING LD A,LOCAL$IDE$MODE ;Select Internal IDE FPGA circuit for IDE drive A: or B: access OUT (IDE_SWITCH_PORT),A LD IX,@DRIVE_1_TABLE LD DE,CURENT_A_MSG ;'A = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_2_TABLE LD A,(IX+INITILIZED) LD DE,CURENT_B_MSG ;'B = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_3_TABLE LD A,(IX+INITILIZED) LD DE,CURENT_C_MSG ;'C = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_4_TABLE LD DE,CURENT_D_MSG ;'D = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_5_TABLE LD DE,CURENT_E_MSG ;'E = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_6_TABLE LD DE,CURENT_F_MSG ;'F = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_1_TABLE ;Default LD DE,Z_MENU_MSG ;Z Go to Z80 Monitor CALL PRINT_STRING LD DE,DRIVE_MSG ;'Select Drive Sub-Menu:-$' CALL PRINT_STRING ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,INITILIZE LD C,A ;Echo character CALL ZCO CP A,'Z' JP Z,Z80_MENU CP A,'A' JP Z,IDE_SETUP_1 ;Setup IDE drive in[A] CP A,'B' JP Z,IDE_SETUP_2 ;Setup IDE drive in[B] CP A,'C' ;Must be floppy circuit JP Z,FL_SETUP_3 ;Setup FD drive in[C] CP A,'D' JP Z,FL_SETUP_4 ;Setup FD drive in[D] CP A,'E' JP Z,FL_SETUP_5 ;Setup FD drive in[E] CP A,'F' JP Z,FL_SETUP_6 ;Setup FD drive in[F] JP BEGIN MONITOR_FLOPPY_ONLY: LD A,1 OUT (USB_STATUS_PORT),A ;Raise bit 0 to overide IOBYTE control of the USB terminal LD DE,FLOPPY_ONLY_MENU ;'Z80 Monitor + Floppy Menu (IOBYTE=$' CALL PRINT_STRING IN A,(IOBYTE) CALL PRINT_BITS LD DE,IDE_BRACKET_MENU ;')',CR,LF,'$' CALL PRINT_STRING LD A,LOCAL$IDE$MODE ;Select Internal IDE FPGA circuit for drive A: or B: access (Not used) OUT (IDE_SWITCH_PORT),A LD IX,@DRIVE_3_TABLE LD A,(IX+INITILIZED) LD DE,CURENT_C_MSG ;'C = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_4_TABLE LD DE,CURENT_D_MSG ;'D = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_5_TABLE LD DE,CURENT_E_MSG ;'E = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_6_TABLE LD DE,CURENT_F_MSG ;'F = ' CALL PRINT_STRING CALL SHOW_DRIVE_NAME ;IX has start of drive table info LD IX,@DRIVE_3_TABLE ;Default LD DE,Z_MENU_MSG ;Z Go to Z80 Monitor CALL PRINT_STRING ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,INITILIZE LD C,A ;Echo character CALL ZCO CP A,'Z' JP Z,Z80_MENU CP A,'C' ;Must be floppy circuit JP Z,FL_SETUP_3 ;Setup FD drive in[C] CP A,'D' JP Z,FL_SETUP_4 ;Setup FD drive in[D] CP A,'E' JP Z,FL_SETUP_5 ;Setup FD drive in[E] CP A,'F' JP Z,FL_SETUP_6 ;Setup FD drive in[F] JP BEGIN BOTH_CMDS: ;Menu for both boards POP AF CP A,'A' JP Z,IDE_SETUP_1 ;Setup IDE drive in[A] CP A,'B' JP Z,IDE_SETUP_2 ;Setup IDE drive in[B] CP A,'C' JP Z,FL_SETUP_3 ;Setup FD drive in[C] CP A,'D' JP Z,FL_SETUP_4 ;Setup FD drive in[D] CP A,'E' JP Z,FL_SETUP_5 ;Setup FD drive in[E] CP A,'F' JP Z,FL_SETUP_6 ;Setup FD drive in[F] JP BEGIN IDE_CMDS: ;Menu for IDE board POP AF CP A,'A' JP Z,IDE_SETUP_1 ;Setup IDE drive in[A] CP A,'B' JP Z,IDE_SETUP_2 ;Setup IDE drive in[B] JP BEGIN Z80_MENU: LD DE,Z80_MENU_MSG1 ;Print 'FPGA onboard Z80 CPU Monitor Menu. RAM 0-7FFFH, CALL PRINT_STRING LD DE,SP_MSG ;Print 'SP=$' CALL PRINT_STRING LD HL,STACK CALL PRINT_HL ;Print HL LD DE,H_MSG ;'H ' CALL PRINT_STRING CALL CRLF LD DE,Z80_MENU_MSG2 ;Then Z80 Menu Message CALL PRINT_STRING CALL ZCSTS ;Check if garbage at keyboard CALL NZ,ZCI ;If so flush it CALL ZCSTS ;Flush CI status port ;;;; LD A,WRITECFG8255 ;10000000b, Set all three 8255 ports to output mode (For testing!) LD A,READCFG8255 ;10010010b, Set 8255 IDEportC to output, IDEportA/B input OUT (IDEportCtrl),a ;------------------------------- THIS IS THE START ON THE MAIN SBC-Z80 LOOP-------------------------------- Z80_MENU_LOOP: LD SP,STACK ;Just to be safe, redo stack at 0FFF0H LD DE,Z80_MENU_LOOP PUSH DE ;FOR ALL COMMANDS, ANY EXTRA UNBALANCED POP & [DE] WOULD END UP IN [PC] CALL CRLF LD C,'-' CALL ZCO LD C,'>' CALL ZCO STARO: CALL ZCSTS ;Need to check status first because IOBYTE may have changed JR Z,STARO CALL TI ;Get character and echo cp ESC ;ESC back to main menu jp z,BEGIN AND 7FH JR Z,STARO SUB '@' ;Commands @ to Z only RET M CP 1BH ;A-Z only RET NC ADD A LD HL,MON_CMD_TABLE ADD A,L LD L,A LD A,(HL) INC HL LD H,(HL) LD L,A LD C,02H JP (HL) ;JUMP TO COMMAND TO COMMAND (from TABLE) ; ; ; ;PRINT MAIN SBC-Z80 MENU ON CRT KCMD: LD DE,SIGNON_MSG ;Menu Option "Y", List Menu Options CALL PRINT_STRING LD DE,Z80_MENU_MSG2 ;Then Menu Message JP PRINT_STRING INVALID_DATA: LD DE,Invalid_Msg CALL PRINT_STRING JP BEGIN ;Diagnostic test of S100 Bus data In/out port. Runs continously until reset S100_DATA_IN: LD DE,H_MENU_MSG ;Continously display S100 Data In Port. Reset to abort." CALL PRINT_STRING MORE1: CALL CRLF IN A,(STATUS_BUS_PORT) PUSH AF CALL PRINT_BITS POP AF OUT (DATA_BUS_PORT),A JP MORE1 PRINT_STRING: ;A ROUTINE TO PRINT OUT A STRING @ [DE] LD A,(DE) ;UP TO THE FIRST '$' ---- IF IOBYTE BIT 0 is 0 INC DE CP '$' RET Z LD C,A CALL ZCO ;Note will go to USB Port -- If bit 0 of IOBYTE = 1 JR PRINT_STRING ;ABORT IF ESC AT CONSOL, PAUSE IF ^S AT CONSOL CCHK: CALL ZCSTS ;FIRST IS THERE ANYTHING THERE RET Z CALL ZCI CP 'S'-40H JR NZ,CCHK1 CCHK2: CALL ZCSTS ;WAIT HERE UNTIL ANOTHER INPUT IS GIVEN JR Z,CCHK2 CCHK1: CP ESC RET NZ ;RETURN EXECPT IF ESC ;RESTORE SYSTEM AFTER ERROR ERROR: CALL MEMSIZ ;GET RAM AVAILABLE - WORKSPACE IN [HL] LD SP,HL ;SET STACK UP IN WORKSPACE AREA LD C,'*' CALL ZCO JP Z80_MENU_LOOP ;PRINT HIGHEST RAM MEMORY FROM BOTTOM SIZE: CALL MEMSIZ ;RETURNS WITH [HL]= RAM AVAILABLE-WORKSPACE LFADR: CALL CRLF ;Print CR/LF + HL + SPACE PRINT_HL_SPACE: PUSH HL ;PRINT [HL] AND A SPACE PUSH BC CALL PRINT_HL ;Print [HL] with no space afterwards LD C,SPACE CALL ZCO POP BC POP HL RET PRINT_SPACE: LD C,SPACE ;PRINT A SPACE CALL ZCO RET CONV: AND 0FH ;CONVERT HEX TO ASCII ADD A,90H DAA ADC A,40H DAA LD C,A call ZCO RET GET_HL_DE: ;GET TWO PARAMETERS AND PUT THEM IN [HL] & [DE] THEN CRLF CALL HEXSP POP DE POP HL RET ;PUT THREE PARAMETERS IN [BC] [DE] [HL] THEN CR/LF EXPR3: INC C ;ALREADY HAD [C]=2 FROM START CALL HEXSP CALL CRLF POP BC POP DE POP HL RET EXPR1: LD C,01H HEXSP: LD HL,0000 ;GET # OF PARAMETERS in C EX0: CALL TI EX1: LD B,A CALL NIBBLE JR C,EX2X ADD HL,HL ADD HL,HL ADD HL,HL ADD HL,HL OR L LD L,A JR EX0 EX2X: EX (SP),HL PUSH HL LD A,B CALL QCHK JR NC,SF560 DEC C RET Z SF560: JP NZ,ERROR DEC C JR NZ,HEXSP RET EXF: LD C,01H LD HL,0000H JR EX1 HILOX: CALL CCHK ;RANGE TEST ROUTINE CARRY SET = RANGE EXCEEDED CALL HILO RET NC POP DE ;DROP ONE LEVEL BACK TO START RET HILO: INC HL ;RANGE CHECK SET CARRY IF [DE]=[HL] LD A,H OR L SCF RET Z LD A,E SUB L LD A,D SBC A,H RET PRINT_HL: ;PRINT [HL] ON CONSOL PUSH AF LD A,H CALL LBYTE LD A,L CALL LBYTE POP AF RET LBYTE: PUSH AF RRCA RRCA RRCA RRCA CALL SF598 POP AF SF598: CALL CONV ;Convert to ASCII AND print it RET ;THIS IS A CALLED ROUTINE USED TO CALCULATE TOP OF RAM IS USED BY ;THE ERROR ROUTINE TO RESET THE STACK. ;Returns top of RAM in [HL] MEMSIZ: PUSH BC ;SAVE [BC] MEMSZ1: LD HL,0FFFFH ;START FROM THE TOP DOWN MEMSZ2: LD A,(HL) CPL LD (HL),A CP (HL) CPL ;PUT BACK WHAT WAS THERE LD (HL),A JP Z,GOTTOP DEC H ;TRY 100H BYTES LOWER JR MEMSZ2 ;KEEP LOOKING FOR RAM GOTTOP: POP BC ;RESTORE [BC] RET NIBBLE: SUB 30H RET C CP 17H CCF RET C CP LF CCF RET NC SUB 07H CP LF RET COPCK: LD C,'-' CALL ZCO PCHK: CALL TI QCHK: CP SPACE ;TEST FOR DELIMITERS RET Z CP ',' RET Z CP CR SCF RET Z CCF RET ;KEYBOARD HANDELING ROUTINE (WILL NOT ECHO CR/LF or ESC) ;IT CONVERTS LOWER CASE TO UPPER CASE FOR LOOKUP COMMANDS ;ALL OTHERE CHARACTERS ARE ECHOED ON CONSOL TI: CALL ZCI CP CR RET Z CP ESC RET Z CP 40H ;LC->UC JR C,TI1 CP 7BH JR NC,TI1 AND 5FH TI1: PUSH BC LD C,A CALL ZCO LD A,C POP BC RET ;NO ECHO KEYBOARD HANDELING ROUTINE ;IT CONVERTS LOWER CASE TO UPPER CASE FOR LOOKUP COMMANDS ;ALL OTHERE CHARACTERS ARE ECHOED ON CONSOL TI_NO_ECHO: CALL ZCI CP CR RET Z CP 40H ;LC->UC RET C CP 7BH RET NC AND 5FH RET GETHL: PUSH BC ;Return a HEX value in [HL] LD C,1 ;1 paramater CALL HEXSP POP HL POP BC RET PRINT_BITS: ;DISPLAY 8 BITS OF [A] (No registers changed) PUSH DE PUSH BC LD E,A CALL BITS POP BC POP DE RET BITS: LD B,08H ;DISPLAY 8 BITS IN [E] (B & C registers changed) CALL PRINT_SPACE SF76E: SLA E LD A,18H ADC A LD C,A CALL ZCO DJNZ SF76E RET ;MEMORY MAP PROGRAM CF.DR.DOBBS VOL 31 P40. ;IT WILL SHOW ON CONSOL TOTAL MEMORY SUMMARY OF RAM,PROM, AND NO MEMORY MEMMAP: CALL CRLF LD HL,0 LD B,1 MAP1: LD E,'R' ;PRINT R FOR RAM LD A,(HL) CPL LD (HL),A CP (HL) CPL LD (HL),A JR NZ,MAP2 CP (HL) JR Z,PRINT MAP2: LD E,'p' MAP3: LD A,0FFH CP (HL) JR NZ,PRINT INC L XOR A CP L JR NZ,MAP3 LD E,'.' PRINT: LD L,0 DEC B JR NZ,NLINE LD B,16 CALL CRLF CALL HXOT4 NLINE: LD A,SPACE CALL OTA LD A,E CALL OTA INC H JR NZ,MAP1 CALL CRLF CALL CRLF JP Z80_MENU_LOOP ;16 HEX OUTPUT ROUTINE HXOT4: LD C,H CALL HXO2 LD C,L HXO2: LD A,C RRA RRA RRA RRA CALL HXO3 LD A,C HXO3: AND 0FH CP 10 JR C,HADJ ADD A,7 HADJ: ADD A,30H OTA: PUSH BC LD C,A CALL ZCO ;SEND TO CONSOL POP BC RET ;DISPLAY MEMORY IN HEX DISP: CALL GET_HL_DE ;GET PARAMETERS IN [HL],[DE] LD A,L ;ROUND OFF ADDRESSES TO XX00H AND 0F0H LD L,A LD A,E ;FINAL ADDRESS LOWER HALF AND 0F0H ADD A,10H ;FINISH TO END 0F LINE SF172A: CALL LFADR ;Print Address + CRLF SF175A: CALL BLANK ; CALL ZCSTS ;For debugging ; CALL PROP_CI LD A,(HL) CALL LBYTE CALL HILOX LD A,L AND 0FH JR NZ,SF175A LD C,TAB ;INSERT A TAB BETWEEN DATA CALL ZCO LD B,4H ;ALSO 1 SPACE TA11: LD C,SPACE CALL ZCO DJNZ TA11 ; IN A,IOBYTE ;For some reason ASCII display only on VGA display is ; BIT 2,A ;not working. Skip it for now! ; JR Z,SF172A LD B,16 ;NOW PRINT ASCII (16 CHARACTERS) PUSH DE ;TEMPORLY SAVE [DE] LD DE,0010H SBC HL,DE POP DE T11: LD A,(HL) AND 7FH CP ' ' ;FILTER OUT CONTROL CHARACTERS' JR NC,T33 T22: LD A,'.' T33: CP 07CH JR NC,T22 LD C,A ;SET UP TO SEND CALL ZCO INC HL DJNZ T11 ;REPEAT FOR WHOLE LINE JR SF172A SUBS: LD C,1 ;INSPECT AND / OR MODIFY MEMORY CALL HEXSP POP HL SF2E3: LD A,(HL) CALL LBYTE LD C,'-' CALL ZCO CALL PCHK RET C JR Z,SF2FC CP 5FH JR Z,SF305 PUSH HL CALL EXF POP DE POP HL LD (HL),E LD A,B CP CR RET Z SF2FC: INC HL SF2FD: LD A,L AND 07H CALL Z,LFADR JR SF2E3 SF305: DEC HL JR SF2FD HCRLF: PUSH AF PUSH BC LD C,'H' ;Finish current line with a 'H' first CALL ZCO JR CRLF1 CRLF: PUSH AF PUSH BC CRLF1: LD C,LF CALL ZCO LD C,CR CALL ZCO POP BC POP AF RET ; ; ; ;>>>>>> Print [A] in HEX-ASCII. (No Resisters altered) HEXOUT: PUSH AF PUSH BC PUSH AF RRCA RRCA RRCA RRCA CALL ZCONV POP AF CALL ZCONV POP BC POP AF RET ; ; ; HHEXOUT:PUSH AF ; Same + H at the end PUSH BC PUSH AF RRCA RRCA RRCA RRCA CALL ZCONV POP AF CALL ZCONV LD C,'H' CALL ZCO POP BC POP AF RET ; HHEXOUT_CR: PUSH AF ; Same + H + CR+LF at the end PUSH BC PUSH AF RRCA RRCA RRCA RRCA CALL ZCONV POP AF CALL ZCONV LD C,'H' CALL ZCO LD C,CR CALL ZCO LD C,LF CALL ZCO POP BC POP AF RET ; ; ZCONV: AND A,0FH ;HEX to ASCII ADD 90H DAA ADC 40H DAA LD C,A CALL ZCO RET BLANK: PUSH AF PUSH BC ;Print a space on screen PUSH HL LD C,' ' CALL ZCO POP HL POP BC POP AF RET FILL: CALL EXPR3 ;FILL A BLOCK OF MEMORY WITH A VALUE SF1A5: LD (HL),C CALL HILOX JR NC,SF1A5 POP DE JP Z80_MENU_LOOP ;GO TO A RAM LOCATION GOTO: LD C,1 ;SIMPLE GOTO FIRST GET PARMS. CALL HEXSP CALL CRLF POP HL ;GET PARAMETER PUSHED BY EXF JP (HL) ; GET OR OUTPUT TO A PORT QUERY: CALL PCHK CP 'O' ;OUTPUT TO PORT JR Z,OUT_PORT CP 'I' ;INPUT FROM PORT JP Z,IN_PORT LD C,'*' JP ZCO ;WILL ABORT IF NOT 'I' OR 'O' IN_PORT: LD C,1 ;IN Port CALL HEXSP POP BC IN A,(C) JP PRINT_BITS ; OUT_PORT: CALL HEXSP ;OUT Port POP DE POP BC OUT (C),E RET RAMTEST: ; MEMORY TEST PUSH DE PUSH BC LD DE,RAM_TEST_MSG CALL PRINT_STRING POP BC POP DE CALL GET_HL_DE SF200: LD A,(HL) LD B,A CPL LD (HL),A XOR (HL) JR Z,SF215 PUSH DE LD D,B LD E,A ;TEMP STORE BITS CALL PRINT_HL_SPACE CALL BLANK LD A,E CALL PRINT_BITS CALL CRLF LD B,D POP DE SF215: LD (HL),B CALL HILOX JR SF200 MOVE: CALL EXPR3 ;MOVE A BLOCK OF MEMORY TO ANOTHER LOCATION SF21E: LD A,(HL) LD (BC),A INC BC CALL HILOX JR SF21E VERIFY: CALL EXPR3 ;VERIFY ONE BLOCK OF MEMORY WITH ANOTHER VERIO: LD A,(BC) CP (HL) JR Z,SF78E PUSH BC CALL CERR POP BC SF78E: INC BC CALL HILOX JR VERIO RET ; CERR: LD B,A CALL PRINT_HL_SPACE LD A,(HL) CALL LBYTE CALL BLANK LD A,B CALL LBYTE JP CRLF ECHO: LD DE,ECHO_MSG CALL PRINT_STRING ECHO1: CALL ZCI ;Routeen to check keyboard etc. CP 'C'-40H ;Loop until ^C RET Z CP 'Z'-40H RET Z LD C,A CALL ZCO JR ECHO1 TYPE: CALL GET_HL_DE ;READ ASCII FROM MEMORY SF30B: CALL LFADR LD B,56 SF310: LD A,(HL) AND 7FH CP SPACE JR NC,SF319 SF317: LD A,2EH SF319: CP 7CH JR NC,SF317 LD C,A CALL ZCO CALL HILOX DJNZ SF310 JR SF30B ; INPORTS: ;Display all active IO input ports in the system LD DE,ALL_PORTS CALL PRINT_STRING CALL CRLF LD B,0 ;Now loop through all ports (0-FF) LD D,6 ;Display 6 ports across LD E,0FFH ;Will contain port number LOOPIO: LD C,E LD A,E IN A,(C) ;Remember [ZASMB does not work with this opcode,SLR is OK] CP A,0FFH ;No need for 0FF's JR Z,SKIP LD H,A ;store port data in H for below LD A,E ;Need to print port # first CALL LBYTE ;Print port number LD C,'-' CALL ZCO LD C,'>' CALL ZCO LD A,H ;get back port data CALL LBYTE ;print it LD C,TAB CALL ZCO DEC D ;6 ports per line JR NZ,SKIP LD D,6 CALL CRLF SKIP: DEC E ;Next Port DJNZ LOOPIO CALL CRLF RET ; ; ; ;************************************************************************************************************ ;************************************************************************************************************ ;**************************** IDE MODULE ****************************************************************** ;************************************************************************************************************ ;************************************************************************************************************ ;************************************************************************************************************ ; ; IDE_SETUP: IN A,(CONFIGURATION_PORT) BIT 7,A JR NZ,IDE_SETUP1 LD DE,NO_IDE_CIRCUIT_MSG ;'NO IDE/CF Card circuit detected!$' CALL PRINT_STRING JP MONITOR_MENU IDE_SETUP1: LD A,(IX+DRIVE_NUMBER) ;Is a drive selected OR A JP Z,NO_DRIVE CP A,1 JR Z,IDE_SETUP_1 CP A,2 JR Z,IDE_SETUP_1 JP NO_DRIVE IDE_SETUP_1: LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware JP IDE_LOOP IDE_SETUP_2: LD IX,@DRIVE_2_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware JP IDE_LOOP IDE_LOOP: LD SP,STACK ;Just to be safe, redo stack at 0FFF0H LD a,READcfg8255 ;Config 8255 chip (10010010B), read mode on return OUT (IDEportCtrl),a ld de,IDE_CARD_MENU_MSG ;List command options call PRINT_STRING CALL SHOW_DRIVE_NAME CALL CRLF call SET_IDE_TRK_SEC ;Update LBA on drive call SHOW_DMA_TRK_SEC ;Display current Track,sector CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,INITILIZE cp a,'R' jp z,MENU_READ_IDE_SEC ; "R" Read sector(s) to data buffer cp a,'W' jp z,MENU_WRITE_IDE_SEC ; "W" Write data buffer to sector(s) cp a,'N' jp z,MENU_NEXT_IDE_SEC ; "N" Next Sector cp a,'+' jp z,MENU_NEXT_IDE_SEC ; "N" Next Sector cp a,'P' jp z,MENU_PREV_IDE_SEC ; "P" Previous sector cp a,'-' jp z,MENU_PREV_IDE_SEC ; "P" Previous sector cp a,'C' jp z,MENU_COPY_IDE_SEC ; "C" Read sector(s) and copy to another sector(s) cp a,'V' jp z,MENU_VERIFY_IDE_SEC ; "V" Verify sector(s) are teh same cp a,'F' jp z,MENU_FILL_IDE_SEC ; "F" Fill a sector with a byte value) cp a,'S' jp z,MENU_SET_IDE_LBA ; "L" Set LBA value (Set Track,sector) cp a,'B' jp z,MENU_SHOW_IDE_RAM_DMA ; "D" Display SECTOR Buffer in RAM cp a,'Y' JP Z,MENU_SHOW_IDE ; "Y" Show CF Card Paramaters cp a,'M' JP Z,MENU_COPY_IDE_DRIVE ; "M" Copy IDE Drive #1 to IDE Drive #2 LD DE,MENU_ERR_MSG ;'Invalid Menu Command!' CALL PRINT_STRING JP IDE_LOOP ;------------------MENU_SET_IDE_LBA IDE or SD DRIVES --------------------------------------------------------------------- MENU_SET_IDE_LBA: ;Set the logical block address LD DE,LBA_MENU_MSG CALL PRINT_STRING ld de,GET_LBA_MSG call PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK jp c,SET_IDE_LBA1 ;Ret C set if abort/error CALL SET_IDE_TRK_SEC ;Actully move head on a real drive, Ret Z SET_IDE_LBA1: call CRLF jp IDE_LOOP ;------------------MENU_READ_IDE_SEC ---------------------------------------------------------------- MENU_READ_IDE_SEC: ;Read Sector @ LBA to the RAM buffer CALl CRLF LD DE,RD_SEC_MENU_MSG CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA call CRLF CALL LOCAL_IDE_READ_SECTOR ;<<<<<<<<< Read actual IDE/CF card sector at @DMA jp z,RD_SEC_IDE_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Error, so Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort JP IDE_LOOP RD_SEC_IDE_OK: ld de,SEC_RD_OK ;'Sector Read OK' call PRINT_STRING call DISP_SEC_BUFFER ;Show sector data @DMA CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA address CALL LED_TRK_SEC ;Update LED HEX display LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL JP IDE_LOOP ;------------------MENU_WRITE_IDE_SEC ------------------------------------------------------------------- MENU_WRITE_IDE_SEC: ;Write data in RAM buffer to sector @ LBA CALL CRLF LD DE,WR_SEC_MENU_MSG ;'Write Track,Sector:-$' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD DE,WR_RAM_MENU_MSG ;From RAM at:- (XXXXH):$' CALL PRINT_STRING CALL EXPR1 ;Get 16 bit value, put on stack POP HL ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' jp nz,IDE_LOOP CALL CRLF CALL LOCAL_IDE_WRITE_SECTOR ;<<<<<<<<< Read actual IDE/CF card sector at @DMA jp z,WR_SEC_IDE_OK ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;Error, so back to start Buffer DMA LD (@DMA),HL JP IDE_LOOP WR_SEC_IDE_OK: ld de,SEC_WR_OK ;'Sector Write OK' call PRINT_STRING call DISP_SEC_BUFFER ;Show sector data @DMA CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA address CALL LED_TRK_SEC ;Update LED HEX display LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL JP IDE_LOOP ;------------------MENU_COPY_IDE_SEC ------------------------------------------------------------------------------------- MENU_COPY_IDE_SEC: LD DE,COPY_MENU_MSG CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD A,(IX+TRK) LD (@TRK_SOURCE),A ;Store starting Trk/Sec LD A,(IX+SEC) LD (@SEC_SOURCE),A LD DE,TO_MSG ;' To----> ' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD A,(IX+TRK) LD (@TRK_DEST),A ;Store destination Trk/Sec LD A,(IX+SEC) LD (@SEC_DEST),A LD A,(@TRK_SOURCE) ;Get back starting track/sec LD (IX+TRK),A LD A,(@SEC_SOURCE) LD (IX+SEC),A ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,IDE_LOOP LD HL,SECTOR_BUFFER ld (@DMA),hl ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA call LOCAL_IDE_READ_SECTOR ;Read actual sector at @DMA jp z,COPY_IDE_SEC_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP COPY_IDE_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display source DMA, Track,sector (only) ;Now write it to destination LD A,(@TRK_DEST) ;Get back destination track/sec LD (IX+TRK),A LD A,(@SEC_DEST) LD (IX+SEC),A call SET_IDE_TRK_SEC ;Update LBA on drive call LOCAL_IDE_WRITE_SECTOR ;write actual sector at @DMA jp z,COPY_IDE_SEC_OK1 ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP COPY_IDE_SEC_OK1: ld de,WR_TO_msgwr ;'Copy to Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display destination Track,sector at @DMA ld de,COPY_OK_MSG ;'Copy to Sector:- ' call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP ;------------------ MENU_FILL_IDE_SEC ------------------------------------------------------------------------------------- MENU_FILL_IDE_SEC: LD DE,FILL_MENU_MSG CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD DE,FILL_BYTE_MSG ;Enter the sector fill byte (xxH);- call PRINT_STRING call GETHEX jp c,IDE_LOOP ;Abort if ESC (C flag set) LD (@FILL_BYTE),A ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,IDE_LOOP LD A,(@FILL_BYTE) ;Fill Byte LD B,0 ;Assume worse case scenerio, 1K sectors so 256X4 = 1024 bytes LD HL,SECTOR_BUFFER LD (@DMA),HL LD (@DMA_STORE),HL MORE_IDE_CLEAR: LD (HL),A INC HL LD (HL),A INC HL LD (HL),A INC HL LD (HL),A INC HL DJNZ MORE_IDE_CLEAR call CRLF call LOCAL_IDE_WRITE_SECTOR ;write actual sector at @DMA jp z,FILL_IDE_SEC_OK ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP FILL_IDE_SEC_OK: ld de,FILL_msgwr ;'Sector Fill was OK' call PRINT_STRING ; call DISP_SEC_BUFFER ;Show sector data @DMA ; CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA CALL LED_TRK_SEC ;Update LED HEX display ld de,FILL_OK_MSG ;'Sector Filled OK call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP ;------------------ MENU_VERIFY_IDE_SEC ------------------------------------------------------------------------------------- MENU_VERIFY_IDE_SEC: LD DE,VERIFY_MENU_MSG CALL PRINT_STRING ld hl,(@DMA) ;Point to buffer LD (@DMA_STORE),HL ;for when we are finished call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD A,(IX+TRK) LD (@TRK_$1),A ;Store starting Trk/Sec LD A,(IX+SEC) LD (@SEC_$1),A LD DE,WITH_MSG ;' With ----> ' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD A,(IX+TRK) LD (@TRK_$2),A ;Store destination Trk/Sec LD A,(IX+SEC) LD (@SEC_$2),A LD A,(@TRK_$1) ;Get back starting track/sec LD (IX+TRK),A LD A,(@SEC_$1) LD (IX+SEC),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_$1),HL ;Always Start Buffer DMA (TRK#1,SEC#1) LD DE,1000H ;Worse case scenerio 1K sectors ADD HL,DE LD (@DMA_$2),HL ;Always for second sector @DMA (TRK#2,SEC#2) call CRLF LD HL,(@DMA_$1) LD (@DMA),HL call LOCAL_IDE_READ_SECTOR ;Read actual sector at @DMA (TRK#1,SEC#1) jp z,VERIFY_IDE_SEC_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP VERIFY_IDE_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display source DMA, Track,sector (only) ;Now compare with "destination sector" LD A,(@TRK_$2) ;Get back destination track/sec LD (IX+TRK),A LD A,(@SEC_$2) LD (IX+SEC),A call SET_IDE_TRK_SEC ;Update LBA on drive LD HL,(@DMA_$2) LD (@DMA),HL ;@DMA now pointng to second RAM buffer area call LOCAL_IDE_READ_SECTOR ;read actual sector at @DMA (TRK#2,SEC#2) jp z,VERIFY_1_IDE_SEC_OK ;Z means the sector write was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP VERIFY_1_IDE_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display destination Track,sector at @DMA CALL COMPARE_BUFFERS ;Tell if sectors match or not CALL CRLF LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP COMPARE_BUFFERS: LD HL,0 LD (@SEC_POSITION),HL LD HL,(@DMA_$1) ;First Sector buffer LD DE,(@DMA_$2) ;Second sector buffer LD B,(IX+SEC_SIZE_BYTES+1) ;Get sector size in bytes LD C,(IX+SEC_SIZE_BYTES) PUSH BC ;Save it COMPARE1: LD B,(HL) LD A,(DE) CP A,B JR NZ,SEC_MISMATCH INC HL INC DE PUSH HL LD HL,(@SEC_POSITION) INC HL ;Update sector pointer LD (@SEC_POSITION),HL POP HL POP BC DEC BC ;Do all (usually 512 bytes) LD A,C OR A,B PUSH BC JR Z,COMPARE2 JR COMPARE1 COMPARE2: POP BC ;Balance up stack LD DE,SEC_MATCH_MSG ;Sectors match! CALL PRINT_STRING XOR A RET SEC_MISMATCH; LD DE,SEC_MISMATCH_MSG ;Sectors do NOT match starting at position:- CALL PRINT_STRING POP BC ;Balance up stack LD HL,(@SEC_POSITION) ;Get current pointer CALL PRINT_HL ;Show position in HL LD C,'H' CALL ZCO XOR A DEC A RET ;------------------ MENU_NEXT_IDE_SEC ------------------------------------------------------------ MENU_NEXT_IDE_SEC: LD DE,NEXT_IDE_SEC_MSG CALL PRINT_STRING CALL SEC_BUMP jp IDE_LOOP ;------------------ MENU_PREV_IDE_SEC ------------------------------------------------------------------------- MENU_PREV_IDE_SEC: LD DE,PREV_IDE_SEC_MSG CALL PRINT_STRING CALL PREV_SEC jp IDE_LOOP ;------------------MENU_SHOW_IDE_RAM_DMA --------------------------------------------------------------------- MENU_SHOW_IDE_RAM_DMA: CALL SHOW_DMA JP IDE_LOOP SHOW_DMA: LD DE,RAM_MENU_MSG CALL PRINT_STRING LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA NEXT_SHOW_RAM: CALL DISP_SEC_BUFFER ;Show one sector buffer at current DMA address CALL CRLF LD DE,CONTINUE_MSG ;Any keyboard character for next sector. Esc to Main Menu CALL PRINT_STRING CALL ZCI CP A,ESC JP Z,RAM_DONE ;ESC then done LD HL,(@DMA) LD D,(IX+SEC_SIZE_BYTES+1) ;Get sector size LD E,(IX+SEC_SIZE_BYTES) ADD HL,DE LD (@DMA),HL JR NEXT_SHOW_RAM RAM_DONE: LD HL,(@DMA_STORE) ;Start Buffer DMA LD (@DMA),HL RET ;------------------MENU_COPY_IDE_SEC -------------------------------- MENU_COPY_IDE_DRIVE: LD DE,DR_COPY_MENU_MSG ;Copy IDE #1 to IDE #2 CALL PRINT_STRING ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,IDE_LOOP LD DE,ESC_ABORT_MSG ;Hit ESC to stop/abort copying$ CALL PRINT_STRING LD IX,@DRIVE_2_TABLE ;IDE destination Drive will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware XOR A LD (IX+TRK),A LD (IX+SEC),A LD IX,@DRIVE_1_TABLE ;IDE source Drive will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware XOR A LD (IX+TRK),A LD (IX+SEC),A LD DE,START_COPY_MSG ;'Copying started.....(HEX Display shows status)' CALL PRINT_STRING CALL CRLF LD DE,AT_TRK_MSG ;Currently at Track CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA DRIVE_COPY_LOOP: ;READ -------------------------------------- LD HL,(@DMA_STORE) ;Start Buffer DMA ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display call LOCAL_IDE_READ_SECTOR ;<<<<<< Read actual sector at @DMA >>>>>>> JP Z,DR1_COPY_IDE_SEC_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP ;WRITE ---------------------------------------- DR1_COPY_IDE_SEC_OK: CALL SEC_BUMP ;Point to next sector LD HL,(@DMA_STORE) ;Start Buffer DMA ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_2_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware call LOCAL_IDE_WRITE_SECTOR ;<<<<<<<<< write actual sector at @DMA >>>>>> jp z,DR2_COPY_IDE_SEC_OK1 ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP DR2_COPY_IDE_SEC_OK1: CALL QUICK_CSTS ;Any keyboard character will stop display JP Z,MORE_IDE_COPY CALL ZCI ;Flush character LD DE,CONTINUE_MSG CALL PRINT_STRING CALL ZCI CP A,ESC JP Z,FINISH_FCOPY CALL CRLF MORE_IDE_COPY: CALL SEC_BUMP ;Point to next sector JP Z,FINISH_COPY ;Check for end of Disk JP NC,DRIVE_COPY_LOOP ;NC if just a sector increase LD DE,AT_TRK_MSG ;Currently at Track CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT JP DRIVE_COPY_LOOP ;Do next sector FINISH_FCOPY: ld de,DRIVE_COPY_OK_MSG ;'Drive copy complete' call PRINT_STRING LD IX,@DRIVE_2_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE XOR A LD (IX+TRK),A LD (IX+SEC),A LD IX,@DRIVE_1_TABLE ;IDE Drive 1 will always be @DRIVE_1_TABLE LD A,(IX+DRIVE_ADDR) OUT (IDE_CS_PORT),A ;Select drive in hardware XOR A LD (IX+TRK),A LD (IX+SEC),A LD HL,SECTOR_BUFFER LD (@DMA),HL call CRLF ;NZ Abort jp IDE_LOOP ; ; ; ; ;************************************************************************************************************ ;************************************************************************************************************ ;**************************** FLOPPY DRIVE MODULES ********************************************************* ;************************************************************************************************************ ;************************************************************************************************************ ;************************************************************************************************************ ;****; FLOPPY_MENU_INIT: LD IX,@DRIVE_3_TABLE ;Force Tests on 8" SSSD Disk LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card C: JP FLOPPY_LOOP_INITILIZE FL_DRIVES: IN A,(CONFIGURATION_PORT) BIT 6,A JR NZ,FL_DRIVES1 LD DE,NO_FDC_CIRCUIT_MSG ;'NO FDC circuit was detected!$' CALL PRINT_STRING JP MONITOR_MENU LD SP,STACK ;Just to be safe, redo stack at 0FFF0H FL_DRIVES1: LD A,(IX+DRIVE_NUMBER) ;Assume a drive is selected OR A JR Z,NO_DRIVE CP A,3 JR Z,FL_SETUP_3 CP A,4 JR Z,FL_SETUP_4 CP A,5 JR Z,FL_SETUP_5 CP A,6 JR Z,FL_SETUP_6 NO_DRIVE: LD DE,NO_DRIVE_SELECTED_MSG CALL PRINT_STRING JP BEGIN ;Drop back to main menu FL_SETUP_3: LD IX,@DRIVE_3_TABLE ;Get from RAM store the current drive type for hardware Drive [C] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card C: JP FLOPPY_LOOP_INITILIZE FL_SETUP_4: LD IX,@DRIVE_4_TABLE ;Get from RAM store the current drive type for hardware Drive [D] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: JP FLOPPY_LOOP_INITILIZE FL_SETUP_5: LD IX,@DRIVE_5_TABLE ;Get from RAM store the current drive type for hardware Drive [E] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card E: JP FLOPPY_LOOP_INITILIZE FL_SETUP_6: LD IX,@DRIVE_6_TABLE ;Get from RAM store the current drive type for hardware Drive [F] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card F: FLOPPY_LOOP_INITILIZE: CALL FDC_INITILIZE FLOPPY_LOOP: ld de,FLOPPY_MENU_MSG ;List command options call PRINT_STRING CALL SHOW_DRIVE_NAME CALL CRLF call SET_FLOPPY_TRK_SEC ;Update Track/Sec on drive call SHOW_DMA_TRK_SEC ;Display current Track,sector CALL LEDS_FLOPPY ;Update FLOPPY LED HEX display ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,INITILIZE LD C,A CALL ZCO CP A,'U' ; "U" Test WD2793 Chip hardware registers JP Z,MENU_FDC_REG_TEST CP A,'H' ; "H" Step Head in one track JP Z,MENU_STEP_IN_TEST CP A,'X' ; "X" Step Head to track 0 JP Z,MENU_RESTORE_TEST CP A,'Y' ; "Y" Get current Track ID JP Z,MENU_GET_TRACK_ID CP A,'Z' ; "Z" Track seek test JP Z,MENU_SEEK_TRACK_TEST CP A,'E' ; "E" Read the WD2793 Registers JP Z,MENU_READ_WD_REGS CP A,'S' ; "S" Set Track/Sector JP Z,MENU_SET_FDC_TRK_SEC CP A,'B' ; "B" Show DMA Buffer JP Z,MENU_SHOW_FDC_RAM_DMA CP A,'G' ; "G" Set Floppy disk side JP Z,MENU_SET_FDC_SIDE CP A,'N' JP Z,MENU_NEXT_FLOPPY_SEC ; "N" Next Sector CP A,'P' JP Z,MENU_PREV_FLOPPY_SEC ; "P" Previous Sector CP A,'R' JP Z,MENU_READ_FLOPPY_SEC ; "R" Read sector(s) to data buffer CP A,'F' JP Z,MENU_FILL_FLOPPY_SEC ; "F" Fill a sector with a byte value CP A,'W' JP Z,MENU_WRITE_FLOPPY_SEC ; "W" Write data at a RAM location to a sector CP A,'C' JP Z,MENU_SEC_COPY_FLOPPY ; "C" Copy a sector to another sector CP A,'V' JP Z,MENU_SEC_VERIFY_FLOPPY ; "V" verify a sector = another sector CP A,'M' JP Z,MENU_FDC_DISK_COPY ; "M" Copy Drive C:->D: CP A,'T' ; :T" Read the current Track JP Z,MENU_READ_FDC_TRACK CP A,'D' JP Z,MENU_FORMAT_FDC_DISK ; "D" Format disk JP FLOPPY_LOOP LEDS_FLOPPY: LD A,(IX+TRK) CALL DISPLAY_HEX_TRACK LD A,(IX+SEC) CALL DISPLAY_HEX_SECTOR RET DISPLAY_HEX_SECTOR: ;Shortcut to immediatly dump [A] on Sector TILs PUSH AF ;Store the value in A AND A,0FH ;Get low Nibble first OUT HEX_DISPLAY_PORT,A LD B,00010000B ;To lower strobe for TIL 0 OR B OUT HEX_DISPLAY_PORT,A POP AF ;Get back stored [A] RRA RRA RRA RRA AND A,0FH OUT HEX_DISPLAY_PORT,A LD B,00100000B ;Raise strobe for TIL 1 OR A,B OUT HEX_DISPLAY_PORT,A LD A,00000000B ;Lower strobe for TIL 0 OUT HEX_DISPLAY_PORT,A RET DISPLAY_HEX_TRACK: ;Shortcut to immediatly dump [A] on Sector TILs PUSH AF ;Store the value in A AND A,0FH ;Get low Nibble first OUT HEX_DISPLAY_PORT,A LD B,01000000B ;To lower strobe for TIL 3 OR A,B OUT HEX_DISPLAY_PORT,A POP AF ;Get back stored [A] RRA RRA RRA RRA AND A,0FH OUT HEX_DISPLAY_PORT,A LD B,10000000B ;Raise strobe for TIL 4 OR A,B OUT HEX_DISPLAY_PORT,A LD A,00000000B ;Lower strobe for TIL 4 OUT HEX_DISPLAY_PORT,A RET MENU_VERIFY_FLOPPY_SEC: ; "V" Verify sector(s) are teh same MENU_DRIVE_COPY_FLOPPY: ; "M" Copy IDE Drive #1 to IDE Drive #2 LD DE,MENU_ERR_MSG ;'Invalid Menu Command!' CALL PRINT_STRING JP FLOPPY_LOOP ;------------------------------------------------------------------------------------------------------ MENU_FDC_REG_TEST: CALL CRLF LD DE,FDC_RESET_MSG ;'Will Reset WD2793 Chip and Set TRACK,SECTOR = 0,1$' CALL PRINT_STRING ;XXX: ; LD A,33H ; OUT (WD2793_CMD),A ; JR XXX: XOR A ;Pulse Reset pin 19 OUT (WD2793_RESET),A INC A OUT (WD2793_RESET),A XOR A OUT (WD2793_RESET),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct XOR A,A OUT (WD2793_TRACK),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct INC A OUT (WD2793_SECTOR),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct CALL CRLF LD DE,FDC_GOT_MSG ;'The WD2793 Chip TRACK,SECTOR returned:$' CALL PRINT_STRING IN A,(WD2793_TRACK) CALL HEXOUT LD C,',' CALL ZCO IN A,(WD2793_SECTOR) CALL HHEXOUT CALL CRLF LD DE,UPDATE_TRACK_MSG ;'Will now continously update the WD2793 TRACK,SECTOR Registers. Hit CR to continue, ESC to abort$' CALL PRINT_STRING CALL ZCI LD HL,4321H MORE2: LD A,H OUT (WD2793_TRACK),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct LD A,L OUT (WD2793_SECTOR),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct LD A,H CALL HEXOUT LD A,L CALL HEXOUT LD C,'-' CALL ZCO IN A,(WD2793_TRACK) LD D,A IN A,(WD2793_SECTOR) LD E,A LD A,D CALL HEXOUT LD A,E CALL HEXOUT LD A,D CP A,H CALL NZ,ERR1 LD A,E CP A,L CALL NZ,ERR1 INC L INC H CALL CRLF CALL ZCSTS JP Z,MORE2 CALL ZCI CP A,ESC JP Z,MONITOR_MENU ;Drop back to main menu JP FLOPPY_LOOP ERR1: LD C,'*' CALL ZCO CALL ZCO LD C,BELL CALL ZCO RET ;------------------------------------------------------------------------------------------------------ MENU_NEXT_FLOPPY_SEC: CALL SEC_BUMP JP FLOPPY_LOOP ;Z if all OK ;------------------------------------------------------------------------------------------------------ MENU_PREV_FLOPPY_SEC: CALL PREV_SEC JP FLOPPY_LOOP ;Z if all OK ;------------------------------------------------------------------------------------------------------ MENU_STEP_IN_TEST: ;Note the Track register on the WD2793 is NOT updated LD DE,FDC_STEP_MSG ;'H' Will Step the Floppy disk head in one track CALL PRINT_STRING CALL CORE_STEP_IN JP Z,STEP_IN_OK CP A,0FFH LD DE,STEP_IN_HUNG ;'WD2793 Timeout Error after STEP-IN Command$' JP Z,STEPIN_ERR1 LD DE,STEP_IN_ERR ;Must be 'Head Step In Error, DRIVE NOT READY ERROR$' STEPIN_ERR1: CALL PRINT_STRING JP FLOPPY_LOOP ;Return to Floppy menu STEP_IN_OK: LD DE,STEP_IN_OK_MSG ;'Head Step In Command returned no errors$' CALL PRINT_STRING JP FLOPPY_LOOP ;Z if all OK CORE_STEP_IN: ;<<<<<<<<<<<<<<<<<<<<<<<<< LD A,STEPIN OUT (WD2793_CMD),A LD D,SIN_ERR_MASK ;Just look at DRIVE NOT READY bit CALL WD2793_WAIT ;Wait 30uS, then return status in A RET ;Z if no errors, NZ, error bits in A CORE_STEP_OUT: ;<<<<<<<<<<<<<<<<<<<<<<<<< LD A,STEPOUT OUT (WD2793_CMD),A LD D,SIN_ERR_MASK ;Just look at DRIVE NOT READY bit CALL WD2793_WAIT ;Wait 30uS, then return status in A RET ;Z if no errors, NZ, error bits in A ;------------------------------------------------------------------------------------------------------ MENU_RESTORE_TEST: ;'X' Will Restore the Floppy disk head to track 0 LD DE,FDC_RESTORE_MSG CALL PRINT_STRING CALL CORE_RESTORE JP Z,RESTORE_OK ;Z if all OK RESTORE_ERRORS: CP A,0FFH LD DE,RESTORE_HUNG ;'WD2793 Timeout Error after RESTORE Command$' JP Z,RESTORE_ERR1 LD DE,RESTORE_ERR ;Must be 'Restore Error, DRIVE NOT READY ERROR$' RESTORE_ERR1: CALL PRINT_STRING JP FLOPPY_LOOP ;Return to Floppy menu RESTORE_OK: XOR A,A LD (IX+TRK),A ;Do not adjust side or sector LD (@CURRENT_TRACK),A call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA address CALL LED_TRK_SEC ;Update LED HEX display LD DE,RESTORE_OK_MSG ;'Head Restore Command returned no errors$' CALL PRINT_STRING JP FLOPPY_LOOP ;Z if all OK CORE_RESTORE: LD A,RSCMD ;<<<<<<<<<<<<<<<<<<<<<<<<< OUT (WD2793_CMD),A LD D,SIN_ERR_MASK ;Just look at DRIVE NOT READY bit CALL WD2793_WAIT ;Wait 30uS, then check status RET NZ IN A,(WD2793_TRACK) ;Get track# in data register LD (IX+TRK),A ;Do not adjust side RET ; ------------------------------------------------------------------------------------------------- ; Seek to track test, WITH verify. Assumes VALID track in (IX+TRK) ; Note, Re-seeks ARE done here. MENU_SEEK_TRACK_TEST: LD DE,FDC_SEEK_MSG ;'Y' Seek Track with verify routine CALL PRINT_STRING LD A,SEEK_RETRY_MAX ;Put Seek retry count here LD (@SEEK_RT),A LD HL,ID_BUFFER ;Will store the 6 bytes here XOR A LD (HL),A ;1 INC HL LD (HL),A ;2 INC HL LD (HL),A ;3 INC HL LD (HL),A ;4 INC HL LD (HL),A ;5 INC HL LD (HL),A ;6 XOR A ;Start at Track 0 LD (IX+TRK),A CALL SET_A_SIDE CALL CRLF CALL CORE_RESTORE ;Core Head Restore routine SEEK_TRACK1: CALL QUICK_CSTS ;Any keyboard character will stop display JP Z,SEEK_TRACK2 CALL ZCI ;Flush character LD DE,CONTINUE_MSG CALL PRINT_STRING CALL ZCI CP A,ESC JP Z,FLOPPY_LOOP CALL CRLF SEEK_TRACK2: LD DE,AT_TRACK_MSG ;'Current track = $ CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT LD DE,ID_BUFFER_CONTENTS ;'Track ID = $' CALL PRINT_STRING LD A,(IX+TRK) CALL CORE_SEEK ;<<<< Seek to Track in[A] JP Z,SEEK_OK LD A,(@SEEK_RT) ;Get Seek retry count DEC A LD (@SEEK_RT),A JP Z,SEEK_TRK_ERROR ;If Z, retrys did not work CALL CORE_RESTORE ;Core Head Restore routine JP Z,SEEK_TRACK1 ;Retry seek after this restore command JP RESTORE_ERRORS SEEK_TRK_ERROR: CP A,0FFH ;Was there a timeout error LD DE,SEEK_TRK_HUNG JP Z,SEEK_ERR1 LD DE,SEEK_REST_ERR ;Must be a WD2793 status RESTORE (DRIVE NOT READY) error SEEK_ERR1: CALL PRINT_STRING JP FLOPPY_LOOP ;return to main menu SEEK_OK: CALL CORE_GET_TRACK_ID ;<<<<<<<<<<<<<<<<<< PUSH AF LD HL,ID_BUFFER ;Get Location of ID Buffer LD B,6 ;Six bytes total SEEK_OK2: LD A,(HL) CALL HEXOUT ;Send 6 bytes to USB Terminal INC HL DJNZ SEEK_OK2 POP AF ;Any eerrors? JR Z,TRACK_ID_OK CP A,0FFH ;Was there a timeout error LD DE,ID_ERR_HUNG JP Z,TRK_ID_ERROR2 ;Abort is Hung BIT 7,A LD DE,ID_ERR1 ;Get Track ID, NOT READY flag JP NZ,TRK_ID_ERROR2 BIT 4,A LD DE,ID_ERR2 ;Get Track ID, RNF ERROR flag JP NZ,TRK_ID_ERROR2 BIT 2,A LD DE,ID_ERR3 ;Get Track ID, LOST DATA ERROR flag JP NZ,TRK_ID_ERROR2 LD DE,ID_ERR4 ;Must be CRC ERROR flag JP TRK_ID_ERROR2 TRK_ID_ERROR2: CALL PRINT_STRING TRACK_ID_OK: CALL LEDS_FLOPPY ;Update the Floppy HEX display CALL CRLF LD A,SEEK_RETRY_MAX ;Put Seek retry count here LD (@SEEK_RT),A CALL RANDOM_TRK_SEC ;Get a new random track in IX+TRK LD A,(IX+TRK) LD B,(IX+NTRKS) ;Are we at the end DEC B LD A,(IX+TRK) CP A,B JP Z,SEEK_END JP SEEK_TRACK1 ;Next track SEEK_END: XOR A LD (IX+TRK),A CALL SET_CURRENT_SIDE CALL CORE_RESTORE ;Core Head Restore routine if at the last Track JP Z,SEEK_TRACK1 ;Retry seek after this restore command JP RESTORE_ERRORS CORE_SEEK: ;<<<<<<<< Track is in [A] OUT (WD2793_DATA),A ;Put required track# in data register LD (IX+TRK),A ;Update table LD A,SKCMD ;Then send a Seek with Verify CMD OUT (WD2793_CMD),A ;Send seek cmd to current drive LD D,SK_ERR_MASK ;Mask for Seek with verify bits CALL WD2793_WAIT ;Wait 30uS, then check status and return RET ;------------------------------------------------------------------------------------------------------ ; Read an ID from the Track that the head of the current disk is on. ; Note any Sector ID from the track will be obtained depending where the head falls ; The currently selected side at (SIDE) is read. Six bytes of ID data are passed back to Z80 CPU MENU_GET_TRACK_ID: LD DE,GET_TRK_ID ;Get current tarck ID CALL PRINT_STRING CALL CRLF LD HL,ID_BUFFER ;Will store the 6 bytes here XOR A LD (HL),A ;1 INC HL LD (HL),A ;2 INC HL LD (HL),A ;3 INC HL LD (HL),A ;4 INC HL LD (HL),A ;5 INC HL LD (HL),A ;6 CALL FDC_RDY CALL CORE_GET_TRACK_ID ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< PUSH AF LD DE,TRK_ID_MSG ;'Track ID = $' CALL PRINT_STRING LD HL,ID_BUFFER ;Get Location of ID Buffer LD B,6 ;Six bytes total SEEK_OK1: LD A,(HL) CALL HEXOUT ;Send 6 bytes to USB Terminal INC HL DJNZ SEEK_OK1 POP AF ;Any errors? JR Z,GET_TRACK_ID_OK CP A,0FFH ;Was there a timeout error LD DE,ID_ERR_HUNG JP Z,TRK_ID_ERROR ;Abort is Hung BIT 7,A LD DE,ID_ERR1 ;Get Track ID, NOT READY flag JP NZ,TRK_ID_ERROR BIT 4,A LD DE,ID_ERR2 ;Get Track ID, RNF ERROR flag JP NZ,TRK_ID_ERROR BIT 2,A LD DE,ID_ERR3 ;Get Track ID, LOST DATA ERROR flag JP NZ,TRK_ID_ERROR LD DE,ID_ERR4 ;Must be CRC ERROR flag JP TRK_ID_ERROR TRK_ID_ERROR: CALL PRINT_STRING GET_TRACK_ID_OK: CALL CRLF JP FLOPPY_LOOP ;All OK CORE_GET_TRACK_ID: ;<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< PUSH HL PUSH DE PUSH BC LD HL,ID_BUFFER ;Will store the 6 bytes here LD B,6 LD C,WD2793_DATA ;6 bytes in B, Data port in [C] below LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,RDACMD ;Send the Read Track ID CMD OUT (WD2793_CMD),A WD_SEC_ID: IN A,(WD2793_STATUS) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,WD_SEC_ID ;if no data IN A,(C) LD [HL],A ;For some reason INI does NOT work. Seems too fast! INC HL DJNZ WD_SEC_ID LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,ID_ERR_MASK CALL WD2793_WAIT ;Wait 30uS, then check status and return POP BC POP DE POP HL RET NZ IN A,(WD2793_TRACK) ;Get track# in data register LD (IX+TRK),A RET ;------------------------------------------------------------------------------------------------------ MENU_READ_FLOPPY_SEC: CALL CRLF LD DE,RD_SEC_MENU_MSG ;Read Track,Sector CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP MORE_FLOPPY_SEC_READ: LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA call CRLF CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA JP Z,RD_SEC_FLOPPY_OK ;Z means the sector read was OK RD_SEC_FLOPPY_ERR: ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Error, so Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort JP FLOPPY_LOOP RD_SEC_FLOPPY_OK: call DISP_SEC_BUFFER ;Show sector data @DMA CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA address CALL LED_TRK_SEC ;Update LED HEX display LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL LD DE,RD_NEXT_SEC ;'Hit any key for next sector. ESC to abort$' call PRINT_STRING CALL ZCI CP A,ESC JP Z,FLOPPY_LOOP CALL SEC_BUMP LD A,(@CURRENT_TRACK) CP A,(IX+TRK) JP Z,MORE_FLOPPY_SEC_READ LD A,(IX+TRK) CALL CORE_SEEK ;<<<< Seek to next Track in [A] JP NZ,RD_SEC_FLOPPY_ERR JP MORE_FLOPPY_SEC_READ ;------------------------------------------------------------------------------------------------------ MENU_FILL_FLOPPY_SEC: ; "F" Fill a sector with a byte value CALL CRLF LD DE,FILL_MENU_MSG CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP LD DE,FILL_BYTE_MSG ;Enter the sector fill byte (xxH);- call PRINT_STRING call GETHEX jp c,IDE_LOOP ;Abort if ESC (C flag set) LD (@FILL_BYTE),A ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,FLOPPY_LOOP LD A,(@FILL_BYTE) ;Fill Byte LD B,0 ;Assume worse case scenerio, 1K sectors so 256X4 = 1024 bytes LD HL,SECTOR_BUFFER MORE_FLOPPY_CLEAR: LD (HL),A INC HL LD (HL),A INC HL LD (HL),A INC HL LD (HL),A INC HL DJNZ MORE_FLOPPY_CLEAR LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER LD (@DMA),HL LD (@DMA_STORE),HL call CRLF CALL CORE_FLOPPY_WRITE_SECTOR ;write actual sector at @DMA JP Z,FILL_FLOPPY_SEC_OK ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP FILL_FLOPPY_SEC_OK: ld de,FILL_msgwr ;'Sector Fill was OK' call PRINT_STRING ; call DISP_SEC_BUFFER ;Show sector data @DMA CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA CALL LED_TRK_SEC ;Update LED HEX display ld de,FILL_OK_MSG ;'SectorFilled OK call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP ;------------------WRITE_FLOPPY_SEC ------------------------------------------------------------------- MENU_WRITE_FLOPPY_SEC: ;Write data in RAM location to sector @ LBA CALL CRLF LD DE,WR_SEC_MENU_MSG ;Write Track,Sector:-$' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP LD DE,WR_RAM_MENU_MSG ;From RAM at:- (XXXXH):$' CALL PRINT_STRING CALL EXPR1 ;Get 16 bit value, put on stack POP HL ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' jp nz,FLOPPY_LOOP CALL CRLF CALL FDC_RDY CALL CORE_FLOPPY_WRITE_SECTOR ;write actual sector at @DMA jp z,WR_SEC_FLOPPY_OK ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;Error, so back to start Buffer DMA LD (@DMA),HL JP FLOPPY_LOOP WR_SEC_FLOPPY_OK: ld de,SEC_WR_OK ;'Sector Write OK' call PRINT_STRING ; call DISP_SEC_BUFFER ;Show sector data @DMA CALL CRLF call SHOW_DMA_TRK_SEC ;Display current Track,sector at @DMA address CALL LED_TRK_SEC ;Update LED HEX display LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL JP FLOPPY_LOOP ;------------------------------------------------------------------------------------------------------ MENU_READ_WD_REGS: LD DE,WD_STATUS_MSG ;WD Status Register CALL PRINT_STRING IN A,(WD2793_STATUS) ;Get FDC status CALL HHEXOUT LD DE,WD_TRACK_MSG ;WD Tarck Register CALL PRINT_STRING IN A,(WD2793_TRACK) CALL HHEXOUT LD DE,WD_SECTOR_MSG ;WD Sector Register CALL PRINT_STRING IN A,(WD2793_SECTOR) CALL HHEXOUT LD DE,WD_DATA_MSG ;WD Data Register CALL PRINT_STRING IN A,(WD2793_DATA) CALL HHEXOUT JP FLOPPY_LOOP ;------------------------------------------------------------------------------------------------ ; MENU_SEC_COPY_FLOPPY: CALL CRLF LD DE,COPY_MENU_MSG CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,IDE_LOOP LD A,(IX+TRK) LD (@TRK_SOURCE),A ;Store starting Trk/Sec LD A,(IX+SEC) LD (@SEC_SOURCE),A LD DE,TO_MSG ;' To----> ' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP LD A,(IX+TRK) LD (@TRK_DEST),A ;Store destination Trk/Sec LD A,(IX+SEC) LD (@SEC_DEST),A LD A,(@TRK_SOURCE) ;Get back starting track/sec LD (IX+TRK),A LD A,(@SEC_SOURCE) LD (IX+SEC),A ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,FLOPPY_LOOP LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),hl ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA jp z,COPY_FLOPPY_SEC_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP COPY_FLOPPY_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display source DMA, Track,sector (only) ;Now write it to destination LD A,(@TRK_DEST) ;Get back destination track/sec LD (IX+TRK),A LD A,(@SEC_DEST) LD (IX+SEC),A LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),hl ;Point to buffer call SET_FLOPPY_TRK_SEC ;Update LBA on drive CALL FDC_RDY CALL CORE_FLOPPY_WRITE_SECTOR ;<<<<<<<<< Write actual Floppy sector at @DMA jp z,COPY_FLOPPY_DONE ;Z means the sector write was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP COPY_FLOPPY_DONE: ld de,WR_TO_msgwr ;'Copy to Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display destination Track,sector at @DMA ld de,COPY_OK_MSG ;'Copy to Sector:- ' call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP ;------------------ MENU_VERIFY_IDE_SEC ------------------------------------------------------------------------------------- ; ; MENU_SEC_VERIFY_FLOPPY: CALL CRLF LD DE,VERIFY_MENU_MSG CALL PRINT_STRING ld hl,(@DMA) ;Point to buffer LD (@DMA_STORE),HL ;for when we are finished call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP LD A,(IX+TRK) LD (@TRK_$1),A ;Store starting Trk/Sec LD A,(IX+SEC) LD (@SEC_$1),A LD DE,WITH_MSG ;' With ----> ' CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK JP NZ,FLOPPY_LOOP LD A,(IX+TRK) LD (@TRK_$2),A ;Store destination Trk/Sec LD A,(IX+SEC) LD (@SEC_$2),A LD A,(@TRK_$1) ;Get back starting track/sec LD (IX+TRK),A LD A,(@SEC_$1) LD (IX+SEC),A LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_$1),HL ;Always Start Buffer DMA (TRK#1,SEC#1) LD DE,1000H ;Worse case scenerio 1K sectors ADD HL,DE LD (@DMA_$2),HL ;Always for second sector @DMA (TRK#2,SEC#2) call CRLF LD HL,(@DMA_$1) LD (@DMA),HL CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA jp z,VERIFY_FDC_SEC_OK ;Z means the sector read was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP VERIFY_FDC_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display source DMA, Track,sector (only) ;Now compare with "destination sector" LD A,(@TRK_$2) ;Get back destination track/sec LD (IX+TRK),A LD A,(@SEC_$2) LD (IX+SEC),A LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A call SET_IDE_TRK_SEC ;Update LBA on drive LD HL,(@DMA_$2) LD (@DMA),HL ;@DMA now pointng to second RAM buffer area CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA jp z,VERIFY_1_FDC_SEC_OK ;Z means the sector write was OK ld de,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD HL,(@DMA_STORE) ;back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP VERIFY_1_FDC_SEC_OK: ld de,RD_FROM_msgrd ;'Read from Sector:- ' call PRINT_STRING call SHORT_DMA_TRK_SEC ;Display destination Track,sector at @DMA CALL COMPARE_BUFFERS ;Tell if sectors match or not CALL CRLF LD HL,(@DMA_STORE) ;Back to start Buffer DMA LD (@DMA),HL call CRLF ;NZ Abort jp FLOPPY_LOOP ;------------------- MENU COPY FLOPPY C: -> D: ---------------------------------------------------------- MENU_FDC_DISK_COPY: ; "M" Copy Drive C:->D: CALL CRLF LD DE,FDC_FLOPPY_COPY_MSG ;Will copy all sectors on Floppy disk C: to D: CALL PRINT_STRING ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,FLOPPY_LOOP LD DE,ESC_TO_ABOPRT_MSG ;Hit ESC to abort CALL PRINT_STRING CALL SET_A_SIDE ;This will set @CURRENT_SIDE = 0 SECOND_SIDE: XOR A ; LD A,48H ;For testing only LD (@CURRENT_TRACK),A LD A,1 LD (@CURRENT_SECTOR),A LD IX,@DRIVE_4_TABLE ;Get from RAM store the current drive type for hardware Drive [D] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL SET_CURRENT_SIDE LD IX,@DRIVE_3_TABLE ;Get from RAM store the current drive type for hardware Drive [C] LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select FLOPPY card D: LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL SET_CURRENT_SIDE LD HL,SECTOR_BUFFER ;Load up a Track worth of sectors (26), starting here. ld (@DMA),HL ;Point to buffer ;--------------------------------------------------------------------------------------------------- FDC_FAST_COPY_LOOP: LD IX,@DRIVE_3_TABLE ;Floppy Drive C: will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware MORE_TRACK_READ: ;Next sector on same track LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display LD DE,COPY_TRACK_MSG ;Transferring Track $' CALL PRINT_STRING LD A,(@CURRENT_TRACK) CALL HEXOUT LD DE,COPY_TRACK2_MSG ;H, Sector $' CALL PRINT_STRING LD A,(@CURRENT_SECTOR) CALL HHEXOUT CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;Read actual Floppy sector at @DMA jp z,FDC_DISK_READ_SEC_OK ;Z means the sector read was OK LD DE,SEC_READ_ERROR ;Sector read error call PRINT_STRING LD (@DMA),HL call CRLF JP FDC_COPY_ERROR FDC_DISK_READ_SEC_OK: LD (@DMA),HL ;Save current pointer LD A,(@CURRENT_SECTOR) INC A LD C,(IX+NSCTRS) CP A,C JP Z,FDC_TRACK_WRITE1 ;Last sec on track, then done LD (@CURRENT_SECTOR),A JP MORE_TRACK_READ ;Next sector on same track FDC_TRACK_WRITE1: LD A,1 ;Back to first sector on track LD (@CURRENT_SECTOR),A FDC_TRACK_WRITE: ;-------------Write to second disk ---------------- LD HL,SECTOR_BUFFER ;Load up a Track worth of sectors (26), starting here. ld (@DMA),HL ;Point to buffer LD IX,@DRIVE_4_TABLE ;IDE Drive 2 will always be @DRIVE_2_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware LD A,(@CURRENT_TRACK) LD (IX+TRK),A LD A,(@CURRENT_SECTOR) LD (IX+SEC),A CALL LED_TRK_SEC ;Update LED HEX display CALL LED_DRIVE ;Lock in Drive number on drive display MORE_TRACK_WRITE: CALL FDC_RDY ;WriteRead actual Floppy sector at @DMA CALL CORE_FLOPPY_WRITE_SECTOR ;Write actual Floppy sector at @DMA JP Z,FDC_DISK_WRITE_SEC_OK ;Z means the sector read was OK ld de,SEC_WRITE_ERROR ;Sector write error call PRINT_STRING LD (@DMA),HL call CRLF ;NZ Abort JP FDC_COPY_ERROR FDC_DISK_WRITE_SEC_OK: LD (@DMA),HL CALL QUICK_CSTS ;Any keyboard character will stop display JP Z,DISK_DRIVE_BUMP CALL ZCI ;Flush character LD DE,CONTINUE_MSG CALL PRINT_STRING CALL ZCI CP A,ESC JP Z,FDC_ABORT_DISK_COPY CALL CRLF DISK_DRIVE_BUMP: LD A,(@CURRENT_SECTOR) INC A LD C,(IX+NSCTRS) CP A,C JP Z,TRACK_WRITTEN ;Last sec on track, then done LD (@CURRENT_SECTOR),A JP FDC_TRACK_WRITE ;Next sector on same track TRACK_WRITTEN: LD A,1 LD (@CURRENT_SECTOR),A LD A,(@CURRENT_TRACK) CP A,(IX+NTRKS) ;8", 76 tracks JP Z,FDC_COPY_DONE ;At last sector+1 INC A LD (@CURRENT_TRACK),A JP FDC_FAST_COPY_LOOP FDC_COPY_DONE: LD A,(IX+SIDES_NUMBER) ;Is it a double sided disk CP A,2 JP NZ,FINISH_COPY ;No then we are done LD A,(IX+DRIVE_ADDR) ;Are we already on side B BIT 2,A JP Z,FINISH_COPY ;We have done with side B as well LD DE,FORMATING_B_SIDE ;'Copying B side$' CALL PRINT_STRING CALL CORE_RESTORE ;Lower head/Start Motor. Must be done here/early. Absolutly critical the disk XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) LD A,1 LD (IX+SEC),A CALL SET_B_SIDE ;This will set @CURRENT_SIDE =1 CALL LED_TRK_SEC ;Update LED HEX display JP MORE_FORMAT_FDC_DISK ;Do side B FINISH_COPY: ld de,FDC_DRIVE_OK_MSG ;Floppy Disk copy complete call PRINT_STRING JP FDC_FINISH_COPY FDC_ABORT_DISK_COPY: LD DE,FDC_FAST_ABORT_MSG ;Fast Copy of Disk C:->D: Aborted call PRINT_STRING JP FDC_FINISH_COPY FDC_COPY_ERROR: LD DE,FDC_FAST_RW_ERROR_MSG ;Fast Copy of Disk C:->D: R/W Error call PRINT_STRING JP FDC_FINISH_COPY FDC_FINISH_COPY: LD HL,SECTOR_BUFFER LD (@DMA),HL call CRLF ;NZ Abort LD IX,@DRIVE_3_TABLE ;Floppy Drive C: will always be @DRIVE_3_TABLE LD A,(IX+DRIVE_ADDR) OUT (FDC_SELECT_PORT),A ;Select drive in hardware CALL CORE_RESTORE XOR A,A LD (IX+TRK),A LD A,1 LD (IX+SEC),A CALL SET_A_SIDE jp FLOPPY_LOOP ;------------------------------------------------------------------------------------------------ ; MENU_SET_FDC_TRK_SEC: LD DE,TRK_SEC_MENU_MSG ;Enter New Track,Sector (XX,XX) CALL PRINT_STRING call GET_NEW_TRK_SEC ;Get new CPM style Track & Sector number and put them in RAM at IX+SEC & IX+TRK LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,SEEK_RETRY_MAX ;Put Seek retry count here LD (@SEEK_RT),A SET_TRK_SEC1: LD A,(@CURRENT_TRACK) CALL CORE_SEEK ;<<<< Seek to Track in [A] (if required) JP Z,FLOPPY_LOOP LD A,(@SEEK_RT) DEC A LD (@SEEK_RT),A ;Save for next time JP Z,BAD_SET_TRK_SEC CALL CORE_RESTORE ;Core Head Restore routine JP SET_TRK_SEC1 ;Retry seek after this restore command BAD_SET_TRK_SEC: LD DE,TRK_SEEK_FAIL_MSG ;Could not see to Track CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT JP FLOPPY_LOOP ;------------------------------------------------------------------------------------------------ MENU_SET_FDC_SIDE: ;"G" Set Floppy disk side LD DE,SET_SIDE_MSG ;Enter Side of current Disk (A,B): CALL PRINT_STRING CALL ZCI ;Get character and echo cp ESC ;ESC back to main menu jp z,FLOPPY_LOOP CALL UPPER LD C,A CALL ZCO CP A,'B' JR Z,MENU_B_SIDE CALL SET_A_SIDE JP FLOPPY_LOOP MENU_B_SIDE: CALL SET_B_SIDE JP FLOPPY_LOOP SET_A_SIDE: PUSH AF SET_A_SIDE1: LD A,1 LD (IX+SIDE),A LD (@CURRENT_SIDE),A LD A,(IX+DRIVE_ADDR) ;Select side A in hardware SET 2,A ;1 = Side A LD (IX+DRIVE_ADDR),A OUT (FDC_SELECT_PORT),A ;Select drive/Side POP AF RET SET_B_SIDE: PUSH AF SET_B_SIDE1: LD A,0 LD (IX+SIDE),A LD (@CURRENT_SIDE),A LD A,(IX+DRIVE_ADDR) ;Select side B in hardware RES 2,A ;0 = Side B LD (IX+DRIVE_ADDR),A OUT (FDC_SELECT_PORT),A ;Select drive/Side POP AF RET SET_CURRENT_SIDE: PUSH AF LD A,(@CURRENT_SIDE) OR A,A JP Z,SET_B_SIDE1 JP SET_A_SIDE1 GET_CURRENT_SIDE: LD A,(@CURRENT_SIDE) OR A,A RET ;------------------------------------------------------------------------------------------------ ; MENU_SHOW_FDC_RAM_DMA: CALL SHOW_DMA JP FLOPPY_LOOP ;------------------------------------------------------------------------------------------------------ ; ; ; READ TRACK ROUTINE. This routine first reads a complete track from a disk (via WD2793 chip) to ; RAM on the FPGA_DC board. One complete track is read, index hole to index hole MENU_READ_FDC_TRACK: LD DE,TRACK_DATA ;Complete contents of Track CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT PUSH AF CALL CORE_RESTORE POP AF LD (IX+TRK),A CALL CORE_SEEK ;<<<<<<<< Track is in [A] CALL CRLF LD HL,SECTOR_BUFFER ;Will will load the complete track image here (9000H) LD BC,MAX_TRACK_SIZE ;so for debugging it can be seen with the monitor command what was read XOR A,A RDO_FILL: LD (HL),A ;Fill the whole Buffer area with "blank" bytes INC HL DEC C JR NZ,RDO_FILL DEC B JR NZ,RDO_FILL ;Do 4K, (should be overkill)! DI ;Just in case LD E,(IX+TRACK_SIZE) ;Total number of bytes on a track LD D,(IX+TRACK_SIZE+1) LD HL,SECTOR_BUFFER ;Will will build the complete track image here LD C,WD2793_DATA ;Data port for collection LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,RDTCMD ;Send the Read Track CMD OUT (WD2793_CMD),A CALL DELAY_30uS WD_TRK_RD: IN A,(WD2793_STATUS) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,WD_TRK_RD ;if no data IN A,(C) LD [HL],A ;For some reason INI does NOT work. Seems too fast! INC HL DEC DE LD A,E OR A,D JR NZ,WD_TRK_RD LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,RT_ERR_MASK CALL WD2793_WAIT ;Wait 30uS, then check status and return JR Z,READ_TRACK_OK LD DE,TRACK_DATA_ERR ;Read Track Error was detected CALL PRINT_STRING JP FLOPPY_LOOP READ_TRACK_OK: CALL CRLF LD HL,SECTOR_BUFFER ;GET PARAMETERS IN [HL],[DE] LD DE,SECTOR_BUFFER + MAX_TRACK_SIZE LD A,L ;ROUND OFF ADDRESSES TO XX00H AND 0F0H LD L,A ; LD A,E ;FINAL ADDRESS LOWER HALF LD A,16 ;Display line count LD (@LINE_COUNT),A AND 0F0H ADD A,10H ;FINISH TO END 0F LINE RSF172: CALL LFAD ;CRLF, Print [HL] value RSF175: LD C,SPACE ;One space across CALL ZCO LD A,(HL) CALL HEXOUT CALL HILOX LD A,L AND 0FH JR NZ,RSF175 LD C,TAB ;INSERT A TAB BETWEEN DATA CALL ZCO LD B,4H ;ALSO 4 SPACES RTA11: LD C,SPACE CALL ZCO DJNZ RTA11 LD B,16 ;NOW PRINT ASCII (16 CHARACTERS) PUSH DE ;TEMPORLY SAVE [DE] LD DE,0010H SBC HL,DE POP DE RT11: LD A,(HL) AND 7FH CP ' ' ;FILTER OUT CONTROL CHARACTERS' JR NC,RTT33 RTT22: LD A,'.' RTT33: CP 07CH JR NC,RTT22 LD C,A ;SET UP TO SEND CALL ZCO INC HL DJNZ RT11 ;REPEAT FOR WHOLE LINE LD A,(@LINE_COUNT) DEC A LD (@LINE_COUNT),A ;Check if we have done a page of lines JR NZ,RSF172 LD A,16 LD (@LINE_COUNT),A CALL CRLF PUSH DE LD DE,HIT_SP_MSG ;"Hit ESC to Abort Msg" CALL PRINT_STRING CALL ZCI CP A,ESC POP DE JR Z,TRK_DONE CALL CRLF JR RSF172 TRK_DONE: JP FLOPPY_LOOP ;PRINT [HL] AND A SPACE LFAD: CALL CRLF PUSH HL PUSH BC CALL LADR LD C,SPACE CALL ZCO POP BC POP HL RET ;PRINT [HL] ON CONSOL LADR: LD A,H CALL HEXOUT LD A,L CALL HEXOUT RET ;------------------------------------------------------------------------------------------------ ; ; MENU_FORMAT_FDC_DISK: ;Because or limited ROM space this routine will only format a standard 8" SDSS CALL CORE_RESTORE XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) CALL SET_A_SIDE LD DE,FORMAT_TRK_START_MSG ;'Will format Disk Side A. Hit any key to halt, ESC to abort$' CALL PRINT_STRING ld de,msgsure ;Are you sure? call PRINT_STRING call ZCI call upper LD C,A ;Print response CALL ZCO CP A,'Y' PUSH AF CALL CRLF POP AF jp nz,FLOPPY_LOOP MORE_FORMAT_FDC_DISK: LD DE,FORMAT_TRK_MSG ;'Format Track = $' CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT LD A,(IX+TRK) OUT (WD2793_DATA),A ;Put required track# in data register CALL BUILD_TRACK ;<<<<<<< Build a complete track image in RAM @ SECTOR_BUFFER LD HL,SECTOR_BUFFER ;To start of Buffer LD E,(IX+TRACK_SIZE) LD D,(IX+TRACK_SIZE+1) DI ;Disable Interrupts -- just in case LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,(IX+TRK) OUT (WD2793_DATA),A ;Put required track# in data register LD A,WRTCMD ;Send the Write Track CMD OUT (WD2793_CMD),A LD C,WD2793_DATA ;Data port in [C] below CALL DELAY_30uS ; <<<<<<<<<<<<<<<<<<<<< WRITE_TRACK - SIDE A >>>>>>>>>>>>>>>>>>>>> WT2: IN A,(WD2793_Status) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,WT2 ;if no data LD A,(HL) OUT (C),A INC HL DEC DE LD A,E OR A,D JR NZ,WT2 LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,WT_ERR_MASK CALL WD2793_WAIT ;Wait until chip is ready JP NZ,FORMAT_FDC_ERR1 LD A,(IX+TRK) INC A CP A,(IX+NTRKS) JP Z,SIDE_A_DONE LD (IX+TRK),A LD A,STEPIN OUT (WD2793_CMD),A ;No need to check, always works CALL LED_TRK_SEC ;Update LED HEX display (if present) CALL QUICK_CSTS ;Any keyboard character will stop display JP Z,MORE_FORMAT_FDC_DISK ;Do the next track CALL ZCI ;Flush character LD DE,CONTINUE_MSG CALL PRINT_STRING CALL ZCI CP A,ESC JP Z,FINISH_FORMAT CALL CRLF JP MORE_FORMAT_FDC_DISK ;Do the next Track SIDE_A_DONE: LD A,(IX+SIDES_NUMBER) ;Is it a double sided disk CP A,2 JP NZ,FINISH_FORMAT ;No then we are done LD A,(IX+DRIVE_ADDR) BIT 2,A JP Z,FINISH_FORMAT ;We have done with side B as well LD DE,FORMATING_B_SIDE ;'Formating B side$' CALL PRINT_STRING CALL CORE_RESTORE ;Lower head/Start Motor. Must be done here/early. Absolutly critical the disk XOR A,A ;IBM 3750 Format disk. For other formats use the DC_DIAG.Z80 Program. LD A,(IX+TRK) LD A,1 LD (IX+SEC),A CALL SET_B_SIDE CALL LED_TRK_SEC ;Update LED HEX display JP MORE_FORMAT_FDC_DISK ;<<<<<<<<<<<<<<<<<<<<< WRITE_TRACK - SIDE B >>>>>>>>>>>>>>>>>>>>> FINISH_FORMAT: CALL DELAY_30uS CALL CORE_RESTORE XOR A,A LD (IX+TRK),A LD A,1 LD (IX+SEC),A CALL SET_A_SIDE CALL LED_TRK_SEC ;Update LED HEX display XOR A,A JP FLOPPY_LOOP FORMAT_FDC_ERR1: LD DE,FORMAT_ERR1_MSG ;'Format Error detected for Track $' CALL PRINT_STRING LD A,(IX+TRK) CALL HHEXOUT XOR A,A DEC A JP FLOPPY_LOOP ;----------------------------- BUILD TRACK IMAGE IN RAM ------------------------------------------------ ; Note for debugging you can examine the track image in the RAM of the ; ZFDC board using the Monitor command. It starts at RAM_BASE + 1000H ,(9000H). ; BUILD_TRACK: EXX ;The sector numbers on a track (usually 1,2,3,4... LD A,(IX+SEC_SKEW_TABLE) ;Set [HL'] to point to the table containing the order of LD l,A LD A,(IX+SEC_SKEW_TABLE+1) LD h,A EXX ;Sector skew table in [hl'] LD HL,SECTOR_BUFFER ;This will be at FBUFFER where track is built in RAM BIT 4,(IX+DRIVE_ADDR) ;Will build a different track image for SD or DD disks JP Z,DD_TRACKS ;Need a seperate Track Image for DD tracks SD_TRACKS: CALL SD_TRK_HEADER ;Drop in header and Index mark BEFORE first sector EXX LD A,(hl) ;sector# in D, usually 1 at the start EXX LD D,A LD E,(IX+NSCTRS) ;Total Sectors/side DEC E ;Because sec/track +1 in table NEXT_SEC: CALL SD_BUILD_SEC ;<<< Build a sector >>>>> EXX INC hl ;point to next sector number in sec skew table LD A,(hl) EXX LD D,A ;store sector # in D DEC E JR NZ,NEXT_SEC ;All sectors are in RAM CALL SD_TRK_END ;Now need to flush out track to end RET ; ; ; Build in memory at SECTOR_BUFFER a complete Single Density Track. ; SD_TRK_HEADER: ;Lay down the track header before the 1st sector LD A,(IX+GAP_FILL_CHAR) ;Do not alter [D]= Sec# or [E]= Sec/side LD B,(IX+HEADR) ;Header has 40 (FF's) CALL DROP ;drop it at the end of the growing image (Count in B) XOR A,A ;Now 6 0's LD B,6 CALL DROP LD A,0FCH ;Index ID mark LD (HL),A ;drop into image INC HL LD A,(IX+GAP_FILL_CHAR) ;Now 26 (FF's) LD B,26 ;Header has the count of fill characters required CALL DROP ;drop it at the end of the growing image (Count in B) RET ;return with [HL] pointing to first sector byte SD_BUILD_SEC: ;Lay down a sector at current [HL]. Do not alter [D] or [E] XOR A,A LD B,(IX+GAP1) ;<---- (eg. 6,0's for IMB 3740, 8") CALL DROP LD A,0FEH ;Sector ID Address mark LD (HL),A ;drop it in the growing image INC HL LD A,(IX+TRK) ;Drop in the track # LD (HL),A INC HL LD A,(IX+DRIVE_ADDR) ;Current Side#, 1 for A side, 0 for B side BIT 2,A LD A,00 JR Z,FORM_A_SIDE LD A,01 FORM_A_SIDE: LD (HL),A ;0 here for A side, 1 for B side INC HL LD (HL),D ;Drop in sector # INC HL LD A,(IX+SEC_SIZE_FLAG) ;128=0,256=1,512=2, 1024=3 LD (HL),A ;drop in sector length byte INC HL LD A,0F7H ;Dropping in a 0F7 will cause the 179x LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP2) ;<---- (eg. 11,FF's for IMB 3740, 8") CALL DROP XOR A,A LD B,(IX+GAP1) ;<---- (eg. 6,0's for IMB 3740, 8") CALL DROP LD A,0FBH ;Data address mark for 1791/5 LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,D CP A,1 ;If first sector then store data marker JR NZ,SDATA_FIELD LD (S_DATA_MARK),HL ;Pointer to start of sector data area SDATA_FIELD: ;Now write in the sector data field itself LD A,(IX+SEC_SIZE_FLAG) ;128,256,512 or 1024 byte sector size LD B,128 LD C,1 ;1 loop of 128 bytes in WR_DATA_FIELD below OR A,A JR Z,SD_DATA_FIELD ;Do 128 byte write (B=128) LD B,0 ;Need 256 bytes for the rest of possible sectors LD C,1 ;One loop CP A,1 JR Z,SD_DATA_FIELD ;Do 256 byte write LD C,2 ;2 loops of 256 bytes in WRITE_DATA_FIELD CP A,2 JR Z,SD_DATA_FIELD ;Do 512 byte read LD C,4 ;(must be 3) so 1024 byte sector SD_DATA_FIELD: LD A,(IX+DATA_FILL_CHAR) ;get the sector fill character (usually E5) SDF0: CALL DROP DEC C JR NZ,SDF0 ;Decrese [C] to 0 LD A,D CP A,1 ;If first sector then store image mark JR NZ,NOT_FIRST LD (E_DATA_MARK),HL ;For first sector will diaplay data late NOT_FIRST: LD A,0F7H ;Dropping in a 0F7 will cause the 1791/5 LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP3) ;<---- (eg. 27,FF's for IMB 3740, 8") CALL DROP LD A,D CP A,1 ;If first sector then store image mark RET NZ LD (E_SEC_MARK),HL ;For first sector will diaplay data later RET ; SD_TRK_END LD (S_GAP4_MARK),HL ;Mark beginning of end of track field (GAP4) LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP4) ;<---- (eg 247,FF's for IMB 3740, 8") LD C,(IX+GAP4R) ;Times to repeat DROP SD_TRK1:CALL DROP DEC C JR NZ,SD_TRK1 LD (E_GAP4_MARK),HL ;Mark end of Track RET ; ; DROP: LD (HL),A ;DATA block loader INC HL ;B= byte count,HL pointer DJNZ DROP ;A = value to drop into image. Count in B RET DD_TRACKS: CALL DD_TRK_HEADER ;Drop in header and Index mark BEFORE first sector EXX LD A,(hl) ;sector# in D, usually 1 at the start EXX LD D,A LD E,(IX+NSCTRS) ;Total Sectors/side DEC E ;Because sec/track +1 in table DD_NEXT_SEC: CALL DD_BUILD_SEC ;<<< Build a sector >>>>> EXX INC hl ;point to next sector number in sec skew table LD A,(hl) EXX LD D,A ;store sector # in D DEC E JR NZ,DD_NEXT_SEC ;All sectors are in RAM CALL DD_TRK_END ;Now need to flush out track to end RET ; ; Build in memory at SECTOR_BUFFER a complete Double Density Track. ; DD_TRK_HEADER: ;Lay down the track header before the 1st sector LD A,(IX+GAP_FILL_CHAR) ;Do not alter [D]= Sec# or [E]= Sec/side LD B,(IX+HEADR) ;Header has 80 (4E's) CALL DROP ;drop it at the end of the growing image (Count in B) XOR A,A ;Now 12 0's LD B,12 CALL DROP LD A,0F6H ;3 of F6's LD B,3 CALL DROP LD A,0FCH ;Index ID mark (FC) LD (HL),A ;drop into image INC HL LD A,(IX+GAP_FILL_CHAR) ;Now 50 (4Es) LD B,50 ;Header has the count of fill characters required CALL DROP ;drop it at the end of the growing image (Count in B) RET ;return with [HL] pointing to first sector byte DD_BUILD_SEC: ;Lay down a sector at current [HL]. Do not alter [D] or [E] XOR A,A LD B,(IX+GAP1) ;<---- (eg. 12,0's for IBM System 34 Format) CALL DROP LD A,0F5H ;Special DD bytes LD B,3 CALL DROP LD A,0FEH ;Sector ID Address mark LD (HL),A ;drop it in the growing image INC HL LD A,(IX+TRK) ;Drop in the track # LD (HL),A INC HL LD A,(IX+DRIVE_ADDR) ;Side#, 0 for A side, 1 for B side BIT 2,A LD A,0 JR Z,DFORM_A_SIDE LD A,01 ;1 for side B DFORM_A_SIDE: LD (HL),A ;0 here for A side, 1 for B side INC HL LD (HL),D ;Drop in sector # INC HL LD A,(IX+SEC_SIZE_FLAG) ;128=0,256=1,512=2, 1024=3 LD (HL),A ;drop in sector length byte INC HL LD A,0F7H ;Dropping in a 0F7 will cause the 179x LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP2) ;<----(eg 22,4E's for IBM System 34 Format) CALL DROP XOR A,A LD B,(IX+GAP1) ;<---- (eg 8,0's for IBM System 34 Format) CALL DROP LD A,0F5H ;Special DD bytes LD B,3 CALL DROP LD A,0FBH ;Data address mark for 1791/5 LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,D ;Get sec # CP A,1 ;If first sector then store data marker JR NZ,DDATA_FIELD LD (S_DATA_MARK),HL ;Pointer to start of sector data area DDATA_FIELD: ;Now write in the sector data field itself LD A,(IX+SEC_SIZE_FLAG) ;128,256,512 or 1024 byte sector size LD B,128 LD C,1 ;1 loop of 128 bytes in WR_DATA_FIELD below OR A,A JR Z,DD_DATA_FIELD ;Do 128 byte write (B=128) LD B,0 ;Need 256 bytes for the rest of possible sectors LD C,1 ;One loop CP A,1 JR Z,DD_DATA_FIELD ;Do 256 byte write LD C,2 ;2 loops of 256 bytes in WRITE_DATA_FIELD CP A,2 JR Z,DD_DATA_FIELD ;Do 512 byte read <--- FOR 1.44MG Disks LD C,4 ;(must be 3) so 1024 byte sector DD_DATA_FIELD: LD A,(IX+DATA_FILL_CHAR) ;get the sector fill character (Usually E5. Note MSDOS disks are different) DDF0: CALL DROP DEC C JR NZ,DDF0 ;Decrease [C] to 0 LD A,D ;Get back sec # CP A,1 ;If first sector then store image mark JR NZ,DNOT_FIRST LD (E_DATA_MARK),HL ;For first sector will diaplay data late DNOT_FIRST: LD A,0F7H ;Dropping in a 0F7 will cause the 1791/5 LD (HL),A ;to write in the 2 CRC bytes INC HL LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP3) ;<---- (54,4E's for IBM System 34 Format) CALL DROP LD A,D CP A,1 ;If first sector then store image mark RET NZ LD (E_SEC_MARK),HL ;For first sector will diaplay data later RET ; DD_TRK_END LD (S_GAP4_MARK),HL ;Mark beginning of end of track field (GAP4) LD A,(IX+GAP_FILL_CHAR) LD B,(IX+GAP4) ;<---- (eg 598 4E's for IBM System 34 Format) LD C,(IX+GAP4R) ;Times to repeat DROP DD_TRK1:CALL DROP DEC C JR NZ,DD_TRK1 LD (E_GAP4_MARK),HL ;Mark end of Double density Track RET ;=================== FDC Support Routines ================================================= FDC_INITILIZE: ;Initilize a new floppy disk LD DE,WAIT_FOR_FLOPPY_MSG ;'One moment please while the Floppy Disk is activated' CALL PRINT_STRING FDC_INITILIZE_NO_WAIT: CALL CORE_RESTORE ;Always start from track 0 XOR A ;Pulse Reset WD2793 pin 19 OUT (WD2793_RESET),A INC A OUT (WD2793_RESET),A XOR A OUT (WD2793_RESET),A CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct XOR A,A OUT (WD2793_TRACK),A LD (IX+TRK),A CALL SET_A_SIDE CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct LD A,1 OUT (WD2793_SECTOR),A LD (IX+SEC),A ;Not really necessary CALL DELAY_30uS RET ; This routine reads info from disk (via WD2793 chip) to RAM on the FPGA_DC board (@DMA) CORE_FLOPPY_READ_SECTOR: PUSH HL PUSH DE PUSH BC LD A,SEEK_RETRY_MAX ;Put Seek retry count here LD (@SEEK_RT),A LD A,SECTOR_RETRY_MAX ;Put Sector read retry count here LD (@SEC_RT),A FLOPPY_READ_SECTOR: LD A,(@CURRENT_TRACK) CALL CORE_SEEK ;<<<< Seek to Track in [A] (if required) JP Z,CORRECT_RD_TRACK RESEEK2: LD A,(@SEEK_RT) DEC A LD (@SEEK_RT),A ;Save for next time JP Z,BAD_RD_SEC_SEEK CALL CORE_RESTORE ;Core Head Restore routine JP Z,FLOPPY_READ_SECTOR ;Retry seek after this restore command JP RESEEK2 ;Try 3 times ;----- ACTUAL FLOPPY SECTOR READ ROUTINES ---- CORRECT_RD_TRACK: LD A,(IX+TRK) OUT (WD2793_TRACK),A LD A,(IX+SIDES_NUMBER) ;One or two sided disk CP A,1 JR Z,RD_ONE_SIDE_DISK ;<<< ONE SIDED DISK, 1 side only, then take care of it LD A,(IX+SEC) ;Get requested sector number CP A,(IX+NSCTRS) ;Are we within range of the first side JR NC,RD_SECOND_SIDE_SECTORS RD_ONE_SIDE_DISK: OR A JR Z,BAD_RD_SEC_NUMBER OUT (WD2793_SECTOR),A CALL SET_A_SIDE ;Always A side JR FLOPPY_READ RD_SECOND_SIDE_SECTORS: LD C,(IX+NSCTRS) ;Subtract one sides worth of sectors DEC C ;Because NSCTRS +Sec/track+1 SUB A,C CP A,(IX+NSCTRS) ;Are we still within range JR NC,BAD_RD_SEC_NUMBER OR A JR Z,BAD_RD_SEC_NUMBER OUT (WD2793_SECTOR),A CALL SET_B_SIDE ;Set B side JR FLOPPY_READ FLOPPY_READ: LD E,(IX+SEC_SIZE_BYTES) ;Bytes/sector LD D,(IX+SEC_SIZE_BYTES+1) ld HL,(@DMA) ;Point to buffer LD C,WD2793_DATA ;Bytes in B, Data port in [C] below LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,RDCMD93 ;Send the Read Sector CMD OUT (WD2793_CMD),A WD_SEC_RD: IN A,(WD2793_STATUS) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,WD_SEC_RD ;if no data IN A,(C) LD [HL],A ;For some reason INI does NOT work. Seems too fast! INC HL DEC DE LD A,E OR A,D JR NZ,WD_SEC_RD LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,ID_ERR_MASK CALL WD2793_WAIT ;Wait 30uS, then check status and return POP BC POP DE POP HL RET BAD_RD_SEC_SEEK: LD DE,RD_SEC_SEEK_ERR ;Read sector seek error CALL PRINT_STRING LD A,(@CURRENT_TRACK) CALL HHEXOUT POP BC POP DE POP HL XOR A DEC A RET ;Ret NZ, 0FFH error BAD_RD_SEC_NUMBER: LD DE,SEC_RD_RANGE_MSG ;Sector range error CALL PRINT_STRING POP BC POP DE POP HL XOR A DEC A RET ;Ret NZ, 0FFH error ; This routine writes info to the disk (via WD2793 chip) from RAM on the FPGA_DC board (@DMA) CORE_FLOPPY_WRITE_SECTOR: PUSH HL PUSH DE PUSH BC LD A,SEEK_RETRY_MAX ;Put Seek retry count here LD (@SEEK_RT),A LD A,SECTOR_RETRY_MAX ;Put Sector read retry count here LD (@SEC_RT),A FLOPPY_WRITE_SECTOR: LD A,(@CURRENT_TRACK) CALL CORE_SEEK ;<<<< Seek to Track in[A] (if required) JP Z,CORRECT_WR_TRACK RESEEK3: LD A,(@SEEK_RT) DEC A LD (@SEEK_RT),A ;Save for next time JP Z,BAD_WR_SEC_SEEK CALL CORE_RESTORE ;Core Head Restore routine JP Z,FLOPPY_WRITE_SECTOR ;Retry seek after this restore command JP RESEEK3 ;Try 3 times ;----- ACTUAL FLOPPY SECTOR WRITE ROUTINE ---- CORRECT_WR_TRACK: LD A,(IX+TRK) OUT (WD2793_TRACK),A LD A,(IX+SIDES_NUMBER) ;One or two sided disk CP A,1 JR Z,WR_ONE_SIDE_DISK ;<<< ONE SIDED DISK, 1 side only, then take care of it LD A,(IX+SEC) ;Get requested sector number CP A,(IX+NSCTRS) ;Are we within range of the first side JR NC,WR_SECOND_SIDE_SECTORS WR_ONE_SIDE_DISK: OR A JR Z,BAD_WR_SEC_NUMBER OUT (WD2793_SECTOR),A CALL SET_A_SIDE ;Always A side JR FLOPPY_WRITE WR_SECOND_SIDE_SECTORS: LD C,(IX+NSCTRS) ;Subtract one sides worth of sectors DEC C ;Because NSCTRS +Sec/track+1 SUB A,C CP A,(IX+NSCTRS) ;Are we still within range JR NC,BAD_WR_SEC_NUMBER OR A JR Z,BAD_WR_SEC_NUMBER OUT (WD2793_SECTOR),A CALL SET_B_SIDE ;Set B side JR FLOPPY_WRITE FLOPPY_WRITE: LD E,(IX+SEC_SIZE_BYTES) ;Bytes/sector LD D,(IX+SEC_SIZE_BYTES+1) LD HL,(@DMA) ;Will store data here LD C,WD2793_DATA ;Bytes in B, Data port in [C] below LD A,80H OUT (CPU_SPEED_PORT),A ;Run with HIGH speed CPU (40 MHz) LD (@CURRENT_CPU_SPEED),A LD A,WRCMD93 ;Send the Write Sector CMD OUT (WD2793_CMD),A WD_SEC_WR: IN A,(WD2793_STATUS) ;Get FDC status RRA ;C = Busy RRA ;C = DRQ JR NC,WD_SEC_WR ;if no data LD A,[HL] ;For some reason INI does NOT work. Seems too fast! OUT (C),A INC HL DEC DE LD A,E OR A,D JR NZ,WD_SEC_WR LD A,0 OUT (CPU_SPEED_PORT),A ;Back to LOW speed CPU (30 MHz) LD (@CURRENT_CPU_SPEED),A LD D,ID_ERR_MASK CALL WD2793_WAIT ;Wait 30uS, then check status and return POP BC POP DE POP HL RET BAD_WR_SEC_SEEK: LD DE,WR_SEC_SEEK_ERR ;Write sector seek error CALL PRINT_STRING LD A,(@CURRENT_TRACK) CALL HHEXOUT POP BC POP DE POP HL XOR A DEC A RET ;Ret NZ, 0FFH error BAD_WR_SEC_NUMBER: LD DE,SEC_WR_RANGE_MSG ;Sector range error CALL PRINT_STRING POP BC POP DE POP HL XOR A DEC A RET ;Ret NZ, 0FFH error ; WD2793_WAIT, just waits for the WD2793 chip to go not busy, or it times out. ; IF, not busy it then checks the WD2793 status register against the error mask bits in [D] ; Returns Z if no errors, NZ & 0FFH in [A] if Timeout, else Masked status error bits in [A]. WD2793_WAIT: PUSH BC CALL DELAY_30uS ;We need to delay 30uS, previous command may have been an output to CMD port LD BC,0 ;been an output to CMD port LD E,STATUS_DELAY ;Timeout, (about 5 seconds) WAIT_1: IN A,(WD2793_STATUS) ;Wait until chip is not busy BIT 0,A ;Check Busy bit JR Z,CHECK_STATUS ;Z flag set if OK DJNZ WAIT_1 ;Try for ~0.5 seconds DEC B ;Reset B to 0FFH DEC C JR NZ,WAIT_1 DEC B ;Reset B to 0FFH DEC C DEC E JR NZ,WAIT_1 XOR A DEC A POP BC RET ;Return NZ flag set if timeout, 0FFH in [A] CHECK_STATUS: AND A,D ;Check against mask error bits for this command (I,II or III) POP BC RET FDC_RDY: IN A,(WD2793_STATUS) ;Wait until chip is not busy BIT 7,A ;Check Drive Not Ready bit JR NZ,FDC_RDY ;Z flag set if OK ; Very short Software time delay ~30 uSec @ 6MHZ ;(No registers changed) ----- MEASURE ??? DELAY_30uS: PUSH AF LD A,40H WAIT_5: DEC A JR NZ,WAIT_5 POP AF RET ;Get a random Track & Sector number and put in IX+TRK and IX+SEC RANDOM_TRK_SEC: LD B,(IX+TRK) ;Get current track number CALL RANDOM ;Get next random number in A RANDOM1:CP A,(IX+NTRKS) ;Trim to size JR NC,RANDOM_TRK_SEC LD (IX+TRK),A ;Store new track number RAND_SEC: CALL RANDOM AND 1FH ;Will never be more than this LD B,(IX+NSCTRS) ;Trim to size DEC B ;Becaurse it's sectors+1 CP A,B JR NC,RAND_SEC LD (IX+SEC),A ;Store new sector number LD A,(IX+TRK) ;Return with new track number RET ; Simple random number generator. Return number in [A] RANDOM: LD A,R ;Seed will be differentd each time LD B,A ADD A,A ADD A,A ADD A,B RR A ADD A,7 RET SET_FLOPPY_TRK_SEC: ;Write the logical block address to the drive's registers ;Note we do not need to set the upper nibble of the LBA ;It will always be 0 for these small drives LD A,(IX+TRK) ;Get Requested Track OUT (WD2793_TRACK),A ;Send Track request to WD2793 chip CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct LD A,(IX+SEC) ;Get Requested Sector OUT (WD2793_SECTOR),A ;Send Sector request to WD2793 chip CALL DELAY_30uS ;Seems to be required otherewise next, set track#, is not correct RET ;------------------------------------------------------------------------------------------------------------ ;----------------------------------------------------------------------------------------------------------- ;------------------------------------ SUPPORT ROUTINES ------------------------------------------------------- ;------------------------------------------------------------------------------------------------------------ ;------------------------------------------------------------------------------------------------------------ ;------------------------------------------------------------------------------------------------------------ ;----------------------------------------------------------------------------------------------------------- MOVE_DISK_TABLES: LD E,0 LD BC,500H LD HL,@DRIVE_1_TABLE ;Clear the drives data storage area for easy debug viewing later RAM_CLEAR: LD (HL),E INC HL DEC BC LD A,C OR A,B JR NZ,RAM_CLEAR LD DE,@DRIVE_0_TABLE ;----- Unassigned Drive ---- LD HL,NO_DRIVE_0 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_1_TABLE LD DE,@DRIVE_1_TABLE ;----- IDE DRIVE 1 ---- LD HL,IDE_DRIVE_1 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_1_TABLE IN A,(IOBYTE) AND A,00000110B ;Check if special format sec/track CP A,00000110B ;xxxxx10xB = 3F sectors/track JR Z,NO_SPECIAL_1 ;xxxxx01xB = 3C sectors/track CP A,00000100B ;xxxxx11xB = FF sectors/track JR NZ,SPECIAL_2 LD A,3CH LD IX,@DRIVE_1_TABLE LD (IX+NSCTRS),A JR NO_SPECIAL_1 SPECIAL_2: LD A,3FH LD IX,@DRIVE_1_TABLE LD (IX+NSCTRS),A NO_SPECIAL_1: LD DE,@DRIVE_2_TABLE ;----- IDE DRIVE 2---- LD HL,IDE_DRIVE_2 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_2_TABLE IN A,(IOBYTE) AND A,00000110B ;Check if special format sec/track CP A,00000110B ;xxxxx10xB = 3F sectors/track JR Z,NO_SPECIAL_4 ;xxxxx01xB = 3C sectors/track CP A,00000100B ;xxxxx11xB = FF sectors/track JR NZ,SPECIAL_3 LD A,3CH LD IX,@DRIVE_2_TABLE LD (IX+NSCTRS),A JR NO_SPECIAL_4 SPECIAL_3: LD A,3FH LD IX,@DRIVE_2_TABLE LD (IX+NSCTRS),A NO_SPECIAL_4: LD DE,@DRIVE_3_TABLE ;-----FLDRIVE 3 ---- LD HL,FL_DRIVE_3 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_3_TABLE LD DE,@DRIVE_4_TABLE ;----- FL DRIVE 4 ---- LD HL,FL_DRIVE_4 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_4_TABLE LD DE,@DRIVE_5_TABLE ;----- FL DRIVE 5 ---- LD HL,FL_DRIVE_5 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_5_TABLE LD DE,@DRIVE_6_TABLE ;----- FL DRIVE 6 ---- LD HL,FL_DRIVE_6 LD BC,80H ;Assume table (without Skew Table), is less than this. LDIR ;Block move table to RAM at @DRIVE_6_TABLE LD DE,DISK_TABLES_MOVED_MSG ;Disk tables moved CALL PRINT_STRING LD HL,@DRIVE_1_TABLE ;Default to IDE Drive A CALL PRINT_HL LD DE,H_MSG CALL PRINT_STRING RET ; ; ; ;----------------------------------------------------------------------------------------------------------------- DRIVE_ID: call IDEwaitnotbusy ;Do the IDEntify drive command, and return with the buffer ;filled with info about the drive ret c ;If Busy return NZ ld d,COMMANDid ld e,REGcommand call IDEwr8D ;issue the command call IDEwaitdrq ;Wait for Busy=0, DRQ=1 jp c,SHOW_IDE_errors ld b,0 ;256 words ld hl,ID_BUFFER ;Store data here call MoreRD16 ;Get 256 words of data from REGdata port to [HL] ret ; ; ; ;----------------------------------------------------------------------------------------------------------------- SHOW_DMA_TRK_SEC: ;Display current DMA, track,sector & head position LD DE,msgDMA ;Show current DMA Address CALL PRINT_STRING ld a,(@DMA+1) ;High DMA byte call HEXOUT ld a,(@DMA) ;Low DMA byte call HEXOUT LD DE,msgDMA2 ;'H' CALL PRINT_STRING LD DE,Drive_L1 ;'Drive ' CALL PRINT_STRING LD C,(IX+DRIVE_ASCII) ;+Drive Letter CALL ZCO LD DE,Drive_L2 ;': ' CALL PRINT_STRING ld de,msgCPMTRK ;Display in CPM format call PRINT_STRING ;---- CPM FORMAT ---- ld a,(IX+TRK) LD C,A ;Store it call HEXOUT ;Low Track byte ld de,msgCPMSEC call PRINT_STRING ;SEC = (16 bits) ld a,(IX+SEC) ;Low sec LD C,A ;Save it call HEXOUT LD A,(IX+DISK_TYPE) CP A,CFCARD JR Z,TRK_SEC_DONE ld de,msgSIDE call PRINT_STRING ;'SIDE ' LD A,(IX+DRIVE_ADDR) BIT 2,A JR Z,SHOW_B LD C,'A' CALl ZCO JR OVER_SHOW_B SHOW_B: LD C,'B' CALl ZCO OVER_SHOW_B: ld de,WD2793_TRACK_MSG ;' WD2793 TRK =$' call PRINT_STRING IN A,(WD2793_TRACK) ;Get Track # in data register CALL HEXOUT ld de,WD2793_SECTOR_MSG ;'SEC =$' call PRINT_STRING IN A,(WD2793_SECTOR) ;Get Sector # in data register CALL HEXOUT ld de,WD2793_H_MSG ;'H)' call PRINT_STRING RET TRK_SEC_DONE: ld de,msgCPMSEC2 ;'H' call PRINT_STRING RET ; ; ; ;----------------------------------------------------------------------------------------------------------------- SHORT_DMA_TRK_SEC: ;Display just track,sector LD DE,msgDMA ;Show current DMA Address CALL PRINT_STRING ld a,(@DMA+1) ;High DMA byte call HEXOUT ld a,(@DMA) ;Low DMA byte call HEXOUT LD DE,msgDMA2 ;'H' CALL PRINT_STRING ld de,msgCPMTRK ;Display in LBA format call PRINT_STRING ;---- CPM FORMAT ---- ld a,(IX+TRK) ;Low TRK byte call HEXOUT ld de,msgCPMSEC call PRINT_STRING ;SEC = (16 bits) ld a,(IX+SEC) ;Low sec call HEXOUT ret ; ; ; LED_DRIVE: ;Display current drive on HEX display LD A,(IX+DRIVE_LETTER) OUT (HEX_DISPLAY_PORT),A ;Drive data to HEX display lines LD A,01H OUT (DRIVE_HEX_DISPLAY),A RET ;Latch date into 74LS374 on board ; ; ; LED_TRK_SEC: ;Display current track,sector ld a,(IX+TRK) LD C,A ;Store it RRCA RRCA RRCA RRCA ;High nibble now at lower 4 bits AND A,0FH ;Select Low Nibble + High track select for U17 OR 80H OUT (HEX_DISPLAY_PORT),A LD A,C AND A,0FH ;Select Low Nibble + Low track select for U18 OR 40H OUT (HEX_DISPLAY_PORT),A ld a,(IX+SEC) ;Low sec LD C,A ;Save it RRCA RRCA RRCA RRCA ;High nibble now at lower 4 bits AND A,0FH ;Select Low Nibble + High sector select for U3 OR 20H OUT (HEX_DISPLAY_PORT),A LD A,C AND A,0FH ;Select Low Nibble + Low sector select for U19 OR 10H OUT (HEX_DISPLAY_PORT),A RET ; ; ; ;----------------------------------------------------------------------------------------------------------------- SHOW_NEW_TRACK_SEC: ;Display only current Track +CR (no LF) ld de,msgCPMTRK ;Display in CPM format call PRINT_STRING ;---- CPM FORMAT ---- ld a,(IX+TRK) call HEXOUT ;Low Track byte ld de,msgCPMSEC call PRINT_STRING ;SEC = (16 bits) ld a,(IX+SEC) ;Low sec call HEXOUT LD C,CR CALL ZCO RET ; ; ; ;----------------------------------------------------------------------------------------------------------------- GET_NEW_TRK_SEC: ;Get CPM style Track# & Sector# data PUSH BC ;Save BC XOR A ;Note for now assume 256 X 256 Tracks X Sectors for CPM/MSDOS LD (IX+TRK+1),A ;For future upgrade LD (IX+SEC+1),A CALL GETHEX_NO_ECHO ;TRACK LOW, get 2 HEX digits JR NC,SKIP_CR CP A,CR ;If CR here then no data update JP Z,NO_UPDATE JP BAD_FORMAT_ENTRY SKIP_CR: LD C,(IX+NTRKS) ;Must be less than or equal to NSCTRS-1 DEC C CP A,C JR Z,TRK_L_SIZE_OK JP NC,BAD_LBA_ENTRY TRK_L_SIZE_OK: LD (IX+TRK),A LD (@CURRENT_TRACK),A CALL ZCI ;Format is XX,XX CP A,',' JR NZ,BAD_FORMAT_ENTRY LD C,',' CALL ZCO call GETHEX_NO_ECHO ;SECTOR, get 2 more HEX digits JP C,NO_UPDATE1 CP A,(IX+NSCTRS) ;Must be less than NSCTRS+1 JR Z,BAD_LBA_ENTRY JP NC,BAD_LBA_ENTRY CP A,(IX+FIRST_SEC) ;Number of first sector, 0 for IDE, 1 for floppies JP C,BAD_LBA_ENTRY SEC_SIZE_OK: ld (IX+SEC),a xor A ;Ret Z if data is OK POP BC ret BAD_LBA_ENTRY: LD DE,BAD_LBA_ENTRY_MSG CALL PRINT_STRING XOR A ;Ret Z if error or no new data DEC A POP BC RET BAD_FORMAT_ENTRY: LD DE,FORMAT_ERR_MSG CALL PRINT_STRING XOR A ;Ret Z if error or no new data DEC A POP BC RET NO_UPDATE: ld a,(IX+TRK) ;Show current Low TRK byte call HEXOUT LD C,',' CALL ZCO ld a,(IX+SEC) ;Show current Low sec call HEXOUT xor A ;Ret Z if no new data is OK NO_UPDATE1: POP BC ret ; ; ; ;----------------------------------------------------------------------------------------------------------------- SEC_BUMP: ;Generalized routine (IDE & Floppy Drives) to point to the next sector/track PUSH BC LD C,(IX+NSCTRS) ;Sec/track+1 ld A,(IX+SEC) ;<<< NOTE CURRENTLY LIMITED TO 0FFH SECTORS/TRACK CP A,0FFH ;For SD/CF cards >>> JR Z,SEC_BUMP_TRK inc A ;For Floppies (Sectors numbered 1,2,3... CP A,C JR Z,SEC_BUMP_TRK ld (IX+SEC),A POP BC XOR A DEC A RET ;RET NZ if just a sector increase SEC_BUMP_TRK: ld A,(IX+FIRST_SEC) ;Back to first sector ld (IX+SEC),A LD A,(IX+TRK) INC A POP BC CP A,0H RET Z ;Ret Z if end of CF or disk Card CP A,(IX+NTRKS) RET Z ;Ret Z if end of Floppy track+1 ld (IX+TRK),A ;Note currently no check for TRK overflow XOR A DEC A SCF ;Set carry flag in a new track RET ; ; ; ;----------------------------------------------------------------------------------------------------------------- PREV_SEC: ;Generalized routine (IDE & SD Drives) to point to the previous sec/trk ld A,(IX+SEC) ;<<< NOTE CURRENTLY LIMITED TO 0FFH SECTORS/TRACK >>> CP A,(IX+FIRST_SEC) ;Is it the first sector JR Z,ZERO_SEC DEC A ld (IX+SEC),A ;Not 0 so update sector store XOR A DEC A RET ;RET NZ if just a sector decrease ZERO_SEC: LD A,(IX+NSCTRS) ;Last sector on previous track +1 DEC A ld (IX+SEC),A ;Highest sector/track (previous track) LD A,(IX+TRK) ;Drop to previous track OR A JR Z,PREV_SEC_DONE ;Cannot go below Track zero DEC A ld (IX+TRK),A ;Note currently no check for TRK overflow XOR A DEC A SCF ;Set carry flag in a new track RET ;Returning if Floppy (numbered 1,2,3...) PREV_SEC_DONE: XOR A DEC A RET ;RET NZ if just a sector decrease ; ; ; ;----------------------------------------------------------------------------------------------------------------- GETHEX: call GETCMD ;Get a character from keyboard & ECHO cp ESC jp z,HEXABORT cp '/' ;check 0-9, A-F jp c,HEXABORT cp 'F'+1 jp nc,HEXABORT call ASBIN ;Convert to binary rlca ;Shift to high nibble rlca rlca rlca ld b,A ;Store it call GETCMD ;Get 2nd character from keyboard & ECHO cp ESC jp z,HEXABORT cp '/' ;check 0-9, A-F jp c,HEXABORT cp 'F'+1 jp nc,HEXABORT call ASBIN ;Convert to binary or B ;add in the first digit or A ;To return NC ret HEXABORT: scf ;Set Carry flag ret ; ; ; ;----------------------------------------------------------------------------------------------------------------- GETHEX_NO_ECHO: call ZCI ;GET A CHARACTER, convert to UC, ECHO it call UPPER cp ESC jp z,HEXABORT_NO_ECHO cp '/' ;check 0-9, A-F jp c,HEXABORT_NO_ECHO cp 'F'+1 jp nc,HEXABORT_NO_ECHO PUSH BC PUSH AF LD C,A CALL ZCO POP AF POP BC call ASBIN ;Convert to binary rlca ;Shift to high nibble rlca rlca rlca ld b,A ;Store it call ZCI ;GET second CHARACTER, convert to UC, ECHO it call UPPER cp ESC jp z,HEXABORT_NO_ECHO cp '/' ;check 0-9, A-F jp c,HEXABORT_NO_ECHO cp 'F'+1 jp nc,HEXABORT_NO_ECHO PUSH BC PUSH AF LD C,A CALL ZCO POP AF POP BC call ASBIN ;Convert to binary or B ;add in the first digit or A ;To return NC ret HEXABORT_NO_ECHO: scf ;Set Carry flag ret ; ; ; ;----------------------------------------------------------------------------------------------------------------- MENU_SHOW_IDE: LD DE,GET_CF_PARMS_MSG ;Show current IDE card paramaters CALL PRINT_STRING CALL CRLF CALL CRLF call DRIVE_ID ;<<<<< Get the drive ID info. If there is no drive, abort jp z,ID_OK1 ld de,ID_ERROR call PRINT_STRING CALL CRLF call SHOW_IDE_errors jp IDE_LOOP ;otherewise sector #'s are off by one! ID_OK1: ;Print the drive's model number etc from ID_BUFFER ld de, msgmdl call PRINT_STRING ld hl,ID_BUFFER + 54 ld b,10 ;character count in words call printname ;Print [HL], [B] X 2 characters call CRLF ;print the drive's serial number ld de, msgsn call PRINT_STRING ld hl,ID_BUFFER + 20 ld b, 5 ;Character count in words call printname call CRLF ;Print the drive's firmware revision string ld de, msgrev call PRINT_STRING ld hl,ID_BUFFER + 46 ld b, 2 call printname ;Character count in words call CRLF ;Tell user whether or not LBA is supported LD DE,msgLBAsup1 ;First part of LBA support message CALL PRINT_STRING LD A,(ID_BUFFER+98+1) ;Bits 15-10 reserved, 9 LBA, 8 DMA AND A,02H JR NZ,ID$PRINT3 ;LBA is supported LD DE,msgLBAnot ;LBA is not supported CALL PRINT_STRING ID$PRINT3: LD DE,msgLBAsup2 CALL PRINT_STRING ld de, msgcy call PRINT_STRING ld hl,ID_BUFFER + 2 ;print the drive's cylinder, head, and sector specs call printparm ld de,msghd call PRINT_STRING ld hl,ID_BUFFER + 6 call printparm ld de, msgsc call PRINT_STRING ld hl,ID_BUFFER + 12 call printparm call CRLF ;Default position will be first block ld A,0 ld (IX+SEC),A ;Default to Track 0, Sec 0 ld (IX+TRK),A ld hl,SECTOR_BUFFER ;Set DMA address to normal default buffer ld (@DMA),hl call IDE_init ;For some reason this need to be here after getting the drive ID. jp IDE_LOOP ;otherewise sector #'s are off by one! ; ; ; ;----------------------------------------------------------------------------------------------------------------- DISP_SEC_BUFFER: ;Display IDE RAM Buffer at @DMA address push af ;Save everything push bc push de push hl LD HL,(@DMA) ;Point to current sector buffer pointer LD D,(IX+SEC_SIZE_BYTES+1) ;Get sector size LD E,(IX+SEC_SIZE_BYTES) LD (@BYTE_COUNT),DE DISP_BUFFER2: CALL LFADR DF175A: CALL BLANK LD A,(HL) CALL LBYTE INC HL LD A,L AND 0FH JR NZ,DF175A LD C,TAB ;INSERT A TAB BETWEEN DATA CALL ZCO LD B,4H ;ALSO 1 SPACE DTA11: LD C,SPACE CALL ZCO DJNZ DTA11 LD B,16 ;NOW PRINT ASCII (16 CHARACTERS) LD DE,0010H SBC HL,DE ;Back up 16 positions DT11: LD A,(HL) AND 7FH CP ' ' ;FILTER OUT CONTROL CHARACTERS' JR NC,DT33 DT22: LD A,'.' DT33: CP 07CH JR NC,DT22 LD C,A ;SET UP TO SEND CALL ZCO INC HL LD DE,(@BYTE_COUNT) ;Have we done all bytes in sector DEC DE LD A,E OR A,D JR Z,DISP_SEC_DONE LD (@BYTE_COUNT),DE DJNZ DT11 ;REPEAT FOR WHOLE LINE JR DISP_BUFFER2 DISP_SEC_DONE: CALL CRLF pop hl ;Get back origional registers pop de pop bc pop af ret ; ; ; ;----------------------------------------------------------------------------------------------------------------- SHOW_IDE_errors: call CRLF ld e,REGstatus ;Get status in status register call IDErd8D ld a,D and 1H JP NZ,MORE_ERROR SHOW_STATUS_BITS ;Must be drive not ready or fault PUSH AF ;Save for return below and 80H jp z,NOT7 ld de,DRIVE_BUSY ;Drive Busy (bit 7) stuck high. Status = call PRINT_STRING jp DONEERR NOT7: and 40H jp nz,NOT6 ld de,DRIVE_NOT_READY ;Drive Not Ready (bit 6) stuck low. Status = call PRINT_STRING jp DONEERR NOT6: and 20H jp nz,NOT5 ld de,DRIVE_WR_FAULT ;Drive write fault. Status = call PRINT_STRING jp DONEERR NOT5 LD DE,UNKNOWN_ERROR call PRINT_STRING jp DONEERR MORE_ERROR: ;Get here if bit 0 of the status register indicted a problem ld e,REGerr ;Get error code in REGerr call IDErd8D ld a,D PUSH AF ;Save for BITS display below and 10H jp z,NOTE4 ld de,SEC_NOT_FOUND call PRINT_STRING jp DONEERR NOTE4: and 80H jp z,NOTE7 ld de,BAD_BLOCK call PRINT_STRING jp DONEERR NOTE7: and 40H jp z,NOTE6 ld de,UNRECOVER_ERR call PRINT_STRING jp DONEERR NOTE6: and 4H jp z,NOTE2 ld de,INVALID_CMD call PRINT_STRING jp DONEERR NOTE2: and 2H jp z,NOTE1 ld de,TRK0_ERR call PRINT_STRING jp DONEERR NOTE1: ld de,UNKNOWN_ERROR call PRINT_STRING jp DONEERR DONEERR:POP AF ;Saved from above call PRINT_BITS call CRLF XOR A DEC A ;Ret NZ scf ; Set Carry flag to also indicate an error ret ;-----------------------------------BASIC ROUTINES ------------------------------------------------------------------------ ; Print a 16 bit number in RAM located @ [HL] ; (Note Special Low Byte First. Used only for Drive ID) printparm: inc hl ;Index to high byte first ld a,(hl) call HEXOUT dec HL ;Now low byte ld a,(hl) call HEXOUT ret printname: ;Special Send text for Drive ID inc hl ;Text is low byte then high byte format ld c,(hl) call ZCO dec HL ld c,(hl) call ZCO inc hl inc hl DEC B jp nz,printname ret GETCMD: call ZCI ;GET A CHARACTER, convert to UC, ECHO it call UPPER cp ESC ret z ;Don't echo an ESC push af ;Save it push bc ld c,A call ZCO ;Echo it pop bc pop af ;get it back ret ;Convert LC to UC UPPER: cp 'a' ;must be >= lowercase a ret c ; else go back... cp 'z'+1 ;must be <= lowercase z ret nc ; else go back... sub 'a'-'A' ;subtract lowercase bias ret ;ASCII TO BINARY CONVERSION ROUTINE ASBIN: sub 30H cp 0AH ret m sub 07H ret ; ; ; QUICK_DRIVE_NAME: PUSH IX POP IY ;IX->IY QUICK_DRIVE1: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string RET Z LD C,A CALL ZCO INC IY JP QUICK_DRIVE1 SHOW_DRIVE_NAME: ;Show the drive name and track info for the current drive PUSH IY PUSH IX ;Save origional pointer PUSH BC PUSH IX POP IY ;IX-> to IY LD A,(IY+DRIVE_NUMBER) ;Which drive CP A,1 JR Z,SHOW_DR1 ;IDE A: CP A,2 JR Z,SHOW_DR2 ;IDE B: CP A,3 JP Z,SHOW_DR3 ;FLOPPY C: CP A,4 JP Z,SHOW_DR4 ;FLOPPY D: CP A,5 JP Z,SHOW_DR5 ;FLOPPY E: CP A,6 JP Z,SHOW_DR6 ;FLOPPY F: JP NO_CARD SHOW_DR1: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string JR Z,DR1_SECTORS LD C,A CALL ZCO INC IY JP SHOW_DR1 DR1_SECTORS: LD A,(IX+INITILIZED) ;See if un-initilized/not present OR A JP Z,NO_CARD NO_CF1_CARD_MSG: LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid CALL HHEXOUT JP SHOW_DONE SHOW_DR2: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string JR Z,DR2_SECTORS LD C,A CALL ZCO INC IY JP SHOW_DR2 DR2_SECTORS: LD A,(IX+INITILIZED) ;See if un-initilized/not present OR A JP Z,NO_CARD CARD_2_OK: LD A,(IX+NTRKS) CALL HHEXOUT LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid CALL HHEXOUT JP SHOW_DONE SHOW_DR3: LD A,(IY+TITLE) ;FLOPPY C: OR A,A ;Repeat up to end of string JR Z,DR3_CARD LD C,A CALL ZCO INC IY JP SHOW_DR3 DR3_CARD: LD A,(IX+NTRKS) CALL HHEXOUT XOR A ;Flag as having a card LD (IX+NO_DRIVE_PRESENT),A LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JP SHOW_DONE SHOW_DR4: ;FLOPPY D: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string JR Z,DR4_CARD LD C,A CALL ZCO INC IY JP SHOW_DR4 DR4_CARD: LD A,(IX+NTRKS) CALL HHEXOUT XOR A ;Flag as having a card LD (IX+NO_DRIVE_PRESENT),A LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JP SHOW_DONE SHOW_DR5: ;FLOPPY E: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string JR Z,DR5_CARD LD C,A CALL ZCO INC IY JP SHOW_DR5 DR5_CARD: LD A,(IX+NTRKS) CALL HHEXOUT XOR A ;Flag as having a card LD (IX+NO_DRIVE_PRESENT),A LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JP SHOW_DONE SHOW_DR6: ;FLOPPY F: LD A,(IY+TITLE) OR A,A ;Repeat up to end of string JR Z,DR6_CARD LD C,A CALL ZCO INC IY JP SHOW_DR6 DR6_CARD: LD A,(IX+NTRKS) CALL HHEXOUT XOR A ;Flag as having a card LD (IX+NO_DRIVE_PRESENT),A LD DE,SEC_TRK_MSG CALL PRINT_STRING LD A,(IX+NSCTRS) ;Note at this stage IY is invalid DEC A ;Table for floppies is Sec/track+1 CALL HHEXOUT JP SHOW_DONE NO_CARD: LD DE,NO_DISK_MSG CALL PRINT_STRING XOR A ;Flag as NOT having a disk DEC A SHOW_DONE: POP BC POP IX POP IY RET ; ; ;================================================================================================ ; ; IDE Drive BIOS Routines written in a format that can be used directly with CPM3 ; ;================================================================================================ ; IDE_init: ;Initilze the 8255 and drive, send a hard reset to the drive PUSH BC ;Save used registers PUSH DE ld a,READcfg8255 ;Config 8255 chip (10010010B), read mode on return out (IDEportCtrl),a ;Config 8255 chip, READ mode ;Hard reset to the disk drive ;For some reason some CF cards need to the RESET line ;pulsed very carefully. You may need to play around ld a,IDErstline ;with the pulse length. Symptoms are: incorrect data comming out (IDEportC),a ;back from a sector read (often due to the wrong sector being read) ;I have a (negative)pulse of 2.7uSec. (10Mz Z80, two IO wait states). ;IDERSTLINE = 80H ld b,IDE_RESET_DELAY ;080H Which seem to work for the 5 different CF cards I have. ResetDelay: ;Use a NEC 82C55A-2 Chip. Others seem to have problems DEC B jp nz,ResetDelay ;Delay (reset pulse width) xor A out (IDEportC),a ;No IDE control lines asserted (just bit 7 of port C) call DELAY$SHORT CALL IDEwaitnotbusy ;Wait for drive JP C,WaitInitErr ld d,11100000b ;Data for IDE SDH reg (512bytes, LBA mode,single drive,head 0000) ;For Trk,Sec,head (non LBA) use 10100000 ;Note. Cannot get LBA mode to work with an old Seagate Medalist 6531 drive. ;have to use the non-LBA mode. (Common for old hard disks). ld e,REGshd ;00001110,(0EH) for CS0,A2,A1, call IDEwr8D ;Write byte to select the MASTER device ld b,IDE_SPEED_DELAY ; (2) May need to adjust delay time for "real" hard disks WaitInit: ld e,REGstatus ;Get status after initialization call IDErd8D ;Check Status (info in [D]) ld a,D and 80H jp nz,WaitInitL ;Need a longer wait... POP DE POP BC RET ;Will Ret z if all OK WaitInitL: ld a,IDE_SPEED_DELAY call DELAY$LONG ;Long delay, drive has to get up to speed DEC B jp nz,WaitInit call SHOW_IDE_errors ;Ret with NZ flag set if error (probably no drive) XOR A DEC A POP DE POP BC RET ;Ret NZ if errors ;;;;; WaitInitErr: LD DE,IDE_INIT_ERR_MSG ;IDE/CF Card Initilize ERROR CALL PRINT_STRING XOR A DEC A POP DE POP BC RET ;Ret NZ if errors DELAY$LONG: ld (@DELAYStore),a push bc ld bc,00FFH ;May need to adjust delay time to allow a cold drive to DELAY2: ld a,(@DELAYStore) ;get up to speed, However if no CF card/Drive is present the DELAY1: DEC A ;syetem will be stuck here waiting for too long. Keep as short as jp nz,DELAY1 ;possible for CF cards. dec bc ld a,C or B jp nz,DELAY2 pop bc ret DELAY$SHORT: ld a,40 ;DELAY ~32 MS (DOES NOT SEEM TO BE CRITICAL) DELAY3: ld b,0 M0: DJNZ M0 DEC A JP NZ,DELAY3 RET ;------------------------------------------------------------------------------------------------------- ;Read a sector from local RAM, specified by the 3 bytes in LBA ;Z on success, NZ call error routine if problem LOCAL_IDE_READ_SECTOR: call SET_IDE_TRK_SEC ;Tell which sector we want to read from. ;Note: Translate first in case of an error otherwise we ;will get stuck on bad sector call IDEwaitnotbusy ;make sure drive is ready jp c,SHOW_IDE_errors ;Returned with NZ set if error ld d,COMMANDread ld e,REGcommand call IDEwr8D ;Send sec read command to drive. call IDEwaitdrq ;wait until it's got the data jp c,SHOW_IDE_errors LD HL,(@DMA) ;<<<<< DMA address of local buffer >>>>> ld b,0 ;Read 512 bytes to [HL] (256X2 bytes) MoreRD16: ld a,REGdata ;REG register address out (IDEportC),a or IDErdline ;08H+40H, Pulse RD line out (IDEportC),a in a,(IDEportA) ;Read the lower byte first (Note very early versions had high byte then low byte ld (hl),A ;this made sector data incompatible with other controllers!). inc hl in a,(IDEportB) ;THEN read the upper byte ld (hl),A inc hl ld a,REGdata ;De-assert RD line out (IDEportC),a DJNZ MoreRD16 ld e,REGstatus call IDErd8D ld a,D and 1H call nz,SHOW_IDE_errors ;If error display status ret ;Return Z if no errors ;------------------------------------------------------------------------------------------------------- ;Read a sector for S100 Bus, specified by the 3 bytes in LBA ;Z on success, NZ call error routine if problem ;Note no local RAM is involved S100_IDE_READ_SECTOR: call SET_IDE_TRK_SEC ;Tell which sector we want to read from. ;Note: Translate first in case of an error otherwise we call IDEwaitnotbusy ;make sure drive is ready jp c,SHOW_IDE_errors ;Returned with NZ set if error ld d,COMMANDread ld e,REGcommand call IDEwr8D ;Send sec read command to drive. call IDEwaitdrq ;wait until it's got the data jp c,SHOW_IDE_errors LD B,0 ;-------------------------------------- S100_RD16: ld a,REGdata ;REG register address out (IDEportC),a or IDErdline ;08H+40H, Pulse RD line out (IDEportC),a in a,(IDEportA) ;Read the lower byte first (Note very early versions had high byte then low byte LD C,A CALL SEND_FPGA_TO_S100 ;Send data in [C] back to S100 in a,(IDEportB) ;THEN read the upper byte LD C,A CALL SEND_FPGA_TO_S100 ;Send data in [C] back to S100 ld a,REGdata ;De-assert RD line out (IDEportC),a DJNZ S100_RD16 ;-------------------------------------- ld e,REGstatus call IDErd8D ld a,D and 1H call nz,SHOW_IDE_errors ;If error display status ret ;------------------------------------------------------------------------------------------------------- S100_FDC_READ_SECTOR: LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA LD A,3 LD (@SEC$RETRY$COUNT),A FDC_READ_RETRY: CALL FDC_RDY CALL CORE_FLOPPY_READ_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA JR Z,S100_RD_SEC_FLOPPY_OK ;Z means the sector read was OK LD C,'.' CALL ZCO LD A,(@SEC$RETRY$COUNT) DEC A LD (@SEC$RETRY$COUNT),A JR NZ,FDC_READ_RETRY ld de,S100_RD_ERR_MSG ;Sector read error. Track= call PRINT_STRING LD A,(IX+TRK) CALL HEXOUT ld de,S100_RD_1_ERR_MSG ;H Sector= call PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT XOR A,A DEC A RET S100_RD_SEC_FLOPPY_OK: XOR A,A ; CALL LED_TRK_SEC ;Update LED HEX display RET ;------------------------------------------------------------------------------------------------------- ;Write a sector to local RAM, specified by the 3 bytes in LBA ;Z on success, NZ to error routine if problem LOCAL_IDE_WRITE_SECTOR: call SET_IDE_TRK_SEC ;Tell which sector we want to read from. ;Note: Translate first in case of an error otherwise we ;will get stuck on bad sector call IDEwaitnotbusy ;make sure drive is ready jp c,SHOW_IDE_errors ld d,COMMANDwrite ld e,REGcommand call IDEwr8D ;tell drive to write a sector call IDEwaitdrq ;wait unit it wants the data jp c,SHOW_IDE_errors ld a,WRITEcfg8255 out (IDEportCtrl),a ld hl,(@DMA) ;<<<<<< DMA address of local buffer >>>>>>>> ld b,0 ;256X2 bytes WRSEC1: ld a,(hl) inc hl out (IDEportA),a ;Write the lower byte first (Note early versions had high byte then low byte ld a,(hl) ;this made sector data incompatible with other controllers). inc hl out (IDEportB),a ;THEN High byte on B ld a,REGdata push af out (IDEportC),a ;Send write command or IDEwrline ;Send WR pulse out (IDEportC),a pop af out (IDEportC),a DJNZ WRSEC1 ld a,READcfg8255 ;Set 8255 back to default read mode out (IDEportCtrl),a ld e,REGstatus call IDErd8D ld a,D and 1H call nz,SHOW_IDE_errors ;If error display status ret ;------------------------------------------------------------------------------------------------ ;Write a sector from S100 bus port, specified by the 3 bytes in LBA ;Z on success, NZ to error routine if problem S100_IDE_WRITE_SECTOR: call SET_IDE_TRK_SEC ;Tell which sector we want to read from. ;Note: Translate first in case of an error otherwise we ;will get stuck on bad sector call IDEwaitnotbusy ;make sure drive is ready jp c,SHOW_IDE_errors ld d,COMMANDwrite ld e,REGcommand call IDEwr8D ;tell drive to write a sector call IDEwaitdrq ;wait unit it wants the data jp c,SHOW_IDE_errors ld a,WRITEcfg8255 out (IDEportCtrl),a ld b,0 ;256X2 bytes ;------------------------------------ S100_WR16: CALL GET_S100_TO_FPGA ;Get Source Sector data byte out (IDEportA),a ;Write the lower byte first CALL GET_S100_TO_FPGA ;Get Source Sector data byte out (IDEportB),a ;THEN High byte on B ld a,REGdata push af out (IDEportC),a ;Send write command or IDEwrline ;Send WR pulse out (IDEportC),a pop af out (IDEportC),a DJNZ S100_WR16 ;---------------------------------- ld a,READcfg8255 ;Set 8255 back to default read mode out (IDEportCtrl),a ld e,REGstatus call IDErd8D ld a,D and 1H call nz,SHOW_IDE_errors ;If error display status ret ; ; ; ;------------------------------------------------------------------------------------------------ ;Write a sector from S100 bus port, specified by the 3 bytes in LBA ;Z on success, NZ to error routine if problem S100_FDC_WRITE_SECTOR: LD A,(IX+TRK) LD (@CURRENT_TRACK),A LD A,(IX+SEC) LD (@CURRENT_SECTOR),A LD HL,SECTOR_BUFFER ld (@DMA),HL ;Point to buffer LD (@DMA_STORE),HL ;Start Buffer DMA LD A,3 LD (@SEC$RETRY$COUNT),A FDC_WRITE_RETRY: CALL FDC_RDY CALL CORE_FLOPPY_WRITE_SECTOR ;<<<<<<<<< Read actual Floppy sector at @DMA JR Z,S100_WR_SEC_FLOPPY_OK ;Z means the sector read was OK LD C,'.' CALL ZCO LD A,(@SEC$RETRY$COUNT) DEC A LD (@SEC$RETRY$COUNT),A JR NZ,FDC_WRITE_RETRY ld de,S100_WR_ERR_MSG ;Sector write error. Track= call PRINT_STRING LD A,(IX+TRK) CALL HEXOUT ld de,S100_WR_1_ERR_MSG ;H Sector= call PRINT_STRING LD A,(IX+SEC) CALL HHEXOUT XOR A,A DEC A RET S100_WR_SEC_FLOPPY_OK: XOR A,A ; CALL LED_TRK_SEC ;Update LED HEX display RET ; ; ; ;------------------------------------------------------------------------------------------------ ; ; ; SET_IDE_TRK_SEC: ;Write the logical block address to the drive's registers ;Note we do not need to set the upper nibble of the LBA ;It will always be 0 for these small drives ld D,(IX+TRK) ;LBA mode Low sectors go directly ld e,REGcylinderLSB call IDEwr8D ld D,(IX+SEC) ;LBA mode Low sectors go directly ld e,REGsector ;Send info sector # to drive call IDEwr8D ;Note: For drive we will have 0 - MAXSEC sectors only ld d,0 ;Send High TRK# (Always 0) ld e,REGcylinderMSB call IDEwr8D ld d,1 ;For now, one sector at a time ld e,REGseccnt call IDEwr8D XOR A,A ;Ret Z,NC ret IDEwaitnotbusy: ;Is Drive READY ld b,0FFH ld a,0FFH ;Number of loops to allow drive to get up to speed (Real hard disks only) ld (@DELAYStore),a ;May need to adjust for hardware MoreWait: ld e,REGstatus ;wait for RDY bit to be set ;(0FH) call IDErd8D ;<<<<<<<<<<<<<<<<<< READ ld a,D and 11000000B xor 01000000B ;If so 01000000 jp z,DoneNotbusy DEC B jp nz,MoreWait ld a,(@DELAYStore) ;Check timeout delay DEC A ld (@DELAYStore),a jp nz,MoreWait scf ;Set carry to indicate an error ret DoneNotBusy: or A ;Clear carry it indicate no error ret ;Wait for the drive to be ready to transfer data. ;Returns the drive's status in Acc IDEwaitdrq: ld b,0FFH ld a,0FFH ;Delay, must be above 80H for 4MHz Z80. Leave longer for slower drives ld (@DELAYStore),a MoreDRQ: ld e,REGstatus ;wait for DRQ bit to be set call IDErd8D ld a,D and 10001000B cp 00001000B jp z,DoneDRQ DEC B jp nz,MoreDRQ ld a,(@DELAYStore) ;Check timeout delay DEC A ld (@DELAYStore),a jp nz,MoreDRQ scf ;Set carry to indicate error ret DoneDRQ: or A ;Clear carry ret ;------------------------------------------------------------------ ; Low Level 8 bit R/W to the drive controller. These are the routines that talk ; directly to the drive controller registers, via the 8255 chip. ; Note the 16 bit I/O to the drive (which is only for SEC R/W) is done directly ; in the routines IDE_READSECTOR & IDE_WRITESECTOR for speed reasons. ; IDErd8D: ;READ 8 bits from IDE register in [E], return info in [D] ld a,E out (IDEportC),a ;drive address onto control lines or IDErdline ;RD pulse pin (40H) out (IDEportC),a ;assert read pin in a,(IDEportA) ld d,A ;return with data in [D] ld a,E ;<---Ken Robbins suggestion out (IDEportC),a ;de-assert RD pin xor A out (IDEportC),a ;Zero all port C lines ret IDEwr8D: ;WRITE Data in [D] to IDE register in [E] ld a,WRITEcfg8255 ;Set 8255 to write mode out (IDEportCtrl),a ld a,D ;Get data put it in 8255 A port out (IDEportA),a ld a,E ;select IDE register out (IDEportC),a or IDEwrline ;lower WR line out (IDEportC),a ld a,E ;<-- Ken Robbins suggestion, raise WR line out (IDEportC),a ;de-assert RD pin xor A ;Deselect all lines including WR line out (IDEportC),a ld a,READcfg8255 ;Config 8255 chip, read mode on return out (IDEportCtrl),a ret NOT_DONE: LD DE,NOT_DONE_MSG ;Routine not written yet CALL PRINT_STRING RET ;------------------------------------ TIME DATE ROUTINES ------------------------------ TIME_MENU: LD SP,STACK ;Just to be safe, redo stack at 0FFF0H ld de,TIME_MENU_MSG ;List Time menu options call PRINT_STRING TIME_LOOP: LD A,RTC_CS_LOW ;Deselect RTC chip SPI interface (Note HIGH for CS to select chip) OUT (RTC_CS),A ld de,Prompt ;'Please enter a command >' call PRINT_STRING call TI_NO_ECHO ;Simple UC character Input (Note, no fancy checking) cp ESC ;ESC back to main menu jp z,FINISH_TIME cp a,'A' JP Z,ACTIVATE_RTC CP A,'S' JP Z,READ_SECONDS CP A,'W' JP Z,WRITE_RTC_RAM CP A,'M' JP Z,READ_RTC_RAM CP A,'T' JP Z,SET_TIME CP A,'R' JP Z,READ_TIME CP A,'X' JP Z,DISPLAY_RGS JP TIME_MENU_ERROR FINISH_TIME: ; LD (@CURRENT_CPU_SPEED),A ; OUT (CPU_SPEED_PORT),A ;Back to High speed CPU (50MHz) JP INITILIZE TIME_MENU_ERROR: LD DE,MENU_ERR_MSG ;"Menu error" CALL PRINT_STRING JP TIME_MENU ;------------------------------------------------------------------------------------------------- ACTIVATE_RTC: LD HL,MSG0 ; "Activate RTC Chip" CALL RTC_PMSG LD B,RTC_CTL_REG OR 80H ; RTC Register address + Write LD C,00000000B ; ENABLE_OSC, Bit 7 to enable/start the RTC chip (0=start, 1=stop) CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) JP TIME_MENU ;------------------------------------------------------------------------------------------------- READ_SECONDS: LD HL,MSG1 ; "1 = Read Seconds Register from RTC Chip" CALL RTC_PMSG LD B,RTC_SECONDS ; Seconds Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] PUSH AF ; Save it LD HL,MSG2 ; "RTC Seconds Register = " CALL RTC_PMSG POP AF CALL HEXOUT ; Display Returned SPI PROM Byte CALL CRLF JP TIME_MENU ;------------------------------------------------------------------------------------------------- WRITE_RTC_RAM: LD HL,MSG3 ; "2",CR,LF,Enter RAM location (20H-7FH) " CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR OR A,80H ; Add write bit LD D,A ; RAM Location to D (with Write bit) LD HL,MSG4 ; 'Enter Byte value " CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD E,A ; Save above values in DE LD C,A ; Value to write to RAM LD B,D ; Get the above saved address CALL WRITE_RTC_SPI ; <<< Send Write pulse (Address in B, data in C) LD HL,MSG5 ; "Wrote" CALL RTC_PMSG LD A,E CALL HEXOUT LD HL,MSG6 ; " to RAM location CALL RTC_PMSG LD A,D AND A,7FH ; Strip Write bit CALL HEXOUT LD HL,MSG7 ; " in RTC" CALL RTC_PMSG CALL CRLF JP TIME_MENU READ_RTC_RAM: LD HL,MSG8 ; "3 CR,LF,Enter RAM location (20H-7FH) " CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD D,A ; Save RAM Location to D LD B,A ; RAM Location to B CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] PUSH AF ; Save data LD HL,MSG9 ; "RAM location " CALL RTC_PMSG LD A,D CALL HEXOUT LD HL,MSG10 ; " H = " CALL RTC_PMSG POP AF CALL HEXOUT LD HL,MSG11 ; " in RTC" CALL RTC_PMSG CALL CRLF JP TIME_MENU ;------------------------------------------------------------------------------------------------- SET_TIME: LD HL,MSG12 ; "4",CR,LF,'Enter Year (00-99) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@YEAR),A CALL HEXOUT LD B,RTC_YEAR OR 80H ; RTC Register address + Write LD C,A ; DATA CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG13 ; CR,LF,'Enter Month (01-12) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@MONTH),A LD B,RTC_MONTH OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG14 ; CR,LF,'Enter Date (01-31) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@DATE),A LD B,RTC_DATE OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG15 ; CR,LF,'Enter Hours (00-23) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@HOURS),A LD B,RTC_HOURS OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG16 ; CR,LF,'Enter Minutes (00-59) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@MINUTES),A LD B,RTC_MINUTES OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG17 ; CR,LF,'Enter Seconds (00-59) ' CALL RTC_PMSG CALL GETHEX JP C,DATA_ERROR LD (@SECONDS),A LD B,RTC_SECONDS OR 80H ; RTC Register address + Write LD C,A CALL WRITE_RTC_SPI ; <<<< Send Write pulse (Address + DATA) LD HL,MSG18 ; CR,LF,'Entered:- 20' CALL RTC_PMSG LD A,(@YEAR) CALL HEXOUT LD C,'/' CALL ZCO LD A,(@MONTH) CALL HEXOUT LD C,'/' CALL ZCO LD A,(@DATE) CALL HEXOUT LD HL,MSG19 ; ' Time= ' CALL RTC_PMSG LD A,(@HOURS) CALL HEXOUT LD C,'/' CALL ZCO LD A,(@MINUTES) CALL HEXOUT LD C,'/' CALL ZCO LD A,(@SECONDS) CALL HEXOUT CALL CRLF JP TIME_MENU READ_TIME: LD HL,MSG20 ; "5",CR,LF,'Date = ' CALL RTC_PMSG LD B,RTC_YEAR ; Year Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,'/' CALL ZCO LD B,RTC_MONTH ; Month Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,'/' CALL ZCO LD B,RTC_DATE ; Date Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD HL,MSG19 ; ' Time= ' CALL RTC_PMSG LD B,RTC_HOURS ; Hours Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,'/' CALL ZCO LD B,RTC_MINUTES ; Minutes Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,'/' CALL ZCO LD B,RTC_SECONDS ; Seconds Register address + READ CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT CALL CRLF JP TIME_MENU DISPLAY_RGS: LD HL,MSG21 ; "6",CR,LF,'Register Dump:-' CALL RTC_PMSG LD HL,MSG22 ; 'Register (00H - 06H) ' CALL RTC_PMSG LD D,07H ;Count LD B,00H ;Register pointer REGS_1: CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,' ' CALL ZCO INC B DEC D LD A,D OR A,A JP NZ,REGS_1 LD HL,MSG23 ; 'Register (07H - 0EH) ' CALL RTC_PMSG LD D,08H ;Count LD B,09H ;Register pointer REGS_2: CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,' ' CALL ZCO INC B DEC D LD A,D OR A,A JP NZ,REGS_2 LD HL,MSG24 ; 'Register (0FH - 11H) ' CALL RTC_PMSG LD D,03H ;Count LD B,0FH ;Register pointer REGS_3: CALL READ_RTC_SPI ; <<< Send Read pulse (Address, get DATA), return result in [A] CALL HEXOUT LD C,' ' CALL ZCO INC B DEC D LD A,D OR A,A JP NZ,REGS_3 CALL CRLF JP TIME_MENU ;------------------------ RTC SPI CORE ROUTINES --------------------------------------------------------- WRITE_RTC_SPI: ; [C] contains DATA, [B] contains Register address LD A,RTC_CS_HIGH ; Select RTC OUT (RTC_CS),A ; 52H LD A,B ; <<<---- Send address (Low Byte) OUT (RTC_DATA_OUT),A LD A,C ; <<<---- Send data (High Byte) OUT (RTC_ADDRESS),A OUT (RTC_WRITE),A ; (Port 53H) Send Write pulse CALL RTC_DELAY LD A,RTC_CS_LOW ; De-select RTC OUT (RTC_CS),A RET READ_RTC_SPI: LD A,RTC_CS_HIGH ; Select RTC OUT (RTC_CS),A ; 52H LD A,B ; <<<---- Send address (only) OUT (RTC_DATA_OUT),A IN A,(RTC_READ) ; Send Read pulse (Port 6B) CALL RTC_DELAY IN A,(RTC_DATA_IN) ; 51H, <<< Get RTC SPI data returned in [A] PUSH AF CALL RTC_DELAY LD A,RTC_CS_LOW ; De-select RTC OUT (RTC_CS),A POP AF RET ;Return with value in [A] RTC_DELAY: PUSH AF PUSH BC PUSH HL LD HL,080H ;Extra time required for RTC to write multiple data bytes DELAY6: DEC HL ;before Status is valid LD A,H OR A,L JR NZ,DELAY6 POP HL DELAY7: IN A,(RTC_STATUS) ; Wait until busy is low OR A JR NZ,DELAY7 POP BC POP AF RET DATA_ERROR: LD HL,FORMAT_ERR_MSG ; "DATA error" CALL RTC_PMSG JP TIME_MENU ;<<<<<<<<<<<<<<<<<<<<<<<<< SUPPORT ROUTINES >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> RTC_PMSG: PUSH BC ; Only [A] and [HL] is changed RTC_PMSG1: LD A,(HL) ; A ROUTINE TO PRINT OUT A STRING @ [HL] INC HL ; UP TO THE FIRST 0. CP A,'$' JP Z,RTC_PMSG_DONE LD C,A CALL ZCO JP RTC_PMSG1 RTC_PMSG_DONE: POP BC RET ;<<<<<<<<<<<<<<<<<<<<<< MAIN CONSOL I/O ROUTINES >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ZCO: IN A,(USB_STATUS_PORT) ;USB Port for Console OUT AND 00000010B JR NZ,ZCO LD A,C AND 7FH OUT (USB_DATA_PORT),A LD A,C ;Return with char in A RET ;<<<<<<<<<<<<<<<<<<< MAIN CONSOL STATUS ROUTINE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ZCSTS: IN A,(USB_STATUS_PORT) AND 01H JR Z,NO_CSTS ;Zero if nothing XOR A DEC A ;RETURN WITH 0FFH IN [A] IF SOMETHING RET NO_CSTS: XOR A RET ;RETURN WITH 0 IN A IF NOTHING THERE QUICK_CSTS: IN A,(USB_STATUS_PORT) AND 01H RET ;Ret Z if nothing ;<<<<<<<<<<<<<<<<<<<< MAIN CONSOL INPUT ROUTINE >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ZCI: IN A,(USB_STATUS_PORT) ;NEED CONSTAT TO CLEAN UP SHIFT KEYS ETC AND 01H JR Z,ZCI ;Wait until something there IN A,(USB_DATA_PORT) AND 7FH ;Always 7 bits only. RET ;<<<<<<<<<<<<<<<<<<<< MAIN I/O ROUTINES TO SEND/GET DATA TO/FROM S100 BUS PORT S100_DATA_PORT (81H) >>>>>>>>>>>>> GET_S100_STATUS: IN A,(STATUS_BUS_PORT) ;Get S100 Status Port - Bit 7, 1 = data present, 0, no data present AND A,S100_RTS ;80H, Bit 7 RET ;Ret Z if nothing, 80H if data GET_S100_TO_FPGA: IN A,(STATUS_BUS_PORT) ;Get S100 Status Port - Bit 7, 1 = data present, 0, no data present AND A,S100_RTS ;80H, Bit 7 JR Z,GET_S100_TO_FPGA ;Wait until data is available IN A,(DATA_BUS_PORT) ;Return Data in [A], FPGA "hardware" will lower bit 7 of S100 Bus port 30H RET SEND_FPGA_TO_S100: IN A,(STATUS_BUS_PORT) ;Has previous data been read by S100 bus AND A,FPGA_RTS ;01H, Bit 0 JR NZ,SEND_FPGA_TO_S100 LD A,C OUT (DATA_BUS_PORT),A PUSH AF SEND_FPGA1: IN A,(STATUS_BUS_PORT) ;Wait until accepted by S100 system, this will (in hardware) lower bit 0 of status port AND A,FPGA_RTS ;01H, Has bit 0 returned low yet by a S100 bus read JR NZ,SEND_FPGA1 POP AF ;Return with sent character in A RET SET_ERROR_FLAG: LD A,04H ;Indicate to S100 Bus that the FPGA has detected an error with a CMD OUT (SET_ERROR_FLAG_PORT),A RET ;--------------------------------------------------------------------------------------------------- ; LOOKUP TABLES OF DISK PARAMETERS DRIVE_TABLES EQU ($ & 0FF00H) + 100H ; ORG DRIVE_TABLES ; ;IDE/CF and FLOPPY cards currently must be formatted in a PC. ;Sectors per track for CF my Memory drive, Kingston CF 8G. (For CPM format, 0-3CH) ;This translates to LBA format of 1 to 3D sectors, for a total of 61 sectors/track. ;This CF card actully has 3F sectors/track. Will use 0...3C for my CPM3 system because ;my Seagate drive has 3D sectors/track. Don't want different CPM3.SYS files around ;so this program as is will also work with a "real" IDE Seagate 6531 IDE drive as well. ; ; ; IDE_DRIVE_1: DB CFCARD ;0 (0FFH), DISK_TYPE (Default IDE Card/Drive) DB 0FFH ;1 Default Card Present DB IDE_CS_1 ;2 DRIVE_CS, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 1 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 2 ;5 512 Bytes/sec flag DB 0 ;6 Tracks set aside for operating system (eg CPM 2 for floppies) DB 0AH ;7 HEX of Drive letter DB 'A' ;8 ACCII Character for Drive DB 0 ;9 First sector # DW 512 ;10 <------ 512 Bytes/sec DW 00FFH ;12 SECTORS PER TRACK:- (Was 3CH (60)for my on old CPM3 for Kingston CF 8G). (Note. No +1 for cards) DW 00FFH ;14 Max Tracks DW 0000H ;16 TRK, Current Track DW 0000H ;18 SEC, Current Sector DB 0H ;20 Side DB 0 ;21 Formatting (Not used for SD/CF cards) DB 0 ;22 GAP1 "" DB 0 ;23 GAP2 "" DB 0 ;24 GAP3 "" DB 0 ;25 GAP4 "" DB 0 ;26 GAP4R "" DB 0 ;27 GAP fill byte "" DB 0E5H ;28 CPM Sector Data Fill Character DB 0 ;29 Special Flag DB 0000H ;30 Skew Table (Not used for SD/CF cards) DB 0 ;32 Format Number DW 0000H ;33 Track Size DB 0 ;35 Number of (Floppy) disk sides (Not used for SD/CF cards) DB ' IDE/CF/SD Card A: ',0 ;36 ; ; IDE_DRIVE_2: DB CFCARD ;0 (0FFH), DISK_TYPE (Default IDE Card/Drive) DB 0FFH ;1 Default Card Present DB IDE_CS_2 ;2 DRIVE_CS, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 2 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 2 ;5 512 Bytes/sec flag DB 0 ;6 Tracks set aside for operating system (eg CPM 2 for floppies) DB 0BH ;7 HEX of Drive letter DB 'B' ;8 ACCII Character for Drive DB 0 ;9 First sector # DW 512 ;10 <------ 512 Bytes/sec DW 00FFH ;12 SECTORS PER TRACK:- (Was 3CH (60)for my on old CPM3 for Kingston CF 8G).(Note. No +1 for cards) DW 00FFH ;14 Max Tracks DW 0000H ;16 TRK, Current Track DW 0000H ;18 SEC, Current Sector DB 0H ;20 SIDE (Unused) DB 0 ;21 Formatting (Not used for SD/CF cards) DB 0 ;22 GAP1 "" DB 0 ;23 GAP2 "" DB 0 ;24 GAP3 "" DB 0 ;25 GAP4 "" DB 0 ;26 GAP4R "" DB 0 ;27 GAP fill byte "" DB 0E5H ;28 CPM Sector Data Fill Character DB 0 ;29 Special Flag DB 0000H ;30 Skew Table (Not used for SD/CF cards) DB 0 ;32 Format Number DW 0000H ;33 Track Size DB 0 ;35 Number of (Floppy) disk sides (Not used for SD/CF cards) DB ' IDE/CF/SD Card B: ',0 ;36 ; ; FL_DRIVE_3: ; (0F0H), 8" SINGLE DENSITY DRIVE VARIABLES (IBM 3740 Format) DB IBM3740 ;0 DISK_TYPE (SDDS) DB 0 ;1 Default 0, No Drive Present DB FL_CS_1 ;2 DRIVE_ADDR, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 3 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 0 ;5 128 Bytes/sec DB 2 ;6 Tracks set aside for operating system (eg CPM = 2) DB 0CH ;7 HEX of Drive letter DB 'C' ;8 ACCII Character for Drive DB 1 ;9 First sector # DW 128 ;10, <------ 128 Bytes/sec DW 26+1 ;12, (1AH) 26+1 SECTORS PER TRACK (Note Floppy sectors are numbered 1,2,...1B (not 0,1,2,3) DW 76 ;14, (4CH) TRACKS PER SIDE (0,1,2,3...76) DW 0000H ;16, TRK, Current Track DW 0000H ;18, SEC, Current Sector DB 0H ;20 SIDE, Current Side DB 40 ;21, HEADER GAP (SD-Systems has 100-27, IBM is 40!) DB 6 ;22, GAP 1 (0's) DB 11 ;23, GAP 2 (FF's) DB 27 ;24, GAP 3 (FF's) DB 247 ;25, GAP 4 (FF's) DB 1 ;26, GAPR (Flag for multiple repeats of GAP4) DB 0FFH ;27, GAP Format fill character DB 0E5H ;28, CPM Sector Data Fill Character DB 0H ;29, No special post format DW SKEW_IBM ;30, Location of this disks sector skew table DB 01H ;32, Each format will have a unique number. For disk to disk copy DW 13F0H ;33, <--- Size in bytes of 1 formatted track (see top of tables) DB 2 ;35, Number of Floppy Disk sides DB ' 8" IBM 3740 Drive C: (128 Bytes/Sec) ',0 ;36 SKEW_IBM: DB 1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH DB 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH ; ; FL_DRIVE_4: ; (0F0H), 8" SINGLE DENSITY DRIVE VARIABLES (IBM 3740 Format) DB IBM3740 ;0 DISK_TYPE (SDSS) DB 0 ;1 Default 0, No Drive Present DB FL_CS_1 ;2 DRIVE_ADDR, actual Drive CS* Line (Use this value if you have only one 8" Floppy Disk) ; DB FL_CS_2 ;2 DRIVE_ADDR, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 4 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 0 ;5 128 Bytes/sec DB 2 ;6 Tracks set aside for operating system (eg CPM = 2) DB 0DH ;7 HEX of Drive letter DB 'D' ;8 ACCII Character for Drive DB 1 ;9 First sector # DW 128 ;10 <------ 128 Bytes/sec DW 26+1 ;12, (1AH) 26+1 SECTORS PER TRACK (Note Floppy sectors are numbered 1,2,...1B (not 0,1,2,3) DW 76 ;14, (4CH) TRACKS PER SIDE (0,1,2,3...76) DW 0000H ;16 TRK, Current Track DW 0000H ;18 SEC, Current Sector DB 0H ;20 SIDE, Current Side DB 40 ;HEADER GAP (SD-Systems has 100-27, IBM is 40!) DB 6 ;GAP 1 (0's) DB 11 ;GAP 2 (FF's) DB 27 ;GAP 3 (FF's) DB 247 ;GAP 4 (FF's) DB 1 ;GAPR (Flag for multiple repeats of GAP4) DB 0FFH ;GAP Format fill character DB 0E5H ;CPM Sector Data Fill Character DB 0H ;No special post format DW SKEW_IBM ;Location of this disks sector skew table DB 01H ;Each format will have a unique number. For disk to disk copy DW 13F0H ;<--- Size in bytes of 1 formatted track (see top of tables) DB 2 ;Number of Floppy Disk sides DB ' 8" IBM 3740 Drive D: (128 Bytes/Sec) ',0 ; ; FL_DRIVE_5: DB IBM34 ;0 (080H), 8" DOUBLE DENSITY DRIVE VARIABLES (IBM 34 Format) DB 0 ;1 Default 0, No Drive Present DB FL_CS_5 ;2 DRIVE_ADDR, actual Drive CS* Line (Use this value if you have only one 8" Floppy Disk) ; DB FL_CS_3 ;2 DRIVE_ADDR, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 5 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 1 ;5 256 Bytes/sec flag DB 2 ;6 Tracks set aside for operating system (eg CPM 2 for floppies) DB 0EH ;7 HEX of Drive letter DB 'E' ;8 ACCII Character for Drive DB 1 ;9 First sector # DW 256 ;10 <------ 256 Bytes/sec DW 26+1 ;12, (1AH) 26+1 SECTORS PER TRACK (Note Floppy sectors are numbered 1,2,...1B (not 0,1,2,3) DW 76 ;14, (4CH) TRACKS PER SIDE (0,1,2,3...76) DW 0000H ;16 TRK, Current Track DW 0000H ;18 SEC, Current Sector DB 0H ;20 SIDE, Current Side DB 80 ;HEADER GAP (SD-Systems has 100-54, IBM is 80!) DB 12 ;GAP 1 (00's) DB 22 ;GAP 2 (4E's) DB 54 ;GAP 3 (4E's) DB 199 ;GAP 4 (4E's) (X3 = 597) DB 3 ;GAPR (Flag for multiple repeats of GAP4) DB 4EH ;GAP Format fill character DB 0E5H ;CPM Sector Data Fill Character DB 0H ;Special formating modifications of disk req (+++ NOT DONE YET) DW SKEW_256 ;Location of this disks sector skew table DB 12H ;Each format will have a unique number. For disk to disk copy DW 2780H ;<--- Size in bytes of 1 formatted track (more than enough!) DB 2 ;Number of Floppy Disk sides DB ' 8" IBM 34 Drive E: (256 Bytes/Sec) ',0 SKEW_256: DB 1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH db 10H,11H,12H,13H,14H,15H,16H,17H,18H,19H,1AH ; ; FL_DRIVE_6: DB IBM144 ;0 (040H), DISK_TYPE (3.5" 1.4MB DDDS Disk) DB 0 ;1 Default 0, No Drive Present DB FL_CS_4 ;2 DRIVE_ADDR, actual Drive CS* Line ; Bits 0,1 are used for drive hardware selection (00=A, 01=B,10=C,11=D) ; Bit 2, 1 if side A is selected, 0 if Side B ; Bit 3, 0 if 8" disk, 1 = 5" disk ; Bit 4, 0 if Single Density, 1 = Double Density ; Bit 5 WD2793 INTRQ 1=ON, 0=OFF ; Bit 6 Write protect flag 0 = ON, 1 = OFF ; Bit 7 Drive Head load (currently unused) DB 6 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 2 ;5 512 Bytes/sec flag DB 0 ;6 Tracks set aside for operating system (eg CPM 2 for floppies) DB 0FH ;7 ASCII of Drive letter DB 'F' ;8 ACCII Character for Drive DB 1 ;9 First sector # DW 512 ;10, <------ 512 Bytes/sec DW 18+1 ;12, (12H+1) SECTORS PER TRACK +1 (Note, always +1 for floppies) DW 80 ;14, (50H) Max Tracks DW 0000H ;16, TRK, Current Track DW 0000H ;18, SEC, Current Sector DB 0H ;20, SIDE, Current Side DB 80 ;HEADER GAP (SD-Systems has 100-54, IBM is 80!) DB 12 ;GAP 1 DB 22 ;GAP 2 DB 84 ;GAP 3 DB 200 ;GAP 4 (4E's) (X3 = 597) DB 1 ;GAPR (Flag for multiple repeats of GAP4) DB 4EH ;GAP Format fill character DB 0E5H ;<--- CPM Sector Data Fill Character (Is 0 for MSDOS) DB 0H ;Special formating modifications of disk req (+++ NOT DONE YET) DW SKEW_144 ;Location of this disks sector skew table DB 15H ;Each format will have a unique number. For disk to disk copy DW 2E90H ;Size in bytes of 1 formatted track (more than enough!) DB 2 ;Number of Floppy Disk sides DB ' 3.5" 1.44MB Drive F: (512 Bytes/Sec) ',0 SKEW_144: DB 1H,2H,3H,4H,5H,6H,7H,8H,9H,0AH,0BH,0CH,0DH,0EH,0FH DB 10H,11H,12H ; NO_DRIVE_0: DB 0H ;0 Disk DISK_TYPE (Default IDE Card/Drive) DB 0H ;1 Default Card Present DB 0 ;2 DRIVE_CS, actual Drive CS* Line DB 0 ;3 Drive NUMBER DB 0 ;4 INITILIZED, unitilized DB 2 ;5 512 Bytes/sec flag DB 0 ;6 Tracks set aside for operating system (eg CPM, 2 for floppies) DB 00H ;7 HEX of Drive # DB '?' ;8 ACCII Character for Drive DB 0 ;9 First sector # DW 512 ;10 <------ 512 Bytes/sec DW 00FFH ;12 SECTORS PER TRACK:- (Was 3CH (60)for my on old CPM3 for Kingston CF 8G). DW 003CH ;14 Max Tracks DW 0000H ;16 TRK, Current Track DW 0000H ;18 SEC, Current Sector DB 0H ;20 Side DB 0 ;21 Formatting (Not used for SD/CF cards) DB 0 ;22 GAP1 "" DB 0 ;23 GAP2 "" DB 0 ;24 GAP3 "" DB 0 ;25 GAP4 "" DB 0 ;26 GAP4R "" DB 0E5H ;27 CPM Sector data fill byte DB 0 ;28 Data Fill Character DB 0 ;29 Special Flag DB 0000H ;30 Skew Table (Not used for SD/CF cards) DB 0 ;32 Format Number DB 0000H ;33 Track Size DB 2 ;35 Number of (Floppy) disk sides (Not used for SD/CF cards) DB ' No Drive yet assigned (512 Bytes/Sec) ',0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> MESAGES <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>< ; SIGNON_MSG DB CR,LF,LF,'FPGA DC BOARD MONITOR -- V2.00 John Monahan, 12/02/2021$' DRIVE_MSG DB CR,LF,LF,'Select Drive Sub-Menu:-$' Z80_MENU_MSG1 DB CR,LF,'FPGA onboard Z80 CPU Monitor Menu. RAM 8000-FFFFH, $' SP_MSG DB 'SP=$' H_MSG DB 'H $' Z80_MENU_MSG2: DB CR,LF DB 'A Memmap B Time/Date Menu D Show RAM E Echo Text' DB CR,LF DB 'F Fill RAM G Goto Location H Data Port I IDE Card Menu' DB CR,LF DB 'J Test RAM K Z80 Menu M Move RAM QI,O Port' DB CR,LF DB 'R Show Ports S Subs RAM T RAM Ascii U Floppy Menu' DB CR,LF DB 'X IDE MODE V Verify RAM Z Top Of RAM (ESC) Main menu' DB CR,LF,LF,'$' ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; MON_CMD_TABLE EQU ($ & 0FF00H) + 100H ; NOTE TABLE MUST BE WITHIN 0-FFH BOUNDRY (CHECK YOUR LISTING) ORG MON_CMD_TABLE ; ;COMMAND BRANCH TABLE DW NOT_DONE ;FLUSH ; "@" DW MEMMAP ; "A" DISPLAY A MAP OF MEMORY DW TIME_MENU ; "B" TIME_DATE SUB-MENU DW BEGIN ; "C" DW DISP ; "D" DISPLAY MEMORY (IN HEX & ASCII) DW ECHO ; "E" ECHO CHAR IN TO CHAR OUT DW FILL ; "F" FILL MEMORY WITH A CONSTANT DW GOTO ; "G" GO TO [ADDRESS] DW S100_DATA_IN ; "H" Display S100 Bus Data In port DW IDE_SETUP ; "I" GOTO IDE MENU DW RAMTEST ; "J" NON-DESTRUCTIVE MEMORY TEST DW KCMD ; "K" DISPLAY THE LIST OF SBC-Z80 COMMANDS DW BEGIN ; "L" DW MOVE ; "M" MOVE BLOCK OF MEMORY (START,FINISH,DESTINATION) DW NOT_DONE ;CPM_BOOT_SD ; "N" Boot up CPM on SD card DW NOT_DONE ; "O" Boot up 8086 (if present) DW NOT_DONE ;CPM_BOOT_IDE ; "P" Boot up CPM on IDE Drive DW QUERY ; "Q" QUERY PORT (IN OR OUT) DW INPORTS ; "R" Read ALL Input Ports DW SUBS ; "S" SUBSTITUTE &/OR EXAMINE MEMORY DW TYPE ; "T" TYPE ASCII PRESENT IN MEMORY DW FL_DRIVES ; "U" GOTO FLOPPY MENU, (start with C drive) DW VERIFY ; "V" COMPARE MEMORY DW NOT_DONE ;INTS_OK ; "W" Allow Interrupts DW NOT_DONE ; "X" DW NOT_DONE ; "Y" DW SIZE ; "Z" FIND HIGHEST R/W RAM ALL_PORTS DB CR,LF,'Active I/O Ports:-$' Invalid_Msg DB CR,LF,BELL,'Invalid Data$' NOT_DONE_MSG DB CR,LF,BELL,'Routine not written!$' RAM_TEST_MSG DB CR,LF,'Enter RAM range (xxxx,yyyy) $' ECHO_MSG DB CR,LF,'Type characters. (^C to abort)$' H_MENU_MSG DB CR,LF,'Continously display S100 Data In Port. Reset to abort.$' NO_STATUS_MESSAGES DB CR,LF,'Note: Bit 0 of SW1 is open, so no runtime status messages!$' ALL_CARDS_MENU DB CR,LF,LF,'Z80 Monitor + IDE/CF cards + Floppy Menu (IOBYTE =$' FLOPPY_ONLY_MENU DB CR,LF,LF,'Z80 Monitor + Floppy Menu (IOBYTE =$' IDE_ONLY_MENU DB CR,LF,LF,'Z80 Monitor + IDE/CF cards Menu (IOBYTE =$' IDE_BRACKET_MENU DB ')',CR,LF,'$' IDE_CARD_MENU_MSG DB CR,LF,LF,'IDE Menu for onboard IDE/CF Card' DB CR,LF DB CR,LF,'R Read Sector W Write Sector N Next Sector P Previous Sector' DB CR,LF,'C Copy Sector V Verify Sector F Fill Sector S Set TRK/SEC' DB CR,LF,'B Show Buffer M Copy Drive A:->B: Y Show Drive Info. (ESC) Main menu' DB CR,LF,LF,'$' FLOPPY_MENU_MSG DB CR,LF,LF,'Menu for onboard FDC Drives' DB CR,LF DB CR,LF,'R Read Sector W Write Sector N Next Sector P Previous Sector' DB CR,LF,'C Copy Sector V Verify Sector F Fill Sector S Set TRK/SEC' DB CR,LF,'G Set Disk Side B Show Buffer M Copy Drive C:->D: U WD2793 Reg. Test' DB CR,LF,'X Restore Head Y Get Track ID Z Track Seek Test E Show WD Registers' DB CR,LF,'H Step Head In D Format Disk T Read Track (ESC) Main menu' DB CR,LF,LF,'$' ID_ERROR DB 'Error reading Drive ID$' msgLBAsup1: DB 'LBA is $' msgLBAnot: DB 'NOT $' msgLBAsup2 DB 'Supported',CR,LF,'$' msgmdl DB 'Model: $' msgsn DB 'S/N: $' msgrev DB 'Rev: $' msgcy DB 'Cylinders: $' msghd DB ', Heads: $' msgsc DB ', Sectors: $' msgDMA: DB 'Buffer=$' msgDMA2: DB 'H. $' Drive_L1 DB 'Drive $' Drive_L2 DB ': $' msgCPMTRK DB 'TRK=$' msgCPMSEC DB 'H, SEC=$' msgCPMSEC2 DB 'H $' GET_CF_PARMS_MSG DB 'Get CF card parameters$' Prompt DB CR,LF,LF,'Enter command >$' msgsure DB CR,LF,'Warning: this will change data on the drive, ' DB 'are you sure? (Y/N)...$' SEC_RD_OK DB CR,LF,'Sector Read OK$' SEC_WR_OK DB CR,LF,'Sector Write OK$' GET_LBA_MSG DB CR,LF,'Enter CPM style TRK,SEC Data (XX,XX +CR):-$' MENU_ERR_MSG DB CR,LF,'Invalid menu option!$' IDE_INIT_OK_MSG DB CR,LF,'IDE/CF Card Initilized OK.$' IDE_INIT_ERR_MSG DB CR,LF,'IDE/CF Card Initilize ERROR.$' IDE_INIT_MSG DB CR,LF,'Initilize IDE/CF Drive ($' DRIVE_INIT_MSG2 DB ':)$' BAD_COPY_RD_MSG DB CR,LF,BELL,'Sector read error copying disk$' BAD_COPY_WR_MSG DB CR,LF,BELL,'Sector write error copying disk$' DRIVE_BUSY DB CR,LF,BELL,'IDE drive Busy Status=$' DRIVE_NOT_READY DB CR,LF,BELL,'IDE Drive Not Ready (bit 6) stuck low. Status =$' DRIVE_WR_FAULT DB CR,LF,BELL,'IDE Drive write fault. Status =$' UNKNOWN_ERROR DB CR,LF,BELL,'Unknown IDE Drive error$' SEC_NOT_FOUND DB CR,LF,BELL,'IDE drive sector not found$' BAD_BLOCK DB CR,LF,BELL,'IDE drive Bad block$' UNRECOVER_ERR DB CR,LF,BELL,'IDE drive Unrecovered error$' INVALID_CMD DB CR,LF,BELL,'IDE drive Invalid command$' TRK0_ERR DB CR,LF,BELL,'IDE drive Track 0 Error$' BAD_LBA_ENTRY_MSG DB CR,LF,BELL,'Sector/Track paramaters outside the range of this drive.$' CONTINUE_MSG DB CR,LF,'Hit any keyboard character to continue. Esc for drive Menu$' FORMAT_ERR_MSG DB CR,LF,BELL,'Incorrect keyboard data format entered.$' NEXT_IDE_SEC_MSG DB CR,LF,'Next IDE Drive Sector$' PREV_IDE_SEC_MSG DB CR,LF,'Previous IDE_Drive Sector$' RD_FROM_msgrd DB CR,LF,'Read from sector:- $' TO_MSG DB ' TO----> $' WR_TO_msgwr DB CR,LF,'Copy to sector:- $' FILL_msgwr DB CR,LF,'Sector Fill was OK$' FILL_BYTE_MSG DB ' ---> Enter Sector Fill Byte (XXH):- $' WITH_MSG DB ' With ----> $' SEC_MATCH_MSG DB CR,LF,'Sectors match.$' SEC_MISMATCH_MSG DB CR,LF,BELL,'Sectors do NOT match starting at position:- $' INIT_MENU_MSG DB 'Initilize Drive.$' LBA_MENU_MSG DB 'Set Drive LBA value.$' RD_SEC_MENU_MSG DB 'Read Track,Sector:-$' WR_SEC_MENU_MSG DB 'Write Track,Sector:-$' COPY_MENU_MSG DB 'Copy Sector:-$' FILL_MENU_MSG DB 'Fill Sector:-$' VERIFY_MENU_MSG DB 'Verify Sector:-$' RAM_MENU_MSG DB 'Display Sector Buffer$' PRIOR_SEC_MSG DB CR,LF,'CMD 37H, Previous Sector$' NEXT_SEC_MSG DB CR,LF,'CMD 36H, Next Sector$' DISK_TABLES_MOVED_MSG DB CR,LF,LF,'Default Disk paramater tables moved to the FPGA local RAM at :- $' DB CR,LF,'Board now active.$' NO_RESPONSE_MSG DB CR,LF,BELL,'Timeout, S100 bus is not responding.$' RESET_CMD_MSG DB CR,LF,'CMD 03H, Reset Z80 command recieved$' SEC_READ_ERROR DB CR,LF,'Sector read Error$' SEC_WRITE_ERROR DB CR,LF,'Sector write Error$' NO_DRIVE_SELECTED_MSG DB CR,LF,'A valid drive has not yet been selected$' COPY_OK_MSG DB CR,LF,'Sector Copied OK$' FILL_OK_MSG DB CR,LF,'Sector Filled OK$' ESC_ABORT_MSG DB CR,LF,'Hit ESC to stop/abort copying$' CODE_INCOMPLETE DB CR,LF,'Code not yet done$' DRIVE_COPY_MSG DB CR,LF,'CMD 3CH, Copy current drive to another drive$' START_COPY_MSG DB CR,LF,'Copying started.....$' SEC_TRK_MSG DB ' Tracks, Sec/Track = $' DR_COPY_MENU_MSG DB CR,LF,'Copy CF Card A: to CF Card B:$' DRIVE_COPY_OK_MSG DB CR,LF,LF,BELL,'Drive copy complete$' DRS_COPY_MENU_MSG DB CR,LF,'Copy the current CF card to another CF Card$' IDE_1_MSG DB CR,LF,'IOBYTE SW1 bit 0 is LOW so this board will update the UART-USB Terminal.$' IDE_2_MSG DB CR,LF,'IOBYTE SW1 bit 0 is HIGH so this board will only provide critical data ' DB CR,LF,'to the UART-USB Terminal.$' IDE_3_MSG DB CR,LF,'IOBYTE SW1 bit 0 is HIGH so this board will update HEX LED Displays and ' DB CR,LF,'only provide critical data to the UART-USB Terminal.$' IDE_4_MSG DB CR,LF,'IOBYTE SW1 bit 0 is LOW so this board will update the HEX LED Displays and ' DB CR,LF,'send info to the UART-USB terminal.$' S100_RD_ERR_MSG DB 'Sector Read Error. Track = $' S100_RD_1_ERR_MSG DB 'H Sector = $' S100_WR_ERR_MSG DB 'Sector Write Error. Track = $' S100_WR_1_ERR_MSG DB 'H Sector = $' POSSIBLE_CPM_MSG DB CR,LF,'Possible CPM3 Boot Loader detected starting on IDE/CF Card A: Track 0, Sector 1',CR,LF,'$' INVALID_DR_MSG DB CR,LF,BELL,'Invalid Drive$' WILL_IDE_A_MSG DB CR,LF,LF,'Will initilize IDE/CF Card A:$' WILL_IDE_B_MSG DB CR,LF,LF,'Will initilize IDE/CF Card B:$' IDE_ERR_1_MSG DB CR,LF,'Error initilizing IDE/CF Card A: (or no card present)$' IDE_ERR_2_MSG DB CR,LF,'Error initilizing IDE/CF Card B: (or no card present)$' DISABLLE_IDE_B_MSG DB CR,LF,'The IDE/CF Card B: is moved offline. (Only the IDE/CF Card A: is active).$' SEC_RD_ERR_SENT DB CR,LF,'A sector READ error notice was sent to the S100 bus$' SEC_WR_ERR_SENT DB CR,LF,'A sector WRITE error notice was sent to the S100 bus$' IDE_READ_NR_MSG DB CR,LF,'Sector read error - IDE Card not ready$' IDE_RD_ERR1_MSG DB CR,LF,'Got error with IDE Read Sector command$' RESET_IDE_RD_MSG DB CR,LF,'Retry reading sector on IDE card$' IDE_WRITE_NR_MSG DB CR,LF,'Sector write error - IDE Card not ready$' IDE_WR_ERR1_MSG DB CR,LF,'Got error with IDE Write Sector command$' RESET_IDE_WR_MSG DB CR,LF,'Retry writing to sector on IDE card$' EXT_IDE0_MODE_MSG DB 'FPGA Set to External IDE/CF Card Ports. (IDE Mode 0).$' EXT_IDE1_MODE_MSG DB 'FPGA Set to Local Z80 IDE/CF Card Ports. (IDE Mode 1).$' EXT_IDE2_MODE_MSG DB 'FPGA Set to External IDE/CF Card Ports + Diagnostic Info (IDE Mode 2).$' CMD_MSG DB CR,LF,'CMD=$' DMA_H_MSG DB ' DMA=$' READ_MSG DB ' Read Sector Track $' WRITE_MSG DB ' WRITE Sector Track $' R_W_SEC_MSG DB ' R/W Sector Track $' SECT_MSG DB 'H Sector $' H_CRLF DB 'H',CR,LF,'$' SET_TRK_SEC_MSG DB ' Set Trk/Sec $' TRK_MSG DB ' Track $' CURRENT_SIDE_MSG DB ' Side $' CF_A_SELECTED_MSG DB 'CF Card A: selected$' CF_B_SELECTED_MSG DB 'CF Card B: selected$' CF_A_NOT_INIT_MSG DB BELL,'CF Card A: is marked as uninitilized$' CF_B_NOT_INIT_MSG DB BELL,'CF Card B: is marked as uninitilized$' FLOPPY_C_SELECTED_MSG DB 'FLOPPY DISK C: selected$' FLOPPY_D_SELECTED_MSG DB 'FLOPPY DISK D: selected$' FLOPPY_E_SELECTED_MSG DB 'FLOPPY DISK E: selected$' FLOPPY_F_SELECTED_MSG DB 'FLOPPY DISK F: selected$' FLOPPY_C_NOT_INIT_MSG DB BELL,'FLOPPY Drive C: is marked as uninitilized$' FLOPPY_D_NOT_INIT_MSG DB BELL,'FLOPPY Drive D: is marked as uninitilized$' FLOPPY_E_NOT_INIT_MSG DB BELL,'FLOPPY Drive E: is marked as uninitilized$' FLOPPY_F_NOT_INIT_MSG DB BELL,'FLOPPY Drive F: is marked as uninitilized$' SELECTED_MSG DB ' Selected$' NMI_MSG DB CR,LF,'NMI Int. $' INT_MSG DB CR,LF,'INT $' FAST_COPY_MSG DB 'Fast Copy of CF Card A:->B: in process. At Track 00H$' FAST_ABORT_MSG DB CR,LF,BELL,'CMD=E0H Fast Copy of CF card A:->B: Aborted.$' FAST_RW_ERROR_MSG DB CR,LF,BELL,'Sector R/W error during fast CF card copying A:->B:$' SET_FDC_HOME_MSG DB ' Restore Disk head to Track 0$' SET_CF_HOME_MSG DB ' Set IDE/CF Card to Track 0$' FORMATING_B_SIDE DB CR,LF,'----------- Formating Side B ------------------$' COPYING_B_SIDE DB CR,LF,'-------------Copying Side B ----------------$' TRACK_DATA DB ' Getting contents of Track: $' FDC_DRIVE_OK_MSG DB CR,LF,'Floppy Disk copy complete$' FDC_FAST_ABORT_MSG DB CR,LF,'Fast Copy of Disk C:->D: Aborted$' FDC_FAST_RW_ERROR_MSG DB CR,LF,'Fast Copy of Disk C:->D: R/W Error$' FDC_FLOPPY_COPY_MSG DB CR,LF,'Will copy all sectors on Floppy disk C: to D:$' COPY_TRACK_MSG DB CR,'Transferring C:->D: Track $' COPY_TRACK2_MSG DB 'H, Sector $' FDC_COPY_MSG DB ' Copy Floppy C:->D:$' SEC_RD_RANGE_MSG DB CR,LF,BELL,'Invalid Read Sector Number. ',CR,LF,'$' SEC_WR_RANGE_MSG DB CR,LF,BELL,'Invalid Write Sector Number. ',CR,LF,'$' RD_SEC_SEEK_ERR DB CR,LF,BELL,'Read sector seek error Track $' WR_SEC_SEEK_ERR DB CR,LF,BELL,'Write sector seek error Track $' TIME_MENU_MSG DB CR,LF,LF,'---------- Time/Date Menu ---------------' DB CR,LF,'A. Activate Maxim DS1305 RTC chip.' DB CR,LF,'S. Read Seconds Register from RTC Chip.' DB CR,LF,'W. Write byte to RAM at a specified location in RTC.' DB CR,LF,'M. Read byte from RAM at a specified location in RTC.' DB CR,LF,'T. Set Time & Date.' DB CR,LF,'R. Read Time & Date.' DB CR,LF,'X. Display all RTC Registers.' DB CR,LF,'ESC Abort to startup program.',CR,LF,'$' Z_MENU_MSG DB CR,LF,'Z = Go to Z80 Menu$' MSG0: DB 'A',CR,LF,'Activating the RTC Chip.',CR,LF,'$' MSG1: DB 'S',CR,LF,'Reading Seconds Register from RTC Chip.$' MSG2: DB CR,LF,'RTC Seconds Register = $' MSG3: DB 'W',CR,LF,'Enter RAM location (20H-7FH) $' MSG4: DB CR,LF,'Enter Byte value $' MSG5: DB CR,LF,'Wrote $' MSG6: DB 'H to RAM location $' MSG7: DB 'H in RTC$' MSG8: DB 'M',CR,LF,'Enter RAM location (20H-7FH) $' MSG9: DB CR,LF,'RAM location $' MSG10: DB 'H = $' MSG11: DB 'H in RTC$' MSG12: DB 'T',CR,LF,'Enter Year (00-99) $' MSG13: DB CR,LF,'Enter Month (01-12) $' MSG14: DB CR,LF,'Enter Date (01-31) $' MSG15: DB CR,LF,'Enter Hours (00-23) $' MSG16: DB CR,LF,'Enter Minutes (00-59) $' MSG17: DB CR,LF,'Enter Seconds (00-59) $' MSG18: DB CR,LF,LF,'Entered:- 20$' MSG19: DB ' Time = $' MSG20: DB 'R',CR,LF,'Date = 20$' MSG21 DB 'X',CR,LF,'Register Dump:-$' MSG22 DB CR,LF,'Registers (00H - 06H) $' MSG23 DB CR,LF,'Registers (07H - 0EH) $' MSG24 DB CR,LF,'Registers (0FH - 11H) $' RTC_CMD_GET_MSG DB 'Read Date/Time $' RTC_CMD_SET_MSG DB 'Set Date/Time $' GET_DATE_TIME_MSG DB ' Date and Time to S100 Bus:- 20$' SET_DATE_TIME_MSG DB ' Date and Time from S100 Bus:- 20$' NO_FLOPPY2_MSG DB CR,LF,LF,'IDE/CF/SD (No Floppies) Version of the board detected.$' NO_FLOPPY_C_MSG DB CR,LF,'No Floppy C: was detected$' NO_FLOPPY_D_MSG DB CR,LF,'No Floppy D: was detected$' NO_FLOPPY_E_MSG DB CR,LF,'No Floppy E: was detected$' NO_FLOPPY_F_MSG DB CR,LF,'No Floppy F: was detected$' NO_FLOPPY_MSG DB ' No Floppy was detected$' WILL_FLOPPY_MSG DB CR,LF,LF,'Will initilize Floppy Disk Drives',CR,LF,'$' INIT_OK_MSG DB ' Initilized OK $' NO_DISK_MSG DB ' No Card or Disk Initilized$' AT_TRK_MSG DB CR,'Currently at Track $' NO_IDE_CIRCUIT_MSG DB CR,LF,'NO IDE/CF Card circuit was detected!$' NO_CIRCUITS_MSG DB CR,LF,BELL,'Serious error, could not detect IDE or FDC circuits. Check board jumpers',CR,LF,'$' NO_FDC_CIRCUIT_MSG DB CR,LF,'NO FDC circuit was detected!$' FDC_RESET_MSG DB 'Will Reset WD2793 Chip and Set TRACK,SECTOR = 0,1$' UPDATE_TRACK_MSG DB 'Will now update continously the WD2793 TRACK,SECTOR Registers.' DB CR,LF,'Hit CR to continue, ESC to abort$' FDC_GOT_MSG DB 'The WD2793 Chip TRACK,SECTOR returned: $' STEP_IN_HUNG DB CR,LF,BELL,'WD2793 Timeout Error after STEP-IN Command$' STEP_IN_ERR DB CR,LF,BELL,'Head Step In Error, DRIVE NOT READY ERROR$' FDC_STEP_MSG DB CR,LF,'Will Step the Floppy disk head in one track$' FDC_RESTORE_MSG DB CR,LF,'Will restore the Floppy disk head to track 0$' RESTORE_HUNG DB CR,LF,BELL,'WD2793 Timeout Error after Restore CMD$' RESTORE_ERR DB CR,LF,BELL,'Restore head to track 0 Error, DRIVE NOT READY ERROR$' STEP_IN_OK_MSG DB CR,LF,'Head Step In Command returned no errors$' RESTORE_OK_MSG DB CR,LF,'Head Restore Command returned no errors$' GET_TRK_ID DB CR,LF,'Get current Track ID$' ID_ERR_HUNG DB ' WD2793 Timeout Error after READ TRACK ID Command.$' ID_ERR1 DB ' Track ID Error, DRIVE NOT READY ERROR.$' ID_ERR2 DB ' Track ID Error, RNF ERROR.$' ID_ERR3 DB ' Track ID Error, LOST DATA ERROR.$' ID_ERR4 DB ' Track ID Error, CRC ERROR.$' ID_BUFFER_CONTENTS DB ' Track ID = $' TRK_ID_MSG DB 'Track ID = $' g FDC_SEEK_MSG DB CR,LF,'Seek to a random Track with verify test. Enter ESC to abort.$' SEEK_TRK_HUNG DB CR,LF,'WD2793 Timeout Error after SEEK with Verify Command$' SEEK_REST_ERR DB CR,LF,'Restore to track 0, DRIVE NOT READY ERROR within SEEK with Verify Command$' AT_TRACK_MSG DB CR,'Current Track = $' SEC_REG_MSG DB ' WD2793 Sector Register = $' RD_SEC_ERR1 DB CR,LF,BELL,'Error Seeking to Track for Sec Read$' SEC_READ_HUNG_ERR DB CR,LF,BELL,'Sector Read Hung Error$' RS_RESTORE_ERR DB CR,LF,BELL,'Restore Error during Sector Read$' SEC_READ_ERR DB CR,LF,BELL,'Floppy Sector Read Error$' WD_STATUS_MSG DB CR,LF,'WD2793 Status Register = $' WD_TRACK_MSG DB CR,LF,'WD2793 Track Register = $' WD_SECTOR_MSG DB CR,LF,'WD2793 Sector Register = $' WD_DATA_MSG DB CR,LF,'WD2793 Data Register = $' msgSIDE DB 'H, Side $' WD2793_TRACK_MSG DB ' (WD2793 TRK=$' WD2793_SECTOR_MSG DB 'H SEC=$' WD2793_H_MSG DB 'H)$' RD_NEXT_SEC DB CR,LF,'Hit any key for next sector. ESC to abort$' WR_RAM_MENU_MSG DB ' From RAM at:- (XXXXH):$' WAIT_FOR_FLOPPY_MSG DB CR,LF,'One moment please while the Floppy Disk is activated$' CONFIG_MSG DB 'Sending to the S100 bus this boards hardware configuration: $' GET_TRK_ID_MSG DB ' Track ID = $' TRK_ID_ERR_MSG DB ' Track ID Error detected.$' STEP_IN_MSG DB ' Step Head IN one Track.$' STEP_OUT_MSG DB ' Step Head OUT one Track.$' FULL_IN_MSG DB ' Head is at Max Track Number.$' FULL_OUT_MSG DB ' Head is at Track 0.$' FORMAT_TRK_MSG DB CR,LF,'Format Track = $' FORMAT_DISK_DONE DB CR,LF,'Format Disk Complete',CR,LF,'$' FORMAT_ERR1_MSG DB CR,LF,BELL,'Format Error detected for Track $' TRACK_DATA_MSG DB ' Sending the complete contents of Track: $' TRACK_DATA_ERR DB CR,LF,BELL,'A Read Track Error was detected.$' TRK_SEC_MENU_MSG DB CR,LF,'Enter New Track,Sector (XX,XX) $' TRK_SEEK_FAIL_MSG DB CR,LF,BELL,'Could not seek to Track: $' SET_SIDE_MSG DB CR,LF,'Enter Side of current Disk (A,B): $' FORMAT_TRK_START_MSG DB CR,LF,'Will format the CURRENT Disk (Side A). Hit any key to halt, ESC to abort$' HIT_SP_MSG DB CR,LF,'Hit Space Bar for more data. ESC to abort.$' FORMAT_DISK1_MSG DB ' Formatting SDSS 8" IBM 3740 Disk$' FORMAT_DISK2_MSG DB ' Formatting SDDS 8" IBM 3740 Disk$' FORMAT_DISK3_MSG DB ' Formatting DDDS 8" System 34 Disk$' FORMAT_DISK4_MSG DB ' Formatting DDDS 3.25" Disk$' FDC_SELECT_PORT_MSG DB ' Unknown disk type format request$' FORMAT_ABORT_MSG DB ' Abort Format requested from S100 Bus.$' FDC_BAD_FORMAT_MSG DB BELL,CR,LF,'Incorrect Disk Format request.$' UNKNOWN_CMD_MSG DB BELL,' Invalid Command$' DO_SIDE_MSG DB ' Set active side of current Floppy disk to Side $' BAD_SIDE_MSG DB CR,LF,BELL,'Invalid active side selected for the current Floppy Disk.$' ESC_TO_ABOPRT_MSG DB CR,LF,'Hit any key to stop, ESC to abort.',CR,LF,'$' READING_TRACK_MSG DB CR,'Reading Sectors on Drive C: Track: $' WRITEING_TRACK_MSG DB CR,'Writing Sectors on Drive D: Track: $' CURENT_A_MSG DB CR,LF,'A = $' CURENT_B_MSG DB CR,LF,'B = $' CURENT_C_MSG DB CR,LF,'C = $' CURENT_D_MSG DB CR,LF,'D = $' CURENT_E_MSG DB CR,LF,'E = $' CURENT_F_MSG DB CR,LF,'F = $' ; -------------------------- RAM usage for IDE Routines (in Z80_MONB.Z80) ----------------------------------------- SECTOR_BUFFER EQU RAM_BASE + 1000H ;(9000H) ID_BUFFER EQU RAM_BASE + 2000H ;(A000H), 512 Bytes for CF-Card paramaters, Sector compares, Floppy ID's @DMA EQU RAM_BASE + 7F00H ;Remember Stack is at Top of RAM ~7FF0H @SECTOR_COUNT EQU RAM_BASE + 7F02H @DELAYSTORE EQU RAM_BASE + 7F04H @BYTE_COUNT EQU RAM_BASE + 7F06H @DMA_STORE EQU RAM_BASE + 7F08H @DMA_DISPLAY EQU RAM_BASE + 7F0AH @TRK_SOURCE EQU RAM_BASE + 7F0CH ;For sec copy @SEC_SOURCE EQU RAM_BASE + 7F0EH @TRK_DEST EQU RAM_BASE + 7F10H @SEC_DEST EQU RAM_BASE + 7F12H @FILL_BYTE EQU RAM_BASE + 7F14H ;For sec fill @TRK_$1 EQU RAM_BASE + 7F16H ;For sec verify @TRK_$2 EQU RAM_BASE + 7F18H @SEC_$1 EQU RAM_BASE + 7F1AH @SEC_$2 EQU RAM_BASE + 7F1CH @DMA_$1 EQU RAM_BASE + 7F1EH @DMA_$2 EQU RAM_BASE + 7F20H @SEC_POSITION EQU RAM_BASE + 7F22H ;For sec verify @DMA_TEMP EQU RAM_BASE + 7F24H ;Temporary HL store for SD Sector R/W's @NMI_ADDRESS EQU RAM_BASE + 7F26H ;Store routine for NMI Interrupt routine @INTR_ADDRESS EQU RAM_BASE + 7F28H ;Store routine for Interrupt routine @CURRENT_SIDE EQU RAM_BASE + 7F2AH ;Current active floppy disk side @COPY_SOURCE_IX EQU RAM_BASE + 7F2CH ;For Drive copy @COPY_DEST_IX EQU RAM_BASE + 7F2EH ;For Drive copy @TRACK_COUNT EQU RAM_BASE + 7F30H @CURRENT_CMD EQU RAM_BASE + 7F34H @BOARD_ACTIVE EQU RAM_BASE + 7F36H @SECTOR_RETRYS EQU RAM_BASE + 7F38H @CURRENT_CPU_SPEED EQU RAM_BASE + 7F3AH @CURRENT_IDE_MODE EQU RAM_BASE + 7F3CH @STOP_FLAG EQU RAM_BASE + 7F3EH @MODE_STORE EQU RAM_BASE + 7F40H @DRIVE_IX_SOURCE EQU RAM_BASE + 7F42H ;For sec and card copy @DRIVE_IX_DEST EQU RAM_BASE + 7F44H ;For sec and card copy @YEAR: EQU RAM_BASE + 7F46H @MONTH: EQU RAM_BASE + 7F48H @DATE: EQU RAM_BASE + 7F4AH @HOURS: EQU RAM_BASE + 7F4CH @MINUTES: EQU RAM_BASE + 7F4EH @SECONDS: EQU RAM_BASE + 7F50H @SEEK_RT EQU RAM_BASE + 7F52H ;Floppy seek retry count @SEC_RT EQU RAM_BASE + 7F54H ;Floppy sec R/W retry count @CURRENT_TRACK EQU RAM_BASE + 7F56H @CURRENT_SECTOR EQU RAM_BASE + 7F58H S_DATA_MARK EQU RAM_BASE + 7F5AH ;Pointer to start of Data area for track formatting E_DATA_MARK EQU RAM_BASE + 7F5CH ;Pointer to end of Data area+1 E_SEC_MARK EQU RAM_BASE + 7F5EH ;End Sector image +1 S_GAP4_MARK EQU RAM_BASE + 7F60H ;Start GAP4 area E_GAP4_MARK EQU RAM_BASE + 7F62H ;End track +1 (Not used here. Can be used to determine a new minimum total track size) @LINE_COUNT EQU RAM_BASE + 7F64H @DISK_FORMAT EQU RAM_BASE + 7F66H @SIDE_COUNT EQU RAM_BASE + 7F68H ;For Floppy disk formatting @SEC$RETRY$COUNT EQU RAM_BASE + 7F6AH @DRIVE_1_TABLE EQU RAM_BASE + 6000H ;E000H, Start of Drive paramater storage area. (Critical not to overwrite) @DRIVE_2_TABLE EQU @DRIVE_1_TABLE + 80H ;IDE 2 DRIVE RAM Storage @DRIVE_3_TABLE EQU @DRIVE_2_TABLE + 80H ;SD Drive 3 @DRIVE_4_TABLE EQU @DRIVE_3_TABLE + 80H ;SD Drive 4 @DRIVE_5_TABLE EQU @DRIVE_4_TABLE + 80H ;SD Drive 4 @DRIVE_6_TABLE EQU @DRIVE_5_TABLE + 80H ;SD Drive 4 @DRIVE_0_TABLE EQU @DRIVE_6_TABLE + 80H ;Unassigned drive ;END