dragon-nx32: lp driver
authorAlan Cox <alan@linux.intel.com>
Thu, 28 May 2015 22:09:19 +0000 (23:09 +0100)
committerAlan Cox <alan@linux.intel.com>
Thu, 28 May 2015 22:09:19 +0000 (23:09 +0100)
Supports both the "real" printer port and also the drivewire virtual
printing.

Kernel/platform-dragon-nx32/devlpr.c
Kernel/platform-dragon-nx32/devlpr.h
Kernel/platform-dragon-nx32/drivewire.s

index a011085..9ddfae4 100644 (file)
@@ -4,51 +4,67 @@
 #include <device.h>
 #include <devlpr.h>
 
-/* 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;
 }
index 7765c18..0e078ca 100644 (file)
@@ -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
index dc8010c..35b9aac 100644 (file)
        .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