Subject: port-mac/2113: Add resource management for ADB support on P550
To: None <gnats-bugs@NetBSD.ORG>
From: Walter Ruetten <walter@ghpc8.ihf.rwth-aachen.de>
List: netbsd-bugs
Date: 02/22/1996 21:25:16
>Number: 2113
>Category: port-mac
>Synopsis: Add resource management for ADB support on P550
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: gnats-admin (GNATS administrator)
>State: open
>Class: change-request
>Submitter-Id: net
>Arrival-Date: Thu Feb 22 16:05:05 1996
>Last-Modified:
>Originator: Walter Ruetten
>Organization:
>Release: 1.1
>Environment:
Mac Performa P550, NetBSD/mac68k,
System: NetBSD islington.ihf.rwth-aachen.de 1.1A NetBSD 1.1A (ISLINGTON) #278: Tue Feb 20 19:39:14 MET 1996 walter@islington.ihf.rwth-aachen.de:/usr/src/sys/arch/mac68k.vi/compile/ISLINGTON mac68k
>Description:
- Performa P550 needs the 'CountResources', 'GetIndResource',
'FixDiv' and 'FixMul' toolbox traps.
- OStrap 'Delay' is also needed.
- NewPtr trap doesn't clear memory! This harms ADB on the P550.
- PB180 needs Vertical Blanking Queue (VBLQueue, 60Hz retrace interrupts).
>How-To-Repeat:
>Fix:
File: macrom.c:
- Add ExpandMem and assorted memory.
- Add variables for resource management.
- Add mrg_Delay() which handles the OStrap 'Delay'
- Add C functions for resource management:
is_resource()
count_all_resources()
w_build_resource_list()
w_count_resources()
w_get_ind_resource()
- Add mrg_VBLQueue() to handle the Vertical Blanking Queue
(still preliminary).
- Zero out memory allocated by OStrap 'Newptr sys,clear'.
- Add mrg_StripAddress() to handle 'StripAddress' trap.
- Update mrg_OStrap[] and mrg_ToolBoxtraps[]
- Add mrg_SetOSTrapAddress() to handle 'SetOSTrapAddress' trap.
- make mrg_aline_super() tell from where it got called,
what parameters it got, and which ones it is going to return
when MRG_DEBUG is defined.
- fill in addresses for 'FixDiv' and 'FixMul' traps from the
ROM vector table.
- in mrg_init(): build up resourcelist before any of the
ADB stuff starts running.
- in mrg_init(): initialize VBLQueue.
- in mrg_init(): initialize ExpandMem et al. with magic numbers
and pointers to each other.
- make setup_egret() more verbose concerning interrupt vectors
and the results of SetOSTrapAddress.
- allow setup_egret() to run for two different values of
HwCfgFlag3.
- in mrg_fixupROMBase(): relocate ToolBoxtraps too.
File: macromasm.s:
- variables for ExpandMem and VBLQueue.
- assembler stubs for mrg_CountResources() and mrg_GetIndResource().
File: locore.s:
- Divert 60Hz timer tick to mrg_VBLQueue().
File: autoconf.c:
- rt clock must be running before adb_init for PowerBooks,
as they use the VBLqueue.
diffs follow:
diff -c mac68k/mac68k/macrom.c mac68k.vi/mac68k/macrom.c
*** mac68k/mac68k/macrom.c Sat Oct 14 03:09:10 1995
--- mac68k.vi/mac68k/macrom.c Tue Feb 20 21:27:52 1996
***************
*** 69,74 ****
--- 69,77 ----
u_char mrg_adbstore[512];
u_char mrg_adbstore2[512];
u_char mrg_adbstore3[512];
+ u_char mrg_ExpandMem[512]; /* 0x1ea Bytes minimum */
+ u_char mrg_adbstore4[32]; /* 0x16 bytes was the largest I found yet */
+ u_char mrg_adbstore5[80]; /* 0x46 bytes minimum */
caddr_t mrg_romadbintr = (caddr_t)0x40807002; /* ROM ADB interrupt */
caddr_t mrg_rompmintr = 0; /* ROM PM (?) interrupt */
***************
*** 77,88 ****
--- 80,331 ----
caddr_t mrg_InitEgret = 0;
caddr_t mrg_ADBIntrPtr = (caddr_t)0x0; /* ADB interrupt taken from MacOS vector table*/
+ caddr_t *rsrc_handle; /* Variables for ROM resource map */
+ caddr_t *rsrc_header;
+ u_int32_t nr_of_rsrcs;
+
+
/*
* Last straw functions; we didn't set them up, so freak out!
* When someone sees these called, we can finally go back and
* bother to implement them.
*/
+
+ int
+ mrg_Delay()
+ {
+ #define TICK_DURATION 16625
+
+ int result = noErr;
+ u_int32_t ticks;
+
+ asm(" movl a0, %0" /* get arguments */
+ :
+ : "g" (ticks));
+
+ #if defined(MRG_DEBUG)
+ printf("mrg: mrg_Delay(%d) = %d ms\n", ticks, ticks * 60);
+ #endif
+ delay(ticks * TICK_DURATION);
+ return(ticks); /* The number of ticks since startup should be
+ * returned here. Until someone finds a need for
+ * this, we just return the requested number
+ * of ticks */
+ }
+
+
+ int
+ is_resource(caddr_t rp)
+ {
+ /* Heuristic to locate resources in the ROM.
+ * rp+8 builds a linked list, but where does it start?
+ */
+ if ( (0x00000000 == ( *((u_int32_t *) rp ) & 0x00ffffff)) /* magic numbers */
+ && (0x00000000 == *((u_int32_t *) (rp+0x04)) ) /* magic numbers */
+ && ( 0 == ( *((u_int32_t *) (rp+0x08)) & 0x0f ) ) /* on paragraph boundary */
+ && ( 0 == ( *((u_int32_t *) (rp+0x0c)) & 0x0f ) ) /* on paragraph boundary */
+ && ( 0 == ( ((u_int32_t) rp) & 0x0f ) ) /* on paragraph boundary */
+ && (256 > ( *((u_int32_t *) (rp+0x0c)) - ((u_int32_t)rp & 0x0fffff) ))
+ /* point to someplace near rp */
+ )
+ return 1;
+ else return 0;
+ }
+
+ int
+ count_all_resources(caddr_t rombase, u_int32_t romlen)
+ {
+ caddr_t romptr;
+ u_int32_t nr_of_rsrcs = 0;
+
+ for (romptr = rombase + romlen; romptr >= rombase; romptr -= 0x10)
+ {
+ if (is_resource(romptr))
+ nr_of_rsrcs++;
+ }
+ return nr_of_rsrcs;
+ }
+
+ void
+ w_build_resource_list(caddr_t rombase, u_int32_t romlen)
+ {
+ caddr_t romptr;
+ u_int32_t rsrc_no = 0;
+ #ifdef MRG_DEBUG
+ char rsrc_name[5];
+
+ printf("mrg: Resources found:\n");
+ #endif
+ nr_of_rsrcs = count_all_resources(rombase, romlen);
+ if(0 == (rsrc_header = (caddr_t *) malloc(nr_of_rsrcs * sizeof(caddr_t), M_TEMP, M_NOWAIT)))
+ panic("mrg: Can't malloc memory for rsrc_header list\n");
+ if(0 == (rsrc_handle = (caddr_t *) malloc(nr_of_rsrcs * sizeof(caddr_t), M_TEMP, M_NOWAIT)))
+ panic("mrg: Can't malloc memory for rsrc_handle list\n");
+
+ for (romptr = rombase + romlen; romptr >= rombase; romptr -= 0x10)
+ {
+ if (is_resource(romptr))
+ if (rsrc_no < nr_of_rsrcs)
+ {
+ rsrc_header[rsrc_no] = romptr;
+ rsrc_handle[rsrc_no] = (caddr_t) (ROMBase + *((u_int32_t *)(romptr + 0x0c)));
+ rsrc_no++;
+ #ifdef MRG_DEBUG
+ strncpy(rsrc_name, (char *) (romptr + 0x10), 4);
+ rsrc_name[4] = '\0';
+ printf("%4s 0x%2x ", rsrc_name, *((u_int16_t *) (romptr + 0x14)) );
+ #endif
+ }
+ }
+ #ifdef MRG_DEBUG
+ printf("\n");
+ #endif
+ }
+
+ int
+ w_count_resources(u_int32_t rsrc_type)
+ {
+ u_int32_t rsrc_no = 0;
+ u_int32_t rsrc_count = 0;
+
+ #ifdef MRG_DEBUG
+ char rsrc_name[5];
+
+ strncpy(rsrc_name, (char *) (&rsrc_type), 4);
+ rsrc_name[4] = '\0';
+ printf("mrg: w_count_resources called for resource %4s : ", rsrc_name);
+ #endif
+ while (rsrc_no < nr_of_rsrcs)
+ {
+ if (rsrc_type == *((u_int32_t *) (rsrc_header[rsrc_no] + 0x10)) )
+ rsrc_count++;
+ rsrc_no++;
+ }
+ #ifdef MRG_DEBUG
+ printf("found %d resources of requested type!\n", rsrc_count);
+ #endif
+ return rsrc_count;
+ }
+
+ caddr_t *
+ w_get_ind_resource(u_int32_t rsrc_type, u_int16_t rsrc_ind)
+ {
+ u_int32_t rsrc_no = 0;
+
+ #ifdef MRG_DEBUG
+ char rsrc_name[5];
+
+ strncpy(rsrc_name, (char *) (&rsrc_type), 4);
+ rsrc_name[4] = '\0';
+ printf("mrg: w_get_int_resource called for resource %4s, no. %d : ", rsrc_name, rsrc_ind);
+ #endif
+
+ while (rsrc_ind > 0)
+ {
+ while ( (rsrc_no < nr_of_rsrcs)
+ && (rsrc_type != *((u_int32_t *) (rsrc_header[rsrc_no] + 0x10)) )
+ )
+ {
+ rsrc_no++;
+ }
+ rsrc_ind--;
+ rsrc_no++;
+ }
+ rsrc_no--;
+ if (rsrc_no == nr_of_rsrcs)
+ { /* Error */
+ #ifdef MRG_DEBUG
+ printf("not found!\n");
+ #endif
+ return (caddr_t *) 0;
+ }
+ else
+ {
+ #ifdef MRG_DEBUG
+ printf("found at addr 0x%x -> 0x%x\n", &rsrc_handle[rsrc_no], rsrc_handle[rsrc_no]);
+ #endif
+ return (caddr_t *) &rsrc_handle[rsrc_no];
+ }
+ }
+
+
+ void
+ mrg_VBLQueue()
+ {
+ #define qLink 0
+ #define qType 4
+ #define vblAddr 6
+ #define vblCount 10
+ #define vblPhase 12
+
+ caddr_t vbltask;
+ caddr_t last_vbltask;
+
+ last_vbltask = (caddr_t) &VBLQueue_head;
+ vbltask = VBLQueue_head;
+ while (0 != vbltask)
+ {
+ if ( 0 != *((u_int16_t *)(vbltask + vblPhase)) )
+ {
+ *((u_int16_t *)(vbltask + vblPhase)) -= 1;
+ } else
+ {
+ if ( 0 != *((u_int16_t *)(vbltask + vblCount)) )
+ {
+ *((u_int16_t *)(vbltask + vblCount)) -= 1;
+ } else
+ {
+ #if defined(MRG_DEBUG)
+ printf("mrg: mrg_VBLQueue: calling VBL task at 0x%x with VBLTask block at 0x%x\n",
+ *((u_int32_t *)(vbltask + vblAddr)), vbltask);
+ #endif
+ asm(" movml #0xfffe, sp@- /* better save all registers! */
+ movl %0, a0
+ movl %1, a1
+ jbsr a1@
+ movml sp@+, #0x7fff" /* better restore all registers! */
+ :
+ : "g" (vbltask), "g" (*((caddr_t)(vbltask + vblAddr))));
+ #if defined(MRG_DEBUG)
+ printf("mrg: mrg_VBLQueue: back from VBL task\n");
+ #endif
+ if ( 0 == *((u_int16_t *)(vbltask + vblCount)) )
+ {
+ #if defined(MRG_DEBUG)
+ printf("mrg: mrg_VBLQueue: removing VBLTask block at 0x%x\n",
+ vbltask);
+ #endif
+ *((u_int32_t *)(last_vbltask + qLink)) = *((u_int32_t *)(vbltask + qLink));
+ /* can't free memory from VBLTask block as
+ * we don't know where it came from */
+ if (vbltask == VBLQueue_tail)
+ { /* last task of do{}while */
+ VBLQueue_tail = last_vbltask;
+ }
+ }
+ }
+ }
+ last_vbltask = vbltask;
+ vbltask = (caddr_t) *((u_int32_t *)(vbltask + qLink));
+ } /* while */
+ }
+
+
+ void
+ mrg_init_stub_1()
+ {
+ asm("movml #0xffff, sp@-");
+ printf("mrg: hit mrg_init_stub_1\n");
+ asm("movml sp@+, #0xffff");
+ }
+
+ void
+ mrg_init_stub_2()
+ {
+ panic("mrg: hit mrg_init_stub_2\n");
+ }
+
void
mrg_1sec_timer_tick()
{
***************
*** 229,234 ****
--- 472,478 ----
#endif
*(u_int32_t *)ptr = numbytes;
ptr += 4;
+ bzero(ptr, numbytes); /* NewPtr, Clear ! */
}
asm(" movl %0, a0" : : "g" (ptr));
***************
*** 298,303 ****
--- 542,552 ----
return 0;
}
+ void
+ mrg_StripAddress()
+ {
+ }
+
/*
* trap jump address tables (different per machine?)
* Can I just use the tables stored in the ROMs?
***************
*** 313,318 ****
--- 562,570 ----
(caddr_t)mrg_SetPtrSize,
(caddr_t)mrg_GetPtrSize,
[0x2f] (caddr_t)mrg_PostEvent,
+ [0x3b] (caddr_t)mrg_Delay,
+ [0x47] (caddr_t)mrg_SetOSTrapAddress,
+ [0x55] (caddr_t)mrg_StripAddress,
[0x77] (caddr_t)0x40807778, /* CountADBs */
(caddr_t)0x40807792, /* GetIndADB */
(caddr_t)0x408077be, /* GetADBInfo */
***************
*** 327,336 ****
--- 579,613 ----
};
caddr_t mrg_ToolBoxtraps[1024] = {
+ [0x19c] (caddr_t)mrg_CountResources,
+ [0x19d] (caddr_t)mrg_GetIndResource,
[0x1a0] (caddr_t)mrg_GetResource,
[0x1af] (caddr_t)mrg_ResError,
};
+ int
+ mrg_SetOSTrapAddress()
+ {
+ int result = noErr;
+ u_int trapnumber;
+ u_int trapaddress;
+ u_int32_t trapword;
+
+ asm(" movl d1, %0
+ movl d0, %1
+ movl a0, %2"
+ : "=g" (trapword), "=g" (trapnumber), "=g" (trapaddress));
+
+ #if defined(MRG_SHOWTRAPS)
+ printf("mrg: SetOSTrapAddress(Trap: 0x%x, Address: 0x%8x)", trapnumber,
+ trapaddress);
+ #endif
+
+ mrg_OStraps[trapnumber] = (caddr_t) trapaddress;
+
+ return(result);
+ }
+
/*
* Handle a supervisor mode A-line trap.
*/
***************
*** 377,382 ****
--- 654,661 ----
trapaddr = mrg_OStraps[trapnum];
#if defined(MRG_DEBUG)
printf(" addr 0x%x\n", trapaddr);
+ printf(" got: d0 = 0x%8x, a0 = 0x%8x, called from: 0x%8x\n",
+ frame->f_regs[0], frame->f_regs[8], frame->f_pc );
#endif
if(trapaddr == NULL){
printf("unknown %s trap 0x%x, no trap address available\n",
***************
*** 422,427 ****
--- 701,708 ----
troff();
#endif
#if defined(MRG_DEBUG)
+ printf(" result: d0 = 0x%8x, a0 = 0x%8x\n",
+ d0bucket, a0bucket );
printf(" bk");
#endif
***************
*** 521,526 ****
--- 802,811 ----
printf("Can't read RTC without it. Using MacOS boot time.\n");
}
+ mrg_ToolBoxtraps[0x04d] = rom->FixDiv;
+ mrg_ToolBoxtraps[0x068] = rom->FixMul;
+
+
#if defined(MRG_DEBUG)
printf("mrg: ROM adbintr 0x%08x\n", mrg_romadbintr);
printf("mrg: ROM pmintr 0x%08x\n", mrg_rompmintr);
***************
*** 556,562 ****
caddr_t *handle;
int sizeptr;
extern short mrg_ResErr;
!
if(mrg_romready()){
printf("mrg: '%s' rom glue", mrg_romident);
--- 841,853 ----
caddr_t *handle;
int sizeptr;
extern short mrg_ResErr;
!
! w_build_resource_list(ROMBase, 0x00100000); /* search one MB */
!
! VBLQueue = (u_int16_t) 0; /* No vertical blanking routines in the queue */
! VBLQueue_head = (caddr_t) 0; /* Let's hope that this init happens
! VBLQueue_tail = (caddr_t) 0; * before the RTC interrupts are enabled */
!
if(mrg_romready()){
printf("mrg: '%s' rom glue", mrg_romident);
***************
*** 592,597 ****
--- 883,901 ----
printf("mrg: start init\n");
#endif
/* expected globals */
+ ExpandMem = &mrg_ExpandMem[0];
+ *((u_int16_t *)(mrg_ExpandMem + 0x00) ) = 0x0123; /* magic (word) */
+ *((u_int32_t *)(mrg_ExpandMem + 0x02) ) = 0x000001ea; /* Length of table (long) */
+ *((u_int32_t *)(mrg_ExpandMem + 0x1e0)) = (u_int32_t) &mrg_adbstore4[0];
+
+ *((u_int32_t *)(mrg_adbstore4 + 0x8)) = (u_int32_t) mrg_init_stub_1;
+ *((u_int32_t *)(mrg_adbstore4 + 0xc)) = (u_int32_t) mrg_init_stub_2;
+ *((u_int32_t *)(mrg_adbstore4 + 0x4)) = (u_int32_t) &mrg_adbstore5[0];
+
+ *((u_int32_t *)(mrg_adbstore5 + 0x08)) = (u_int32_t) 0x00100000;
+ *((u_int32_t *)(mrg_adbstore5 + 0x0c)) = (u_int32_t) 0x00100000;
+ *((u_int32_t *)(mrg_adbstore5 + 0x16)) = (u_int32_t) 0x00480000;
+
ADBBase = &mrg_adbstore[0];
ADBState = &mrg_adbstore2[0];
ADBYMM = &mrg_adbstore3[0];
***************
*** 698,705 ****
movml sp@+, a0-a2 "
:
: "g" (mrg_InitEgret), "g" (ADBState));
}
! else printf("Help ... No vector for InitEgret!!");
}
void
--- 1002,1017 ----
movml sp@+, a0-a2 "
:
: "g" (mrg_InitEgret), "g" (ADBState));
+ jEgret = (void (*)) mrg_OStraps[0x92]; /* may have been set in asm() */
}
! else printf("Help ... No vector for InitEgret!!\n");
!
! printf("mrg: ADBIntrVector: 0x%8x, mrg_ADBIntrVector: 0x%8x\n",
! (long) mrg_romadbintr,
! *((long *) 0x19a));
! printf("mrg: EgretOSTrap: 0x%8x\n",
! (long) mrg_OStraps[0x92]);
!
}
void
***************
*** 734,740 ****
* set it up. If not, just enable the interrupts (only on
* some machines, others are already on from ADBReInit?).
*/
! if ( (HwCfgFlags3 & 0x0e) == 0x06 ) {
if (mac68k_machine.do_graybars)
printf("mrg: setup_egret:\n");
--- 1046,1053 ----
* set it up. If not, just enable the interrupts (only on
* some machines, others are already on from ADBReInit?).
*/
! if ( ((HwCfgFlags3 & 0x0e) == 0x06 )
! || ((HwCfgFlags3 & 0x70) == 0x20 )) {
if (mac68k_machine.do_graybars)
printf("mrg: setup_egret:\n");
***************
*** 774,779 ****
--- 1087,1098 ----
temp = (u_int) mrg_OStraps[i];
temp = (temp - oldbase) + newbase;
mrg_OStraps[i] = (caddr_t) temp;
+ }
+ for (i=0 ; i<1024 ; i++)
+ if (IS_ROM_ADDR(mrg_ToolBoxtraps[i])) {
+ temp = (u_int) mrg_ToolBoxtraps[i];
+ temp = (temp - oldbase) + newbase;
+ mrg_ToolBoxtraps[i] = (caddr_t) temp;
}
p = (u_int32_t *) mrg_adbstore;
for (i=0 ; i<512/4 ; i++)
diff -c mac68k/mac68k/macromasm.s mac68k.vi/mac68k/macromasm.s
*** mac68k/mac68k/macromasm.s Fri Feb 2 14:16:55 1996
--- mac68k.vi/mac68k/macromasm.s Tue Feb 20 13:02:48 1996
***************
*** 98,103 ****
--- 98,108 ----
loglob(jClkNoMem, 0x54c) /* Pointer to ClkNoMem function */
loglob(PramTransfer, 0x1e4) /* Transfer buffer used with PRam */
loglob(SysParam, 0x1f8) /* Place where PRam data gets stored */
+ loglob(ExpandMem, 0x2b6) /* pointer to Expanded Memory used by */
+ /* newer ADB routines */
+ loglob(VBLQueue, 0x160) /* Vertical blanking Queue, unused ? */
+ loglob(VBLQueue_head, 0x162) /* Vertical blanking Queue, head */
+ loglob(VBLQueue_tail, 0x166) /* Vertical blanking Queue, tail */
#if 0
***************
*** 125,130 ****
--- 130,145 ----
* to the ROMs; none of this is called.
*/
+ /* Initialize Utils, mainly XPRam */
+ .global _InitUtil
+ /*
+ * void
+ */
+ _InitUtil:
+ .word 0xa03f
+ rts
+
+
/* Initialize the ADB ------------------------------------------------------*/
.global _ADBReInit
/*
***************
*** 339,344 ****
--- 354,396 ----
movl #-192, d0 | resNotFound; that's pretty accurate.
movw d0, _mrg_ResErr | set current ResMan error
pascalret(6) | I hate Pascal.
+
+
+
+ function(mrg_CountResources)
+ /* WRU: 960120
+ * sp@(4) u_int32_t rsrc_type
+ * sp@(8) u_int16_t nr_of_rsrcs
+ */
+ movl sp@(4), d0
+ movl d0, sp@-
+ jbsr _w_count_resources
+ addl #4, sp /* pop C params */
+ movw d0, sp@(8) /* store result */
+ movl sp@+, a0 /* get PC */
+ addl #4, sp /* pop params */
+ jra a0@ /* return */
+
+
+
+ function(mrg_GetIndResource)
+ /* WRU: 960120
+ * sp@(4) u_int16_t rsrc_index
+ * sp@(6) u_int32_t rsrc_type
+ * sp@(10) caddr_t *rsrc_handle
+ */
+ movl sp@(6), a0
+ clrl d0
+ movw sp@(4), d0
+ movl d0, sp@-
+ movl a0, sp@-
+ jbsr _w_get_ind_resource
+ addl #8, sp /* pop C params */
+ movl d0, sp@(10) /* store result */
+ movl sp@+, a0 /* get PC */
+ addl #6, sp /* pop params */
+ jra a0@ /* return */
+
/*
* I'd like to take a moment here to talk about the calling convention
diff -c mac68k/mac68k/locore.s mac68k.vi/mac68k/locore.s
*** mac68k/mac68k/locore.s Sun Feb 11 13:23:51 1996
--- mac68k.vi/mac68k/locore.s Tue Feb 20 21:16:29 1996
***************
*** 553,558 ****
--- 553,559 ----
*/
/* BARF We must re-configure this. */
.globl _hardclock, _nmihand
+ .globl _mrg_VBLQueue
_spurintr:
_lev3intr:
***************
*** 612,617 ****
--- 613,619 ----
movl sp, sp@- | push pointer to ps, pc
jbsr _hardclock | call generic clock int routine
lea sp@(12), sp | pop params
+ jbsr _mrg_VBLQueue | give programs in the VBLqueue a chance
addql #1,_intrcnt+20 | add another system clock interrupt
addql #1,_cnt+V_INTR | chalk up another interrupt
diff -c mac68k/mac68k/autoconf.c mac68k.vi/mac68k/autoconf.c
*** mac68k/mac68k/autoconf.c Sun Feb 4 14:01:51 1996
--- mac68k.vi/mac68k/autoconf.c Tue Feb 20 13:13:22 1996
***************
*** 134,142 ****
mrg_init(); /* Init Mac ROM Glue */
adb_init(); /* ADB device subsystem & driver */
! startrtclock();
if (config_rootfound("mainbus", "mainbus") == 0)
panic("No main device!");
--- 134,144 ----
mrg_init(); /* Init Mac ROM Glue */
+ startrtclock(); /* swapped with adb_init (WRU) */
+
adb_init(); /* ADB device subsystem & driver */
! /* startrtclock(); swapped with adb_init (WRU) */
if (config_rootfound("mainbus", "mainbus") == 0)
panic("No main device!");
>Audit-Trail:
>Unformatted: