#!/bin/rc # # command: /bin/boddle /n/cd/sys/src/fs/pc pc # srcdir: /n/cd/sys/src/fs/pc # version: 918342595 # date: Sat Feb 6 18:09:55 EST 1999 # myname=$0 doextract=no fn usage{ echo $myname: usage: $myname '[-X] [src-directory]' >[1=2] exit usage } fn sigint{ rm -rf 918342595 exit interrupt } while(~ $1 -*){ switch($1){ case -X doextract=yes case -* usage } shift } switch($#*){ case 0 srcdir=/n/cd/sys/src/fs/pc case 1 srcdir=$1 case * usage } if(! ~ $doextract yes){ echo This shell file contains a bundle of diffs representing changes echo to original source files in the Plan 9 distribution. It will run echo against the files in echo ' ' $srcdir echo '(unless overridden by the optional source directory argument)' echo and create a directory 918342595 containing the updated files. echo It will NOT automatically update the original files. echo echo Invoke with argument -X to perform the actual extraction. exit 0 } rm -rf 918342595 mkdir 918342595 target=918342595/8253.c echo -n '918342595/8253.c: ' if(! test -f $srcdir/8253.c || ! test -r $srcdir/8253.c){ echo $srcdir/8253.c unreadable exit unreadable } sum=`{sum < $srcdir/8253.c} if(! ~ db5037461800 $sum(1)^$sum(2)){ echo $srcdir/8253.c is not the original distribution file exit original } cp $srcdir/8253.c 918342595/8253.c ed 918342595/8253.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM 8253.c' 86,113c /* * add in possible .2% error and convert to MHz */ cpumhz = (cpufreq + cpufreq/500)/1000000; . 81,84c cpufreq = loops*((t->aalcycles*Freq)/x); loopconst = (cpufreq/1000)/t->aalcycles; /* AAM+LOOP's for 1 ms */ . 79c * figure out clock frequency and a loop multiplier for delay(). . 69,76c x >>= 1; . 67c * counter goes at twice the frequency, once per transition, * i.e., twice per square wave . 65a /* find biggest loop that doesn't wrap */ incr = 16000000/(t->aalcycles*HZ*2); x = 2000; for(loops = incr; loops < 64*1024; loops += incr) { /* * measure time for the loop * * MOVL loops,CX * aaml1: AAM * LOOP aaml1 * * the time for the loop should be independent of external * cache and memory system since it fits in the execution * prefetch buffer. * */ outb(Tmode, Latch0); x = inb(T0cntr); x |= inb(T0cntr)<<8; aamloop(loops); outb(Tmode, Latch0); y = inb(T0cntr); y |= inb(T0cntr)<<8; x -= y; if(x < 0) x += Freq/HZ; if(x > Freq/(3*HZ)) break; } . 61a x86cpuid(&cpuidax, &cpuiddx); family = FAMILY(cpuidax); model = MODEL(cpuidax); for(t = x86type; t->name; t++) if((t->family == family && t->model == model) || (t->family == family && t->model == -1) || (t->family == -1)) break; cputype = t; /* * set clock for 1/HZ seconds */ . 60c * figure out what we are . 52c int x, y; /* change in counter */ int family, model, loops, incr; X86type *t; . 45,46c print("CPU is a %d MHz %s (cpuid: ax %lux dx %lux)\n", cpumhz, cputype->name, cpuidax, cpuiddx); . 42,43c void printcpufreq(void) . 37,39c /* * microsecond delay */ void microdelay(int l) { l *= loopconst; l /= 1000; if(l <= 0) l = 1; aamloop(l); . 35c l *= loopconst; if(l <= 0) l = 1; aamloop(l); } . 27a static void clockintr(Ureg *ur, void *v) { USED(v); clock(0, ur->pc); } #define STEPPING(x) ((x)&0xf) #define MODEL(x) (((x)>>4)&0xf) #define FAMILY(x) (((x)>>8)&0xf) enum { /* flags */ CpuidFPU = 0x001, /* on-chip floating point unit */ CpuidMCE = 0x080, /* machine check exception */ CpuidCX8 = 0x100, /* CMPXCHG8B instruction */ }; typedef struct { int family; int model; int aalcycles; char *name; } X86type; X86type x86type[] = { /* from the cpuid instruction */ { 4, 0, 22, "Intel486DX", }, { 4, 1, 22, "Intel486DX", }, { 4, 2, 22, "Intel486SX", }, { 4, 3, 22, "Intel486DX2", }, { 4, 4, 22, "Intel486DX2", }, { 4, 5, 22, "Intel486SL", }, { 4, 8, 22, "IntelDX4", }, { 5, 1, 23, "Pentium510", }, { 5, 2, 23, "Pentium735", }, /* family defaults */ { 3, -1, 32, "Intel386", }, { 4, -1, 22, "Intel486", }, { 5, -1, 23, "Pentium", }, /* total default */ { -1, -1, 23, "unknown", }, }; static X86type *cputype; . 26c static int cpufreq = 66000000; static int cpumhz = 66; static int loopconst = 100; static int cpuidax, cpuiddx; . 21a Trigger= 0x30, /* interrupt on terminal count */ . wq //GO.SYSIN DD VADIM 8253.c sum=`{sum < 918342595/8253.c} if(~ 61820e873701 $sum(1)^$sum(2)) echo if not{ echo 918342595/8253.c checksum error creating updated file exit checksum } target=918342595/9pcfs.c echo -n '918342595/9pcfs.c: ' if(! test -f $srcdir/9pcfs.c || ! test -r $srcdir/9pcfs.c){ echo $srcdir/9pcfs.c unreadable exit unreadable } sum=`{sum < $srcdir/9pcfs.c} if(! ~ 684354542476 $sum(1)^$sum(2)){ echo $srcdir/9pcfs.c is not the original distribution file exit original } cp $srcdir/9pcfs.c 918342595/9pcfs.c ed 918342595/9pcfs.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM 9pcfs.c' 38a printcpufreq(); . wq //GO.SYSIN DD VADIM 9pcfs.c sum=`{sum < 918342595/9pcfs.c} if(~ 9df269282493 $sum(1)^$sum(2)) echo if not{ echo 918342595/9pcfs.c checksum error creating updated file exit checksum } target=918342595/fns.h echo -n '918342595/fns.h: ' if(! test -f $srcdir/fns.h || ! test -r $srcdir/fns.h){ echo $srcdir/fns.h unreadable exit unreadable } sum=`{sum < $srcdir/fns.h} if(! ~ c6a11d731559 $sum(1)^$sum(2)){ echo $srcdir/fns.h is not the original distribution file exit original } cp $srcdir/fns.h 918342595/fns.h ed 918342595/fns.h >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM fns.h' 61,62c int x86cpuid(int*, int*); . 44a void printcpureg(void); . 23a long idesize(Device); int ideread(Device, long, void *); int idewrite(Device, long, void *); void ideinit(Device); . 4a void aamloop(int); . wq //GO.SYSIN DD VADIM fns.h sum=`{sum < 918342595/fns.h} if(~ b478c8361727 $sum(1)^$sum(2)) echo if not{ echo 918342595/fns.h checksum error creating updated file exit checksum } target=918342595/hard.c echo -n '918342595/hard.c: ' if(! test -f $srcdir/hard.c || ! test -r $srcdir/hard.c){ echo $srcdir/hard.c unreadable exit unreadable } sum=`{sum < $srcdir/hard.c} if(! ~ b86b8f3515450 $sum(1)^$sum(2)){ echo $srcdir/hard.c is not the original distribution file exit original } cp $srcdir/hard.c 918342595/hard.c ed 918342595/hard.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM hard.c' 749a /* * fs entry points for IDE device Devide */ void ideinit( Device d ) { Disc *dp; cmd_install( "stath", "-- ide stats", cmd_stats ); dp = &hard[ d.unit + 2*d.ctrl ]; dofilter( &(dp->rate) ); dofilter( &(dp->work) ); } /* * idesize * return device size in logical blocks of RBUFSIZE units. */ long idesize( Device d ) { Disc *dp; dp = &hard[ d.unit + 2*d.ctrl ]; return (dp->cap)/RBUFSIZE; } /* * ideread * read device d logical block b to addr c. */ int ideread( Device d, long b, void *c ) { Disc *dp; Controller *cp; Partition *pp; ulong off, len; int i; dp = &hard[ d.unit + 2*d.ctrl ]; cp = dp->cp; qlock( cp ); /* lock controller level */ hardwait( cp ); /* make sure we're done */ /* * compute disk address and length of read in physical units */ off = b * RBUFSIZE; len = RBUFSIZE; /* * set to operate on the entire disk, ignoring partitions. */ sethardpart( d.unit + 2*d.ctrl, "disk" ); pp = dp->current; dp->work.count++; dp->rate.count += len; cp->buf = c; i = hardxfer( dp, pp, Cread, off, len ); qunlock( cp ); if( i <= 0 ) { return -1; } else { return 0; } } /* * idewrite * write logical block b with data c */ int idewrite( Device d, long b, void *c ) { Disc *dp; Controller *cp; Partition *pp; ulong off, len; int i; dp = &hard[ d.unit + 2*d.ctrl ]; cp = dp->cp; qlock( cp ); /* lock controller level */ hardwait( cp ); /* make sure we're done */ /* * compute disk address and length of read in physical units. */ off = b * RBUFSIZE; len = RBUFSIZE; /* * set to operate on entire disk */ sethardpart( d.unit + 2*d.ctrl, "disk" ); pp = dp->current; cp->buf = c; dp->work.count++; dp->rate.count += len; i = hardxfer( dp, pp, Cwrite, off, len ); qunlock( cp ); if( i <= 0 ) return -1; else return 0; } static void cmd_stats( int argc, char *argv[] ) { /* Controller *ctlr; */ stats( &hardc[0] ); } static void stats( Controller *ctlr ) { int drive; Disc *d; print("\n"); for( drive = 0; drive < 4; drive++ ) { d = &hard[ drive ]; if( drive&0x2 == 0 ) print( "ide%d stats\n", drive&0x2 ); if( d->online == 0 ) print( " drive %.2o offline (%d)\n" , d - hard, d->online ); else { print( " drive %.2o = %10ld\n" , d - hard, d->cap/RBUFSIZE ); print( " work = %F\n" , (Filta){&d->work, 1}); print( " rate = %F tBps\n" , (Filta){&d->rate, 1000}); } } } /* * XXX no swab?! */ void swab( char *a, char *b, int k ) { char c; while( k/2 > 0 ) { c = *(b+1); *(a+1) = *b; *a = c; a+=2; b+=2; k-=2; } } . 727c print("hardintr 2 cmd %ux status %ux while IDENTing", cp->cmd, inb(cp->pbase+Pstatus)); . 513a /* save the ident structure */ memmove( &dp->ident, ip, sizeof( Ident ) ); . 507a if( cp->status == 0xff ) { return -1; /* unit doesn't exist */ } else if( cp->status & Serr ) { print("IDENT drive %d failed, error %x\n" , dp->drive, cp->status ); return -1; } . 417a */ . 415c . 406c print("part fault: req %ud max %ud\n", start, pp->end); . 403a cp->addr = (start * dp->bytes)/RBUFSIZE; . 384,385c ulong lsec; ulong loop; . 381c hardxfer(Disc *dp, Partition *pp, int cmd, ulong start, long len) . 368,370c while(((val = inb(cp->pbase+Pstatus)) & (Sready|Sbusy)) != Sready) if(TK2MS(m->ticks - start) > Timeout) { /* * check peculiar value associated * with nonexistent controllers. */ if( val == -1 ) { return -1; } print("readywait failed block %d ctlr %lud port %x 0x%lux\n" , cp-hardc, cp->addr, cp->pbase , inb( cp->pbase + Pstatus ) , val ); . 365c long start; int val; . 236,239c if(TK2SEC(m->ticks - start) >= Timeout){ print("hardwait timed out ctlr %x %ux\n" , cp-hardc, inb(cp->pbase+Pstatus)); hardintr(0, cp); } . 211a continue; } outb( dp->cp->pbase + AltOffset, 0x8 ); /* 4 head bits */ /* * invoke controller diagnostic */ outb( cp->pbase, Cdiagnostic ); delay( 5 * 1000 ); if( cmdreadywait( cp ) < 0 ) { print("failed to go ready after diagnostic\n"); dp->online = 0; continue; } /* snarf error register value before * hardsetbuf wipes it out */ i = inb( cp->pbase + Perror ); if( i&0x1 ) { /* if master passed... */ hardsetbuf( dp, 1 ); if( hardparams(dp) == 0 ) { swab( buf, (char *)&(dp->ident.model), 20 ); print("h%d.%d: [%20s] %d cylinders %d heads %d sectors/track %ud bytes status %x\n" , disks/2, disks&1, buf , dp->cyl, dp->heads, dp->sectors, dp->cap , i ); print("dmaflags %x pioflags %x dwtf %x capabilities %x s2i %x\n" , dp->ident.mwdma , dp->ident.pioflags , dp->ident.dwtf , dp->ident.capabilities , dp->ident.s2i ); dp->online = 1; hardpart(dp); hardsetbuf(dp, 1); dp++; disks++; /* * now poke slave and see if it's really there */ continue; /* XXX avoid slaves */ if( hardparams( dp ) == 0 ) { swab( buf, (char *)&(dp->ident.model), 20 ); print("h%d.%d: [%20s] %d cylinders %d heads %d sectors/track %ud bytes status %x\n" , disks/2, disks&1, buf , dp->cyl, dp->heads, dp->sectors, dp->cap , i ); print("dmaflags %x pioflags %x dwtf %x capabilities %x s2i %x\n" , dp->ident.mwdma , dp->ident.pioflags , dp->ident.dwtf , dp->ident.capabilities , dp->ident.s2i ); dp->online = 1; hardpart( dp ); hardsetbuf( dp, 1 ); continue; } } else { print("h%d.%d not found: Port %x irq %d\n" , disks/2, disks&1 , Configurations[ disks/2 ].port , Configurations[ disks/2 ].irq ); dp->online = 0; } } else { print("hd%d.%d returned failed status %x\n" , disks/2, disks&1, i ); dp->online = 0; } . 201,210c for(dp = hard; dp < &hard[nhard]; dp++, disks++){ cp = dp->cp; /* * check for writability of cylinder low register. */ /* XXX 0xa0 = CHS master unit head 0 */ outb( dp->cp->pbase + Pdh, 0xa0 ); outb( dp->cp->pbase + Pcyllsb, 0xa5 ); if( inb( dp->cp->pbase + Pcyllsb) == 0xff ) { dp->online = 0; /* declare it dead */ continue; } /* * try to reset the unit */ outb( dp->cp->pbase + AltOffset, 0x4 ); /* 0x4 | 02x = SRST | ~IntEnabled */ delay( 5 * 1000 ); /* 5 seconds */ outb( dp->cp->pbase + AltOffset, 0x0 ); /* 0x2 = ~IntEnabled */ /* XXX do this anyway so we won't kill masters w/o slaves */ outb( dp->cp->pbase + AltOffset, 0x8 ); if( cmdreadywait( cp ) < 0 ) { print("declaring it dead\n"); . 197c setvec( Configurations[ drive/2 ].irq, hardintr, cp); . 192d 188a cp->pbase = Configurations[ drive/2 ].port; . 180,181c hard = ialloc(4 * sizeof(Disc), 0); hardc = ialloc(2 * sizeof(Controller), 0); . 177c */ nhard = 4; . 168a /* XXX ignore what nvram says and probe . 164c /* uchar equip; */ char buf[20]; . 162c int drive, i; . 154,155c * second, etc. Discover drive parameters. . 150a static void stats(Controller *); static void cmd_stats(int, char **); static int cmdreadywait(Controller *); static void swab(char *, char *, int); . 144c static long hardxfer(Disc*, Partition*, int, ulong, long); . 139a /* * possible controller configurations * XXX really should do this through PCI * XXX where available. */ struct CtlrCfg { int port; /* i/o port base */ int irq; /* interrupt vector */ }; static CtlrCfg Configurations[] = { { 0x1f0, Hardvec } ,{ 0x170, Int0vec+15 } ,{ 0,0 } }; . 137a ulong addr; /* logical address being accessed */ . 120a QLock; . 113a Filter work; Filter rate; . 99a Ident ident; /* Ident structure */ . 72,85c ushort dwtf; /* [48] double word transfer flag */ ushort capabilities; /* [49] capability flags */ ushort reserved2; /* [50] */ ushort piocyclemode; /* [51] PIO data transfer cycle tyming mode */ ushort reserved3; /* [52] */ ushort extensionflags; /* [53] flags defining whether */ /* words 64-70 and 54-58 are valid */ ushort logcyls; /* current # of logical cyls */ ushort logheads; /* current # of logical heads */ ushort logsecs; /* current # of logical sectors */ ushort capacity[2]; /* [57:58] current capacity in sectors */ ushort mrflags; /* [59] multiple-read flags and current mode */ ushort lbacapacity[2]; /* [60:61] total sectors in LBA mode */ ushort reserved4; /* obsolete */ ushort mwdma; /* [63] multiword DMA flags and mode */ ushort pioflags; /* [64] PIO transfer modes supported */ ushort mwcycle; /* [65] minimum multiword cycle time/word in nSec */ ushort mfgrmw; /* [66] mfgr recommended MW dma transfer cycle */ ushort piocycle; /* [67] minimumm PIO transfer cycle time */ ushort pioiordy; /* [68] PIO transfer cycle time with IORDY flag */ ushort expansion[11]; . 47a AltOffset= 0x206, /* offset to alt status port */ . 39a Cdiagnostic= 0x90, . 28a Seekcomp= (1<<4), . 7a typedef struct CtlrCfg CtlrCfg; . wq //GO.SYSIN DD VADIM hard.c sum=`{sum < 918342595/hard.c} if(~ eb570f4b22301 $sum(1)^$sum(2)) echo if not{ echo 918342595/hard.c checksum error creating updated file exit checksum } target=918342595/l.s echo -n '918342595/l.s: ' if(! test -f $srcdir/l.s || ! test -r $srcdir/l.s){ echo $srcdir/l.s unreadable exit unreadable } sum=`{sum < $srcdir/l.s} if(! ~ 18f1beb39742 $sum(1)^$sum(2)){ echo $srcdir/l.s is not the original distribution file exit original } cp $srcdir/l.s 918342595/l.s ed 918342595/l.s >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM l.s' 671a RET TEXT famd+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FADDF a+0(FP), F0 FMOVL c+8(FP), F0 FMULDP F0, F1 FMOVL d+12(FP), F0 FDIVDP F0, F1 FMOVFP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ RET TEXT fdf+0(SB), $4 PUSHFL CLI /* spl hi */ FMOVL b+4(FP), F0 FDIVRF a+0(FP), F0 FMOVLP F0, .safe-4(SP) MOVL .safe-4(SP), AX POPFL /* splx */ . 586a MOVL c+0(FP),CX aaml1: AAM LOOP aaml1 RET . 585a /* * basic timing loop to determine CPU frequency */ TEXT aamloop(SB),$0 . 583a POPL BX . 582c MOVL a+0(FP),CX MOVL AX,0(CX) MOVL d+4(FP),CX MOVL DX,0(CX) . 580c MOVL $(3<<8),AX MOVL $0,DX . 577c MOVL $(4<<8),AX MOVL $0,DX . 574c MOVL $1,AX /* CPUID */ BYTE $0x0F BYTE $0xA2 . 572c ANDL $0x200000,AX /* if we can't change this, there's no CPUID */ . 559c TEXT x86cpuid(SB),$0 . wq //GO.SYSIN DD VADIM l.s sum=`{sum < 918342595/l.s} if(~ 8a18317710398 $sum(1)^$sum(2)) echo if not{ echo 918342595/l.s checksum error creating updated file exit checksum } target=918342595/pc.c echo -n '918342595/pc.c: ' if(! test -f $srcdir/pc.c || ! test -r $srcdir/pc.c){ echo $srcdir/pc.c unreadable exit unreadable } sum=`{sum < $srcdir/pc.c} if(! ~ 1ff381bc6001 $sum(1)^$sum(2)){ echo $srcdir/pc.c is not the original distribution file exit original } cp $srcdir/pc.c 918342595/pc.c ed 918342595/pc.c >/dev/null >[2=1] <<'//GO.SYSIN DD VADIM pc.c' 346a */ . 335a /* in assembly language . wq //GO.SYSIN DD VADIM pc.c sum=`{sum < 918342595/pc.c} if(~ dbeaed426028 $sum(1)^$sum(2)) echo if not{ echo 918342595/pc.c checksum error creating updated file exit checksum }