; MP/M 2 XIOS for Z80-Simulator ; ; Copyright (C) 1989-2006 by Udo Munk ; .Z80 CSEG ; ; i/o ports ; CONSTA EQU 0 ;console status port CONDAT EQU 1 ;console data port PRTSTA EQU 2 ;printer status port PRTDAT EQU 3 ;printer data port AUXSTA EQU 4 ;auxilary status port AUXDAT EQU 5 ;auxilary data port FDCD EQU 10 ;fdc-port: # of drive FDCT EQU 11 ;fdc-port: # of track FDCS EQU 12 ;fdc-port: # of sector FDCOP EQU 13 ;fdc-port: command FDCST EQU 14 ;fdc-port: status DMAL EQU 15 ;dma-port: dma address low DMAH EQU 16 ;dma-port: dma address high MMUINI EQU 20 ;initialize mmu MMUSEL EQU 21 ;bank select mmu CLKCMD EQU 25 ;clock command CLKDAT EQU 26 ;clock data TIMER EQU 27 ;interrupt timer ; ; clock commands ; GETSEC EQU 0 ;get seconds GETMIN EQU 1 ;get minutes GETHOU EQU 2 ;get hours GETDAL EQU 3 ;get days low GETDAH EQU 4 ;get days high ; BDOS EQU 5 ;bdos calls SETTD EQU 104 ;bdos set time and date ; POLL EQU 131 ;xdos poll function PLCI0 EQU 0 ;poll console in #0 FLAGSET EQU 133 ;xdos flag set function SYSDATA EQU 154 ;xdos syste data address ; ; jump vector for individual subroutines ; JP COMMONBASE ;commonbase JP WARMSTART ;warm start JP CONST ;console status JP CONIN ;console character in JP CONOUT ;console character out JP LIST ;list character out JP PUNCH ;not used by MP/M 2 JP READER ;not used by MP/M 2 JP HOME ;move head to home JP SELDSK ;select disk JP SETTRK ;set track numer JP SETSEC ;set sector number JP SETDMA ;set dma address JP READ ;read disk JP WRITE ;write disk JP LISTST ;not used by MP/M 2 JP SECTRAN ;sector translate JP SELMEMORY ;select memory JP POLLDEVICE ;poll device JP STARTCLOCK ;start clock JP STOPCLOCK ;stop clock JP EXITREGION ;exit region JP MAXCONSOLE ;maximum console number JP SYSTEMINIT ;system initialization JP IDLE ;idle prozedure ; COMMONBASE: JP COLDSTART SWTUSER: JP $-$ SWTSYS: JP $-$ PDISP: JP $-$ XDOS: JP $-$ SYSDAT: DEFW $-$ ; COLDSTART: WARMSTART: LD C,0 JP XDOS ;system reset, terminate prozess ; ; MP/M II V2.0 Console Bios ; CONST: CALL PTBLJMP ;compute and jump to handler DW PTSTI0 ; CONIN: CALL PTBLJMP ;compute and jump to handle DW PTIN0 ; CONOUT: CALL PTBLJMP ;compute and jump to handler DW PTOUT0 ; PTSTI0: IN A,(CONSTA) ;console 0 input RET ; PTIN0: LD C,POLL ;poll console 0 status in LD E,PLCI0 CALL XDOS ;poll console 0 IN A,(CONDAT) ;read character AND 7FH ;strip parity RET ; PTOUT0: LD A,C ;console 0 output OUT (CONDAT),A RET ; PTBLJMP: ;compute and jump to handler LD A,D ADD A,A ;double table index for adress offset POP HL ;return adress of jump table LD E,A LD D,0 ADD HL,DE ;table index * 2 + table base LD E,(HL) ;get handler address INC HL LD D,(HL) EX DE,HL JP (HL) ;jump to computed handler ; LIST: LD A,C OUT (PRTDAT),A RET ; ; not used by MP/M 2 PUNCH: READER: LISTST: RET ; ; MP/M II V2.0 Xios ; ; select/protect memory ; BC = address of memory descriptor SELMEMORY: LD HL,3 ;offset memory bank in memory descriptor ADD HL,BC LD A,(HL) ;get bank OUT (MMUSEL),A ;and select it RET ; ; poll character devices ; POLLDEVICE: JP PTSTI0 ;poll console 0 status in ; ; start clock ; STARTCLOCK: LD A,0FFH LD (TICKN),A RET ; ; stop clock ; STOPCLOCK: XOR A LD (TICKN),A RET ; ; exit region: ; enable interrupt if not preempted or in dispatcher ; EXITREGION: LD A,(PREEMP) OR A RET NZ EI RET ; ; maximum console number ; MAXCONSOLE: LD A,1 RET ; ; system initialization ; C MP/M debugger restart # ; DE MP/M entry point for debugger ; HL BIOS jump table address ; SYSTEMINIT: ; ;doesn't work PUSH HL LD C,SYSDATA ;get system data page address CALL XDOS CALL SETTOD ;set tod from hardware clock POP HL ; LD A,8 ;initialize banked memory OUT (MMUINI),A LD B,A ; SYS1: DEC B LD A,B OUT (MMUSEL),A ;select every bank and initialize LD A,0C3H ;jp instruction LD (0),A LD (38H),A LD (1),HL PUSH HL LD HL,INTHND LD (39H),HL POP HL JP NZ,SYS1 ; LD HL,SIGNON ;print message SYS2: LD A,(HL) OR A JP Z,SYS3 OUT (CONDAT),A INC HL JP SYS2 ; SYS3: IM 1 LD A,1 ;enable 20ms interrupt timer OUT (TIMER),A EI RET ; ; set mp/m tod from hardware clock ; hl = tod address ; SETTOD: LD A,GETDAL OUT (CLKCMD),A IN A,(CLKDAT) LD (HL),A INC HL LD A,GETDAH OUT (CLKCMD),A IN A,(CLKDAT) LD (HL),A INC HL LD A,GETHOU OUT (CLKCMD),A IN A,(CLKDAT) LD (HL),A INC HL LD A,GETMIN OUT (CLKCMD),A IN A,(CLKDAT) LD (HL),A RET ; ; idle ; IDLE: EI HALT RET ; ; interrupt handler ; INTHND: LD (SVDHL),HL ;save registers POP HL LD (SVDRET),HL PUSH AF LD HL,0 ADD HL,SP LD (SVDSP),HL LD SP,INTSTK PUSH DE PUSH BC LD A,0FFH ;set preempted flag LD (PREEMP),A LD A,(TICKN) OR A ;test tick, indicates delayed process JP Z,INTHND1 LD C,FLAGSET ;set flag #1 each tick LD E,1 CALL XDOS INTHND1: LD HL,CNT50 ;decrement tick counter DEC (HL) JP NZ,INTDONE LD (HL),50 ;set flag #2 each second LD C,FLAGSET LD E,2 CALL XDOS INTDONE: XOR A ;clear preempted flag LD (PREEMP),A POP BC ;restore registers POP DE LD HL,(SVDSP) LD SP,HL POP AF LD HL,(SVDRET) PUSH HL LD HL,(PDISP+1) ;dispatch processes PUSH HL LD HL,(SVDHL) RETI ; ; i/o drivers for disks ; ; move to the track 00 position of current drive ; translate this call into a settrk call with parameter 00 ; HOME: LD C,0 ;select track 0 JP SETTRK ;we will move to 00 on first read/write ; ; select disk given by register C ; SELDSK: LD HL,0000H ;error return code LD A,C CP 4 ;must be between 0 and 3 JR NC,SELHD ;no carry if 4,5,... ; disk number is in the proper range ; compute proper disk parameter header address OUT (FDCD),A ;selekt disk drive LD L,A ;L=disk number 0,1,2,3 ADD HL,HL ;*2 ADD HL,HL ;*4 ADD HL,HL ;*8 ADD HL,HL ;*16 (size of each header) LD DE,DPBASE ADD HL,DE ;HL=.dpbase(diskno*16) RET SELHD: CP 8 ;select the harddisk? RET NZ ;no, error OUT (FDCD),A ;select disk drive LD HL,HDBASE ;HL=hdbase for harddisk RET ; ; set track given by register c ; SETTRK: LD A,C OUT (FDCT),A RET ; ; set sector given by register c ; SETSEC: LD A,C OUT (FDCS),A RET ; ; translate the sector given by BC using the ; translate table given by DE ; SECTRAN: EX DE,HL ;HL=.trans ADD HL,BC ;HL=.trans(sector) LD L,(HL) ;L = trans(sector) LD H,0 ;HL= trans(sector) RET ;with value in HL ; ; set dma address given by registers b and c ; SETDMA: LD A,C ;low order address OUT (DMAL),A LD A,B ;high order address OUT (DMAH),A ;in dma RET ; ; perform read operation ; READ: XOR A ;read command -> A JP WAITIO ;to perform the actual i/o ; ; perform a write operation ; WRITE: LD A,1 ;write command -> A ; ; enter here from read and write to perform the actual i/o ; operation. return a 00h in register a if the operation completes ; properly, and 01h if an error occurs during the read or write ; ; in this case, we have saved the disk number in 'diskno' (0-3) ; the track number in 'track' (0-76) ; the sector number in 'sector' (1-26) ; the dma address in 'dmaad' (0-65535) ; WAITIO: OUT (FDCOP),A ;start i/o operation IN A,(FDCST) ;status of i/o operation -> A RET ; ; XIOS data segment ; SIGNON: DEFB 13,10 DEFM 'MP/M 2 XIOS V1.1 for Z80SIM, ' DEFM 'Copyright 1989-2006 by Udo Munk' DEFB 13,10,0 ; TICKN: DEFB 0 ;flag for tick PREEMP: DEFB 0 ;preempted flag TOD: DEFS 4 ;time of day SVDHL: DEFS 2 ;save hl during interrupt SVDRET: DEFS 2 ;save return address during interrupt SVDSP: DEFS 2 ;save sp during interrupt CNT50: DEFB 50 ;50 ticks a 20ms = 1 second ;interrupt stack DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H DEFW 0C7C7H,0C7C7H,0C7C7H,0C7C7H INTSTK: ; ; fixed data tables for four-drive standard ; IBM-compatible 8" disks ; ; disk parameter header for disk 00 DPBASE: DEFW TRANS,0000H DEFW 0000H,0000H DEFW DIRBF,DPBLK DEFW CHK00,ALL00 ; disk parameter header for disk 01 DEFW TRANS,0000H DEFW 0000H,0000H DEFW DIRBF,DPBLK DEFW CHK01,ALL01 ; disk parameter header for disk 02 DEFW TRANS,0000H DEFW 0000H,0000H DEFW DIRBF,DPBLK DEFW CHK02,ALL02 ; disk parameter header for disk 03 DEFW TRANS,0000H DEFW 0000H,0000H DEFW DIRBF,DPBLK DEFW CHK03,ALL03 ; ; sector translate vector for the IBM 8" disks ; TRANS: DEFB 1,7,13,19 ;sectors 1,2,3,4 DEFB 25,5,11,17 ;sectors 5,6,7,8 DEFB 23,3,9,15 ;sectors 9,10,11,12 DEFB 21,2,8,14 ;sectors 13,14,15,16 DEFB 20,26,6,12 ;sectors 17,18,19,20 DEFB 18,24,4,10 ;sectors 21,22,23,24 DEFB 16,22 ;sectors 25,26 ; ; disk parameter block, common to all IBM 8" disks ; DPBLK: DEFW 26 ;sectors per track DEFB 3 ;block shift factor DEFB 7 ;block mask DEFB 0 ;extent mask DEFW 242 ;disk size-1 DEFW 63 ;directory max DEFB 192 ;alloc 0 DEFB 0 ;alloc 1 DEFW 16 ;check size DEFW 2 ;track offset ; ; fixed data tables for 4MB harddisk ; ; disk parameter header HDBASE: DEFW HDTRA,0000H DEFW 0000H,0000H DEFW DIRBF,HDBLK DEFW CHKHD,ALLHD ; ; sector translate vector for the hardisk ; HDTRA: DEFB 1,2,3,4,5,6,7,8,9,10 DEFB 11,12,13,14,15,16,17,18,19,20 DEFB 21,22,23,24,25,26,27,28,29,30 DEFB 31,32,33,34,35,36,37,38,39,40 DEFB 41,42,43,44,45,46,47,48,49,50 DEFB 51,52,53,54,55,56,57,58,59,60 DEFB 61,62,63,64,65,66,67,68,69,70 DEFB 71,72,73,74,75,76,77,78,79,80 DEFB 81,82,83,84,85,86,87,88,89,90 DEFB 91,92,93,94,95,96,97,98,99,100 DEFB 101,102,103,104,105,106,107,108,109,110 DEFB 111,112,113,114,115,116,117,118,119,120 DEFB 121,122,123,124,125,126,127,128 ; ; disk parameter block for harddisk ; HDBLK: DEFW 128 ;sectors per track DEFB 4 ;block shift factor DEFB 15 ;block mask DEFB 0 ;extent mask DEFW 2039 ;disk size-1 DEFW 1023 ;directory max DEFB 255 ;alloc 0 DEFB 255 ;alloc 1 DEFW 0 ;check size DEFW 0 ;track offset ; DIRBF: DEFS 128 ;scratch directory area ALL00: DEFS 31 ;allocation vector 0 ALL01: DEFS 31 ;allocation vector 1 ALL02: DEFS 31 ;allocation vector 2 ALL03: DEFS 31 ;allocation vector 3 ALLHD: DEFS 255 ;allocation vector harddisk CHK00: DEFS 16 ;check vector 0 CHK01: DEFS 16 ;check vector 1 CHK02: DEFS 16 ;check vector 2 CHK03: DEFS 16 ;check vector 3 CHKHD: DEFS 0 ;check vector harddisk ; END