134103Sbostic /*
234103Sbostic * Copyright (c) 1982, 1986 Regents of the University of California.
334103Sbostic * All rights reserved. The Berkeley software License Agreement
434103Sbostic * specifies the terms and conditions for redistribution.
534103Sbostic *
6*45804Sbostic * @(#)ik.c 7.7 (Berkeley) 12/16/90
734103Sbostic */
834103Sbostic
934103Sbostic #include "ik.h"
1034103Sbostic #if NIK > 0
1134103Sbostic /*
1234103Sbostic * Ikonas Frame Buffer Interface -- Bill Reeves.
1334103Sbostic */
14*45804Sbostic #include "../include/pte.h"
1534103Sbostic
16*45804Sbostic #include "sys/param.h"
17*45804Sbostic #include "sys/user.h"
18*45804Sbostic #include "sys/buf.h"
19*45804Sbostic #include "sys/systm.h"
20*45804Sbostic #include "sys/map.h"
21*45804Sbostic #include "sys/uio.h"
22*45804Sbostic #include "sys/ioctl.h"
2334103Sbostic
2434103Sbostic #include "ubareg.h"
2534103Sbostic #include "ubavar.h"
2634103Sbostic #include "ikreg.h"
2734103Sbostic
2834103Sbostic #define IKBUSY 01
2934103Sbostic #define IKDMAPRI (PZERO-1)
3034103Sbostic #define IKWAITPRI (PZERO+1)
3134103Sbostic
3234103Sbostic int ikprobe(), ikattach(), ikintr();
3334103Sbostic struct uba_device *ikdinfo[NIK];
3434103Sbostic u_short ikstd[] = { 0772460, 0000000, 0 };
3534103Sbostic struct uba_driver ikdriver =
3634103Sbostic { ikprobe, 0, ikattach, 0, ikstd, "ik", ikdinfo, 0, 0 };
3734103Sbostic
3834103Sbostic struct ik_softc {
3934103Sbostic char ik_open;
4034103Sbostic short ik_uid;
4134103Sbostic short ik_state;
4234103Sbostic int ik_ubinfo;
4334103Sbostic int ik_count;
4434103Sbostic struct buf *ik_bp;
4534103Sbostic int ik_bufp;
4634103Sbostic int ik_icnt;
4734103Sbostic } ik_softc[NIK];
4834103Sbostic
4934103Sbostic int ikstrategy();
5034103Sbostic u_int ikminphys();
5134103Sbostic struct buf rikbuf[NIK];
5234103Sbostic
5334103Sbostic #define IKUNIT(dev) (minor(dev))
5434103Sbostic
ikprobe(reg)5534103Sbostic ikprobe(reg)
5634103Sbostic caddr_t reg;
5734103Sbostic {
5834103Sbostic register int br, cvec; /* value-result */
5934103Sbostic register struct ikdevice *ikaddr = (struct ikdevice *) reg;
6034103Sbostic
6134103Sbostic #ifdef lint
6234103Sbostic br = 0; cvec = br; br = cvec;
6334103Sbostic ikintr(0);
6434103Sbostic #endif
6534103Sbostic ikaddr->ik_istat = 0;
6634103Sbostic ikaddr->ik_xaddr = 0;
6734103Sbostic ikaddr->ik_yaddr = 0;
6834103Sbostic ikaddr->ik_ustat = IK_IENABLE | IK_GO;
6934103Sbostic DELAY(10000);
7034103Sbostic ikaddr->ik_ustat = 0;
7134103Sbostic return (sizeof (struct ikdevice));
7234103Sbostic }
7334103Sbostic
7434103Sbostic /*ARGSUSED*/
7534103Sbostic ikattach(ui)
7634103Sbostic struct uba_device *ui;
7734103Sbostic {
7834103Sbostic
7934103Sbostic }
8034103Sbostic
ikopen(dev)8134103Sbostic ikopen(dev)
8234103Sbostic dev_t dev;
8334103Sbostic {
8434103Sbostic register struct ik_softc *ikp;
8534103Sbostic register struct uba_device *ui;
8634103Sbostic
8734103Sbostic if (IKUNIT(dev) >= NIK || (ikp = &ik_softc[minor(dev)])->ik_open ||
8834103Sbostic (ui = ikdinfo[IKUNIT(dev)]) == 0 || ui->ui_alive == 0)
8934103Sbostic return (ENXIO);
9034103Sbostic ikp->ik_open = 1;
9134103Sbostic ikp->ik_icnt = 0;
9234103Sbostic ikp->ik_state = 0;
9334103Sbostic ikp->ik_uid = u.u_uid;
9434103Sbostic maptouser(ui->ui_addr);
9534103Sbostic return (0);
9634103Sbostic }
9734103Sbostic
ikclose(dev)9834103Sbostic ikclose(dev)
9934103Sbostic dev_t dev;
10034103Sbostic {
10134103Sbostic
10234103Sbostic ik_softc[minor(dev)].ik_open = 0;
10334103Sbostic ik_softc[minor(dev)].ik_state = 0;
10434103Sbostic unmaptouser(ikdinfo[IKUNIT(dev)]->ui_addr);
10540729Skarels return (0);
10634103Sbostic }
10734103Sbostic
ikread(dev,uio)10834103Sbostic ikread(dev, uio)
10934103Sbostic dev_t dev;
11034103Sbostic struct uio *uio;
11134103Sbostic {
11234103Sbostic register int unit = IKUNIT(dev);
11334103Sbostic
11434103Sbostic if (unit >= NIK)
11534103Sbostic return (ENXIO);
11634103Sbostic return (physio(ikstrategy, &rikbuf[unit], dev, B_READ, ikminphys, uio));
11734103Sbostic }
11834103Sbostic
ikwrite(dev,uio)11934103Sbostic ikwrite(dev, uio)
12034103Sbostic dev_t dev;
12134103Sbostic struct uio *uio;
12234103Sbostic {
12334103Sbostic register int unit = IKUNIT(dev);
12434103Sbostic
12534103Sbostic if (unit >= NIK)
12634103Sbostic return (ENXIO);
12734103Sbostic return (physio(ikstrategy, &rikbuf[unit], dev, B_WRITE, ikminphys, uio));
12834103Sbostic }
12934103Sbostic
13034103Sbostic u_int
ikminphys(bp)13134103Sbostic ikminphys(bp)
13234103Sbostic register struct buf *bp;
13334103Sbostic {
13434103Sbostic
13534103Sbostic if (bp->b_bcount > 65536) /* may be able to do twice as much */
13634103Sbostic bp->b_bcount = 65536;
13734103Sbostic }
13834103Sbostic
ikstrategy(bp)13934103Sbostic ikstrategy(bp)
14034103Sbostic register struct buf *bp;
14134103Sbostic {
14234103Sbostic register struct ik_softc *ikp = &ik_softc[IKUNIT(bp->b_dev)];
14334103Sbostic register struct uba_device *ui;
14434103Sbostic
14534103Sbostic if (IKUNIT(bp->b_dev) >= NIK || (ui = ikdinfo[IKUNIT(bp->b_dev)]) == 0
14634103Sbostic || ui->ui_alive == 0)
14734103Sbostic goto bad;
14834103Sbostic (void) spl5();
14934103Sbostic while (ikp->ik_state & IKBUSY)
15040729Skarels (void) tsleep((caddr_t)ikp, IKDMAPRI+1, devout, 0);
15134103Sbostic ikp->ik_state |= IKBUSY;
15234103Sbostic ikp->ik_bp = bp;
15334103Sbostic ikp->ik_ubinfo = ubasetup(ui->ui_ubanum, bp, UBA_NEEDBDP);
15436035Skarels ikp->ik_bufp = UBAI_ADDR(ikp->ik_ubinfo);
15534103Sbostic ikp->ik_count = -(bp->b_bcount>>1); /* its a word count */
15634103Sbostic ikstart(ui);
15734103Sbostic while (ikp->ik_state&IKBUSY)
15840729Skarels (void) tsleep((caddr_t)ikp, IKDMAPRI, devout, 0);
15934103Sbostic ikp->ik_count = 0;
16034103Sbostic ikp->ik_bufp = 0;
16134103Sbostic (void) spl0();
16234103Sbostic ubarelse(ui->ui_ubanum, &ikp->ik_ubinfo);
16334103Sbostic ikp->ik_bp = 0;
16434103Sbostic iodone(bp);
16534103Sbostic wakeup((caddr_t)ikp);
16634103Sbostic return;
16734103Sbostic bad:
16834103Sbostic bp->b_flags |= B_ERROR;
16934103Sbostic iodone(bp);
17034103Sbostic return;
17134103Sbostic }
17234103Sbostic
ikstart(ui)17334103Sbostic ikstart(ui)
17434103Sbostic register struct uba_device *ui;
17534103Sbostic {
17634103Sbostic register int istat;
17734103Sbostic register struct ikdevice *ikaddr = (struct ikdevice *) ui->ui_addr;
17834103Sbostic register struct ik_softc *ikp = &ik_softc[IKUNIT(ui->ui_unit)];
17934103Sbostic
18034103Sbostic istat = ikaddr->ik_istat|DMAENABLE;
18134103Sbostic ikaddr->ik_istat = istat;
18234103Sbostic ikaddr->ik_wc = ikp->ik_count;
18334103Sbostic ikaddr->ik_ubaddr = ikp->ik_bufp;
18434103Sbostic ikaddr->ik_ustat = IK_GO|IK_IENABLE|((ikp->ik_bufp>>12)&060);
18534103Sbostic }
18634103Sbostic
18734103Sbostic /*ARGSUSED*/
ikioctl(dev,cmd,data,flag)18834103Sbostic ikioctl(dev, cmd, data, flag)
18934103Sbostic dev_t dev;
19034103Sbostic int cmd;
19134103Sbostic register caddr_t data;
19234103Sbostic int flag;
19334103Sbostic {
19434103Sbostic register struct uba_device *ui = ikdinfo[IKUNIT(dev)];
19534103Sbostic register struct ik_softc *ikp;
19640729Skarels int error = 0;
19734103Sbostic
19834103Sbostic switch (cmd) {
19934103Sbostic
20034103Sbostic case IKIOGETADDR:
20134103Sbostic *(caddr_t *)data = ui->ui_addr;
20234103Sbostic break;
20334103Sbostic
20434103Sbostic case IKIOWAITINT:
20534103Sbostic ikp = &ik_softc[IKUNIT(dev)];
20634103Sbostic ikp->ik_state |= IKBUSY;
20740729Skarels while (ikp->ik_state&IKBUSY && error == 0)
20840729Skarels error = tsleep((caddr_t)ikp, IKWAITPRI | PCATCH,
20940729Skarels devwait, 0);
21034103Sbostic break;
21134103Sbostic
21234103Sbostic default:
21334103Sbostic return (ENOTTY);
21434103Sbostic }
21540729Skarels return (error);
21634103Sbostic }
21734103Sbostic
21834103Sbostic /*ARGSUSED*/
ikintr(dev)21934103Sbostic ikintr(dev)
22034103Sbostic dev_t dev;
22134103Sbostic {
22234103Sbostic register struct ikdevice *ikaddr =
22334103Sbostic (struct ikdevice *) ikdinfo[IKUNIT(dev)]->ui_addr;
22434103Sbostic register struct ik_softc *ikp = &ik_softc[IKUNIT(dev)];
22534103Sbostic
22634103Sbostic ikp->ik_icnt++;
22734103Sbostic if (ikp->ik_state&IKBUSY) {
22834103Sbostic ikaddr->ik_ustat = 0;
22934103Sbostic ikp->ik_state &= ~IKBUSY;
23034103Sbostic wakeup((caddr_t)ikp);
23134103Sbostic }
23234103Sbostic }
23334103Sbostic
ikreset(uban)23434103Sbostic ikreset(uban)
23534103Sbostic int uban;
23634103Sbostic {
23734103Sbostic register int i;
23834103Sbostic register struct uba_device *ui;
23934103Sbostic register struct ik_softc *ikp = ik_softc;
24034103Sbostic
24134103Sbostic for (i = 0; i < NIK; i++, ikp++) {
24234103Sbostic if ((ui = ikdinfo[i]) == 0 || ui->ui_alive == 0 ||
24334103Sbostic ui->ui_ubanum != uban || ikp->ik_open == 0)
24434103Sbostic continue;
24534103Sbostic printf(" ik%d", i);
24634103Sbostic if ((ikp->ik_state&IKBUSY) == 0)
24734103Sbostic continue;
24834103Sbostic ikp->ik_ubinfo =
24934103Sbostic ubasetup(ui->ui_ubanum, ikp->ik_bp, UBA_NEEDBDP);
25034103Sbostic ikp->ik_count = -(ikp->ik_bp->b_bcount/2);
25134103Sbostic ikstart(ui);
25234103Sbostic }
25334103Sbostic }
25434103Sbostic #endif
255