## diffname pc/devincon.c 1992/0205
## diff -e /dev/null /n/bootesdump/1992/0205/sys/src/9/safari/devincon.c
0a
#include "u.h"
#include "lib.h"
#include "mem.h"
#include "dat.h"
#include "fns.h"
#include "../port/error.h"
#include "devtab.h"
#include "io.h"
/* Centronix parallel (printer) port */
/* base addresses */
static int lptbase[] = {
0x3bc, /* lpt1 */
0x378, /* lpt2 (sic) */
0x278 /* lpt3 (sic) */
};
#define NDEV (sizeof lptbase/sizeof lptbase[0])
/* offsets, and bits in the registers */
enum
{
/* data latch register */
Qdlr= 0x0,
/* printer status register */
Qpsr= 0x1,
Fbusy= 0x80,
Fintbar= 0x40,
/* printer control register */
Qpcr= 0x2,
Fie= 0x10,
Fsi= 0x08,
Finitbar= 0x04,
Faf= 0x02,
Fstrobe= 0x01,
/* other `registers' */
Qstats= 0x03,
Qdebug= 0x04
};
/*
* af si dlr<7:0>
* 0 x xxxxxxxx wr ctl/data char (si is dcto)
* 1 0 xxxxxxxx wr cmd
* 1 1 xxxxxx00 rd ctl/data char
* 1 1 xxxxxx01 rd status
* 1 1 xxxxxx11 nop (multiplexer to normal state)
*
* psr<7:3> multiplexed as follows:
*
* bc7 bc6 bc5 bc4 bc3
* rd, st- low bsy d8 d7 d6 d5
* rd, st- high d4 d3 d2 d1 d0
* other bsy int-
*/
typedef struct Incon Incon;
#define NOW (MACHP(0)->ticks*MS2HZ)
#define DPRINT if(incondebug)kprint
static void inconintr(Ureg *ur);
enum {
Minstation= 2, /* lowest station # to poll */
Maxstation= 15, /* highest station # to poll */
Nincon= 1, /* number of incons */
Nin= 32, /* Blocks in the input ring */
Bsize= 128, /* size of an input ring block */
Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */
};
struct Incon {
QLock;
QLock xmit; /* transmit lock */
QLock reslock; /* reset lock */
int dev; /* base address of port */
int station; /* station number */
int state; /* chip state */
Rendez r; /* output process */
Rendez kr; /* input kernel process */
ushort chan; /* current input channel */
Queue *rq; /* read queue */
int kstarted; /* true if kernel process started */
/* input blocks */
Block *inb[Nin];
ushort wi;
ushort ri;
/* statistics */
ulong overflow; /* overflow errors */
ulong pack0; /* channel 0 */
ulong crc; /* crc errors */
ulong in; /* bytes in */
ulong out; /* bytes out */
ulong wait; /* wait time in milliseconds */
};
Incon incon[Nincon];
/*
* chip state
*/
enum {
Selecting,
Selected,
Notliving,
};
/*
* internal chip registers
*/
#define sel_polln 0
#define sel_station 1
#define sel_poll0 2
#define sel_rcv_cnt 3
#define sel_rcv_tim 4
#define sel_tx_cnt 5
/*
* CSR bits
*/
#define INCON_RUN 0x80
#define INCON_STOP 0x00
#define ENABLE_IRQ 0x40
#define ENABLE_TX_IRQ 0x20
#define INCON_ALIVE 0x80
#define TX_FULL 0x10
#define TX_EMPTY 0x08
#define RCV_EMPTY 0x04
#define OVERFLOW 0x02
#define CRC_ERROR 0x01
/*
* polling constants
*/
#define HT_GNOT 0x30
#define HT_UNIX 0x31
#define ST_UNIX 0x04
#define NCHAN 64
static void inconkproc(void*);
/*
* incon stream module definition
*/
static void inconoput(Queue*, Block*);
static void inconstopen(Queue*, Stream*);
static void inconstclose(Queue*);
Qinfo inconinfo =
{
nullput,
inconoput,
inconstopen,
inconstclose,
"incon"
};
int incondebug = 0;
Dirtab incondir[]={
"dlr", {Qdlr}, 1, 0666,
"psr", {Qpsr}, 5, 0444,
"pcr", {Qpcr}, 0, 0666,
"stats", {Qstats}, 0, 0444,
"debug", {Qdebug}, 0, 0666,
};
#define NINCON (sizeof incondir/sizeof incondir[0])
static void
reset(int dev) /* hardware reset */
{
outb(dev+Qpcr, Finitbar);
outb(dev+Qpcr, 0);
outb(dev+Qpcr, Finitbar|Fie);
}
static void
wrctl(int dev, int data) /* write control character */
{
outb(dev+Qpcr, Finitbar); /* no interrupts, please */
outb(dev+Qdlr, data);
outb(dev+Qpcr, Finitbar|Fstrobe);
outb(dev+Qpcr, Finitbar|Fie);
}
static void
wrdata(int dev, int data) /* write data character */
{
outb(dev+Qpcr, Finitbar|Fsi);
outb(dev+Qdlr, data);
outb(dev+Qpcr, Finitbar|Fsi|Fstrobe);
outb(dev+Qpcr, Finitbar|Fsi|Fie);
}
static void
wrcmd(int dev, int data) /* write command */
{
outb(dev+Qpcr, Finitbar|Faf);
outb(dev+Qdlr, data);
outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
outb(dev+Qpcr, Finitbar|Faf|Fie);
}
static int
rdstatus(Incon *ip) /* read status */
{
int dev, data;
dev = ip->dev;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
outb(dev+Qdlr, 0x01);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
data = (inb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
data |= inb(dev+Qpsr)>>3;
if(data&(OVERFLOW|CRC_ERROR)){
if(data&OVERFLOW)
ip->overflow++;
if(data&CRC_ERROR)
ip->crc++;
}
outb(dev+Qdlr, 0x03);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fie);
return data;
}
static void
iwrcmd(int dev, int data) /* write command at interrupt level */
{
outb(dev+Qdlr, data);
outb(dev+Qpcr, Finitbar|Faf|Fstrobe);
outb(dev+Qpcr, Finitbar|Faf);
}
static int
irdstatus(Incon *ip) /* read status at interrupt level */
{
int dev, data;
dev = ip->dev;
outb(dev+Qdlr, 0x01);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
data = (inb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
data |= inb(dev+Qpsr)>>3;
if(data&(OVERFLOW|CRC_ERROR)){
if(data&OVERFLOW)
ip->overflow++;
if(data&CRC_ERROR)
ip->crc++;
}
return data;
}
static int
irddata(int dev) /* read data at interrupt level */
{
int data;
outb(dev+Qdlr, 0x00);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
data = (inb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
data |= inb(dev+Qpsr)>>3;
return data;
}
static int
irdnext(int dev) /* read next data at interrupt level */
{
int data;
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
data = (inb(dev+Qpsr)&0xf8)<<2;
outb(dev+Qpcr, Finitbar|Faf|Fsi);
data |= inb(dev+Qpsr)>>3;
return data;
}
static void
irdnop(int dev, int pcr) /* read nop (mux reset) */
{
outb(dev+Qdlr, 0x03);
outb(dev+Qpcr, Finitbar|Faf|Fsi|Fstrobe);
outb(dev+Qpcr, pcr);
}
int Irdnext(int);
#define irdnext Irdnext
/*
* set the incon parameters
*/
void
inconset(Incon *ip, int cnt, int del)
{
int dev;
if (cnt<1 || cnt>14 || del<1 || del>15)
error(Ebadarg);
dev = ip->dev;
wrcmd(dev, sel_rcv_cnt | INCON_RUN);
wrdata(dev, cnt);
wrcmd(dev, sel_rcv_tim | INCON_RUN);
wrdata(dev, del);
wrcmd(dev, INCON_RUN | ENABLE_IRQ);
}
/*
* parse a set request
*/
void
inconsetctl(Incon *ip, Block *bp)
{
char *field[3];
int n;
int del;
int cnt;
del = 15;
n = getfields((char *)bp->rptr, field, 3, ' ');
switch(n){
default:
freeb(bp);
error(Ebadarg);
case 2:
del = strtol(field[1], 0, 0);
if(del<0 || del>15){
freeb(bp);
error(Ebadarg);
}
/* fall through */
case 1:
cnt = strtol(field[0], 0, 0);
if(cnt<0 || cnt>15){
freeb(bp);
error(Ebadarg);
}
}
inconset(ip, cnt, del);
freeb(bp);
}
static void
nop(void)
{
}
/*
* poll for a station number
*/
void
inconpoll(Incon *ip, int station)
{
ulong timer;
int dev;
char *p;
dev = ip->dev;
/*
* get us to a known state
*/
ip->state = Notliving;
wrcmd(dev, INCON_STOP);
/*
* try a station number
*/
wrcmd(dev, sel_station);
wrdata(dev, station);
wrcmd(dev, sel_poll0);
wrdata(dev, HT_GNOT);
wrcmd(dev, sel_rcv_cnt);
wrdata(dev, 3);
wrcmd(dev, sel_rcv_tim);
wrdata(dev, 15);
wrcmd(dev, sel_tx_cnt);
wrdata(dev, 1);
wrcmd(dev, sel_polln);
wrdata(dev, 0x00);
wrdata(dev, ST_UNIX);
wrdata(dev, NCHAN);
for(p = "gnot"; *p; p++)
wrdata(dev, *p);
wrctl(dev, 0);
/*
* poll and wait for ready (or 1/4 second)
*/
ip->state = Selecting;
wrcmd(dev, INCON_RUN | ENABLE_IRQ);
timer = NOW + 250;
while (NOW < timer) {
nop();
if(rdstatus(ip) & INCON_ALIVE){
ip->station = station;
ip->state = Selected;
break;
}
}
}
/*
* reset the chip and find a new station number
*/
void
inconrestart(Incon *ip)
{
int i;
if(!canqlock(&ip->reslock))
return;
/*
* poll for incon station numbers
*/
DPRINT("inconrestart\n");
for(i = Minstation; i <= Maxstation; i++){
inconpoll(ip, i);
if(ip->state == Selected)
break;
}
switch(ip->state) {
case Selecting:
DPRINT("incon[%d] not polled\n", ip-incon);
print("incon[%d] not polled\n", ip-incon);
break;
case Selected:
DPRINT("incon[%d] station %d\n", ip-incon, ip->station);
print("incon[%d] station %d\n", ip-incon, ip->station);
inconset(ip, 3, 15);
break;
default:
DPRINT("incon[%d] bollixed\n", ip-incon);
print("incon[%d] bollixed\n", ip-incon);
break;
}
qunlock(&ip->reslock);
}
/*
* reset all incon chips.
*/
void
inconreset(void)
{
int i;
setvec(Parallelvec, inconintr);
/*
* state is Selected if we used incon as the boot device
* i.e. we've already got a station number.
* state is Selecting if this is a first-time open.
*/
/* inconset(&incon[0], 3, 15); /**/
for(i=0; i<Nincon; i++){
incon[i].dev = lptbase[i];
incon[i].state = Notliving;
reset(incon[i].dev);
incon[i].ri = incon[i].wi = 0;
}
incon[0].state = Selecting;
wrcmd(incon[0].dev, INCON_STOP);
}
void
inconinit(void)
{
wrcmd(incon[0].dev, INCON_STOP);
}
/*
* enable the device for interrupts, spec is the device number
*/
Chan*
inconattach(char *spec)
{
Incon *ip;
int i;
Chan *c;
i = strtoul(spec, 0, 0);
if(i >= Nincon)
error(Ebadarg);
ip = &incon[i];
if(ip->state != Selected)
inconrestart(ip);
c = devattach('i', spec);
c->dev = i;
c->qid.path = CHDIR;
c->qid.vers = 0;
return c;
}
Chan*
inconclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
inconwalk(Chan *c, char *name)
{
return devwalk(c, name, incondir, NINCON, streamgen);
}
void
inconstat(Chan *c, char *dp)
{
devstat(c, dp, incondir, NINCON, streamgen);
}
Chan*
inconopen(Chan *c, int omode)
{
if(c->qid.path != CHDIR && c->qid.path >= Slowqid)
streamopen(c, &inconinfo);
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
return c;
}
void
inconcreate(Chan *c, char *name, int omode, ulong perm)
{
error(Eperm);
}
void
inconclose(Chan *c)
{
if(c->qid.path != CHDIR && c->qid.path >= Slowqid)
streamclose(c);
}
long
inconread(Chan *c, void *buf, long n, ulong offset)
{
char b[256];
Incon *ip;
if(c->qid.path == CHDIR)
return devdirread(c, buf, n, incondir, NINCON, streamgen);
ip = &incon[c->dev];
switch(c->qid.path){
default:
return streamread(c, buf, n);
case Qdlr:
case Qpsr:
case Qpcr:
sprint(b, "0x%2.2ux\n", inb(ip->dev + c->qid.path));
break;
case Qstats:
sprint(b, "state: %d\nstation: %d\nin: %d\nout: %d\noverflow: %d\ncrc: %d\nwait: %d\n",
ip->state, ip->station, ip->in, ip->out, ip->overflow, ip->crc, ip->wait);
break;
case Qdebug:
sprint(b, "%d\n", incondebug);
break;
}
return stringread(buf, n, b, offset);
}
long
inconwrite(Chan *c, void *buf, long n, ulong offset)
{
char b[8];
Incon *ip;
int data;
switch(c->qid.path){
default:
return streamwrite(c, buf, n, 0);
case Qdlr:
case Qpcr:
case Qdebug:
break;
}
if(n > sizeof b-1)
n = sizeof b-1;
memmove(b, buf, n);
b[n] = 0;
data = strtoul(b, 0, 0);
switch(c->qid.path){
default:
ip = &incon[c->dev];
outb(ip->dev + c->qid.path, data);
break;
case Qdebug:
incondebug = data;
break;
}
return n;
}
void
inconremove(Chan *c)
{
error(Eperm);
}
void
inconwstat(Chan *c, char *dp)
{
error(Eperm);
}
/*
* the stream routines
*/
/*
* kill off the kernel process
*/
static int
kNotliving(void *arg)
{
Incon *ip;
ip = (Incon *)arg;
return ip->kstarted == 0;
}
static void
inconstclose(Queue * q)
{
Incon *ip;
ip = (Incon *)q->ptr;
qlock(ip);
ip->rq = 0;
qunlock(ip);
wakeup(&ip->kr);
sleep(&ip->r, kNotliving, ip);
}
/*
* create the kernel process for input
* first wait for any old ones to die
*/
static void
inconstopen(Queue *q, Stream *s)
{
Incon *ip;
char name[32];
ip = &incon[s->dev];
sprint(name, "incon%d", s->dev);
q->ptr = q->other->ptr = ip;
wakeup(&ip->kr);
sleep(&ip->r, kNotliving, ip);
ip->rq = q;
kproc(name, inconkproc, ip);
}
/*
* free all blocks of a message in `q', `bp' is the first block
* of the message
*/
static void
freemsg(Queue *q, Block *bp)
{
for(; bp; bp = getq(q)){
if(bp->flags & S_DELIM){
freeb(bp);
return;
}
freeb(bp);
}
}
static void
showpkt(char *str, int chan, int ctl, Block *bp, int i)
{
int n;
n = bp->wptr - bp->rptr;
kprint("%s(%d)%uo %d", str, chan, ctl, n);
if(n > 8)
n = 8;
for(; i<n; i++)
kprint(" %2.2ux", bp->rptr[i]);
kprint("\n");
}
/*
* output a block
*
* the first 2 bytes of every message are the channel number,
* low order byte first. the third is a possible trailing control
* character.
*/
void
inconoput(Queue *q, Block *bp)
{
int dev;
Incon *ip;
ulong end;
int chan;
int ctl;
int n, size;
ip = (Incon *)q->ptr;
if(bp->type != M_DATA){
if(streamparse("inconset", bp))
inconsetctl(ip, bp);
else
freeb(bp);
return;
}
/*
* get a whole message before handing bytes to the device
*/
if(!putq(q, bp))
return;
/*
* one transmitter at a time
*/
qlock(&ip->xmit);
dev = ip->dev;
/*
* parse message
*/
bp = getq(q);
if(bp->wptr - bp->rptr < 3){
freemsg(q, bp);
qunlock(&ip->xmit);
return;
}
chan = bp->rptr[0] | (bp->rptr[1]<<8);
ctl = bp->rptr[2];
bp->rptr += 3;
if(chan<=0)
print("bad channel %d\n", chan);
if(incondebug)
showpkt("->", chan, ctl, bp, 0);
/*
* make sure there's an incon out there
*/
if(!(rdstatus(ip)&INCON_ALIVE) || ip->state==Notliving){
DPRINT("inconoput: not ready");
inconrestart(ip);
freemsg(q, bp);
qunlock(&ip->xmit);
return;
}
/*
* send the 8 bit data
*/
for(;;){
/*
* spin till there is room
*/
for(n=0, end = NOW+1000; rdstatus(ip) & TX_FULL; n++){
nop(); /* make sure we don't optimize too much */
if(NOW > end){
print("incon output stuck 0\n");
freemsg(q, bp);
qunlock(&ip->xmit);
return;
}
}
ip->wait = (n + ip->wait)>>1;
/*
* put in next packet
*/
n = bp->wptr - bp->rptr;
if(n > 16)
n = 16;
size = n;
wrctl(dev, chan);
ip->out += n;
while(n--){
wrdata(dev, *bp->rptr++);
}
/*
* get next block
*/
if(bp->rptr >= bp->wptr){
if(bp->flags & S_DELIM){
freeb(bp);
break;
}
freeb(bp);
bp = getq(q);
if(bp==0)
break;
}
/*
* end packet
*/
wrctl(dev, 0);
}
/*
* send the control byte if there is one
*/
if(ctl){
if(size >= 16){
wrctl(dev, 0);
for(end = NOW+1000; rdstatus(ip) & TX_FULL;){
nop(); /* make sure we don't optimize too much */
if(NOW > end){
print("incon output stuck 1\n");
freemsg(q, bp);
qunlock(&ip->xmit);
return;
}
}
wrctl(dev, chan);
}
if(rdstatus(ip) & TX_FULL)
print("inconfull\n");
ip->out += 1;
wrctl(dev, ctl);
}
wrctl(dev, 0);
qunlock(&ip->xmit);
return;
}
/*
* return true if the raw fifo is non-empty
*/
static int
notempty(void *arg)
{
Incon *ip;
ip = (Incon *)arg;
return ip->ri!=ip->wi;
}
/*
* Read bytes from the raw input circular buffer.
*/
static void
inconkproc(void *arg)
{
Incon *ip;
Block *bp, *nbp;
int i;
int locked;
ip = (Incon *)arg;
ip->kstarted = 1;
/*
* create a number of blocks for input
*/
for(i = 0; i < Nin; i++){
bp = ip->inb[i] = allocb(Bsize);
bp->wptr += 3;
}
locked = 0;
if(waserror()){
if(locked)
qunlock(ip);
ip->kstarted = 0;
wakeup(&ip->r);
return;
}
for(;;){
/*
* sleep if input fifo empty
*/
sleep(&ip->kr, notempty, ip);
/*
* die if the device is closed
*/
USED(locked);
qlock(ip);
locked = 1;
if(ip->rq == 0){
qunlock(ip);
ip->kstarted = 0;
wakeup(&ip->r);
poperror();
return;
}
/*
* send blocks upstream and stage new blocks. if the block is small
* (< 64 bytes) copy into a smaller buffer.
*/
while(ip->ri != ip->wi){
bp = ip->inb[ip->ri];
ip->in += BLEN(bp);
PUTNEXT(ip->rq, bp);
bp = ip->inb[ip->ri] = allocb(Bsize);
bp->wptr += 3;
ip->ri = (ip->ri+1)%Nin;
}
USED(locked);
qunlock(ip);
locked = 0;
}
}
/*
* drop a single packet
*/
static void
droppacket(int dev)
{
if(irddata(dev) == 0)
return;
while(irdnext(dev))
;
}
/*
* flush the input fifo
*/
static void
flushfifo(Incon *ip)
{
while(!(irdstatus(ip) & RCV_EMPTY))
droppacket(ip->dev);
}
/*
* advance the queue. if we've run out of staged input blocks,
* drop the packet and return 0. otherwise return the next input
* block to fill.
*/
static Block *
nextin(Incon *ip, unsigned int c)
{
Block *bp;
int next;
bp = ip->inb[ip->wi];
bp->base[0] = ip->chan;
bp->base[1] = ip->chan>>8;
bp->base[2] = c;
if(incondebug)
showpkt("<-", ip->chan, c, bp, 3);
next = (ip->wi+1)%Nin;
if(next == ip->ri){
bp->wptr = bp->base+3;
return bp;
}
ip->wi = next;
return ip->inb[ip->wi];
}
/*
* read the packets from the device into the staged input blocks.
* we have to do this at interrupt tevel to turn off the interrupts.
*/
static void
rdpackets(Incon *ip)
{
Block *bp;
unsigned int c;
int dev;
uchar *p;
int first = ip->wi;
dev = ip->dev;
bp = ip->inb[ip->wi];
if(bp==0){
flushfifo(ip);
return;
}
p = bp->wptr;
while(!(irdstatus(ip) & RCV_EMPTY)){
/*
* get channel number
*/
c = irddata(dev);
if(c == 0){
droppacket(dev);
continue;
}
if(ip->chan != c){
if(p - bp->rptr > 3){
bp->wptr = p;
bp = nextin(ip, 0);
p = bp->wptr;
}
ip->chan = c;
}
/*
* null byte marks end of packet
*/
while(c = irdnext(dev)){ /* assign = */
if((c & 0x100) == 0){
/*
* control byte ends block
*/
bp->wptr = p;
bp = nextin(ip, c);
p = bp->wptr;
}else{
/*
* data byte, put in local buffer
*/
*p++ = c;
}
}
/*
* pass a block on if it doesn't have room for one more
* packet. this way we don't have to check per byte.
*/
if(p + 16 > bp->lim){
bp->wptr = p;
bp = nextin(ip, 0);
p = bp->wptr;
}
}
bp->wptr = p;
if(bp->wptr != bp->base+3)
nextin(ip, 0);
if(first != ip->wi)/**/
wakeup(&ip->kr);
}
/*
* Receive an incon interrupt. One entry point
* for all types of interrupt. Until we figure out
* how to use more than one incon, this routine only
* is for incon[0].
*/
static void
inconintr(Ureg *ur)
{
uchar status;
int pcr;
Incon *ip;
ip = &incon[0];
pcr = inb(ip->dev+Qpcr);
status = irdstatus(ip);
if(incondebug){
kprint("pcr=%2.2x status=%2.2x\n", pcr, status);
if(pcr & Fstrobe)
kprint("YIKES!!\n");
}
if(!(status & RCV_EMPTY))
rdpackets(ip);
/* see if it died underneath us */
if(!(status&INCON_ALIVE)){
switch(ip->state){
case Selected:
iwrcmd(ip->dev, INCON_STOP);
DPRINT("Incon died\n");
print("Incon died\n");
break;
case Selecting:
DPRINT("rejected\n");
print("rejected\n");
break;
default:
iwrcmd(ip->dev, INCON_STOP);
DPRINT("state was %d\n", ip->state);
break;
}
ip->state = Notliving;
}
irdnop(ip->dev, pcr);
}
.
## diffname pc/devincon.c 1992/0207
## diff -e /n/bootesdump/1992/0205/sys/src/9/safari/devincon.c /n/bootesdump/1992/0207/sys/src/9/safari/devincon.c
503a
rdstatus(ip);
.
499a
setvec(Parallelvec, inconintr);
.
467d
182c
outb(dev+Qpcr, Finitbar);
.
## diffname pc/devincon.c 1992/0321
## diff -e /n/bootesdump/1992/0207/sys/src/9/safari/devincon.c /n/bootesdump/1992/0321/sys/src/9/safari/devincon.c
2c
#include "../port/lib.h"
.
## diffname pc/devincon.c 1992/0623
## diff -e /n/bootesdump/1992/0321/sys/src/9/safari/devincon.c /n/bootesdump/1992/0623/sys/src/9/safari/devincon.c
750,754d
732a
if(BLEN(bp) < 3){
bp = pullup(bp, 3);
if(bp == 0){
print("inconoput pullup failed\n");
return;
}
}
.
## diffname pc/devincon.c 1992/0625
## diff -e /n/bootesdump/1992/0623/sys/src/9/safari/devincon.c /n/bootesdump/1992/0625/sys/src/9/safari/devincon.c
582c
return readstr(offset, buf, n, b);
.
## diffname pc/devincon.c 1992/0708
## diff -e /n/bootesdump/1992/0625/sys/src/9/safari/devincon.c /n/bootesdump/1992/0708/sys/src/9/safari/devincon.c
1055c
if(bp->wptr != bp->rptr+3)
.
979c
bp->wptr = bp->rptr+3;
.
971,973c
bp->rptr[0] = ip->chan;
bp->rptr[1] = ip->chan>>8;
bp->rptr[2] = c;
.
## diffname pc/devincon.c 1992/0711
## diff -e /n/bootesdump/1992/0708/sys/src/9/safari/devincon.c /n/bootesdump/1992/0711/sys/src/9/safari/devincon.c
1074a
USED(ur);
.
875c
Block *bp;
.
625a
USED(c, dp);
.
619a
USED(c);
.
591a
USED(offset);
.
546a
USED(c, name, omode, perm);
.
## diffname pc/devincon.c 1992/1013
## diff -e /n/bootesdump/1992/0808/sys/src/9/safari/devincon.c /n/bootesdump/1992/1013/sys/src/9/pc/devincon.c
1078a
print("I");
.
791c
print("incon output stuck 0 %.2ux\n", ctl);
.
788c
for(n=0, end = NOW+1000; (ctl=rdstatus(ip)) & TX_FULL; n++){
.
499c
/*setvec(Parallelvec, inconintr);*/
setvec(Int0vec+5, inconintr);
.
474c
incon[i].dev = lptbase[1/*i*/];
.
417a
print("poll: status 0x%.2ux\n", rdstatus(ip));
.
305c
*/
.
302c
/*
.
299a
Xdelay(SDLY);
.
289a
Xdelay(SDLY);
.
287a
Xdelay(SDLY);
.
276a
Xdelay(SDLY);
.
274a
Xdelay(SDLY);
.
256a
Xdelay(SDLY);
.
254a
Xdelay(SDLY);
.
242a
Xdelay(SDLY);
.
232a
Xdelay(SDLY);
.
223a
Xdelay(SDLY);
.
221a
Xdelay(SDLY);
.
208a
Xdelay(SDLY);
.
199a
Xdelay(SDLY);
.
190a
Xdelay(SDLY);
.
181a
Xdelay(10000);
.
176a
/*static void
Xdelay(int n)
{
while(--n >= 0) ;
}
#define SDLY 1000
*/
#define Xdelay(n)
.
63c
#define DPRINT /*if(incondebug)k*/print
.
## diffname pc/devincon.c 1992/1014
## diff -e /n/bootesdump/1992/1013/sys/src/9/pc/devincon.c /n/bootesdump/1992/1014/sys/src/9/pc/devincon.c
1105d
954a
bp->flags |= S_DELIM;
.
950,951c
* send blocks upstream and stage new blocks.
.
794a
}
.
793c
if(incondebug){
kprint("0x%.2ux ", rdstatus(ip));
.
524,525c
setvec(lptinfo[incondev].ivec, inconintr);
.
499c
incon[i].dev = lptinfo[incondev].base;
.
442d
329c
.
326c
.
321a
Xdelay(SDLY);
.
312d
309d
297d
294d
275d
272d
257a
Xdelay(SDLY);
.
248d
238d
235d
219a
Xdelay(SDLY);
.
209a
Xdelay(SDLY);
.
207a
Xdelay(SDLY);
.
199a
Xdelay(SDLY);
.
197a
Xdelay(SDLY);
.
189a
Xdelay(10000);
.
185a
/*#define Xdelay(n)*/
.
183,184d
177c
static void
.
63c
#define DPRINT if(incondebug)kprint
.
20a
static Lptinfo lptinfo[] = {
0x3bc, Parallelvec, /* lpt1 (safari) */
0x378, Parallelvec, /* lpt1 (`official') */
0x278, Int0vec+5, /* lpt2 (`official') */
};
#define NDEV (sizeof lptinfo/sizeof lptinfo[0])
extern int incondev; /* from config */
.
19d
13,17c
typedef struct Lptinfo Lptinfo;
struct Lptinfo
{
int base; /* port number */
int ivec; /* interrupt number */
.
## diffname pc/devincon.c 1992/1015
## diff -e /n/bootesdump/1992/1014/sys/src/9/pc/devincon.c /n/bootesdump/1992/1015/sys/src/9/pc/devincon.c
825c
print("incon output stuck 0 %.2ux\n", status);
.
822c
for(n=0, end = NOW+1000; (status=rdstatus(ip)) & TX_FULL; n++){
.
756,757c
int status, chan, ctl;
.
331d
329d
272d
270d
236d
234d
225d
223d
220d
213d
211d
208d
201d
199d
187,195d
## diffname pc/devincon.c 1993/0915
## diff -e /n/bootesdump/1992/1015/sys/src/9/pc/devincon.c /n/fornaxdump/1993/0915/sys/src/brazil/pc/devincon.c
1091a
if(!(pcr & Fie))
return;
.
476a
* get incondev from p9rc
*/
p = getconf("incondev");
if(p)
incondev = atoi(p);
/*
.
474a
char *p;
.
369,373d
313a
/**/
.
286c
data |= slowinb(dev+Qpsr)>>3;
.
284c
data = (slowinb(dev+Qpsr)&0xf8)<<2;
.
266c
data |= slowinb(dev+Qpsr)>>3;
.
264c
data = (slowinb(dev+Qpsr)&0xf8)<<2;
.
186a
nop(void)
{
}
static int
slowinb(int x)
{
nop();
nop();
return inb(x);
}
static void
.
## diffname pc/devincon.c 1993/1113 # deleted
## diff -e /n/fornaxdump/1993/0915/sys/src/brazil/pc/devincon.c /n/fornaxdump/1993/1113/sys/src/brazil/pc/devincon.c
1,1140d
|