@@ 0,0 1,803 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+#include "../port/error.h"
+
+#include <libg.h>
+#include <gnot.h>
+
+#include "devtab.h"
+
+#define GSHORT(p) (((p)[0]<<0) | ((p)[1]<<8))
+#define GLONG(p) ((GSHORT(p)<<0) | (GSHORT(p+2)<<16))
+#define PSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8))
+#define PLONG(p, v) (PSHORT(p, (v)), PSHORT(p+2, (v)>>16))
+
+#define ISKVA(va) ((ulong)(va)&KZERO)
+
+typedef struct Lbpfifo {
+ unsigned long fifo;
+ unsigned short csr;
+ unsigned short hblank;
+} Lbpfifo;
+
+enum Csrin {
+ BINT = 0x0001, VEND = 0x0002, EFL = 0x0004, HFL = 0x0008,
+ FFL = 0x0010, VSTARTL = 0x0020,
+ PPRDYL = 0x0100, RDY = 0x0200, SBSY = 0x0400, SCIN = 0x0800,
+ SCLKIN = 0x1000, VSREQ = 0x2000,
+};
+
+enum Csrout {
+ GO = 0x0001, EOL = 0x0002, EFINTEN = 0x0004, HFINTEN = 0x0008,
+ VCLRL = 0x0010, FOURHDPI = 0x0020,
+ CPRDYL = 0x0100, PRNT = 0x0200, CBSY = 0x0400, SC = 0x0800,
+ SCLK = 0x1000, VSYNC = 0x2000,
+};
+
+#define DPRINT kprint
+
+#define LBPDEV ((Lbpfifo *)&PORT[56])
+
+static ushort csrwval;
+
+#define CSRW(val) (dev->csr = csrwval = (val))
+#define CSRSET(val) (dev->csr = csrwval |= (val))
+#define CSRCLR(val) (dev->csr = csrwval &= ~(val))
+
+#define CMDW(val) (csrwval &= ~(CBSY|SC|SCLK), CSRSET(val))
+
+enum {
+ Inited = 1,
+ Cmdlocked=2,
+ Bitlocked=4,
+ Bitmapped=8
+};
+
+typedef struct Lbp {
+ int fifosize;
+ ulong flags;
+ Lock mlock; /* monitor proc active */
+ Rendez ready; /* to wake monitor proc */
+ QLock cmdlock; /* to send commands */
+ int cmdreply;
+ QLock pagelock; /* to print */
+ Rendez printing; /* to wake printing proc */
+ Rectangle rect; /* page size */
+ ulong *left, lmask, rmask;
+ int nhblank, width, nvblank, nlines;
+ Segment *s; /* bitmap may not span segments (BUG) */
+ Page *xmap[256];
+ Page **x, **xend;
+ KMap *kmap;
+ int ihl, maxhl, lcount;
+ long startclicks, stopclicks;
+} Lbp;
+
+enum Lbpsize {
+ NHBLANK = 255, NVBLANK = 84,
+ LBPXMAX = 2424, LBPYMAX = 3262, LBPDOTS = 300,
+};
+
+typedef struct Lbpconf {
+ int nhblank, nvblank, xmax, ymax, res;
+} Lbpconf;
+
+static Lbpconf lbpiconf = {
+ NHBLANK, NVBLANK, LBPXMAX, LBPYMAX, LBPDOTS,
+};
+static Lbpconf lbpconf;
+static Lbp lbp;
+static int cprint0, cprint1;
+static ulong pingval;
+
+enum {
+ Qdir, Qconf, Qdcmd, Qrcmd, Qmon, Qping, Qbit, Qpage
+};
+
+Dirtab lbpdir[]={
+ "conf", {Qconf}, sizeof(Lbpconf), 0666,
+ "dcmd", {Qdcmd}, 1, 0666,
+ "rcmd", {Qrcmd}, 1, 0666,
+ "mon", {Qmon}, 0, 0666,
+ "ping", {Qping}, 0, 0666,
+ "bit", {Qbit}, 0, 0666,
+ "page", {Qpage}, 0, 0666
+};
+#define NLBP (sizeof lbpdir/sizeof(Dirtab))
+
+static int lbpcmd(int);
+static long lbppage(Point, GBitmap *, Rectangle);
+static void lbpmap(Point, GBitmap *, Rectangle);
+static Page * addr2page(ulong);
+static void validbitmap(GBitmap *);
+static int fillfifo(int);
+static int lbpintr(void);
+
+static void
+lbpsetconf(Lbpconf *cp)
+{
+ lbpconf = *cp;
+ lbp.rect.max.x = lbpconf.xmax;
+ lbp.rect.max.y = lbpconf.ymax;
+ return;
+}
+
+void
+lbpreset(void)
+{
+ lbpsetconf(&lbpiconf);
+}
+
+void
+lbpinit(void)
+{}
+
+Chan *
+lbpattach(char *param)
+{
+ Lbpfifo *dev = LBPDEV;
+ int i, hsize=0, fsize=0;
+
+ addportintr(lbpintr);
+ if(lbp.fifosize<=0){
+ CSRCLR(VCLRL);
+ CSRSET(VCLRL);
+ for(i=0; i<20000; i+=4){
+ dev->fifo = 0;
+ if(!hsize && (dev->csr&HFL) == 0)
+ hsize = i+4;
+ if((dev->csr&FFL) == 0){
+ fsize = i+4;
+ break;
+ }
+ }
+ /*pprint("lbpattach: hsize=%d, fsize=%d\n", hsize, fsize);*/
+ lbp.fifosize = fsize;
+ }
+ return devattach('l', param);
+}
+
+Chan *
+lbpclone(Chan *c, Chan *nc)
+{
+ return devclone(c, nc);
+}
+
+int
+lbpwalk(Chan *c, char *name)
+{
+ return devwalk(c, name, lbpdir, NLBP, devgen);
+}
+
+void
+lbpstat(Chan *c, char *db)
+{
+ devstat(c, db, lbpdir, NLBP, devgen);
+}
+
+Chan *
+lbpopen(Chan *c, int omode)
+{
+ switch ((int)(c->qid.path & ~CHDIR)) {
+ /*case Qcmd:*/
+ case Qbit:
+ case Qpage:
+ if (!(lbp.flags & Inited)) {
+ lbp.cmdreply = lbpcmd(0x40);
+ lbp.flags |= Inited;
+ }
+ break;
+ }
+ return devopen(c, omode, lbpdir, NLBP, devgen);
+}
+
+void
+lbpcreate(Chan *c, char *name, int omode, ulong perm)
+{
+ USED(c, name, omode, perm);
+ error(Eperm);
+}
+
+void
+lbpclose(Chan *c)
+{
+ USED(c);
+}
+
+long
+lbpread(Chan *c, void *va, long n, ulong offset)
+{
+ uchar *a = (uchar *)va;
+ if (n == 0)
+ return 0;
+ switch ((int)(c->qid.path & ~CHDIR)) {
+ case Qdir:
+ return devdirread(c, va, n, lbpdir, NLBP, devgen);
+ case Qconf:
+ if (offset >= 20)
+ return 0;
+ if (n < 20)
+ error(Etoosmall);
+ PLONG(&a[ 0], lbpconf.nhblank);
+ PLONG(&a[ 4], lbpconf.nvblank);
+ PLONG(&a[ 8], lbpconf.xmax);
+ PLONG(&a[12], lbpconf.ymax);
+ PLONG(&a[16], lbpconf.res);
+ n = 20;
+ break;
+ case Qdcmd:
+ *a = cprint1;
+ n = 1;
+ break;
+ case Qrcmd:
+ if (lbp.cmdreply > 0)
+ *a = lbp.cmdreply, n = 1;
+ else
+ n = 0;
+ break;
+ case Qmon:
+ if (canlock(&lbp.mlock)) {
+ sleep(&lbp.ready, return0, 0);
+ unlock(&lbp.mlock);
+ } else
+ error(Einuse);
+ n = 0;
+ break;
+ case Qping:
+ if (n != sizeof(ulong))
+ n = 0;
+ else
+ *(ulong *)a = pingval;
+ break;
+ case Qbit:
+ case Qpage:
+ n = 0;
+ break;
+ }
+ return n;
+}
+
+#define OKRECT(r) ((r).min.x<(r).max.x && (r).min.y<(r).max.y)
+#define PTINRECT(p, r) ((r).min.x<=(p).x && (r).min.y<=(p).y && \
+ (p).x<=(r).max.x && (p).y<=(r).max.y)
+#define RINRECT(r, s) (PTINRECT((r).min, s) && PTINRECT((r).max, s))
+
+long
+lbpwrite(Chan *c, void *va, long n, ulong offset)
+{
+ uchar *a = (uchar *)va;
+ extern GBitmap *id2bit(int);
+ Point p; GBitmap *bp; Rectangle r;
+ Lbpconf tc;
+ int k, m = 0;
+ if (n == 0)
+ return 0;
+ switch ((int)c->qid.path) {
+ case Qconf:
+ if (offset >= 20)
+ return 0;
+ if (n < 20)
+ error(Etoosmall);
+ tc.nhblank = GLONG(&a[ 0]);
+ tc.nvblank = GLONG(&a[ 4]);
+ tc.xmax = GLONG(&a[ 8]);
+ tc.ymax = GLONG(&a[12]);
+ tc.res = GLONG(&a[16]);
+ lbpsetconf(&tc);
+ m = 20;
+ break;
+ case Qdcmd:
+ cprint1 = *a ? PRNT : 0;
+ m = 1;
+ break;
+ case Qrcmd:
+ lbp.cmdreply = lbpcmd(*a);
+ m = 1;
+ break;
+ case Qmon:
+ wakeup(&lbp.ready);
+ m = 0;
+ break;
+ case Qping:
+ if (n != sizeof(ulong))
+ m = 0;
+ else {
+ Lbpfifo *dev = LBPDEV;
+ dev->fifo = *(ulong *)a;
+ pingval = dev->fifo;
+ m = sizeof(ulong);
+ }
+ break;
+ case Qbit:
+ case Qpage:
+ if (n != 28)
+ error(Ebadarg);
+ p.x = GLONG(&a[0]);
+ p.y = GLONG(&a[4]);
+ if (c->qid.path == Qbit)
+ bp = id2bit(GLONG(&a[8]));
+ else {
+ bp = (GBitmap *)GLONG(&a[8]);
+ validbitmap(bp);
+ }
+ r.min.x = GLONG(&a[12]);
+ r.min.y = GLONG(&a[16]);
+ r.max.x = GLONG(&a[20]);
+ r.max.y = GLONG(&a[24]);
+ DPRINT("lbpwrite: ckpage...");
+ if ((k = lbp.rect.min.x - p.x) > 0)
+ r.min.x += k, p.x += k;
+ if ((k = lbp.rect.min.y - p.y) > 0)
+ r.min.y += k, p.y += k;
+ if ((k = Dx(r) + p.x - lbp.rect.max.x) > 0)
+ r.max.x -= k;
+ if ((k = Dy(r) + p.y - lbp.rect.max.y) > 0)
+ r.max.y -= k;
+ if (!OKRECT(r) || !RINRECT(r, bp->r))
+ error(Ebadblt);
+ DPRINT("OK\n");
+ m = lbppage(p, bp, r);
+ /*pprint("lbpwrite: %d clicks\n", m);*/
+ break;
+ default:
+ panic("lbpwrite");
+ }
+ return m;
+}
+
+void
+lbpremove(Chan *c)
+{
+ USED(c);
+ error(Eperm);
+}
+
+void
+lbpwstat(Chan *c, char *dp)
+{
+ USED(c, dp);
+ error(Eperm);
+}
+
+static short poot, hoot;
+#define MICROSECOND (poot=0, hoot=0); USED(poot, hoot)
+#define TLIMIT 0x3fffff
+
+static void
+lbpwait(int set, int clear, long timeout)
+{
+ Lbpfifo *dev = LBPDEV;
+ int status; long i=0;
+
+ if(timeout <= 0)
+ timeout = TLIMIT;
+ timeout += m->ticks;
+ do{
+ status = dev->csr;
+ if((status & set) == set && (status & clear) == 0){
+ DPRINT("OK lbpwait(pid=%d,i=%d)...", u->p->pid, i);
+ return;
+ }
+ if((i++ % 32768) == 0)
+ DPRINT("lbpwait(pid=%d,i=%d)...", u->p->pid, i-1);
+ sched();
+ if(u->p->notepending){
+ u->p->notepending = 0;
+ DPRINT("intr lbpwait(pid=%d,i=%d)\n", u->p->pid, i);
+ error(Eintr);
+ }
+ }while(m->ticks < timeout);
+ DPRINT("timeout lbpwait(pid=%d,i=%d)\n", u->p->pid, i);
+ error(Eio);
+}
+
+static int
+lbpcmd(int cmd)
+{
+ Lbpfifo *dev = LBPDEV;
+ int mask = 0x80, status;
+
+ qlock(&lbp.cmdlock);
+ if (waserror()) {
+ qunlock(&lbp.cmdlock);
+ nexterror();
+ }
+ lbpwait(0, (PPRDYL|SBSY|SC|SCLK), 600);
+
+ CMDW(CBSY); /* cbsy asserted */
+ do {
+ if (cmd & mask) {
+ CMDW(CBSY|SCLK|SC); /* clock up, data 1 */
+ MICROSECOND;
+ CMDW(CBSY|SC); /* clock down, data 1 */
+ MICROSECOND;
+ } else {
+ CMDW(CBSY|SCLK); /* clock up, data 0 */
+ MICROSECOND;
+ CMDW(CBSY); /* clock down, data 0 */
+ MICROSECOND;
+ }
+ } while (mask >>= 1);
+ CMDW(0); /* release cbsy, clock, data */
+
+ lbpwait(SBSY, 0, 120); /* wait for sbsy */
+ sched(); /* wait >1 msec */
+
+ status = 0;
+ mask = 0x80; do {
+ int temp;
+ CMDW(SCLK); /* clock up */
+ MICROSECOND;
+ CMDW(0); /* clock down */
+ MICROSECOND;
+ temp = dev->csr;
+ if (temp & SC)
+ status |= mask;
+ } while (mask >>= 1);
+
+ DPRINT("lbp: cmd = 0x%x, status = 0x%x\n", cmd, status);
+ poperror();
+ qunlock(&lbp.cmdlock);
+ return status;
+}
+
+#define WORDSIZE 32
+
+/*extern ulong _topbits[];*/
+
+static ulong _topbits[]={
+ 0x00000000, 0x80000000, 0xc0000000, 0xe0000000,
+ 0xf0000000, 0xf8000000, 0xfc000000, 0xfe000000,
+ 0xff000000, 0xff800000, 0xffc00000, 0xffe00000,
+ 0xfff00000, 0xfff80000, 0xfffc0000, 0xfffe0000,
+ 0xffff0000, 0xffff8000, 0xffffc000, 0xffffe000,
+ 0xfffff000, 0xfffff800, 0xfffffc00, 0xfffffe00,
+ 0xffffff00, 0xffffff80, 0xffffffc0, 0xffffffe0,
+ 0xfffffff0, 0xfffffff8, 0xfffffffc, 0xfffffffe,
+ 0xffffffff,
+};
+
+#define PBASE(va) (((ulong)(va)) & ~(BY2PG-1))
+#define POFFSET(va) (((ulong)(va)) & (BY2PG-1))
+
+static void
+lbpmap(Point p, GBitmap *bp, Rectangle r)
+{
+ ulong *left, *right; ulong j;
+ int i, lbits, rbits;
+
+ if ((lbits = r.min.x%WORDSIZE) < 0)
+ lbits += WORDSIZE;
+ if ((rbits = r.max.x%WORDSIZE) < 0)
+ rbits += WORDSIZE;
+ lbp.lmask = lbits ? ~_topbits[lbits] : 0;
+ lbp.rmask = rbits ? _topbits[rbits] : 0;
+ lbp.nhblank = 0xff00-(lbpconf.nhblank - lbits + p.x);
+ if (lbp.nhblank < 0)
+ lbp.nhblank = 0;
+ else if (lbp.nhblank > 0xfeff)
+ lbp.nhblank = 0xfeff;
+ left = gaddr(bp, r.min);
+ right = gaddr(bp, Pt(r.max.x-1, r.min.y));
+ lbp.left = left;
+ lbp.maxhl = right - left;
+ lbp.width = bp->width;
+ lbp.nvblank = lbpconf.nvblank + p.y;
+ lbp.nlines = lbp.nvblank + Dy(r);
+ DPRINT("lbpmap: nvblank=%d, nlines=%d\n", lbp.nvblank, lbp.nlines);
+ lbp.ihl = 0;
+ lbp.lcount = 0;
+
+ lbp.x = lbp.xend = lbp.xmap;
+ lbp.s = 0;
+ if (ISKVA(left))
+ return;
+ lbp.s = seg(u->p, (ulong)left, 1);
+ if (!lbp.s)
+ error(Ebadarg);
+ lbp.s->steal++;
+ qunlock(&lbp.s->lk);
+ if (waserror()){
+ qlock(&lbp.s->lk);
+ lbp.s->steal--;
+ qunlock(&lbp.s->lk);
+ error(Ebadarg);
+ }
+
+ for (i=r.min.y; i<r.max.y; i++, left+=bp->width, right+=bp->width) {
+ for (j=PBASE(left); j<=PBASE(right); j+=BY2PG) {
+ if (lbp.xend > lbp.xmap && j <= lbp.xend[-1]->va)
+ continue;
+ /*DPRINT("probing 0x%lux\n", j);*/
+ *lbp.xend++ = addr2page(j);
+ }
+ }
+ poperror();
+}
+
+Page *
+addr2page(ulong addr)
+{
+ Segment *s; long soff; Pte *pte; Page *pg = 0;
+
+ poot = *(ulong *)addr; /* fault it if necessary */
+ s = seg(u->p, addr, 1);
+ if(s != lbp.s)
+ error(Ebadarg);
+ soff = addr-s->base;
+ pte = s->map[soff/PTEMAPMEM];
+ if(pte)
+ pg = pte->pages[(soff&(PTEMAPMEM-1))/BY2PG];
+
+ if(pg == 0){
+ qunlock(&s->lk);
+ pprint("nonresident page addr %lux (complain to rob)\n", addr);
+ error(Eio);
+ }
+ qunlock(&s->lk);
+ return pg;
+}
+
+static void
+validbitmap(GBitmap *bp)
+{
+ ulong tl, br;
+ validaddr((ulong)bp, sizeof(GBitmap), 0);
+ if (((ulong)bp->base&3) || bp->width<=0 || bp->ldepth!=0 || !OKRECT(bp->r))
+ error(Ebadbitmap);
+ tl = (ulong)gaddr(bp, bp->r.min);
+ br = (ulong)gaddr(bp, bp->r.max);
+ validaddr(tl, br-tl, 0);
+}
+
+static long
+lbppage(Point p, GBitmap *bp, Rectangle r)
+{
+ extern QLock bitlock;
+ Lbpfifo *dev = LBPDEV;
+ long dt;
+
+ if (csrwval & (PRNT|GO)) {
+ cprint0 = PRNT;
+ if (!(csrwval & PRNT))
+ CSRSET(PRNT);
+ }
+ DPRINT("lbppage: qlock %d...\n", u->p->pid);
+ qlock(&lbp.pagelock);
+ DPRINT("...%d OK\n", u->p->pid);
+ if(waserror()){
+ if(lbp.flags & Bitmapped){
+ lbp.flags &= ~Bitmapped;
+ kunmap(lbp.kmap);
+ qlock(&lbp.s->lk);
+ lbp.s->steal--;
+ qunlock(&lbp.s->lk);
+ }
+ if(lbp.flags & Bitlocked){
+ lbp.flags &= ~Bitlocked;
+ qunlock(&bitlock);
+ }
+ if(lbp.flags & Cmdlocked){
+ lbp.flags &= ~Cmdlocked;
+ qunlock(&lbp.cmdlock);
+ }
+ qunlock(&lbp.pagelock);
+ nexterror();
+ }
+ cprint0 = lbp.pagelock.head ? PRNT : 0;
+
+ if (dev->csr & PPRDYL) {
+ CSRW(0);
+ pprint("printer power not ready\n");
+ error(Eio);
+ }
+ if (!(dev->csr & RDY)) {
+ DPRINT("lbpprt: not ready, waiting...");
+ wakeup(&lbp.ready);
+ lbpwait(RDY, 0, 0x7fffffffL); /* wait for rdy */
+ DPRINT("OK\n");
+ }
+
+ qlock(&lbp.cmdlock);
+ lbp.flags |= Cmdlocked;
+ if(ISKVA(bp->base)){
+ qlock(&bitlock);
+ lbp.flags |= Bitlocked;
+ }
+ lbpmap(p, bp, r);
+ if(!ISKVA(bp->base)){
+ lbp.kmap = kmap(lbp.xmap[0]);
+ lbp.flags |= Bitmapped;
+ }
+ DPRINT("lbpprt: filling fifo...");
+ CSRCLR(VCLRL); /* clear fifo */
+ CSRSET(VCLRL);
+ dev->hblank = lbp.nhblank; /* left margin */
+ if (fillfifo(lbp.fifosize)) /* did all the data fit ? */
+ CSRSET(EFINTEN); /* yes, interrupt when fifo empty */
+ else
+ CSRSET(HFINTEN|EFINTEN);/* no, interrupt when half-empty */
+ DPRINT("OK\n");
+ CSRSET(PRNT); /* assert prnt */
+ DPRINT("(PRNT 0x%4.4x)...", csrwval);
+ lbpwait(VSREQ, 0, 0L); /* wait for vsreq */
+ DPRINT("VSREQ+...");
+
+ DPRINT("(VSYNC)...");
+ CSRSET(VSYNC); /* now give him vsync */
+
+ lbpwait(0, VSREQ, 0L); /* wait for ack (vsreq goes away) */
+ DPRINT("VSREQ-...");
+ csrwval &= ~(FOURHDPI|PRNT|VSYNC);
+ if (lbpconf.res == 400)
+ CSRSET(FOURHDPI|cprint0|cprint1|GO);
+ else
+ CSRSET(cprint0|cprint1|GO);
+ DPRINT("lbpprt: ready, ticks=%d\n", m->ticks);
+ qunlock(&lbp.cmdlock);
+ lbp.flags &= ~Cmdlocked;
+ lbp.startclicks = 0;
+ lbp.stopclicks = 0;
+ sleep(&lbp.printing, return0, 0);
+ if(ISKVA(bp->base)){
+ qunlock(&bitlock);
+ lbp.flags &= ~Bitlocked;
+ }else{
+ kunmap(lbp.kmap);
+ qlock(&lbp.s->lk);
+ lbp.s->steal--;
+ qunlock(&lbp.s->lk);
+ lbp.flags &= ~Bitmapped;
+ }
+ dt = lbp.stopclicks - lbp.startclicks;
+ DPRINT("lbpprt: lcount=%d, nlines=%d\n", lbp.lcount, lbp.nlines);
+ DPRINT("lbpprt: start=%d, stop=%d, dt=%d\n",
+ lbp.startclicks, lbp.stopclicks, dt);
+ qunlock(&lbp.pagelock);
+ poperror();
+ return dt;
+}
+
+static int
+fillfifo(int nfifo)
+{
+ Lbpfifo *dev = LBPDEV;
+ ulong *up, *kp;
+ int nout, npg;
+ if (lbp.lcount < lbp.nvblank) {
+ nout = lbp.nvblank - lbp.lcount;
+ if (nout > nfifo)
+ nout = nfifo;
+ nfifo -= nout;
+ lbp.lcount += nout;
+ CSRSET(EOL);
+ while (--nout >= 0)
+ *(char *)&dev->fifo = 0;
+ CSRCLR(EOL);
+ }
+ while (nfifo > sizeof(ulong)) {
+ up = lbp.left + lbp.ihl;
+ if (ISKVA(up))
+ kp = up;
+ else {
+ while (PBASE(up) > (*lbp.x)->va)
+ ++lbp.x;
+ lbp.kmap->pa = (*lbp.x)->pa;
+ putkmmu(lbp.kmap->va, PPN(lbp.kmap->pa) | PTEVALID | PTEKERNEL);
+ kp = (ulong *)(lbp.kmap->va + POFFSET(up));
+ }
+ if (lbp.ihl == 0 && lbp.lmask) {
+ dev->fifo = *kp & lbp.lmask;
+ ++lbp.ihl, nfifo -= sizeof(ulong);
+ } else if (lbp.ihl == lbp.maxhl && lbp.rmask) {
+ dev->fifo = *kp & lbp.rmask;
+ ++lbp.ihl, nfifo -= sizeof(ulong);
+ } else {
+ nout = lbp.maxhl - lbp.ihl + (lbp.rmask == 0);
+ npg = (BY2PG - POFFSET(up))/BY2WD;
+ if (nout > npg)
+ nout = npg;
+ if (nout > nfifo/sizeof(ulong))
+ nout = nfifo/sizeof(ulong);
+ lbp.ihl += nout;
+ nfifo -= nout*sizeof(ulong);
+ while(--nout >= 0)
+ dev->fifo = *kp++;
+ }
+ if (lbp.ihl > lbp.maxhl) {
+ CSRSET(EOL);
+ *(char *)&dev->fifo = 0;
+ CSRCLR(EOL);
+ --nfifo;
+ lbp.ihl = 0;
+ lbp.left += lbp.width;
+ if (++lbp.lcount >= lbp.nlines)
+ return 1;
+ }
+ }
+ return 0;
+}
+
+/*static int
+fillfifo(int nfifo)
+{
+ Lbpfifo *dev = LBPDEV;
+ ulong *up;
+ int nout, npg;
+ if (lbp.lcount < lbp.nvblank) {
+ nout = lbp.nvblank - lbp.lcount;
+ if (nout > nfifo)
+ nout = nfifo;
+ nfifo -= nout;
+ lbp.lcount += nout;
+ CSRSET(EOL);
+ while (--nout >= 0)
+ *(char *)&dev->fifo = 0;
+ CSRCLR(EOL);
+ }
+ while (nfifo > sizeof(ulong)) {
+ up = lbp.left + lbp.ihl;
+ if (lbp.ihl == 0 && lbp.lmask) {
+ dev->fifo = *up & lbp.lmask;
+ ++lbp.ihl, nfifo -= sizeof(ulong);
+ } else if (lbp.ihl == lbp.maxhl && lbp.rmask) {
+ dev->fifo = *up & lbp.rmask;
+ ++lbp.ihl, nfifo -= sizeof(ulong);
+ } else {
+ nout = lbp.maxhl - lbp.ihl + (lbp.rmask == 0);
+ if (nout > nfifo/sizeof(ulong))
+ nout = nfifo/sizeof(ulong);
+ lbp.ihl += nout;
+ nfifo -= nout*sizeof(ulong);
+ while (--nout >= 0)
+ dev->fifo = *up++;
+ }
+ if (lbp.ihl > lbp.maxhl) {
+ CSRSET(EOL);
+ *(char *)&dev->fifo = 0;
+ CSRCLR(EOL);
+ --nfifo;
+ lbp.ihl = 0;
+ lbp.left += lbp.width;
+ if (++lbp.lcount >= lbp.nlines)
+ return 1;
+ }
+ }
+ return 0;
+}
+*/
+
+static int
+lbpintr(void)
+{
+ Lbpfifo *dev = LBPDEV;
+ ushort csr = dev->csr;
+ if (!(csr & BINT)) {
+ /*print("lbpintr: no BINT 0x%x\n", csr);*/
+ return 1/*0*/;
+ }
+ if (!lbp.printing.p) {
+ CSRCLR(HFINTEN|EFINTEN|GO);
+ print("spurious lbpintr: 0x%4.4ux\n", csr);
+ return 1;
+ }
+ if (!(csr & EFL)) {
+ lbp.stopclicks = m->ticks;
+ CSRCLR(HFINTEN|EFINTEN|GO);
+ wakeup(&lbp.printing);
+ } else if (csr & HFL) {
+ if (!lbp.startclicks)
+ lbp.startclicks = m->ticks;
+ if (fillfifo(lbp.fifosize/2)) { /* did all the data fit ? */
+ csrwval &= ~HFINTEN;
+ CSRSET(EFINTEN); /* yes, interrupt when fifo empty */
+ }
+ } else {
+ print("null lbpintr: 0x%4.4ux\n", csr);
+ }
+ return 1;
+}
@@ 40,8 40,8 @@ sysparam[] =
{ 0x53, "1+ 4/65", 0, 65536, 16, 8, 128, 0, 64 },
{ 0x54, "SLC 4/20", 0, 65536, 16, 8, 128, 0, 64 },
{ 0x55, "2 4/75", 1, 65536, 32, 16, 256, 1, 64 },
- { 0x56, "ELC 4/25", 1, 65536, 32, 16, 256, 1, 64 },
- { 0x57, "IPX 4/50", 1, 65536, 32, 16, 256, 1, 64 },
+ { 0x56, "ELC 4/25", 1, 65536, 32, 8, 128, 1, 64 },
+ { 0x57, "IPX 4/50", 1, 65536, 32, 8, 256, 1, 64 },
{ 0 }
};
Sysparam *sparam;