#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