Commit | Line | Data |
---|---|---|
da7c5cc6 | 1 | /* |
0880b18e | 2 | * Copyright (c) 1982, 1986 Regents of the University of California. |
da7c5cc6 KM |
3 | * All rights reserved. The Berkeley software License Agreement |
4 | * specifies the terms and conditions for redistribution. | |
5 | * | |
0880b18e | 6 | * @(#)ps.c 7.1 (Berkeley) %G% |
da7c5cc6 | 7 | */ |
705372a2 SL |
8 | |
9 | /* | |
bdb9a395 | 10 | * Evans and Sutherland Picture System 2 driver -- Bill Reeves. |
705372a2 SL |
11 | */ |
12 | ||
13 | /* | |
14 | * Still to be done: | |
15 | * WAIT_HIT | |
16 | */ | |
17 | ||
18 | #include "ps.h" | |
19 | #if NPS > 0 | |
20 | ||
21 | #define EXTERNAL_SYNC | |
22 | ||
961945a8 SL |
23 | #include "../machine/pte.h" |
24 | ||
ff360633 JB |
25 | #include "param.h" |
26 | #include "systm.h" | |
27 | #include "ioctl.h" | |
28 | #include "map.h" | |
29 | #include "buf.h" | |
30 | #include "conf.h" | |
31 | #include "dir.h" | |
32 | #include "user.h" | |
33 | #include "uio.h" | |
34 | ||
35 | #include "ubareg.h" | |
36 | #include "ubavar.h" | |
37 | #include "psreg.h" | |
896962b1 | 38 | |
5db7da11 SL |
39 | int psprobe(), psattach(), psextsync(); |
40 | int psclockintr(), pssystemintr(), psdeviceintr(), psdmaintr(); | |
705372a2 SL |
41 | struct uba_device *psdinfo[NPS]; |
42 | u_short psstd[] = { 0 }; | |
43 | struct uba_driver psdriver = | |
44 | { psprobe, 0, psattach, 0, psstd, "ps", psdinfo }; | |
45 | ||
46 | #define PSUNIT(dev) (minor(dev)) | |
47 | ||
aaa53878 SL |
48 | #define MAXAUTOREFRESH 4 |
49 | #define MAXAUTOMAP 4 | |
50 | #define MAXDBSIZE (0177777/2) | |
705372a2 | 51 | |
aaa53878 | 52 | #define PSPRI (PZERO+1) |
705372a2 | 53 | |
aaa53878 SL |
54 | #define PSWAIT(psaddr) { \ |
55 | register short i = 20000, j; \ | |
56 | while (i-- != 0 && ((j = psaddr->ps_iostat) & DIOREADY) == 0) \ | |
57 | ;\ | |
58 | } | |
59 | ||
60 | struct psrefresh { | |
61 | enum { | |
62 | SINGLE_STEP_RF, | |
63 | AUTO_RF, | |
64 | TIME_RF | |
65 | } state; | |
66 | enum { | |
67 | RUNNING_RF, | |
68 | SYNCING_RF, | |
69 | WAITING_MAP, | |
70 | STOPPED_RF | |
71 | } mode; | |
72 | u_short sraddrs[MAXAUTOREFRESH]; | |
73 | short nsraddrs; | |
74 | short srcntr; | |
75 | char waiting; | |
76 | char stop; | |
77 | int icnt; | |
78 | int timecnt; | |
79 | }; | |
80 | ||
81 | struct psdbuffer { | |
82 | enum { | |
83 | ON_DB, | |
84 | OFF_DB | |
85 | } state; | |
86 | u_short dbaddrs[2]; | |
87 | u_short dbsize; | |
88 | short rbuffer; | |
89 | }; | |
90 | ||
91 | struct psmap { | |
92 | enum { | |
93 | SINGLE_STEP_MAP, | |
94 | AUTO_MAP | |
95 | } state; | |
96 | enum { | |
97 | RUNNING_MAP, | |
98 | WAITING_RF, | |
99 | WAITING_START, | |
100 | STOPPED_MAP | |
101 | } mode; | |
102 | u_short maddrs[MAXAUTOMAP]; | |
103 | short nmaddrs; | |
104 | short mcntr; | |
105 | short outputstart; | |
106 | char waiting; | |
107 | char stop; | |
108 | int icnt; | |
109 | }; | |
705372a2 | 110 | |
aaa53878 SL |
111 | /* |
112 | * PS2 software state. | |
113 | */ | |
705372a2 | 114 | struct ps { |
aaa53878 SL |
115 | char ps_open; /* device is open */ |
116 | uid_t ps_uid; /* uid of device owner */ | |
117 | struct psrefresh ps_refresh; /* refresh state */ | |
118 | struct psdbuffer ps_dbuffer; /* double buffering state */ | |
119 | struct psmap ps_map; /* segment map state */ | |
120 | int ps_clockticks; /* clock ints between refresh */ | |
121 | int ps_clockmiss; /* clock ints w/o refresh */ | |
122 | int ps_clockcnt; /* count of clock interrupts */ | |
123 | int ps_hitcnt; /* count of hit interrupts */ | |
124 | int ps_strayintr; /* count of stray interrupts */ | |
125 | int ps_icnt; /* count of system interrupts */ | |
126 | /* BEGIN GROT */ | |
127 | int ps_lastrequest; | |
128 | int ps_lastrequest2; | |
129 | int ps_lastfunnyrequest; | |
130 | int ps_funnycnt; | |
131 | /* END GROT */ | |
705372a2 SL |
132 | } ps[NPS]; |
133 | ||
134 | psprobe(reg) | |
135 | caddr_t reg; | |
136 | { | |
137 | register int br, cvec; | |
aaa53878 | 138 | register struct psdevice *psaddr = (struct psdevice *)reg; |
705372a2 | 139 | |
5db7da11 SL |
140 | #ifdef lint |
141 | br = 0; cvec = br; br = cvec; | |
142 | psclockintr((dev_t)0); pssystemintr((dev_t)0); | |
143 | psdeviceintr((dev_t)0); psdmaintr((dev_t)0); | |
144 | psextsync(0, 0); | |
145 | #endif | |
705372a2 SL |
146 | psaddr->ps_iostat = PSRESET; |
147 | DELAY(200); | |
148 | psaddr->ps_addr = RTCIE; | |
aaa53878 | 149 | PSWAIT(psaddr); psaddr->ps_data = 01; |
705372a2 SL |
150 | psaddr->ps_iostat = PSIE; |
151 | psaddr->ps_addr = RTCSR; | |
aaa53878 | 152 | PSWAIT(psaddr); psaddr->ps_data = SYNC|RUN; |
705372a2 SL |
153 | DELAY(200000); |
154 | psaddr->ps_addr = RTCREQ; | |
aaa53878 | 155 | PSWAIT(psaddr); psaddr->ps_data = 01; |
705372a2 SL |
156 | psaddr->ps_iostat = 0; |
157 | psaddr->ps_iostat = PSRESET; | |
9c0adba0 | 158 | return (sizeof (struct psdevice)); |
705372a2 SL |
159 | } |
160 | ||
161 | /*ARGSUSED*/ | |
162 | psattach(ui) | |
5db7da11 | 163 | struct uba_device *ui; |
705372a2 | 164 | { |
705372a2 | 165 | |
7da157da | 166 | } |
705372a2 SL |
167 | |
168 | psopen(dev) | |
169 | dev_t dev; | |
170 | { | |
171 | register struct ps *psp; | |
172 | register struct uba_device *ui; | |
173 | register int unit = PSUNIT(dev); | |
174 | ||
7da157da BJ |
175 | if (unit >= NPS || (psp = &ps[minor(dev)])->ps_open || |
176 | (ui = psdinfo[unit]) == 0 || ui->ui_alive == 0) | |
177 | return (ENXIO); | |
705372a2 SL |
178 | psp->ps_open = 1; |
179 | psp->ps_uid = u.u_uid; | |
180 | psp->ps_strayintr = 0; | |
181 | psp->ps_refresh.state = SINGLE_STEP_RF; | |
5db7da11 | 182 | psp->ps_refresh.mode = STOPPED_RF; |
705372a2 SL |
183 | psp->ps_refresh.waiting = 0; |
184 | psp->ps_refresh.stop = 0; | |
185 | psp->ps_dbuffer.state = OFF_DB; | |
186 | psp->ps_map.state = SINGLE_STEP_MAP; | |
5db7da11 | 187 | psp->ps_map.mode = STOPPED_MAP; |
705372a2 SL |
188 | psp->ps_map.waiting = 0; |
189 | psp->ps_map.stop = 0; | |
aaa53878 SL |
190 | psp->ps_clockticks = 0; |
191 | psp->ps_clockmiss = 0; | |
192 | psp->ps_refresh.icnt = psp->ps_map.icnt = psp->ps_clockcnt = 0; | |
193 | psp->ps_hitcnt = 0; | |
c5c0b1fb | 194 | psp->ps_icnt = 0; |
705372a2 | 195 | maptouser(ui->ui_addr); |
7da157da | 196 | return (0); |
705372a2 SL |
197 | } |
198 | ||
199 | psclose(dev) | |
200 | dev_t dev; | |
201 | { | |
202 | register struct psdevice *psaddr = | |
aaa53878 | 203 | (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; |
705372a2 SL |
204 | |
205 | ps[PSUNIT(dev)].ps_open = 0; | |
aaa53878 SL |
206 | psaddr->ps_iostat = 0; /* clear IENABLE */ |
207 | PSWAIT(psaddr); psaddr->ps_addr = RFSR; /* set in auto refresh mode */ | |
208 | PSWAIT(psaddr); psaddr->ps_data = AUTOREF; | |
5db7da11 | 209 | unmaptouser((caddr_t)psaddr); |
705372a2 SL |
210 | } |
211 | ||
212 | /*ARGSUSED*/ | |
740e4029 | 213 | psread(dev, uio) |
705372a2 | 214 | dev_t dev; |
740e4029 | 215 | struct uio *uio; |
705372a2 SL |
216 | { |
217 | } | |
218 | ||
219 | /*ARGSUSED*/ | |
740e4029 | 220 | pswrite(dev, uio) |
705372a2 | 221 | dev_t dev; |
740e4029 | 222 | struct uio *uio; |
705372a2 SL |
223 | { |
224 | } | |
225 | ||
226 | /*ARGSUSED*/ | |
942f05a9 SL |
227 | psioctl(dev, cmd, data, flag) |
228 | register caddr_t data; | |
705372a2 SL |
229 | { |
230 | register struct uba_device *ui = psdinfo[PSUNIT(dev)]; | |
231 | register struct ps *psp = &ps[PSUNIT(dev)]; | |
942f05a9 | 232 | int *waddr = *(int **)data; |
705372a2 SL |
233 | int n, arg, i; |
234 | ||
235 | switch (cmd) { | |
942f05a9 SL |
236 | |
237 | case PSIOGETADDR: | |
238 | *(caddr_t *)data = ui->ui_addr; | |
705372a2 | 239 | break; |
942f05a9 SL |
240 | |
241 | case PSIOAUTOREFRESH: | |
5db7da11 | 242 | n = fuword((caddr_t)waddr++); |
7da157da BJ |
243 | if (n == -1) |
244 | return (EFAULT); | |
245 | if (n < 0 || n > MAXAUTOREFRESH) | |
246 | return (EINVAL); | |
247 | for (i = 0; i < n; i++) { | |
5db7da11 | 248 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
7da157da BJ |
249 | return (EFAULT); |
250 | psp->ps_refresh.sraddrs[i] = arg; | |
705372a2 | 251 | } |
7da157da BJ |
252 | psp->ps_refresh.state = AUTO_RF; |
253 | psp->ps_refresh.nsraddrs = n; | |
254 | psp->ps_refresh.srcntr = 0; | |
255 | psp->ps_refresh.mode = WAITING_MAP; | |
705372a2 | 256 | break; |
942f05a9 SL |
257 | |
258 | case PSIOAUTOMAP: | |
5db7da11 | 259 | n = fuword((caddr_t)waddr++); |
7da157da BJ |
260 | if (n == -1) |
261 | return (EFAULT); | |
262 | if (n < 0 || n > MAXAUTOMAP) | |
263 | return (EINVAL); | |
264 | for (i = 0; i < n; i++) { | |
5db7da11 | 265 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
7da157da BJ |
266 | return (EFAULT); |
267 | psp->ps_map.maddrs[i] = arg; | |
705372a2 | 268 | } |
5db7da11 | 269 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
7da157da BJ |
270 | return (EFAULT); |
271 | psp->ps_map.outputstart = arg; | |
272 | psp->ps_map.state = AUTO_MAP; | |
273 | psp->ps_map.nmaddrs = n; | |
274 | psp->ps_map.mcntr = 0; | |
275 | psp->ps_map.mode = WAITING_START; | |
705372a2 | 276 | break; |
942f05a9 SL |
277 | |
278 | case PSIOSINGLEREFRESH: | |
705372a2 SL |
279 | psp->ps_refresh.state = SINGLE_STEP_RF; |
280 | break; | |
942f05a9 SL |
281 | |
282 | case PSIOSINGLEMAP: | |
705372a2 SL |
283 | psp->ps_map.state = SINGLE_STEP_MAP; |
284 | break; | |
942f05a9 SL |
285 | |
286 | case PSIODOUBLEBUFFER: | |
5db7da11 | 287 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
7da157da BJ |
288 | return (EFAULT); |
289 | psp->ps_dbuffer.dbaddrs[0] = arg; | |
5db7da11 | 290 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
7da157da BJ |
291 | return (EFAULT); |
292 | if (arg <= 0 || arg > MAXDBSIZE) | |
293 | return (EINVAL); | |
294 | psp->ps_dbuffer.dbsize = arg; | |
aaa53878 | 295 | psp->ps_dbuffer.dbaddrs[1] = psp->ps_dbuffer.dbaddrs[0]+arg; |
7da157da BJ |
296 | psp->ps_dbuffer.state = ON_DB; |
297 | psp->ps_dbuffer.rbuffer = 0; | |
705372a2 | 298 | break; |
942f05a9 SL |
299 | |
300 | case PSIOSINGLEBUFFER: | |
705372a2 SL |
301 | psp->ps_dbuffer.state = OFF_DB; |
302 | break; | |
942f05a9 | 303 | |
c5c0b1fb SL |
304 | case PSIOTIMEREFRESH: |
305 | if (psp->ps_refresh.state != SINGLE_STEP_RF) | |
aaa53878 | 306 | return (EINVAL); |
5db7da11 | 307 | if ((arg = fuword((caddr_t)waddr++)) == -1) |
aaa53878 | 308 | return (EFAULT); |
c5c0b1fb SL |
309 | psp->ps_refresh.state = TIME_RF; |
310 | psp->ps_refresh.timecnt = arg; | |
311 | break; | |
312 | ||
942f05a9 | 313 | case PSIOWAITREFRESH: |
7da157da | 314 | if (psp->ps_refresh.mode != RUNNING_RF) /* not running */ |
aaa53878 | 315 | return (0); /* dont wait */ |
7da157da | 316 | /* fall into ... */ |
942f05a9 | 317 | |
c5c0b1fb SL |
318 | case PSIOSTOPREFRESH: |
319 | if (cmd == PSIOSTOPREFRESH) { | |
aaa53878 SL |
320 | if (psp->ps_refresh.mode == STOPPED_RF && |
321 | psp->ps_refresh.state != TIME_RF) | |
c5c0b1fb | 322 | return (0); |
705372a2 | 323 | psp->ps_refresh.stop = 1; |
c5c0b1fb | 324 | } |
aaa53878 | 325 | (void) spl5(); |
705372a2 | 326 | psp->ps_refresh.waiting = 1; |
7da157da | 327 | while (psp->ps_refresh.waiting) |
705372a2 | 328 | sleep(&psp->ps_refresh.waiting, PSPRI); |
aaa53878 | 329 | (void) spl0(); |
c5c0b1fb SL |
330 | if (cmd == PSIOSTOPREFRESH) |
331 | psp->ps_refresh.mode = STOPPED_RF; | |
332 | if (psp->ps_refresh.state == TIME_RF) | |
333 | psp->ps_refresh.state = SINGLE_STEP_RF; | |
705372a2 | 334 | break; |
942f05a9 SL |
335 | |
336 | case PSIOWAITMAP: | |
7da157da | 337 | if (psp->ps_map.mode != RUNNING_MAP) /* not running */ |
aaa53878 | 338 | return (0); /* dont wait */ |
7da157da | 339 | /* fall into ... */ |
942f05a9 SL |
340 | |
341 | case PSIOSTOPMAP: | |
c5c0b1fb | 342 | if (cmd == PSIOSTOPMAP) |
705372a2 | 343 | psp->ps_map.stop = 1; |
aaa53878 | 344 | (void) spl5(); |
705372a2 | 345 | psp->ps_map.waiting = 1; |
7da157da | 346 | while (psp->ps_map.waiting) |
705372a2 | 347 | sleep(&psp->ps_map.waiting, PSPRI); |
aaa53878 | 348 | (void) spl0(); |
705372a2 | 349 | break; |
942f05a9 | 350 | |
705372a2 | 351 | default: |
7da157da | 352 | return (ENOTTY); |
705372a2 SL |
353 | break; |
354 | } | |
7da157da | 355 | return (0); |
705372a2 SL |
356 | } |
357 | ||
aaa53878 SL |
358 | #define SAVEPSADDR(psaddr, savepsaddr) { \ |
359 | register short i, xx1; \ | |
8011f5df | 360 | xx1 = splclock(); \ |
aaa53878 SL |
361 | i = psaddr->ps_addr; \ |
362 | while ((psaddr->ps_iostat & DIOREADY) == 0) \ | |
363 | ; \ | |
364 | savepsaddr = psaddr->ps_data; \ | |
365 | splx(xx1); \ | |
366 | } | |
367 | #define RESTORPSADDR(psaddr, savepsaddr) { \ | |
368 | register short xx2; \ | |
8011f5df | 369 | xx2 = splclock(); \ |
aaa53878 SL |
370 | while ((psaddr->ps_iostat & DIOREADY) == 0) \ |
371 | ;\ | |
372 | psaddr->ps_addr = savepsaddr; \ | |
373 | splx(xx2); \ | |
374 | } | |
705372a2 SL |
375 | |
376 | psclockintr(dev) | |
377 | dev_t dev; | |
378 | { | |
379 | register struct psdevice *psaddr = | |
aaa53878 | 380 | (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; |
705372a2 SL |
381 | register struct ps *psp = &ps[PSUNIT(dev)]; |
382 | int savepsaddr; | |
383 | ||
7da157da | 384 | if (!psp->ps_open) |
705372a2 | 385 | return; |
aaa53878 SL |
386 | psp->ps_clockcnt++; |
387 | SAVEPSADDR(psaddr, savepsaddr); | |
705372a2 | 388 | #ifndef EXTERNAL_SYNC |
7da157da | 389 | if (psp->ps_refresh.state == AUTO_RF) { |
aaa53878 SL |
390 | if (psp->ps_refresh.mode == SYNCING_RF && |
391 | psp->ps_refresh.state != TIME_RF) { | |
5db7da11 | 392 | (void) psrfnext(psp, psaddr); |
705372a2 | 393 | } else { |
aaa53878 SL |
394 | psp->ps_clockticks++; |
395 | psp->ps_clockmiss++; | |
705372a2 SL |
396 | } |
397 | } | |
398 | #endif | |
aaa53878 SL |
399 | PSWAIT(psaddr); psaddr->ps_addr = RTCREQ; |
400 | PSWAIT(psaddr); psaddr->ps_data = 01; /* clear the request bits */ | |
401 | RESTORPSADDR(psaddr, savepsaddr); | |
705372a2 SL |
402 | } |
403 | ||
404 | /*ARGSUSED*/ | |
405 | pssystemintr(dev) | |
406 | dev_t dev; | |
407 | { | |
408 | register struct psdevice *psaddr = | |
aaa53878 | 409 | (struct psdevice *)psdinfo[PSUNIT(dev)]->ui_addr; |
705372a2 | 410 | register struct ps *psp = &ps[PSUNIT(dev)]; |
aaa53878 | 411 | short request, tmp; |
705372a2 SL |
412 | register int savepsaddr, x; |
413 | ||
7da157da | 414 | if (!psp->ps_open) |
705372a2 | 415 | return; |
c5c0b1fb | 416 | psp->ps_icnt++; |
aaa53878 SL |
417 | SAVEPSADDR(psaddr, savepsaddr); |
418 | PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; | |
419 | PSWAIT(psaddr); request = psaddr->ps_data; | |
5db7da11 | 420 | request = request&0377; |
aaa53878 SL |
421 | psp->ps_lastrequest2 = psp->ps_lastrequest; |
422 | psp->ps_lastrequest = request; | |
423 | if (request &~ (HALT_REQ|RFSTOP_REQ|HIT_REQ)) { | |
424 | psp->ps_lastfunnyrequest = request; | |
425 | psp->ps_funnycnt++; | |
5db7da11 | 426 | } |
aaa53878 SL |
427 | PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; |
428 | tmp = request&(~(HALT_REQ|MOSTOP_REQ)); /* acknowledge */ | |
429 | PSWAIT(psaddr); psaddr->ps_data = tmp; | |
705372a2 | 430 | |
7da157da | 431 | if (request & (MOSTOP_REQ|HALT_REQ)) { /* Map stopped */ |
705372a2 | 432 | psp->ps_map.icnt++; |
aaa53878 | 433 | psmapstop(psaddr, psp, request);/* kill it dead */ |
7da157da | 434 | if (psp->ps_map.waiting) { |
705372a2 SL |
435 | psp->ps_map.waiting = 0; |
436 | wakeup(&psp->ps_map.waiting); | |
7da157da | 437 | if (psp->ps_map.stop) { |
705372a2 SL |
438 | psp->ps_map.stop = 0; |
439 | goto tryrf; | |
440 | } | |
441 | } | |
aaa53878 | 442 | if (psp->ps_map.state == AUTO_MAP && !psmapnext(psp, psaddr)) { |
5db7da11 SL |
443 | psp->ps_map.mcntr = 0; |
444 | /* prepare for next round */ | |
445 | pssetmapbounds(psp, psaddr); | |
446 | if (psp->ps_refresh.state == AUTO_RF) { | |
aaa53878 | 447 | if (psp->ps_refresh.mode == WAITING_MAP){ |
7da157da | 448 | if (psp->ps_dbuffer.state == ON_DB) |
705372a2 SL |
449 | /* fill other db */ |
450 | psdbswitch(psp, psaddr); | |
451 | else | |
452 | psp->ps_map.mode = WAITING_RF; | |
5db7da11 | 453 | #ifdef EXTERNAL_SYNC |
8011f5df | 454 | x = splclock(); |
5db7da11 SL |
455 | #endif |
456 | (void) psrfnext(psp, psaddr); | |
457 | #ifdef EXTERNAL_SYNC | |
458 | splx(x); | |
459 | #endif | |
705372a2 SL |
460 | } else |
461 | psp->ps_map.mode = WAITING_RF; | |
5db7da11 SL |
462 | } else { /* no auto refresh */ |
463 | if (psp->ps_dbuffer.state == ON_DB) | |
464 | /* fill other db */ | |
465 | psdbswitch(psp, psaddr); | |
466 | else | |
467 | (void) psmapnext(psp, psaddr); | |
705372a2 | 468 | } |
5db7da11 | 469 | } |
705372a2 SL |
470 | } |
471 | tryrf: | |
7da157da | 472 | if (request & RFSTOP_REQ) { /* Refresh stopped */ |
705372a2 | 473 | psp->ps_refresh.icnt++; |
c5c0b1fb | 474 | if (psp->ps_refresh.state == TIME_RF) |
aaa53878 | 475 | if (--psp->ps_refresh.timecnt > 0) |
c5c0b1fb | 476 | goto tryhit; |
705372a2 | 477 | psrfstop(psaddr, psp); |
7da157da | 478 | if (psp->ps_refresh.waiting) { |
705372a2 SL |
479 | psp->ps_refresh.waiting = 0; |
480 | wakeup(&psp->ps_refresh.waiting); | |
7da157da | 481 | if (psp->ps_refresh.stop) { |
705372a2 SL |
482 | psp->ps_refresh.stop = 0; |
483 | goto tryhit; | |
484 | } | |
485 | } | |
7da157da BJ |
486 | if (psp->ps_refresh.state == AUTO_RF) |
487 | if (!psrfnext(psp, psaddr)) { /* at end of refresh cycle */ | |
488 | if (psp->ps_map.state == AUTO_MAP && | |
aaa53878 | 489 | psp->ps_map.mode == WAITING_RF) { |
7da157da | 490 | if (psp->ps_dbuffer.state == ON_DB) |
705372a2 SL |
491 | psdbswitch(psp, psaddr); |
492 | else | |
5db7da11 | 493 | (void) psmapnext(psp, psaddr); |
705372a2 SL |
494 | } |
495 | psp->ps_refresh.srcntr = 0; | |
496 | #ifdef EXTERNAL_SYNC | |
8011f5df | 497 | x = splclock(); |
705372a2 | 498 | #endif |
705372a2 | 499 | psp->ps_refresh.mode = SYNCING_RF; |
aaa53878 | 500 | if (psp->ps_clockticks) |
5db7da11 | 501 | (void) psrfnext(psp, psaddr); |
aaa53878 | 502 | psp->ps_clockticks = 0; |
705372a2 SL |
503 | #ifdef EXTERNAL_SYNC |
504 | splx(x); | |
505 | #endif | |
506 | } | |
507 | } | |
508 | tryhit: | |
aaa53878 SL |
509 | if (request & HIT_REQ) /* Hit request */ |
510 | psp->ps_hitcnt++; | |
7da157da | 511 | if (request == 0) |
705372a2 | 512 | psp->ps_strayintr++; |
aaa53878 | 513 | RESTORPSADDR(psaddr, savepsaddr); |
705372a2 SL |
514 | } |
515 | ||
516 | psrfnext(psp, psaddr) | |
517 | register struct ps *psp; | |
518 | register struct psdevice *psaddr; | |
519 | { | |
aaa53878 | 520 | u_short start, last; |
705372a2 | 521 | |
aaa53878 | 522 | if (psp->ps_refresh.srcntr < psp->ps_refresh.nsraddrs) { |
705372a2 | 523 | psrfstart(psp->ps_refresh.sraddrs[psp->ps_refresh.srcntr++], |
aaa53878 SL |
524 | 0, psp, psaddr); |
525 | return (1); | |
526 | } | |
527 | if (psp->ps_refresh.srcntr == psp->ps_refresh.nsraddrs && | |
528 | psp->ps_dbuffer.state == ON_DB) { | |
5db7da11 SL |
529 | start = psp->ps_dbuffer.dbaddrs[psp->ps_dbuffer.rbuffer]; |
530 | last = start+psp->ps_dbuffer.dbsize; | |
531 | psrfstart(start, last, psp, psaddr); | |
705372a2 | 532 | psp->ps_refresh.srcntr++; /* flag for after dbuffer */ |
aaa53878 SL |
533 | return (1); |
534 | } | |
535 | return (0); | |
705372a2 SL |
536 | } |
537 | ||
5db7da11 | 538 | psrfstart(dfaddr, last, psp, psaddr) |
aaa53878 | 539 | u_short dfaddr, last; |
705372a2 SL |
540 | register struct ps *psp; |
541 | register struct psdevice *psaddr; | |
542 | { | |
aaa53878 SL |
543 | short dummy; |
544 | ||
545 | PSWAIT(psaddr); psaddr->ps_addr = RFASA; | |
546 | PSWAIT(psaddr); psaddr->ps_data = dfaddr; | |
547 | PSWAIT(psaddr); | |
548 | if (last != 0) | |
5db7da11 SL |
549 | psaddr->ps_data = last; |
550 | else | |
551 | dummy = psaddr->ps_data;/* just access to get to status reg */ | |
aaa53878 | 552 | PSWAIT(psaddr); psaddr->ps_data = RFSTART; /* may want | here */ |
705372a2 SL |
553 | psp->ps_refresh.mode = RUNNING_RF; |
554 | } | |
555 | ||
5db7da11 | 556 | /*ARGSUSED*/ |
705372a2 SL |
557 | psrfstop(psaddr, psp) |
558 | register struct psdevice *psaddr; | |
559 | register struct ps *psp; | |
560 | { | |
561 | ||
aaa53878 SL |
562 | PSWAIT(psaddr); psaddr->ps_addr = RFSR; |
563 | PSWAIT(psaddr); psaddr->ps_data = 0; | |
705372a2 SL |
564 | } |
565 | ||
566 | psdbswitch(psp, psaddr) | |
567 | register struct ps *psp; | |
568 | register struct psdevice *psaddr; | |
569 | { | |
570 | ||
571 | psp->ps_dbuffer.rbuffer = !psp->ps_dbuffer.rbuffer; | |
572 | pssetmapbounds(psp, psaddr); | |
5db7da11 | 573 | (void) psmapnext(psp, psaddr); |
705372a2 SL |
574 | } |
575 | ||
576 | psmapnext(psp, psaddr) | |
577 | register struct ps *psp; | |
578 | register struct psdevice *psaddr; | |
579 | { | |
580 | ||
aaa53878 SL |
581 | if (psp->ps_map.mcntr < psp->ps_map.nmaddrs) { |
582 | psmapstart(psp->ps_map.maddrs[psp->ps_map.mcntr++], | |
583 | psp, psaddr); | |
584 | return (1); | |
585 | } | |
586 | return (0); | |
705372a2 SL |
587 | } |
588 | ||
589 | pssetmapbounds(psp, psaddr) | |
590 | register struct ps *psp; | |
591 | register struct psdevice *psaddr; | |
592 | { | |
aaa53878 | 593 | u_short start, last; |
705372a2 | 594 | |
aaa53878 SL |
595 | PSWAIT(psaddr); psaddr->ps_addr = MAOL; |
596 | PSWAIT(psaddr); | |
7da157da | 597 | if (psp->ps_dbuffer.state == ON_DB) { |
5db7da11 SL |
598 | start = psp->ps_dbuffer.dbaddrs[!psp->ps_dbuffer.rbuffer]; |
599 | last = start+psp->ps_dbuffer.dbsize-2; /* 2 for halt cmd */ | |
600 | psaddr->ps_data = last; | |
aaa53878 | 601 | PSWAIT(psaddr); psaddr->ps_data = start; |
705372a2 SL |
602 | } else { |
603 | start = psaddr->ps_data; /* dummy: don't update limit */ | |
aaa53878 | 604 | PSWAIT(psaddr); psaddr->ps_data = psp->ps_map.outputstart; |
705372a2 SL |
605 | } |
606 | } | |
607 | ||
608 | psmapstart(dfaddr, psp, psaddr) | |
aaa53878 | 609 | u_short dfaddr; |
705372a2 SL |
610 | register struct ps *psp; |
611 | register struct psdevice *psaddr; | |
612 | { | |
705372a2 | 613 | |
aaa53878 SL |
614 | PSWAIT(psaddr); psaddr->ps_addr = MAIA; |
615 | PSWAIT(psaddr); psaddr->ps_data = dfaddr; | |
616 | PSWAIT(psaddr); psaddr->ps_data = MAO|MAI; /* may want more here */ | |
705372a2 SL |
617 | psp->ps_map.mode = RUNNING_MAP; |
618 | } | |
619 | ||
5db7da11 SL |
620 | int pskillcnt = 1; |
621 | ||
622 | psmapstop(psaddr, psp, request) | |
705372a2 | 623 | register struct psdevice *psaddr; |
5db7da11 | 624 | register struct ps *psp; |
aaa53878 | 625 | short request; |
705372a2 | 626 | { |
5db7da11 | 627 | register int i; |
705372a2 | 628 | |
aaa53878 SL |
629 | request &= HALT_REQ|MOSTOP_REQ; /* overkill?? */ |
630 | for (i = 0; i < pskillcnt; i++) { | |
631 | PSWAIT(psaddr); psaddr->ps_addr = MASR; | |
632 | PSWAIT(psaddr); psaddr->ps_data = IOUT; /* zero MAI & MAO */ | |
633 | PSWAIT(psaddr); psaddr->ps_addr = MAIA; | |
634 | PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 input addr reg */ | |
635 | PSWAIT(psaddr); psaddr->ps_addr = MAOA; | |
636 | PSWAIT(psaddr); psaddr->ps_data = 0; /* 0 output addr reg */ | |
637 | PSWAIT(psaddr); psaddr->ps_addr = SYSREQ; | |
638 | PSWAIT(psaddr); psaddr->ps_data = request; | |
5db7da11 SL |
639 | } |
640 | psp->ps_map.mode = STOPPED_MAP; | |
705372a2 SL |
641 | } |
642 | ||
643 | /*ARGSUSED*/ | |
644 | psdeviceintr(dev) | |
645 | dev_t dev; | |
646 | { | |
647 | ||
648 | printf("ps device intr\n"); | |
649 | } | |
650 | ||
651 | /*ARGSUSED*/ | |
652 | psdmaintr(dev) | |
653 | dev_t dev; | |
654 | { | |
655 | ||
656 | printf("ps dma intr\n"); | |
657 | } | |
658 | ||
5db7da11 | 659 | /*ARGSUSED*/ |
705372a2 SL |
660 | psreset(uban) |
661 | int uban; | |
662 | { | |
aaa53878 | 663 | |
705372a2 SL |
664 | } |
665 | ||
5db7da11 | 666 | /*ARGSUSED*/ |
aaa53878 SL |
667 | psextsync(PC, PS) |
668 | { | |
705372a2 SL |
669 | register int n; |
670 | register struct psdevice *psaddr; | |
671 | register struct ps *psp; | |
672 | register int savepsaddr; | |
673 | ||
674 | #ifdef EXTERNAL_SYNC | |
7da157da BJ |
675 | for (psp = ps, n = 0; n < NPS; psp++, n++) { |
676 | if (!psp->ps_open) | |
705372a2 | 677 | continue; |
aaa53878 SL |
678 | if (psp->ps_refresh.mode == SYNCING_RF && |
679 | psp->ps_refresh.state != TIME_RF) { | |
680 | psaddr = (struct psdevice *)psdinfo[n]->ui_addr; | |
681 | SAVEPSADDR(psaddr, savepsaddr); | |
5db7da11 | 682 | (void) psrfnext(psp, psaddr); |
aaa53878 | 683 | RESTORPSADDR(psaddr, savepsaddr); |
705372a2 | 684 | } else { |
aaa53878 SL |
685 | psp->ps_clockticks++; |
686 | psp->ps_clockmiss++; | |
705372a2 SL |
687 | } |
688 | } | |
689 | #endif | |
690 | } | |
691 | #endif |