A pc/archgeneric.c => pc/archgeneric.c +25 -0
@@ 0,0 1,25 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+static void
+genericreset(void)
+{
+ print("Reset the machine!\n");
+ for(;;);
+}
+
+PCArch generic =
+{
+ "generic",
+ genericreset,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+};
A pc/archncr3170.c => pc/archncr3170.c +49 -0
@@ 0,0 1,49 @@
+#include "u.h"
+#include "../port/lib.h"
+#include "mem.h"
+#include "dat.h"
+#include "fns.h"
+#include "io.h"
+
+enum
+{
+ Pindex= 0x198,
+ Pdata= 0x199,
+};
+
+static Lock pmulock;
+static int
+pmuwrbit(int index, int bit, int pos)
+{
+ uchar x;
+
+ lock(&pmulock);
+ outb(Pindex, index);
+ x = inb(Pdata);
+ if(bit)
+ x |= 1<<pos;
+ else
+ x &= ~(1<<pos);
+ outb(Pindex, index);
+ outb(Pdata, x);
+ unlock(&pmulock);
+ return 0;
+}
+
+static int
+ncr3170serialpower(int onoff)
+{
+ return pmuwrbit(0x85, 1^onoff, 4);
+}
+
+PCArch ncr3170 =
+{
+ "NCRD.0",
+ i8042reset,
+ 0,
+ 0,
+ 0,
+ ncr3170serialpower,
+ 0,
+ 0,
+};
R pc/pmu.c => pc/archnsx20.c +50 -12
@@ 6,6 6,10 @@
#include "io.h"
/*
+ * safari nsx20 specific routines
+ */
+
+/*
* intel power management unit (i80c51)
*/
enum {
@@ 54,8 58,8 @@ pmubusy(void)
/*
* set a bit in the PMU
*/
-Lock pmulock;
-int
+static Lock pmulock;
+static int
pmuwrbit(int index, int bit, int pos)
{
lock(&pmulock);
@@ 90,8 94,8 @@ pmuwrbit(int index, int bit, int pos)
* onoff == 1 means on
* onoff == 0 means off
*/
-int
-pmuserial(int onoff)
+static int
+nsx20serialpower(int onoff)
{
return pmuwrbit(1, 1^onoff, 6);
}
@@ 101,8 105,8 @@ pmuserial(int onoff)
* onoff == 1 means on
* onoff == 0 means off
*/
-int
-pmumodem(int onoff)
+static int
+nsx20modempower(int onoff)
{
if(pmuwrbit(1, 1^onoff, 0)<0) /* modem speaker */
return -1;
@@ 114,8 118,8 @@ pmumodem(int onoff)
* 0 == low speed
* 1 == high speed
*/
-int
-pmucpuspeed(int speed)
+static int
+nsx20cpuspeed(int speed)
{
return pmuwrbit(0, speed, 0);
}
@@ 124,8 128,8 @@ pmucpuspeed(int speed)
* f == frequency in Hz
* d == duration in ms
*/
-void
-pmubuzz(int f, int d)
+static void
+nsx20buzz(int f, int d)
{
static QLock bl;
static Rendez br;
@@ 142,9 146,43 @@ pmubuzz(int f, int d)
* 1 == owl eye
* 2 == mail icon
*/
-void
-pmulights(int val)
+static void
+nsx20lights(int val)
{
pmuwrbit(0, (val&1), 4); /* owl */
pmuwrbit(0, ((val>>1)&1), 1); /* mail */
}
+
+/*
+ * headland system controller (ht21)
+ */
+enum
+{
+ /*
+ * system control port
+ */
+ Head= 0x92, /* control port */
+ Reset= (1<<0), /* reset the 386 */
+ A20ena= (1<<1), /* enable address line 20 */
+};
+
+/*
+ * reset machine
+ */
+static void
+headreset(void)
+{
+ outb(Head, Reset);
+}
+
+PCArch nsx20 =
+{
+ "AT&TNSX",
+ headreset,
+ nsx20cpuspeed,
+ nsx20buzz,
+ nsx20lights,
+ nsx20serialpower,
+ nsx20modempower,
+ 0,
+};
M pc/clock.c => pc/clock.c +32 -18
@@ 16,32 16,36 @@ enum
T2cntr= 0x42, /* ... */
Tmode= 0x43, /* mode port */
- Load0square= 0x36, /* load counter 0 with 2 bytes,
- * output a square wave whose
- * period is the counter period
- */
- Latch0= 0x06,
- Freq= 1193182, /* Real clock frequency */
+ /* commands */
+ Latch0= 0x00, /* latch counter 0's value */
+ Load0= 0x30, /* load counter 0 with 2 bytes */
+
+ /* modes */
+ Square= 0x36, /* perioic square wave */
+
+ Freq= 1193182, /* Real clock frequency */
};
+static ulong delayloop = 1000;
+
/*
- * delay for l milliseconds
+ * delay for l milliseconds more or less. delayloop is set by
+ * clockinit() to match the actual CPU speed.
*/
void
delay(int l)
{
- int i;
+ ulong i;
- while(--l){
- for(i=0; i < 404; i++)
+ while(l-- > 0)
+ for(i=0; i < delayloop; i++)
;
- }
}
void
clockinit(void)
{
- ulong dc; /* change in counter */
+ ulong x, y; /* change in counter */
/*
* set vector for clock interrupts
@@ 51,18 55,28 @@ clockinit(void)
/*
* make clock output a square wave with a 1/HZ period
*/
- outb(Tmode, Load0square);
+ outb(Tmode, Load0|Square);
outb(T0cntr, (Freq/HZ)); /* low byte */
outb(T0cntr, (Freq/HZ)>>8); /* high byte */
/*
- * measure cpu speed to make delay() system
- * independent
+ * measure time for delay(10) with current delayloop count
*/
- delay(100);
outb(Tmode, Latch0);
- dc = inb(T0cntr);
- dc |= inb(T0cntr)<<8;
+ x = inb(T0cntr);
+ x |= inb(T0cntr)<<8;
+ delay(10);
+ outb(Tmode, Latch0);
+ y = inb(T0cntr);
+ y |= inb(T0cntr)<<8;
+ x -= y;
+
+ /*
+ * fix count, the factor of 2 is a hack
+ */
+ delayloop = (delayloop*1193*10)/x;
+ if(delayloop == 0)
+ delayloop = 1;
}
void
M pc/dat.h => pc/dat.h +18 -5
@@ 4,6 4,7 @@ typedef struct Label Label;
typedef struct Lock Lock;
typedef struct MMU MMU;
typedef struct Mach Mach;
+typedef struct PCArch PCArch;
typedef struct Page Page;
typedef struct PMMU PMMU;
typedef struct Segdesc Segdesc;
@@ 177,14 178,26 @@ struct
short exiting;
}active;
+/*
+ * routines for things outside the PC model, like power management
+ */
+struct PCArch
+{
+ char *id;
+ void (*reset)(void); /* this should be in the model */
+ int (*cpuspeed)(int); /* 0 = low, 1 = high */
+ void (*buzz)(int, int); /* make a noise */
+ void (*lights)(int); /* turn lights or icons on/off */
+ int (*serialpower)(int); /* 1 == on, 0 == off */
+ int (*modempower)(int); /* 1 == on, 0 == off */
+ int (*extvga)(int); /* 1 == external, 0 == internal */
+};
+
extern Mach *m;
extern User *u;
extern int flipD[]; /* for flipping bitblt destination polarity */
-/*
- * bootline passed by boot program
- */
-#define BOOTLINE ((char *)0x80000100)
+#define BOOTLINE ((char *)0x80000100) /* bootline passed by boot program */
-extern char machtype[];
+extern PCArch *arch; /* PC architecture */
M pc/ether509.c => pc/ether509.c +37 -25
@@ 78,6 78,30 @@ enum {
#define COMMAND(hw, cmd, a) outs(hw->addr+Command, ((cmd)<<11)|(a))
/*
+ * Write two 0 bytes to idnetify the IDport and them reset the
+ * ID sequence. Then send the ID sequenced to the card to get
+ * the card it into command state.
+ */
+void
+idseq(void)
+{
+ int i;
+ uchar al;
+
+ outb(IDport, 0);
+ outb(IDport, 0);
+ for(al = 0xFF, i = 0; i < 255; i++){
+ outb(IDport, al);
+ if(al & 0x80){
+ al <<= 1;
+ al ^= 0xCF;
+ }
+ else
+ al <<= 1;
+ }
+}
+
+/*
* get configuration parameters
*/
static int
@@ 85,8 109,7 @@ reset(EtherCtlr *cp)
{
EtherHw *hw = cp->hw;
int i, ea;
- ushort acr;
- uchar al;
+ ushort x, acr;
cp->rb = xspanalloc(sizeof(EtherBuf)*Nrb, BY2PG, 0);
cp->nrb = Nrb;
@@ 98,23 121,12 @@ reset(EtherCtlr *cp)
* at the first board that responds, if we ever have more
* than one we'll need to modify this sequence.
*
- * 2. Write two 0 bytes then the ID sequence to the IDport.
+ * 2. get to cammand state, reset, then return to command state
*/
- outb(IDport, 0);
- outb(IDport, 0);
- outb(IDport, 0xc0);
- delay(100)
- outb(IDport, 0);
- outb(IDport, 0);
- for(al = 0xFF, i = 0; i < 255; i++){
- outb(IDport, al);
- if(al & 0x80){
- al <<= 1;
- al ^= 0xCF;
- }
- else
- al <<= 1;
- }
+ idseq();
+ outb(IDport, 0xC1);
+ delay(2);
+ idseq();
/*
* 3. Read the Product ID from the EEPROM.
@@ 128,12 140,12 @@ reset(EtherCtlr *cp)
* probably isn't there, so barf.
*/
outb(IDport, 0x83);
- for(acr = 0, i = 0; i < 16; i++){
+ for(x = 0, i = 0; i < 16; i++){
delay(5);
- acr <<= 1;
- acr |= inb(IDport) & 0x01;
+ x <<= 1;
+ x |= inb(IDport) & 0x01;
}
- if((acr & 0xF0FF) != 0x9050)
+ if((x & 0xF0FF) != 0x9050)
return -1;
/*
@@ 172,9 184,9 @@ reset(EtherCtlr *cp)
outs(hw->addr+EEPROMcmd, (2<<6)|i);
while(ins(hw->addr+EEPROMcmd) & 0x8000)
;
- acr = ins(hw->addr+EEPROMdata);
- cp->ea[ea] = (acr>>8) & 0xFF;
- cp->ea[ea+1] = acr & 0xFF;
+ x = ins(hw->addr+EEPROMdata);
+ cp->ea[ea] = (x>>8) & 0xFF;
+ cp->ea[ea+1] = x & 0xFF;
}
/*
M pc/fns.h => pc/fns.h +0 -7
@@ 24,8 24,6 @@ void fpsave(FPsave*);
ulong fpstatus(void);
ulong getcr0(void);
ulong getcr2(void);
-void heada20(void);
-void headreset(void);
void i8042a20(void);
void i8042reset(void);
void ident(void);
@@ 47,11 45,6 @@ void outb(int, int);
void outs(int, ushort);
void outss(int, void*, int);
void outsl(int, void*, int);
-void pmubuzz(int, int);
-int pmucpuspeed(int);
-void pmulights(int);
-int pmumodem(int);
-int pmuserial(int);
void prhex(ulong);
void procrestore(Proc*);
void procsave(Proc*);
D pc/headland.c => pc/headland.c +0 -37
@@ 1,37 0,0 @@
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-/*
- * headland system controller (ht21)
- */
-enum
-{
- /*
- * system control port
- */
- Head= 0x92, /* control port */
- Reset= (1<<0), /* reset the 386 */
- A20ena= (1<<1), /* enable address line 20 */
-};
-
-/*
- * enable address bit 20
- */
-void
-heada20(void)
-{
- outb(Head, A20ena);
-}
-
-/*
- * reset machine
- */
-void
-headreset(void)
-{
- outb(Head, Reset);
-}
M pc/main.c => pc/main.c +29 -68
@@ 8,24 8,19 @@
#include "init.h"
#include <ctype.h>
-/* configuration parameters */
-enum
-{
- /* what kind of power management */
- PMUother= 0,
- PMUnsx20= 1,
-
- /* how to reset the processor */
- Resetother= 0,
- Reset8042= 1,
- Resetheadland= 2,
-};
-int pmutype;
-int resettype;
-char machtype[9];
uchar *sp; /* stack pointer for /boot */
+extern PCArch nsx20, generic, ncr3170;
+
+PCArch *arch;
+PCArch *knownarch[] =
+{
+ &nsx20,
+ &ncr3170,
+ &generic,
+};
+
void
main(void)
{
@@ 51,7 46,6 @@ main(void)
streaminit();
swapinit();
userinit();
-
schedinit();
}
@@ 64,21 58,12 @@ void
ident(void)
{
char *id = (char*)(ROMBIOS + 0xFF40);
- int i;
+ PCArch **p;
- for(i = 0; i < 8; i++){
- if(isprint(id[i]) == 0)
+ for(p = knownarch; *p != &generic; p++)
+ if(strncmp((*p)->id, id, strlen((*p)->id)) == 0)
break;
- machtype[i] = id[i];
- }
- if(i == 0)
- strcpy(machtype, "generic");
- if(strcmp(machtype, "AT&TNSX") == 0){
- pmutype = PMUnsx20;
- resettype = Resetheadland;
- }else if(strcmp(machtype, "NCRD.0") == 0){
- resettype = Reset8042;
- }
+ arch = *p;
}
void
@@ 117,7 102,7 @@ init0(void)
chandevinit();
if(!waserror()){
- strcpy(tstr, machtype);
+ strcpy(tstr, arch->id);
strcat(tstr, " %s");
ksetterm(tstr);
ksetenv("cputype", "386");
@@ 447,15 432,7 @@ exit(int ispanic)
if(ispanic)
for(;;);
- switch(resettype){
- case Resetheadland:
- headreset();
- case Reset8042:
- i8042reset(); /* via keyboard controller */
- default:
- print("Reset the machine!\n");
- for(;;);
- }
+ (*arch->reset)();
}
/*
@@ 466,12 443,10 @@ exit(int ispanic)
int
cpuspeed(int speed)
{
- switch(pmutype){
- case PMUnsx20:
- return pmucpuspeed(speed);
- default:
+ if(arch->cpuspeed)
+ return (*arch->cpuspeed)(speed);
+ else
return 0;
- }
}
/*
@@ 481,13 456,8 @@ cpuspeed(int speed)
void
buzz(int f, int d)
{
- switch(pmutype){
- case PMUnsx20:
- pmubuzz(f, d);
- break;
- default:
- break;
- }
+ if(arch->buzz)
+ (*arch->buzz)(f, d);
}
/*
@@ 496,13 466,8 @@ buzz(int f, int d)
void
lights(int val)
{
- switch(pmutype){
- case PMUnsx20:
- pmulights(val);
- break;
- default:
- break;
- }
+ if(arch->lights)
+ (*arch->lights)(val);
}
/*
@@ 513,12 478,10 @@ lights(int val)
int
serial(int onoff)
{
- switch(pmutype){
- case PMUnsx20:
- return pmuserial(onoff);
- default:
+ if(arch->serialpower)
+ return (*arch->serialpower)(onoff);
+ else
return 0;
- }
}
/*
@@ 529,10 492,8 @@ serial(int onoff)
int
modem(int onoff)
{
- switch(pmutype){
- case PMUnsx20:
- return pmumodem(onoff);
- default:
+ if(arch->modempower)
+ return (*arch->modempower)(onoff);
+ else
return 0;
- }
}
M port/sysproc.c => port/sysproc.c +1 -0
@@ 308,6 308,7 @@ sysexec(ulong *arg)
nargs++;
}
ssize = BY2WD*(nargs+1) + ((nbytes+(BY2WD-1)) & ~(BY2WD-1));
+
/*
* 8-byte align SP for those (e.g. sparc) that need it.
* execregs() will subtract another 4 bytes for argc.
M power/mem.h => power/mem.h +1 -1
@@ 120,7 120,7 @@
#define UTZERO (UZERO+BY2PG) /* first address in user text */
#define USTKTOP KZERO /* byte just beyond user stack */
#define TSTKTOP (USERADDR+USTKSIZE) /* top of temporary stack */
-#define TSTKSIZ 100
+#define TSTKSIZ 500
#define KZERO KSEG0 /* base of kernel address space */
#define KTZERO (KZERO+0x20000) /* first address in kernel text */
#define USTKSIZE (4*1024*1024) /* size of user stack */