|
|
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 <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: x_sleep(&blocked, pritty, slpriSigCatch, "qqioctl");
220: #else
221: v_sleep(&blocked, CVTTOUT, IVTTOUT, SVTTOUT, "qqioctl");
222: #endif
223: if (SELF->p_ssig && nondsig()) { /* signal? */
224: u.u_error = EINTR;
225: break;
226: }
227: }
228: }
229:
230: int
231: qqtime()
232: {
233: int j;
234: char buffer[20 + 1];
235:
236: buffer[20] = '\0';
237:
238: j = --drvl[QQ_MAJOR].d_time;
239:
240: if ((j % 2) == 0) {
241: if (sg_hal) {
242: qqct += 20;
243: printf("qqtime: j=%d pxcopy(sg_hal=%x, dest=%x, len=%x, space=%x ",
244: j, sg_hal, screen_fp + qqct, 20, SEG_386_KD|SEG_VIRT);
245: pxcopy(sg_hal, buffer, 20,
246: SEG_386_KD|SEG_VIRT);
247: printf("buffer=%s\n", buffer);
248: pxcopy(sg_hal, screen_fp + qqct, 20,
249: SEG_386_KD|SEG_VIRT);
250: } else
251: putchar('?');
252: }
253:
254: if (j == 0) {
255: printf("wakeup\n");
256: blocked = 0;
257: wakeup(&blocked);
258: }
259: }
260:
261: int
262: vtosg(virt, size)
263: int virt;
264: int size;
265: {
266: register SR *srp;
267: register SEG *sp;
268: register caddr_t base;
269: int ret = 0;
270:
271: for (srp=u.u_segl; srp<&u.u_segl[NUSEG]; srp++) {
272: if ((sp=srp->sr_segp) == NULL)
273: continue;
274: #if 0
275: /*
276: * Doing this check means string constants in text
277: * are inaccessible to system global memory.
278: */
279: if ((srp->sr_flag&SRFDATA) == 0)
280: continue;
281: #endif
282: /*
283: * The following calculation is because the system represents
284: * the 'base' of a stack as its upper limit (because it is the
285: * upper limit that is fixed).
286: */
287: base = srp->sr_base;
288: if (srp==&u.u_segl[SISTACK])
289: base -= srp->sr_size;
290:
291: if (virt < base)
292: continue;
293: if (virt + size > base + sp->s_size)
294: continue;
295: ret = MAPIO(sp->s_vmem, virt - base);
296: }
297: return ret;
298: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.