|
|
1.1 root 1: static int blocked;
2: static int sg_hal;
3:
4: /*
5: * qq - sample device driver using absolute memory addressing
6: *
7: * All this device does is read/write video ram.
8: * It assumes that there is a monochrome adapter in use, so that video
9: * ram starts at segment B000; if color, this should be changed to B800.
10: *
11: * This driver does not do anything useful; it is intended to serve as
12: * an example.
13: */
14: #include <sys/coherent.h>
15: #include <sys/stat.h>
16: #include <sys/uproc.h>
17: #include <sys/proc.h>
18: #include <sys/con.h>
19: #include <sys/errno.h>
20: #include <sys/sched.h>
21: #include <sys/seg.h>
22: #include <sys/types.h>
23: #include <sys/mmu.h>
24:
25: /*
26: * Definitions.
27: *
28: */
29: #define MONOVIDEO 0xB000 /* monochrome text RAM segment */
30: #define VIDLENGTH (2048*2) /* screen locations (2 bytes each) */
31:
32: #define QQ_MAJOR 7 /* device major number */
33:
34: /*
35: * Export Functions.
36: */
37: int qqload();
38: int qqopen();
39: int qqclose();
40: int qqread();
41: int qqwrite();
42: int qqunload();
43: int qqioctl();
44: int qqtime();
45:
46: /*
47: * Import Functions
48: */
49: int nulldev();
50: int nonedev();
51:
52: /*
53: * Configuration table.
54: */
55: CON qqcon ={
56: DFCHR, /* Flags */
57: QQ_MAJOR, /* Major index */
58: qqopen, /* Open */
59: qqclose, /* Close */
60: nulldev, /* Block */
61: qqread, /* Read */
62: qqwrite, /* Write */
63: qqioctl, /* Ioctl */
64: nulldev, /* Powerfail */
65: qqtime, /* Timeout */
66: qqload, /* Load */
67: qqunload, /* Unload */
68: nulldev /* Poll */
69: };
70:
71: /*
72: * Local variables.
73: */
74: #ifdef _I386
75: static paddr_t screen_fp; /* virtual address of screen base */
76: #else
77: static faddr_t screen_fp; /* (far *) to access screen */
78: static paddr_t screen_base; /* physical address of screen base */
79: #endif
80: int qqopct;
81:
82: /*
83: * Load Routine.
84: */
85: qqload()
86: {
87: /*
88: * Allocate a selector to map onto the video RAM. ptov() will
89: * return the first available selector of the 8,192 possible.
90: * This is time consuming, so we only want to do this as part
91: * of our initialization code and not on every access.
92: *
93: * Since we are operating in 286 protected mode (ugh), the
94: * second argument to ptov() must not exceed 0x10000L.
95: */
96: #ifdef _I386
97: screen_fp = map_pv(MONOVIDEO<<4, VIDLENGTH);
98: printf("qqload: screen_fp = %x = map_pv(%x, %x)\n",
99: screen_fp, MONOVIDEO<<4, VIDLENGTH);
100: #else
101: screen_base = (paddr_t)((long)(unsigned)MONOVIDEO << 4);
102: screen_fp = ptov(screen_base, (fsize_t)VIDLENGTH);
103: #endif
104: }
105:
106: qqunload()
107: {
108: /*
109: * We have to free up the selector now that we're done using it.
110: */
111: #ifdef _I386
112: unmap_pv(screen_fp);
113: #else
114: vrelse(screen_fp);
115: #endif
116: }
117:
118: /*
119: * Open Routine.
120: */
121: qqopen( dev, mode )
122: dev_t dev;
123: {
124: qqopct++;
125: printf("qqopen %d\n", qqopct);
126: }
127:
128: /*
129: * Close Routine.
130: */
131: qqclose( dev )
132: dev_t dev;
133: {
134: qqopct--;
135: printf("qqclose %d\n", qqopct);
136: }
137:
138: /*
139: * Read Routine.
140: */
141: qqread( dev, iop )
142: dev_t dev;
143: register IO * iop;
144: {
145: static int offset;
146: int c;
147: /*
148: * Read a character code from video RAM
149: * Start reading RAM just after where previous read ended
150: *
151: * Note that "offset" is the value of the displacement into
152: * the screen RAM. Any expression which results in a value
153: * which is less than VIDLENGTH is OK here.
154: */
155: while(iop->io_ioc) {
156: c = ((char *)screen_fp)[offset];
157: if(ioputc(c, iop) == -1)
158: break;
159: offset += 2;
160: offset %= VIDLENGTH;
161: }
162: }
163:
164: /*
165: * Write Routine.
166: */
167: static char flab [] = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ";
168:
169: qqwrite( dev, iop )
170: dev_t dev;
171: register IO * iop;
172: {
173: int offset = 0;
174: int c;
175:
176: struct foob { long la, lb; } f;
177:
178: while (iop->io_ioc >= sizeof(f)) {
179: ioread(iop, &f, sizeof(f));
180: #if MEMCPY
181: /* memcpy from struct f to virtual address */
182: memcpy(screen_fp + offset, &f, sizeof(f));
183: #else
184: /* struct assignment to virtual address (implicit memcpy) */
185: * (struct foob *)(screen_fp + offset) = f;
186: #endif
187: offset += 2 * sizeof(f); /* skip attribute byte */
188: }
189:
190: /* single character writes to virtual address */
191: while ((c = iogetc(iop)) >= 0 && offset < VIDLENGTH) {
192: *(char *)(screen_fp + offset) = c;
193: *(char *)(screen_fp + offset + 1) ^= 0xff;
194: offset += 2; /* skip attribute byte */
195: }
196:
197:
198: /* no virtual address used - xpcopy to physical destination */
199: xpcopy(flab, (MONOVIDEO<<4)+320, 52, SEG_386_KD);
200: }
201:
202: int qqct;
203:
204: int
205: qqioctl(dev, com, vec)
206: dev_t dev;
207: int com;
208: struct sgttyb *vec;
209: {
210: if (com == 333) {
211: ukcopy(vec, screen_fp, 20);
212: sg_hal = vtosg(vec, 20);
213: drvl[QQ_MAJOR].d_time = 30;
214: blocked = 1;
215: qqct = 0;
216: }
217: while (blocked) {
218: #ifdef _I386
219: if (x_sleep (& blocked, pritty, slpriSigCatch,
220: "qqioctl") == PROCESS_SIGNALLED) {
221: #else
222: v_sleep(&blocked, CVTTOUT, IVTTOUT, SVTTOUT, "qqioctl");
223: if (nondsig ()) { /* signal? */
224: #endif
225: u.u_error = EINTR;
226: break;
227: }
228: }
229: }
230:
231: int
232: qqtime()
233: {
234: int j;
235: char buffer[20 + 1];
236:
237: buffer[20] = '\0';
238:
239: j = --drvl[QQ_MAJOR].d_time;
240:
241: if ((j % 2) == 0) {
242: if (sg_hal) {
243: qqct += 20;
244: printf("qqtime: j=%d pxcopy(sg_hal=%x, dest=%x, len=%x, space=%x ",
245: j, sg_hal, screen_fp + qqct, 20, SEG_386_KD|SEG_VIRT);
246: pxcopy(sg_hal, buffer, 20,
247: SEG_386_KD|SEG_VIRT);
248: printf("buffer=%s\n", buffer);
249: pxcopy(sg_hal, screen_fp + qqct, 20,
250: SEG_386_KD|SEG_VIRT);
251: } else
252: putchar('?');
253: }
254:
255: if (j == 0) {
256: printf("wakeup\n");
257: blocked = 0;
258: wakeup(&blocked);
259: }
260: }
261:
262: int
263: vtosg(virt, size)
264: int virt;
265: int size;
266: {
267: register SR *srp;
268: register SEG *sp;
269: register caddr_t base;
270: int ret = 0;
271:
272: for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) {
273: if ((sp=srp->sr_segp) == NULL)
274: continue;
275: #if 0
276: /*
277: * Doing this check means string constants in text
278: * are inaccessible to system global memory.
279: */
280: if ((srp->sr_flag&SRFDATA) == 0)
281: continue;
282: #endif
283: /*
284: * The following calculation is because the system represents
285: * the 'base' of a stack as its upper limit (because it is the
286: * upper limit that is fixed).
287: */
288: base = srp->sr_base;
289: if (srp==&u.u_segl[SISTACK])
290: base -= srp->sr_size;
291:
292: if (virt < base)
293: continue;
294: if (virt + size > base + sp->s_size)
295: continue;
296: ret = MAPIO(sp->s_vmem, virt - base);
297: }
298: return ret;
299: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.