| Sharp X68000 RS-232C receive: own the Z8530 SCC channel A RX interrupt.
|
| RSDRV.SYS's receive ring is ~64 bytes -- far too small for a binary protocol
| whose client can be busy blitting for >100 ms -- so instead of draining it by
| polling, serial.c steals the SCC's channel A RX vectors and points them here:
| every received byte lands straight in the port's big soft ring with no RSDRV
| involvement at all.  This is the same take-over-the-hardware model every other
| JoeyLib target uses (the DOS UART IRQ ring, the 8-bit ACIA rings).
|
| Entered DIRECTLY from the 68000 exception vector the SCC supplies at IACK
| (WR2 base | %110x for channel A RX -- serial.c reads RR2 and computes it), so
| these are raw interrupt handlers: every register touched is saved, and both
| return with RTE.  Unlike the tick hook there is NO chaining -- the byte is
| consumed here, so running RSDRV's handler afterwards would be wrong.
|
| Ring protocol (single consumer, single producer): the mainline reads gX68kRxHead,
| this ISR writes gX68kRxTail; the byte is stored BEFORE the tail moves, and the
| 68000 is strictly in-order, so no further interlock is needed.  A full ring
| drops the byte -- the frame CRC upstream turns that into a clean retransmit-less
| drop rather than corruption.
|
| GAS m68k syntax, ELF target -- symbols carry NO leading underscore.

                .equ    SCC_A_CTRL, 0xE98005    | channel A command/status
                .equ    SCC_A_DATA, 0xE98007    | channel A data (direct, no pointer)
                .equ    RING_MASK,  4095        | X68K_RX_RING_CAP - 1 (power of two)

                .text
                .even
                .globl  x68kSccRxIsr
                .globl  x68kSccSpIsr

| Channel A "receive character available".
x68kSccRxIsr:
                movem.l %d0-%d2/%a0,-(%sp)
                move.b  SCC_A_DATA,%d0          | the received byte
                move.w  gX68kRxTail,%d1
                move.w  %d1,%d2
                addq.w  #1,%d2
                andi.w  #RING_MASK,%d2          | next tail
                cmp.w   gX68kRxHead,%d2
                beq.s   rxFull                  | ring full: drop, CRC upstream recovers
                lea     gX68kRxRing,%a0
                move.b  %d0,(%a0,%d1.w)         | store BEFORE publishing the new tail
                move.w  %d2,gX68kRxTail
rxFull:         move.b  #0x38,SCC_A_CTRL        | WR0: reset highest IUS
                movem.l (%sp)+,%d0-%d2/%a0
                rte

| Channel A "special receive condition" (overrun / framing error).  The byte is
| suspect, so unlatch and discard it, clear the error, and drop the IUS -- the
| frame CRC turns the loss into a clean drop.
x68kSccSpIsr:
                move.l  %d0,-(%sp)
                move.b  SCC_A_DATA,%d0          | unlatch the offending byte
                move.b  #0x30,SCC_A_CTRL        | WR0: error reset
                move.b  #0x38,SCC_A_CTRL        | WR0: reset highest IUS
                move.l  (%sp)+,%d0
                rte
