; ;================================================================================================== ; S100 PROPELLER CONSOLE DRIVER ;================================================================================================== ; ; TODO: ; SCON_IOBASE .EQU $0000 ; NOTE: 16-BIT I/O ; SCON_STATUS .EQU SCON_IOBASE SCON_DATA .EQU SCON_IOBASE + 1 ; SCON_KBDRDY .EQU %00000010 SCON_DSPRDY .EQU %00000100 ; SCON_COLS .EQU 80 SCON_ROWS .EQU 40 ; DEVECHO "SCON: IO=" DEVECHO SCON_IOBASE DEVECHO "\n" ; ; ; SCON_PREINIT: ; ; ADD OURSELVES TO CIO DISPATCH TABLE ; OR $FF ; CLEAR OUT LD (SCON_UNIT),A ; ... SCON UNIT NUMBER CALL SCON_DETECT ; SEE IF WE ARE THERE RET NZ ; ABORT IF NOT ; LD D,0 ; PHYSICAL UNIT IS ZERO LD E,CIODEV_SCON ; DEVICE TYPE LD BC,SCON_FNTBL ; BC := FUNCTION TABLE ADDRESS CALL CIO_ADDENT ; ADD ENTRY, A := UNIT ASSIGNED LD (SCON_UNIT),A ; RECORD OUR UNIT NUMBER CALL CIO_SETCRT ; SET OURSELVES AS THE CRT DEVICE ; XOR A ; SIGNAL SUCCESS RET ; ; ; SCON_INIT: CALL NEWLINE PRTS("SCON:$") PRTS(" IO=0x$") ; FORMATTING LD A,SCON_IOBASE CALL PRTHEXBYTE ; LD A,(SCON_UNIT) CP $FF JR NZ,SCON_INIT1 ; ; HARDWARE NOT PRESENT PRTS(" NOT PRESENT$") OR $FF ; SIGNAL FAILURE RET ; SCON_INIT1: ; DISPLAY CONSOLE DIMENSIONS CALL PC_SPACE LD A,SCON_COLS CALL PRTDECB LD A,'X' CALL COUT LD A,SCON_ROWS CALL PRTDECB CALL PRTSTRD .TEXT " TEXT (ANSI)$" ; XOR A ; SIGNAL SUCCESS RET ; ; DRIVER FUNCTION TABLE ; SCON_FNTBL: .DW SCON_IN .DW SCON_OUT .DW SCON_IST .DW SCON_OST .DW SCON_INITDEV .DW SCON_QUERY .DW SCON_DEVICE #IF (($ - SCON_FNTBL) != (CIO_FNCNT * 2)) .ECHO "*** INVALID SCON FUNCTION TABLE ***\n" #ENDIF ; ; ; SCON_IN: CALL SCON_IST ; CHECK FOR CHAR PENDING JR Z,SCON_IN ; WAIT FOR IT IF NECESSARY ;IN0 A,(SCON_DATA) ; READ THE CHAR FROM PROPIO LD BC,SCON_DATA ; DATA PORT (16 BIT I/O) IN A,(C) ; READ THE CHAR FROM PROPIO LD E,A RET ; ; ; SCON_IST: ;IN0 A,(SCON_STATUS) ; READ LINE STATUS REGISTER LD BC,SCON_STATUS ; STATUS PORT (16-BIT I/O) IN A,(C) ; READ LINE STATUS REGISTER AND SCON_KBDRDY ; ISOLATE KBDRDY JP Z,CIO_IDLE ; RETURN VIA IDLE PROCESSING OR $FF ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; SCON_OUT: CALL SCON_OST ; CHECK FOR OUTPUT READY JR Z,SCON_OUT ; WAIT IF NECESSARY LD A,E ; RECOVER THE CHAR TO WRITE ;OUT0 (SCON_DATA),A ; WRITE THE CHAR TO PROPIO LD BC,SCON_DATA ; DATA PORT (16 BIT I/O) OUT (C),A ; WRITE THE CHAR TO PROPIO RET ; ; ; SCON_OST: ;IN0 A,(SCON_STATUS) ; READ LINE STATUS REGISTER LD BC,SCON_STATUS ; STATUS PORT (16-BIT I/O) IN A,(C) ; READ LINE STATUS REGISTER AND SCON_DSPRDY ; ISOLATE DSPRDY JP Z,CIO_IDLE ; RETURN VIA IDLE PROCESSING OR $FF ; SET A=$FF TO SIGNAL READY RET ; RETURN ; ; ; SCON_INITDEV: SYSCHKERR(ERR_NOTIMPL) RET ; ; ; SCON_QUERY: LD DE,0 LD HL,0 XOR A RET ; ; ; SCON_DEVICE: LD D,CIODEV_SCON ; D := DEVICE TYPE LD E,0 ; E := DEVICE NUM, ALWAYS 0 LD C,$BF ; C := DEVICE TYPE, 0xBF IS PROP TERM LD H,0 ; H := 0, DRIVER HAS NO MODES LD L,SCON_IOBASE ; L := BASE I/O ADDRESS XOR A ; SIGNAL SUCCESS RET ; ; TEST FOR HARDWARE PRESENCE. ; THIS IS REALLY A POOR SOLUTION. WE ASSUME THAT THE STATUS AND ; DATA PORT SHOULD NOT BE THE SAME VALUE. IF SO, IT PROBABLY MEANS ; THERE IS NOTHING THERE. ; SCON_DETECT: IN A,(SCON_STATUS) ; GET STATUS PORT VALUE DIRECTLY CP $FF ; CHECK FOR $FF JR Z,SCON_DETECT1 ; IF $FF, NOT ACTIVE LD B,A ; STASH IN B IN A,(SCON_DATA) ; READ DATA PORT CP B ; SAME? JR Z,SCON_DETECT1 ; IF SO, NOT ACTIVE XOR A ; SIGNAL ACTIVE RET SCON_DETECT1: OR $FF ; SET NZ TO SIGNAL NOT PRESENT RET ; DONE ; ; ; SCON_UNIT .DB $FF ; OUR ASSIGNED UNIT NUMBER