; ;================================================================================================== ; SIMPLE SERIAL DRIVER ;================================================================================================== ; ; TODO: ; DEVECHO "SSER: IO=" DEVECHO SSERSTATUS DEVECHO "\n" ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE HEADER ;-------------------------------------------------------------------------------------------------- ; ORG_SSER .EQU $ ; .DW SIZ_SSER ; MODULE SIZE .DW SSER_INITPHASE ; ADR OF INIT PHASE HANDLER ; SSER_INITPHASE: ; INIT PHASE HANDLER, A=PHASE CP HB_PHASE_PREINIT ; PREINIT PHASE? JP Z,SSER_PREINIT ; DO PREINIT CP HB_PHASE_INIT ; INIT PHASE? JP Z,SSER_INIT ; DO INIT RET ; DONE ; ; ; SSER_PREINIT: ; ; TEST FOR PRESENCE ; XOR A ; CLEAR ACCUM LD (SSER_PRESENT),A ; PRESET TO NOT PRESENT CALL SSER_DETECT ; CHECK FOR HARDWARE, Z=PRESENT RET NZ ; ABORT IF NOT PRESENT OR $FF ; PRESENT FLAG LD (SSER_PRESENT),A ; STORE IT ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; LD D,0 ; PHYSICAL UNIT IS ZERO LD E,CIODEV_SSER ; DEVICE TYPE LD BC,SSER_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED ; XOR A RET ; ; ; SSER_INIT: LD A,(SSER_PRESENT) ; PRESENT FLAG OR A ; SET FLAGS RET Z ; ABORT IF NOT PRESENT CALL NEWLINE PRTS("SSER:$") PRTS(" IO=0x$") ; FORMATTING LD A,SSERSTATUS CALL PRTHEXBYTE ; XOR A ; SIGNAL SUCCESS RET ; ; DRIVER FUNCTION TABLE ; SSER_FNTBL: .DW SSER_IN .DW SSER_OUT .DW SSER_IST .DW SSER_OST .DW SSER_INITDEV .DW SSER_QUERY .DW SSER_DEVICE #IF (($ - SSER_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID SSER FUNCTION TABLE ***\n" #ENDIF ; ; ; SSER_IN: CALL SSER_IST ; CHECK FOR CHAR PENDING JR Z,SSER_IN ; WAIT FOR IT IF NECESSARY IN A,(SSERDATA) ; READ THE CHAR LD E,A RET ; ; ; SSER_IST: IN A,(SSERSTATUS) ; READ LINE STATUS REGISTER #IF (SSERIINV) CPL #ENDIF AND SSERIRDY ; ISOLATE DATA READY JP Z,CIO_IDLE ; RETURN VIA IDLE PROCESSING OR $FF ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; SSER_OUT: CALL SSER_OST ; CHECK FOR OUTPUT READY JR Z,SSER_OUT ; WAIT IF NECESSARY LD A,E ; RECOVER THE CHAR TO WRITE OUT (SSERDATA),A ; WRITE THE CHAR RET ; ; ; SSER_OST: IN A,(SSERSTATUS) ; READ LINE STATUS REGISTER #IF (SSEROINV) CPL #ENDIF AND SSERORDY ; ISOLATE OUTPUT RDY JP Z,CIO_IDLE ; RETURN VIA IDLE PROCESSING OR $FF ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; SSER_INITDEV: SYSCHKERR(ERR_NOTIMPL) RET ; ; ; SSER_QUERY: LD DE,SSERCFG XOR A RET ; ; ; SSER_DEVICE: LD D,CIODEV_SSER ; D := DEVICE TYPE LD E,0 ; E := DEVICE NUM, ALWAYS 0 LD C,$00 ; C := DEVICE TYPE, 0x00 IS RS-232 LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,SSERSTATUS ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; TEST FOR HARDWARE PRESENCE BY CHECKING THE STATUS PORT. IF IT IS ; $FF, WE ASSUME NOT PRESENT. THEN READ PORT A DIFFERENT WAY. IF ; PRESENT PORT SHOULD HAVE SAME VALUE. ; SSER_DETECT: IN A,(SSERSTATUS) ; GET DATA PORT VALUE DIRECTLY CP $FF ; CHECK FOR $FF JR NZ,SSER_DETECT1 ; IF NOT $FF, MAY BE ACTIVE, CONTINUE OR A ; SWITCH ZF BACK TO NZ RET ; DONE SSER_DETECT1: LD C,SSERSTATUS ; PORT ADR TO C IN B,(C) ; GET DATA PORT VALUE VIA (C) CP B ; COMPARE, EQUAL IMPLIES ACTIVE PORT RET ; ; ; SSER_PRESENT .DB 0 ; FLAG FOR HARDWARE PRESENT ; ;-------------------------------------------------------------------------------------------------- ; HBIOS MODULE TRAILER ;-------------------------------------------------------------------------------------------------- ; END_SSER .EQU $ SIZ_SSER .EQU END_SSER - ORG_SSER ; MEMECHO "SSER occupies " MEMECHO SIZ_SSER MEMECHO " bytes.\n"