DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦9a5922984⟧ TextFile

    Length: 8579 (0x2183)
    Types: TextFile
    Notes: UNIX file
    Names: »hr2.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦2d53db1df⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »hr/src/driver/hr2.c« 

TextFile


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