diff --git a/libsrc/apple2/ser/a2.ssc.s b/libsrc/apple2/ser/a2.ssc.s index 5b81128f9..f81155543 100644 --- a/libsrc/apple2/ser/a2.ssc.s +++ b/libsrc/apple2/ser/a2.ssc.s @@ -38,8 +38,8 @@ .endif ; Driver signature - .byte $73, $65, $72 ; "ser" - .byte SER_API_VERSION ; Serial API version number + .byte $73, $65, $72 ; "ser" + .byte SER_API_VERSION ; Serial API version number ; Library reference .addr $0000 @@ -59,16 +59,16 @@ ; I/O definitions .if (.cpu .bitand CPU_ISET_65C02) -ACIA = $C088 +ACIA := $C088 .else Offset = $8F ; Move 6502 false read out of I/O to page $BF -ACIA = $C088-Offset +ACIA := $C088-Offset .endif -ACIA_DATA = ACIA+0 ; Data register -ACIA_STATUS = ACIA+1 ; Status register -ACIA_CMD = ACIA+2 ; Command register -ACIA_CTRL = ACIA+3 ; Control register +ACIA_DATA := ACIA+0 ; Data register +ACIA_STATUS := ACIA+1 ; Status register +ACIA_CMD := ACIA+2 ; Command register +ACIA_CTRL := ACIA+3 ; Control register ;---------------------------------------------------------------------------- ; Global variables @@ -77,16 +77,17 @@ ACIA_CTRL = ACIA+3 ; Control register RecvHead: .res 1 ; Head of receive buffer RecvTail: .res 1 ; Tail of receive buffer -RecvFreeCnt: .res 1 ; Number of bytes in receive buffer +RecvFreeCnt: .res 1 ; Number of free bytes in receive buffer SendHead: .res 1 ; Head of send buffer SendTail: .res 1 ; Tail of send buffer -SendFreeCnt: .res 1 ; Number of bytes in send buffer +SendFreeCnt: .res 1 ; Number of free bytes in send buffer Stopped: .res 1 ; Flow-stopped flag -RtsOff: .res 1 ; +RtsOff: .res 1 ; Cached value of command register with + ; flow stopped -RecvBuf: .res 256 ; Receive buffers: 256 bytes -SendBuf: .res 256 ; Send buffers: 256 bytes +RecvBuf: .res 256 ; Receive buffer: 256 bytes +SendBuf: .res 256 ; Send buffer: 256 bytes Index: .res 1 ; I/O register index @@ -96,8 +97,9 @@ Slot: .byte $02 ; Default to SSC in slot 2 .rodata - ; Tables used to translate RS232 params into register values -BaudTable: ; bit7 = 1 means setting is invalid +BaudTable: ; Table used to translate RS232 baudrate param + ; into control register value + ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_45_5 .byte $01 ; SER_BAUD_50 .byte $02 ; SER_BAUD_75 @@ -118,49 +120,55 @@ BaudTable: ; bit7 = 1 means setting is invalid .byte $FF ; SER_BAUD_57600 .byte $FF ; SER_BAUD_115200 .byte $FF ; SER_BAUD_230400 -BitTable: + +BitTable: ; Table used to translate RS232 databits param + ; into control register value .byte $60 ; SER_BITS_5 .byte $40 ; SER_BITS_6 .byte $20 ; SER_BITS_7 .byte $00 ; SER_BITS_8 -StopTable: + +StopTable: ; Table used to translate RS232 stopbits param + ; into control register value .byte $00 ; SER_STOP_1 .byte $80 ; SER_STOP_2 -ParityTable: + +ParityTable: ; Table used to translate RS232 parity param + ; into command register value .byte $00 ; SER_PAR_NONE .byte $20 ; SER_PAR_ODD .byte $60 ; SER_PAR_EVEN .byte $A0 ; SER_PAR_MARK .byte $E0 ; SER_PAR_SPACE - ; Check five bytes at known positions on the - ; slot's firmware to make sure this is an SSC - ; (or Apple //c comm port) firmware that drives - ; an ACIA 6551 chip. - ; - ; The SSC firmware and the Apple //c(+) comm - ; port firmware all begin with a BIT instruction. - ; The IIgs, on the other hand, has a - ; Zilog Z8530 chip and its firmware starts with - ; a SEP instruction. We don't want to load this - ; driver on the IIgs' serial port. We'll - ; differentiate the firmware on this byte. - ; - ; The next four bytes we check are the Pascal - ; Firmware Protocol Bytes that identify a - ; serial card. Those are the same bytes for - ; SSC firmwares, Apple //c firmwares and IIgs - ; Zilog Z8530 firmwares - which is the reason - ; we have to check for the firmware's first - ; instruction too. - -IdOfsTable: +IdOfsTable: ; Table of bytes positions, used to check five + ; specific bytes on the slot's firmware to make + ; sure this is an SSC (or Apple //c comm port) + ; firmware that drives an ACIA 6551 chip. + ; + ; The SSC firmware and the Apple //c(+) comm + ; port firmware all begin with a BIT instruction. + ; The IIgs, on the other hand, has a + ; Zilog Z8530 chip and its firmware starts with + ; a SEP instruction. We don't want to load this + ; driver on the IIgs' serial port. We'll + ; differentiate the firmware on this byte. + ; + ; The next four bytes we check are the Pascal + ; Firmware Protocol Bytes that identify a + ; serial card. Those are the same bytes for + ; SSC firmwares, Apple //c firmwares and IIgs + ; Zilog Z8530 firmwares - which is the reason + ; we have to check for the firmware's first + ; instruction too. .byte $00 ; First instruction .byte $05 ; Pascal 1.0 ID byte .byte $07 ; Pascal 1.0 ID byte .byte $0B ; Pascal 1.1 generic signature byte .byte $0C ; Device signature byte -IdValTable: + +IdValTable: ; Table of expected values for the five checked + ; bytes .byte $2C ; BIT .byte $38 ; ID Byte 0 (from Pascal 1.0), fixed .byte $18 ; ID Byte 1 (from Pascal 1.0), fixed @@ -193,12 +201,10 @@ SER_CLOSE: ldx Index ; Check for open port beq :+ - ; Deactivate DTR and disable 6551 interrupts - lda #%00001010 + lda #%00001010 ; Deactivate DTR and disable 6551 interrupts sta ACIA_CMD,x - ; Done, return an error code -: lda #SER_ERR_OK +: lda #SER_ERR_OK ; Done, return an error code .assert SER_ERR_OK = 0, error tax stx Index ; Mark port as closed @@ -215,98 +221,96 @@ SER_OPEN: ora Slot sta ptr2+1 - ; Check Pascal 1.1 Firmware Protocol ID bytes -: ldy IdOfsTable,x +: ldy IdOfsTable,x ; Check Pascal 1.1 Firmware Protocol ID bytes lda IdValTable,x cmp (ptr2),y - bne NoDevice + bne NoDev inx cpx #IdTableLen bcc :- - ; Convert slot to I/O register index - lda Slot + lda Slot ; Convert slot to I/O register index asl asl asl asl .if .not (.cpu .bitand CPU_ISET_65C02) - adc #Offset ; Assume carry to be clear + adc #Offset ; Assume carry to be clear .endif tax ; Check if the handshake setting is valid - ldy #SER_PARAMS::HANDSHAKE ; Handshake + ldy #SER_PARAMS::HANDSHAKE lda (ptr1),y - cmp #SER_HS_HW ; This is all we support - bne InvParam + cmp #SER_HS_HW ; This is all we support + bne InvParm - ; Initialize buffers - ldy #$00 + ldy #$00 ; Initialize buffers sty Stopped sty RecvHead sty RecvTail sty SendHead sty SendTail - dey ; Y = 255 + dey ; Y = 255 sty RecvFreeCnt sty SendFreeCnt ; Set the value for the control register, which contains stop bits, ; word length and the baud rate. ldy #SER_PARAMS::BAUDRATE - lda (ptr1),y ; Baudrate index + lda (ptr1),y ; Baudrate index tay - lda BaudTable,y ; Get 6551 value - bmi InvBaud ; Branch if rate not supported + lda BaudTable,y ; Get 6551 value + bmi InvBaud ; Branch if rate not supported sta tmp1 - ldy #SER_PARAMS::DATABITS ; Databits - lda (ptr1),y + ldy #SER_PARAMS::DATABITS + lda (ptr1),y ; Databits index tay - lda BitTable,y + lda BitTable,y ; Get 6551 value ora tmp1 sta tmp1 - ldy #SER_PARAMS::STOPBITS ; Stopbits - lda (ptr1),y + ldy #SER_PARAMS::STOPBITS + lda (ptr1),y ; Stopbits index tay - lda StopTable,y + lda StopTable,y ; Get 6551 value ora tmp1 - ora #%00010000 ; Receiver clock source = baudrate + ora #%00010000 ; Set receiver clock source = baudrate sta ACIA_CTRL,x ; Set the value for the command register. We remember the base value ; in RtsOff, since we will have to manipulate ACIA_CMD often. - ldy #SER_PARAMS::PARITY ; Parity - lda (ptr1),y + ldy #SER_PARAMS::PARITY + lda (ptr1),y ; Parity index tay - lda ParityTable,y - ora #%00000001 ; DTR active - sta RtsOff - ora #%00001000 ; Enable receive interrupts + lda ParityTable,y ; Get 6551 value + + ora #%00000001 ; Set DTR active + sta RtsOff ; Store value to easily handle flow control later + ora #%00001000 ; Enable receive interrupts (RTS low) sta ACIA_CMD,x ; Done - stx Index ; Mark port as open + stx Index ; Mark port as open lda #SER_ERR_OK .assert SER_ERR_OK = 0, error tax rts ; Device (hardware) not found -NoDevice:lda #SER_ERR_NO_DEVICE - ldx #0 ; return value is char +NoDev: lda #SER_ERR_NO_DEVICE + ldx #$00 ; return value is char rts ; Invalid parameter -InvParam:lda #SER_ERR_INIT_FAILED - ldx #0 ; return value is char +InvParm:lda #SER_ERR_INIT_FAILED + ldx #$00 ; return value is char rts ; Baud rate not available InvBaud:lda #SER_ERR_BAUD_UNAVAIL - ldx #0 ; return value is char + ldx #$00 ; return value is char rts ;---------------------------------------------------------------------------- @@ -317,21 +321,19 @@ InvBaud:lda #SER_ERR_BAUD_UNAVAIL SER_GET: ldx Index - ; Check for buffer empty - lda RecvFreeCnt ; (25) + lda RecvFreeCnt ; Check for buffer empty cmp #$FF bne :+ lda #SER_ERR_NO_DATA - ldx #0 ; return value is char + ldx #$00 ; return value is char rts - ; Check for flow stopped & enough free: release flow control -: ldy Stopped ; (34) +: ldy Stopped ; Check for flow stopped beq :+ - cmp #63 + cmp #63 ; Enough free? bcc :+ .if (.cpu .bitand CPU_ISET_65C02) - stz Stopped + stz Stopped ; Release flow control .else lda #$00 sta Stopped @@ -340,14 +342,13 @@ SER_GET: ora #%00001000 sta ACIA_CMD,x - ; Get byte from buffer -: ldy RecvHead ; (41) +: ldy RecvHead ; Get byte from buffer lda RecvBuf,y inc RecvHead inc RecvFreeCnt - ldx #$00 ; (59) + ldx #$00 .if (.cpu .bitand CPU_ISET_65C02) - sta (ptr1) + sta (ptr1) ; Store it for caller .else sta (ptr1,x) .endif @@ -361,29 +362,26 @@ SER_GET: SER_PUT: ldx Index - ; Try to send - ldy SendFreeCnt - cpy #$FF ; Nothing to flush + ldy SendFreeCnt ; Anything to send first? + cpy #$FF ; No beq :+ pha lda #$00 ; TryHard = false - jsr TryToSend + jsr TryToSend ; Try to flush send buffer pla - ; Reload SendFreeCnt after TryToSend - ldy SendFreeCnt + ldy SendFreeCnt ; Reload SendFreeCnt after TryToSend bne :+ lda #SER_ERR_OVERFLOW - ldx #0 ; return value is char + ldx #$00 ; return value is char rts - ; Put byte into send buffer & send -: ldy SendTail +: ldy SendTail ; Put byte into send buffer sta SendBuf,y inc SendTail dec SendFreeCnt lda #$FF ; TryHard = true - jsr TryToSend + jsr TryToSend ; Flush send buffer lda #SER_ERR_OK .assert SER_ERR_OK = 0, error tax @@ -405,26 +403,25 @@ SER_STATUS: ;---------------------------------------------------------------------------- ; SER_IOCTL: Driver defined entry point. The wrapper will pass a pointer to ioctl ; specific data in ptr1, and the ioctl code in A. +; The ioctl data is the slot number to open. ; Must return an SER_ERR_xx code in a/x. SER_IOCTL: - ; Check data msb and code to be 0 - ora ptr1+1 + ora ptr1+1 ; Check data msb and code to be 0 bne :+ - ; Check data lsb to be [1..7] - ldx ptr1 + ldx ptr1 ; Check data lsb to be [1..7] beq :+ cpx #7+1 bcs :+ - stx Slot + stx Slot ; Store slot .assert SER_ERR_OK = 0, error tax rts : lda #SER_ERR_INV_IOCTL - ldx #0 ; return value is char + ldx #$00 ; return value is char rts ;---------------------------------------------------------------------------- @@ -450,8 +447,7 @@ SER_IRQ: bcc Flow ; Assert flow control if buffer space low rts ; Interrupt handled (carry already set) - ; Assert flow control if buffer space too low -Flow: ldx Index +Flow: ldx Index ; Assert flow control if buffer space too low lda RtsOff sta ACIA_CMD,x sta Stopped @@ -464,26 +460,23 @@ Done: rts TryToSend: sta tmp1 ; Remember tryHard flag NextByte: - lda SendFreeCnt - cmp #$FF - beq Quit ; Bail out + lda SendFreeCnt ; Is there anything to send? This can happen if + cmp #$FF ; we got interrupted by RX while sending, and + beq Quit ; flow control was asserted. - ; Check for flow stopped -Again: lda Stopped - bne Quit ; Bail out +Again: lda Stopped ; Is flow stopped? + bne Quit ; Yes, Bail out - ; Check that ACIA is ready to send - lda ACIA_STATUS,x + lda ACIA_STATUS,x ; Check that ACIA is ready to send and #$10 - bne Send + bne Send ; It is! bit tmp1 ; Keep trying if must try hard bmi Again Quit: rts - ; Send byte and try again -Send: ldy SendHead +Send: ldy SendHead ; Get first byte to send lda SendBuf,y - sta ACIA_DATA,x + sta ACIA_DATA,x ; Send it inc SendHead inc SendFreeCnt - jmp NextByte + jmp NextByte ; And try next one