Subject: Small progress with ADB on MacIIvi (IIsi/IIvx?)
To: None <macbsd-development@NetBSD.ORG>
From: Walter Ruetten <>
List: macbsd-development
Date: 12/31/1994 13:52:34

I had some partial success with the Egret ADB controller used in my
MacIIvi (equiv. to IIsi, IIvx ?). 

Until now, the ADB controller just stopped dead when booting (thus said
my oscilloscope). This may be due to a lost interrupt in  VIA1. 
During the boot process, the ADB chips signals that is has data ready
from the external ADB bus by pulling bit 3 of vBufB (vPB3) low _and_ it
sends a dummy byte to the VIA1 shiftregister vSR to generate an
interrupt. The CPU is then supposed to pull bit 5 of vBufB (vPB5) high
to signal its attention.

When booting NetBSD, the controller tries to send data (vPB3 goes low),
but the interrupt gets lost somewhere in the initialisation, so the CPU
does not know whats up.

ADBReInit() waits for vPB3 to become high, but this will never happen as
we dont have any interrupts pending and no one fetches the data from the
ADB chip. :-(

So I wrote program that fetches data bytes from the ADB chip until vPB3
goes high (no more data in ADB chip) and then goes on to the
ADBReInit() call in adb_init(). (Time seems to be important here, so
don't put any messages on the screen between emptying the ADB chip and
calling ADBReInit) 

The good news is: CPU and ADB chip talk to each other (very busy).
The bad news is: After entering ADBReInit (trap a07b), I get lots of 
		traps a092 (Egret), each with a ' bk exit' message,
		but it never comes back from ADBReInit.

So if anyone wants to try this further (I surely will), I append part of
the modified adb_init() routine (look for WRU).

Have fun

------ begin: dev/adbsys.c (parts of it) ------- 

/*	$NetBSD: adbsys.c,v 1.8 1994/12/03 23:34:13 briggs Exp $	*/

[stuff deleted ..]

void adb_init()
	int i;
	int totaladbs;
	int adbindex;
	int adbaddr;
	ADBDataBlock adbdata;
	ADBSetInfoBlock adbinfo;
	int s;
	int error;

		printf("adb: no ROM ADB driver in this kernel for this machine\n");

	printf("adb: bus subsystem\n");
#if defined(MRG_DEBUG)
	printf("adb: call mrg_initadbintr\n");

	/* s = splhigh(); */
	mrg_initadbintr();	/* Mac ROM Glue okay to do ROM intr */
#if defined(MRG_DEBUG)
	printf("adb: returned from mrg_initadbintr\n");

		/* ADBReInit pre/post-processing */
	JADBProc = adb_jadbproc;

		/* Initialize ADB */
/* WRU 941230: Begin */
/* Get last message from ADB controller even if there is no interrupt pending */
/* 	PB3 of VIA is low, signaling that there is data waiting, but the      */
/*	corresponding interrupt V1IF_ADBRDY (shift register full) was lost    */
/*	during the boot process						      */

if (current_mac_model->class == MACH_CLASSIIsi)
#define vPB3	0x08
#define vPB4	0x10
#define vPB5	0x20
/* The guess for TROEDEL works for MacIIvi, on anything faster you
   might need more time (possibly ADBDelay ?) */
#define TROEDEL		500
#define LANG_GENUG	500

	long my_time, endofframe;

#if defined(MRG_DEBUG)
	printf("adb: empty ADB chip\n");

	via_reg(VIA1, vIER) = 0x04; /* disable ADB interrupt on IIs. */

	if (0 == (via_reg(VIA1, vBufB) & vPB3))
		/* controller has still something to say */
		via_reg(VIA1, vBufB) |= vPB5;	/* begin data frame */

		endofframe = 0;
		while (0 == endofframe)
			/* poll for ADB interrupt */
			my_time = 0;
			while (    (0 == (via_reg(VIA1, vIFR) & V1IF_ADBRDY) )
				&& (my_time < LANG_GENUG) )
			my_time = via_reg(VIA1, vSR);	/* reset interrupt flag	   */
							/* by reading vSR 	   */
							/* my_time serves as dummy */
			if ( 0 != (via_reg(VIA1, vBufB) & vPB3) )
				endofframe = 1;

			via_reg(VIA1, vBufB) |= vPB4;	/* send ACK to ADB chip */
			for (my_time=0; my_time< TROEDEL; my_time++);
			via_reg(VIA1, vBufB) &= ~vPB4;	/* send ACK to ADB chip */
		via_reg(VIA1, vBufB) &= ~vPB5;	/* signal end of frame */
		for (my_time=0; my_time< 2*TROEDEL; my_time++);
	via_reg(VIA1, vIER) = 0x84; /* enable ADB interrupt on IIs. */

/* WRU 941230: End */

		/* Initialize ADB */
#if 0		/* don't waste time, its precious */
#if defined(MRG_DEBUG)
	printf("adb: calling ADBReInit\n");

#if defined(MRG_DEBUG)
	printf("adb: done with ADBReInit\n");

	totaladbs = CountADBs();
		/* for each ADB device */
	for(adbindex = 1; adbindex <= totaladbs ; adbindex++){
			/* Get the ADB information */
		adbaddr = GetIndADB(&adbdata, adbindex);

[stuff deleted ..]

		error = SetADBInfo(&adbinfo, adbaddr);
#if defined(MRG_DEBUG)
		printf("returned %d from SetADBInfo\n", error);

	/* splx(s);	/* allow interrupts to go on */

------ end: dev/adbsys.c (parts of it) ------- 
EMail:   | SnailMail: Walter Ruetten        _o        Turmstr. 190
Phone: ++49 241 807945                   _`\_<,       52064 Aachen
Fax  : ++49 241 8888213                 (*)/'(*)      Germany
  "History --- an agreeable set of untruths"  -- Powhiri Rika-Heke