uint8_t ser_type = 2;
+tcflag_t uart0_mask[4] = {
+ _ISYS,
+ _OSYS,
+ CSIZE|CSTOPB|PARENB|PARODD|_CSYS,
+ _LSYS
+};
+
+tcflag_t uart1_mask[4] = {
+ _ISYS,
+ /* FIXME: break */
+ _OSYS,
+ /* FIXME CTS/RTS */
+ CSIZE|CBAUD|CSTOPB|PARENB|PARODD|_CSYS,
+ _LSYS,
+};
+
+tcflag_t *termios_mask[NUM_DEV_TTY + 1] = {
+ NULL,
+ uart0_mask,
+ uart1_mask
+};
+
struct s_queue ttyinq[NUM_DEV_TTY + 1] = { /* ttyinq[0] is never used */
{NULL, NULL, NULL, 0, 0, 0},
{tbuf1, tbuf1, tbuf1, TTYSIZ, 0, TTYSIZ / 2},
{tbuf2, tbuf2, tbuf2, TTYSIZ, 0, TTYSIZ / 2},
};
+uint8_t sio_r[] = {
+ 0x03, 0xC1,
+ 0x04, 0xC4,
+ 0x05, 0xEA
+};
+
+static void sio2_setup(uint8_t minor, uint8_t flags)
+{
+ struct termios *t = &ttydata[minor].termios;
+ uint8_t r;
+ /* Set bits per character */
+ sio_r[1] = 0x01 | ((t->c_cflag & CSIZE) << 2);
+ r = 0xC4;
+ if (t->c_cflag & CSTOPB)
+ r |= 0x08;
+ if (t->c_cflag & PARENB)
+ r |= 0x01;
+ if (t->c_cflag & PARODD)
+ r |= 0x02;
+ sio_r[3] = r;
+ sio_r[5] = 0x8A | ((t->c_cflag & CSIZE) << 1);
+}
+
void tty_setup(uint8_t minor, uint8_t flags)
{
- if (minor == 1) {
+ if (ser_type == 1) {
+ sio2_setup(minor, flags);
+ sio2_otir(SIO0_BASE + 2 * minor);
+ /* We need to do CTS/RTS support and baud setting on channel 2
+ yet */
+ }
+ if (ser_type == 2) {
+ struct termios *t = &ttydata[1].termios;
+ uint8_t r = t->c_cflag & CSIZE;
+ /* No CS5/CS6 CS7 must have parity enabled */
+ if (r <= CS7) {
+ t->c_cflag &= ~CSIZE;
+ t->c_cflag |= CS7|PARENB;
+ }
+ /* No CS8 parity and 2 stop bits */
+ if (r == CS8 && (t->c_cflag & PARENB))
+ t->c_cflag &= ~CSTOPB;
+ /* There is no obvious logic to this */
+ switch(t->c_cflag & (CSIZE|PARENB|PARODD|CSTOPB)) {
+ case CS7|PARENB:
+ r = 0xEB;
+ break;
+ case CS7|PARENB|PARODD:
+ r = 0xEF;
+ break;
+ case CS7|PARENB|CSTOPB:
+ r = 0xE3;
+ case CS7|PARENB|PARODD|CSTOPB:
+ r = 0xE7;
+ case CS8|CSTOPB:
+ r = 0xF3;
+ break;
+ case CS8:
+ r = 0xF7;
+ break;
+ case CS8|PARENB:
+ r = 0xFB;
+ break;
+ case CS8|PARENB|PARODD:
+ r = 0xFF;
+ break;
+ }
+ ACIA_C = r;
}
}
int tty_carrier(uint8_t minor)
{
-// uint8_t c;
- if (minor == 1) {
-// c = UART0_MSR;
-// return (c & 0x80) ? 1 : 0; /* test DCD */
- }
- return 1;
+ uint8_t c;
+ if (ser_type == 1) {
+ if (minor == 1) {
+ SIOA_C = 0;
+ c = SIOA_C;
+ } else {
+ SIOB_C = 0;
+ c = SIOB_C;
+ }
+ if (c & 0x8)
+ return 1;
+ return 0;
+ } else /* ACIA isn't wired for carrier on any bord */
+ return 1;
}
void tty_pollirq_sio(void)
{
+ static uint8_t old_ca, old_cb;
uint8_t ca, cb;
+ uint8_t progress;
+
+ /* Check for an interrupt */
+ SIOA_C = 0;
+ if (!(SIOA_C & 2))
+ return;
/* FIXME: need to process error/event interrupts as we can get
spurious characters or lines on an unused SIO floating */
do {
+ progress = 0;
SIOA_C = 0; // read register 0
ca = SIOA_C;
- if (ca & 1)
+ /* Input pending */
+ if ((ca & 1) && !fullq(&ttyinq[1])) {
+ progress = 1;
tty_inproc(1, SIOA_D);
+ }
+ /* Break */
+ if (ca & 2)
+ SIOA_C = 2 << 5;
+ /* Output pending */
if (ca & 4) {
tty_outproc(1);
SIOA_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending
}
+ /* Carrier changed */
+ if ((ca ^ old_ca) & 8) {
+ if (ca & 8)
+ tty_carrier_raise(1);
+ else
+ tty_carrier_drop(1);
+ }
SIOB_C = 0; // read register 0
cb = SIOB_C;
- if (cb & 1)
+ if ((cb & 1) && !fullq(&ttyinq[2])) {
tty_inproc(2, SIOB_D);
+ progress = 1;
+ }
if (cb & 4) {
tty_outproc(2);
SIOB_C = 5 << 3; // reg 0 CMD 5 - reset transmit interrupt pending
}
- } while((ca | cb) & 1);
+ if ((cb ^ old_cb) & 8) {
+ if (cb & 8)
+ tty_carrier_raise(2);
+ else
+ tty_carrier_drop(2);
+ }
+ } while(progress);
}
void tty_pollirq_acia(void)
;
-; SC108 Initial Support
+; SC108 Initial Support
;
- .module sc108
-
- ; exported symbols
- .globl init_hardware
- .globl interrupt_handler
- .globl _program_vectors
- .globl _kernel_flag
- .globl map_page_low
- .globl map_kernel_low
- .globl map_user_low
- .globl map_save_low
- .globl map_restore_low
- .globl _platform_doexec
- .globl _platform_reboot
- .globl _int_disabled
-
- ; exported debugging tools
- .globl _platform_monitor
- .globl outchar
-
- ; imported symbols
- .globl _ramsize
- .globl _procmem
- .globl istack_top
- .globl istack_switched_sp
- .globl kstack_top
- .globl unix_syscall_entry
- .globl outcharhex
- .globl _ser_type
-
- .globl s__COMMONMEM
- .globl l__COMMONMEM
-
- .include "kernel.def"
- .include "../kernel.def"
+ .module sc108
+
+ ; exported symbols
+ .globl init_hardware
+ .globl interrupt_handler
+ .globl _program_vectors
+ .globl _kernel_flag
+ .globl map_page_low
+ .globl map_kernel_low
+ .globl map_user_low
+ .globl map_save_low
+ .globl map_restore_low
+ .globl _platform_doexec
+ .globl _platform_reboot
+ .globl _int_disabled
+
+ ; exported debugging tools
+ .globl _platform_monitor
+ .globl outchar
+
+ ; imported symbols
+ .globl _ramsize
+ .globl _procmem
+ .globl istack_top
+ .globl istack_switched_sp
+ .globl kstack_top
+ .globl unix_syscall_entry
+ .globl outcharhex
+ .globl _ser_type
+
+ .globl s__COMMONMEM
+ .globl l__COMMONMEM
+
+ .include "kernel.def"
+ .include "../kernel.def"
;
; so we can recover the discard memory into the buffer pool
;
- .globl _bufpool
- .area _BUFFERS
+ .globl _bufpool
+ .area _BUFFERS
_bufpool:
- .ds BUFSIZE * NBUFS
+ .ds BUFSIZE * NBUFS
; -----------------------------------------------------------------------------
;
; usual Z80 setup.
;
; -----------------------------------------------------------------------------
- .area _COMMONMEM
+ .area _COMMONMEM
_platform_monitor:
; Reboot ends up back in the monitor
_platform_reboot:
- xor a
- out (0x38), a ; ROM appears low
- rst 0 ; bang
+ xor a
+ out (0x38), a ; ROM appears low
+ rst 0 ; bang
_int_disabled:
- .db 1
+ .db 1
; -----------------------------------------------------------------------------
;
; -----------------------------------------------------------------------------
banknum:
- .byte 0x81 ; copied into far bank then set to 1
+ .byte 0x81 ; copied into far bank then set to 1
; -----------------------------------------------------------------------------
; All of discard gets reclaimed when init is run
; Discard must be above 0x8000 as we need some of it when the ROM
; is paged in during init_hardware
; -----------------------------------------------------------------------------
- .area _DISCARD
+ .area _DISCARD
init_hardware:
- ld hl, #128
- ld (_ramsize), hl
- ld hl,#64
- ld (_procmem), hl
-
- ld hl,#s__COMMONMEM
- ld ix,#s__COMMONMEM
- ld bc,#l__COMMONMEM
- xor a ; Kernel + ROM
- out (0x38),a ;
-
- ld de,#0x8000 ; bank 0 to bank 1 (ROM in)
- xor a ; return to bank 0
- call 0x7FFD ; ROM helper vector
-
- ld a,#0x01 ; bank 0 ROM out
- out (0x38),a
- ld (banknum),a ; and correct page
-
- ; We now have our common in place. We can do the rest ourselves
-
- ; Put the low stubs into place in the kernel
- ld hl,#stubs_low
- ld de,#0
- ld bc,#0x68
- ldir
- ld hl,#stubs_low
- ld ix,#0
- ld bc,#0x68
- call ldir_to_user
-
- ; Play guess the serial port
- ld bc,#0x80
- ; If writing to 0x80 changes the data we see on an input then
- ; it's most likely an SIO and not the 68B50
- out (c),b
- in d,(c)
- inc b
- out (c),b
- in a,(c)
- sub d
-;;FIXME jr z, is_sio
-
- ; We have however pooped on the 68B50 setup so put it back into
- ; a sensible state.
- ld a,#0x03
- out (c),a
- in a,(c)
- or a
- jr z, not_acia_either
- ld a, #ACIA_RTS_LOW_A
- out (c),a ; Initialise ACIA
- ld a,#2
- ld (_ser_type),a
- im 1
- ret
-
- ;
- ; Doomed I say .... doomed, we're all doomed
- ;
- ; At least until RC2014 grows a nice keyboard/display card!
- ;
+ ld hl, #128
+ ld (_ramsize), hl
+ ld hl,#64
+ ld (_procmem), hl
+
+ ld hl,#s__COMMONMEM
+ ld ix,#s__COMMONMEM
+ ld bc,#l__COMMONMEM
+ xor a ; Kernel + ROM
+ out (0x38),a ;
+
+ ld de,#0x8000 ; bank 0 to bank 1 (ROM in)
+ xor a ; return to bank 0
+ call 0x7FFD ; ROM helper vector
+
+ ld a,#0x01 ; bank 0 ROM out
+ out (0x38),a
+ ld (banknum),a ; and correct page
+
+ ; We now have our common in place. We can do the rest ourselves
+
+ ; Put the low stubs into place in the kernel
+ ld hl,#stubs_low
+ ld de,#0
+ ld bc,#0x68
+ ldir
+ ld hl,#stubs_low
+ ld ix,#0
+ ld bc,#0x68
+ call ldir_to_user
+
+ ; Play guess the serial port
+ ; This needs doing better. We might be fooled by floating flow
+ ; control lines as the SC104 does expose flow control. FIXME
+ in a,(SIOA_C)
+ and #0x2C
+ cp #0x2C
+ ; CTS and DCD should be high as they are not wired
+ jr nz, try_acia
+
+ ; Repeat the check on SIO B
+ in a,(SIOB_C)
+ and #0x2C
+ cp #0x2C
+ jr z, is_sio
+try_acia:
+ ;
+ ; Look for an ACIA
+ ;
+ ld a,#ACIA_RESET
+ out (ACIA_C),a
+ ; TX should now have gone
+ in a,(ACIA_C)
+ bit 1,a
+ jr z, not_acia_either
+ ; Set up the ACIA
+
+ ld a, #ACIA_RTS_LOW_A
+ out (ACIA_C),a ; Initialise ACIA
+ ld a,#2
+ ld (_ser_type),a
+ jp serial_up
+
+ ;
+ ; Doomed I say .... doomed, we're all doomed
+ ;
+ ; At least until RC2014 grows a nice keyboard/display card!
+ ;
not_acia_either:
- xor a
- ld (_ser_type),a
- ret
-
-is_sio: ld a,b
- ld (_ser_type),a
-
-init_partial_uart:
- ld a,#0x00
- out (SIOA_C),a
- ld a,#0x18
- out (SIOA_C),a
-
- ld a,#0x04
- out (SIOA_C),a
- ld a,#0xC4
- out (SIOA_C),a
-
- ld a,#0x01
- out (SIOA_C),a
- ld a,#0x18;A? ; Receive int mode 11, tx int enable (was $18)
- out (SIOA_C),a
-
- ld a,#0x03
- out (SIOA_C),a
- ld a,#0xE1
- out (SIOA_C),a
-
-RTS_LOW .EQU 0xEA
-
- ld a,#0x05
- out (SIOA_C),a
- ld a,#RTS_LOW
- out (SIOA_C),a
-
- ld a,#0x00
- out (SIOB_C),a
- ld a,#0x18
- out (SIOB_C),a
-
- ld a,#0x04
- out (SIOB_C),a
- ld a,#0xC4
- out (SIOB_C),a
-
- ld a,#0x01
- out (SIOB_C),a
- ld a, #0x18;A? ; Receive int mode 11, tx int enable (was $18)
- out (SIOB_C),a
-
- ld a,#0x03
- out (SIOB_C),a
- ld a,#0xE1
- out (SIOB_C),a
-
- ld a,#0x05
- out (SIOB_C),a
- ld a,#RTS_LOW
- out (SIOB_C),a
-
- im 1 ; set CPU interrupt mode
+ xor a
+ ld (_ser_type),a
+ jp serial_up
+;
+; We have an SIO so do the required SIO hdance
+;
+is_sio: ld a,b
+ ld (_ser_type),a
+
+ ld hl,#sio_setup
+ ld bc,#0xA00 + SIOA_C ; 10 bytes to SIOA_C
+ otir
+ ld hl,#sio_setup
+ ld bc,#0x0A00 + SIOB_C ; and to SIOB_C
+ otir
+
+serial_up:
+ im 1 ; set CPU interrupt mode
+ ret
+
+RTS_LOW .EQU 0xEA
+
+sio_setup:
+ .byte 0x00
+ .byte 0x18 ; Reset
+ .byte 0x04
+ .byte 0xC4
+ .byte 0x01
+ .byte 0x18
+ .byte 0x03
+ .byte 0xE1
+ .byte 0x05
+ .byte RTS_LOW
- ret
;
; Our memory setup is weird and common is kind of meaningless here
_program_vectors:
ret
+
+;
+; A little SIO helper
+;
+ .globl _sio_r
+ .globl _sio2_otir
+
+_sio2_otir:
+ ld b,#0x06
+ ld c,l
+ ld hl,#_sio_r
+ otir
+ ret
;
; outchar: Wait for UART TX idle, then print the char in A
; destroys: AF