* Evans and Sutherland Picture System 2 driver
#include "../machine/pte.h"
#include "../vaxuba/ubareg.h"
#include "../vaxuba/ubavar.h"
#include "../vaxuba/psreg.h"
int psprobe(), psattach(), psintr();
struct uba_device
*psdinfo
[NPS
];
struct uba_driver psdriver
=
{ psprobe
, 0, psattach
, 0, psstd
, "ps", psdinfo
};
#define PSUNIT(dev) (minor(dev))
#define MAXAUTOREFRESH (4)
#define MAXDBSIZE (0177777/2)
#define PSWAIT() {register short int i, j; i=20000; while((i-- != 0)\
&& (((j=psaddr->ps_iostat)&DIOREADY)==0));}
enum { SINGLE_STEP_RF
, AUTO_RF
} state
;
enum { RUNNING_RF
, SYNCING_RF
, WAITING_MAP
} mode
;
unsigned short int sraddrs
[MAXAUTOREFRESH
];
enum { ON_DB
, OFF_DB
} state
;
unsigned short int dbaddrs
[2];
unsigned short int dbsize
;
enum { SINGLE_STEP_MAP
, AUTO_MAP
} state
;
enum { RUNNING_MAP
, WAITING_RF
, WAITING_START
} mode
;
unsigned short int maddrs
[MAXAUTOMAP
];
register struct psdevice
*psaddr
= (struct psdevice
*) reg
;
psaddr
->ps_iostat
= PSRESET
;
psaddr
->ps_iostat
= PSIE
;
psaddr
->ps_data
= (SYNC
|RUN
);
psaddr
->ps_addr
= RTCREQ
;
psaddr
->ps_iostat
= PSRESET
;
return (sizeof (struct psdevice
));
register struct uba_device
*ui
;
register struct uba_device
*ui
;
register int unit
= PSUNIT(dev
);
if (unit
>= NPS
|| (psp
= &ps
[minor(dev
)])->ps_open
||
(ui
= psdinfo
[unit
]) == 0 || ui
->ui_alive
== 0)
psp
->ps_refresh
.state
= SINGLE_STEP_RF
;
psp
->ps_refresh
.waiting
= 0;
psp
->ps_refresh
.stop
= 0;
psp
->ps_dbuffer
.state
= OFF_DB
;
psp
->ps_map
.state
= SINGLE_STEP_MAP
;
psp
->ps_clock
.ticked
= 0;
psp
->ps_refresh
.icnt
= psp
->ps_map
.icnt
= psp
->ps_clock
.icnt
= 0;
register struct psdevice
*psaddr
=
(struct psdevice
*) psdinfo
[PSUNIT(dev
)]->ui_addr
;
ps
[PSUNIT(dev
)].ps_open
= 0;
psaddr
->ps_iostat
= 0; /* clear IENABLE */
psaddr
->ps_addr
= RFSR
; /* set in auto refresh mode */
psaddr
->ps_data
= AUTOREF
;
psioctl(dev
, cmd
, data
, flag
)
register struct uba_device
*ui
= psdinfo
[PSUNIT(dev
)];
register struct ps
*psp
= &ps
[PSUNIT(dev
)];
int *waddr
= *(int **)data
;
*(caddr_t
*)data
= ui
->ui_addr
;
if (n
< 0 || n
> MAXAUTOREFRESH
)
for (i
= 0; i
< n
; i
++) {
if ((arg
= fuword(waddr
++)) == -1)
psp
->ps_refresh
.sraddrs
[i
] = arg
;
psp
->ps_refresh
.state
= AUTO_RF
;
psp
->ps_refresh
.nsraddrs
= n
;
psp
->ps_refresh
.srcntr
= 0;
psp
->ps_refresh
.mode
= WAITING_MAP
;
if (n
< 0 || n
> MAXAUTOMAP
)
for (i
= 0; i
< n
; i
++) {
if ((arg
= fuword(waddr
++)) == -1)
psp
->ps_map
.maddrs
[i
] = arg
;
if ((arg
= fuword(waddr
++)) == -1)
psp
->ps_map
.outputstart
= arg
;
psp
->ps_map
.state
= AUTO_MAP
;
psp
->ps_map
.mode
= WAITING_START
;
psp
->ps_refresh
.state
= SINGLE_STEP_RF
;
psp
->ps_map
.state
= SINGLE_STEP_MAP
;
if ((arg
= fuword(waddr
++)) == -1)
psp
->ps_dbuffer
.dbaddrs
[0] = arg
;
if ((arg
= fuword(waddr
++)) == -1)
if (arg
<= 0 || arg
> MAXDBSIZE
)
psp
->ps_dbuffer
.dbsize
= arg
;
psp
->ps_dbuffer
.dbaddrs
[1] =
psp
->ps_dbuffer
.dbaddrs
[0]+arg
;
psp
->ps_dbuffer
.state
= ON_DB
;
psp
->ps_dbuffer
.rbuffer
= 0;
psp
->ps_dbuffer
.state
= OFF_DB
;
if (psp
->ps_refresh
.mode
!= RUNNING_RF
) /* not running */
return (0); /* dont wait */
if (cmd
== PSSTOPREFRESH
)
psp
->ps_refresh
.stop
= 1;
psp
->ps_refresh
.waiting
= 1;
while (psp
->ps_refresh
.waiting
)
sleep(&psp
->ps_refresh
.waiting
, PSPRI
);
if (psp
->ps_map
.mode
!= RUNNING_MAP
) /* not running */
return (0); /* dont wait */
while (psp
->ps_map
.waiting
)
sleep(&psp
->ps_map
.waiting
, PSPRI
);
#define SAVEPSADDR() {register short int i, x;x=spl6();i=psaddr->ps_addr;\
while(((i=psaddr->ps_iostat)&DIOREADY)==0);\
savepsaddr=psaddr->ps_data;splx(x);}
#define RESTORPSADDR() {register int x,i;x=spl6();\
while(((i=psaddr->ps_iostat)&DIOREADY)==0);\
psaddr->ps_addr=savepsaddr;splx(x);}
register struct psdevice
*psaddr
=
(struct psdevice
*) psdinfo
[PSUNIT(dev
)]->ui_addr
;
register struct ps
*psp
= &ps
[PSUNIT(dev
)];
if (psp
->ps_refresh
.state
== AUTO_RF
) {
if (psp
->ps_refresh
.mode
== SYNCING_RF
) {
psaddr
->ps_addr
= RTCREQ
;
psaddr
->ps_data
= 01; /* clear the request bits */
register struct psdevice
*psaddr
=
(struct psdevice
*) psdinfo
[PSUNIT(dev
)]->ui_addr
;
register struct ps
*psp
= &ps
[PSUNIT(dev
)];
register int savepsaddr
, x
;
psaddr
->ps_addr
= SYSREQ
;
request
= psaddr
->ps_data
;
psp
->last_request
= request
;
psaddr
->ps_addr
= SYSREQ
;
psaddr
->ps_data
= request
&(~(HALT_REQ
|MOSTOP_REQ
)); /* acknowledge */
if (request
& (MOSTOP_REQ
|HALT_REQ
)) { /* Map stopped */
psmapstop(psaddr
); /* kill it dead */
if (psp
->ps_map
.waiting
) {
wakeup(&psp
->ps_map
.waiting
);
if (psp
->ps_map
.state
== AUTO_MAP
)
if (!psmapnext(psp
, psaddr
)) {
/* prepare for next round */
pssetmapbounds(psp
, psaddr
);
if (psp
->ps_refresh
.mode
== WAITING_MAP
) {
if (psp
->ps_dbuffer
.state
== ON_DB
)
psp
->ps_map
.mode
= WAITING_RF
;
psrfnext(psp
, psaddr
); /* start rf */
psp
->ps_map
.mode
= WAITING_RF
;
if (request
& RFSTOP_REQ
) { /* Refresh stopped */
if (psp
->ps_refresh
.waiting
) {
psp
->ps_refresh
.waiting
= 0;
wakeup(&psp
->ps_refresh
.waiting
);
if (psp
->ps_refresh
.stop
) {
psp
->ps_refresh
.stop
= 0;
if (psp
->ps_refresh
.state
== AUTO_RF
)
if (!psrfnext(psp
, psaddr
)) { /* at end of refresh cycle */
if (psp
->ps_map
.state
== AUTO_MAP
&&
psp
->ps_map
.mode
==WAITING_RF
) {
if (psp
->ps_dbuffer
.state
== ON_DB
)
psp
->ps_refresh
.srcntr
= 0;
if (!psp
->ps_clock
.ticked
||
!psrfnext(psp
, psaddr
)) {
psp
->ps_refresh
.mode
= SYNCING_RF
;
psp
->ps_clock
.ticked
= 0;
psp
->ps_refresh
.mode
= SYNCING_RF
;
if (request
& HIT_REQ
) { /* Hit request */
register struct psdevice
*psaddr
;
if (psp
->ps_refresh
.srcntr
< psp
->ps_refresh
.nsraddrs
)
psrfstart(psp
->ps_refresh
.sraddrs
[psp
->ps_refresh
.srcntr
++],
else if (psp
->ps_refresh
.srcntr
== psp
->ps_refresh
.nsraddrs
&& psp
->ps_dbuffer
.state
== ON_DB
) {
psrfstart(psp
->ps_dbuffer
.dbaddrs
[psp
->ps_dbuffer
.rbuffer
],
psp
->ps_refresh
.srcntr
++; /* flag for after dbuffer */
psrfstart(dfaddr
, psp
, psaddr
)
register struct psdevice
*psaddr
;
psaddr
->ps_data
= dfaddr
;
dummy
= psaddr
->ps_data
; /* just access to get to status reg */
psaddr
->ps_data
= RFSTART
; /* may want to | this value in */
psp
->ps_refresh
.mode
= RUNNING_RF
;
register struct psdevice
*psaddr
;
register struct psdevice
*psaddr
;
psp
->ps_dbuffer
.rbuffer
= !psp
->ps_dbuffer
.rbuffer
;
pssetmapbounds(psp
, psaddr
);
register struct psdevice
*psaddr
;
if (psp
->ps_map
.mcntr
< psp
->ps_map
.nmaddrs
)
psmapstart(psp
->ps_map
.maddrs
[psp
->ps_map
.mcntr
++], psp
, psaddr
);
pssetmapbounds(psp
, psaddr
)
register struct psdevice
*psaddr
;
unsigned short int start
;
if (psp
->ps_dbuffer
.state
== ON_DB
) {
psaddr
->ps_data
= (start
= psp
->ps_dbuffer
.dbaddrs
[!psp
->ps_dbuffer
.rbuffer
])
+psp
->ps_dbuffer
.dbsize
-2; /* 2 for a refresh halt command */
start
= psaddr
->ps_data
; /* dummy: don't update limit */
psaddr
->ps_data
= psp
->ps_map
.outputstart
;
psmapstart(dfaddr
, psp
, psaddr
)
register struct psdevice
*psaddr
;
psaddr
->ps_data
= dfaddr
;
psaddr
->ps_data
= MAO
|MAI
; /* may want more here */
psp
->ps_map
.mode
= RUNNING_MAP
;
register struct psdevice
*psaddr
;
psaddr
->ps_data
= 0; /* zero MAI bit */
psaddr
->ps_data
= 0; /* zero input address register */
psaddr
->ps_addr
= SYSREQ
;
psaddr
->ps_data
= HALT_REQ
|MOSTOP_REQ
; /* overkill?? */
printf("ps device intr\n");
register struct psdevice
*psaddr
;
for (psp
= ps
, n
= 0; n
< NPS
; psp
++, n
++) {
if (psp
->ps_refresh
.mode
== SYNCING_RF
) {
psaddr
= (struct psdevice
*) psdinfo
[n
]->ui_addr
;