1: /*
   2:  * Copyright (c) 1986 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  *
   6:  *	@(#)if_sri.c	1.1 (2.10BSD Berkeley) 12/1/86
   7:  */
   8: 
   9: #include "sri.h"
  10: #if NSRI > 0
  11: 
  12: /*
  13:  * SRI dr11c ARPAnet IMP interface driver.
  14:  */
  15: 
  16: #include "param.h"
  17: #include "systm.h"
  18: #include "mbuf.h"
  19: #include "buf.h"
  20: #include "domain.h"
  21: #include "protosw.h"
  22: #include "socket.h"
  23: #include "pdpuba/ubavar.h"
  24: #include "netinet/in.h"
  25: #include "netinet/in_systm.h"
  26: #include "net/if.h"
  27: #include "pdpif/if_sri.h"
  28: #include "netimp/if_imp.h"
  29: #include "pdpif/if_uba.h"
  30: 
  31: int     sriprobe(), sriattach(), srirint(), srixint();
  32: struct  uba_device *sriinfo[NSRI];
  33: u_short sristd[] = { 0 };
  34: struct  uba_driver sridriver =
  35:     { sriprobe, 0, sriattach, 0, sristd, "sri", sriinfo };
  36: #define SRIUNIT(x)  minor(x)
  37: 
  38: #define IFRADDR sc->sri_ifuba.ifu_r.ifrw_info
  39: #define IFWADDR sc->sri_ifuba.ifu_w.ifrw_info
  40: 
  41: int sriinit(), sristart(), srireset();
  42: 
  43: /*
  44:  * "Lower half" of IMP interface driver.
  45:  *
  46:  * Each IMP interface is handled by a common module which handles
  47:  * the IMP-host protocol and a hardware driver which manages the
  48:  * hardware specific details of talking with the IMP.
  49:  *
  50:  * The hardware portion of the IMP driver handles DMA and related
  51:  * management of UNIBUS resources.  The IMP protocol module interprets
  52:  * contents of these messages and "controls" the actions of the
  53:  * hardware module during IMP resets, but not, for instance, during
  54:  * UNIBUS resets.
  55:  *
  56:  * The two modules are coupled at "attach time", and ever after,
  57:  * through the imp interface structure.  Higher level protocols,
  58:  * e.g. IP, interact with the IMP driver, rather than the SRI.
  59:  */
  60: struct  sri_softc {
  61:     /* pdma registers, shared with assembly helper */
  62:     struct sridevice *sri_addr;     /* hardware address */
  63:     char    *sri_iba;               /* in byte addr */
  64:     short   sri_ibc;                /* in byte count */
  65:     short   sri_iclick;             /* in click addr */
  66:     short   sri_ibf;                /* in buf (last byte, plus flags) */
  67:     short   sri_ibusy;              /* in dma busy flag */
  68:     char    *sri_oba;               /* out byte addr */
  69:     short   sri_obc;                /* out byte count */
  70:     short   sri_oclick;             /* out click addr */
  71:     short   sri_oend;               /* out end flags */
  72:     /* end pdma */
  73:     struct  ifnet *sri_if;      /* pointer to IMP's ifnet struct */
  74:     struct  impcb *sri_ic;      /* data structure shared with IMP */
  75:     struct  ifuba sri_ifuba;    /* UNIBUS resources */
  76:     struct  mbuf *sri_iq;       /* input reassembly queue */
  77:     short   sri_olen;       /* size of last message sent */
  78:     char    sri_flush;      /* flush remainder of message */
  79: } sri_softc[NSRI];
  80: 
  81: /*
  82:  * Reset the IMP and cause a transmitter interrupt.
  83:  */
  84: sriprobe(reg)
  85:     caddr_t reg;
  86: {
  87: #if !pdp11
  88:     register int br, cvec;      /* r11, r10 value-result */
  89:     register struct sridevice *addr = (struct sridevice *)reg;
  90:     int i;
  91: 
  92: #ifdef lint
  93:     br = 0; cvec = br; br = cvec;
  94:     srirint(0); srixint(0);
  95: #endif
  96:     addr->csr = 0;
  97:     addr->obf = OUT_HRDY;
  98:     DELAY(100000L);
  99:     addr->csr = SRI_OINT|SRI_OENB;
 100:     addr->obf = OUT_LAST;
 101:     DELAY(100000L);
 102:     addr->csr = 0;
 103:     addr->obf = OUT_HNRDY;
 104:     if(cvec && cvec != 0x200)
 105:         return(1);
 106:     addr->csr = SRI_IINT|SRI_IENB;
 107:     i = addr->ibf;
 108:     DELAY(100000L);
 109:     addr->csr = 0;
 110:     if(cvec && cvec != 0x200)
 111:         cvec -= 4;              /* report as xmit intr */
 112:     return(1);
 113: #endif
 114: }
 115: 
 116: /*
 117:  * Call the IMP module to allow it to set up its internal
 118:  * state, then tie the two modules together by setting up
 119:  * the back pointers to common data structures.
 120:  */
 121: sriattach(ui)
 122:     struct uba_device *ui;
 123: {
 124:     register struct sri_softc *sc = &sri_softc[ui->ui_unit];
 125:     register struct impcb *ip;
 126:     struct ifimpcb {
 127:         struct  ifnet ifimp_if;
 128:         struct  impcb ifimp_impcb;
 129:     } *ifimp;
 130: 
 131:     if ((ifimp = (struct ifimpcb *)impattach(ui, srireset)) == 0)
 132:         panic("sriattach");
 133:     sc->sri_if = &ifimp->ifimp_if;
 134:     ip = &ifimp->ifimp_impcb;
 135:     sc->sri_ic = ip;
 136:     ip->ic_init = sriinit;
 137:     ip->ic_start = sristart;
 138:     sc->sri_if->if_reset = srireset;
 139:     sc->sri_addr = (struct sridevice *) ui->ui_addr;
 140: }
 141: 
 142: /*
 143:  * Reset interface after UNIBUS reset.
 144:  * If interface is on specified uba, reset its state.
 145:  */
 146: srireset(unit, uban)
 147:     int unit, uban;
 148: {
 149:     register struct uba_device *ui;
 150:     struct sri_softc *sc;
 151: 
 152:     if (unit >= NSRI || (ui = sriinfo[unit]) == 0 || ui->ui_alive == 0 ||
 153:         ui->ui_ubanum != uban)
 154:         return;
 155:     printf(" sri%d", unit);
 156:     sc = &sri_softc[unit];
 157:     /* must go through IMP to allow it to set state */
 158:     (*sc->sri_if->if_init)(unit);
 159: }
 160: 
 161: /*
 162:  * Initialize interface: clear recorded pending operations,
 163:  * and retrieve, and initialize UNIBUS resources.  Note
 164:  * return value is used by IMP init routine to mark IMP
 165:  * unavailable for outgoing traffic.
 166:  */
 167: sriinit(unit)
 168:     int unit;
 169: {
 170:     register struct sri_softc *sc;
 171:     register struct uba_device *ui;
 172:     register struct sridevice *addr;
 173:     int x, info;
 174: 
 175:     if (unit >= NSRI || (ui = sriinfo[unit]) == 0 || ui->ui_alive == 0) {
 176:         printf("sri%d: not alive\n", unit);
 177:         return (0);
 178:     }
 179:     sc = &sri_softc[unit];
 180:     /*
 181: 	 * Header length is 0 since we have to passs
 182: 	 * the IMP leader up to the protocol interpretation
 183: 	 * routines.  If we had the header length as
 184: 	 * sizeof(struct imp_leader), then the if_ routines
 185: 	 * would asssume we handle it on input and output.
 186: 	 */
 187: 
 188:     if (if_ubainit(&sc->sri_ifuba, ui->ui_ubanum, 0,
 189:          (int)btoc(IMPMTU)) == 0) {
 190:         printf("sri%d: can't initialize\n", unit);
 191:         goto down;
 192:     }
 193:     addr = (struct sridevice *)ui->ui_addr;
 194: #if pdp11
 195:     sc->sri_iclick = (sc->sri_ifuba.ifu_r.ifrw_click);
 196:     sc->sri_oclick = (sc->sri_ifuba.ifu_w.ifrw_click);
 197: #endif
 198: 
 199:     /*
 200: 	 * Reset the imp interface;
 201: 	 * the delays are pure guesswork.
 202: 	 */
 203:     addr->csr = 0; DELAY(5000L);
 204:     addr->obf = OUT_HRDY;           /* close the relay */
 205:     DELAY(10000L);
 206:     addr->obf = 0;
 207:     /* YECH!!! */
 208:     x = 5;              /* was 500 before rdy line code!!! */
 209:     while (x-- > 0) {
 210:         if ((addr->ibf & IN_INRDY) == 0 )
 211:             break;
 212:         DELAY(10000L);
 213:     }
 214:     if (x <= 0) {
 215: /*		printf("sri%d: imp doesn't respond, ibf=%b\n", unit,
 216: 			addr->ibf, SRI_INBITS);
 217: */
 218:         return(0);  /* goto down;*/
 219:     }
 220: 
 221:     /*
 222: 	 * Put up a read.  We can't restart any outstanding writes
 223: 	 * until we're back in synch with the IMP (i.e. we've flushed
 224: 	 * the NOOPs it throws at us).
 225: 	 * Note: IMPMTU includes the leader.
 226: 	 */
 227:     x = splimp();
 228:     sc->sri_iba = (char *)IFRADDR;
 229:     sc->sri_ibc = IMPMTU;
 230:     sc->sri_ibusy = -1;     /* skip leading zeros */
 231:     addr->csr |= (SRI_IINT|SRI_IENB);
 232:     splx(x);
 233:     return (1);
 234: down:
 235:     ui->ui_alive = 0;
 236:     return (0);
 237: }
 238: 
 239: /*
 240:  * Start output on an interface.
 241:  */
 242: sristart(dev)
 243:     dev_t dev;
 244: {
 245:     int unit = SRIUNIT(dev), info;
 246:     register struct sri_softc *sc = &sri_softc[unit];
 247:     register struct sridevice *addr;
 248:     struct mbuf *m;
 249:     u_short cmd;
 250: 
 251:     if (sc->sri_ic->ic_oactive)
 252:         goto restart;
 253: 
 254:     /*
 255: 	 * Not already active, deqeue a request and
 256: 	 * map it onto the UNIBUS.  If no more
 257: 	 * requeusts, just return.
 258: 	 */
 259:     IF_DEQUEUE(&sc->sri_if->if_snd, m);
 260:     if (m == 0) {
 261:         sc->sri_ic->ic_oactive = 0;
 262:         return;
 263:     }
 264:     sc->sri_olen = ((if_wubaput(&sc->sri_ifuba, m) + 1 ) & ~1);
 265: 
 266: restart:
 267:     addr = (struct sridevice *)sriinfo[unit]->ui_addr;
 268:     sc->sri_oba = (char *)IFWADDR;
 269:     sc->sri_obc = sc->sri_olen;
 270:     sc->sri_oend = OUT_LAST;
 271:     sc->sri_obc--;
 272:     addr->csr |= (SRI_OENB|SRI_OINT);
 273:     addr->obf = (*sc->sri_oba++ & 0377);
 274:     sc->sri_ic->ic_oactive = 1;
 275: }
 276: 
 277: /*
 278:  * Output interrupt handler.
 279:  */
 280: srixint(unit)
 281: {
 282:     register struct sri_softc *sc = &sri_softc[unit];
 283:     register struct sridevice *addr = sc->sri_addr;
 284:     int burst,delay;
 285:     register int x;
 286: 
 287:     burst = 0;
 288:     while(sc->sri_obc > 0) {
 289:         x = (*sc->sri_oba++ & 0377);
 290:         if(--sc->sri_obc <= 0) x |= sc->sri_oend;
 291:         addr->obf = x;
 292:         if(++burst > 16) goto out;
 293:         for(delay=0 ;; delay++) {
 294:             if(delay > 12) goto out;
 295:             if(addr->csr&SRI_OREQ) break;
 296:         }
 297:     }
 298: 
 299:     addr->csr &= ~SRI_OINT;
 300:     if (sc->sri_ic->ic_oactive == 0) {
 301:         printf("sri%d: stray xmit interrupt\n", unit);
 302:         goto out;
 303:     }
 304:     sridump("out",IFWADDR,sc->sri_olen);
 305:     sc->sri_if->if_opackets++;
 306:     sc->sri_ic->ic_oactive = 0;
 307:     if (sc->sri_obc != 0) { /* only happens if IMP ready drop */
 308:         printf("sri%d: output error, csr=%b\n", unit,
 309:             addr->csr, SRI_BITS);
 310:         sc->sri_if->if_oerrors++;
 311:     }
 312:     if (sc->sri_ifuba.ifu_xtofree) {
 313:         m_freem(sc->sri_ifuba.ifu_xtofree);
 314:         sc->sri_ifuba.ifu_xtofree = 0;
 315:     }
 316:     if (sc->sri_if->if_snd.ifq_head)
 317:         sristart(unit);
 318: out:
 319:     return;
 320: }
 321: 
 322: /*
 323:  * Input interrupt handler
 324:  */
 325: srirint(unit)
 326: {
 327:     register struct sri_softc *sc = &sri_softc[unit];
 328:         struct mbuf *m;
 329:     int len, info;
 330:     register struct sridevice *addr = sc->sri_addr;
 331:     int burst,delay;
 332:     register int x;
 333: 
 334:     burst = 0;
 335:     for(;;) {
 336:         addr->csr &= ~SRI_IENB; /* prevents next read from starting */
 337:         sc->sri_ibf = x = addr->ibf;
 338:         if(x & IN_CHECK) break; /* LAST or error */
 339:         if(sc->sri_ibc <= 0) break;     /* spurrious int */
 340:         x &= 0377;
 341:         if(sc->sri_ibusy < 0) { /* flushing leading zeros */
 342:             if(x == 0) goto next;
 343:             sc->sri_ibusy = 1;
 344:         }
 345:         *sc->sri_iba++ = x;
 346:         if(--sc->sri_ibc <= 0) break;   /* count exhausted */
 347:     next:
 348:         addr->csr |= SRI_IENB;  /* start next read */
 349:         if(++burst > 16) goto out;
 350:         for(delay=0 ;; delay++) {
 351:             if(delay > 12) goto out;
 352:             if(addr->csr&SRI_IREQ) break;
 353:         }
 354:     }
 355: 
 356:     x = sc->sri_ibf;
 357:     /* grab the last byte if EOM */
 358:     if((x & IN_LAST) && !(x & IN_INRDY) && sc->sri_ibc > 0) {
 359:         *sc->sri_iba++ = (x & 0377);
 360:         sc->sri_ibc--;
 361:     }
 362:     addr->csr &= ~SRI_IINT;
 363:     sc->sri_if->if_ipackets++;
 364:     if ((x & IN_INRDY)) {
 365:         printf("sri%d: input error, ibf=%b\n", unit,
 366:             x, SRI_INBITS);
 367:         sc->sri_if->if_ierrors++;
 368:         sc->sri_flush = 1;
 369:         if(sc->sri_obc > 0) {   /* if output active */
 370:             sc->sri_obc = -1;       /* flush it */
 371:             srixint(unit);
 372:         }
 373:         /* tell "other half" of module that ready line just dropped */
 374:         /* Kludge, I know, but the alternative is to create an mbuf */
 375:         impinput(unit, (struct  mbuf *) 0); /* ready line dropped */
 376:         goto out; /* leave interrupts un-enabled */ /* FIX THIS!!!! */
 377:     }
 378: 
 379:     if (sc->sri_flush) {
 380:         if (x & IN_LAST)
 381:             sc->sri_flush = 0;
 382:         goto setup;
 383:     }
 384:     len = IMPMTU - sc->sri_ibc;
 385:     if (len < 10 || len > IMPMTU) {
 386:         printf("sri%d: bad length=%d\n", len);
 387:         sc->sri_if->if_ierrors++;
 388:         goto setup;
 389:     }
 390:     sridump("in ",IFRADDR,len);
 391: 
 392:     /*
 393: 	 * The next to last parameter is always 0 since using
 394: 	 * trailers on the ARPAnet is insane.
 395: 	 */
 396:     m = if_rubaget(&sc->sri_ifuba, len, 0, &sc->sri_if);
 397:     if (m == 0)
 398:         goto setup;
 399:     if ((x & IN_LAST) == 0) {
 400:         if (sc->sri_iq)
 401:             m_cat(sc->sri_iq, m);
 402:         else
 403:             sc->sri_iq = m;
 404:         goto setup;
 405:     }
 406:     if (sc->sri_iq) {
 407:         m_cat(sc->sri_iq, m);
 408:         m = sc->sri_iq;
 409:         sc->sri_iq = 0;
 410:     }
 411:     impinput(unit, m);
 412: 
 413: setup:
 414:     /*
 415: 	 * Setup for next message.
 416: 	 */
 417:     sc->sri_iba = (char *)IFRADDR;
 418:     sc->sri_ibc = IMPMTU;
 419:     sc->sri_ibusy = -1;     /* skip leading zeros */
 420:     addr->csr |= (SRI_IINT|SRI_IENB);
 421: out:
 422:     return;
 423: }
 424: 
 425: sridump(str,aba,abc)
 426: char *str,*aba;
 427: {
 428:     int col,i;
 429: 
 430:     if(str[0] != 07)
 431:         if(!sridebug()) return;
 432:     printf("%s  ",str);
 433:     col = 0;
 434:     for(; abc ; abc--) {
 435:         i = *aba++ & 0377;
 436:         printf("%o ",i);
 437:         if(++col > 31) {
 438:             col = 0;
 439:             printf("\n   ");
 440:         }
 441:     }
 442:     printf("\n");
 443: }
 444: 
 445: #if vax
 446: 
 447: sridebug()
 448: {
 449:         return( (mfpr(RXCS) & RXCS_DONE) == 0 &&
 450:             (mfpr(RXDB) & 0177) == 07);
 451: }
 452: 
 453: #endif
 454: #if pdp11
 455: 
 456: sridebug()
 457: {
 458:         return( (*(char *)0177560 & 0200) == 0 &&
 459:             (*(char *)0177562 & 0177) == 07);
 460: }
 461: 
 462: #endif
 463: #endif NSRI

Defined functions

sriattach defined in line 121; used 2 times
sridebug defined in line 456; used 1 times
sridump defined in line 425; used 2 times
sriinit defined in line 167; used 2 times
sriprobe defined in line 84; used 2 times
srireset defined in line 146; used 3 times
srirint defined in line 325; used 2 times
sristart defined in line 242; used 3 times
srixint defined in line 280; used 3 times

Defined variables

sri_softc defined in line 79; used 6 times
sridriver defined in line 34; never used
sriinfo defined in line 32; used 4 times
sristd defined in line 33; used 1 times
  • in line 35

Defined struct's

ifimpcb defined in line 126; used 2 times
  • in line 131(2)
sri_softc defined in line 60; used 12 times

Defined macros

IFRADDR defined in line 38; used 3 times
IFWADDR defined in line 39; used 2 times
SRIUNIT defined in line 36; used 1 times
Last modified: 1990-05-01
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4050
Valid CSS Valid XHTML 1.0 Strict