|
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 - 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); }