From f4a192e9b9cdbef498539e3b660385affc613487 Mon Sep 17 00:00:00 2001 From: Alan Cox Date: Thu, 28 May 2015 23:09:19 +0100 Subject: [PATCH] dragon-nx32: lp driver Supports both the "real" printer port and also the drivewire virtual printing. --- Kernel/platform-dragon-nx32/devlpr.c | 78 +++++++++++++++---------- Kernel/platform-dragon-nx32/devlpr.h | 9 ++- Kernel/platform-dragon-nx32/drivewire.s | 67 +++++++++++++++++++++ 3 files changed, 120 insertions(+), 34 deletions(-) diff --git a/Kernel/platform-dragon-nx32/devlpr.c b/Kernel/platform-dragon-nx32/devlpr.c index a0110858..9ddfae4b 100644 --- a/Kernel/platform-dragon-nx32/devlpr.c +++ b/Kernel/platform-dragon-nx32/devlpr.c @@ -4,51 +4,67 @@ #include #include -/* random test places */ -uint8_t *lpstat = (uint8_t *)0xFF00; -uint8_t *lpdata = (uint8_t *)0xFF01; +volatile uint8_t * const pia0b = (uint8_t *)0xFF02; +volatile uint8_t * const pia1a = (uint8_t *)0xFF20; +volatile uint8_t * const pia1b = (uint8_t *)0xFF22; int lpr_open(uint8_t minor, uint16_t flag) { - minor; - flag; // shut up compiler - return 0; + if (minor < 2) + return 0; + udata.u_error = ENODEV; + return -1; } int lpr_close(uint8_t minor) { - minor; // shut up compiler + if (minor == 1) + dw_lpr_close(); return 0; } -int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +static int iopoll(int sofar) { - int c = udata.u_count; - char *p = udata.u_base; - uint16_t ct; - - minor; - rawflag; - flag; // shut up compiler + /* Ought to be a core helper for this lot ? */ + if (need_resched()) + _sched_yield(); + if (udata.u_cursig || udata.u_ptab->p_pending) { + if (sofar) + return sofar; + udata.u_error = EINTR; + return -1; + } + return 0; +} - while (c-- > 0) { - ct = 0; +int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag) +{ + uint8_t *p = udata.u_base; + uint8_t *pe = p + udata.u_count; + int n; + irqflags_t irq; - /* Try and balance polling and sleeping */ - while (*lpstat & 2) { - ct++; - if (ct == 10000) { - udata.u_ptab->p_timeout = 3; - if (psleep_flags(NULL, flag)) { - if (udata.u_count) - udata.u_error = 0; - return udata.u_count; - } - ct = 0; + if (minor == 1) { + while (p < pe) { + if ((n = iopoll(pe - p)) != 0) + return n; + dw_lpr(ugetc(p++)); + } + } else { + while (p < pe) { + /* Printer busy ? */ + while (*pia1b & 1) { + if ((n = iopoll(pe - p)) != 0) + return n; } + /* The Dragon shares the printer and keyboard scan + lines. Make sure we don't collide */ + irq = di(); + *pia0b = ugetc(p++); + *pia1a |= 0x02; /* Strobe */ + *pia1a &= ~0x02; + irqrestore(irq); } - /* Data */ - *lpdata = ugetc(p++); } - return udata.u_count; + return pe - p; } diff --git a/Kernel/platform-dragon-nx32/devlpr.h b/Kernel/platform-dragon-nx32/devlpr.h index 7765c187..0e078ca6 100644 --- a/Kernel/platform-dragon-nx32/devlpr.h +++ b/Kernel/platform-dragon-nx32/devlpr.h @@ -1,8 +1,11 @@ #ifndef __DEVLPR_DOT_H__ #define __DEVLPR_DOT_H__ -int lpr_open(uint8_t minor, uint16_t flag); -int lpr_close(uint8_t minor); -int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag); +extern int lpr_open(uint8_t minor, uint16_t flag); +extern int lpr_close(uint8_t minor); +extern int lpr_write(uint8_t minor, uint8_t rawflag, uint8_t flag); + +extern void dw_lpr(uint8_t c); +extern void dw_lpr_close(void); #endif diff --git a/Kernel/platform-dragon-nx32/drivewire.s b/Kernel/platform-dragon-nx32/drivewire.s index dc8010cb..35b9aac6 100644 --- a/Kernel/platform-dragon-nx32/drivewire.s +++ b/Kernel/platform-dragon-nx32/drivewire.s @@ -10,6 +10,11 @@ .globl _dw_operation .globl _dw_reset + .globl _dw_lpr + .globl _dw_lpr_close + .globl _dw_rtc_read + + ; imported .globl map_process_a .globl map_kernel @@ -129,6 +134,68 @@ ReRead pshs a ReadErr comb ; set carry bit ReadEx puls d,x,y,pc + .area .text +; +; Virtual devices on DriveWire +; +; Line printer +; RTC +; Virtual serial ??? +; +; +; dw_lpr(uint8_t c) +; +; Print a byte to drive wire printers +; +; B holds the byte. Call with interrupts off +; +_dw_lpr: + pshs y + stb lprb2 + ldx #lprb + ldy #2 +dwop: + jsr DWWrite + puls y,pc + +; +; dw_lpr_close(void) +; +; Close the printer device +; +_dw_lpr_close: + pshs y + ldx #lprb3 + ldy #1 + bra dwop + +; +; uint8_t dw_rtc_read(uint8_t *p) +; +_dw_rtc_read: + pshs y + ldy #2 + pshs x + ldx #lprrtw + jsr DWWrite + puls x + ldy #6 + clra + jsr DWRead + clrb + sbcb #0 + bra dwop + + .area .data + +lprb: .db 0x50 ; print char +lprb2: .db 0x00 ; filled in with byte to send +lprb3: .db 0x46 ; printer flush +lprrtw: .db 0x23 ; request for time + + .area .common + + ; Used by DWRead and DWWrite IntMasks equ $50 NOINTMASK equ 1 -- 2.34.1