V8/usr/sys/dev/an.c
#include "an.h"
#if NAN > 0
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/buf.h"
#include "../h/conf.h"
#include "../h/dir.h"
#include "../h/user.h"
#include "../h/pte.h"
#include "../h/map.h"
#include "../h/vm.h"
#include "../h/anet.h"
#include "../h/cmap.h"
#include "../h/ubareg.h"
#include "../h/ubavar.h"
#include "../h/cpu.h"
#include "../h/proc.h"
#include "../h/status.h"
#ifdef ANDEBUG
int andebug = 1;
#else
int andebug = 0;
#endif
/* flags for status */
#define INPUT 1
#define OUTPUT 2
#define min(x,y) ((x) < (y) ? (x) : (y))
#define swab(x) (((x<<8) | ((x&0xFF00)>>8)) & 0xFFFF)
#define ANPRI 28
struct device {
short drcs;
short drout;
short drin;
};
/* Command and Status word */
#define CSR0 0x1
#define CSR1 0x2
#define RIE 0x20
#define TIE 0x40
#define TEMPTY 0x80
#define RFULL 0x8000
/*
* CSR1 CSR0
* 0 0 Write Data
* 0 1 Write EOP
* 1 0 Write Command
* 1 1 Read Status
*/
#define DATA_MODE (RIE)
#define EOP_MODE (CSR0 | RIE)
#define CMD_MODE (CSR1 | RIE)
#define STATUS_MODE (CSR0 | CSR1 | RIE)
#define MAXMSGLEN 2042
#define IBUF 1
#define OBUF 2
struct an_dev {
char open;
char flag;
short uid;
short icnt, ocnt;
short ibuf[MAXMSGLEN/2];
short obuf[MAXMSGLEN/2];
} an_dev[NAN];
#ifdef TIMEOUT
#define CKFUZZ 4 /* number of timeouts we wait for a response */
#define CKTICKS (hz/4) /* number of ticks per timeout */
int an_state;
#define OPEN 1 /* set if at least one sn? is open */
#define TIMER 2 /* set if at timer is running */
int cktimchk();
int an_opncnt;
#endif TIMEOUT
/*struct anmach anmach[8] = {
{ 1, 255 },
{ 2, 254 },
{ 3, 253 },
{ 4, 252 },
{ 5, 251 },
{ 6, 250 },
{ 7, 249 },
{ 8, 248 } };*/
#define RETURN(x) {u.u_error = x; return(0);}
int anprobe(), anattach();
struct uba_device *andinfo[NAN];
u_short anstd[] = {0};
struct uba_driver andriver =
{ anprobe, 0, anattach, 0, anstd, "an", andinfo};
anprobe(reg)
caddr_t reg;
{
register int br, cvec; /* value result */
br = 0x15;
cvec = 0510;
return(1);
}
anattach()
{
register struct device *draddr;
register struct uba_device *ui;
ui = andinfo[0];
draddr = (struct device *)ui->ui_addr;
draddr->drcs = CMD_MODE;
draddr->drout = 0;
draddr->drout = MASTER_CLEAR;
draddr->drout = 0;
draddr->drout = BOARD_RESET;
draddr->drout = 0;
draddr->drcs = STATUS_MODE;
printf("S/NET BIB #%d\n", (draddr->drin>>10)&0xF);
}
/*
open the argus network
*/
anopen(dev)
register dev_t dev;
{
register struct device *draddr;
register struct an_dev *an;
register struct uba_device *ui;
int net = NET(dev);
if(andebug)
printf("anopen(%x)\n", dev);
if(net >= NAN || (ui = andinfo[net]) == 0 || ui->ui_alive == 0)
RETURN(ENXIO);
draddr = (struct device *)ui->ui_addr;
an = &an_dev[net];
spl6();
if (an->open++ != 0) {
spl0();
RETURN(EBUSY);
}
an->uid = u.u_uid;
#ifdef TIMEOUT
sn_opncnt++;
sn_state |= OPEN;
if ((sn_state & TIMER) == 0) {
sn_state |= TIMER;
timeout(cktimchk, (caddr_t)0, CKTICKS);
}
#endif TIMEOUT
draddr->drcs = CMD_MODE;
draddr->drout = 0;
draddr->drout = BOARD_RESET;
draddr->drout = 0;
draddr->drcs = DATA_MODE;
spl0();
return(1);
}
anclose(dev)
{
struct uba_device *ui;
register struct an_dev *an;
int net = NET(dev);
if(andebug)
printf("anclose(%x)\n", dev);
if(net >= NAN)
RETURN(ENXIO)
an = &an_dev[net];
spl6();
an->open = 0;
spl0();
}
anread(dev)
dev_t dev;
{
int net;
register struct device *draddr;
register struct an_dev *an;
register struct uba_device *ui;
short stat;
net = NET(dev);
if(net >= NAN)
RETURN(ENXIO)
ui = andinfo[net];
draddr = (struct device *)ui->ui_addr;
an = &an_dev[net];
if(an->open == 0) RETURN(ENXIO)
spl6();
if((an->flag&IBUF) == 0)
RETURN(EIO);
if(copyout(an->ibuf, u.u_base, an->icnt))
{
spl0();
RETURN(EFAULT);
}
u.u_count -= an->icnt;
an->flag &= ~IBUF;
spl0();
}
anwrite(dev)
dev_t dev;
{
int net;
register struct device *draddr;
register struct an_dev *an;
register struct uba_device *ui;
short stat;
net = NET(dev);
if(net >= NAN)
RETURN(ENXIO)
ui = andinfo[net];
draddr = (struct device *)ui->ui_addr;
an = &an_dev[net];
if(an->open == 0) RETURN(ENXIO)
if((an->ocnt = u.u_count) > MAXMSGLEN)
an->ocnt = MAXMSGLEN;
if(an->ocnt < 2)
RETURN(EIO);
if(copyin(u.u_base, an->obuf, an->ocnt))
RETURN(EFAULT);
if(andebug)
printf("write on dev %d of %d bytes, sh[0]=%x, sh[1]=%x\n",
net, u.u_count, an->obuf[0], an->obuf[1]);
an->flag |= OBUF;
if(anxstart(net))
u.u_count -= an->ocnt;
}
anrint(net)
int net;
{
register struct an_dev *an;
register short *dp, *sp;
register struct device *draddr;
register struct uba_device *ui;
short stat;
int i, len, clen;
an = &an_dev[net];
if(an->flag&IBUF)
{
andrain(net);
return;
}
ui = andinfo[net];
draddr = (struct device *)ui->ui_addr;
dp = &draddr->drin;
len = *dp;
len = swab(len);
if(len > MAXMSGLEN)
len = MAXMSGLEN;
sp = an->ibuf;
an->icnt = len;
for(i = (len+1)/2; i; i--)
*sp++ = *dp;
draddr->drcs = STATUS_MODE;
*sp = *dp;
draddr->drcs = DATA_MODE;
i = spl6();
an->flag |= IBUF;
splx(i);
if ((*sp&INBUF_E) == 0)
andrain(net);
}
andrain(net)
int net;
{
register struct an_dev *an;
register short *dp;
short sp;
register struct device *draddr;
register struct uba_device *ui;
short stat;
int i, len;
ui = andinfo[net];
draddr = (struct device *)ui->ui_addr;
dp = &draddr->drin;
do {
len = *dp;
len = swab(len);
if(len > MAXMSGLEN)
len = MAXMSGLEN;
for(i = (len+1)/2; i; i--)
sp = *dp;
sp = *dp;
sp = *dp;
draddr->drcs = STATUS_MODE;
sp = *dp;
draddr->drcs = DATA_MODE;
} while((sp&INBUF_E) == 0);
}
anxstart(net)
int net;
{
register struct an_dev *an;
register short *dp, *sp;
register struct device *draddr;
register struct uba_device *ui;
int retrys, nreps;
int i, len;
ui = andinfo[net];
draddr = (struct device *)ui->ui_addr;
an = &an_dev[net];
dp = &draddr->drout;
draddr->drcs = STATUS_MODE;
i = draddr->drin;
nreps = retrys = 0;
if ( (i&OUTBUF_E) == 0 ) {
do {
if(++retrys > 100000)
{
nreps++;
printf("anxstart: %d retrys on OUTBUF_E loop\n", nreps*retrys);
retrys = 0;
draddr->drcs = CMD_MODE;
if(nreps >= 2)
{
printf("S/NET: MASTER CLEAR\n");
draddr->drout = 0;
draddr->drout = MASTER_CLEAR;
}
draddr->drout = 0;
draddr->drout = BOARD_RESET;
draddr->drout = 0;
draddr->drcs = DATA_MODE;
if(nreps >= 3) return(0);
}
i = draddr->drin;
} while( (i&OUTBUF_E) == 0 );
}
retrys = 0;
len = an->ocnt;
loop:
sp = an->obuf;
draddr->drcs = CMD_MODE;
*dp = *sp++;
draddr->drcs = DATA_MODE;
for(i = (len+1)/2-1; i > 1; i--)
*dp = *sp++;
draddr->drcs = EOP_MODE;
*dp = *sp;
draddr->drcs = STATUS_MODE;
i = draddr->drin;
draddr->drcs = DATA_MODE;
if(i&SNACK) {
if(++retrys < 100)
goto loop;
else
return(0);
}
return(1);
}
anioctl(dev, cmd, addr, flag)
caddr_t addr;
dev_t dev;
{
int i;
int error;
int net = NET(dev);
if(net >= NAN)
RETURN(ENXIO)
switch(cmd)
{
case ANRESET:
/*if(copyin(addr, (caddr_t)&args, sizeof(args)))
RETURN(EFAULT)*/
break;
}
}
#ifdef TIMEOUT
cktimchk()
{
register struct chdat *cp;
register struct sninfo *sninfop;
int unit;
int s;
for(cp=sn_chans; cp < &sn_chans[NUMLCH]; cp++) {
if( cp->flags&(SENTDATA|SENTRDY) && --cp->ckticks == 0 ) {
unit = cp->snunit;
sninfop = &sn_sninfo[unit];
sninfop->snsched++;
sninfop->snenqlost[cp->machno]++;
cp->flags |= RETRY;
if (cp->flags & SENTDATA) {
wakeup((caddr_t)cp->output.buf);
} else {
wakeup((caddr_t)cp->input.buf);
}
}
}
s = spl6();
if (sn_state & OPEN) {
timeout(cktimchk, (caddr_t)0, CKTICKS);
} else {
sn_state &= ~TIMER;
}
splx(s);
}
#endif TIMEOUT
#endif