From 6eb3d5e63dceafa17b050c2d9a5592dfc806d65b Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Tue, 27 Jun 2000 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 2000-06-27 --- pc/cycintr.c | 32 ++++++++++++++------ pc/fns.h | 5 ++-- pc/i8253.c | 82 ++++++++++++++++++++++++++++++++++++++------------- pc/sd53c8xx.c | 32 ++++++++++++++++++-- 4 files changed, 118 insertions(+), 33 deletions(-) diff --git a/pc/cycintr.c b/pc/cycintr.c index 93a6ecedfac798147e0191fdd71149cbb229865d..4959218b0f305b083e7db78260c66cc6495e8ac7 100644 --- a/pc/cycintr.c +++ b/pc/cycintr.c @@ -9,31 +9,47 @@ static struct { Lock; - vlong when; /* next scheduled interrupt time */ Cycintr *ci; }cycintrs; -static void -cycsched(void) +/* + * called by clockintrsched() + */ +vlong +cycintrnext(void) { + Cycintr *ci; + vlong when; + + ilock(&cycintrs); + when = 0; + ci = cycintrs.ci; + if(ci != nil) + when = ci->when; + iunlock(&cycintrs); + return when; } -void +vlong checkcycintr(Ureg *u, void*) { Cycintr *ci; + vlong when; ilock(&cycintrs); while(ci = cycintrs.ci){ - if(ci->when > fastticks(nil)) - break; + when = ci->when; + if(when > fastticks(nil)){ + iunlock(&cycintrs); + return when; + } cycintrs.ci = ci->next; iunlock(&cycintrs); (*ci->f)(u, ci); ilock(&cycintrs); } - cycsched(); iunlock(&cycintrs); + return 0; } void @@ -59,8 +75,6 @@ cycintradd(Cycintr *nci) } nci->next = *last; *last = nci; - if(nci->when < cycintrs.when) - cycsched(); iunlock(&cycintrs); } diff --git a/pc/fns.h b/pc/fns.h index 6044e71ecca52c1116b338e1dd374fbc367a1316..3036badddcafd5f1dac9e389a9f811a83aa005b5 100644 --- a/pc/fns.h +++ b/pc/fns.h @@ -1,9 +1,10 @@ #include "../port/portfns.h" -void checkcycintr(Ureg*, void*); +vlong checkcycintr(Ureg*, void*); void cycintradd(Cycintr*); void cycintrdel(Cycintr*); - +void clockintrsched(void); +vlong cycintrnext(void); void aamloop(int); void addconf(char*, char*); diff --git a/pc/i8253.c b/pc/i8253.c index 8b43c0c687ea111050637027a189cc5c3f0d185d..3e7f69db7838851fee34dc2abec23266a3a68593 100644 --- a/pc/i8253.c +++ b/pc/i8253.c @@ -52,8 +52,10 @@ enum static struct { - Lock lock; + Lock; + int mode; vlong when; /* next fastticks a clock interrupt should occur */ + vlong cycwhen; /* next fastticks a cycintr happens; 0 == infinity */ long fastperiod; /* fastticks/hz */ long fast2freq; /* fastticks*FreqMul/Freq */ }i8253; @@ -74,6 +76,7 @@ i8253init(int aalcycles, int havecycleclock) * set clock for 1/HZ seconds */ outb(Tmode, Load0|Square); + i8253.mode = Square; outb(T0cntr, (Freq/HZ)); /* low byte */ outb(T0cntr, (Freq/HZ)>>8); /* high byte */ @@ -158,31 +161,70 @@ i8253init(int aalcycles, int havecycleclock) } } -#ifdef SETNEXT -set up clock so it is reloaded every interrupt - outb(Tmode, Load0|Trigger); - outb(T0cntr, (Freq/HZ)); /* low byte */ - outb(T0cntr, (Freq/HZ)>>8); /* high byte */ -#endif - +/* + * schedule the next interrupt + * cycwhen is the next time for the cycle counter routines + */ static void -clockintr0(Ureg* ureg, void *v) +clockintrsched0(vlong next) { -#ifdef SETNEXT vlong now; long set; + i8253.cycwhen = next; + if(i8253.mode == Square && next == 0) + return; + now = fastticks(nil); - while(i8253.when < now) - i8253.when += i8253.fastperiod; - set = (long)(i8253.when - now) * FreqMul / i8253.fast2freq; - set -= 3; /* three cycles for the count to take effect: outb, outb, wait */ - outb(T0cntr, set); /* low byte */ - outb(T0cntr, set>>8); /* high byte */ -#endif - - checkcycintr(ureg, v); - clockintr(ureg, v); + if(next || now < i8253.when - i8253.fastperiod || now > i8253.when - ((3*i8253.fastperiod)>>2)){ + if(next > i8253.when) + next = i8253.when; + set = (long)(next - now) * FreqMul / i8253.fast2freq; + set -= 3; /* three cycles for the count to take effect: outb, outb, wait */ + if(i8253.mode != Trigger){ + outb(Tmode, Load0|Trigger); + i8253.mode = Trigger; + set--; + } + if(set < 3) + set = 5; + outb(T0cntr, set); /* low byte */ + outb(T0cntr, set>>8); /* high byte */ + }else if(i8253.mode != Square){ + i8253.mode = Square; + outb(Tmode, Load0|Square); + outb(T0cntr, (Freq/HZ)); /* low byte */ + outb(T0cntr, (Freq/HZ)>>8); /* high byte */ + } +} + +void +clockintrsched(void) +{ + vlong next; + + ilock(&i8253); + next = cycintrnext(); + if(next != i8253.cycwhen) + clockintrsched0(next); + iunlock(&i8253); +} + +static void +clockintr0(Ureg* ureg, void *v) +{ + vlong now, when; + + now = fastticks(nil); + when = i8253.when; + if(now >= i8253.when){ + clockintr(ureg, v); + do + i8253.when += i8253.fastperiod; + while(i8253.when < now); + } + if(i8253.cycwhen || i8253.mode != Square) + clockintrsched0(checkcycintr(ureg, v)); } void diff --git a/pc/sd53c8xx.c b/pc/sd53c8xx.c index 740abd5838e0f5b981c587e52acf199364db3d48..ecb8660b22e4d00f50418c5e2e2aa269243bd4eb 100644 --- a/pc/sd53c8xx.c +++ b/pc/sd53c8xx.c @@ -315,6 +315,10 @@ static unsigned char cf2[] = { 6, 2, 3, 4, 6, 8, 12, 16 }; typedef struct Controller { Lock; + struct { + uchar scntl3; + uchar stest2; + } bios; uchar synctab[NULTRA2SCF - 1][8];/* table of legal tpfs */ NegoState s[MAXTARGET]; uchar scntl3[MAXTARGET]; @@ -359,6 +363,7 @@ enum { DataOut, DataIn, Cmd, Status, ReservedOut, ReservedIn, MessageOut, Messag static void setmovedata(Movedata*, ulong, ulong); static void advancedata(Movedata*, long); +static int bios_set_differential(Controller *c); static char *phase[] = { "data out", "data in", "command", "status", @@ -838,8 +843,8 @@ softreset(Controller *c) n->dmode |= (1 << 1); /* burst opcode fetch */ if (c->v->feature & Differential) { /* chip capable */ - if ((c->feature & Differential) || (n->gpreg & 0x8) == 0) { - /* user enabled, or bit 3 of GPREG clear (Symbios cards) */ + if ((c->feature & Differential) || bios_set_differential(c)) { + /* user enabled, or some evidence bios set differential */ if (n->sstat2 & (1 << 2)) print("sd53c8xx: can't go differential; wrong cable\n"); else { @@ -1797,6 +1802,25 @@ docheck: return r->status = status; } +static void +cribbios(Controller *c) +{ + c->bios.scntl3 = c->n->scntl3; + c->bios.stest2 = c->n->stest2; + print("sd53c8xx: bios scntl3(%.2x) stest2(%.2x)\n", c->bios.scntl3, c->bios.stest2); +} + +static int +bios_set_differential(Controller *c) +{ + /* Concept lifted from FreeBSD - thanks Gerard */ + /* basically, if clock conversion factors are set, then there is + * evidence the bios had a go at the chip, and if so, it would + * have set the differential enable bit in stest2 + */ + return (c->bios.scntl3 & 7) != 0 && (c->bios.stest2 & 0x20) != 0; +} + #define NCR_VID 0x1000 #define NCR_810_DID 0x0001 #define NCR_820_DID 0x0002 /* don't know enough about this one to support it */ @@ -1808,6 +1832,7 @@ docheck: #define SYM_895_DID 0x000c #define SYM_885_DID 0x000d /* ditto */ #define SYM_875_DID 0x000f /* ditto */ +#define SYM_1010_DID 0x0020 #define SYM_875J_DID 0x008f static Variant variant[] = { @@ -1826,6 +1851,7 @@ static Variant variant[] = { { SYM_885_DID, 0xff, "SYM53C885", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|ClockDouble }, { SYM_895_DID, 0xff, "SYM53C895", Burst128, 16, 24, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, { SYM_896_DID, 0xff, "SYM53C896", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, +{ SYM_896_DID, 0xff, "SYM53C1010", Burst128, 16, 64, Prefetch|LocalRAM|BigFifo|Wide|Ultra|Ultra2 }, }; #define offsetof(s, t) ((ulong)&((s *)0)->t) @@ -2046,6 +2072,7 @@ symenable(SDev* sdev) ilock(ctlr); synctabinit(ctlr); + cribbios(ctlr); reset(ctlr); iunlock(ctlr); @@ -2070,3 +2097,4 @@ SDifc sd53c8xxifc = { scsibio, /* bio */ }; +