/* * abcpun80.c * * Emulate a PUN80 network card */ #include "compiler.h" #include "fw.h" #include "io.h" #include "abcio.h" #define PUN_IOSEL 60 #define PUN_TTY_CHAN 1 #if PUN_TTY_CHAN >= TTY_CHANNELS # error "PUN_TTY_CHAN out of range" #endif #define PUN_DATA TTY_DATA(PUN_TTY_CHAN) #define PUN_WATERCTL TTY_WATERCTL(PUN_TTY_CHAN) #define PUN_STATUS TTY_STATUS(PUN_TTY_CHAN) #define PUN_IRQEN TTY_IRQEN(PUN_TTY_CHAN) #define PUN_IRQPOL TTY_IRQPOL(PUN_TTY_CHAN) #define PUN_IRQ TTY_NIRQ(PUN_TTY_CHAN) #define PUN_IRQ_MASK (TTY_STATUS_TX_FULL|TTY_STATUS_RX_EMPTY|\ TTY_STATUS_USB_CONFIG) static struct abc_dev pun80_iodev; static __hot void pun80_refresh_input(bool advance); IRQHANDLER(tty,PUN_TTY_CHAN) { pun80_refresh_input(false); } /* * Convert to FT232H-compatible status codes, and advance * the receive FIFO if applicable. */ static __hot void pun80_refresh_input(bool advance) { static bool data_loaded; unsigned int status; unsigned int pun80_status; status = PUN_STATUS; if (!data_loaded || advance) { data_loaded = !(status & TTY_STATUS_RX_EMPTY); if (data_loaded) { abc_set_inp_default(&pun80_iodev, PUN_DATA); status = PUN_STATUS; } } pun80_status = ~15; if (status & TTY_STATUS_USB_CONFIG) pun80_status |= 8; if (!(status & TTY_STATUS_TX_FULL)) pun80_status |= 2; if (data_loaded) pun80_status |= 1; abc_set_inp_status(&pun80_iodev, pun80_status); PUN_IRQPOL = status; } ABC_CALLBACK(pun80_callback_out) { PUN_DATA = data; pun80_refresh_input(false); } ABC_CALLBACK(pun80_callback_inp) { pun80_refresh_input(true); } /* The "flush" command in FT232H (C1#) is not needed with our USB stack */ static struct abc_dev pun80_iodev = { .callback_mask = (1 << 0)|(1 << 8), .inp_en = 3, .status_first_out_mask = ~0, .status_first_inp_mask = ~0, .callback_out[0] = pun80_callback_out, .callback_inp[0] = pun80_callback_inp }; void pun80_init(void) { mask_irq(PUN_IRQ); PUN_IRQEN = PUN_IRQ_MASK; pun80_refresh_input(false); abc_register(&pun80_iodev, PUN_IOSEL); unmask_irq(PUN_IRQ); }