118 lines
4 KiB
C
118 lines
4 KiB
C
// Does opening one built-in SCC port survive the OTHER one?
|
|
//
|
|
// The Zilog 8530 in a IIgs carries both built-in ports: channel A is the
|
|
// printer port (where AppleTalk lives), channel B is the modem port. WR9's
|
|
// reset command is chip-wide, so an open that issues the force-hardware-reset
|
|
// (0xC0) takes the other channel down with it -- registers, FIFOs, baud
|
|
// generator and, decisively for this probe, the transmit enable in WR5.
|
|
//
|
|
// So: bring channel A up through the real HAL, hand it back (the IIgs close
|
|
// deliberately leaves the chip configured), then open channel B -- the
|
|
// operation under test -- and finally poke a byte STRAIGHT into channel A's
|
|
// data register, bypassing the library. If channel A survived, its transmitter
|
|
// is still enabled and the byte reaches the host peer. If the open reset the
|
|
// whole chip, WR5 went to zero, the transmitter is off, and nothing arrives.
|
|
//
|
|
// Run headless by scripts/verify-iigs-serial.sh, which reads the bytes off a
|
|
// socket and the progress flags out of the SHR framebuffer.
|
|
|
|
#include <joey/serial.h>
|
|
|
|
// SHR framebuffer, used purely as a mailbox the emulator harness can read: the
|
|
// probe never calls jlInit, so nothing else is drawing here.
|
|
#define SHR_BASE ((volatile uint8_t *)0x00E12000L)
|
|
#define MB_SIGNATURE_0 0
|
|
#define MB_SIGNATURE_1 1
|
|
#define MB_PRINTER_OPEN 2
|
|
#define MB_PRINTER_WROTE 3
|
|
#define MB_MODEM_OPEN 4
|
|
#define MB_DIRECT_WROTE 5
|
|
#define MB_SIG_VALUE_0 0xA5u
|
|
#define MB_SIG_VALUE_1 0x5Au
|
|
|
|
// Channel A (printer port) registers -- the channel this probe checks for
|
|
// survival. Deliberately spelled out here rather than shared with the HAL: the
|
|
// point is to look at the hardware independently of the code under test.
|
|
#define SCC_A_CTRL ((volatile uint8_t *)0x00C039L)
|
|
#define SCC_A_DATA ((volatile uint8_t *)0x00C03BL)
|
|
#define SCC_RR0_TX_EMPTY 0x04u
|
|
|
|
// Bounded so a dead transmitter reports "nothing arrived" instead of hanging
|
|
// the machine and stalling the gate.
|
|
#define TX_SPIN_LIMIT 200000ul
|
|
|
|
static void mailbox(uint16_t slot, uint8_t value);
|
|
static bool pokeChannelA(uint8_t byte);
|
|
|
|
|
|
static void mailbox(uint16_t slot, uint8_t value) {
|
|
SHR_BASE[slot] = value;
|
|
}
|
|
|
|
|
|
// Write one byte to channel A without going through the HAL. Returns false if
|
|
// the transmitter never reports empty, which is exactly what a wiped channel
|
|
// looks like.
|
|
static bool pokeChannelA(uint8_t byte) {
|
|
uint32_t spin;
|
|
|
|
for (spin = 0; spin < TX_SPIN_LIMIT; spin++) {
|
|
if ((*SCC_A_CTRL & SCC_RR0_TX_EMPTY) != 0u) {
|
|
*SCC_A_DATA = byte;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
int main(void) {
|
|
jlSerialConfigT cfg;
|
|
uint16_t i;
|
|
|
|
mailbox(MB_SIGNATURE_0, MB_SIG_VALUE_0);
|
|
mailbox(MB_SIGNATURE_1, MB_SIG_VALUE_1);
|
|
|
|
cfg.baud = 9600u;
|
|
cfg.dataBits = 8u;
|
|
cfg.stopBits = 1u;
|
|
cfg.parity = JL_SERIAL_PARITY_NONE;
|
|
cfg.flow = JL_SERIAL_FLOW_NONE;
|
|
cfg.unit = 0u;
|
|
|
|
// 1. Bring channel A (printer) up through the HAL and prove it transmits.
|
|
if (!jlSerialOpen(JL_SERIAL_PRINTER, &cfg)) {
|
|
return 1;
|
|
}
|
|
mailbox(MB_PRINTER_OPEN, 1u);
|
|
if (jlSerialWrite((const uint8_t *)"A1\r\n", 4u) == 4u) {
|
|
mailbox(MB_PRINTER_WROTE, 1u);
|
|
}
|
|
jlSerialFlush();
|
|
jlSerialClose();
|
|
|
|
// 2. Open channel B (modem). THIS is the operation under test: with the
|
|
// old chip-wide 0xC0 reset it also wipes channel A.
|
|
if (!jlSerialOpen(JL_SERIAL_MODEM, &cfg)) {
|
|
return 1;
|
|
}
|
|
mailbox(MB_MODEM_OPEN, 1u);
|
|
|
|
// 3. Channel A is untouched by the library from here on. Poke it directly:
|
|
// the byte only leaves the chip if channel A's transmitter is still on.
|
|
if (pokeChannelA('A')) {
|
|
mailbox(MB_DIRECT_WROTE, 1u);
|
|
}
|
|
(void)pokeChannelA('2');
|
|
(void)pokeChannelA('\r');
|
|
(void)pokeChannelA('\n');
|
|
|
|
// Hold the machine still so the harness can read the mailbox, and give the
|
|
// last byte time to clock out at 9600 baud.
|
|
for (i = 0; i < 60000u; i++) {
|
|
(void)*SCC_A_CTRL;
|
|
}
|
|
jlSerialClose();
|
|
for (;;) {
|
|
}
|
|
}
|