1*8571Sroot /* lpa.c 4.8 82/10/17 */ 28476Sroot 36968Ssam #include "lpa.h" 46968Ssam #if NLPA > 0 56968Ssam 66968Ssam #include "../h/param.h" 76968Ssam #include "../h/dir.h" 86968Ssam #include "../h/user.h" 96968Ssam #include "../h/buf.h" 106968Ssam #include "../h/proc.h" 116968Ssam #include "../h/ioctl.h" 127729Sroot #include "../h/uio.h" 136968Ssam 148476Sroot #include "../vaxuba/ubavar.h" 158476Sroot 166968Ssam /* 178492Sroot * LPA driver for -- Asa Romberger 188492Sroot * 196968Ssam * open 206968Ssam * write microcode 216968Ssam * write dedicated mode dispatch table 226968Ssam * ioctl TIOCSETP to set parameters 236968Ssam * struct iocb { 246968Ssam * short *baddr; buffer address 256968Ssam * short rate; - 1,000,000 / frequency in Hz 266968Ssam * short wc; 15-13 = number of buffers - 1 276968Ssam * 12-0 = buffer size in words 286968Ssam * } iocb; 296968Ssam * read - 1 character indicating buffer index 306968Ssam * fill or empty buffer 316968Ssam * minor device number = DDCCCCCC where: 326968Ssam * DD = 00 for analog input 336968Ssam * = 01 for analog output 346968Ssam * CCCCCC = channel number 356968Ssam */ 366968Ssam * define NOMCODE to eliminate the microcode download check 376968Ssam */ 388492Sroot /* #define TRACELPA */ 398492Sroot /* #define NOMCODE */ 406968Ssam 416968Ssam #ifdef TRACELPA 426968Ssam # define TRACER(x) printf(x) 436968Ssam # define TRACERN(x, d) printf(x, d) 446968Ssam #else 456968Ssam # define TRACER(x) 466968Ssam # define TRACERN(x, d) 476968Ssam #endif 486968Ssam 496968Ssam /* PRIORITY AT WHICH PROGRAM SHOULD RUN */ 506968Ssam /* THIS SHOULD EVENTUALLY TELL UNIX THIS IS A REAL-TIME DEVICE */ 516968Ssam 526968Ssam #define NICE 0 536968Ssam 548492Sroot #define inc(v) (sc->v = ((sc->v + 1) % sc->sc_nbuf)) 556968Ssam 568492Sroot #define LPAPRI (PZERO + 0) 576968Ssam #define LPAUNIT(dev) 0 586968Ssam #define LPADEVICE(dev) (((dev) >> 6) & 03) 596968Ssam #define LPACHANNEL(dev) ((dev) & 077) 606968Ssam 618492Sroot int lpaprobe(), lpaattach(), lpaiintr(), lpaointr(); 628492Sroot u_short lpastd[] = {0170460, 0}; 638492Sroot struct uba_device *lpadinfo[NLPA]; 646968Ssam struct uba_driver lpadriver = 658492Sroot {lpaprobe, 0, lpaattach, 0, lpastd, "lpa", lpadinfo, 0, 0, 0 }; 666968Ssam 676968Ssam struct lpa_softc { 686968Ssam int sc_flag; /* flags, as defined below */ 696968Ssam int sc_device; /* device: 0 = analog in, 1 = analog out */ 706968Ssam int sc_channel; /* device channel number */ 716968Ssam struct buf sc_ubuffer; /* user buffer header */ 726968Ssam int sc_ubabuf; /* uba allocation pointer for buffer */ 736968Ssam int sc_ubufn; /* present buffer that user is accessing */ 746968Ssam int sc_lbufn; /* present buffer that lpa is accessing */ 756968Ssam int sc_lbufnx; /* next buffer for lpa (value in ustat) */ 766968Ssam int sc_nbuf; /* number of buffers */ 776968Ssam int sc_count; /* buffer size in words */ 786968Ssam short sc_ustat; /* user status word */ 796968Ssam struct buf sc_ustatbuf; /* dummy user status word buffer for ubasetup */ 806968Ssam int sc_ubaustat; /* uba allocation pointer for ustat */ 816968Ssam struct buf *sc_buffer; /* scratch buffer header */ 826968Ssam int sc_start; /* 0 if lpa operation has been started */ 836968Ssam } lpa_softc[NLPA]; 848492Sroot 858492Sroot /* flags for sc_flag */ 866968Ssam #define OPEN 01 /* device is open */ 876968Ssam #define MCODE 02 /* microcode has been loaded */ 886968Ssam #define DMDT 04 /* dedicated mode dispatch table loaded */ 896968Ssam #define STTY 010 /* stty call and device initialized */ 906968Ssam #define SLEEP 020 /* sleeping */ 918492Sroot 928492Sroot /* bits for ustat */ 936968Ssam #define DONE 0100000 /* done */ 946968Ssam #define STOP 0040000 /* stop data transfer */ 956968Ssam #define NBI 0003400 /* next buffer index */ 966968Ssam #define LBI 0000003 /* last buffer index */ 976968Ssam 986968Ssam struct lpadevice { 996968Ssam short lcim; /* control in and maintenance */ 1006968Ssam short lcos; /* control and status out */ 1016968Ssam short lrda; /* request description array address word */ 1026968Ssam short lms; /* maintenance status */ 1036968Ssam }; 1048492Sroot 1058492Sroot /* control in and maintenance register bits */ 1066968Ssam #define READYI 0000200 /* ready in */ 1076968Ssam #define IIE 0000100 /* in interrupt enable */ 1086968Ssam #define RDAEXT 0000014 /* rda address extension */ 1096968Ssam #define RDAEXTOFFSET 2 /* offset of RDAEXT from right side */ 1106968Ssam #define GO 0000001 /* go */ 1116968Ssam #define RUN 0100000 /* run */ 1126968Ssam #define RESET 0040000 /* reset */ 1136968Ssam #define CWRITE 0020000 /* cram write */ 1146968Ssam #define EA 0004000 /* enable arbitration */ 1156968Ssam #define ROMO 0002000 /* rom O */ 1166968Ssam #define ROMI 0001000 /* rom I */ 1176968Ssam #define SMICRO 0000400 /* step microprocessor */ 1188492Sroot 1198492Sroot /* control and status out register bits */ 1206968Ssam #define READYO 0200 /* ready out */ 1216968Ssam #define OIE 0100 /* out interrupt enable */ 1226968Ssam #define UINDEX 0007 /* user index */ 1236968Ssam #define ERROR 0100000 /* error */ 1246968Ssam #define ESTAT 0060000 /* error status */ 1256968Ssam #define ESCODE 0017400 /* error sub code */ 1266968Ssam #define ECODE 0077400 /* error status + error sub code */ 1276968Ssam #define OVERRUN 0243 /* overrun error */ 1286968Ssam 1298492Sroot /* LPA COMMAND DESCRIPTION AREA */ 1306968Ssam 1318492Sroot /* INIT COMMAND */ 1326968Ssam #define INIT 0 /* mode */ 1336968Ssam #define MCVERS 4 /* microcode version */ 1346968Ssam #define ACLOCKA 0170404 /* LPA bus addresses */ 1356968Ssam #define ACLOCKB 0170432 1366968Ssam #define AAD1 0170400 1376968Ssam #define AAD2 1 /* 0170440 - DOES NOT EXIST */ 1386968Ssam #define ADA 0170420 1396968Ssam #define ADIO1 1 /* 0167770 - DOES NOT EXIST */ 1406968Ssam #define ADIO2 1 /* 0167760 - DOES NOT EXIST */ 1416968Ssam #define ADIO3 1 /* 0167750 - DOES NOT EXIST */ 1426968Ssam #define ADIO4 1 /* 0167740 - DOES NOT EXIST */ 1436968Ssam #define ADIO5 1 /* 0167730 - DOES NOT EXIST */ 1448492Sroot 1458492Sroot /* CLOCK START COMMAND */ 1466968Ssam #define CLOCK 1 /* mode */ 1476968Ssam #define CLOCKA 0<<4 /* clock A */ 1488492Sroot /* clock status word */ 1496968Ssam #define ENACTR 1 /* enable counter */ 1506968Ssam #define R1M 1<<1 /* 1 MHz rate */ 1516968Ssam #define R100K 2<<1 /* 100 KHz rate */ 1526968Ssam #define R10K 3<<1 /* 10 KHz rate */ 1536968Ssam #define R1K 4<<1 /* 1 KHz rate */ 1546968Ssam #define R100 5<<1 /* 100 Hz rate */ 1556968Ssam #define REXT 6<<1 /* external rate (from st1 input) */ 1566968Ssam #define R60 7<<1 /* line frequency rate */ 1576968Ssam #define MFIE 0100 /* mode flag interrupt enable */ 1586968Ssam #define MSI 0<<8 /* single interval mode */ 1596968Ssam #define MRI 1<<8 /* repeat interval mode */ 1606968Ssam #define MEET 2<<8 /* external event time mode */ 1616968Ssam #define MEETZ 3<<8 /* external event time mode from zero base */ 1626968Ssam #define ST1EC 020000 /* st1 enable counter */ 1636968Ssam #define ST1IE 040000 /* st1 interrupt enable */ 1648492Sroot 1658492Sroot /* DATA TRANSFER START COMMAND */ 1666968Ssam #define DTS 2 /* mode */ 1676968Ssam #define SCHAN 1<<8 /* single channel */ 1686968Ssam 1696968Ssam lpaprobe(reg) 1708492Sroot caddr_t reg; 1716968Ssam { 1728492Sroot register int br, cvec; /* value result */ 1738492Sroot register struct lpadevice *lpaaddr = (struct lpadevice *)reg; 1746968Ssam 1756968Ssam #ifdef lint 1766968Ssam br = 0; cvec = br; br = cvec; 1776968Ssam #endif 1786968Ssam /* this should force an interrupt, stall, clear the lpa */ 1796968Ssam br = 0x15; 1806968Ssam cvec = 0330; 1816968Ssam TRACER("PROBE\n"); 1827413Skre return (sizeof (struct lpadevice)); 1836968Ssam } 1846968Ssam 1856968Ssam lpaattach(ui) 1868492Sroot register struct upa_device *ui; 1876968Ssam { 1888492Sroot 1896968Ssam } 1906968Ssam 1916968Ssam lpaopen(dev, flag) 1928492Sroot dev_t dev; 1938492Sroot int flag; 1946968Ssam { 1956968Ssam register int unit = LPAUNIT(dev); 1966968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 1976968Ssam register struct uba_device *ui = lpadinfo[unit]; 1986968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 1996968Ssam 2006968Ssam TRACER("OPEN\n"); 2016968Ssam if (unit >= NLPA || sc->sc_flag & OPEN || ui == 0 || 202*8571Sroot ui->ui_alive == 0) 203*8571Sroot return (ENXIO); 2046968Ssam (void) spl7(); 2056968Ssam lpaaddr->lcim = RESET; 2066968Ssam lpaaddr->lcim = 0; 2076968Ssam (void) spl0(); 2086968Ssam lpaaddr->lcos = 0; /* clear the registers as a precaution */ 2096968Ssam lpaaddr->lrda = 0; 2106968Ssam lpaaddr->lms = 0; 2116968Ssam sc->sc_flag = OPEN; 2126968Ssam sc->sc_device = LPADEVICE(dev); 2136968Ssam sc->sc_channel = LPACHANNEL(dev); 2146968Ssam sc->sc_buffer = geteblk(); 2156968Ssam sc->sc_buffer->b_error = 0; 2166968Ssam sc->sc_buffer->b_proc = u.u_procp; 2176968Ssam sc->sc_ubufn = -1; 2186968Ssam /* THIS SHOULD EVENTUALLY SPECIFY "REAL-TIME" */ 2196968Ssam u.u_procp->p_nice = NICE; 220*8571Sroot return (0); 2216968Ssam } 2226968Ssam 2236968Ssam lpaclose(dev, flag) 2248492Sroot dev_t dev; 2258492Sroot int flag; 2266968Ssam { 2276968Ssam register int unit = LPAUNIT(dev); 2286968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 2296968Ssam register struct uba_device *ui = lpadinfo[unit]; 2306968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 2316968Ssam 2326968Ssam if (sc->sc_device && sc->sc_ubufn >= 0 && (sc->sc_flag & ERROR) == 0) { 2336968Ssam if (sc->sc_start) 2346968Ssam lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); 2356968Ssam sc->sc_flag |= STOP; 2366968Ssam (void) spl5(); 2376968Ssam while (sc->sc_flag & STOP) { 2386968Ssam TRACER("SLEEP\n"); 2396968Ssam sc->sc_flag |= SLEEP; 2406968Ssam sleep((caddr_t)sc, LPAPRI); 2416968Ssam } 2426968Ssam } 2436968Ssam (void) spl7(); 2446968Ssam lpaaddr->lcim = RESET; 2456968Ssam lpaaddr->lcim = 0; 2466968Ssam (void) spl0(); 2476968Ssam if (sc->sc_ubabuf) { 2486968Ssam ubarelse(ui->ui_ubanum, &sc->sc_ubabuf); 2496968Ssam sc->sc_ubabuf = 0; 2506968Ssam (void) spl6(); 2516968Ssam vsunlock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount, 2526968Ssam (sc->sc_device)? B_READ : B_WRITE); 2536968Ssam u.u_procp->p_flag &= ~SPHYSIO; 2546968Ssam (void) spl0(); 2556968Ssam } 2566968Ssam if (sc->sc_ubaustat) { 2576968Ssam ubarelse(ui->ui_ubanum, &sc->sc_ubaustat); 2586968Ssam sc->sc_ubaustat = 0; 2596968Ssam } 2606968Ssam if (sc->sc_buffer) { 2616968Ssam brelse(sc->sc_buffer); 2626968Ssam sc->sc_buffer = 0; 2636968Ssam } 2646968Ssam sc->sc_flag = 0; 2656968Ssam TRACER("CLOSE\n"); 2666968Ssam } 2676968Ssam 2687835Sroot lpawrite(dev, uio) 2697835Sroot dev_t dev; 2707835Sroot struct uio *uio; 2716968Ssam { 2726968Ssam register int unit = LPAUNIT(dev); 2736968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 2746968Ssam register struct uba_device *ui = lpadinfo[unit]; 2756968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 2766968Ssam register int f; 2776968Ssam 2786968Ssam TRACER("WRITE\n"); 2796968Ssam f = sc->sc_flag; 2808492Sroot if ((f & OPEN) == 0) 2818492Sroot return (ENXIO); 2828492Sroot if ((f & MCODE) == 0) /* first write is the microcode */ 2838492Sroot return (lpamcode(lpaaddr, sc, uio)); 2848492Sroot if ((f & DMDT) == 0) /* second write is the dispatch table */ 2858492Sroot return (lpadmdt(lpaaddr, sc, ui->ui_ubanum, uio)); 2868492Sroot return (ENXIO); 2876968Ssam } 2886968Ssam 2897835Sroot lpamcode(lpaaddr, sc, uio) 2907835Sroot register struct lpadevice *lpaaddr; 2917835Sroot register struct lpa_softc *sc; 2927835Sroot struct uio *uio; 2936968Ssam { 2946968Ssam short v, r; 2956968Ssam register int mcaddr; 2966968Ssam 2976968Ssam mcaddr = 0; 2987835Sroot while (uio->uio_resid) { 2997835Sroot uiomove(&v, 2, UIO_WRITE, uio); /* get next microcode word */ 3006968Ssam lpaaddr->lcim = 0; /* load microcode word */ 3016968Ssam lpaaddr->lrda = mcaddr; 3026968Ssam lpaaddr->lms = v; 3036968Ssam lpaaddr->lcim = ROMO; 3046968Ssam lpaaddr->lcim |= CWRITE; 3056968Ssam lpaaddr->lcim = 0; /* verify microcode word */ 3066968Ssam lpaaddr->lrda = mcaddr; 3076968Ssam lpaaddr->lcim = ROMO; 3086968Ssam if ((r = lpaaddr->lms) != v) { 3096968Ssam /* download failure */ 3106968Ssam printf("LPA MICROCODE FAIL: exp:%o got:%o\n", v, r); 3118492Sroot return (ENXIO); 3126968Ssam } 3136968Ssam mcaddr++; 3146968Ssam } 3156968Ssam lpaaddr->lcim = RUN | EA; /* turn it on */ 3166968Ssam sc->sc_flag |= MCODE; 3176968Ssam lpaaddr->lcim |= IIE; 3186968Ssam lpaaddr->lcos |= OIE; 3198492Sroot return (0); 3206968Ssam TRACER("MCODE\n"); 3216968Ssam } 3226968Ssam 3237835Sroot lpadmdt(lpaaddr, sc, ubanum, uio) 3247835Sroot register struct lpadevice *lpaaddr; 3257835Sroot register struct lpa_softc *sc; 3267835Sroot register short ubanum; 3277835Sroot struct uio *uio; 3286968Ssam { 3296968Ssam register short *p; 3306968Ssam register int n; 3318492Sroot int error; 3326968Ssam 3336968Ssam p = (short *) sc->sc_buffer->b_un.b_addr; /* INIT */ 3346968Ssam *p++ = (MCVERS << 8) | INIT; /* mode */ 3356968Ssam *p++ = ACLOCKA; /* LPA bus device addresses */ 3366968Ssam *p++ = ACLOCKB; 3376968Ssam *p++ = AAD1; 3386968Ssam *p++ = AAD2; 3396968Ssam *p++ = ADA; 3406968Ssam *p++ = ADIO1; 3416968Ssam *p++ = ADIO2; 3426968Ssam *p++ = ADIO3; 3436968Ssam *p++ = ADIO4; 3446968Ssam *p++ = ADIO5; 3457835Sroot n = min(uio->uio_resid, 256); /* dedicated mode dispatch table */ 3468492Sroot error = uiomove((char *)p, n, UIO_WRITE, uio); 3478492Sroot if (error) 3488492Sroot return (error); 3496968Ssam n >>= 1; 3506968Ssam p += n; 3516968Ssam while (n++ < 128) 3526968Ssam *p++ = 0; 3536968Ssam lpacmd(sc->sc_buffer, lpaaddr, sc, ubanum); 3546968Ssam sc->sc_flag |= DMDT; 3558492Sroot return (0); 3566968Ssam TRACER("DMDT\n"); 3576968Ssam } 3586968Ssam 3597632Ssam lpaioctl(dev, cmd, data, flag) 3607632Ssam dev_t dev; 3617632Ssam caddr_t data; 3626968Ssam { 3636968Ssam register int unit = LPAUNIT(dev); 3646968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 3656968Ssam register struct uba_device *ui = lpadinfo[unit]; 3666968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 3676968Ssam register short *p; 3686968Ssam register int i; 3696968Ssam register int v; 3706968Ssam struct iocb { 3716968Ssam short *baddr; 3726968Ssam short rate; 3736968Ssam short wc; 3747632Ssam } *iocb; 3756968Ssam 3766968Ssam TRACER("IOCTL IN\n"); 377*8571Sroot if (cmd != TIOCSETP || (sc->sc_flag & DMDT) == 0) 378*8571Sroot return (ENXIO); 3797632Ssam iocb = (struct iocb *)data; 3806968Ssam p = (short *) sc->sc_buffer->b_un.b_addr; /* CLOCK START */ 3816968Ssam *p++ = CLOCK | CLOCKA; /* mode */ 3826968Ssam *p++ = ENACTR | R1M | MFIE | MRI; /* clock status */ 3837632Ssam *p = iocb->rate; /* clock preset */ 3846968Ssam lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); 3856968Ssam TRACER("CLOCK STARTED\n"); 3866968Ssam p = (short *) sc->sc_buffer->b_un.b_addr; /* DATA TRANSFER START*/ 3876968Ssam *p++ = (sc->sc_device << 7) | DTS | SCHAN; /* mode */ 3887632Ssam sc->sc_count = iocb->wc & 017777; /* word count per buffer */ 3896968Ssam *p++ = sc->sc_count; 3906968Ssam /* user status word */ 3916968Ssam sc->sc_ustatbuf.b_un.b_addr = (caddr_t) &sc->sc_ustat; 3926968Ssam sc->sc_ustatbuf.b_flags = 0; 3936968Ssam sc->sc_ustatbuf.b_bcount = 2; 3946968Ssam sc->sc_ustatbuf.b_proc = u.u_procp; 3956968Ssam sc->sc_ubaustat = ubasetup(ui->ui_ubanum, &sc->sc_ustatbuf, 0); 3966968Ssam v = sc->sc_ubaustat; 3976968Ssam *p++ = v; 3986968Ssam *p = (v >> 16) & 03; /* into low portion of word */ 3997632Ssam sc->sc_nbuf = (iocb->wc >> 13) & 07; /* number of buffers */ 4006968Ssam *p++ |= sc->sc_nbuf++ << 8; /* into high portion of word */ 4016968Ssam /* buffer addresses */ 4027632Ssam if (useracc(sc->sc_ubuffer.b_un.b_addr = (caddr_t) iocb->baddr, 403*8571Sroot sc->sc_ubuffer.b_bcount = sc->sc_count * sc->sc_nbuf * 2, 404*8571Sroot (i = (sc->sc_device)? B_READ : B_WRITE) ) == NULL) { 4056968Ssam TRACER("USER BUFFER FAULT\n"); 406*8571Sroot return (EFAULT); 4076968Ssam } 4086968Ssam sc->sc_ubuffer.b_flags = B_PHYS | B_BUSY | i; 4096968Ssam sc->sc_ubuffer.b_proc = u.u_procp; 4106968Ssam u.u_procp->p_flag |= SPHYSIO; 4116968Ssam vslock(sc->sc_ubuffer.b_un.b_addr, sc->sc_ubuffer.b_bcount); 4126968Ssam sc->sc_ubabuf = ubasetup(ui->ui_ubanum, &sc->sc_ubuffer, 0); 4136968Ssam v = sc->sc_ubabuf; 4146968Ssam for (i = 0; i < sc->sc_nbuf; i++) { 4156968Ssam *p++ = v; 4166968Ssam *p++ = (v >> 16) & 03; 4176968Ssam v += sc->sc_count * 2; 4186968Ssam } 4196968Ssam for ( ; i <= 7; i++) { 4206968Ssam *p++ = 0; 4216968Ssam *p++ = 0; 4226968Ssam } 4236968Ssam *p++ = 0; *p++ = 0; /* random channel list address */ 4246968Ssam *p++ = 0; /* delay */ 4256968Ssam *p++ = sc->sc_channel; /* start channel, channel inc */ 4266968Ssam *p++ = 1; /* number of samples in a sequence */ 4276968Ssam *p++ = 0; /* dwell */ 4286968Ssam *p++ = 0; /* start word no., event mark word */ 4296968Ssam *p++ = 0; /* start word mask */ 4306968Ssam *p = 0; /* event mark mask */ 4316968Ssam sc->sc_ustat = 0; 4326968Ssam sc->sc_start = (sc->sc_device)? sc->sc_nbuf+1 : 1; 4336968Ssam sc->sc_lbufn = 0; 4346968Ssam sc->sc_lbufnx = 0; 4356968Ssam sc->sc_flag |= STTY; 4366968Ssam TRACER("IOCTL OUT\n"); 437*8571Sroot return (0); 4386968Ssam } 4396968Ssam 4407729Sroot lparead(dev, uio) 4417835Sroot dev_t dev; 4427835Sroot struct uio *uio; 4436968Ssam { 4446968Ssam register int unit = LPAUNIT(dev); 4456968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 4466968Ssam register struct uba_device *ui = lpadinfo[unit]; 4476968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 4486968Ssam 4496968Ssam TRACER("READ\n"); 4508492Sroot if ((sc->sc_flag & STTY) == 0) 4518492Sroot return (ENXIO); 4528492Sroot if (sc->sc_flag & ERROR) 4538492Sroot return (ENXIO); 4546968Ssam if (sc->sc_start) 4556968Ssam if (--sc->sc_start == 0) { 4566968Ssam lpacmd(sc->sc_buffer, lpaaddr, sc, ui->ui_ubanum); 4576968Ssam TRACER("START\n"); 4586968Ssam } 4596968Ssam inc(sc_ubufn); 4606968Ssam if (sc->sc_start == 0) { 4616968Ssam (void) spl5(); 4626968Ssam while (sc->sc_ubufn == sc->sc_lbufn) { 4638492Sroot if (sc->sc_flag & ERROR) 4648492Sroot return (ENXIO); 4656968Ssam TRACER("SLEEP\n"); 4666968Ssam sc->sc_flag |= SLEEP; 4676968Ssam sleep(sc, LPAPRI); 4686968Ssam } 4696968Ssam (void) spl0(); 4706968Ssam } 4716968Ssam TRACERN("READ %d\n", sc->sc_ubufn); 4728492Sroot return (uiomove(&sc->sc_ubufn, 1, UIO_READ, uio)); 4736968Ssam } 4746968Ssam 4756968Ssam lpacmd(bp, lpaaddr, sc, ubanum) 4767835Sroot register struct buf *bp; 4777835Sroot register struct lpadevice *lpaaddr; 4787835Sroot register struct lpa_softc *sc; 4797835Sroot register short ubanum; 4806968Ssam { 4816968Ssam int ubareg; 4826968Ssam 4836968Ssam TRACER("CMD\n"); 4846968Ssam ubareg = ubasetup(ubanum, bp, UBA_NEEDBDP); 4856968Ssam lpawait(lpaaddr, sc); 4866968Ssam lpaaddr->lrda = ubareg; 4876968Ssam lpaaddr->lcim &= ~RDAEXT; 4886968Ssam lpaaddr->lcim |= ((ubareg >> (16-RDAEXTOFFSET)) & RDAEXT) | GO; 4896968Ssam lpawait(lpaaddr, sc); 4906968Ssam ubarelse(ubanum, &ubareg); 4916968Ssam } 4926968Ssam 4936968Ssam lpawait(lpaaddr, sc) 4948492Sroot register struct lpadevice *lpaaddr; 4958492Sroot register struct lpa_softc *sc; 4966968Ssam { 4978492Sroot 4986968Ssam (void) spl5(); 4996968Ssam while ((lpaaddr->lcim & READYI) == 0) { 5006968Ssam TRACER("SLEEP\n"); 5016968Ssam sc->sc_flag |= SLEEP; 5026968Ssam sleep((caddr_t)sc, LPAPRI); 5036968Ssam } 5046968Ssam (void) spl0(); 5056968Ssam } 5066968Ssam 5076968Ssam lpaiintr(unit) 5088492Sroot int unit; 5096968Ssam { 5106968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 5116968Ssam 5126968Ssam TRACER("{I"); 5136968Ssam if (sc->sc_flag & SLEEP) { 5146968Ssam TRACER("<WAKEUP>"); 5156968Ssam wakeup((caddr_t)sc); 5166968Ssam sc->sc_flag &= ~SLEEP; 5176968Ssam } 5186968Ssam TRACER("}"); 5196968Ssam } 5206968Ssam 5216968Ssam lpaointr(unit) 5228492Sroot int unit; 5236968Ssam { 5246968Ssam register int c, m; 5256968Ssam register struct lpa_softc *sc = &lpa_softc[unit]; 5266968Ssam register struct uba_device *ui = lpadinfo[unit]; 5276968Ssam register struct lpadevice *lpaaddr = (struct lpadevice *) ui->ui_addr; 5286968Ssam int spx; 5296968Ssam 5306968Ssam TRACER("{O"); 5316968Ssam if (sc->sc_flag & SLEEP) { 5326968Ssam TRACER("<WAKEUP>"); 5336968Ssam wakeup(sc); 5346968Ssam sc->sc_flag &= ~SLEEP; 5356968Ssam } 5366968Ssam c = lpaaddr->lcos; 5376968Ssam m = lpaaddr->lms; 5386968Ssam lpaaddr->lcos &= ~READYO; 5396968Ssam if (c & ERROR) { 5406968Ssam TRACER("<ERROR>"); 5416968Ssam c = (c >> 8) & 0377; 5426968Ssam if ((sc->sc_flag & STOP) == 0 || (c != OVERRUN)) { 5436968Ssam printf("LPA ERROR %o %o\n", c, m&0177777); 5446968Ssam sc->sc_flag |= ERROR; 5456968Ssam } 5466968Ssam sc->sc_flag &= ~STOP; 5476968Ssam TRACER("}\n"); 5486968Ssam return; 5496968Ssam } 5506968Ssam TRACERN("<LPA %d>", sc->sc_lbufnx); 5516968Ssam sc->sc_lbufn = sc->sc_lbufnx; 5526968Ssam if (sc->sc_ubufn == sc->sc_lbufnx && c & ECODE) { 5536968Ssam TRACER("<STOP?>"); 5546968Ssam if (sc->sc_flag & STOP) 5556968Ssam return; 5566968Ssam printf("LPA OVERRUN\n"); 5576968Ssam sc->sc_flag |= ERROR; 5586968Ssam } 5596968Ssam inc(sc_lbufnx); 5606968Ssam TRACERN("<USTAT %o>", sc->sc_ustat); 5616968Ssam spx = spl7(); 5626968Ssam sc->sc_ustat &= ~NBI; 5636968Ssam sc->sc_ustat |= sc->sc_lbufnx << 8; 5646968Ssam sc->sc_ustat &= ~DONE; 5656968Ssam (void) splx(spx); 5666968Ssam TRACERN("<LPAN %d>}", sc->sc_lbufnx); 5676968Ssam } 5686968Ssam 5696968Ssam lpareset(uban) 5708492Sroot int uban; 5716968Ssam { 5726968Ssam register struct uba_device *ui; 5736968Ssam register struct lpadevice *lpaaddr; 5746968Ssam register struct lpa_softc *sc; 5756968Ssam register int unit; 5766968Ssam 5776968Ssam TRACER("LPA RESET\n"); 5786968Ssam for (unit = 0; unit < NLPA; unit++) { 5798492Sroot if ((ui = lpadinfo[unit]) == 0 || 5808492Sroot ui->ui_ubanum != uban || ui->ui_alive == 0) 5818492Sroot continue; 5826968Ssam printf(" lpa%d", unit); 5836968Ssam lpaaddr = (struct lpadevice *)ui->ui_addr; 5846968Ssam sc = &lpa_softc[unit]; 5856968Ssam sc->sc_flag |= ERROR; 5866968Ssam (void) spl7(); 5876968Ssam lpaaddr->lcim = RESET; 5886968Ssam lpaaddr->lcim = 0; 5896968Ssam (void) spl0(); 5906968Ssam if (sc->sc_flag & SLEEP) { 5916968Ssam wakeup((caddr_t)sc); 5926968Ssam sc->sc_flag &= ~SLEEP; 5936968Ssam } 5946968Ssam } 5956968Ssam } 5966968Ssam #endif NLPA 597