|
|
DataMuseum.dkPresents historical artifacts from the history of: Commodore CBM-900 |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about Commodore CBM-900 Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - download
Length: 8579 (0x2183)
Types: TextFile
Notes: UNIX file
Names: »hr2.c«
└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
└─⟦2d53db1df⟧ UNIX Filesystem
└─⟦this⟧ »hr/src/driver/hr2.c«
/*
* allocate a free message buffer.
* The process as the client is made to wait if none are available.
*/
struct mbuf *
hralloc(self)
register uint self;
{
register struct client *cp;
register struct mbuf *p;
int s;
cp = &client[self];
s = sphi();
while ( not ismbfree() ) {
spl(s);
hrlock(self, WANTMB);
cp->flags |= WANTMB;
hrsleep( &cp->head, self, SLP_MBUF);
cp->flags &= ~WANTMB;
wakeup(&cp->flags);
s = sphi();
}
p = mbufp;
mbufp = p->mb_next;
spl(s);
return p;
}
/*
* put back a free message buffer.
* This message buffer was allocated but not used and must be
* reattached to the message queue.
*/
hrunalloc(p)
struct mbuf *p;
{
int s;
s = sphi();
p->mb_next = mbufp;
mbufp = p;
spl(s);
}
/*
* free a message buffer.
* The 1st message buffer in the client's queue is attached to the free
* buffer list. All clients waiting for a message buffer are notified.
*/
hrfree(self)
uint self;
{
register struct mbuf *p;
register struct client *cp;
int s;
s = sphi();
cp = &client[self];
p = cp->head;
cp->head = p->mb_next;
if ( p == mstail )
mstail = 0;
p->mb_next = mbufp;
mbufp = p;
spl(s);
if ( ismbfree() )
for (cp=client; cp<endof( client); ++cp)
if ((cp->flags & WANTMB) ||
((cp->flags & (BUSY+NEEDMSG)) == BUSY+NEEDMSG) )
wakeup( &cp->head);
}
/*
* flush an entire message queue.
* All clients waiting for a message buffer are notified.
*/
hrflush(self)
uint self;
{
register struct mbuf *p;
register struct client *cp;
int s;
s = sphi();
cp = &client[self];
p = cp->head;
cp->head = 0;
cp->tail->mb_next = mbufp;
mbufp = p;
if ( self == hrsmgr )
mstail = 0;
spl(s);
if ( ismbfree() )
for (cp=client; cp<endof( client); ++cp)
if ((cp->flags & WANTMB) ||
((cp->flags & (BUSY+NEEDMSG)) == BUSY+NEEDMSG) )
wakeup( &cp->head);
}
/*
* Return false if the number of free message buffers falls below
* the reasonable limit.
*/
ismbfree()
{
register struct mbuf *p;
register int i;
int s;
s = sphi();
p = mbufp;
for ( i=0 ; i < 15 ; i++ )
{
if ( not p )
{
spl(s);
return 0;
}
p = p->mb_next;
}
spl(s);
return ~0;
}
/*
* wait outside until the door is open, enter, and lock it.
*/
hrlock(self, flag)
uint self;
uint flag;
{
register struct client *cp;
cp = &client[self];
while ( cp->flags & flag )
sleep( &cp->flags, 0, 0, 0);
cp->flags |= flag;
}
/*
* wait inside door until condition is met.
* Unlock the door and leave. Interruptable. Returns FALSE if interrupted.
*/
int hrwait(self, stype)
uint self;
uint stype;
{
register struct client *cp;
cp = &client[self];
while ( cp->flags & (1 << stype) )
{
hrsleep( (stype==SLP_READ ? &cp->datc : &cp->data), self, stype);
if (SELF->p_ssig && nondsig( ))
{
u.u_error = EINTR;
cp->flags &= ~(1 << stype);
wakeup( &cp->flags);
return FALSE;
}
}
wakeup(&cp->flags);
return TRUE;
}
/*
* link a message buffer to the client's queue.
* Wake up anyone waiting for a non-empty client queue.
*/
hrlink(dst, p)
uint dst;
register struct mbuf *p;
{
register struct client *cp;
struct mbufp *p2; /*** DEBUG ***/
int s;
s = sphi();
#ifdef DEBUG
if ( dst == p->mb_m.m_src )
printf("\007LINKME: dst = src = %d\n", dst);
for ( cp = client; cp < endof( client); cp++ )
{
if ( not cp->ocount )
continue;
for ( p2=cp->head ; p2 ; p2=p2->mb_next )
{
if ( p == p2 )
{
printf("\007LINK %d: in list %d\n", dst, cp-client);
break;
}
}
}
for ( p2=mbufp ; p2 ; p2=p2->mb_next )
if ( p2 == p )
printf("\007LINK %d: in free list\n", dst);
if ( (p2 = client[dst].head) )
{
while ( p2 && p2->mb_next )
p2 = p2->mb_next;
if ( p2 != client[dst].tail )
printf("\007LINK: bad tail %d\n", dst);
}
#endif
cp = &client[dst];
if (cp->head)
cp->tail->mb_next = p;
else
{
cp->head = p;
wakeup( &cp->head);
}
cp->tail = p;
p->mb_next = 0;
spl(s);
}
/*
* send signal to process group
* The signal `sig' is sent to all processes grouped under client `d'.
* High priority is needed when scanning the proc table.
*/
static
hrsignal( d, sig)
uint d;
{
register PROC *pp;
uint g,
s;
if (d >= DESTMAX)
baddest( );
pp = &procq;
if ( d < WINDOW )
{
if ( g = client[d].pid )
{
s = sphi();
while ( (pp=pp->p_nforw) != &procq )
if ( pp->p_pid == g )
{
sendsig( sig, pp);
break;
}
spl( s);
}
}
else
{
if (g = client[d].group)
{
s = sphi( );
while ( (pp=pp->p_nforw) != &procq )
if ( pp->p_group == g )
sendsig( sig, pp);
spl( s);
}
}
}
static
baddest( )
{
panic( "bad dest");
}
hrmseon()
{
extern void hrmouse();
if ( not mousebuf.ms_en )
{
mousebuf.ms_en = ~0;
hrmerge(mousebuf.ms_x/8, mousebuf.ms_y);
timeout( &timebuf, 1, hrmouse, 0);
}
}
hrmseoff()
{
if ( mousebuf.ms_en )
{
mousebuf.ms_en = 0;
hrudraw();
}
}
void
hrmouse( )
{
struct mbuf *p;
static uint lastk;
static lastxrel,
lastyrel;
register uint k,
i;
register int x,
y,
xrel,
yrel;
int s;
if ( !mousebuf.ms_en || hrsmgr == NOEVMGR )
return;
timeout( &timebuf, 1, hrmouse, 0);
i = in( XPORT);
xrel = i & (1<<MBITS)-1;
k = i & (DSMENU|DWMENU|DACTION);
yrel = in( YPORT) & (1<<MBITS)-1;
x = (int)mouse.m_msg[2] + (xrel-lastxrel<<16-MBITS>>16-MBITS);
if (x < 0)
x = 0;
else if (x >= XMAX - MOUSEWI)
x = XMAX - MOUSEWI - 1;
y = (int)mouse.m_msg[3] + (yrel-lastyrel<<16-MBITS>>16-MBITS);
if (y < 0)
y = 0;
else if (y >= YMAX - MOUSEHI)
y = YMAX - MOUSEHI - 1;
if (x!=mouse.m_msg[2] || y!=mouse.m_msg[3])
{
if (mouse.m_msg[0] != SM_MOUSE)
wakeup( &client[hrsmgr].head);
mouse.m_msg[0] = SM_MOUSE;
mouse.m_msg[1] = hrticks;
mouse.m_msg[2] = x;
mouse.m_msg[3] = y;
hrudraw();
hrdraw(x, y);
}
s = sphi();
if ( (k^lastk) && (p=mbufp) ) {
mbufp = p->mb_next;
if ( mstail )
{
if ( not (p->mb_next = mstail->mb_next) )
client[hrsmgr].tail = p;
mstail->mb_next = p;
}
else
{
if ( not (p->mb_next = client[hrsmgr].head) )
{
client[hrsmgr].tail = p;
wakeup( &client[hrsmgr].head);
}
client[hrsmgr].head = p;
}
mstail = p;
p->mb_m.m_src = DRIVER;
p->mb_m.m_msg[0] = SM_MKEY;
p->mb_m.m_msg[1] = hrticks;
p->mb_m.m_msg[2] = k^lastk | x;
p->mb_m.m_msg[3] = k | y;
lastk = k;
#ifdef DEBUG
for ( p = client[hrsmgr].head; p ; p=p->mb_next )
if ( p == mstail )
break;
if ( not p )
printf("\007\007HRMOUSE: bad mstail\n");
else
{
while ( p->mb_next )
p = p->mb_next;
if ( p != client[hrsmgr].tail )
printf("\007HRMOUSE: bad queue tail\n");
}
#endif
}
spl(s);
lastxrel = xrel;
lastyrel = yrel;
++hrticks;
}
#define CTS 0x04
#define ALS 0x08
uint hrshift; /* shift keys */
void
hrkey()
{
register struct mbuf *p;
register uint key;
int i;
/*
* Clear interrupt condition in chip and read data from PA and PC3
*/
outb(ZCIO1+PACAS, C_IPIUS);
key = inb(ZCIO1+PADATA) & 0x7f;
if ( inb(ZCIO1+PCDATA) & PC2 )
key += 0x80;
if ( hrsmgr != NOEVMGR && (p = mbufp) )
{
mbufp = p->mb_next;
hrlink(hrsmgr, p);
wakeup(&client[hrsmgr].head); /* should catch all weird cases */
p->mb_m.m_src = DRIVER;
p->mb_m.m_msg[0] = SM_KKEY;
p->mb_m.m_msg[1] = hrticks;
p->mb_m.m_msg[2] = key;
}
outb(ZCIO1+PCDATA, 0);
outb(ZCIO1+PCDATA, PC3);
if ( key == 0x80+0x1d )
hrshift &= ~CTS;
else if ( key == 0x80+0x38 )
hrshift &= ~ALS;
else if ( key == 0x1d )
hrshift |= CTS;
else if ( key == 0x38 )
hrshift |= ALS;
else if ( key == 0x54 && hrshift == ALS|CTS )
{
hruload();
hrsignal( DMGR, SIGSEGV );
}
}
hrmerge(xcbase, y)
int xcbase;
register int y;
{
register char *p;
register char *q;
int yn;
if ( y < YSPLIT )
p = (char *)SEG0 + y*(XMAX/8) + xcbase;
else
p = (char *)SEG1 + (y-YSPLIT)*(XMAX/8) + xcbase;
q = (char *)mousebuf.ms_buf;
for ( yn = nel(mousebuf.ms_buf) ; yn ; yn-- )
{
*p++ ^= *q++;
*p++ ^= *q++;
*p++ ^= *q++;
q++; /* bad practice, skip over unused byte */
y++;
if ( y != YSPLIT )
p += (XMAX/8) - 3;
else
p = (char *)SEG1 + xcbase;
}
}
hrlshift(dx)
{
register ulong *lp;
register int rows;
if (!dx)
return;
lp = mousebuf.ms_buf;
for ( rows = nel(mousebuf.ms_buf); rows; rows-- )
{
sdll(lp, dx);
lp++;
}
}
/*
* undraw mouse cursor
*/
hrudraw()
{
hrmerge(mousebuf.ms_x/8, mousebuf.ms_y);
}
/*
* set and draw mouse cursor
*/
hrdraw(x, y)
int x;
int y;
{
int obit;
mousebuf.ms_x = x;
mousebuf.ms_y = y;
obit = mousebuf.ms_bit;
hrlshift( (mousebuf.ms_bit = 7 - (x&7)) - obit);
hrmerge(x/8, y);
}