%!PS-Adobe-2.0 %%Version: 3.3.2 %%DocumentFonts: (atend) %%Pages: (atend) %%EndComments % % Version 3.3.2 prologue for text files. % /#copies 1 store /aspectratio 1 def /font /Courier def /formsperpage 1 def /landscape false def /magnification 1 def /margin 10 def /orientation 0 def /pointsize 10 def /rotation 1 def /xoffset .25 def /yoffset .25 def /roundpage true def /useclippath true def /pagebbox [0 0 612 792] def /inch {72 mul} bind def /min {2 copy gt {exch} if pop} bind def /show {show} bind def % so later references don't bind /stringwidth {stringwidth} bind def /setup { counttomark 2 idiv {def} repeat pop landscape {/orientation 90 orientation add def} if font findfont pointsize scalefont setfont /charwidth (M) stringwidth pop def /linespace pointsize pointsize .10 mul add neg def pagedimensions xcenter ycenter translate orientation rotation mul rotate width 2 div neg height 2 div translate xoffset inch yoffset inch neg translate margin 2 div dup neg translate magnification dup aspectratio mul scale height width div 1 min dup scale 0 linespace translate } def /pagedimensions { useclippath userdict /gotpagebbox known not and { /pagebbox [clippath pathbbox newpath] def roundpage currentdict /roundpagebbox known and {roundpagebbox} if } if pagebbox aload pop 4 -1 roll exch 4 1 roll 4 copy landscape {4 2 roll} if sub /width exch def sub /height exch def add 2 div /xcenter exch def add 2 div /ycenter exch def userdict /gotpagebbox true put } def /pagesetup {/page exch def 0 0 moveto 0} bind def /L { counttomark 2 idiv {charwidth mul currentpoint exch pop moveto show} repeat linespace add dup 0 exch moveto } bind def /l {show linespace add dup 0 exch moveto} bind def /LL { counttomark 2 idiv {charwidth mul currentpoint exch pop moveto show} repeat } bind def /done {/lastpage where {pop lastpage} if} def % % Tries to round clipping path dimensions, as stored in array pagebbox, so they % match one of the known sizes in the papersizes array. Lower left coordinates % are always set to 0. % /roundpagebbox { 7 dict begin /papersizes [8.5 inch 11 inch 14 inch 17 inch] def /mappapersize { /val exch def /slop .5 inch def /diff slop def /j 0 def 0 1 papersizes length 1 sub { /i exch def papersizes i get val sub abs dup diff le {/diff exch def /j i def} {pop} ifelse } for diff slop lt {papersizes j get} {val} ifelse } def pagebbox 0 0 put pagebbox 1 0 put pagebbox dup 2 get mappapersize 2 exch put pagebbox dup 3 get mappapersize 3 exch put end } bind def %%EndProlog %%BeginSetup mark /pointsize 9 def /landscape true def % % Encoding vector, operator and procedure redefinitions for Plan 9 UTF % encoding. Prologues are expected to take steps to ensure operator % redefinitions given here are actually used. Current implementation % assumes UTF byte streams that represent ASCII or Latin1 text. % /UTFLatin1Encoding [ /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /space /exclam /quotedbl /numbersign /dollar /percent /ampersand /quoteright /parenleft /parenright /asterisk /plus /comma /minus /period /slash /zero /one /two /three /four /five /six /seven /eight /nine /colon /semicolon /less /equal /greater /question /at /A /B /C /D /E /F /G /H /I /J /K /L /M /N /O /P /Q /R /S /T /U /V /W /X /Y /Z /bracketleft /backslash /bracketright /asciicircum /underscore /quoteleft /a /b /c /d /e /f /g /h /i /j /k /l /m /n /o /p /q /r /s /t /u /v /w /x /y /z /braceleft /bar /braceright /asciitilde /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /.notdef /dotlessi /grave /acute /circumflex /tilde /macron /breve /dotaccent /dieresis /.notdef /ring /cedilla /.notdef /hungarumlaut /ogonek /caron /space /exclamdown /cent /sterling /currency /yen /brokenbar /section /dieresis /copyright /ordfeminine /guillemotleft /logicalnot /hyphen /registered /macron /degree /plusminus /twosuperior /threesuperior /acute /mu /paragraph /periodcentered /cedilla /onesuperior /ordmasculine /guillemotright /onequarter /onehalf /threequarters /questiondown /Agrave /Aacute /Acircumflex /Atilde /Adieresis /Aring /AE /Ccedilla /Egrave /Eacute /Ecircumflex /Edieresis /Igrave /Iacute /Icircumflex /Idieresis /Eth /Ntilde /Ograve /Oacute /Ocircumflex /Otilde /Odieresis /multiply /Oslash /Ugrave /Uacute /Ucircumflex /Udieresis /Yacute /Thorn /germandbls /agrave /aacute /acircumflex /atilde /adieresis /aring /ae /ccedilla /egrave /eacute /ecircumflex /edieresis /igrave /iacute /icircumflex /idieresis /eth /ntilde /ograve /oacute /ocircumflex /otilde /odieresis /divide /oslash /ugrave /uacute /ucircumflex /udieresis /yacute /thorn /ydieresis ] def /NewFontDirectory FontDirectory maxlength dict def % % Apparently no guarantee findfont is defined in systemdict so the obvious % % systemdict /findfont get exec % % can generate an error. So far the only exception is a VT600 (version 48.0). % userdict /@RealFindfont known not { userdict begin /@RealFindfont systemdict begin /findfont load end def end } if /findfont { dup NewFontDirectory exch known not { dup %dup systemdict /findfont get exec % not always in systemdict dup userdict /@RealFindfont get exec dup /Encoding get StandardEncoding eq { dup length 1 add dict begin {1 index /FID ne {def}{pop pop} ifelse} forall /Encoding UTFLatin1Encoding def /Metrics 1 dict def Metrics /.notdef 0 put currentdict end /DummyFontName exch definefont } if NewFontDirectory 3 1 roll put } if NewFontDirectory exch get } bind def % % UTF string decoding for ASCII and Latin1 only: % % C2 XX => 00 XX % C3 XX => XX+40 00 % % Two passes through each string with search is undoubtedly faster than % PostScript that examines each byte. % /UTFstring { dup { (\302) search { pop 0 0 put }{pop exit} ifelse } loop dup { (\303) search { pop 1 index 0 get 16#40 add 0 exch put dup length 0 gt {dup 0 0 put} if }{pop exit} ifelse } loop } bind def /ashow {mark 4 1 roll UTFstring //ashow cvx exec cleartomark} bind def /awidthshow {mark 7 1 roll UTFstring //awidthshow cvx exec cleartomark} bind def /show {mark exch UTFstring //show cvx exec cleartomark} bind def /stringwidth {UTFstring //stringwidth cvx exec} bind def /widthshow {mark 5 1 roll UTFstring //widthshow cvx exec cleartomark} bind def % % kshow is harder - stack can't change because of the procedure. % /kshow dup load type /operatortype eq {{UTFstring kshow} bind} {{UTFstring //kshow cvx exec} bind} ifelse def setup %%EndSetup %%Page: 1 1 /saveobj save def mark 1 pagesetup ()l ()l (Oct 3 19:26 2005 sys/include/a.out.h Page 1)l ()l ()l (1 typedef struct Exec Exec;)l (2 struct Exec)l (3 {)l (4)0(long magic;)8(/* magic number */)32 L (5)0(long text;)8(/* size of text segment */)32 L (6)0(long data;)8(/* size of initialized data */)32 L (7)0(long bss;)8(/* size of uninitialized data */)32 L (8)0(long syms;)8(/* size of symbol table */)32 L (9)0(long entry;)8(/* entry point */)32 L (10)0(long spsz;)8(/* size of pc/sp offset table */)32 L (11)0(long pcsz;)8(/* size of pc/line number table */)32 L (12 };)l (13)l (14 #define _MAGIC\(b\))0(\(\(\(\(4*b\)+0\)*b\)+7\))32 L (15 #define A_MAGIC)0(_MAGIC\(8\))32(/* 68020 */)48 L (16 #define I_MAGIC)0(_MAGIC\(11\))32(/* intel 386 */)48 L (17 #define J_MAGIC)0(_MAGIC\(12\))32(/* intel 960 */)48 L (18 #define K_MAGIC)0(_MAGIC\(13\))32(/* sparc */)48 L (19 #define V_MAGIC)0(_MAGIC\(16\))32(/* mips 3000 */)48 L (20 #define X_MAGIC)0(_MAGIC\(17\))32(/* att dsp 3210 */)48 L (21 #define M_MAGIC)0(_MAGIC\(18\))32(/* mips 4000 */)48 L (22 #define D_MAGIC)0(_MAGIC\(19\))32(/* amd 29000 */)48 L (23 #define E_MAGIC)0(_MAGIC\(20\))32(/* arm 7-something */)48 L (24 #define Q_MAGIC)0(_MAGIC\(21\))32(/* powerpc */)48 L (25 #define N_MAGIC)0(_MAGIC\(22\))32(/* mips 4000 LE */)48 L (26 #define L_MAGIC)0(_MAGIC\(23\))32(/* dec alpha */)48 L (27)l (28 typedef struct Sym Sym;)l (29 struct Sym)l (30 {)l (31)0(long value;)8 L (32)0(char type;)8 L (33)0(char *name;)8 L (34 };)l cleartomark showpage saveobj restore %%EndPage: 1 1 %%Page: 2 2 /saveobj save def mark 2 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/dat.h Page 1)l ()l ()l (1 typedef struct Conf)0(Conf;)32(69)100(ulong nmach;)108(/* processors */)132 L (2 typedef struct FPsave FPsave;)0(70)100(ulong nproc;)108(/* processes */)132 L (3 typedef struct ISAConf ISAConf;)0(71)100(ulong monitor;)108(/* has monitor? */)132 L (4 typedef struct Label)0(Label;)32(72)100(ulong npage0;)108(/* total physical pages of memory */)132 L (5 typedef struct Lock)0(Lock;)32(73)100(ulong npage1;)108(/* total physical pages of memory */)132 L (6 typedef struct MMU)0(MMU;)32(74)100(ulong npage;)108(/* total physical pages of memory */)132 L (7 typedef struct Mach)0(Mach;)32(75)100(ulong upages;)108(/* user page pool */)132 L (8 typedef struct Notsave Notsave;)0(76)100(ulong nimage;)108(/* number of page cache image headers */)132 L (9 typedef struct PCArch PCArch;)0(77)100(ulong nswap;)108(/* number of swap pages */)132 L (10 typedef struct Pcidev Pcidev;)0(78)100(int nswppo;)108(/* max # of pageouts per segment pass */)132 L (11 typedef struct PCMmap PCMmap;)0(79)100(ulong base0;)108(/* base of bank 0 */)132 L (12 typedef struct Page)0(Page;)32(80)100(ulong base1;)108(/* base of bank 1 */)132 L (13 typedef struct PMMU)0(PMMU;)32(81)100(ulong copymode;)108(/* 0 is copy on write, 1 is copy on reference */)132 L (14 typedef struct Proc)0(Proc;)32(82)100(ulong ialloc;)108(/* max interrupt time allocation in bytes */)132 L (15 typedef struct Segdesc Segdesc;)0(83)100(ulong pipeqsize;)108(/* size in bytes of pipe queues */)132 L (16 typedef struct Ureg)0(Ureg;)32(84 };)100 L (17 typedef struct Vctl)0(Vctl;)32(85)100 L (18)0(86 /*)100 L (19 /*)0(87 * MMU stuff in proc)100 L (20 * parameters for sysproc.c)0(88 */)100 L (21 */)0(89 #define NCOLOR 1)100 L (22 #define AOUT_MAGIC)0(\(I_MAGIC\))32(90 struct PMMU)100 L (23)0(91 {)100 L (24 struct Lock)0(92)100(Page* mmupdb;)108(/* page directory base */)140 L (25 {)0(93)100(Page* mmufree;)108(/* unused page table pages */)140 L (26)0(ulong key;)8(94)100(Page* mmuused;)108(/* used page table pages */)140 L (27)0(ulong sr;)8(95 };)100 L (28)0(ulong pc;)8(96)100 L (29)0(Proc *p;)8(97 /*)100 L (30)0(ushort isilock;)8(98 * things saved in the Proc structure during a notify)100 L (31 };)0(99 */)100 L (32)0(100 struct Notsave)100 L (33 struct Label)0(101 {)100 L (34 {)0(102 ulong svflags;)100 L (35)0(ulong sp;)8(103 ulong svcs;)100 L (36)0(ulong pc;)8(104 ulong svss;)100 L (37 };)0(105 };)100 L (38)0(106)100 L (39)0(107 #include "../port/portdat.h")100 L (40 /*)0(108)100 L (41 * FPsave.status)0(109 typedef struct {)100 L (42 */)0(110 ulong link;)100(/* link \(old TSS selector\) */)140 L (43 enum)0(111 ulong esp0;)100(/* privilege level 0 stack pointer */)140 L (44 {)0(112 ulong ss0;)100(/* privilege level 0 stack selector */)140 L (45)0(FPinit,)8(113 ulong esp1;)100(/* privilege level 1 stack pointer */)140 L (46)0(FPactive,)8(114 ulong ss1;)100(/* privilege level 1 stack selector */)140 L (47)0(FPinactive,)8(115 ulong esp2;)100(/* privilege level 2 stack pointer */)140 L (48 };)0(116 ulong ss2;)100(/* privilege level 2 stack selector */)140 L (49)0(117 ulong cr3;)100(/* page directory base register */)140 L (50 struct FPsave)0(118 ulong eip;)100(/* instruction pointer */)140 L (51 {)0(119 ulong eflags;)100(/* flags register */)140 L (52)0(ushort control;)8(120 ulong eax;)100(/* general registers */)140 L (53)0(ushort r1;)8(121 ulong ecx;)100 L (54)0(ushort status;)8(122 ulong edx;)100 L (55)0(ushort r2;)8(123 ulong ebx;)100 L (56)0(ushort tag;)8(124 ulong esp;)100 L (57)0(ushort r3;)8(125 ulong ebp;)100 L (58)0(ulong pc;)8(126 ulong esi;)100 L (59)0(ushort selector;)8(127 ulong edi;)100 L (60)0(ushort r4;)8(128 ulong es;)100(/* segment selectors */)140 L (61)0(ulong operand;)8(129 ulong cs;)100 L (62)0(ushort oselector;)8(130 ulong ss;)100 L (63)0(ushort r5;)8(131 ulong ds;)100 L (64)0(uchar regs[80];)8(/* floating point registers */)32(132 ulong fs;)100 L (65 };)0(133 ulong gs;)100 L (66)0(134 ulong ldt;)100(/* selector for task's LDT */)140 L (67 struct Conf)0(135 ulong iomap;)100(/* I/O map base address + T-bit */)140 L (68 {)0(136 } Tss;)100 L cleartomark showpage saveobj restore %%EndPage: 2 2 %%Page: 3 3 /saveobj save def mark 3 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/dat.h Page 2)l ()l ()l (137)0(205 struct)100 L (138 struct Segdesc)0(206 {)100 L (139 {)0(207 Lock;)100 L (140 ulong d0;)0(208 int machs;)100(/* bitmap of active CPUs */)140 L (141 ulong d1;)0(209 int exiting;)100(/* shutdown */)140 L (142 };)0(210 int ispanic;)100(/* shutdown in response to a panic */)140 L (143)0(211 }active;)100 L (144 struct Mach)0(212)100 L (145 {)0(213 /*)100 L (146 int machno;)0(/* physical id of processor */)40(214 * routines for things outside the PC model, like power management)100 L (147 ulong splpc;)0(/* pc of last caller to splhi */)40(215 */)100 L (148)0(216 struct PCArch)100 L (149 ulong* pdb;)0(/* page directory base for this processor \(va\) */)40(217 {)100 L (150 Tss* tss;)0(/* tss for this processor */)40(218 char* id;)100 L (151 Segdesc gdt[6];)0(/* gdt for this processor */)40(219 int \(*ident\)\(void\);)100(/* this should be in the model */)140 L (152)0(220 void \(*reset\)\(void\);)100(/* this should be in the model */)140 L (153 Proc* proc;)0(/* current process on this processor */)40(221 int \(*serialpower\)\(int\); /* 1 == on, 0 == off */)100 L (154 Proc* externup;)0(/* extern register Proc *up */)40(222 int \(*modempower\)\(int\); /* 1 == on, 0 == off */)100 L (155)0(223)100 L (156 Page* pdbpool;)0(224 void \(*intrinit\)\(void\);)100 L (157 int pdbcnt;)0(225 int \(*intrenable\)\(Vctl*\);)100 L (158)0(226)100 L (159 ulong ticks;)0(/* of the clock since boot time */)40(227 void \(*clockenable\)\(void\);)100 L (160 Label sched;)0(/* scheduler wakeup */)40(228 uvlong \(*fastclock\)\(uvlong*\);)100 L (161 Lock alarmlock;)0(/* access to alarm list */)40(229 };)100 L (162 void* alarm;)0(/* alarms bound to this clock */)40(230)100 L (163)0(231 /*)100 L (164 ulong fairness;)0(/* for runproc */)40(232 * a parsed plan9.ini line)100 L (165)0(233 */)100 L (166 int tlbfault;)0(234 #define ISAOPTLEN 16)100 L (167 int tlbpurge;)0(235 #define NISAOPT)100(8)132 L (168 int pfault;)0(236)100 L (169 int cs;)0(237 struct ISAConf {)100 L (170 int syscall;)0(238 char type[NAMELEN];)100 L (171 int load;)0(239 ulong port;)100 L (172 int intr;)0(240 ulong irq;)100 L (173 vlong fastclock;)0(/* last sampled value */)40(241 ulong dma;)100 L (174 vlong intrts;)0(/* time stamp of last interrupt */)40(242 ulong mem;)100 L (175 int flushmmu;)0(/* make current proc flush it's mmu state */)40(243 ulong size;)100 L (176)0(244 ulong freq;)100 L (177 ulong spuriousintr;)0(245)100 L (178 int lastintr;)0(246 int nopt;)100 L (179)0(247 char opt[NISAOPT][ISAOPTLEN];)100 L (180 int loopconst;)0(248 };)100 L (181)0(249)100 L (182 int cpumhz;)0(250 extern PCArch *arch;)100(/* PC architecture */)148 L (183 int cpuhz;)0(251)100 L (184 int cpuidax;)0(252 /*)100 L (185 int cpuiddx;)0(253 * Each processor sees its own Mach structure at address MACHADDR.)100 L (186 char cpuidid[16];)0(254 * However, the Mach structures must also be available via the per-processor)100 L (187 char* cpuidtype;)0(255 * MMU information array machp, mainly for disambiguation and access to)100 L (188)0(256 * the clock which is only maintained by the bootstrap processor \(0\).)100 L (189 vlong mtrrcap;)0(257 */)100 L (190 vlong mtrrdef;)0(258 Mach* machp[MAXMACH];)100 L (191 vlong mtrrfix[11];)0(259)100 L (192 vlong mtrrvar[32];)0(/* 256 max. */)40(260 #define MACHP\(n\))100(\(machp[n]\))132 L (193)0(261)100 L (194 int stack[1];)0(262 extern Mach)100(*m;)124 L (195 };)0(263 #define up)100(\(\(\(Mach*\)MACHADDR\)->externup\))124 L (196)l (197 /*)l (198 * Fake kmap)l (199 */)l (200 typedef void)0(KMap;)32 L (201 #define VA\(k\))0(\(\(ulong\)\(k\)\))32 L (202 #define kmap\(p\))0(\(KMap*\)\(\(p\)->pa|KZERO\))32 L (203 #define kunmap\(k\))l (204)l cleartomark showpage saveobj restore %%EndPage: 3 3 %%Page: 4 4 /saveobj save def mark 4 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dat.h Page 1)l ()l ()l (1 typedef struct List {)0(69)100 L (2)0(void *next;)8(70 typedef struct Exec Exec;)100 L (3 } List;)0(71 struct Exec)100 L (4)0(72 {)100 L (5 typedef struct Alarm {)0(73)100(uchar magic[4];)108(/* magic number */)140 L (6)0(List;)8(74)100(uchar text[4];)108(/* size of text segment */)140 L (7)0(int busy;)8(75)100(uchar data[4];)108(/* size of initialized data */)140 L (8)0(long dt;)8(76)100(uchar bss[4];)108(/* size of uninitialized data */)140 L (9)0(void \(*f\)\(void*\);)8(77)100(uchar syms[4];)108(/* size of symbol table */)140 L (10)0(void *arg;)8(78)100(uchar entry[4];)108(/* entry point */)140 L (11 } Alarm;)0(79)100(uchar spsz[4];)108(/* size of sp/pc offset table */)140 L (12)0(80)100(uchar pcsz[4];)108(/* size of pc/line number table */)140 L (13 typedef struct Block Block;)0(81 };)100 L (14 struct Block {)0(82)100 L (15)0(Block* next;)8(83 /*)100 L (16)0(uchar* rp;)8(/* first unconsumed byte */)40(84 * a parsed .ini line)100 L (17)0(uchar* wp;)8(/* first empty byte */)40(85 */)100 L (18)0(uchar* lim;)8(/* 1 past the end of the buffer */)40(86 #define ISAOPTLEN 16)100 L (19)0(uchar* base;)8(/* start of the buffer */)40(87 #define NISAOPT)100(8)132 L (20)0(ulong flag;)8(88)100 L (21 };)0(89 typedef struct ISAConf {)100 L (22 #define BLEN\(s\) \(\(s\)->wp - \(s\)->rp\))0(90)100(char type[NAMELEN];)108 L (23)0(91)100(ulong port;)108 L (24 typedef struct IOQ IOQ;)0(92)100(ulong irq;)108 L (25 typedef struct IOQ {)0(93)100(ulong mem;)108 L (26)0(uchar buf[4096];)8(94)100(ulong size;)108 L (27)0(uchar *in;)8(95)100(uchar ea[6];)108 L (28)0(uchar *out;)8(96)100 L (29)0(int state;)8(97)100(int nopt;)108 L (30)0(int \(*getc\)\(IOQ*\);)8(98)100(char opt[NISAOPT][ISAOPTLEN];)108 L (31)0(int \(*putc\)\(IOQ*, int\);)8(99 } ISAConf;)100 L (32)0(void *ptr;)8(100)100 L (33 };)0(101 typedef struct Pcidev Pcidev;)100 L (34)0(102 typedef struct PCMmap PCMmap;)100 L (35 enum {)0(103)100 L (36)0(Eaddrlen)8(= 6,)24(104 #define BOOTLINE \(\(char*\)CONFADDR\))100 L (37)0(ETHERMINTU)8(= 60,)24(/* minimum transmit size */)40(105)100 L (38)0(ETHERMAXTU)8(= 1514,)24(/* maximum transmit size */)40(106 enum {)100 L (39)0(ETHERHDRSIZE = 14,)8(/* size of an ethernet header */)40(107 MB =)100(\(1024*1024\),)124 L (40)0(108 };)100 L (41)0(MaxEther)8(= 4,)24(109 #define ROUND\(s, sz\))100(\(\(\(s\)+\(\(sz\)-1\)\)&~\(\(sz\)-1\)\))132 L (42 };)0(110)100 L (43)0(111)100 L (44 typedef struct {)0(112 typedef struct Type Type;)100 L (45)0(uchar d[Eaddrlen];)8(113 typedef struct Medium Medium;)100 L (46)0(uchar s[Eaddrlen];)8(114 typedef struct Boot Boot;)100 L (47)0(uchar type[2];)8(115)100 L (48)0(uchar data[1500];)8(116 enum {)100(/* type */)148 L (49)0(uchar crc[4];)8(117 Tnil)100(= 0x00,)124 L (50 } Etherpkt;)0(118)100 L (51)0(119 Tfloppy)100(= 0x01,)124 L (52 extern uchar broadcast[Eaddrlen];)0(120 Tsd)100(= 0x02,)124 L (53)0(121 Tether)100(= 0x03,)124 L (54 typedef struct Ureg Ureg;)0(122)100 L (55)0(123 Tany)100(= -1,)124 L (56 typedef struct Segdesc {)0(124 };)100 L (57)0(ulong d0;)8(125)100 L (58)0(ulong d1;)8(126 enum {)100(/* name and flag */)148 L (59 } Segdesc;)0(127 Fnone)100(= 0x00,)124 L (60)0(128)100 L (61 typedef struct Mach {)0(129 Ndos)100(= 0x00,)124 L (62)0(ulong ticks;)8(/* of the clock since boot time */)40(130 Fdos)100(= \(1<0\))116 L (7)0(75)100(cgascreenputc\(' '\);)124 L (8 enum {)0(76)100(})108 L (9)0(Black,)8(77)100(else if\(c == '\\b'\){)108 L (10)0(Blue,)8(78)100(if\(cgapos >= 2\))116 L (11)0(Green,)8(79)100(cgapos -= 2;)124 L (12)0(Cyan,)8(80)100(cgascreenputc\(' '\);)116 L (13)0(Red,)8(81)100(cgapos -= 2;)116 L (14)0(Magenta,)8(82)100(})108 L (15)0(Brown,)8(83)100(else{)108 L (16)0(Grey,)8(84)100(CGASCREENBASE[cgapos++] = c;)116 L (17)0(85)100(CGASCREENBASE[cgapos++] = Attr;)116 L (18)0(Bright = 0x08,)8(86)100(})108 L (19)0(Blinking = 0x80,)8(87)100(if\(cgapos >= Width*Height\){)108 L (20)0(88)100(memmove\(CGASCREENBASE, &CGASCREENBASE[Width], Width*\(Height-1\)\);)116 L (21)0(Yellow = Bright|Brown,)8(89)100(p = &CGASCREENBASE[Width*\(Height-1\)];)116 L (22)0(White = Bright|Grey,)8(90)100(for\(i=0; i 0\))100 L (55 movecursor\(void\))0(123)100(cgascreenputc\(*s++\);)116 L (56 {)0(124)100 L (57)0(cgaregw\(0x0E, \(cgapos/2>>8\) & 0xFF\);)8(125 unlock\(&cgascreenlock\);)100 L (58)0(cgaregw\(0x0F, cgapos/2 & 0xFF\);)8(126 })100 L (59)0(CGASCREENBASE[cgapos+1] = Attr;)8(127)100 L (60 })0(128 void \(*screenputs\)\(char*, int\) = cgascreenputs;)100 L (61)l (62 static void)l (63 cgascreenputc\(int c\))l (64 {)l (65)0(int i;)8 L (66)0(uchar *p;)8 L (67)l (68)0(if\(c == '\\n'\){)8 L cleartomark showpage saveobj restore %%EndPage: 6 6 %%Page: 7 7 /saveobj save def mark 7 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/clock.c Page 1)l ()l ()l (1 #include "u.h")0(69)100 L (2 #include "../port/lib.h")0(70)100(if\(up == 0 || up->state != Running\))108 L (3 #include "mem.h")0(71)100(return;)116 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(if\(anyready\(\)\))108 L (6 #include "io.h")0(74)100(sched\(\);)116 L (7 #include "ureg.h")0(75)100 L (8)0(76)100(if\(\(ureg->cs & 0xFFFF\) == UESEL\) {)108 L (9 void \(*kproftimer\)\(ulong\);)0(77)100(\(*\(ulong*\)\(USTKTOP-BY2WD\)\) += TK2MS\(1\);)116 L (10)0(78)100(segclock\(ureg->pc\);)116 L (11 typedef struct Clock0link Clock0link;)0(79)100(})108 L (12 typedef struct Clock0link {)0(80 })100 L (13)0(void)8(\(*clock\)\(void\);)24(81)100 L (14)0(Clock0link* link;)8(82 void)100 L (15 } Clock0link;)0(83 delay\(int millisecs\))100 L (16)0(84 {)100 L (17 static Clock0link *clock0link;)0(85)100(millisecs *= m->loopconst;)108 L (18 static Lock clock0lock;)0(86)100(if\(millisecs <= 0\))108 L (19)0(87)100(millisecs = 1;)116 L (20 void)0(88)100(aamloop\(millisecs\);)108 L (21 addclock0link\(void \(*clock\)\(void\)\))0(89 })100 L (22 {)0(90)100 L (23)0(Clock0link *lp;)8(91 void)100 L (24)0(92 microdelay\(int microsecs\))100 L (25)0(if\(\(lp = malloc\(sizeof\(Clock0link\)\)\) == 0\){)8(93 {)100 L (26)0(print\("addclock0link: too many links\\n"\);)16(94)100(microsecs *= m->loopconst;)108 L (27)0(return;)16(95)100(microsecs /= 1000;)108 L (28)0(})8(96)100(if\(microsecs <= 0\))108 L (29)0(ilock\(&clock0lock\);)8(97)100(microsecs = 1;)116 L (30)0(lp->clock = clock;)8(98)100(aamloop\(microsecs\);)108 L (31)0(lp->link = clock0link;)8(99 })100 L (32)0(clock0link = lp;)8(100)100 L (33)0(iunlock\(&clock0lock\);)8(101 ulong)100 L (34 })0(102 TK2MS\(ulong ticks\))100 L (35)0(103 {)100 L (36 void)0(104 uvlong t, hz;)100 L (37 clockintr\(Ureg* ureg, void*\))0(105)100 L (38 {)0(106 t = ticks;)100 L (39)0(Clock0link *lp;)8(107 hz = HZ;)100 L (40)0(108 t *= 1000L;)100 L (41)0(// this needs to be here for synchronizing mp clocks)8(109 t = t/hz;)100 L (42)0(// see mp.c's squidboy\(\))8(110 ticks = t;)100 L (43)0(fastticks\(nil\);)8(111 return ticks;)100 L (44)0(m->ticks++;)8(112 })100 L (45)0(if\(m->proc\))8 L (46)0(m->proc->pc = ureg->pc;)16 L (47)l (48)0(accounttime\(\);)8 L (49)0(if\(kproftimer != nil\))8 L (50)0(kproftimer\(ureg->pc\);)16 L (51)0(if\(\(active.machs & \(1<machno\)\) == 0\))8 L (52)0(return;)16 L (53)0(if\(active.exiting && \(active.machs & \(1<machno\)\)\))8 L (54)0(exit\(0\);)16 L (55)l (56)0(checkalarms\(\);)8 L (57)0(if\(m->machno == 0\){)8 L (58)0(ilock\(&clock0lock\);)16 L (59)0(for\(lp = clock0link; lp; lp = lp->link\))16 L (60)0(lp->clock\(\);)24 L (61)0(iunlock\(&clock0lock\);)16 L (62)0(})8 L (63)l (64)0(if\(m->flushmmu\){)8 L (65)0(if\(up\))16 L (66)0(flushmmu\(\);)24 L (67)0(m->flushmmu = 0;)16 L (68)0(})8 L cleartomark showpage saveobj restore %%EndPage: 7 7 %%Page: 8 8 /saveobj save def mark 8 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/dat.h Page 1)l ()l ()l (1 typedef struct Conf)0(Conf;)32(69)100(ulong nmach;)108(/* processors */)132 L (2 typedef struct FPsave FPsave;)0(70)100(ulong nproc;)108(/* processes */)132 L (3 typedef struct ISAConf ISAConf;)0(71)100(ulong monitor;)108(/* has monitor? */)132 L (4 typedef struct Label)0(Label;)32(72)100(ulong npage0;)108(/* total physical pages of memory */)132 L (5 typedef struct Lock)0(Lock;)32(73)100(ulong npage1;)108(/* total physical pages of memory */)132 L (6 typedef struct MMU)0(MMU;)32(74)100(ulong npage;)108(/* total physical pages of memory */)132 L (7 typedef struct Mach)0(Mach;)32(75)100(ulong upages;)108(/* user page pool */)132 L (8 typedef struct Notsave Notsave;)0(76)100(ulong nimage;)108(/* number of page cache image headers */)132 L (9 typedef struct PCArch PCArch;)0(77)100(ulong nswap;)108(/* number of swap pages */)132 L (10 typedef struct Pcidev Pcidev;)0(78)100(int nswppo;)108(/* max # of pageouts per segment pass */)132 L (11 typedef struct PCMmap PCMmap;)0(79)100(ulong base0;)108(/* base of bank 0 */)132 L (12 typedef struct Page)0(Page;)32(80)100(ulong base1;)108(/* base of bank 1 */)132 L (13 typedef struct PMMU)0(PMMU;)32(81)100(ulong copymode;)108(/* 0 is copy on write, 1 is copy on reference */)132 L (14 typedef struct Proc)0(Proc;)32(82)100(ulong ialloc;)108(/* max interrupt time allocation in bytes */)132 L (15 typedef struct Segdesc Segdesc;)0(83)100(ulong pipeqsize;)108(/* size in bytes of pipe queues */)132 L (16 typedef struct Ureg)0(Ureg;)32(84 };)100 L (17 typedef struct Vctl)0(Vctl;)32(85)100 L (18)0(86 /*)100 L (19 /*)0(87 * MMU stuff in proc)100 L (20 * parameters for sysproc.c)0(88 */)100 L (21 */)0(89 #define NCOLOR 1)100 L (22 #define AOUT_MAGIC)0(\(I_MAGIC\))32(90 struct PMMU)100 L (23)0(91 {)100 L (24 struct Lock)0(92)100(Page* mmupdb;)108(/* page directory base */)140 L (25 {)0(93)100(Page* mmufree;)108(/* unused page table pages */)140 L (26)0(ulong key;)8(94)100(Page* mmuused;)108(/* used page table pages */)140 L (27)0(ulong sr;)8(95 };)100 L (28)0(ulong pc;)8(96)100 L (29)0(Proc *p;)8(97 /*)100 L (30)0(ushort isilock;)8(98 * things saved in the Proc structure during a notify)100 L (31 };)0(99 */)100 L (32)0(100 struct Notsave)100 L (33 struct Label)0(101 {)100 L (34 {)0(102 ulong svflags;)100 L (35)0(ulong sp;)8(103 ulong svcs;)100 L (36)0(ulong pc;)8(104 ulong svss;)100 L (37 };)0(105 };)100 L (38)0(106)100 L (39)0(107 #include "../port/portdat.h")100 L (40 /*)0(108)100 L (41 * FPsave.status)0(109 typedef struct {)100 L (42 */)0(110 ulong link;)100(/* link \(old TSS selector\) */)140 L (43 enum)0(111 ulong esp0;)100(/* privilege level 0 stack pointer */)140 L (44 {)0(112 ulong ss0;)100(/* privilege level 0 stack selector */)140 L (45)0(FPinit,)8(113 ulong esp1;)100(/* privilege level 1 stack pointer */)140 L (46)0(FPactive,)8(114 ulong ss1;)100(/* privilege level 1 stack selector */)140 L (47)0(FPinactive,)8(115 ulong esp2;)100(/* privilege level 2 stack pointer */)140 L (48 };)0(116 ulong ss2;)100(/* privilege level 2 stack selector */)140 L (49)0(117 ulong cr3;)100(/* page directory base register */)140 L (50 struct FPsave)0(118 ulong eip;)100(/* instruction pointer */)140 L (51 {)0(119 ulong eflags;)100(/* flags register */)140 L (52)0(ushort control;)8(120 ulong eax;)100(/* general registers */)140 L (53)0(ushort r1;)8(121 ulong ecx;)100 L (54)0(ushort status;)8(122 ulong edx;)100 L (55)0(ushort r2;)8(123 ulong ebx;)100 L (56)0(ushort tag;)8(124 ulong esp;)100 L (57)0(ushort r3;)8(125 ulong ebp;)100 L (58)0(ulong pc;)8(126 ulong esi;)100 L (59)0(ushort selector;)8(127 ulong edi;)100 L (60)0(ushort r4;)8(128 ulong es;)100(/* segment selectors */)140 L (61)0(ulong operand;)8(129 ulong cs;)100 L (62)0(ushort oselector;)8(130 ulong ss;)100 L (63)0(ushort r5;)8(131 ulong ds;)100 L (64)0(uchar regs[80];)8(/* floating point registers */)32(132 ulong fs;)100 L (65 };)0(133 ulong gs;)100 L (66)0(134 ulong ldt;)100(/* selector for task's LDT */)140 L (67 struct Conf)0(135 ulong iomap;)100(/* I/O map base address + T-bit */)140 L (68 {)0(136 } Tss;)100 L cleartomark showpage saveobj restore %%EndPage: 8 8 %%Page: 9 9 /saveobj save def mark 9 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/dat.h Page 2)l ()l ()l (137)0(205 struct)100 L (138 struct Segdesc)0(206 {)100 L (139 {)0(207 Lock;)100 L (140 ulong d0;)0(208 int machs;)100(/* bitmap of active CPUs */)140 L (141 ulong d1;)0(209 int exiting;)100(/* shutdown */)140 L (142 };)0(210 int ispanic;)100(/* shutdown in response to a panic */)140 L (143)0(211 }active;)100 L (144 struct Mach)0(212)100 L (145 {)0(213 /*)100 L (146 int machno;)0(/* physical id of processor */)40(214 * routines for things outside the PC model, like power management)100 L (147 ulong splpc;)0(/* pc of last caller to splhi */)40(215 */)100 L (148)0(216 struct PCArch)100 L (149 ulong* pdb;)0(/* page directory base for this processor \(va\) */)40(217 {)100 L (150 Tss* tss;)0(/* tss for this processor */)40(218 char* id;)100 L (151 Segdesc gdt[6];)0(/* gdt for this processor */)40(219 int \(*ident\)\(void\);)100(/* this should be in the model */)140 L (152)0(220 void \(*reset\)\(void\);)100(/* this should be in the model */)140 L (153 Proc* proc;)0(/* current process on this processor */)40(221 int \(*serialpower\)\(int\); /* 1 == on, 0 == off */)100 L (154 Proc* externup;)0(/* extern register Proc *up */)40(222 int \(*modempower\)\(int\); /* 1 == on, 0 == off */)100 L (155)0(223)100 L (156 Page* pdbpool;)0(224 void \(*intrinit\)\(void\);)100 L (157 int pdbcnt;)0(225 int \(*intrenable\)\(Vctl*\);)100 L (158)0(226)100 L (159 ulong ticks;)0(/* of the clock since boot time */)40(227 void \(*clockenable\)\(void\);)100 L (160 Label sched;)0(/* scheduler wakeup */)40(228 uvlong \(*fastclock\)\(uvlong*\);)100 L (161 Lock alarmlock;)0(/* access to alarm list */)40(229 };)100 L (162 void* alarm;)0(/* alarms bound to this clock */)40(230)100 L (163)0(231 /*)100 L (164 ulong fairness;)0(/* for runproc */)40(232 * a parsed plan9.ini line)100 L (165)0(233 */)100 L (166 int tlbfault;)0(234 #define ISAOPTLEN 16)100 L (167 int tlbpurge;)0(235 #define NISAOPT)100(8)132 L (168 int pfault;)0(236)100 L (169 int cs;)0(237 struct ISAConf {)100 L (170 int syscall;)0(238 char type[NAMELEN];)100 L (171 int load;)0(239 ulong port;)100 L (172 int intr;)0(240 ulong irq;)100 L (173 vlong fastclock;)0(/* last sampled value */)40(241 ulong dma;)100 L (174 vlong intrts;)0(/* time stamp of last interrupt */)40(242 ulong mem;)100 L (175 int flushmmu;)0(/* make current proc flush it's mmu state */)40(243 ulong size;)100 L (176)0(244 ulong freq;)100 L (177 ulong spuriousintr;)0(245)100 L (178 int lastintr;)0(246 int nopt;)100 L (179)0(247 char opt[NISAOPT][ISAOPTLEN];)100 L (180 int loopconst;)0(248 };)100 L (181)0(249)100 L (182 int cpumhz;)0(250 extern PCArch *arch;)100(/* PC architecture */)148 L (183 int cpuhz;)0(251)100 L (184 int cpuidax;)0(252 /*)100 L (185 int cpuiddx;)0(253 * Each processor sees its own Mach structure at address MACHADDR.)100 L (186 char cpuidid[16];)0(254 * However, the Mach structures must also be available via the per-processor)100 L (187 char* cpuidtype;)0(255 * MMU information array machp, mainly for disambiguation and access to)100 L (188)0(256 * the clock which is only maintained by the bootstrap processor \(0\).)100 L (189 vlong mtrrcap;)0(257 */)100 L (190 vlong mtrrdef;)0(258 Mach* machp[MAXMACH];)100 L (191 vlong mtrrfix[11];)0(259)100 L (192 vlong mtrrvar[32];)0(/* 256 max. */)40(260 #define MACHP\(n\))100(\(machp[n]\))132 L (193)0(261)100 L (194 int stack[1];)0(262 extern Mach)100(*m;)124 L (195 };)0(263 #define up)100(\(\(\(Mach*\)MACHADDR\)->externup\))124 L (196)l (197 /*)l (198 * Fake kmap)l (199 */)l (200 typedef void)0(KMap;)32 L (201 #define VA\(k\))0(\(\(ulong\)\(k\)\))32 L (202 #define kmap\(p\))0(\(KMap*\)\(\(p\)->pa|KZERO\))32 L (203 #define kunmap\(k\))l (204)l cleartomark showpage saveobj restore %%EndPage: 9 9 %%Page: 10 10 /saveobj save def mark 10 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devarch.c Page 1)l ()l ()l (1 #include "u.h")0(69 int)100 L (2 #include "../port/lib.h")0(70 ioalloc\(int port, int size, int align, char *tag\))100 L (3 #include "mem.h")0(71 {)100 L (4 #include "dat.h")0(72)100(IOMap *m, **l;)108 L (5 #include "fns.h")0(73)100(int i;)108 L (6 #include "io.h")0(74)100 L (7 #include "ureg.h")0(75)100(lock\(&iomap\);)108 L (8 #include "../port/error.h")0(76)100(if\(port < 0\){)108 L (9)0(77)100(// find a free port above 0x400 and below 0x1000)116 L (10)0(78)100(port = 0x400;)116 L (11 typedef struct IOMap IOMap;)0(79)100(for\(l = &iomap.m; *l; l = &\(*l\)->next\){)116 L (12 struct IOMap)0(80)100(m = *l;)124 L (13 {)0(81)100(i = m->start - port;)124 L (14)0(IOMap *next;)8(82)100(if\(i > size\))124 L (15)0(char tag[13];)8(83)100(break;)132 L (16)0(ulong start;)8(84)100(if\(align > 0\))124 L (17)0(ulong end;)8(85)100(port = \(\(port+align-1\)/align\)*align;)132 L (18 };)0(86)100(else)124 L (19)0(87)100(port = m->end;)132 L (20 static struct)0(88)100(})116 L (21 {)0(89)100(if\(*l == nil\){)116 L (22)0(Lock;)8(90)100(unlock\(&iomap\);)124 L (23)0(IOMap *m;)8(91)100(return -1;)124 L (24)0(IOMap *free;)8(92)100(})116 L (25)0(IOMap maps[32];)8(// some initial free maps)40(93)100(} else {)108 L (26)0(94)100(// see if the space clashes with previously allocated ports)116 L (27)0(QLock ql;)8(// lock for reading map)40(95)100(for\(l = &iomap.m; *l; l = &\(*l\)->next\){)116 L (28 } iomap;)0(96)100(m = *l;)124 L (29)0(97)100(if\(m->end <= port\))124 L (30 enum {)0(98)100(continue;)132 L (31)0(Qdir,)8(99)100(if\(m->start >= port+size\))124 L (32)0(Qcputype,)8(100)100(break;)132 L (33)0(Qioalloc,)8(101)100(unlock\(&iomap\);)124 L (34)0(Qiob,)8(102)100(return -1;)124 L (35)0(Qiow,)8(103)100(})116 L (36)0(Qiol,)8(104 })100 L (37)0(Qirqalloc,)8(105 m = iomap.free;)100 L (38 };)0(106 if\(m == nil\){)100 L (39)0(107)100(print\("ioalloc: out of maps"\);)116 L (40 static Dirtab ioallocdir[] = {)0(108)100(unlock\(&iomap\);)116 L (41)0("cputype",)8({ Qcputype, 0 },)24(0,)48(0444,)56(109)100(return port;)116 L (42)0("ioalloc",)8({ Qioalloc, 0 },)24(0,)48(0444,)56(110 })100 L (43)0("iob",)8({ Qiob, 0 },)24(0,)48(0660,)56(111 iomap.free = m->next;)100 L (44)0("iow",)8({ Qiow, 0 },)24(0,)48(0660,)56(112 m->next = *l;)100 L (45)0("iol",)8({ Qiol, 0 },)24(0,)48(0660,)56(113 m->start = port;)100 L (46)0("irqalloc", { Qirqalloc, 0},)8(0,)48(0444,)56(114 m->end = port + size;)100 L (47 };)0(115 strncpy\(m->tag, tag, sizeof\(m->tag\)\);)100 L (48)0(116 m->tag[sizeof\(m->tag\)-1] = 0;)100 L (49 void)0(117 *l = m;)100 L (50 ioinit\(void\))0(118)100 L (51 {)0(119 ioallocdir[0].qid.vers++;)100 L (52)0(int i;)8(120)100 L (53)0(121 unlock\(&iomap\);)100 L (54)0(for\(i = 0; i < nelem\(iomap.maps\)-1; i++\))8(122 return m->start;)100 L (55)0(iomap.maps[i].next = &iomap.maps[i+1];)16(123 })100 L (56)0(iomap.maps[i].next = nil;)8(124)100 L (57)0(iomap.free = iomap.maps;)8(125 void)100 L (58)0(126 iofree\(int port\))100 L (59)0(// a dummy entry at 2^16)8(127 {)100 L (60)0(ioalloc\(0x10000, 1, 0, "dummy"\);)8(128 IOMap *m, **l;)100 L (61 })0(129)100 L (62)0(130 lock\(&iomap\);)100 L (63 static long cputyperead\(char*, int, ulong\);)0(131 for\(l = &iomap.m; *l; l = &\(*l\)->next\){)100 L (64)0(132)100(if\(\(*l\)->start == port\){)116 L (65 //)0(133)100(m = *l;)124 L (66 //)0(alloc some io port space and remember who it was)16(134)100(*l = m->next;)124 L (67 //)0(alloced to. if port < 0, find a free region.)16(135)100(m->next = iomap.free;)124 L (68 //)0(136)100(iomap.free = m;)124 L cleartomark showpage saveobj restore %%EndPage: 10 10 %%Page: 11 11 /saveobj save def mark 11 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devarch.c Page 2)l ()l ()l (137)0(break;)24(205 };)100 L (138)0(})16(206)100 L (139)0(if\(\(*l\)->start > port\))16(207 static long)100 L (140)0(break;)24(208 archread\(Chan *c, void *a, long n, vlong offset\))100 L (141 })0(209 {)100 L (142 ioallocdir[0].qid.vers++;)0(210 char *p;)100 L (143 unlock\(&iomap\);)0(211 IOMap *m;)100 L (144 })0(212 char buf[Linelen+1];)100 L (145)0(213 int port;)100 L (146 int)0(214 ushort *sp;)100 L (147 iounused\(int start, int end\))0(215 ulong *lp;)100 L (148 {)0(216)100 L (149 IOMap *m;)0(217 switch\(c->qid.path & ~CHDIR\){)100 L (150)0(218)100 L (151 for\(m = iomap.m; m; m = m->next\){)0(219 case Qdir:)100 L (152)0(if\(start >= m->start && start < m->end)16(220)100(return devdirread\(c, a, n, ioallocdir, nelem\(ioallocdir\), devgen\);)116 L (153)0(|| start <= m->start && end > m->start\))16(221)100 L (154)0(return 0;)24(222 case Qiob:)100 L (155 })0(223)100(port = offset;)116 L (156 return 1;)0(224)100(checkport\(offset, offset+n\);)116 L (157 })0(225)100(for\(p = a; port < offset+n; port++\))116 L (158)0(226)100(*p++ = inb\(port\);)124 L (159 static void)0(227)100(return n;)116 L (160 checkport\(int start, int end\))0(228)100 L (161 {)0(229 case Qiow:)100 L (162 /* standard vga regs are OK */)0(230)100(if\(\(n & 0x01\) || \(offset & 0x01\)\))116 L (163 if\(start >= 0x2b0 && end <= 0x2df+1\))0(231)100(error\(Ebadarg\);)124 L (164)0(return;)16(232)100(checkport\(offset, offset+n+1\);)116 L (165 if\(start >= 0x3c0 && end <= 0x3da+1\))0(233)100(n /= 2;)116 L (166)0(return;)16(234)100(sp = a;)116 L (167)0(235)100(for\(port = offset; port < offset+n; port += 2\))116 L (168 if\(iounused\(start, end\)\))0(236)100(*sp++ = ins\(port\);)124 L (169)0(return;)16(237)100(return n*2;)116 L (170 error\(Eperm\);)0(238)100 L (171 })0(239 case Qiol:)100 L (172)0(240)100(if\(\(n & 0x03\) || \(offset & 0x03\)\))116 L (173 static Chan*)0(241)100(error\(Ebadarg\);)124 L (174 archattach\(char* spec\))0(242)100(checkport\(offset, offset+n+3\);)116 L (175 {)0(243)100(n /= 4;)116 L (176 return devattach\('P', spec\);)0(244)100(lp = a;)116 L (177 })0(245)100(for\(port = offset; port < offset+n; port += 4\))116 L (178)0(246)100(*lp++ = inl\(port\);)124 L (179 int)0(247)100(return n*4;)116 L (180 archwalk\(Chan* c, char* name\))0(248)100 L (181 {)0(249 case Qioalloc:)100 L (182 return devwalk\(c, name, ioallocdir, nelem\(ioallocdir\), devgen\);)0(250)100(break;)116 L (183 })0(251)100 L (184)0(252 case Qirqalloc:)100 L (185 static void)0(253)100(return irqallocread\(a, n, offset\);)116 L (186 archstat\(Chan* c, char* dp\))0(254)100 L (187 {)0(255 case Qcputype:)100 L (188 devstat\(c, dp, ioallocdir, nelem\(ioallocdir\), devgen\);)0(256)100(return cputyperead\(a, n, offset\);)116 L (189 })0(257)100 L (190)0(258 default:)100 L (191 static Chan*)0(259)100(error\(Eperm\);)116 L (192 archopen\(Chan* c, int omode\))0(260)100(break;)116 L (193 {)0(261 })100 L (194 return devopen\(c, omode, ioallocdir, nelem\(ioallocdir\), devgen\);)0(262)100 L (195 })0(263 offset = offset/Linelen;)100 L (196)0(264 n = n/Linelen;)100 L (197 static void)0(265 p = a;)100 L (198 archclose\(Chan*\))0(266 lock\(&iomap\);)100 L (199 {)0(267 for\(m = iomap.m; n > 0 && m != nil; m = m->next\){)100 L (200 })0(268)100(if\(offset-- > 0\))116 L (201)0(269)100(continue;)124 L (202 enum)0(270)100(if\(strcmp\(m->tag, "dummy"\) == 0\))116 L (203 {)0(271)100(break;)124 L (204 Linelen= 31,)0(272)100(sprint\(buf, "%8lux %8lux %-12.12s\\n", m->start, m->end-1, m->tag\);)116 L cleartomark showpage saveobj restore %%EndPage: 11 11 %%Page: 12 12 /saveobj save def mark 12 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devarch.c Page 3)l ()l ()l (273)0(memmove\(p, buf, Linelen\);)16(341 archwrite,)100 L (274)0(p += Linelen;)16(342 devbwrite,)100 L (275)0(n--;)16(343 devremove,)100 L (276 })0(344 devwstat,)100 L (277 unlock\(&iomap\);)0(345 };)100 L (278)0(346)100 L (279 return p - \(char*\)a;)0(347 /*)100 L (280 })0(348 * the following is a generic version of the)100 L (281)0(349 * architecture specific stuff)100 L (282 static long)0(350 */)100 L (283 archwrite\(Chan *c, void *a, long n, vlong offset\))0(351)100 L (284 {)0(352 static int)100 L (285 int port;)0(353 unimplemented\(int\))100 L (286 ushort *sp;)0(354 {)100 L (287 ulong *lp;)0(355 return 0;)100 L (288 char *p;)0(356 })100 L (289)0(357)100 L (290 switch\(c->qid.path & ~CHDIR\){)0(358 static void)100 L (291)0(359 nop\(void\))100 L (292 case Qiob:)0(360 {)100 L (293)0(p = a;)16(361 })100 L (294)0(checkport\(offset, offset+n\);)16(362)100 L (295)0(for\(port = offset; port < offset+n; port++\))16(363 void \(*coherence\)\(void\) = nop;)100 L (296)0(outb\(port, *p++\);)24(364 void cycletimerinit\(void\);)100 L (297)0(return n;)16(365 uvlong cycletimer\(uvlong*\);)100 L (298)0(366)100 L (299 case Qiow:)0(367 PCArch* arch;)100 L (300)0(if\(\(n & 01\) || \(offset & 01\)\))16(368 extern PCArch* knownarch[];)100 L (301)0(error\(Ebadarg\);)24(369)100 L (302)0(checkport\(offset, offset+n+1\);)16(370 PCArch archgeneric = {)100 L (303)0(n /= 2;)16(371 "generic",)100(/* id */)148 L (304)0(sp = a;)16(372 0,)100(/* ident */)148 L (305)0(for\(port = offset; port < offset+n; port += 2\))16(373 i8042reset,)100(/* reset */)148 L (306)0(outs\(port, *sp++\);)24(374 unimplemented,)100(/* serialpower */)148 L (307)0(return n*2;)16(375 unimplemented,)100(/* modempower */)148 L (308)0(376)100 L (309 case Qiol:)0(377 i8259init,)100(/* intrinit */)148 L (310)0(if\(\(n & 0x03\) || \(offset & 0x03\)\))16(378 i8259enable,)100(/* intrenable */)148 L (311)0(error\(Ebadarg\);)24(379)100 L (312)0(checkport\(offset, offset+n+3\);)16(380 i8253enable,)100(/* clockenable */)148 L (313)0(n /= 4;)16(381)100 L (314)0(lp = a;)16(382 i8253read,)100(/* read the standard timer */)148 L (315)0(for\(port = offset; port < offset+n; port += 4\))16(383 };)100 L (316)0(outl\(port, *lp++\);)24(384)100 L (317)0(return n*4;)16(385 typedef struct {)100 L (318)0(386 int family;)100 L (319 default:)0(387 int model;)100 L (320)0(error\(Eperm\);)16(388 int aalcycles;)100 L (321)0(break;)16(389 char* name;)100 L (322 })0(390 } X86type;)100 L (323 return 0;)0(391)100 L (324 })0(392 static X86type x86intel[] =)100 L (325)0(393 {)100 L (326 Dev archdevtab = {)0(394 { 4, 0,)100(22, "486DX", }, /* known chips */)124 L (327 'P',)0(395 { 4, 1,)100(22, "486DX50", },)124 L (328 "arch",)0(396 { 4, 2,)100(22, "486SX", },)124 L (329)0(397 { 4, 3,)100(22, "486DX2", },)124 L (330 devreset,)0(398 { 4, 4,)100(22, "486SL", },)124 L (331 devinit,)0(399 { 4, 5,)100(22, "486SX2", },)124 L (332 archattach,)0(400 { 4, 7,)100(22, "DX2WB", }, /* P24D */)124 L (333 devclone,)0(401 { 4, 8,)100(22, "DX4", },)124(/* P24C */)148 L (334 archwalk,)0(402 { 4, 9,)100(22, "DX4WB", }, /* P24CT */)124 L (335 archstat,)0(403 { 5, 0,)100(23, "P5", },)124 L (336 archopen,)0(404 { 5, 1,)100(23, "P5", },)124 L (337 devcreate,)0(405 { 5, 2,)100(23, "P54C", },)124 L (338 archclose,)0(406 { 5, 3,)100(23, "P24T", },)124 L (339 archread,)0(407 { 5, 4,)100(23, "P55C MMX", },)124 L (340 devbread,)0(408 { 5, 7,)100(23, "P54C VRT", },)124 L cleartomark showpage saveobj restore %%EndPage: 12 12 %%Page: 13 13 /saveobj save def mark 13 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devarch.c Page 4)l ()l ()l (409 { 6, 1,)0(16, "PentiumPro", },/* trial and error */)24(477 ulong cr4;)100 L (410 { 6, 3,)0(16, "PentiumII", },)24(478 vlong mct;)100 L (411 { 6, 5,)0(16, "PentiumII/Xeon", },)24(479)100 L (412 { 6, 6,)0(16, "Celeron", },)24(480 cpuid\(m->cpuidid, &m->cpuidax, &m->cpuiddx\);)100 L (413 { 6, 7,)0(16, "PentiumIII/Xeon", },)24(481 if\(strncmp\(m->cpuidid, "AuthenticAMD", 12\) == 0\))100 L (414 { 6, 8,)0(16, "PentiumIII/Xeon", },)24(482)100(t = x86amd;)116 L (415)0(483 else)100 L (416 { 3, -1, 32, "386", },)0(/* family defaults */)48(484)100(t = x86intel;)116 L (417 { 4, -1, 22, "486", },)0(485 family = X86FAMILY\(m->cpuidax\);)100 L (418 { 5, -1, 23, "P5", },)0(486 model = X86MODEL\(m->cpuidax\);)100 L (419 { 6, -1, 16, "P6", },)0(487 while\(t->name\){)100 L (420)0(488)100(if\(\(t->family == family && t->model == model\))116 L (421 { -1, -1, 23, "unknown", }, /* total default */)0(489)100(|| \(t->family == family && t->model == -1\))116 L (422 };)0(490)100(|| \(t->family == -1\)\))116 L (423)0(491)100(break;)124 L (424 /*)0(492)100(t++;)116 L (425 * The AMD processors all implement the CPUID instruction.)0(493 })100 L (426 * The later ones also return the processor name via functions)0(494 m->cpuidtype = t->name;)100 L (427 * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX)0(495 i8253init\(t->aalcycles, t->family >= 5\);)100 L (428 * and DX:)0(496)100 L (429 *)0(K5)16("AMD-K5\(tm\) Processor")24(497 /*)100 L (430 *)0(K6)16("AMD-K6tm w/ multimedia extensions")24(498)100(* If machine check exception or page size extensions are supported)109 L (431 *)0(K6 3D "AMD-K6\(tm\) 3D processor")16(499)100(* enable them in CR4 and clear any other set extensions.)109 L (432 *)0(K6 3D+ ?)16(500)100(* If machine check was enabled clear out any lingering status.)109 L (433 */)0(501)100(*/)109 L (434 static X86type x86amd[] =)0(502 if\(m->cpuiddx & 0x88\){)100 L (435 {)0(503)100(cr4 = 0;)116 L (436 { 5, 0,)0(23, "AMD-K5", }, /* guesswork */)24(504)100(if\(m->cpuiddx & 0x08\))116 L (437 { 5, 1,)0(23, "AMD-K5", }, /* guesswork */)24(505)100(cr4 |= 0x10;)124(/* page size extensions */)148 L (438 { 5, 2,)0(23, "AMD-K5", }, /* guesswork */)24(506)100(if\(m->cpuiddx & 0x80\))116 L (439 { 5, 3,)0(23, "AMD-K5", }, /* guesswork */)24(507)100(cr4 |= 0x40;)124(/* machine check enable */)148 L (440 { 5, 6,)0(11, "AMD-K6", }, /* trial and error */)24(508)100(putcr4\(cr4\);)116 L (441 { 5, 7,)0(11, "AMD-K6", }, /* trial and error */)24(509)100(if\(m->cpuiddx & 0x80\))116 L (442 { 5, 8,)0(11, "AMD-K6-2", }, /* trial and error */)24(510)100(rdmsr\(0x01, &mct\);)124 L (443 { 5, 9,)0(11, "AMD-K6-III", },/* trial and error */)24(511 })100 L (444)0(512)100 L (445 { 6, 1,)0(11, "AMD-Athlon", },/* trial and error */)24(513 cputype = t;)100 L (446 { 6, 2,)0(11, "AMD-Athlon", },/* trial and error */)24(514 return t->family;)100 L (447)0(515 })100 L (448 { 4, -1, 22, "Am486", }, /* guesswork */)0(516)100 L (449 { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */)0(517 static long)100 L (450 { 6, -1, 11, "AMD-Athlon", },/* guesswork */)0(518 cputyperead\(char *a, int n, ulong offset\))100 L (451)0(519 {)100 L (452 { -1, -1, 23, "unknown", }, /* total default */)0(520 char str[32];)100 L (453 };)0(521 ulong mhz;)100 L (454)0(522)100 L (455 static uvlong fasthz;)0(523 mhz = \(m->cpuhz+999999\)/1000000;)100 L (456 static X86type *cputype;)0(524)100 L (457)0(525 snprint\(str, sizeof\(str\), "%s %lud\\n", cputype->name, mhz\);)100 L (458 void)0(526 return readstr\(offset, a, n, str\);)100 L (459 cpuidprint\(void\))0(527 })100 L (460 {)0(528)100 L (461 int i;)0(529 void)100 L (462 char buf[128];)0(530 archinit\(void\))100 L (463)0(531 {)100 L (464 i = sprint\(buf, "cpu%d: %dMHz ", m->machno, m->cpumhz\);)0(532 PCArch **p;)100 L (465 if\(m->cpuidid[0]\))0(533)100 L (466)0(i += sprint\(buf+i, "%s ", m->cpuidid\);)16(534 arch = 0;)100 L (467 sprint\(buf+i, "%s \(cpuid: AX 0x%4.4uX DX 0x%4.4uX\)\\n",)0(535 for\(p = knownarch; *p; p++\){)100 L (468)0(m->cpuidtype, m->cpuidax, m->cpuiddx\);)16(536)100(if\(\(*p\)->ident && \(*p\)->ident\(\) == 0\){)116 L (469 print\(buf\);)0(537)100(arch = *p;)124 L (470 })0(538)100(break;)124 L (471)0(539)100(})116 L (472 int)0(540 })100 L (473 cpuidentify\(void\))0(541 if\(arch == 0\))100 L (474 {)0(542)100(arch = &archgeneric;)116 L (475 int family, model;)0(543 else{)100 L (476 X86type *t;)0(544)100(if\(arch->id == 0\))116 L cleartomark showpage saveobj restore %%EndPage: 13 13 %%Page: 14 14 /saveobj save def mark 14 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devarch.c Page 5)l ()l ()l (545)0(arch->id = archgeneric.id;)24 L (546)0(if\(arch->reset == 0\))16 L (547)0(arch->reset = archgeneric.reset;)24 L (548)0(if\(arch->serialpower == 0\))16 L (549)0(arch->serialpower = archgeneric.serialpower;)24 L (550)0(if\(arch->modempower == 0\))16 L (551)0(arch->modempower = archgeneric.modempower;)24 L (552)l (553)0(if\(arch->intrinit == 0\))16 L (554)0(arch->intrinit = archgeneric.intrinit;)24 L (555)0(if\(arch->intrenable == 0\))16 L (556)0(arch->intrenable = archgeneric.intrenable;)24 L (557 })l (558)l (559 /* pick the better timer */)l (560 if\(X86FAMILY\(m->cpuidax\) >= 5\){)l (561)0(cycletimerinit\(\);)16 L (562)0(arch->fastclock = cycletimer;)16 L (563 })l (564)l (565 /*)l (566)0(* Decide whether to use copy-on-reference \(386 and mp\).)9 L (567)0(*/)9 L (568 if\(X86FAMILY\(m->cpuidax\) == 3 || conf.nmach > 1\))l (569)0(conf.copymode = 1;)16 L (570)l (571 if\(X86FAMILY\(m->cpuidax\) >= 5\))l (572)0(coherence = wbflush;)16 L (573 })l (574)l (575 void)l (576 cycletimerinit\(void\))l (577 {)l (578 wrmsr\(0x10, 0\);)l (579 fasthz = m->cpuhz;)l (580 })l (581)l (582 /*)l (583 * return the most precise clock we have)l (584 */)l (585 uvlong)l (586 cycletimer\(uvlong *hz\))l (587 {)l (588 uvlong tsc;)l (589)l (590 rdmsr\(0x10, \(vlong*\)&tsc\);)l (591 m->fastclock = tsc;)l (592 if\(hz != nil\))l (593)0(*hz = fasthz;)16 L (594 return tsc;)l (595 })l (596)l (597 vlong)l (598 fastticks\(uvlong *hz\))l (599 {)l (600 return \(*arch->fastclock\)\(hz\);)l (601 })l cleartomark showpage saveobj restore %%EndPage: 14 14 %%Page: 15 15 /saveobj save def mark 15 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 1)l ()l ()l (1 #include "u.h")0(69 */)100 L (2 #include "../port/lib.h")0(70 static void)100 L (3 #include "mem.h")0(71 putstrn0\(char *str, int n, int usewrite\))100 L (4 #include "dat.h")0(72 {)100 L (5 #include "fns.h")0(73)100(int m;)108 L (6 #include "../port/error.h")0(74)100(char *t;)108 L (7)0(75)100(char buf[PRINTSIZE+2];)108 L (8 void)0(\(*consdebug\)\(void\) = nil;)16(76)100 L (9)0(77)100(/*)108 L (10 Queue* kbdq;)0(/* unprocessed console input */)40(78)100(* if there's an attached bit mapped display,)109 L (11 Queue* lineq;)0(/* processed console input */)40(79)100(* put the message there. screenputs is defined)109 L (12 Queue* printq;)0(/* console output */)40(80)100(* as a null macro for systems that have no such)109 L (13)0(81)100(* display.)109 L (14 static struct)0(82)100(*/)109 L (15 {)0(83)100(screenputs\(str, n\);)108 L (16)0(QLock;)8(84)100 L (17)0(85)100(/*)108 L (18)0(int raw;)8(/* true if we shouldn't process input */)32(86)100(* if there's a serial line being used as a console,)109 L (19)0(int ctl;)8(/* number of opens to the control file */)32(87)100(* put the message there.)109 L (20)0(int x;)8(/* index into line */)32(88)100(*/)109 L (21)0(char line[1024]; /* current input line */)8(89)100(if\(printq == 0\))108 L (22)0(90)100(return;)116 L (23)0(Rune c;)8(91)100 L (24)0(int count;)8(92)100(while\(n > 0\) {)108 L (25)0(int repeat;)8(93)100(t = memchr\(str, '\\n', n\);)116 L (26)0(int ctlpoff;)8(94)100(if\(t\) {)116 L (27 } kbd;)0(95)100(m = t - str;)124 L (28)0(96)100(memmove\(buf, str, m\);)124 L (29 char)0(sysname[NAMELEN];)16(97)100(buf[m] = '\\r';)124 L (30 vlong fasthz;)0(98)100(buf[m+1] = '\\n';)124 L (31)0(99)100(if\(usewrite\))124 L (32 static ulong)0(randomread\(void*, ulong\);)24(100)100(qwrite\(printq, buf, m+2\);)132 L (33 static void)0(randominit\(void\);)24(101)100(else)124 L (34 static void)0(seedrand\(void\);)24(102)100(qiwrite\(printq, buf, m+2\);)132 L (35 static int)0(readtime\(ulong, char*, int\);)24(103)100(str = t + 1;)124 L (36 static int)0(readbintime\(char*, int\);)24(104)100(n -= m + 1;)124 L (37 static int)0(writetime\(char*, int\);)24(105)100(} else {)116 L (38 static int)0(writebintime\(char*, int\);)24(106)100(if\(usewrite\))124 L (39)0(107)100(qwrite\(printq, str, n\);)132 L (40 void)0(108)100(else)124 L (41 printinit\(void\))0(109)100(qiwrite\(printq, str, n\);)132 L (42 {)0(110)100(break;)124 L (43)0(lineq = qopen\(2*1024, 0, 0, 0\);)8(111)100(})116 L (44)0(if\(lineq == nil\))8(112 })100 L (45)0(panic\("printinit"\);)16(113 })100 L (46)0(qnoblock\(lineq, 1\);)8(114)100 L (47 })0(115 void)100 L (48)0(116 putstrn\(char *str, int n\))100 L (49 int)0(117 {)100 L (50 consactive\(void\))0(118 putstrn0\(str, n, 0\);)100 L (51 {)0(119 })100 L (52)0(if\(printq\))8(120)100 L (53)0(return qlen\(printq\) > 0;)16(121 int)100 L (54)0(return 0;)8(122 snprint\(char *s, int n, char *fmt, ...\))100 L (55 })0(123 {)100 L (56)0(124 va_list arg;)100 L (57 void)0(125)100 L (58 prflush\(void\))0(126 va_start\(arg, fmt\);)100 L (59 {)0(127 n = doprint\(s, s+n, fmt, arg\) - s;)100 L (60)0(while\(consactive\(\)\))8(128 va_end\(arg\);)100 L (61)0(;)16(129 return n;)100 L (62 })0(130 })100 L (63)0(131)100 L (64 /*)0(132 int)100 L (65 * Print a string on the console. Convert \\n to \\r\\n for serial)0(133 sprint\(char *s, char *fmt, ...\))100 L (66 * line consoles. Locking of the queues is left up to the screen)0(134 {)100 L (67 * or uart code. Multi-line messages to serial consoles may get)0(135 int n;)100 L (68 * interspersed with other messages.)0(136 va_list arg;)100 L cleartomark showpage saveobj restore %%EndPage: 15 15 %%Page: 16 16 /saveobj save def mark 16 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 2)l ()l ()l (137)0(205)100 L (138 va_start\(arg, fmt\);)0(206 void)100 L (139 n = doprint\(s, s+PRINTSIZE, fmt, arg\) - s;)0(207 _assert\(char *fmt\))100 L (140 va_end\(arg\);)0(208 {)100 L (141 return n;)0(209 panic\("assert failed: %s", fmt\);)100 L (142 })0(210 })100 L (143)0(211)100 L (144 int noprint;)0(212 int)100 L (145)0(213 pprint\(char *fmt, ...\))100 L (146 int)0(214 {)100 L (147 print\(char *fmt, ...\))0(215 int n;)100 L (148 {)0(216 Chan *c;)100 L (149 int n;)0(217 va_list arg;)100 L (150 va_list arg;)0(218 char buf[2*PRINTSIZE];)100 L (151 char buf[PRINTSIZE];)0(219)100 L (152)0(220 if\(up == nil || up->fgrp == nil\))100 L (153 if\(noprint\))0(221)100(return 0;)116 L (154)0(return -1;)16(222)100 L (155)0(223 c = up->fgrp->fd[2];)100 L (156 va_start\(arg, fmt\);)0(224 if\(c==0 || \(c->mode!=OWRITE && c->mode!=ORDWR\)\))100 L (157 n = doprint\(buf, buf+sizeof\(buf\), fmt, arg\) - buf;)0(225)100(return 0;)116 L (158 va_end\(arg\);)0(226 n = sprint\(buf, "%s %lud: ", up->text, up->pid\);)100 L (159 putstrn\(buf, n\);)0(227 va_start\(arg, fmt\);)100 L (160)0(228 n = doprint\(buf+n, buf+sizeof\(buf\), fmt, arg\) - buf;)100 L (161 return n;)0(229 va_end\(arg\);)100 L (162 })0(230)100 L (163)0(231 if\(waserror\(\)\))100 L (164 int)0(232)100(return 0;)116 L (165 iprint\(char *fmt, ...\))0(233 devtab[c->type]->write\(c, buf, n, c->offset\);)100 L (166 {)0(234 poperror\(\);)100 L (167 int n, s;)0(235)100 L (168 va_list arg;)0(236 lock\(c\);)100 L (169 char buf[PRINTSIZE];)0(237 c->offset += n;)100 L (170)0(238 unlock\(c\);)100 L (171 s = splhi\(\);)0(239)100 L (172 va_start\(arg, fmt\);)0(240 return n;)100 L (173 n = doprint\(buf, buf+sizeof\(buf\), fmt, arg\) - buf;)0(241 })100 L (174 va_end\(arg\);)0(242)100 L (175 serialputs\(buf, n\);)0(243 void)100 L (176 //)0(screenputs\(buf, n\);)16(244 echo\(Rune r, char *buf, int n\))100 L (177 splx\(s\);)0(245 {)100 L (178)0(246 static int ctrlt, pid;)100 L (179 return n;)0(247 extern ulong etext;)100 L (180 })0(248 int x;)100 L (181)0(249)100 L (182 void)0(250 /*)100 L (183 panic\(char *fmt, ...\))0(251)100(* ^p hack)109 L (184 {)0(252)100(*/)109 L (185 int n;)0(253 if\(r==0x10 && cpuserver && !kbd.ctlpoff\){)100 L (186 va_list arg;)0(254)100(lock\(&active\);)116 L (187 char buf[PRINTSIZE];)0(255)100(active.exiting = 1;)116 L (188)0(256)100(unlock\(&active\);)116 L (189 splhi\(\);)0(257 })100 L (190 strcpy\(buf, "panic: "\);)0(258)100 L (191 va_start\(arg, fmt\);)0(259 /*)100 L (192 n = doprint\(buf+strlen\(buf\), buf+sizeof\(buf\), fmt, arg\) - buf;)0(260)100(* ^t hack BUG)109 L (193 va_end\(arg\);)0(261)100(*/)109 L (194 buf[n] = '\\n';)0(262 if\(ctrlt == 2\){)100 L (195 serialputs\(buf, n+1\);)0(263)100(ctrlt = 0;)116 L (196 if\(consdebug\))0(264)100(switch\(r\){)116 L (197)0(consdebug\(\);)16(265)100(case 0x14:)116 L (198 putstrn\(buf, n+1\);)0(266)100(break; /* pass it on */)124 L (199 spllo\(\);)0(267)100(case 's':)116 L (200 prflush\(\);)0(268)100(dumpstack\(\);)124 L (201 dumpstack\(\);)0(269)100(break;)124 L (202)0(270)100(case 'x':)116 L (203 exit\(1\);)0(271)100(xsummary\(\);)124 L (204 })0(272)100(ixsummary\(\);)124 L cleartomark showpage saveobj restore %%EndPage: 16 16 %%Page: 17 17 /saveobj save def mark 17 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 3)l ()l ()l (273)0(mallocsummary\(\);)24(341 /*)100 L (274)0(pagersummary\(\);)24(342 * Put character, possibly a rune, into read queue at interrupt time.)100 L (275)0(break;)24(343 * Called at interrupt time to process a character.)100 L (276)0(case 'd':)16(344 */)100 L (277)0(if\(consdebug == nil\))24(345 int)100 L (278)0(consdebug = rdb;)32(346 kbdputc\(Queue*, int ch\))100 L (279)0(else)24(347 {)100 L (280)0(consdebug = nil;)32(348 int n;)100 L (281)0(print\("consdebug now 0x%p\\n", consdebug\);)24(349 char buf[3];)100 L (282)0(return;)24(350 Rune r;)100 L (283)0(case 'D':)16(351)100 L (284)0(if\(consdebug == nil\))24(352 r = ch;)100 L (285)0(consdebug = rdb;)32(353 n = runetochar\(buf, &r\);)100 L (286)0(consdebug\(\);)24(354 if\(n == 0\))100 L (287)0(return;)24(355)100(return 0;)116 L (288)0(case 'p':)16(356 echo\(r, buf, n\);)100 L (289)0(x = spllo\(\);)24(357 kbd.c = r;)100 L (290)0(procdump\(\);)24(358 qproduce\(kbdq, buf, n\);)100 L (291)0(splx\(x\);)24(359 return 0;)100 L (292)0(return;)24(360 })100 L (293)0(case 'q':)16(361)100 L (294)0(scheddump\(\);)24(362 void)100 L (295)0(break;)24(363 kbdrepeat\(int rep\))100 L (296)0(case 'k':)16(364 {)100 L (297)0(if\(!cpuserver\))24(365 kbd.repeat = rep;)100 L (298)0(killbig\(\);)32(366 kbd.count = 0;)100 L (299)0(break;)24(367 })100 L (300)0(case 'r':)16(368)100 L (301)0(exit\(0\);)24(369 void)100 L (302)0(break;)24(370 kbdclock\(void\))100 L (303)0(})16(371 {)100 L (304 })0(372 if\(kbd.repeat == 0\))100 L (305 else if\(r == 0x14\){)0(373)100(return;)116 L (306)0(ctrlt++;)16(374 if\(kbd.repeat==1 && ++kbd.count>HZ\){)100 L (307)0(return;)16(375)100(kbd.repeat = 2;)116 L (308 })0(376)100(kbd.count = 0;)116 L (309 ctrlt = 0;)0(377)100(return;)116 L (310 if\(kbd.raw\))0(378 })100 L (311)0(return;)16(379 if\(++kbd.count&1\))100 L (312)0(380)100(kbdputc\(kbdq, kbd.c\);)116 L (313 /*)0(381 })100 L (314)0(* finally, the actual echoing)9(382)100 L (315)0(*/)9(383 enum{)100 L (316 if\(r == '\\n'\){)0(384 Qdir,)100 L (317)0(if\(printq\))16(385 Qauth,)100 L (318)0(qiwrite\(printq, "\\r", 1\);)24(386 Qauthcheck,)100 L (319 } else if\(r == 0x15\){)0(387 Qauthent,)100 L (320)0(buf = "^U\\n";)16(388 Qbintime,)100 L (321)0(n = 3;)16(389 Qcons,)100 L (322 })0(390 Qconsctl,)100 L (323 screenputs\(buf, n\);)0(391 Qcputime,)100 L (324 if\(printq\))0(392 Qdrivers,)100 L (325)0(qiwrite\(printq, buf, n\);)16(393 Qkey,)100 L (326 })0(394 Qhostdomain,)100 L (327)0(395 Qhostowner,)100 L (328 /*)0(396 Qnull,)100 L (329 * Called by a uart interrupt for console input.)0(397 Qpgrpid,)100 L (330 *)0(398 Qpid,)100 L (331 * turn '\\r' into '\\n' before putting it into the queue.)0(399 Qppid,)100 L (332 */)0(400 Qrandom,)100 L (333 int)0(401 Qreboot,)100 L (334 kbdcr2nl\(Queue *q, int ch\))0(402 Qswap,)100 L (335 {)0(403 Qsysname,)100 L (336 if\(ch == '\\r'\))0(404 Qsysstat,)100 L (337)0(ch = '\\n';)16(405 Qtime,)100 L (338 return kbdputc\(q, ch\);)0(406 Quser,)100 L (339 })0(407 Qzero,)100 L (340)0(408 };)100 L cleartomark showpage saveobj restore %%EndPage: 17 17 %%Page: 18 18 /saveobj save def mark 18 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 4)l ()l ()l (409)0(477 static Chan*)100 L (410 enum)0(478 consattach\(char *spec\))100 L (411 {)0(479 {)100 L (412 VLNUMSIZE=)0(22,)24(480 return devattach\('c', spec\);)100 L (413 };)0(481 })100 L (414)0(482)100 L (415 static Dirtab consdir[]={)0(483 static int)100 L (416 "authenticate", {Qauth},)0(0,)40(0666,)56(484 conswalk\(Chan *c, char *name\))100 L (417 "authcheck", {Qauthcheck}, 0,)0(0666,)56(485 {)100 L (418 "authenticator", {Qauthent}, 0,)0(0666,)56(486 return devwalk\(c, name, consdir, nelem\(consdir\), devgen\);)100 L (419 "bintime",)0({Qbintime}, 24,)24(0664,)56(487 })100 L (420 "cons",)0({Qcons},)24(0,)40(0660,)56(488)100 L (421 "consctl",)0({Qconsctl}, 0,)24(0220,)56(489 static void)100 L (422 "cputime",)0({Qcputime}, 6*NUMSIZE,)24(0444,)56(490 consstat\(Chan *c, char *dp\))100 L (423 "drivers",)0({Qdrivers}, 0,)24(0644,)56(491 {)100 L (424 "hostdomain", {Qhostdomain}, DOMLEN,)0(0664,)56(492 devstat\(c, dp, consdir, nelem\(consdir\), devgen\);)100 L (425 "hostowner", {Qhostowner}, NAMELEN,)0(0664,)56(493 })100 L (426 "key",)0({Qkey},)24(DESKEYLEN,)40(0622,)56(494)100 L (427 "null",)0({Qnull},)24(0,)40(0666,)56(495 static Chan*)100 L (428 "pgrpid",)0({Qpgrpid},)24(NUMSIZE,)40(0444,)56(496 consopen\(Chan *c, int omode\))100 L (429 "pid",)0({Qpid},)24(NUMSIZE,)40(0444,)56(497 {)100 L (430 "ppid",)0({Qppid},)24(NUMSIZE,)40(0444,)56(498 c->aux = 0;)100 L (431 "random",)0({Qrandom},)24(0,)40(0664,)56(499 switch\(c->qid.path\){)100 L (432 "reboot",)0({Qreboot},)24(0,)40(0664,)56(500 case Qconsctl:)100 L (433 "swap",)0({Qswap},)24(0,)40(0664,)56(501)100(if\(!iseve\(\)\))116 L (434 "sysname",)0({Qsysname}, 0,)24(0664,)56(502)100(error\(Eperm\);)124 L (435 "sysstat",)0({Qsysstat}, 0,)24(0666,)56(503)100(qlock\(&kbd\);)116 L (436 "time",)0({Qtime},)24(NUMSIZE+3*VLNUMSIZE, 0664,)40(504)100(kbd.ctl++;)116 L (437 "user",)0({Quser},)24(NAMELEN,)40(0666,)56(505)100(qunlock\(&kbd\);)116 L (438 "zero",)0({Qzero},)24(0,)40(0444,)56(506)100(break;)116 L (439 };)0(507 })100 L (440)0(508 return devopen\(c, omode, consdir, nelem\(consdir\), devgen\);)100 L (441 int)0(509 })100 L (442 readnum\(ulong off, char *buf, ulong n, ulong val, int size\))0(510)100 L (443 {)0(511 static void)100 L (444 char tmp[64];)0(512 consclose\(Chan *c\))100 L (445)0(513 {)100 L (446 snprint\(tmp, sizeof\(tmp\), "%*.0lud", size-1, val\);)0(514 /* last close of control file turns off raw */)100 L (447 tmp[size-1] = ' ';)0(515 switch\(c->qid.path\){)100 L (448 if\(off >= size\))0(516 case Qconsctl:)100 L (449)0(return 0;)16(517)100(if\(c->flag&COPEN\){)116 L (450 if\(off+n > size\))0(518)100(qlock\(&kbd\);)124 L (451)0(n = size-off;)16(519)100(if\(--kbd.ctl == 0\))124 L (452 memmove\(buf, tmp+off, n\);)0(520)100(kbd.raw = 0;)132 L (453 return n;)0(521)100(qunlock\(&kbd\);)124 L (454 })0(522)100(})116 L (455)0(523)100(break;)116 L (456 int)0(524 case Qauth:)100 L (457 readstr\(ulong off, char *buf, ulong n, char *str\))0(525 case Qauthcheck:)100 L (458 {)0(526 case Qauthent:)100 L (459 int size;)0(527)100(authclose\(c\);)116 L (460)0(528 })100 L (461 size = strlen\(str\);)0(529 })100 L (462 if\(off >= size\))0(530)100 L (463)0(return 0;)16(531 static long)100 L (464 if\(off+n > size\))0(532 consread\(Chan *c, void *buf, long n, vlong off\))100 L (465)0(n = size-off;)16(533 {)100 L (466 memmove\(buf, str+off, n\);)0(534 ulong l;)100 L (467 return n;)0(535 Mach *mp;)100 L (468 })0(536 char *b, *bp;)100 L (469)0(537 char tmp[128];)100(/* must be >= 6*NUMSIZE */)132 L (470 static void)0(538 char *cbuf = buf;)100 L (471 consinit\(void\))0(539 int ch, i, k, id, eol;)100 L (472 {)0(540 vlong offset = off;)100 L (473 todinit\(\);)0(541)100 L (474 randominit\(\);)0(542 if\(n <= 0\))100 L (475 })0(543)100(return n;)116 L (476)0(544 switch\(c->qid.path & ~CHDIR\){)100 L cleartomark showpage saveobj restore %%EndPage: 18 18 %%Page: 19 19 /saveobj save def mark 19 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 5)l ()l ()l (545 case Qdir:)0(613)100(if\(i == TReal\))124 L (546)0(return devdirread\(c, buf, n, consdir, nelem\(consdir\), devgen\);)16(614)100(l = MACHP\(0\)->ticks - l;)132 L (547)0(615)100(l = TK2MS\(l\);)124 L (548 case Qcons:)0(616)100(readnum\(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE\);)124 L (549)0(qlock\(&kbd\);)16(617)100(})116 L (550)0(if\(waserror\(\)\) {)16(618)100(memmove\(buf, tmp+k, n\);)116 L (551)0(qunlock\(&kbd\);)24(619)100(return n;)116 L (552)0(nexterror\(\);)24(620)100 L (553)0(})16(621 case Qpgrpid:)100 L (554)0(if\(kbd.raw\) {)16(622)100(return readnum\(\(ulong\)offset, buf, n, up->pgrp->pgrpid, NUMSIZE\);)116 L (555)0(if\(qcanread\(lineq\)\))24(623)100 L (556)0(n = qread\(lineq, buf, n\);)32(624 case Qpid:)100 L (557)0(else {)24(625)100(return readnum\(\(ulong\)offset, buf, n, up->pid, NUMSIZE\);)116 L (558)0(/* read as much as possible */)32(626)100 L (559)0(do {)32(627 case Qppid:)100 L (560)0(i = qread\(kbdq, cbuf, n\);)40(628)100(return readnum\(\(ulong\)offset, buf, n, up->parentpid, NUMSIZE\);)116 L (561)0(cbuf += i;)40(629)100 L (562)0(n -= i;)40(630 case Qtime:)100 L (563)0(} while \(n>0 && qcanread\(kbdq\)\);)32(631)100(return readtime\(\(ulong\)offset, buf, n\);)116 L (564)0(n = cbuf - \(char*\)buf;)32(632)100 L (565)0(})24(633 case Qbintime:)100 L (566)0(} else {)16(634)100(return readbintime\(buf, n\);)116 L (567)0(while\(!qcanread\(lineq\)\) {)24(635)100 L (568)0(qread\(kbdq, &kbd.line[kbd.x], 1\);)32(636 case Qkey:)100 L (569)0(ch = kbd.line[kbd.x];)32(637)100(return keyread\(buf, n, offset\);)116 L (570)0(if\(kbd.raw\){)32(638)100 L (571)0(qiwrite\(lineq, kbd.line, kbd.x+1\);)40(639 case Qauth:)100 L (572)0(kbd.x = 0;)40(640)100(return authread\(c, cbuf, n\);)116 L (573)0(continue;)40(641)100 L (574)0(})32(642 case Qauthcheck:)100 L (575)0(eol = 0;)32(643)100(return authcheckread\(c, cbuf, n\);)116 L (576)0(switch\(ch\){)32(644)100 L (577)0(case '\\b':)32(645 case Qauthent:)100 L (578)0(if\(kbd.x\))40(646)100(return authentread\(c, cbuf, n\);)116 L (579)0(kbd.x--;)48(647)100 L (580)0(break;)40(648 case Qhostowner:)100 L (581)0(case 0x15:)32(649)100(return readstr\(\(ulong\)offset, buf, n, eve\);)116 L (582)0(kbd.x = 0;)40(650)100 L (583)0(break;)40(651 case Qhostdomain:)100 L (584)0(case '\\n':)32(652)100(return readstr\(\(ulong\)offset, buf, n, hostdomain\);)116 L (585)0(case 0x04:)32(653)100 L (586)0(eol = 1;)40(654 case Quser:)100 L (587)0(default:)32(655)100(return readstr\(\(ulong\)offset, buf, n, up->user\);)116 L (588)0(kbd.line[kbd.x++] = ch;)40(656)100 L (589)0(break;)40(657 case Qnull:)100 L (590)0(})32(658)100(return 0;)116 L (591)0(if\(kbd.x == sizeof\(kbd.line\) || eol\){)32(659)100 L (592)0(if\(ch == 0x04\))40(660 case Qsysstat:)100 L (593)0(kbd.x--;)48(661)100(b = smalloc\(conf.nmach*\(NUMSIZE*8+1\) + 1\);)116(/* +1 for NUL */)164 L (594)0(qwrite\(lineq, kbd.line, kbd.x\);)40(662)100(bp = b;)116 L (595)0(kbd.x = 0;)40(663)100(for\(id = 0; id < 32; id++\) {)116 L (596)0(})32(664)100(if\(active.machs & \(1<cs, NUMSIZE\);)132 L (601)0(poperror\(\);)16(669)100(bp += NUMSIZE;)132 L (602)0(return n;)16(670)100(readnum\(0, bp, NUMSIZE, mp->intr, NUMSIZE\);)132 L (603)0(671)100(bp += NUMSIZE;)132 L (604 case Qcputime:)0(672)100(readnum\(0, bp, NUMSIZE, mp->syscall, NUMSIZE\);)132 L (605)0(k = offset;)16(673)100(bp += NUMSIZE;)132 L (606)0(if\(k >= 6*NUMSIZE\))16(674)100(readnum\(0, bp, NUMSIZE, mp->pfault, NUMSIZE\);)132 L (607)0(return 0;)24(675)100(bp += NUMSIZE;)132 L (608)0(if\(k+n > 6*NUMSIZE\))16(676)100(readnum\(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE\);)132 L (609)0(n = 6*NUMSIZE - k;)24(677)100(bp += NUMSIZE;)132 L (610)0(/* easiest to format in a separate buffer and copy out */)16(678)100(readnum\(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE\);)132 L (611)0(for\(i=0; i<6 && NUMSIZE*itime[i];)24(680)100(readnum\(0, bp, NUMSIZE, mp->load, NUMSIZE\);)132 L cleartomark showpage saveobj restore %%EndPage: 19 19 %%Page: 20 20 /saveobj save def mark 20 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 6)l ()l ()l (681)0(bp += NUMSIZE;)32(749)100(})116 L (682)0(*bp++ = '\\n';)32(750)100(break;)116 L (683)0(})24(751)100 L (684)0(})16(752 case Qconsctl:)100 L (685)0(n = readstr\(\(ulong\)offset, buf, n, b\);)16(753)100(if\(n >= sizeof\(buf\)\))116 L (686)0(free\(b\);)16(754)100(n = sizeof\(buf\)-1;)124 L (687)0(return n;)16(755)100(strncpy\(buf, a, n\);)116 L (688)0(756)100(buf[n] = 0;)116 L (689 case Qswap:)0(757)100(for\(a = buf; a;\){)116 L (690)0(sprint\(tmp, "%lud/%lud memory %lud/%lud swap\\n",)16(758)100(if\(strncmp\(a, "rawon", 5\) == 0\){)124 L (691)0(palloc.user-palloc.freecount,)24(759)100(qlock\(&kbd\);)132 L (692)0(palloc.user, conf.nswap-swapalloc.free, conf.nswap\);)24(760)100(if\(kbd.x\){)132 L (693)0(761)100(qwrite\(kbdq, kbd.line, kbd.x\);)140 L (694)0(return readstr\(\(ulong\)offset, buf, n, tmp\);)16(762)100(kbd.x = 0;)140 L (695)0(763)100(})132 L (696 case Qsysname:)0(764)100(kbd.raw = 1;)132 L (697)0(return readstr\(\(ulong\)offset, buf, n, sysname\);)16(765)100(qunlock\(&kbd\);)132 L (698)0(766)100(} else if\(strncmp\(a, "rawoff", 6\) == 0\){)124 L (699 case Qrandom:)0(767)100(kbd.raw = 0;)132 L (700)0(return randomread\(buf, n\);)16(768)100(kbd.x = 0;)132 L (701)0(769)100(} else if\(strncmp\(a, "ctlpon", 6\) == 0\){)124 L (702 case Qdrivers:)0(770)100(kbd.ctlpoff = 0;)132 L (703)0(b = malloc\(READSTR\);)16(771)100(} else if\(strncmp\(a, "ctlpoff", 7\) == 0\){)124 L (704)0(if\(b == nil\))16(772)100(kbd.ctlpoff = 1;)132 L (705)0(error\(Enomem\);)24(773)100(})124 L (706)0(n = 0;)16(774)100(if\(a = strchr\(a, ' '\)\))124 L (707)0(for\(i = 0; devtab[i] != nil; i++\))16(775)100(a++;)132 L (708)0(n += snprint\(b+n, READSTR-n, "#%C %s\\n", devtab[i]->dc, devtab[i]->name\); 776)24(})116 L (709)0(n = readstr\(\(ulong\)offset, buf, n, b\);)16(777)100(break;)116 L (710)0(free\(b\);)16(778)100 L (711)0(return n;)16(779 case Qtime:)100 L (712)0(780)100(if\(!iseve\(\)\))116 L (713 case Qzero:)0(781)100(error\(Eperm\);)124 L (714)0(memset\(buf, 0, n\);)16(782)100(return writetime\(a, n\);)116 L (715)0(return n;)16(783)100 L (716)0(784 case Qbintime:)100 L (717 default:)0(785)100(if\(!iseve\(\)\))116 L (718)0(print\("consread %lux\\n", c->qid.path\);)16(786)100(error\(Eperm\);)124 L (719)0(error\(Egreg\);)16(787)100(return writebintime\(a, n\);)116 L (720 })0(788)100 L (721 return -1;)0(/* never reached */)32(789 case Qkey:)100 L (722 })0(790)100(return keywrite\(a, n\);)116 L (723)0(791)100 L (724 static long)0(792 case Qhostowner:)100 L (725 conswrite\(Chan *c, void *va, long n, vlong off\))0(793)100(return hostownerwrite\(a, n\);)116 L (726 {)0(794)100 L (727 char buf[256];)0(795 case Qhostdomain:)100 L (728 long l, bp;)0(796)100(return hostdomainwrite\(a, n\);)116 L (729 char *a = va;)0(797)100 L (730 Mach *mp;)0(798 case Quser:)100 L (731 int id, fd;)0(799)100(return userwrite\(a, n\);)116 L (732 Chan *swc;)0(800)100 L (733 ulong offset = off;)0(801 case Qauth:)100 L (734)0(802)100(return authwrite\(c, a, n\);)116 L (735 switch\(c->qid.path\){)0(803)100 L (736 case Qcons:)0(804 case Qauthcheck:)100 L (737)0(/*)16(805)100(return authcheck\(c, a, n\);)116 L (738)0(* Can't page fault in putstrn, so copy the data locally.)17(806)100 L (739)0(*/)17(807 case Qauthent:)100 L (740)0(l = n;)16(808)100(return authentwrite\(c, a, n\);)116 L (741)0(while\(l > 0\){)16(809)100 L (742)0(bp = l;)24(810 case Qnull:)100 L (743)0(if\(bp > sizeof buf\))24(811)100(break;)116 L (744)0(bp = sizeof buf;)32(812)100 L (745)0(memmove\(buf, a, bp\);)24(813 case Qreboot:)100 L (746)0(putstrn0\(a, bp, 1\);)24(814)100(if\(!iseve\(\)\))116 L (747)0(a += bp;)24(815)100(error\(Eperm\);)124 L (748)0(l -= bp;)24(816)100(if\(strncmp\(a, "reboot", 6\) == 0\){)116 L cleartomark showpage saveobj restore %%EndPage: 20 20 %%Page: 21 21 /saveobj save def mark 21 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 7)l ()l ()l (817)0(print\("conswrite: reboot\\n"\);)24(885 setterm\(char *f\))100 L (818)0(exit\(0\);)24(886 {)100 L (819)0(})16(887 char buf[2*NAMELEN];)100 L (820)0(if\(strncmp\(a, "malloc", 6\) == 0\){)16(/* rsc bug */)56(888)100 L (821)0(a = malloc\(2\);)24(889 sprint\(buf, f, conffile\);)100 L (822)0(strcpy\(a, "hi"\);)24(890 ksetenv\("terminal", buf\);)100 L (823)0(free\(a\);)24(891 })100 L (824)0(a = malloc\(2\);)24(892)100 L (825)0(strcpy\(a, "helo"\);)24(893 Dev consdevtab = {)100 L (826)0(free\(a\);)24(894 'c',)100 L (827)0(panic\("not reached conswrite"\);)24(895 "cons",)100 L (828)0(})16(896)100 L (829)0(if\(strncmp\(a, "panic", 5\) == 0\))16(897 devreset,)100 L (830)0(panic\("/dev/reboot"\);)24(898 consinit,)100 L (831)0(break;)16(899 consattach,)100 L (832)0(900 devclone,)100 L (833 case Qsysstat:)0(901 conswalk,)100 L (834)0(for\(id = 0; id < 32; id++\) {)16(902 consstat,)100 L (835)0(if\(active.machs & \(1<cs = 0;)32(905 consclose,)100 L (838)0(mp->intr = 0;)32(906 consread,)100 L (839)0(mp->syscall = 0;)32(907 devbread,)100 L (840)0(mp->pfault = 0;)32(908 conswrite,)100 L (841)0(mp->tlbfault = 0;)32(909 devbwrite,)100 L (842)0(mp->tlbpurge = 0;)32(910 devremove,)100 L (843)0(})24(911 devwstat,)100 L (844)0(})16(912 };)100 L (845)0(break;)16(913)100 L (846)0(914 struct Rb)100 L (847 case Qswap:)0(915 {)100 L (848)0(if\(n >= sizeof buf\))16(916 QLock;)100 L (849)0(error\(Egreg\);)24(917 Rendez producer;)100 L (850)0(memmove\(buf, va, n\); /* so we can NUL-terminate */)16(918 Rendez consumer;)100 L (851)0(buf[n] = 0;)16(919 ulong randomcount;)100 L (852)0(/* start a pager if not already started */)16(920 uchar buf[1024];)100 L (853)0(if\(strncmp\(buf, "start", 5\) == 0\){)16(921 uchar *ep;)100 L (854)0(kickpager\(\);)24(922 uchar *rp;)100 L (855)0(break;)24(923 uchar *wp;)100 L (856)0(})16(924 uchar next;)100 L (857)0(if\(cpuserver && !iseve\(\)\))16(925 uchar wakeme;)100 L (858)0(error\(Eperm\);)24(926 ushort bits;)100 L (859)0(if\(buf[0]<'0' || '9'= NAMELEN\))16(937 nrand\(int n\))100 L (870)0(error\(Ebadarg\);)24(938 {)100 L (871)0(strncpy\(sysname, a, n\);)16(939 if\(rb.randn == 0\))100 L (872)0(sysname[n] = 0;)16(940)100(seedrand\(\);)116 L (873)0(if\(sysname[n-1] == '\\n'\))16(941 rb.randn = rb.randn*1103515245 + 12345 + MACHP\(0\)->ticks;)100 L (874)0(sysname[n-1] = 0;)24(942 return \(rb.randn>>16\) % n;)100 L (875)0(break;)16(943 })100 L (876)0(944)100 L (877 default:)0(945 int)100 L (878)0(print\("conswrite: %lud\\n", c->qid.path\);)16(946 rand\(void\))100 L (879)0(error\(Egreg\);)16(947 {)100 L (880 })0(948 nrand\(1\);)100 L (881 return n;)0(949 return rb.randn;)100 L (882 })0(950 })100 L (883)0(951)100 L (884 void)0(952)100 L cleartomark showpage saveobj restore %%EndPage: 21 21 %%Page: 22 22 /saveobj save def mark 22 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 8)l ()l ()l (953 static int)0(1021 /*)100 L (954 rbnotfull\(void*\))0(1022 * consume random bytes from a circular buffer)100 L (955 {)0(1023 */)100 L (956 int i;)0(1024 static ulong)100 L (957)0(1025 randomread\(void *xp, ulong n\))100 L (958 i = rb.rp - rb.wp;)0(1026 {)100 L (959 return i != 1 && i != \(1 - sizeof\(rb.buf\)\);)0(1027 uchar *e, *p;)100 L (960 })0(1028 ulong x;)100 L (961)0(1029)100 L (962 static int)0(1030 p = xp;)100 L (963 rbnotempty\(void*\))0(1031)100 L (964 {)0(1032 if\(waserror\(\)\){)100 L (965 return rb.wp != rb.rp;)0(1033)100(qunlock\(&rb\);)116 L (966 })0(1034)100(nexterror\(\);)116 L (967)0(1035 })100 L (968 void)0(1036)100 L (969 genrandom\(void*\))0(1037 qlock\(&rb\);)100 L (970 {)0(1038 for\(e = p + n; p < e; \){)100 L (971 up->basepri = PriNormal;)0(1039)100(if\(rb.wp == rb.rp\){)116 L (972 up->priority = up->basepri;)0(1040)100(rb.wakeme = 1;)124 L (973)0(1041)100(wakeup\(&rb.producer\);)124 L (974 for\(;;\){)0(1042)100(sleep\(&rb.consumer, rbnotempty, 0\);)124 L (975)0(for\(;;\))16(1043)100(rb.wakeme = 0;)124 L (976)0(if\(++rb.randomcount > 100000\))24(1044)100(continue;)124 L (977)0(break;)32(1045)100(})116 L (978)0(if\(anyhigher\(\)\))16(1046)100 L (979)0(sched\(\);)24(1047)100(/*)116 L (980)0(if\(!rbnotfull\(0\)\))16(1048)100(* beating clocks will be precictable if)117 L (981)0(sleep\(&rb.producer, rbnotfull, 0\);)24(1049)100(* they are synchronized. Use a cheap pseudo)117 L (982 })0(1050)100(* random number generator to obscure any cycles.)117 L (983 })0(1051)100(*/)117 L (984)0(1052)100(x = rb.randn*1103515245 ^ *rb.rp;)116 L (985 /*)0(1053)100(*p++ = rb.randn = x;)116 L (986 * produce random bits in a circular buffer)0(1054)100 L (987 */)0(1055)100(if\(rb.rp+1 == rb.ep\))116 L (988 static void)0(1056)100(rb.rp = rb.buf;)124 L (989 randomclock\(void\))0(1057)100(else)116 L (990 {)0(1058)100(rb.rp = rb.rp+1;)124 L (991 if\(rb.randomcount == 0 || !rbnotfull\(0\)\))0(1059 })100 L (992)0(return;)16(1060 qunlock\(&rb\);)100 L (993)0(1061 poperror\(\);)100 L (994 rb.bits = \(rb.bits<<2\) ^ rb.randomcount;)0(1062)100 L (995 rb.randomcount = 0;)0(1063 wakeup\(&rb.producer\);)100 L (996)0(1064)100 L (997 rb.next++;)0(1065 return n;)100 L (998 if\(rb.next != 8/2\))0(1066 })100 L (999)0(return;)16(1067)100 L (1000 rb.next = 0;)0(1068 static uvlong uvorder = 0x0001020304050607ULL;)100 L (1001)0(1069)100 L (1002 *rb.wp ^= rb.bits;)0(1070 static uchar*)100 L (1003 if\(rb.wp+1 == rb.ep\))0(1071 le2vlong\(vlong *to, uchar *f\))100 L (1004)0(rb.wp = rb.buf;)16(1072 {)100 L (1005 else)0(1073 uchar *t, *o;)100 L (1006)0(rb.wp = rb.wp+1;)16(1074 int i;)100 L (1007)0(1075)100 L (1008 if\(rb.wakeme\))0(1076 t = \(uchar*\)to;)100 L (1009)0(wakeup\(&rb.consumer\);)16(1077 o = \(uchar*\)&uvorder;)100 L (1010 })0(1078 for\(i = 0; i < sizeof\(vlong\); i++\))100 L (1011)0(1079)100(t[o[i]] = f[i];)116 L (1012 static void)0(1080 return f+sizeof\(vlong\);)100 L (1013 randominit\(void\))0(1081 })100 L (1014 {)0(1082)100 L (1015 addclock0link\(randomclock\);)0(1083 static uchar*)100 L (1016 rb.ep = rb.buf + sizeof\(rb.buf\);)0(1084 vlong2le\(uchar *t, vlong from\))100 L (1017 rb.rp = rb.wp = rb.buf;)0(1085 {)100 L (1018 kproc\("genrandom", genrandom, 0\);)0(1086 uchar *f, *o;)100 L (1019 })0(1087 int i;)100 L (1020)0(1088)100 L cleartomark showpage saveobj restore %%EndPage: 22 22 %%Page: 23 23 /saveobj save def mark 23 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 9)l ()l ()l (1089 f = \(uchar*\)&from;)0(1157 {)100 L (1090 o = \(uchar*\)&uvorder;)0(1158 char b[13];)100 L (1091 for\(i = 0; i < sizeof\(vlong\); i++\))0(1159 long i;)100 L (1092)0(t[i] = f[o[i]];)16(1160 vlong now;)100 L (1093 return t+sizeof\(vlong\);)0(1161)100 L (1094 })0(1162 if\(n >= sizeof\(b\)\))100 L (1095)0(1163)100(error\(Ebadtimectl\);)116 L (1096 static long order = 0x00010203;)0(1164 strncpy\(b, buf, n\);)100 L (1097)0(1165 b[n] = 0;)100 L (1098 static uchar*)0(1166 i = strtol\(b, 0, 0\);)100 L (1099 le2long\(long *to, uchar *f\))0(1167 if\(i <= 0\))100 L (1100 {)0(1168)100(error\(Ebadtimectl\);)116 L (1101 uchar *t, *o;)0(1169 now = i*1000000000LL;)100 L (1102 int i;)0(1170 todset\(now, 0, 0\);)100 L (1103)0(1171 return n;)100 L (1104 t = \(uchar*\)to;)0(1172 })100 L (1105 o = \(uchar*\)ℴ)0(1173)100 L (1106 for\(i = 0; i < sizeof\(long\); i++\))0(1174 /*)100 L (1107)0(t[o[i]] = f[i];)16(1175 * read binary time info. all numbers are little endian.)100 L (1108 return f+sizeof\(long\);)0(1176 * ticks and nsec are syncronized.)100 L (1109 })0(1177 */)100 L (1110)0(1178 static int)100 L (1111 static uchar*)0(1179 readbintime\(char *buf, int n\))100 L (1112 long2le\(uchar *t, long from\))0(1180 {)100 L (1113 {)0(1181 int i;)100 L (1114 uchar *f, *o;)0(1182 vlong nsec, ticks;)100 L (1115 int i;)0(1183 uchar *b = \(uchar*\)buf;)100 L (1116)0(1184)100 L (1117 f = \(uchar*\)&from;)0(1185 i = 0;)100 L (1118 o = \(uchar*\)ℴ)0(1186 if\(fasthz == 0LL\))100 L (1119 for\(i = 0; i < sizeof\(long\); i++\))0(1187)100(fastticks\(\(uvlong*\)&fasthz\);)116 L (1120)0(t[i] = f[o[i]];)16(1188 nsec = todget\(&ticks\);)100 L (1121 return t+sizeof\(long\);)0(1189 if\(n >= 3*sizeof\(uvlong\)\){)100 L (1122 })0(1190)100(vlong2le\(b+2*sizeof\(uvlong\), fasthz\);)116 L (1123)0(1191)100(i += sizeof\(uvlong\);)116 L (1124 char *Ebadtimectl = "bad time control";)0(1192 })100 L (1125)0(1193 if\(n >= 2*sizeof\(uvlong\)\){)100 L (1126 /*)0(1194)100(vlong2le\(b+sizeof\(uvlong\), ticks\);)116 L (1127 * like the old #c/time but with added info. Return)0(1195)100(i += sizeof\(uvlong\);)116 L (1128 *)0(1196 })100 L (1129 *)0(secs nanosecs)16(fastticks)40(fasthz)56(1197 if\(n >= 8\){)100 L (1130 */)0(1198)100(vlong2le\(b, nsec\);)116 L (1131 static int)0(1199)100(i += sizeof\(vlong\);)116 L (1132 readtime\(ulong off, char *buf, int n\))0(1200 })100 L (1133 {)0(1201 return i;)100 L (1134 vlong nsec, ticks;)0(1202 })100 L (1135 long sec;)0(1203)100 L (1136 char str[7*NUMSIZE+4]; // extra 4 bytes are null plus doprint)0(1204 /*)100 L (1137)0(// reserving space for a frigging UTF)32(1205 * set any of the following)100 L (1138)0(// char)32(1206 *)100(- time in nsec)116 L (1139)0(1207 *)100(- nsec trim applied over some seconds)116 L (1140 nsec = todget\(&ticks\);)0(1208 *)100(- clock frequency)116 L (1141 if\(fasthz == 0LL\))0(1209 */)100 L (1142)0(fastticks\(\(uvlong*\)&fasthz\);)16(1210 static int)100 L (1143 sec = nsec/1000000000ULL;)0(1211 writebintime\(char *buf, int n\))100 L (1144 snprint\(str, sizeof\(str\), "%*.0lud %*.0llud %*.0llud %*.0llud ",)0(1212 {)100 L (1145)0(NUMSIZE-1, sec,)16(1213 uchar *p;)100 L (1146)0(VLNUMSIZE-1, nsec,)16(1214 vlong delta;)100 L (1147)0(VLNUMSIZE-1, ticks,)16(1215 long period;)100 L (1148)0(VLNUMSIZE-1, fasthz\);)16(1216)100 L (1149 return readstr\(off, buf, n, str\);)0(1217 n--;)100 L (1150 })0(1218 p = \(uchar*\)buf + 1;)100 L (1151)0(1219 switch\(*buf\){)100 L (1152 /*)0(1220 case 'n':)100 L (1153 * set the time in seconds)0(1221)100(if\(n < sizeof\(vlong\)\))116 L (1154 */)0(1222)100(error\(Ebadtimectl\);)124 L (1155 static int)0(1223)100(le2vlong\(&delta, p\);)116 L (1156 writetime\(char *buf, int n\))0(1224)100(todset\(delta, 0, 0\);)116 L cleartomark showpage saveobj restore %%EndPage: 23 23 %%Page: 24 24 /saveobj save def mark 24 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 10)l ()l ()l (1225)0(break;)16 L (1226 case 'd':)l (1227)0(if\(n < sizeof\(vlong\)+sizeof\(long\)\))16 L (1228)0(error\(Ebadtimectl\);)24 L (1229)0(p = le2vlong\(&delta, p\);)16 L (1230)0(le2long\(&period, p\);)16 L (1231)0(todset\(-1, delta, period\);)16 L (1232)0(break;)16 L (1233 case 'f':)l (1234)0(if\(n < sizeof\(uvlong\)\))16 L (1235)0(error\(Ebadtimectl\);)24 L (1236)0(le2vlong\(&fasthz, p\);)16 L (1237)0(todsetfreq\(fasthz\);)16 L (1238)0(break;)16 L (1239 })l (1240 return n;)l (1241 })l cleartomark showpage saveobj restore %%EndPage: 24 24 %%Page: 25 25 /saveobj save def mark 25 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 1)l ()l ()l (1 #include "u.h")0(69 {)100 L (2 #include "../port/lib.h")0(70)100(Ether *ether;)108 L (3 #include "mem.h")0(71)100(ulong offset = off;)108 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(ether = etherxx[chan->dev];)108 L (6 #include "io.h")0(74)100(if\(\(chan->qid.path & CHDIR\) == 0 && ether->ifstat\){)108 L (7 #include "ureg.h")0(75)100(/*)116 L (8 #include "../port/error.h")0(76)100(* With some controllers it is necessary to reach)117 L (9 #include "../port/netif.h")0(77)100(* into the chip to extract statistics.)117 L (10)0(78)100(*/)117 L (11 #include "etherif.h")0(79)100(if\(NETTYPE\(chan->qid.path\) == Nifstatqid\))116 L (12)0(80)100(return ether->ifstat\(ether, buf, n, offset\);)124 L (13 static Ether *etherxx[MaxEther];)0(81)100(else if\(NETTYPE\(chan->qid.path\) == Nstatqid\))116 L (14)0(82)100(ether->ifstat\(ether, buf, 0, offset\);)124 L (15 Chan*)0(83)100(})108 L (16 etherattach\(char* spec\))0(84)100 L (17 {)0(85)100(return netifread\(ether, chan, buf, n, offset\);)108 L (18)0(ulong ctlrno;)8(86 })100 L (19)0(char *p;)8(87)100 L (20)0(Chan *chan;)8(88 static Block*)100 L (21)0(89 etherbread\(Chan* chan, long n, ulong offset\))100 L (22)0(ctlrno = 0;)8(90 {)100 L (23)0(if\(spec && *spec\){)8(91)100(return netifbread\(etherxx[chan->dev], chan, n, offset\);)108 L (24)0(ctlrno = strtoul\(spec, &p, 0\);)16(92 })100 L (25)0(if\(\(ctlrno == 0 && p == spec\) || *p || \(ctlrno >= MaxEther\)\))16(93)100 L (26)0(error\(Ebadarg\);)24(94 static void)100 L (27)0(})8(95 etherremove\(Chan*\))100 L (28)0(if\(etherxx[ctlrno] == 0\))8(96 {)100 L (29)0(error\(Enodev\);)16(97 })100 L (30)0(98)100 L (31)0(chan = devattach\('l', spec\);)8(99 static void)100 L (32)0(chan->dev = ctlrno;)8(100 etherwstat\(Chan* chan, char* dp\))100 L (33)0(if\(etherxx[ctlrno]->attach\))8(101 {)100 L (34)0(etherxx[ctlrno]->attach\(etherxx[ctlrno]\);)16(102 netifwstat\(etherxx[chan->dev], chan, dp\);)100 L (35)0(return chan;)8(103 })100 L (36 })0(104)100 L (37)0(105 static void)100 L (38 static int)0(106 etherrtrace\(Netfile* f, Etherpkt* pkt, int len\))100 L (39 etherwalk\(Chan* chan, char* name\))0(107 {)100 L (40 {)0(108 int i, n;)100 L (41)0(return netifwalk\(etherxx[chan->dev], chan, name\);)8(109 Block *bp;)100 L (42 })0(110)100 L (43)0(111 if\(qwindow\(f->in\) <= 0\))100 L (44 static void)0(112)100(return;)116 L (45 etherstat\(Chan* chan, char* dp\))0(113 if\(len > 64\))100 L (46 {)0(114)100(n = 64;)116 L (47)0(netifstat\(etherxx[chan->dev], chan, dp\);)8(115 else)100 L (48 })0(116)100(n = len;)116 L (49)0(117 bp = iallocb\(n\);)100 L (50 static Chan*)0(118 if\(bp == 0\))100 L (51 etheropen\(Chan* chan, int omode\))0(119)100(return;)116 L (52 {)0(120 memmove\(bp->wp, pkt->d, n\);)100 L (53)0(return netifopen\(etherxx[chan->dev], chan, omode\);)8(121 i = TK2MS\(MACHP\(0\)->ticks\);)100 L (54 })0(122 bp->wp[58] = len>>8;)100 L (55)0(123 bp->wp[59] = len;)100 L (56 static void)0(124 bp->wp[60] = i>>24;)100 L (57 ethercreate\(Chan*, char*, int, ulong\))0(125 bp->wp[61] = i>>16;)100 L (58 {)0(126 bp->wp[62] = i>>8;)100 L (59 })0(127 bp->wp[63] = i;)100 L (60)0(128 bp->wp += 64;)100 L (61 static void)0(129 qpass\(f->in, bp\);)100 L (62 etherclose\(Chan* chan\))0(130 })100 L (63 {)0(131)100 L (64)0(netifclose\(etherxx[chan->dev], chan\);)8(132 Block*)100 L (65 })0(133 etheriq\(Ether* ether, Block* bp, int fromwire\))100 L (66)0(134 {)100 L (67 static long)0(135 Etherpkt *pkt;)100 L (68 etherread\(Chan* chan, void* buf, long n, vlong off\))0(136 ushort type;)100 L cleartomark showpage saveobj restore %%EndPage: 25 25 %%Page: 26 26 /saveobj save def mark 26 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 2)l ()l ()l (137 int len, multi, tome, fromme;)0(205 })100 L (138 Netfile **ep, *f, **fp, *fx;)0(206)100 L (139 Block *xbp;)0(207 static int)100 L (140)0(208 etheroq\(Ether* ether, Block* bp\))100 L (141 ether->inpackets++;)0(209 {)100 L (142)0(210 int len, loopback, s;)100 L (143 pkt = \(Etherpkt*\)bp->rp;)0(211 Etherpkt *pkt;)100 L (144 len = BLEN\(bp\);)0(212)100 L (145 type = \(pkt->type[0]<<8\)|pkt->type[1];)0(213 ether->outpackets++;)100 L (146 fx = 0;)0(214)100 L (147 ep = ðer->f[Ntypes];)0(215 /*)100 L (148)0(216)100(* Check if the packet has to be placed back onto the input queue,)109 L (149 multi = pkt->d[0] & 1;)0(217)100(* i.e. if it's a loopback or broadcast packet or the interface is)109 L (150 /* check for valid multcast addresses */)0(218)100(* in promiscuous mode.)109 L (151 if\(multi && memcmp\(pkt->d, ether->bcast, sizeof\(pkt->d\)\) && ether->prom == 0\){)0(219)100(* If it's a loopback packet indicate to etheriq that the data isn't)109 L (152)0(if\(!activemulti\(ether, pkt->d, sizeof\(pkt->d\)\)\){)16(220)100(* needed and return, etheriq will pass-on or free the block.)109 L (153)0(if\(fromwire\){)24(221)100(* To enable bridging to work, only packets that were originated)109 L (154)0(freeb\(bp\);)32(222)100(* by this interface are fed back.)109 L (155)0(bp = 0;)32(223)100(*/)109 L (156)0(})24(224 pkt = \(Etherpkt*\)bp->rp;)100 L (157)0(return bp;)24(225 len = BLEN\(bp\);)100 L (158)0(})16(226 loopback = memcmp\(pkt->d, ether->ea, sizeof\(pkt->d\)\) == 0;)100 L (159 })0(227 if\(loopback || memcmp\(pkt->d, ether->bcast, sizeof\(pkt->d\)\) == 0 || ether->prom\){)100 L (160)0(228)100(s = splhi\(\);)116 L (161 /* is it for me? */)0(229)100(etheriq\(ether, bp, 0\);)116 L (162 tome = memcmp\(pkt->d, ether->ea, sizeof\(pkt->d\)\) == 0;)0(230)100(splx\(s\);)116 L (163 fromme = memcmp\(pkt->s, ether->ea, sizeof\(pkt->s\)\) == 0;)0(231 })100 L (164)0(232)100 L (165 /*)0(233 if\(!loopback\){)100 L (166)0(* Multiplex the packet to all the connections which want it.)9(234)100(qbwrite\(ether->oq, bp\);)116 L (167)0(* If the packet is not to be used subsequently \(fromwire != 0\),)9(235)100(ether->transmit\(ether\);)116 L (168)0(* attempt to simply pass it into one of the connections, thereby)9(236 } else)100 L (169)0(* saving a copy of the data \(usual case hopefully\).)9(237)100(freeb\(bp\);)116 L (170)0(*/)9(238)100 L (171 for\(fp = ether->f; fp < ep; fp++\){)0(239 return len;)100 L (172)0(if\(f = *fp\))16(240 })100 L (173)0(if\(f->type == type || f->type < 0\))16(241)100 L (174)0(if\(tome || multi || f->prom\){)16(242 static long)100 L (175)0(/* Don't want to hear bridged packets */)24(243 etherwrite\(Chan* chan, void* buf, long n, vlong\))100 L (176)0(if\(f->bridge && !fromwire && !fromme\))24(244 {)100 L (177)0(continue;)32(245 Ether *ether;)100 L (178)0(if\(!f->headersonly\){)24(246 Block *bp;)100 L (179)0(if\(fromwire && fx == 0\))32(247)100 L (180)0(fx = f;)40(248 ether = etherxx[chan->dev];)100 L (181)0(else if\(xbp = iallocb\(len\)\){)32(249 if\(NETTYPE\(chan->qid.path\) != Ndataqid\))100 L (182)0(memmove\(xbp->wp, pkt, len\);)40(250)100(return netifwrite\(ether, chan, buf, n\);)116 L (183)0(xbp->wp += len;)40(251)100 L (184)0(qpass\(f->in, xbp\);)40(252 if\(n > ETHERMAXTU\))100 L (185)0(})32(253)100(error\(Etoobig\);)116 L (186)0(else)32(254 if\(n < ETHERMINTU\))100 L (187)0(ether->soverflows++;)40(255)100(error\(Etoosmall\);)116 L (188)0(})24(256)100 L (189)0(else)24(257 bp = allocb\(n\);)100 L (190)0(etherrtrace\(f, pkt, len\);)32(258 if\(waserror\(\)\){)100 L (191)0(})16(259)100(freeb\(bp\);)116 L (192 })0(260)100(nexterror\(\);)116 L (193)0(261 })100 L (194 if\(fx\){)0(262 memmove\(bp->rp, buf, n\);)100 L (195)0(if\(qpass\(fx->in, bp\) < 0\))16(263 memmove\(bp->rp+Eaddrlen, ether->ea, Eaddrlen\);)100 L (196)0(ether->soverflows++;)24(264 poperror\(\);)100 L (197)0(return 0;)16(265 bp->wp += n;)100 L (198 })0(266)100 L (199 if\(fromwire\){)0(267 return etheroq\(ether, bp\);)100 L (200)0(freeb\(bp\);)16(268 })100 L (201)0(return 0;)16(269)100 L (202 })0(270 static long)100 L (203)0(271 etherbwrite\(Chan* chan, Block* bp, ulong\))100 L (204 return bp;)0(272 {)100 L cleartomark showpage saveobj restore %%EndPage: 26 26 %%Page: 27 27 /saveobj save def mark 27 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 3)l ()l ()l (273 Ether *ether;)0(341 char name[NAMELEN], buf[128];)100 L (274 long n;)0(342)100 L (275)0(343 for\(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++\){)100 L (276 n = BLEN\(bp\);)0(344)100(if\(ether == 0\))116 L (277 ether = etherxx[chan->dev];)0(345)100(ether = malloc\(sizeof\(Ether\)\);)124 L (278 if\(NETTYPE\(chan->qid.path\) != Ndataqid\){)0(346)100(memset\(ether, 0, sizeof\(Ether\)\);)116 L (279)0(n = netifwrite\(ether, chan, bp->rp, n\);)16(347)100(ether->ctlrno = ctlrno;)116 L (280)0(freeb\(bp\);)16(348)100(ether->tbdf = BUSUNKNOWN;)116 L (281)0(return n;)16(349)100(ether->mbps = 10;)116 L (282 })0(350)100(if\(isaconfig\("ether", ctlrno, ether\) == 0\))116 L (283)0(351)100(continue;)124 L (284 if\(n > ETHERMAXTU\){)0(352)100(for\(n = 0; cards[n].type; n++\){)116 L (285)0(freeb\(bp\);)16(353)100(if\(cistrcmp\(cards[n].type, ether->type\)\))124 L (286)0(error\(Ebadarg\);)16(354)100(continue;)132 L (287 })0(355)100(for\(i = 0; i < ether->nopt; i++\){)124 L (288 if\(n < ETHERMINTU\){)0(356)100(if\(strncmp\(ether->opt[i], "ea=", 3\)\))132 L (289)0(freeb\(bp\);)16(357)100(continue;)140 L (290)0(error\(Etoosmall\);)16(358)100(if\(parseether\(ether->ea, ðer->opt[i][3]\) == -1\))132 L (291 })0(359)100(memset\(ether->ea, 0, Eaddrlen\);)140 L (292)0(360)100(})124 L (293 return etheroq\(ether, bp\);)0(361)100(if\(cards[n].reset\(ether\)\))124 L (294 })0(362)100(break;)132 L (295)0(363)100 L (296 static struct {)0(364)100(/*)124 L (297 char* type;)0(365)100(* IRQ2 doesn't really exist, it's used to gang the interrupt)125 L (298 int \(*reset\)\(Ether*\);)0(366)100(* controllers together. A device set to IRQ2 will appear on)125 L (299 } cards[MaxEther+1];)0(367)100(* the second interrupt controller as IRQ9.)125 L (300)0(368)100(*/)125 L (301 void)0(369)100(if\(ether->irq == 2\))124 L (302 addethercard\(char* t, int \(*r\)\(Ether*\)\))0(370)100(ether->irq = 9;)132 L (303 {)0(371)100(snprint\(name, sizeof\(name\), "ether%d", ctlrno\);)124 L (304 static int ncard;)0(372)100(intrenable\(ether->irq, ether->interrupt, ether, ether->tbdf, name\);)124 L (305)0(373)100 L (306 if\(ncard == MaxEther\))0(374)100(i = sprint\(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",)124 L (307)0(panic\("too many ether cards"\);)16(375)100(ctlrno, ether->type, ether->mbps, ether->port, ether->irq\);)132 L (308 cards[ncard].type = t;)0(376)100(if\(ether->mem\))124 L (309 cards[ncard].reset = r;)0(377)100(i += sprint\(buf+i, " addr 0x%luX", PADDR\(ether->mem\)\);)132 L (310 ncard++;)0(378)100(if\(ether->size\))124 L (311 })0(379)100(i += sprint\(buf+i, " size 0x%luX", ether->size\);)132 L (312)0(380)100(i += sprint\(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",)124 L (313 int)0(381)100(ether->ea[0], ether->ea[1], ether->ea[2],)132 L (314 parseether\(uchar *to, char *from\))0(382)100(ether->ea[3], ether->ea[4], ether->ea[5]\);)132 L (315 {)0(383)100(sprint\(buf+i, "\\n"\);)124 L (316 char nip[4];)0(384)100(print\(buf\);)124 L (317 char *p;)0(385)100 L (318 int i;)0(386)100(if\(ether->mbps == 100\){)124 L (319)0(387)100(netifinit\(ether, name, Ntypes, 256*1024\);)132 L (320 p = from;)0(388)100(if\(ether->oq == 0\))132 L (321 for\(i = 0; i < 6; i++\){)0(389)100(ether->oq = qopen\(256*1024, 1, 0, 0\);)140 L (322)0(if\(*p == 0\))16(390)100(})124 L (323)0(return -1;)24(391)100(else{)124 L (324)0(nip[0] = *p++;)16(392)100(netifinit\(ether, name, Ntypes, 65*1024\);)132 L (325)0(if\(*p == 0\))16(393)100(if\(ether->oq == 0\))132 L (326)0(return -1;)24(394)100(ether->oq = qopen\(65*1024, 1, 0, 0\);)140 L (327)0(nip[1] = *p++;)16(395)100(})124 L (328)0(nip[2] = 0;)16(396)100(if\(ether->oq == 0\))124 L (329)0(to[i] = strtoul\(nip, 0, 16\);)16(397)100(panic\("etherreset %s", name\);)132 L (330)0(if\(*p == ':'\))16(398)100(ether->alen = Eaddrlen;)124 L (331)0(p++;)24(399)100(memmove\(ether->addr, ether->ea, Eaddrlen\);)124 L (332 })0(400)100(memset\(ether->bcast, 0xFF, Eaddrlen\);)124 L (333 return 0;)0(401)100 L (334 })0(402)100(etherxx[ctlrno] = ether;)124 L (335)0(403)100(ether = 0;)124 L (336 static void)0(404)100(break;)124 L (337 etherreset\(void\))0(405)100(})116 L (338 {)0(406 })100 L (339 Ether *ether;)0(407 if\(ether\))100 L (340 int i, n, ctlrno;)0(408)100(free\(ether\);)116 L cleartomark showpage saveobj restore %%EndPage: 27 27 %%Page: 28 28 /saveobj save def mark 28 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 4)l ()l ()l (409 })l (410)l (411 #define POLY 0xedb88320)l (412)l (413 /* really slow 32 bit crc for ethers */)l (414 ulong)l (415 ethercrc\(uchar *p, int len\))l (416 {)l (417 int i, j;)l (418 ulong crc, b;)l (419)l (420 crc = 0xffffffff;)l (421 for\(i = 0; i < len; i++\){)l (422)0(b = *p++;)16 L (423)0(for\(j = 0; j < 8; j++\){)16 L (424)0(crc = \(crc>>1\) ^ \(\(\(crc^b\) & 1\) ? POLY : 0\);)24 L (425)0(b >>= 1;)24 L (426)0(})16 L (427 })l (428 return crc;)l (429 })l (430)l (431 Dev etherdevtab = {)l (432 'l',)l (433 "ether",)l (434)l (435 etherreset,)l (436 devinit,)l (437 etherattach,)l (438 devclone,)l (439 etherwalk,)l (440 etherstat,)l (441 etheropen,)l (442 ethercreate,)l (443 etherclose,)l (444 etherread,)l (445 etherbread,)l (446 etherwrite,)l (447 etherbwrite,)l (448 etherremove,)l (449 etherwstat,)l (450 };)l cleartomark showpage saveobj restore %%EndPage: 28 28 %%Page: 29 29 /saveobj save def mark 29 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 1)l ()l ()l (1 #include "u.h")0(69 {)100 L (2 #include "../port/lib.h")0(70)100(Ether *ether;)108 L (3 #include "mem.h")0(71)100(ulong offset = off;)108 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(ether = etherxx[chan->dev];)108 L (6 #include "io.h")0(74)100(if\(\(chan->qid.path & CHDIR\) == 0 && ether->ifstat\){)108 L (7 #include "ureg.h")0(75)100(/*)116 L (8 #include "../port/error.h")0(76)100(* With some controllers it is necessary to reach)117 L (9 #include "../port/netif.h")0(77)100(* into the chip to extract statistics.)117 L (10)0(78)100(*/)117 L (11 #include "etherif.h")0(79)100(if\(NETTYPE\(chan->qid.path\) == Nifstatqid\))116 L (12)0(80)100(return ether->ifstat\(ether, buf, n, offset\);)124 L (13 static Ether *etherxx[MaxEther];)0(81)100(else if\(NETTYPE\(chan->qid.path\) == Nstatqid\))116 L (14)0(82)100(ether->ifstat\(ether, buf, 0, offset\);)124 L (15 Chan*)0(83)100(})108 L (16 etherattach\(char* spec\))0(84)100 L (17 {)0(85)100(return netifread\(ether, chan, buf, n, offset\);)108 L (18)0(ulong ctlrno;)8(86 })100 L (19)0(char *p;)8(87)100 L (20)0(Chan *chan;)8(88 static Block*)100 L (21)0(89 etherbread\(Chan* chan, long n, ulong offset\))100 L (22)0(ctlrno = 0;)8(90 {)100 L (23)0(if\(spec && *spec\){)8(91)100(return netifbread\(etherxx[chan->dev], chan, n, offset\);)108 L (24)0(ctlrno = strtoul\(spec, &p, 0\);)16(92 })100 L (25)0(if\(\(ctlrno == 0 && p == spec\) || *p || \(ctlrno >= MaxEther\)\))16(93)100 L (26)0(error\(Ebadarg\);)24(94 static void)100 L (27)0(})8(95 etherremove\(Chan*\))100 L (28)0(if\(etherxx[ctlrno] == 0\))8(96 {)100 L (29)0(error\(Enodev\);)16(97 })100 L (30)0(98)100 L (31)0(chan = devattach\('l', spec\);)8(99 static void)100 L (32)0(chan->dev = ctlrno;)8(100 etherwstat\(Chan* chan, char* dp\))100 L (33)0(if\(etherxx[ctlrno]->attach\))8(101 {)100 L (34)0(etherxx[ctlrno]->attach\(etherxx[ctlrno]\);)16(102 netifwstat\(etherxx[chan->dev], chan, dp\);)100 L (35)0(return chan;)8(103 })100 L (36 })0(104)100 L (37)0(105 static void)100 L (38 static int)0(106 etherrtrace\(Netfile* f, Etherpkt* pkt, int len\))100 L (39 etherwalk\(Chan* chan, char* name\))0(107 {)100 L (40 {)0(108 int i, n;)100 L (41)0(return netifwalk\(etherxx[chan->dev], chan, name\);)8(109 Block *bp;)100 L (42 })0(110)100 L (43)0(111 if\(qwindow\(f->in\) <= 0\))100 L (44 static void)0(112)100(return;)116 L (45 etherstat\(Chan* chan, char* dp\))0(113 if\(len > 64\))100 L (46 {)0(114)100(n = 64;)116 L (47)0(netifstat\(etherxx[chan->dev], chan, dp\);)8(115 else)100 L (48 })0(116)100(n = len;)116 L (49)0(117 bp = iallocb\(n\);)100 L (50 static Chan*)0(118 if\(bp == 0\))100 L (51 etheropen\(Chan* chan, int omode\))0(119)100(return;)116 L (52 {)0(120 memmove\(bp->wp, pkt->d, n\);)100 L (53)0(return netifopen\(etherxx[chan->dev], chan, omode\);)8(121 i = TK2MS\(MACHP\(0\)->ticks\);)100 L (54 })0(122 bp->wp[58] = len>>8;)100 L (55)0(123 bp->wp[59] = len;)100 L (56 static void)0(124 bp->wp[60] = i>>24;)100 L (57 ethercreate\(Chan*, char*, int, ulong\))0(125 bp->wp[61] = i>>16;)100 L (58 {)0(126 bp->wp[62] = i>>8;)100 L (59 })0(127 bp->wp[63] = i;)100 L (60)0(128 bp->wp += 64;)100 L (61 static void)0(129 qpass\(f->in, bp\);)100 L (62 etherclose\(Chan* chan\))0(130 })100 L (63 {)0(131)100 L (64)0(netifclose\(etherxx[chan->dev], chan\);)8(132 Block*)100 L (65 })0(133 etheriq\(Ether* ether, Block* bp, int fromwire\))100 L (66)0(134 {)100 L (67 static long)0(135 Etherpkt *pkt;)100 L (68 etherread\(Chan* chan, void* buf, long n, vlong off\))0(136 ushort type;)100 L cleartomark showpage saveobj restore %%EndPage: 29 29 %%Page: 30 30 /saveobj save def mark 30 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 2)l ()l ()l (137 int len, multi, tome, fromme;)0(205 })100 L (138 Netfile **ep, *f, **fp, *fx;)0(206)100 L (139 Block *xbp;)0(207 static int)100 L (140)0(208 etheroq\(Ether* ether, Block* bp\))100 L (141 ether->inpackets++;)0(209 {)100 L (142)0(210 int len, loopback, s;)100 L (143 pkt = \(Etherpkt*\)bp->rp;)0(211 Etherpkt *pkt;)100 L (144 len = BLEN\(bp\);)0(212)100 L (145 type = \(pkt->type[0]<<8\)|pkt->type[1];)0(213 ether->outpackets++;)100 L (146 fx = 0;)0(214)100 L (147 ep = ðer->f[Ntypes];)0(215 /*)100 L (148)0(216)100(* Check if the packet has to be placed back onto the input queue,)109 L (149 multi = pkt->d[0] & 1;)0(217)100(* i.e. if it's a loopback or broadcast packet or the interface is)109 L (150 /* check for valid multcast addresses */)0(218)100(* in promiscuous mode.)109 L (151 if\(multi && memcmp\(pkt->d, ether->bcast, sizeof\(pkt->d\)\) && ether->prom == 0\){)0(219)100(* If it's a loopback packet indicate to etheriq that the data isn't)109 L (152)0(if\(!activemulti\(ether, pkt->d, sizeof\(pkt->d\)\)\){)16(220)100(* needed and return, etheriq will pass-on or free the block.)109 L (153)0(if\(fromwire\){)24(221)100(* To enable bridging to work, only packets that were originated)109 L (154)0(freeb\(bp\);)32(222)100(* by this interface are fed back.)109 L (155)0(bp = 0;)32(223)100(*/)109 L (156)0(})24(224 pkt = \(Etherpkt*\)bp->rp;)100 L (157)0(return bp;)24(225 len = BLEN\(bp\);)100 L (158)0(})16(226 loopback = memcmp\(pkt->d, ether->ea, sizeof\(pkt->d\)\) == 0;)100 L (159 })0(227 if\(loopback || memcmp\(pkt->d, ether->bcast, sizeof\(pkt->d\)\) == 0 || ether->prom\){)100 L (160)0(228)100(s = splhi\(\);)116 L (161 /* is it for me? */)0(229)100(etheriq\(ether, bp, 0\);)116 L (162 tome = memcmp\(pkt->d, ether->ea, sizeof\(pkt->d\)\) == 0;)0(230)100(splx\(s\);)116 L (163 fromme = memcmp\(pkt->s, ether->ea, sizeof\(pkt->s\)\) == 0;)0(231 })100 L (164)0(232)100 L (165 /*)0(233 if\(!loopback\){)100 L (166)0(* Multiplex the packet to all the connections which want it.)9(234)100(qbwrite\(ether->oq, bp\);)116 L (167)0(* If the packet is not to be used subsequently \(fromwire != 0\),)9(235)100(ether->transmit\(ether\);)116 L (168)0(* attempt to simply pass it into one of the connections, thereby)9(236 } else)100 L (169)0(* saving a copy of the data \(usual case hopefully\).)9(237)100(freeb\(bp\);)116 L (170)0(*/)9(238)100 L (171 for\(fp = ether->f; fp < ep; fp++\){)0(239 return len;)100 L (172)0(if\(f = *fp\))16(240 })100 L (173)0(if\(f->type == type || f->type < 0\))16(241)100 L (174)0(if\(tome || multi || f->prom\){)16(242 static long)100 L (175)0(/* Don't want to hear bridged packets */)24(243 etherwrite\(Chan* chan, void* buf, long n, vlong\))100 L (176)0(if\(f->bridge && !fromwire && !fromme\))24(244 {)100 L (177)0(continue;)32(245 Ether *ether;)100 L (178)0(if\(!f->headersonly\){)24(246 Block *bp;)100 L (179)0(if\(fromwire && fx == 0\))32(247)100 L (180)0(fx = f;)40(248 ether = etherxx[chan->dev];)100 L (181)0(else if\(xbp = iallocb\(len\)\){)32(249 if\(NETTYPE\(chan->qid.path\) != Ndataqid\))100 L (182)0(memmove\(xbp->wp, pkt, len\);)40(250)100(return netifwrite\(ether, chan, buf, n\);)116 L (183)0(xbp->wp += len;)40(251)100 L (184)0(qpass\(f->in, xbp\);)40(252 if\(n > ETHERMAXTU\))100 L (185)0(})32(253)100(error\(Etoobig\);)116 L (186)0(else)32(254 if\(n < ETHERMINTU\))100 L (187)0(ether->soverflows++;)40(255)100(error\(Etoosmall\);)116 L (188)0(})24(256)100 L (189)0(else)24(257 bp = allocb\(n\);)100 L (190)0(etherrtrace\(f, pkt, len\);)32(258 if\(waserror\(\)\){)100 L (191)0(})16(259)100(freeb\(bp\);)116 L (192 })0(260)100(nexterror\(\);)116 L (193)0(261 })100 L (194 if\(fx\){)0(262 memmove\(bp->rp, buf, n\);)100 L (195)0(if\(qpass\(fx->in, bp\) < 0\))16(263 memmove\(bp->rp+Eaddrlen, ether->ea, Eaddrlen\);)100 L (196)0(ether->soverflows++;)24(264 poperror\(\);)100 L (197)0(return 0;)16(265 bp->wp += n;)100 L (198 })0(266)100 L (199 if\(fromwire\){)0(267 return etheroq\(ether, bp\);)100 L (200)0(freeb\(bp\);)16(268 })100 L (201)0(return 0;)16(269)100 L (202 })0(270 static long)100 L (203)0(271 etherbwrite\(Chan* chan, Block* bp, ulong\))100 L (204 return bp;)0(272 {)100 L cleartomark showpage saveobj restore %%EndPage: 30 30 %%Page: 31 31 /saveobj save def mark 31 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 3)l ()l ()l (273 Ether *ether;)0(341 char name[NAMELEN], buf[128];)100 L (274 long n;)0(342)100 L (275)0(343 for\(ether = 0, ctlrno = 0; ctlrno < MaxEther; ctlrno++\){)100 L (276 n = BLEN\(bp\);)0(344)100(if\(ether == 0\))116 L (277 ether = etherxx[chan->dev];)0(345)100(ether = malloc\(sizeof\(Ether\)\);)124 L (278 if\(NETTYPE\(chan->qid.path\) != Ndataqid\){)0(346)100(memset\(ether, 0, sizeof\(Ether\)\);)116 L (279)0(n = netifwrite\(ether, chan, bp->rp, n\);)16(347)100(ether->ctlrno = ctlrno;)116 L (280)0(freeb\(bp\);)16(348)100(ether->tbdf = BUSUNKNOWN;)116 L (281)0(return n;)16(349)100(ether->mbps = 10;)116 L (282 })0(350)100(if\(isaconfig\("ether", ctlrno, ether\) == 0\))116 L (283)0(351)100(continue;)124 L (284 if\(n > ETHERMAXTU\){)0(352)100(for\(n = 0; cards[n].type; n++\){)116 L (285)0(freeb\(bp\);)16(353)100(if\(cistrcmp\(cards[n].type, ether->type\)\))124 L (286)0(error\(Ebadarg\);)16(354)100(continue;)132 L (287 })0(355)100(for\(i = 0; i < ether->nopt; i++\){)124 L (288 if\(n < ETHERMINTU\){)0(356)100(if\(strncmp\(ether->opt[i], "ea=", 3\)\))132 L (289)0(freeb\(bp\);)16(357)100(continue;)140 L (290)0(error\(Etoosmall\);)16(358)100(if\(parseether\(ether->ea, ðer->opt[i][3]\) == -1\))132 L (291 })0(359)100(memset\(ether->ea, 0, Eaddrlen\);)140 L (292)0(360)100(})124 L (293 return etheroq\(ether, bp\);)0(361)100(if\(cards[n].reset\(ether\)\))124 L (294 })0(362)100(break;)132 L (295)0(363)100 L (296 static struct {)0(364)100(/*)124 L (297 char* type;)0(365)100(* IRQ2 doesn't really exist, it's used to gang the interrupt)125 L (298 int \(*reset\)\(Ether*\);)0(366)100(* controllers together. A device set to IRQ2 will appear on)125 L (299 } cards[MaxEther+1];)0(367)100(* the second interrupt controller as IRQ9.)125 L (300)0(368)100(*/)125 L (301 void)0(369)100(if\(ether->irq == 2\))124 L (302 addethercard\(char* t, int \(*r\)\(Ether*\)\))0(370)100(ether->irq = 9;)132 L (303 {)0(371)100(snprint\(name, sizeof\(name\), "ether%d", ctlrno\);)124 L (304 static int ncard;)0(372)100(intrenable\(ether->irq, ether->interrupt, ether, ether->tbdf, name\);)124 L (305)0(373)100 L (306 if\(ncard == MaxEther\))0(374)100(i = sprint\(buf, "#l%d: %s: %dMbps port 0x%luX irq %lud",)124 L (307)0(panic\("too many ether cards"\);)16(375)100(ctlrno, ether->type, ether->mbps, ether->port, ether->irq\);)132 L (308 cards[ncard].type = t;)0(376)100(if\(ether->mem\))124 L (309 cards[ncard].reset = r;)0(377)100(i += sprint\(buf+i, " addr 0x%luX", PADDR\(ether->mem\)\);)132 L (310 ncard++;)0(378)100(if\(ether->size\))124 L (311 })0(379)100(i += sprint\(buf+i, " size 0x%luX", ether->size\);)132 L (312)0(380)100(i += sprint\(buf+i, ": %2.2uX%2.2uX%2.2uX%2.2uX%2.2uX%2.2uX",)124 L (313 int)0(381)100(ether->ea[0], ether->ea[1], ether->ea[2],)132 L (314 parseether\(uchar *to, char *from\))0(382)100(ether->ea[3], ether->ea[4], ether->ea[5]\);)132 L (315 {)0(383)100(sprint\(buf+i, "\\n"\);)124 L (316 char nip[4];)0(384)100(print\(buf\);)124 L (317 char *p;)0(385)100 L (318 int i;)0(386)100(if\(ether->mbps == 100\){)124 L (319)0(387)100(netifinit\(ether, name, Ntypes, 256*1024\);)132 L (320 p = from;)0(388)100(if\(ether->oq == 0\))132 L (321 for\(i = 0; i < 6; i++\){)0(389)100(ether->oq = qopen\(256*1024, 1, 0, 0\);)140 L (322)0(if\(*p == 0\))16(390)100(})124 L (323)0(return -1;)24(391)100(else{)124 L (324)0(nip[0] = *p++;)16(392)100(netifinit\(ether, name, Ntypes, 65*1024\);)132 L (325)0(if\(*p == 0\))16(393)100(if\(ether->oq == 0\))132 L (326)0(return -1;)24(394)100(ether->oq = qopen\(65*1024, 1, 0, 0\);)140 L (327)0(nip[1] = *p++;)16(395)100(})124 L (328)0(nip[2] = 0;)16(396)100(if\(ether->oq == 0\))124 L (329)0(to[i] = strtoul\(nip, 0, 16\);)16(397)100(panic\("etherreset %s", name\);)132 L (330)0(if\(*p == ':'\))16(398)100(ether->alen = Eaddrlen;)124 L (331)0(p++;)24(399)100(memmove\(ether->addr, ether->ea, Eaddrlen\);)124 L (332 })0(400)100(memset\(ether->bcast, 0xFF, Eaddrlen\);)124 L (333 return 0;)0(401)100 L (334 })0(402)100(etherxx[ctlrno] = ether;)124 L (335)0(403)100(ether = 0;)124 L (336 static void)0(404)100(break;)124 L (337 etherreset\(void\))0(405)100(})116 L (338 {)0(406 })100 L (339 Ether *ether;)0(407 if\(ether\))100 L (340 int i, n, ctlrno;)0(408)100(free\(ether\);)116 L cleartomark showpage saveobj restore %%EndPage: 31 31 %%Page: 32 32 /saveobj save def mark 32 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devether.c Page 4)l ()l ()l (409 })l (410)l (411 #define POLY 0xedb88320)l (412)l (413 /* really slow 32 bit crc for ethers */)l (414 ulong)l (415 ethercrc\(uchar *p, int len\))l (416 {)l (417 int i, j;)l (418 ulong crc, b;)l (419)l (420 crc = 0xffffffff;)l (421 for\(i = 0; i < len; i++\){)l (422)0(b = *p++;)16 L (423)0(for\(j = 0; j < 8; j++\){)16 L (424)0(crc = \(crc>>1\) ^ \(\(\(crc^b\) & 1\) ? POLY : 0\);)24 L (425)0(b >>= 1;)24 L (426)0(})16 L (427 })l (428 return crc;)l (429 })l (430)l (431 Dev etherdevtab = {)l (432 'l',)l (433 "ether",)l (434)l (435 etherreset,)l (436 devinit,)l (437 etherattach,)l (438 devclone,)l (439 etherwalk,)l (440 etherstat,)l (441 etheropen,)l (442 ethercreate,)l (443 etherclose,)l (444 etherread,)l (445 etherbread,)l (446 etherwrite,)l (447 etherbwrite,)l (448 etherremove,)l (449 etherwstat,)l (450 };)l cleartomark showpage saveobj restore %%EndPage: 32 32 %%Page: 33 33 /saveobj save def mark 33 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 1)l ()l ()l (1 #include "u.h")0(69 * - index for b2c is is \(bytes per sector/128\).)100 L (2 #include "../port/lib.h")0(70 * - index for c2b is code from b2c)100 L (3 #include "mem.h")0(71 */)100 L (4 #include "dat.h")0(72 static int b2c[] =)100 L (5 #include "fns.h")0(73 {)100 L (6 #include "io.h")0(74 [1])100(0,)116 L (7 #include "../port/error.h")0(75 [2])100(1,)116 L (8)0(76 [4])100(2,)116 L (9 #include "floppy.h")0(77 [8])100(3,)116 L (10)0(78 };)100 L (11 /* Intel 82077A \(8272A compatible\) floppy controller */)0(79 static int c2b[] =)100 L (12)0(80 {)100 L (13 /* This module expects the following functions to be defined)0(81)100(128,)108 L (14 * elsewhere:)0(82)100(256,)108 L (15 *)0(83)100(512,)108 L (16 * inb\(\))0(84)100(1024,)108 L (17 * outb\(\))0(85 };)100 L (18 * floppyexec\(\))0(86)100 L (19 * floppyeject\(\))0(87 FController)100(fl;)124 L (20 * floppysetup0\(\))0(88)100 L (21 * floppysetup1\(\))0(89 #define MOTORBIT\(i\))100(\(1<<\(\(i\)+4\)\))132 L (22 * dmainit\(\))0(90)100 L (23 * dmasetup\(\))0(91 /*)100 L (24 * dmaend\(\))0(92 * predeclared)100 L (25 *)0(93 */)100 L (26 * On DMA systems, floppyexec\(\) should be an empty function;)0(94 static int)100(cmddone\(void*\);)124 L (27 * on non-DMA systems, dmaend\(\) should be an empty function;)0(95 static void)100(floppyformat\(FDrive*, char*\);)124 L (28 * dmasetup\(\) may enforce maximum transfer sizes.)0(96 static void)100(floppykproc\(void*\);)124 L (29 */)0(97 static void)100(floppypos\(FDrive*,long\);)124 L (30)0(98 static int)100(floppyrecal\(FDrive*\);)124 L (31 enum {)0(99 static int)100(floppyresult\(void\);)124 L (32)0(/* file types */)8(100 static void)100(floppyrevive\(void\);)124 L (33)0(Qdir=)8(0,)24(101 static long)100(floppyseek\(FDrive*, long\);)124 L (34)0(Qdata=)8(\(1<<2\),)24(102 static int)100(floppysense\(void\);)124 L (35)0(Qctl=)8(\(2<<2\),)24(103 static void)100(floppywait\(void\);)124 L (36)0(Qmask=)8(\(3<<2\),)24(104 static long)100(floppyxfer\(FDrive*, int, void*, long, long\);)124 L (37)0(105)100 L (38)0(DMAchan=)8(2,)24(/* floppy dma channel */)32(106 Dirtab floppydir[]={)100 L (39 };)0(107 "fd0disk",)100({Qdata + 0}, 0,)132(0660,)156 L (40)0(108 "fd0ctl",)100({Qctl + 0}, 0,)132(0660,)156 L (41 #define DPRINT if\(floppydebug\)print)0(109 "fd1disk",)100({Qdata + 1}, 0,)132(0660,)156 L (42 int floppydebug = 0;)0(110 "fd1ctl",)100({Qctl + 1}, 0,)132(0660,)156 L (43)0(111 "fd2disk",)100({Qdata + 2}, 0,)132(0660,)156 L (44 /*)0(112 "fd2ctl",)100({Qctl + 2}, 0,)132(0660,)156 L (45 * types of drive \(from PC equipment byte\))0(113 "fd3disk",)100({Qdata + 3}, 0,)132(0660,)156 L (46 */)0(114 "fd3ctl",)100({Qctl + 3}, 0,)132(0660,)156 L (47 enum)0(115 };)100 L (48 {)0(116 #define NFDIR 2)100(/* directory entries/drive */)132 L (49)0(Tnone=)8(0,)24(117)100 L (50)0(T360kb=)8(1,)24(118 static void)100 L (51)0(T1200kb=)8(2,)24(119 fldump\(void\))100 L (52)0(T720kb=)8(3,)24(120 {)100 L (53)0(T1440kb=)8(4,)24(121 DPRINT\("sra %ux srb %ux dor %ux msr %ux dir %ux\\n", inb\(Psra\), inb\(Psrb\),)100 L (54 };)0(122)100(inb\(Pdor\), inb\(Pmsr\), inb\(Pdir\)\);)116 L (55)0(123 })100 L (56 FType floppytype[] =)0(124)100 L (57 {)0(125 /*)100 L (58 { "3\302\275HD",)0(T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },)25(126 * set floppy drive to its default type)101 L (59 { "3\302\275DD",)0(T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },)25(127 */)101 L (60 { "3\302\275DD",)0(T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },)25(128 static void)101 L (61 { "5\302\274HD",)0(T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },)25(129 floppysetdef\(FDrive *dp\))101 L (62 { "5\302\274DD",)0(T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },)25(130 {)101 L (63 { "ATT3B1",)0(T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },)24(131 FType *t;)100 L (64 { "5\302\274DD",)0(T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },)25(132)101 L (65 };)0(133 for\(t = floppytype; t < &floppytype[nelem\(floppytype\)]; t++\))100 L (66)0(134)100(if\(dp->dt == t->dt\){)116 L (67 /*)0(135)100(dp->t = t;)124 L (68 * bytes per sector encoding for the controller.)0(136)100(floppydir[NFDIR*dp->dev].length = dp->t->cap;)124 L cleartomark showpage saveobj restore %%EndPage: 33 33 %%Page: 34 34 /saveobj save def mark 34 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 2)l ()l ()l (137)0(break;)24(205)100 L (138)0(})16(206 if\(fl.ndrive == 0\))100 L (139 })0(207)100(error\(Enodev\);)116 L (140)0(208)100 L (141 static void)0(209 if\(kstarted == 0\){)100 L (142 floppyreset\(void\))0(210)100(/*)116 L (143 {)0(211)100(* watchdog to turn off the motors)117 L (144 FDrive *dp;)0(212)100(*/)117 L (145 FType *t;)0(213)100(kstarted = 1;)116 L (146 ulong maxtsize;)0(214)100(kproc\("floppy", floppykproc, 0\);)116 L (147)0(215 })100 L (148 floppysetup0\(&fl\);)0(216 return devattach\('f', spec\);)100 L (149 if\(fl.ndrive == 0\))0(217 })100 L (150)0(return;)16(218)100 L (151)0(219 static int)100 L (152 /*)0(220 floppywalk\(Chan *c, char *name\))100 L (153)0(* init dependent parameters)9(221 {)100 L (154)0(*/)9(222 return devwalk\(c, name, floppydir, fl.ndrive*NFDIR, devgen\);)100 L (155 maxtsize = 0;)0(223 })100 L (156 for\(t = floppytype; t < &floppytype[nelem\(floppytype\)]; t++\){)0(224)100 L (157)0(t->cap = t->bytes * t->heads * t->sectors * t->tracks;)16(225 static void)100 L (158)0(t->bcode = b2c[t->bytes/128];)16(226 floppystat\(Chan *c, char *dp\))100 L (159)0(t->tsize = t->bytes * t->sectors;)16(227 {)100 L (160)0(if\(maxtsize < t->tsize\))16(228 devstat\(c, dp, floppydir, fl.ndrive*NFDIR, devgen\);)100 L (161)0(maxtsize = t->tsize;)24(229 })100 L (162 })0(230)100 L (163)0(231 static Chan*)100 L (164 dmainit\(DMAchan, maxtsize\);)0(232 floppyopen\(Chan *c, int omode\))100 L (165)0(233 {)100 L (166 /*)0(234 return devopen\(c, omode, floppydir, fl.ndrive*NFDIR, devgen\);)100 L (167)0(* allocate the drive storage)9(235 })100 L (168)0(*/)9(236)100 L (169 fl.d = xalloc\(fl.ndrive*sizeof\(FDrive\)\);)0(237 static void)100 L (170 fl.selected = fl.d;)0(238 floppyclose\(Chan *\))100 L (171)0(239 {)100 L (172 /*)0(240 })100 L (173)0(* stop the motors)9(241)100 L (174)0(*/)9(242 static void)100 L (175 fl.motor = 0;)0(243 islegal\(ulong offset, long n, FDrive *dp\))100 L (176 delay\(10\);)0(244 {)100 L (177 outb\(Pdor, fl.motor | Fintena | Fena\);)0(245 if\(offset % dp->t->bytes\))100 L (178 delay\(10\);)0(246)100(error\(Ebadarg\);)116 L (179)0(247 if\(n % dp->t->bytes\))100 L (180 /*)0(248)100(error\(Ebadarg\);)116 L (181)0(* init drives)9(249 })100 L (182)0(*/)9(250)100 L (183 for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\){)0(251 /*)100 L (184)0(dp->dev = dp - fl.d;)16(252 * check if the floppy has been replaced under foot. cause)100 L (185)0(dp->dt = T1440kb;)16(253 * an error if it has.)100 L (186)0(floppysetdef\(dp\);)16(254 *)100 L (187)0(dp->cyl = -1;)16(/* because we don't know */)48(255 * a seek and a read clears the condition. this was determined)100 L (188)0(dp->cache = \(uchar*\)xspanalloc\(maxtsize, BY2PG, 64*1024\);)16(256 * experimentally, there has to be a better way.)100 L (189)0(dp->ccyl = -1;)16(257 *)100 L (190)0(dp->vers = 0;)16(258 * if the read fails, cycle through the possible floppy)100 L (191 })0(259 * density till one works or we've cycled through all)100 L (192)0(260 * possibilities for this drive.)100 L (193 /*)0(261 */)100 L (194)0(* first operation will recalibrate)9(262 static void)100 L (195)0(*/)9(263 changed\(Chan *c, FDrive *dp\))100 L (196 fl.confused = 1;)0(264 {)100 L (197)0(265 ulong old;)100 L (198 floppysetup1\(&fl\);)0(266 FType *start;)100 L (199 })0(267)100 L (200)0(268 /*)100 L (201 static Chan*)0(269)100(* if floppy has changed or first time through)109 L (202 floppyattach\(char *spec\))0(270)100(*/)109 L (203 {)0(271 if\(\(inb\(Pdir\)&Fchange\) || dp->vers == 0\){)100 L (204 static int kstarted;)0(272)100(DPRINT\("changed\\n"\);)116 L cleartomark showpage saveobj restore %%EndPage: 34 34 %%Page: 35 35 /saveobj save def mark 35 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 3)l ()l ()l (273)0(fldump\(\);)16(341 case Qdata:)100 L (274)0(dp->vers++;)16(342)100(islegal\(offset, n, dp\);)116 L (275)0(floppysetdef\(dp\);)16(343)100(aa = a;)116 L (276)0(start = dp->t;)16(344)100 L (277)0(dp->confused = 1;)16(/* make floppyon recal */)40(345)100(qlock\(&fl\);)116 L (278)0(floppyon\(dp\);)16(346)100(if\(waserror\(\)\){)116 L (279)0(floppyseek\(dp, dp->t->heads*dp->t->tsize\);)16(347)100(qunlock\(&fl\);)124 L (280)0(while\(waserror\(\)\){)16(348)100(nexterror\(\);)124 L (281)0(while\(++dp->t\){)24(349)100(})116 L (282)0(if\(dp->t == &floppytype[nelem\(floppytype\)]\))32(350)100(floppyon\(dp\);)116 L (283)0(dp->t = floppytype;)40(351)100(changed\(c, dp\);)116 L (284)0(if\(dp->dt == dp->t->dt\))32(352)100(for\(rv = 0; rv < n; rv += len\){)116 L (285)0(break;)40(353)100(/*)124 L (286)0(})24(354)100(* all xfers come out of the track cache)125 L (287)0(floppydir[NFDIR*dp->dev].length = dp->t->cap;)24(355)100(*/)125 L (288)0(floppyon\(dp\);)24(356)100(dp->len = n - rv;)124 L (289)0(DPRINT\("changed: trying %s\\n", dp->t->name\);)24(357)100(floppypos\(dp, offset+rv\);)124 L (290)0(fldump\(\);)24(358)100(cyl = dp->tcyl;)124 L (291)0(if\(dp->t == start\))24(359)100(head = dp->thead;)124 L (292)0(nexterror\(\);)32(360)100(len = dp->len;)124 L (293)0(})16(361)100(sec = dp->tsec;)124 L (294)0(floppyxfer\(dp, Fread, dp->cache, 0, dp->t->tsize\);)16(362)100(if\(readtrack\(dp, cyl, head\) < 0\))124 L (295)0(poperror\(\);)16(363)100(break;)132 L (296 })0(364)100(memmove\(aa+rv, dp->cache + \(sec-1\)*dp->t->bytes, len\);)124 L (297)0(365)100(})116 L (298 old = c->qid.vers;)0(366)100(qunlock\(&fl\);)116 L (299 c->qid.vers = dp->vers;)0(367)100(poperror\(\);)116 L (300 if\(old && old != dp->vers\))0(368)100 L (301)0(error\(Eio\);)16(369)100(break;)116 L (302 })0(370 case Qctl:)100 L (303)0(371)100(return readstr\(offset, a, n, dp->t->name\);)116 L (304 static int)0(372 default:)100 L (305 readtrack\(FDrive *dp, int cyl, int head\))0(373)100(panic\("floppyread: bad qid"\);)116 L (306 {)0(374 })100 L (307 int i, nn, sofar;)0(375)100 L (308 ulong pos;)0(376 return rv;)100 L (309)0(377 })100 L (310 nn = dp->t->tsize;)0(378)100 L (311 if\(dp->ccyl==cyl && dp->chead==head\))0(379 #define SNCMP\(a, b\) strncmp\(a, b, sizeof\(b\)-1\))100 L (312)0(return nn;)16(380 static long)100 L (313 pos = \(cyl*dp->t->heads+head\) * nn;)0(381 floppywrite\(Chan *c, void *a, long n, vlong off\))100 L (314 for\(sofar = 0; sofar < nn; sofar += i\){)0(382 {)100 L (315)0(dp->ccyl = -1;)16(383 FDrive *dp;)100 L (316)0(i = floppyxfer\(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar\);)16(384 long rv, i;)100 L (317)0(if\(i <= 0\))16(385 char *aa = a;)100 L (318)0(return -1;)24(386 char ctlmsg[64];)100 L (319 })0(387 ulong offset = off;)100 L (320 dp->ccyl = cyl;)0(388)100 L (321 dp->chead = head;)0(389 rv = 0;)100 L (322 return nn;)0(390 dp = &fl.d[c->qid.path & ~Qmask];)100 L (323 })0(391 switch \(\(int\)\(c->qid.path & Qmask\)\) {)100 L (324)0(392 case Qdata:)100 L (325 static long)0(393)100(islegal\(offset, n, dp\);)116 L (326 floppyread\(Chan *c, void *a, long n, vlong off\))0(394)100(qlock\(&fl\);)116 L (327 {)0(395)100(if\(waserror\(\)\){)116 L (328 FDrive *dp;)0(396)100(qunlock\(&fl\);)124 L (329 long rv;)0(397)100(nexterror\(\);)124 L (330 int sec, head, cyl;)0(398)100(})116 L (331 long len;)0(399)100(floppyon\(dp\);)116 L (332 uchar *aa;)0(400)100(changed\(c, dp\);)116 L (333 ulong offset = off;)0(401)100(for\(rv = 0; rv < n; rv += i\){)116 L (334)0(402)100(floppypos\(dp, offset+rv\);)124 L (335 if\(c->qid.path == CHDIR\))0(403)100(if\(dp->tcyl == dp->ccyl\))124 L (336)0(return devdirread\(c, a, n, floppydir, fl.ndrive*NFDIR, devgen\);)16(404)100(dp->ccyl = -1;)132 L (337)0(405)100(i = floppyxfer\(dp, Fwrite, aa+rv, offset+rv, n-rv\);)124 L (338 rv = 0;)0(406)100(if\(i < 0\))124 L (339 dp = &fl.d[c->qid.path & ~Qmask];)0(407)100(break;)132 L (340 switch \(\(int\)\(c->qid.path & Qmask\)\) {)0(408)100(if\(i == 0\))124 L cleartomark showpage saveobj restore %%EndPage: 35 35 %%Page: 36 36 /saveobj save def mark 36 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 4)l ()l ()l (409)0(error\(Eio\);)32(477)100(floppyrevive\(\);)116 L (410)0(})16(478)100 L (411)0(qunlock\(&fl\);)16(479 /* start motor and select drive */)100 L (412)0(poperror\(\);)16(480 alreadyon = fl.motor & MOTORBIT\(dp->dev\);)100 L (413)0(break;)16(481 fl.motor |= MOTORBIT\(dp->dev\);)100 L (414 case Qctl:)0(482 outb\(Pdor, fl.motor | Fintena | Fena | dp->dev\);)100 L (415)0(rv = n;)16(483 if\(!alreadyon\){)100 L (416)0(qlock\(&fl\);)16(484)100(/* wait for drive to spin up */)116 L (417)0(if\(waserror\(\)\){)16(485)100(tsleep\(&dp->r, return0, 0, 750\);)116 L (418)0(qunlock\(&fl\);)24(486)100 L (419)0(nexterror\(\);)24(487)100(/* clear any pending interrupts */)116 L (420)0(})16(488)100(floppysense\(\);)116 L (421)0(if\(n >= sizeof\(ctlmsg\)\))16(489 })100 L (422)0(n = sizeof\(ctlmsg\) - 1;)24(490)100 L (423)0(memmove\(ctlmsg, aa, n\);)16(491 /* set transfer rate */)100 L (424)0(ctlmsg[n] = 0;)16(492 if\(fl.rate != dp->t->rate\){)100 L (425)0(if\(SNCMP\(ctlmsg, "eject"\) == 0\){)16(493)100(fl.rate = dp->t->rate;)116 L (426)0(floppyeject\(dp\);)24(494)100(outb\(Pdsr, fl.rate\);)116 L (427)0(} else if\(SNCMP\(ctlmsg, "reset"\) == 0\){)16(495 })100 L (428)0(fl.confused = 1;)24(496)100 L (429)0(floppyon\(dp\);)24(497 /* get drive to a known cylinder */)100 L (430)0(} else if\(SNCMP\(ctlmsg, "format"\) == 0\){)16(498 if\(dp->confused\))100 L (431)0(floppyformat\(dp, ctlmsg\);)24(499)100(for\(tries = 0; tries < 4; tries++\))116 L (432)0(} else if\(SNCMP\(ctlmsg, "debug"\) == 0\){)16(500)100(if\(floppyrecal\(dp\) >= 0\))124 L (433)0(floppydebug = 1;)24(501)100(break;)132 L (434)0(} else)16(502 dp->lasttouched = m->ticks;)100 L (435)0(error\(Ebadctl\);)24(503 fl.selected = dp;)100 L (436)0(poperror\(\);)16(504 })100 L (437)0(qunlock\(&fl\);)16(505)100 L (438)0(break;)16(506 /*)100 L (439 default:)0(507 * stop the floppy if it hasn't been used in 5 seconds)100 L (440)0(panic\("floppywrite: bad qid"\);)16(508 */)100 L (441 })0(509 static void)100 L (442)0(510 floppyoff\(FDrive *dp\))100 L (443 return rv;)0(511 {)100 L (444 })0(512 fl.motor &= ~MOTORBIT\(dp->dev\);)100 L (445)0(513 outb\(Pdor, fl.motor | Fintena | Fena | dp->dev\);)100 L (446 static void)0(514 })100 L (447 floppykproc\(void *\))0(515)100 L (448 {)0(516 /*)100 L (449 FDrive *dp;)0(517 * send a command to the floppy)100 L (450)0(518 */)100 L (451 while\(waserror\(\)\))0(519 static int)100 L (452)0(;)16(520 floppycmd\(void\))100 L (453 for\(;;\){)0(521 {)100 L (454)0(for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\){)16(522 int i;)100 L (455)0(if\(\(fl.motor&MOTORBIT\(dp->dev\)\))24(523 int tries;)100 L (456)0(&& TK2SEC\(m->ticks - dp->lasttouched\) > 5)24(524)100 L (457)0(&& canqlock\(&fl\)\){)24(525 fl.nstat = 0;)100 L (458)0(if\(TK2SEC\(m->ticks - dp->lasttouched\) > 5\))32(526 for\(i = 0; i < fl.ncmd; i++\){)100 L (459)0(floppyoff\(dp\);)40(527)100(for\(tries = 0; ; tries++\){)116 L (460)0(qunlock\(&fl\);)32(528)100(if\(\(inb\(Pmsr\)&\(Ffrom|Fready\)\) == Fready\))124 L (461)0(})24(529)100(break;)132 L (462)0(})16(530)100(if\(tries > 1000\){)124 L (463)0(tsleep\(&fl.kr, return0, 0, 1000\);)16(531)100(DPRINT\("cmd %ux can't be sent \(%d\)\\n", fl.cmd[0], i\);)132 L (464 })0(532)100(fldump\(\);)132 L (465 })0(533)100 L (466)0(534)100(/* empty fifo, might have been a bad command */)132 L (467 /*)0(535)100(floppyresult\(\);)132 L (468 * start a floppy drive's motor.)0(536)100(return -1;)132 L (469 */)0(537)100(})124 L (470 static void)0(538)100(microdelay\(8\); /* for machine independence */)124 L (471 floppyon\(FDrive *dp\))0(539)100(})116 L (472 {)0(540)100(outb\(Pfdata, fl.cmd[i]\);)116 L (473 int alreadyon;)0(541 })100 L (474 int tries;)0(542 return 0;)100 L (475)0(543 })100 L (476 if\(fl.confused\))0(544)100 L cleartomark showpage saveobj restore %%EndPage: 36 36 %%Page: 37 37 /saveobj save def mark 37 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 5)l ()l ()l (545 /*)0(613 static int)100 L (546 * get a command result from the floppy)0(614 floppysense\(void\))100 L (547 *)0(615 {)100 L (548 * when the controller goes ready waiting for a command)0(616 fl.ncmd = 0;)100 L (549 * \(instead of sending results\), we're done)0(617 fl.cmd[fl.ncmd++] = Fsense;)100 L (550 *)0(618 if\(floppycmd\(\) < 0\))100 L (551 */)0(619)100(return -1;)116 L (552 static int)0(620 if\(floppyresult\(\) < 2\){)100 L (553 floppyresult\(void\))0(621)100(DPRINT\("can't read sense response\\n"\);)116 L (554 {)0(622)100(fldump\(\);)116 L (555 int i, s;)0(623)100(fl.confused = 1;)116 L (556 int tries;)0(624)100(return -1;)116 L (557)0(625 })100 L (558 /* get the result of the operation */)0(626 return 0;)100 L (559 for\(i = 0; i < sizeof\(fl.stat\); i++\){)0(627 })100 L (560)0(/* wait for status byte */)16(628)100 L (561)0(for\(tries = 0; ; tries++\){)16(629 static int)100 L (562)0(s = inb\(Pmsr\)&\(Ffrom|Fready\);)24(630 cmddone\(void *\))100 L (563)0(if\(s == Fready\){)24(631 {)100 L (564)0(fl.nstat = i;)32(632 return fl.ncmd == 0;)100 L (565)0(return fl.nstat;)32(633 })100 L (566)0(})24(634)100 L (567)0(if\(s == \(Ffrom|Fready\)\))24(635 /*)100 L (568)0(break;)32(636 * Wait for a floppy interrupt. If none occurs in 5 seconds, we)100 L (569)0(if\(tries > 1000\){)24(637 * may have missed one. This only happens on some portables which)100 L (570)0(DPRINT\("floppyresult: %d stats\\n", i\);)32(638 * do power management behind our backs. Call the interrupt)100 L (571)0(fldump\(\);)32(639 * routine to try to clear any conditions.)100 L (572)0(fl.confused = 1;)32(640 */)100 L (573)0(return -1;)32(641 static void)100 L (574)0(})24(642 floppywait\(void\))100 L (575)0(microdelay\(8\); /* for machine independence */)24(643 {)100 L (576)0(})16(644 tsleep\(&fl.r, cmddone, 0, 5000\);)100 L (577)0(fl.stat[i] = inb\(Pfdata\);)16(645 if\(!cmddone\(0\)\){)100 L (578 })0(646)100(floppyintr\(0\);)116 L (579 fl.nstat = sizeof\(fl.stat\);)0(647)100(fl.confused = 1;)116 L (580 return fl.nstat;)0(648 })100 L (581 })0(649 })100 L (582)0(650)100 L (583 /*)0(651 /*)100 L (584 * calculate physical address of a logical byte offset into the disk)0(652 * we've lost the floppy position, go to cylinder 0.)100 L (585 *)0(653 */)100 L (586 * truncate dp->length if it crosses a track boundary)0(654 static int)100 L (587 */)0(655 floppyrecal\(FDrive *dp\))100 L (588 static void)0(656 {)100 L (589 floppypos\(FDrive *dp, long off\))0(657 dp->ccyl = -1;)100 L (590 {)0(658 dp->cyl = -1;)100 L (591 int lsec;)0(659)100 L (592 int ltrack;)0(660 fl.ncmd = 0;)100 L (593 int end;)0(661 fl.cmd[fl.ncmd++] = Frecal;)100 L (594)0(662 fl.cmd[fl.ncmd++] = dp->dev;)100 L (595 lsec = off/dp->t->bytes;)0(663 if\(floppycmd\(\) < 0\))100 L (596 ltrack = lsec/dp->t->sectors;)0(664)100(return -1;)116 L (597 dp->tcyl = ltrack/dp->t->heads;)0(665 floppywait\(\);)100 L (598 dp->tsec = \(lsec % dp->t->sectors\) + 1;)0(666 if\(fl.nstat < 2\){)100 L (599 dp->thead = \(lsec/dp->t->sectors\) % dp->t->heads;)0(667)100(DPRINT\("recalibrate: confused %ux\\n", inb\(Pmsr\)\);)116 L (600)0(668)100(fl.confused = 1;)116 L (601 /*)0(669)100(return -1;)116 L (602)0(* can't read across track boundaries.)9(670 })100 L (603)0(* if so, decrement the bytes to be read.)9(671 if\(\(fl.stat[0] & \(Codemask|Seekend\)\) != Seekend\){)100 L (604)0(*/)9(672)100(DPRINT\("recalibrate: failed\\n"\);)116 L (605 end = \(ltrack+1\)*dp->t->sectors*dp->t->bytes;)0(673)100(dp->confused = 1;)116 L (606 if\(off+dp->len > end\))0(674)100(return -1;)116 L (607)0(dp->len = end - off;)16(675 })100 L (608 })0(676 dp->cyl = fl.stat[1];)100 L (609)0(677 if\(dp->cyl != 0\){)100 L (610 /*)0(678)100(DPRINT\("recalibrate: wrong cylinder %d\\n", dp->cyl\);)116 L (611 * get the interrupt cause from the floppy.)0(679)100(dp->cyl = -1;)116 L (612 */)0(680)100(dp->confused = 1;)116 L cleartomark showpage saveobj restore %%EndPage: 37 37 %%Page: 38 38 /saveobj save def mark 38 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 6)l ()l ()l (681)0(return -1;)16(749 floppywait\(\);)100 L (682 })0(750 if\(fl.nstat < 2\){)100 L (683)0(751)100(DPRINT\("seek: confused\\n"\);)116 L (684 dp->confused = 0;)0(752)100(fl.confused = 1;)116 L (685 return 0;)0(753)100(return -1;)116 L (686 })0(754 })100 L (687)0(755 if\(\(fl.stat[0] & \(Codemask|Seekend\)\) != Seekend\){)100 L (688 /*)0(756)100(DPRINT\("seek: failed\\n"\);)116 L (689 * if the controller or a specific drive is in a confused state,)0(757)100(dp->confused = 1;)116 L (690 * reset it and get back to a known state)0(758)100(return -1;)116 L (691 */)0(759 })100 L (692 static void)0(760)100 L (693 floppyrevive\(void\))0(761 dp->cyl = dp->tcyl;)100 L (694 {)0(762 return dp->tcyl;)100 L (695 FDrive *dp;)0(763 })100 L (696)0(764)100 L (697 /*)0(765 /*)100 L (698)0(* reset the controller if it's confused)9(766 * read or write to floppy. try up to three times.)100 L (699)0(*/)9(767 */)100 L (700 if\(fl.confused\){)0(768 static long)100 L (701)0(DPRINT\("floppyrevive in\\n"\);)16(769 floppyxfer\(FDrive *dp, int cmd, void *a, long off, long n\))100 L (702)0(fldump\(\);)16(770 {)100 L (703)0(771 long offset;)100 L (704)0(/* reset controller and turn all motors off */)16(772 int tries;)100 L (705)0(splhi\(\);)16(773)100 L (706)0(fl.ncmd = 1;)16(774 if\(off >= dp->t->cap\))100 L (707)0(fl.cmd[0] = 0;)16(775)100(return 0;)116 L (708)0(outb\(Pdor, 0\);)16(776 if\(off + n > dp->t->cap\))100 L (709)0(delay\(10\);)16(777)100(n = dp->t->cap - off;)116 L (710)0(outb\(Pdor, Fintena|Fena\);)16(778)100 L (711)0(delay\(10\);)16(779 /* retry on error \(until it gets ridiculous\) */)100 L (712)0(spllo\(\);)16(780 tries = 0;)100 L (713)0(fl.motor = 0;)16(781 while\(waserror\(\)\){)100 L (714)0(fl.confused = 0;)16(782)100(if\(tries++ > 20\))116 L (715)0(floppywait\(\);)16(783)100(nexterror\(\);)124 L (716)0(784)100(DPRINT\("floppyxfer: retrying\\n"\);)116 L (717)0(/* mark all drives in an unknown state */)16(785)100(/*floppyon\(dp\);*/)116 L (718)0(for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\))16(786 })100 L (719)0(dp->confused = 1;)24(787)100 L (720)0(788 dp->len = n;)100 L (721)0(/* set rate to a known value */)16(789 if\(floppyseek\(dp, off\) < 0\){)100 L (722)0(outb\(Pdsr, 0\);)16(790)100(DPRINT\("xfer: seek failed\\n"\);)116 L (723)0(fl.rate = 0;)16(791)100(dp->confused = 1;)116 L (724)0(792)100(error\(Eio\);)116 L (725)0(DPRINT\("floppyrevive out\\n"\);)16(793 })100 L (726)0(fldump\(\);)16(794)100 L (727 })0(795 /*)100 L (728 })0(796)100(* set up the dma \(dp->len may be trimmed\))109 L (729)0(797)100(*/)109 L (730 /*)0(798 if\(waserror\(\)\){)100 L (731 * seek to the target cylinder)0(799)100(dmaend\(DMAchan\);)116 L (732 *)0(800)100(nexterror\(\);)116 L (733 *)0(interrupt, no results)16(801 })100 L (734 */)0(802 dp->len = dmasetup\(DMAchan, a, dp->len, cmd==Fread\);)100 L (735 static long)0(803 if\(dp->len < 0\))100 L (736 floppyseek\(FDrive *dp, long off\))0(804)100(error\(Eio\);)116 L (737 {)0(805)100 L (738 floppypos\(dp, off\);)0(806 /*)100 L (739 if\(dp->cyl == dp->tcyl\))0(807)100(* start operation)109 L (740)0(return dp->tcyl;)16(808)100(*/)109 L (741 dp->cyl = -1;)0(809 fl.ncmd = 0;)100 L (742)0(810 fl.cmd[fl.ncmd++] = cmd | \(dp->t->heads > 1 ? Fmulti : 0\);)100 L (743 fl.ncmd = 0;)0(811 fl.cmd[fl.ncmd++] = \(dp->thead<<2\) | dp->dev;)100 L (744 fl.cmd[fl.ncmd++] = Fseek;)0(812 fl.cmd[fl.ncmd++] = dp->tcyl;)100 L (745 fl.cmd[fl.ncmd++] = \(dp->thead<<2\) | dp->dev;)0(813 fl.cmd[fl.ncmd++] = dp->thead;)100 L (746 fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;)0(814 fl.cmd[fl.ncmd++] = dp->tsec;)100 L (747 if\(floppycmd\(\) < 0\))0(815 fl.cmd[fl.ncmd++] = dp->t->bcode;)100 L (748)0(return -1;)16(816 fl.cmd[fl.ncmd++] = dp->t->sectors;)100 L cleartomark showpage saveobj restore %%EndPage: 38 38 %%Page: 39 39 /saveobj save def mark 39 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 7)l ()l ()l (817 fl.cmd[fl.ncmd++] = dp->t->gpl;)0(885)100(if\(strcmp\(f[1], t->name\)==0 && t->dt==dp->dt\){)124 L (818 fl.cmd[fl.ncmd++] = 0xFF;)0(886)100(dp->t = t;)132 L (819 if\(floppycmd\(\) < 0\))0(887)100(floppydir[NFDIR*dp->dev].length = dp->t->cap;)132 L (820)0(error\(Eio\);)16(888)100(break;)132 L (821)0(889)100(})124 L (822 /* Poll ready bits and transfer data */)0(890)100(})116 L (823 floppyexec\(\(char*\)a, dp->len, cmd==Fread\);)0(891)100(if\(t >= &floppytype[nelem\(floppytype\)]\))116 L (824)0(892)100(error\(Ebadarg\);)124 L (825 /*)0(893 } else {)100 L (826)0(* give bus to DMA, floppyintr\(\) will read result)9(894)100(floppysetdef\(dp\);)116 L (827)0(*/)9(895)100(t = dp->t;)116 L (828 floppywait\(\);)0(896 })100 L (829 dmaend\(DMAchan\);)0(897)100 L (830 poperror\(\);)0(898 /*)100 L (831)0(899)100(* buffer for per track info)109 L (832 /*)0(900)100(*/)109 L (833)0(* check for errors)9(901 buf = smalloc\(t->sectors*4\);)100 L (834)0(*/)9(902 if\(waserror\(\)\){)100 L (835 if\(fl.nstat < 7\){)0(903)100(free\(buf\);)116 L (836)0(DPRINT\("xfer: confused\\n"\);)16(904)100(nexterror\(\);)116 L (837)0(fl.confused = 1;)16(905 })100 L (838)0(error\(Eio\);)16(906)100 L (839 })0(907 /* force a recalibrate to cylinder 0 */)100 L (840 if\(\(fl.stat[0] & Codemask\)!=0 || fl.stat[1] || fl.stat[2]\){)0(908 dp->confused = 1;)100 L (841)0(DPRINT\("xfer: failed %ux %ux %ux\\n", fl.stat[0],)16(909 if\(!waserror\(\)\){)100 L (842)0(fl.stat[1], fl.stat[2]\);)24(910)100(floppyon\(dp\);)116 L (843)0(DPRINT\("offset %lud len %ld\\n", off, dp->len\);)16(911)100(poperror\(\);)116 L (844)0(if\(\(fl.stat[0]&Codemask\)==Cmdexec && fl.stat[1]==Overrun\){)16(912 })100 L (845)0(DPRINT\("DMA overrun: retry\\n"\);)24(913)100 L (846)0(} else)16(914 /*)100 L (847)0(dp->confused = 1;)24(915)100(* format a track at time)109 L (848)0(error\(Eio\);)16(916)100(*/)109 L (849 })0(917 for\(track = 0; track < t->tracks*t->heads; track++\){)100 L (850)0(918)100(cyl = track/t->heads;)116 L (851 /*)0(919)100(h = track % t->heads;)116 L (852)0(* check for correct cylinder)9(920)100 L (853)0(*/)9(921)100(/*)116 L (854 offset = fl.stat[3] * dp->t->heads + fl.stat[4];)0(922)100(* seek to track, ignore errors)117 L (855 offset = offset*dp->t->sectors + fl.stat[5] - 1;)0(923)100(*/)117 L (856 offset = offset * c2b[fl.stat[6]];)0(924)100(floppyseek\(dp, track*t->tsize\);)116 L (857 if\(offset != off+dp->len\){)0(925)100(dp->cyl = cyl;)116 L (858)0(DPRINT\("xfer: ends on wrong cyl\\n"\);)16(926)100(dp->confused = 0;)116 L (859)0(dp->confused = 1;)16(927)100 L (860)0(error\(Eio\);)16(928)100(/*)116 L (861 })0(929)100(* set up the dma \(dp->len may be trimmed\))117 L (862 poperror\(\);)0(930)100(*/)117 L (863)0(931)100(bp = buf;)116 L (864 dp->lasttouched = m->ticks;)0(932)100(for\(sec = 1; sec <= t->sectors; sec++\){)116 L (865 return dp->len;)0(933)100(*bp++ = cyl;)124 L (866 })0(934)100(*bp++ = h;)124 L (867)0(935)100(*bp++ = sec;)124 L (868 /*)0(936)100(*bp++ = t->bcode;)124 L (869 * format a track)0(937)100(})116 L (870 */)0(938)100(if\(waserror\(\)\){)116 L (871 static void)0(939)100(dmaend\(DMAchan\);)124 L (872 floppyformat\(FDrive *dp, char *params\))0(940)100(nexterror\(\);)124 L (873 {)0(941)100(})116 L (874 int cyl, h, sec;)0(942)100(if\(dmasetup\(DMAchan, buf, bp-buf, 0\) < 0\))116 L (875 ulong track;)0(943)100(error\(Eio\);)124 L (876 uchar *buf, *bp;)0(944)100 L (877 FType *t;)0(945)100(/*)116 L (878 char *f[3];)0(946)100(* start operation)117 L (879)0(947)100(*/)117 L (880 /*)0(948)100(fl.ncmd = 0;)116 L (881)0(* set the type)9(949)100(fl.cmd[fl.ncmd++] = Fformat;)116 L (882)0(*/)9(950)100(fl.cmd[fl.ncmd++] = \(h<<2\) | dp->dev;)116 L (883 if\(getfields\(params, f, 3, 1, " "\) > 1\){)0(951)100(fl.cmd[fl.ncmd++] = t->bcode;)116 L (884)0(for\(t = floppytype; t < &floppytype[nelem\(floppytype\)]; t++\){)16(952)100(fl.cmd[fl.ncmd++] = t->sectors;)116 L cleartomark showpage saveobj restore %%EndPage: 39 39 %%Page: 40 40 /saveobj save def mark 40 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devfloppy.c Page 8)l ()l ()l (953)0(fl.cmd[fl.ncmd++] = t->fgpl;)16(1021 floppyread,)100 L (954)0(fl.cmd[fl.ncmd++] = 0x5a;)16(1022 devbread,)100 L (955)0(if\(floppycmd\(\) < 0\))16(1023 floppywrite,)100 L (956)0(error\(Eio\);)24(1024 devbwrite,)100 L (957)0(1025 devremove,)100 L (958)0(/* Poll ready bits and transfer data */)16(1026 devwstat,)100 L (959)0(floppyexec\(\(char *\)buf, bp-buf, 0\);)16(1027 };)100 L (960)l (961)0(/*)16 L (962)0(* give bus to DMA, floppyintr\(\) will read result)17 L (963)0(*/)17 L (964)0(floppywait\(\);)16 L (965)0(dmaend\(DMAchan\);)16 L (966)0(poperror\(\);)16 L (967)l (968)0(/*)16 L (969)0(* check for errors)17 L (970)0(*/)17 L (971)0(if\(fl.nstat < 7\){)16 L (972)0(DPRINT\("format: confused\\n"\);)24 L (973)0(fl.confused = 1;)24 L (974)0(error\(Eio\);)24 L (975)0(})16 L (976)0(if\(\(fl.stat[0]&Codemask\)!=0 || fl.stat[1]|| fl.stat[2]\){)16 L (977)0(DPRINT\("format: failed %ux %ux %ux\\n",)24 L (978)0(fl.stat[0], fl.stat[1], fl.stat[2]\);)32 L (979)0(dp->confused = 1;)24 L (980)0(error\(Eio\);)24 L (981)0(})16 L (982 })l (983 free\(buf\);)l (984 dp->confused = 1;)l (985 poperror\(\);)l (986 })l (987)l (988 static void)l (989 floppyintr\(Ureg *\))l (990 {)l (991 switch\(fl.cmd[0]&~Fmulti\){)l (992 case Fread:)l (993 case Fwrite:)l (994 case Fformat:)l (995 case Fdumpreg:)l (996)0(floppyresult\(\);)16 L (997)0(break;)16 L (998 case Fseek:)l (999 case Frecal:)l (1000 default:)l (1001)0(floppysense\(\); /* to clear interrupt */)16 L (1002)0(break;)16 L (1003 })l (1004 fl.ncmd = 0;)l (1005 wakeup\(&fl.r\);)l (1006 })l (1007)l (1008 Dev floppydevtab = {)l (1009 'f',)l (1010 "floppy",)l (1011)l (1012 floppyreset,)l (1013 devinit,)l (1014 floppyattach,)l (1015 devclone,)l (1016 floppywalk,)l (1017 floppystat,)l (1018 floppyopen,)l (1019 devcreate,)l (1020 floppyclose,)l cleartomark showpage saveobj restore %%EndPage: 40 40 %%Page: 41 41 /saveobj save def mark 41 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devlpt.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(tab += i;)108 L (2 #include "../port/lib.h")0(70)100(qid = tab->qid;)108 L (3 #include "mem.h")0(71)100(if\(qid.path < Qdata\))108 L (4 #include "dat.h")0(72)100(qid.path += lptbase[c->dev];)116 L (5 #include "fns.h")0(73)100(qid.vers = c->dev;)108 L (6 #include "io.h")0(74)100(sprint\(name, "lpt%lud%s", c->dev+1, tab->name\);)108 L (7 #include "../port/error.h")0(75)100(devdir\(c, qid, name, tab->length, eve, tab->perm, dp\);)108 L (8)0(76)100(return 1;)108 L (9 /* Centronix parallel \(printer\) port */)0(77 })100 L (10)0(78)100 L (11 /* base addresses */)0(79 static Chan*)100 L (12 static int lptbase[] = {)0(80 lptattach\(char *spec\))100 L (13)0(0x378, /* lpt1 */)8(81 {)100 L (14)0(0x3bc, /* lpt2 */)8(82)100(Chan *c;)108 L (15)0(0x278 /* lpt3 \(sic\) */)8(83)100(int i = \(spec && *spec\) ? strtol\(spec, 0, 0\) : 1;)108 L (16 };)0(84)100(char name[5];)108 L (17 #define NDEV)0(nelem\(lptbase\))24(85)100(static int set;)108 L (18 static int lptallocd[NDEV];)0(86)100 L (19)0(87)100(if\(!set\){)108 L (20 /* offsets, and bits in the registers */)0(88)100(outb\(lptbase[i-1]+Qpcr, 0\); /* turn off interrupts */)116 L (21 enum)0(89)100(set = 1;)116 L (22 {)0(90)100(intrenable\(IrqLPT, lptintr, 0, BUSUNKNOWN, "lpt"\);)116 L (23)0(/* data latch register */)8(91)100(})108 L (24)0(Qdlr=)8(0x0,)24(92)100(if\(i < 1 || i > NDEV\))108 L (25)0(/* printer status register */)8(93)100(error\(Ebadarg\);)116 L (26)0(Qpsr=)8(0x1,)24(94)100(if\(lptallocd[i-1] == 0\){)108 L (27)0(Fnotbusy=)8(0x80,)24(95)100(sprint\(name, "lpt%d", i-1\);)116 L (28)0(Fack=)8(0x40,)24(96)100(if\(ioalloc\(lptbase[i-1], 3, 0, name\) < 0\))116 L (29)0(Fpe=)8(0x20,)24(97)100(error\("lpt port space in use"\);)124 L (30)0(Fselect=)8(0x10,)24(98)100(lptallocd[i-1] = 1;)116 L (31)0(Fnoerror=)8(0x08,)24(99)100(})108 L (32)0(/* printer control register */)8(100 c = devattach\('L', spec\);)100 L (33)0(Qpcr=)8(0x2,)24(101 c->dev = i-1;)100 L (34)0(Fie=)8(0x10,)24(102 return c;)100 L (35)0(Fselectin=)8(0x08,)24(103 })100 L (36)0(Finitbar=)8(0x04,)24(104)100 L (37)0(Faf=)8(0x02,)24(105 static int)100 L (38)0(Fstrobe=)8(0x01,)24(106 lptwalk\(Chan *c, char *name\))100 L (39)0(/* fake `data register' */)8(107 {)100 L (40)0(Qdata=)8(0x3,)24(108 return devwalk\(c, name, lptdir, nelem\(lptdir\), lptgen\);)100 L (41 };)0(109 })100 L (42)0(110)100 L (43 static int)0(lptready\(void*\);)24(111 static void)100 L (44 static void)0(outch\(int, int\);)24(112 lptstat\(Chan *c, char *dp\))100 L (45 static void)0(lptintr\(Ureg*, void*\);)24(113 {)100 L (46)0(114 devstat\(c, dp, lptdir, nelem\(lptdir\), lptgen\);)100 L (47 static Rendez lptrendez;)0(115 })100 L (48)0(116)100 L (49 Dirtab lptdir[]={)0(117 static Chan*)100 L (50)0("dlr",)8({Qdlr},)24(1,)40(0666,)56(118 lptopen\(Chan *c, int omode\))100 L (51)0("psr",)8({Qpsr},)24(5,)40(0444,)56(119 {)100 L (52)0("pcr",)8({Qpcr},)24(0,)40(0222,)56(120 return devopen\(c, omode, lptdir, nelem\(lptdir\), lptgen\);)100 L (53)0("data",)8({Qdata},)24(0,)40(0222,)56(121 })100 L (54 };)0(122)100 L (55)0(123 static void)100 L (56 static int)0(124 lptclose\(Chan *\))100 L (57 lptgen\(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp\))0(125 {)100 L (58 {)0(126 })100 L (59)0(Qid qid;)8(127)100 L (60)0(char name[NAMELEN];)8(128 static long)100 L (61)0(129 lptread\(Chan *c, void *a, long n, vlong\))100 L (62)0(if\(i == DEVDOTDOT\){)8(130 {)100 L (63)0(sprint\(name, "#L%lud", c->dev+1\);)16(131 char str[16];)100 L (64)0(devdir\(c, \(Qid\){CHDIR, 0}, name, 0, eve, 0555, dp\);)16(132 int size;)100 L (65)0(return 1;)16(133 ulong o;)100 L (66)0(})8(134)100 L (67)0(if\(tab==0 || i>=ntab\))8(135 if\(c->qid.path == CHDIR\))100 L (68)0(return -1;)16(136)100(return devdirread\(c, a, n, lptdir, nelem\(lptdir\), lptgen\);)116 L cleartomark showpage saveobj restore %%EndPage: 41 41 %%Page: 42 42 /saveobj save def mark 42 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devlpt.c Page 2)l ()l ()l (137 size = sprint\(str, "0x%2.2ux\\n", inb\(c->qid.path\)\);)0(205 {)100 L (138 o = c->offset;)0(206 wakeup\(&lptrendez\);)100 L (139 if\(o >= size\))0(207 })100 L (140)0(return 0;)16(208)100 L (141 if\(o+n > size\))0(209 Dev lptdevtab = {)100 L (142)0(n = size-c->offset;)16(210 'L',)100 L (143 memmove\(a, str+o, n\);)0(211 "lpt",)100 L (144 return n;)0(212)100 L (145 })0(213 devreset,)100 L (146)0(214 devinit,)100 L (147 static long)0(215 lptattach,)100 L (148 lptwrite\(Chan *c, void *a, long n, vlong\))0(216 devclone,)100 L (149 {)0(217 lptwalk,)100 L (150 char str[16], *p;)0(218 lptstat,)100 L (151 long base, k;)0(219 lptopen,)100 L (152)0(220 devcreate,)100 L (153 if\(n <= 0\))0(221 lptclose,)100 L (154)0(return 0;)16(222 lptread,)100 L (155 if\(c->qid.path != Qdata\){)0(223 devbread,)100 L (156)0(if\(n > sizeof str-1\))16(224 lptwrite,)100 L (157)0(n = sizeof str-1;)24(225 devbwrite,)100 L (158)0(memmove\(str, a, n\);)16(226 devremove,)100 L (159)0(str[n] = 0;)16(227 devwstat,)100 L (160)0(outb\(c->qid.path, strtoul\(str, 0, 0\)\);)16(228 };)100 L (161)0(return n;)16 L (162 })l (163 p = a;)l (164 k = n;)l (165 base = lptbase[c->dev];)l (166 if\(waserror\(\)\){)l (167)0(outb\(base+Qpcr, Finitbar\);)16 L (168)0(nexterror\(\);)16 L (169 })l (170 while\(--k >= 0\))l (171)0(outch\(base, *p++\);)16 L (172 poperror\(\);)l (173 return n;)l (174 })l (175)l (176 static void)l (177 outch\(int base, int c\))l (178 {)l (179 int status, tries;)l (180)l (181 for\(tries = 0;; tries++\){)l (182)0(status = inb\(base+Qpsr\);)16 L (183)0(if\(!\(status & Fselect\) || !\(status & Fnoerror\)\))16 L (184)0(error\(Eio\);)24 L (185)0(if\(status & Fnotbusy\))16 L (186)0(break;)24 L (187)0(if\(tries > 1000\){)16 L (188)0(outb\(base+Qpcr, Finitbar|Fie\);)24 L (189)0(tsleep\(&lptrendez, lptready, \(void *\)base, MS2HZ\);)24 L (190)0(})16 L (191 })l (192 outb\(base+Qdlr, c\);)l (193 outb\(base+Qpcr, Finitbar|Fstrobe\);)l (194 outb\(base+Qpcr, Finitbar\);)l (195 })l (196)l (197 static int)l (198 lptready\(void *base\))l (199 {)l (200 return inb\(\(int\)base+Qpsr\)&Fnotbusy;)l (201 })l (202)l (203 static void)l (204 lptintr\(Ureg *, void *\))l cleartomark showpage saveobj restore %%EndPage: 42 42 %%Page: 43 43 /saveobj save def mark 43 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devvga.c Page 1)l ()l ()l (1 /*)0(69 checkport\(int start, int end\))100 L (2)0(* VGA controller)7(70 {)100 L (3)0(*/)7(71)100(/* standard vga regs are OK */)108 L (4 #include "u.h")0(72)100(if\(start >= 0x2b0 && end <= 0x2df+1\))108 L (5 #include "../port/lib.h")0(73)100(return;)116 L (6 #include "mem.h")0(74)100(if\(start >= 0x3c0 && end <= 0x3da+1\))108 L (7 #include "dat.h")0(75)100(return;)116 L (8 #include "fns.h")0(76)100 L (9 #include "../port/error.h")0(77)100(if\(iounused\(start, end\)\))108 L (10)0(78)100(return;)116 L (11 #define Image IMAGE)0(79)100(error\(Eperm\);)108 L (12 #include )0(80 })100 L (13 #include )0(81)100 L (14 #include )0(82 static long)100 L (15 #include "screen.h")0(83 vgaread\(Chan* c, void* a, long n, vlong off\))100 L (16)0(84 {)100 L (17 enum {)0(85)100(int len;)108 L (18)0(Qdir,)8(86)100(char *p, *s;)108 L (19)0(Qvgactl,)8(87)100(VGAscr *scr;)108 L (20 };)0(88)100(ulong offset = off;)108 L (21)0(89)100(char chbuf[30];)108 L (22 static Dirtab vgadir[] = {)0(90)100 L (23)0("vgactl",)8({ Qvgactl, 0 },)24(0,)48(0660,)56(91)100(switch\(c->qid.path & ~CHDIR\){)108 L (24 };)0(92)100 L (25)0(93)100(case Qdir:)108 L (26 static void)0(94)100(return devdirread\(c, a, n, vgadir, nelem\(vgadir\), devgen\);)116 L (27 vgareset\(void\))0(95)100 L (28 {)0(96)100(case Qvgactl:)108 L (29)0(/* reserve the 'standard' vga registers */)8(97)100(scr = &vgascreen[0];)116 L (30)0(if\(ioalloc\(0x2b0, 0x2df-0x2b0+1, 0, "vga"\) < 0\))8(98)100 L (31)0(panic\("vga ports already allocated"\);)16(99)100(p = malloc\(READSTR\);)116 L (32)0(if\(ioalloc\(0x3c0, 0x3da-0x3c0+1, 0, "vga"\) < 0\))8(100)100(if\(waserror\(\)\){)116 L (33)0(panic\("vga ports already allocated"\);)16(101)100(free\(p\);)124 L (34)0(conf.monitor = 1;)8(102)100(nexterror\(\);)124 L (35 })0(103)100(})116 L (36)0(104)100 L (37 static Chan*)0(105)100(len = 0;)116 L (38 vgaattach\(char* spec\))0(106)100 L (39 {)0(107)100(if\(scr->dev\))116 L (40)0(if\(*spec && strcmp\(spec, "0"\)\))8(108)100(s = scr->dev->name;)124 L (41)0(error\(Eio\);)16(109)100(else)116 L (42)0(return devattach\('v', spec\);)8(110)100(s = "cga";)124 L (43 })0(111)100(len += snprint\(p+len, READSTR-len, "type %s\\n", s\);)116 L (44)0(112)100 L (45 int)0(113)100(if\(scr->gscreen\) {)116 L (46 vgawalk\(Chan* c, char* name\))0(114)100(len += snprint\(p+len, READSTR-len, "size %dx%dx%d %s\\n",)124 L (47 {)0(115)100(scr->gscreen->r.max.x, scr->gscreen->r.max.y,)132 L (48)0(return devwalk\(c, name, vgadir, nelem\(vgadir\), devgen\);)8(116)100(scr->gscreen->depth, chantostr\(chbuf, scr->gscreen->chan\)\);)132 L (49 })0(117)100 L (50)0(118)100(if\(Dx\(scr->gscreen->r\) != Dx\(physgscreenr\))124 L (51 static void)0(119)100(|| Dy\(scr->gscreen->r\) != Dy\(physgscreenr\)\))124 L (52 vgastat\(Chan* c, char* dp\))0(120)100(len += snprint\(p+len, READSTR-len, "actualsize %dx%d\\n",)132 L (53 {)0(121)100(physgscreenr.max.x, physgscreenr.max.y\);)140 L (54)0(devstat\(c, dp, vgadir, nelem\(vgadir\), devgen\);)8(122)100(})116 L (55 })0(123)100 L (56)0(124)100(len += snprint\(p+len, READSTR-len, "blanktime %lud\\n", blanktime\);)116 L (57 static Chan*)0(125)100(len += snprint\(p+len, READSTR-len, "hwaccel %s\\n", hwaccel ? "on" : "off"\);)116 L (58 vgaopen\(Chan* c, int omode\))0(126)100(len += snprint\(p+len, READSTR-len, "hwblank %s\\n", hwblank ? "on" : "off"\);)116 L (59 {)0(127)100(snprint\(p+len, READSTR-len, "addr 0x%lux\\n", scr->aperture\);)116 L (60)0(return devopen\(c, omode, vgadir, nelem\(vgadir\), devgen\);)8(128)100(n = readstr\(offset, a, n, p\);)116 L (61 })0(129)100(poperror\(\);)116 L (62)0(130)100(free\(p\);)116 L (63 static void)0(131)100 L (64 vgaclose\(Chan*\))0(132)100(return n;)116 L (65 {)0(133)100 L (66 })0(134 default:)100 L (67)0(135)100(error\(Egreg\);)116 L (68 static void)0(136)100(break;)116 L cleartomark showpage saveobj restore %%EndPage: 43 43 %%Page: 44 44 /saveobj save def mark 44 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devvga.c Page 2)l ()l ()l (137 })0(205)100(error\(Ebadarg\);)124 L (138)0(206)100(if\(drawhasclients\(\)\))116 L (139 return 0;)0(207)100(error\(Ebusy\);)124 L (140 })0(208)100 L (141)0(209)100(x = strtoul\(field[1], &p, 0\);)116 L (142 static char Ebusy[] = "vga already configured";)0(210)100(if\(x == 0 || x > 2048\))116 L (143)0(211)100(error\(Ebadarg\);)124 L (144 static void)0(212)100(if\(*p\))116 L (145 vgactl\(char* a\))0(213)100(p++;)124 L (146 {)0(214)100 L (147 int align, i, n, size, x, y, z;)0(215)100(y = strtoul\(p, &p, 0\);)116 L (148 char *chanstr, *field[6], *p;)0(216)100(if\(y == 0 || y > 2048\))116 L (149 ulong chan;)0(217)100(error\(Ebadarg\);)124 L (150 VGAscr *scr;)0(218)100(if\(*p\))116 L (151 extern VGAdev *vgadev[];)0(219)100(p++;)124 L (152 extern VGAcur *vgacur[];)0(220)100 L (153 Rectangle r;)0(221)100(z = strtoul\(p, &p, 0\);)116 L (154)0(222)100 L (155 n = getfields\(a, field, nelem\(field\), 1, " \\t\\n"\);)0(223)100(chanstr = field[2];)116 L (156 if\(n < 1\))0(224)100(if\(\(chan = strtochan\(chanstr\)\) == 0\))116 L (157)0(error\(Ebadarg\);)16(225)100(error\("bad channel"\);)124 L (158)0(226)100 L (159 scr = &vgascreen[0];)0(227)100(if\(chantodepth\(chan\) != z\))116 L (160 if\(strcmp\(field[0], "hwgc"\) == 0\){)0(228)100(error\("depth, channel do not match"\);)124 L (161)0(if\(n < 2\))16(229)100 L (162)0(error\(Ebadarg\);)24(230)100(cursoroff\(1\);)116 L (163)0(231)100(deletescreenimage\(\);)116 L (164)0(if\(strcmp\(field[1], "off"\) == 0\){)16(232)100(if\(screensize\(x, y, z, chan\)\))116 L (165)0(lock\(&cursor\);)24(233)100(error\(Egreg\);)124 L (166)0(if\(scr->cur\){)24(234)100(vgascreenwin\(scr\);)116 L (167)0(if\(scr->cur->disable\))32(235)100(cursoron\(1\);)116 L (168)0(scr->cur->disable\(scr\);)40(236)100(return;)116 L (169)0(scr->cur = nil;)32(237 })100 L (170)0(})24(238 else if\(strcmp\(field[0], "actualsize"\) == 0\){)100 L (171)0(unlock\(&cursor\);)24(239)100(if\(scr->gscreen == nil\))116 L (172)0(return;)24(240)100(error\("set the screen size first"\);)124 L (173)0(})16(241)100 L (174)0(242)100(if\(n < 2\))116 L (175)0(for\(i = 0; vgacur[i]; i++\){)16(243)100(error\(Ebadarg\);)124 L (176)0(if\(strcmp\(field[1], vgacur[i]->name\)\))24(244)100(x = strtoul\(field[1], &p, 0\);)116 L (177)0(continue;)32(245)100(if\(x == 0 || x > 2048\))116 L (178)0(lock\(&cursor\);)24(246)100(error\(Ebadarg\);)124 L (179)0(if\(scr->cur && scr->cur->disable\))24(247)100(if\(*p\))116 L (180)0(scr->cur->disable\(scr\);)32(248)100(p++;)124 L (181)0(scr->cur = vgacur[i];)24(249)100 L (182)0(if\(scr->cur->enable\))24(250)100(y = strtoul\(p, nil, 0\);)116 L (183)0(scr->cur->enable\(scr\);)32(251)100(if\(y == 0 || y > 2048\))116 L (184)0(unlock\(&cursor\);)24(252)100(error\(Ebadarg\);)124 L (185)0(return;)24(253)100 L (186)0(})16(254)100(if\(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y\))116 L (187 })0(255)100(error\("physical screen bigger than virtual"\);)124 L (188 else if\(strcmp\(field[0], "type"\) == 0\){)0(256)100 L (189)0(if\(n < 2\))16(257)100(r = Rect\(0,0,x,y\);)116 L (190)0(error\(Ebadarg\);)24(258)100(if\(!eqrect\(r, scr->gscreen->r\)\){)116 L (191)0(259)100(if\(scr->cur == nil || scr->cur->doespanning == 0\))124 L (192)0(for\(i = 0; vgadev[i]; i++\){)16(260)100(error\("virtual screen not supported"\);)132 L (193)0(if\(strcmp\(field[1], vgadev[i]->name\)\))24(261)100(})116 L (194)0(continue;)32(262)100 L (195)0(if\(scr->dev && scr->dev->disable\))24(263)100(physgscreenr = r;)116 L (196)0(scr->dev->disable\(scr\);)32(264)100(return;)116 L (197)0(scr->dev = vgadev[i];)24(265 })100 L (198)0(if\(scr->dev->enable\))24(266 else if\(strcmp\(field[0], "palettedepth"\) == 0\){)100 L (199)0(scr->dev->enable\(scr\);)32(267)100(if\(n < 2\))116 L (200)0(return;)24(268)100(error\(Ebadarg\);)124 L (201)0(})16(269)100 L (202 })0(270)100(x = strtoul\(field[1], &p, 0\);)116 L (203 else if\(strcmp\(field[0], "size"\) == 0\){)0(271)100(if\(x != 8 && x != 6\))116 L (204)0(if\(n < 3\))16(272)100(error\(Ebadarg\);)124 L cleartomark showpage saveobj restore %%EndPage: 44 44 %%Page: 45 45 /saveobj save def mark 45 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/devvga.c Page 3)l ()l ()l (273)0(341 vgawrite\(Chan* c, void* a, long n, vlong off\))100 L (274)0(scr->palettedepth = x;)16(342 {)100 L (275)0(return;)16(343 char *p;)100 L (276 })0(344 ulong offset = off;)100 L (277 else if\(strcmp\(field[0], "drawinit"\) == 0\){)0(345)100 L (278)0(if\(scr && scr->dev && scr->dev->drawinit\))16(346 switch\(c->qid.path & ~CHDIR\){)100 L (279)0(scr->dev->drawinit\(scr\);)24(347)100 L (280)0(return;)16(348 case Qdir:)100 L (281 })0(349)100(error\(Eperm\);)116 L (282 else if\(strcmp\(field[0], "linear"\) == 0\){)0(350)100 L (283)0(if\(n < 2\))16(351 case Qvgactl:)100 L (284)0(error\(Ebadarg\);)24(352)100(if\(offset || n >= READSTR\))116 L (285)0(353)100(error\(Ebadarg\);)124 L (286)0(size = strtoul\(field[1], 0, 0\);)16(354)100(p = malloc\(READSTR\);)116 L (287)0(if\(n < 3\))16(355)100(if\(waserror\(\)\){)116 L (288)0(align = 0;)24(356)100(free\(p\);)124 L (289)0(else)16(357)100(nexterror\(\);)124 L (290)0(align = strtoul\(field[2], 0, 0\);)24(358)100(})116 L (291)0(if\(screenaperture\(size, align\)\))16(359)100(memmove\(p, a, n\);)116 L (292)0(error\("not enough free address space"\);)24(360)100(p[n] = 0;)116 L (293)0(return;)16(361)100(vgactl\(p\);)116 L (294 })0(362)100(poperror\(\);)116 L (295 /*)0(else if\(strcmp\(field[0], "memset"\) == 0\){)16(363)100(free\(p\);)116 L (296)0(if\(n < 4\))16(364)100(return n;)116 L (297)0(error\(Ebadarg\);)24(365)100 L (298)0(memset\(\(void*\)strtoul\(field[1], 0, 0\), atoi\(field[2]\), atoi\(field[3]\)\);)16(366 default:)100 L (299)0(return;)16(367)100(error\(Egreg\);)116 L (300 })0(368)100(break;)116 L (301 */)0(369 })100 L (302 else if\(strcmp\(field[0], "blank"\) == 0\){)0(370)100 L (303)0(if\(n < 1\))16(371 return 0;)100 L (304)0(error\(Ebadarg\);)24(372 })100 L (305)0(drawblankscreen\(1\);)16(373)100 L (306)0(return;)16(374 Dev vgadevtab = {)100 L (307 })0(375 'v',)100 L (308 else if\(strcmp\(field[0], "blanktime"\) == 0\){)0(376 "vga",)100 L (309)0(if\(n < 2\))16(377)100 L (310)0(error\(Ebadarg\);)24(378 vgareset,)100 L (311)0(blanktime = strtoul\(field[1], 0, 0\);)16(379 devinit,)100 L (312)0(return;)16(380 vgaattach,)100 L (313 })0(381 devclone,)100 L (314 else if\(strcmp\(field[0], "hwaccel"\) == 0\){)0(382 vgawalk,)100 L (315)0(if\(n < 2\))16(383 vgastat,)100 L (316)0(error\(Ebadarg\);)24(384 vgaopen,)100 L (317)0(if\(strcmp\(field[1], "on"\) == 0\))16(385 devcreate,)100 L (318)0(hwaccel = 1;)24(386 vgaclose,)100 L (319)0(else if\(strcmp\(field[1], "off"\) == 0\))16(387 vgaread,)100 L (320)0(hwaccel = 0;)24(388 devbread,)100 L (321)0(else)16(389 vgawrite,)100 L (322)0(error\(Ebadarg\);)24(390 devbwrite,)100 L (323)0(return;)16(391 devremove,)100 L (324 })0(392 devwstat,)100 L (325 else if\(strcmp\(field[0], "hwblank"\) == 0\){)0(393 };)100 L (326)0(if\(n < 2\))16 L (327)0(error\(Ebadarg\);)24 L (328)0(if\(strcmp\(field[1], "on"\) == 0\))16 L (329)0(hwblank = 1;)24 L (330)0(else if\(strcmp\(field[1], "off"\) == 0\))16 L (331)0(hwblank = 0;)24 L (332)0(else)16 L (333)0(error\(Ebadarg\);)24 L (334)0(return;)16 L (335 })l (336)l (337 error\(Ebadarg\);)l (338 })l (339)l (340 static long)l cleartomark showpage saveobj restore %%EndPage: 45 45 %%Page: 46 46 /saveobj save def mark 46 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/fns.h Page 1)l ()l ()l (1 #include "../port/portfns.h")0(69 #define mmunewpage\(x\))100 L (2)0(70 ulong* mmuwalk\(ulong*, ulong, int, int\);)100 L (3 void)0(aamloop\(int\);)16(71 void)100(ns16552install\(void\);)116 L (4 void)0(addconf\(char*, char*\);)16(72 void)100(ns16552special\(int, int, Queue**, Queue**, int \(*\)\(Queue*, int\)\);)116 L (5 //void addscsilink\(char*, Scsiio \(*\)\(int, ISAConf*\)\);)0(73 uchar nvramread\(int\);)100 L (6 void)0(archinit\(void\);)16(74 void)100(nvramwrite\(int, uchar\);)116 L (7 void)0(bootargs\(ulong\);)16(75 void)100(outb\(int, int\);)116 L (8 int)0(cistrcmp\(char*, char*\);)16(76 void)100(outsb\(int, void*, int\);)116 L (9 int)0(cistrncmp\(char*, char*, int\);)16(77 void)100(outs\(int, ushort\);)116 L (10 #define clearmmucache\(\))0(/* x86 doesn't have one */)56(78 void)100(outss\(int, void*, int\);)116 L (11 void)0(clockintr\(Ureg*, void*\);)16(79 void)100(outl\(int, ulong\);)116 L (12 void)0(\(*coherence\)\(void\);)16(80 void)100(outsl\(int, void*, int\);)116 L (13 void)0(cpuid\(char*, int*, int*\);)16(81 int)100(pcicfgr8\(Pcidev*, int\);)116 L (14 int)0(cpuidentify\(void\);)16(82 int)100(pcicfgr16\(Pcidev*, int\);)116 L (15 void)0(cpuidprint\(void\);)16(83 int)100(pcicfgr32\(Pcidev*, int\);)116 L (16 void)0(delay\(int\);)16(84 void)100(pcicfgw8\(Pcidev*, int, int\);)116 L (17 int)0(dmacount\(int\);)16(85 void)100(pcicfgw16\(Pcidev*, int, int\);)116 L (18 int)0(dmadone\(int\);)16(86 void)100(pcicfgw32\(Pcidev*, int, int\);)116 L (19 void)0(dmaend\(int\);)16(87 void)100(pcihinv\(Pcidev*\);)116 L (20 int)0(dmainit\(int, int\);)16(88 Pcidev* pcimatch\(Pcidev*, int, int\);)100 L (21 long)0(dmasetup\(int, void*, long, int\);)16(89 Pcidev* pcimatchtbdf\(int\);)100 L (22 #define evenaddr\(x\))0(/* x86 doesn't care */)56(90 void)100(pcireset\(void\);)116 L (23 void)0(fpenv\(FPsave*\);)16(91 void)100(pcisetbme\(Pcidev*\);)116 L (24 void)0(fpinit\(void\);)16(92 int)100(pcmcistuple\(int, int, void*, int\);)116 L (25 void)0(fpoff\(void\);)16(93 PCMmap* pcmmap\(int, ulong, int, int\);)100 L (26 void)0(fprestore\(FPsave*\);)16(94 int)100(pcmspecial\(char*, ISAConf*\);)116 L (27 void)0(fpsave\(FPsave*\);)16(95 void)100(pcmspecialclose\(int\);)116 L (28 ulong fpstatus\(void\);)0(96 void)100(pcmunmap\(int, PCMmap*\);)116 L (29 ulong getcr0\(void\);)0(97 void)100(printcpufreq\(void\);)116 L (30 ulong getcr2\(void\);)0(98 #define procrestore\(p\))100 L (31 ulong getcr3\(void\);)0(99 void)100(procsave\(Proc*\);)116 L (32 ulong getcr4\(void\);)0(100 void)100(procsetup\(Proc*\);)116 L (33 char* getconf\(char*\);)0(101 void)100(putcr3\(ulong\);)116 L (34 int)0(i8042auxcmd\(int\);)16(102 void)100(putcr4\(ulong\);)116 L (35 void)0(i8042auxenable\(void \(*\)\(int, int\)\);)16(103 void)100(rdmsr\(int, vlong*\);)116 L (36 void)0(i8042reset\(void\);)16(104 void)100(screeninit\(void\);)116 L (37 void)0(i8253init\(int, int\);)16(105 int)100(screenprint\(char*, ...\);)116(/* debugging */)164 L (38 void)0(i8253enable\(void\);)16(106 void)100(\(*screenputs\)\(char*, int\);)116 L (39 uvlong i8253read\(uvlong*\);)0(107 void)100(touser\(void*\);)116 L (40 void)0(i8259init\(void\);)16(108 void)100(trapenable\(int, void \(*\)\(Ureg*, void*\), void*, char*\);)116 L (41 int)0(i8259enable\(Vctl*\);)16(109 void)100(trapinit\(void\);)116 L (42 void)0(idle\(void\);)16(110 int)100(tas\(void*\);)116 L (43 #define idlehands\(\))0(/* nothing to do in the runproc */)48(111 ulong umbmalloc\(ulong, int, int\);)100 L (44 int)0(inb\(int\);)16(112 void)100(umbfree\(ulong, int\);)116 L (45 void)0(insb\(int, void*, int\);)16(113 ulong umbrwmalloc\(ulong, int, int\);)100 L (46 ushort ins\(int\);)0(114 void)100(umbrwfree\(ulong, int\);)116 L (47 void)0(inss\(int, void*, int\);)16(115 ulong upamalloc\(ulong, int, int\);)100 L (48 ulong inl\(int\);)0(116 void)100(upafree\(ulong, int\);)116 L (49 void)0(insl\(int, void*, int\);)16(117 void)100(vectortable\(void\);)116 L (50 void)0(intrenable\(int, void \(*\)\(Ureg*, void*\), void*, int, char*\);)16(118 void)100(wrmsr\(int, vlong\);)116 L (51 void)0(iofree\(int\);)16(119 void)100(wbflush\(void\);)116 L (52 void)0(ioinit\(void\);)16(120 int)100(xchgw\(ushort*, int\);)116 L (53 int)0(iounused\(int, int\);)16(121 ulong TK2MS\(ulong\);)100(/* ticks to milliseconds */)156 L (54 int)0(ioalloc\(int, int, int, char*\);)16(122)100 L (55 int)0(iprint\(char*, ...\);)16(123 #define waserror\(\))100(\(up->nerrlab++, setlabel\(&up->errlab[up->nerrlab-1]\)\))132 L (56 int)0(irqallocread\(char*, long, vlong\);)16(124 #define KADDR\(a\) \(\(void*\)\(\(ulong\)\(a\)|KZERO\)\))100 L (57 int)0(isaconfig\(char*, int, ISAConf*\);)16(125 #define PADDR\(a\) \(\(ulong\)\(a\)&~KZERO\))100 L (58 void)0(kbdinit\(void\);)16(126)100 L (59 void)0(lgdt\(ushort[3]\);)16(127 #define dcflush\(a, b\))100 L (60 void)0(lidt\(ushort[3]\);)16 L (61 void)0(links\(void\);)16 L (62 void)0(ltr\(ulong\);)16 L (63 void)0(mathinit\(void\);)16 L (64 void)0(meminit\(ulong\);)16 L (65 #define mmuflushtlb\(pdb\) putcr3\(pdb\))l (66 void)0(mmuinit\(void\);)16 L (67 ulong mmukmap\(ulong, ulong, int\);)l (68 int)0(mmukmapsync\(ulong\);)16 L cleartomark showpage saveobj restore %%EndPage: 46 46 %%Page: 47 47 /saveobj save def mark 47 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/i8253.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(*)117 L (2 #include "../port/lib.h")0(70)100(*)117(MOVL loops,CX)140 L (3 #include "mem.h")0(71)100(*)117(aaml1:)124(AAM)140 L (4 #include "dat.h")0(72)100(*)117(LOOP aaml1)140 L (5 #include "fns.h")0(73)100(*)117 L (6 #include "io.h")0(74)100(* the time for the loop should be independent of external)117 L (7)0(75)100(* cache and memory system since it fits in the execution)117 L (8 /*)0(76)100(* prefetch buffer.)117 L (9)0(* 8253 timer)7(77)100(*)117 L (10 */)0(78)100(*/)117 L (11 enum)0(79)100(outb\(Tmode, Latch0\);)116 L (12 {)0(80)100(if\(havecycleclock\))116 L (13)0(T0cntr= 0x40,)8(/* counter ports */)32(81)100(rdmsr\(0x10, &a\);)124 L (14)0(T1cntr= 0x41,)8(/* ... */)32(82)100(x = inb\(T0cntr\);)116 L (15)0(T2cntr= 0x42,)8(/* ... */)32(83)100(x |= inb\(T0cntr\)<<8;)116 L (16)0(Tmode= 0x43,)8(/* mode port */)32(84)100(aamloop\(loops\);)116 L (17)0(85)100(outb\(Tmode, Latch0\);)116 L (18)0(/* commands */)8(86)100(if\(havecycleclock\))116 L (19)0(Latch0= 0x00,)8(/* latch counter 0's value */)32(87)100(rdmsr\(0x10, &b\);)124 L (20)0(Load0= 0x30,)8(/* load counter 0 with 2 bytes */)32(88)100(y = inb\(T0cntr\);)116 L (21)0(89)100(y |= inb\(T0cntr\)<<8;)116 L (22)0(/* modes */)8(90)100(x -= y;)116 L (23)0(Square= 0x36,)8(/* periodic square wave */)32(91)100 L (24)0(Trigger= 0x30,)8(/* interrupt on terminal count */)32(92)100(if\(x < 0\))116 L (25)0(93)100(x += Freq/HZ;)124 L (26)0(Freq= 1193182,)8(/* Real clock frequency */)32(94)100 L (27 };)0(95)100(if\(x > Freq/\(3*HZ\)\))116 L (28)0(96)100(break;)124 L (29 void)0(97)100(})108 L (30 i8253init\(int aalcycles, int havecycleclock\))0(98)100 L (31 {)0(99)100(/*)108 L (32)0(int cpufreq, loops, incr, x, y;)8(100)100(* figure out clock frequency and a loop multiplier for delay\(\).)109 L (33)0(vlong a, b;)8(101)100(* n.b. counter goes up by 2*Freq)109 L (34)0(static int initialised;)8(102)100(*/)109 L (35)0(103 cpufreq = loops*\(\(aalcycles*2*Freq\)/x\);)100 L (36)0(if\(initialised == 0\){)8(104 m->loopconst = \(cpufreq/1000\)/aalcycles;)100(/* AAM+LOOP's for 1 ms */)156 L (37)0(initialised = 1;)16(105)100 L (38)0(ioalloc\(T0cntr, 4, 0, "i8253"\);)16(106 if\(havecycleclock\){)100 L (39)0(/*)16(107)100 L (40)0(* set clock for 1/HZ seconds)17(108)100(/* counter goes up by 2*Freq */)116 L (41)0(*/)17(109)100(b = \(b-a\)<<1;)116 L (42)0(outb\(Tmode, Load0|Square\);)16(110)100(b *= Freq;)116 L (43)0(outb\(T0cntr, \(Freq/HZ\)\);)16(/* low byte */)48(111)100(b /= x;)116 L (44)0(outb\(T0cntr, \(Freq/HZ\)>>8\); /* high byte */)16(112)100 L (45)0(113)100(/*)116 L (46)0(/*)16(114)100(* round to the nearest megahz)117 L (47)0(* Introduce a little delay to make sure the count is)17(115)100(*/)117 L (48)0(* latched and the timer is counting down; with a fast)17(116)100(m->cpumhz = \(b+500000\)/1000000L;)116 L (49)0(* enough processor this may not be the case.)17(117)100(m->cpuhz = b;)116 L (50)0(* The i8254 \(which this probably is\) has a read-back)17(118 } else {)100 L (51)0(* command which can be used to make sure the counting)17(119)100(/*)116 L (52)0(* register has been written into the counting element.)17(120)100(* add in possible 0.5% error and convert to MHz)117 L (53)0(*/)17(121)100(*/)117 L (54)0(x = \(Freq/HZ\);)16(122)100(m->cpumhz = \(cpufreq + cpufreq/200\)/1000000;)116 L (55)0(for\(loops = 0; loops < 100000 && x >= \(Freq/HZ\); loops++\){)16(123)100(m->cpuhz = cpufreq;)116 L (56)0(outb\(Tmode, Latch0\);)24(124 })100 L (57)0(x = inb\(T0cntr\);)24(125 })100 L (58)0(x |= inb\(T0cntr\)<<8;)24(126)100 L (59)0(})16(127 void)100 L (60)0(})8(128 i8253enable\(void\))100 L (61)0(129 {)100 L (62)0(/* find biggest loop that doesn't wrap */)8(130 intrenable\(IrqCLOCK, clockintr, 0, BUSUNKNOWN, "clock"\);)100 L (63)0(incr = 16000000/\(aalcycles*HZ*2\);)8(131 })100 L (64)0(x = 2000;)8(132)100 L (65)0(for\(loops = incr; loops < 64*1024; loops += incr\) {)8(133 /*)100 L (66)0(134 * return time elapsed since clock start in)100 L (67)0(/*)16(135 * 100 times hz)100 L (68)0(* measure time for the loop)17(136 */)100 L cleartomark showpage saveobj restore %%EndPage: 47 47 %%Page: 48 48 /saveobj save def mark 48 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/i8253.c Page 2)l ()l ()l (137 uvlong)l (138 i8253read\(uvlong *hz\))l (139 {)l (140 if\(hz\))l (141)0(*hz = HZ*100;)16 L (142 return m->ticks*100;)l (143 })l cleartomark showpage saveobj restore %%EndPage: 48 48 %%Page: 49 49 /saveobj save def mark 49 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/i8259.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(i8259mask &= ~0x04;)108 L (2 #include "../port/lib.h")0(70)100(outb\(Int0aux, i8259mask & 0xFF\);)108 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72)100(/*)108 L (5 #include "fns.h")0(73)100(* Set Ocw3 to return the ISR when ctl read.)109 L (6 #include "io.h")0(74)100(* After initialisation status read is set to IRR.)109 L (7)0(75)100(* Read IRR first to possibly deassert an outstanding)109 L (8 /*)0(76)100(* interrupt.)109 L (9)0(* 8259 interrupt controllers)7(77)100(*/)109 L (10 */)0(78)100(inb\(Int0ctl\);)108 L (11 enum)0(79)100(outb\(Int0ctl, Ocw3|0x03\);)108 L (12 {)0(80)100(inb\(Int1ctl\);)108 L (13)0(Int0ctl=)8(0x20,)24(/* control port \(ICW1, OCW2, OCW3\) */)40(81)100(outb\(Int1ctl, Ocw3|0x03\);)108 L (14)0(Int0aux=)8(0x21,)24(/* everything else \(ICW2, ICW3, ICW4, OCW1\) */)40(82)100 L (15)0(Int1ctl=)8(0xA0,)24(/* control port */)40(83)100(/*)108 L (16)0(Int1aux=)8(0xA1,)24(/* everything else \(ICW2, ICW3, ICW4, OCW1\) */)40(84)100(* Check for Edge/Level register.)109 L (17)0(85)100(* This check may not work for all chipsets.)109 L (18)0(Icw1=)8(0x10,)24(/* select bit in ctl register */)40(86)100(* First try a non-intrusive test - the bits for)109 L (19)0(Ocw2=)8(0x00,)24(87)100(* IRQs 13, 8, 2, 1 and 0 must be edge \(0\). If)109 L (20)0(Ocw3=)8(0x08,)24(88)100(* that's OK try a R/W test.)109 L (21)0(89)100(*/)109 L (22)0(EOI=)8(0x20,)24(/* non-specific end of interrupt */)40(90)100(x = \(inb\(Elcr2\)<<8\)|inb\(Elcr1\);)108 L (23)0(91)100(if\(!\(x & 0x2107\)\){)108 L (24)0(Elcr1=)8(0x4D0,)24(/* Edge/Level Triggered Register */)40(92)100(outb\(Elcr1, 0\);)116 L (25)0(Elcr2=)8(0x4D1,)24(93)100(if\(inb\(Elcr1\) == 0\){)116 L (26 };)0(94)100(outb\(Elcr1, 0x20\);)124 L (27)0(95)100(if\(inb\(Elcr1\) == 0x20\))124 L (28 static Lock i8259lock;)0(96)100(i8259elcr = x;)132 L (29 static int i8259mask = 0xFFFF;)0(/* disabled interrupts */)48(97)100(outb\(Elcr1, x & 0xFF\);)124 L (30 int i8259elcr;)0(/* mask of level-triggered interrupts */)48(98)100(//print\("ELCR: %4.4uX\\n", i8259elcr\);)124 L (31)0(99)100(})116 L (32 void)0(100 })100 L (33 i8259init\(void\))0(101 iunlock\(&i8259lock\);)100 L (34 {)0(102 })100 L (35)0(int x;)8(103)100 L (36)0(104 int)100 L (37)0(ioalloc\(Int0ctl, 2, 0, "i8259.0"\);)8(105 i8259isr\(int vno\))100 L (38)0(ioalloc\(Int1ctl, 2, 0, "i8259.1"\);)8(106 {)100 L (39)0(ilock\(&i8259lock\);)8(107 int irq, isr;)100 L (40)0(108)100 L (41)0(/*)8(109 if\(vno < VectorPIC || vno > VectorPIC+MaxIrqPIC\))100 L (42)0(* Set up the first 8259 interrupt processor.)9(110)100(return 0;)116 L (43)0(* Make 8259 interrupts start at CPU vector VectorPIC.)9(111 irq = vno-VectorPIC;)100 L (44)0(* Set the 8259 as master with edge triggered)9(112)100 L (45)0(* input with fully nested interrupts.)9(113 /*)100 L (46)0(*/)9(114)100(* tell the 8259 that we're done with the)109 L (47)0(outb\(Int0ctl, \(1<<4\)|\(0<<3\)|\(1<<0\)\); /* ICW1 - master, edge triggered,)8(115)100(* highest level interrupt \(interrupts are still)109 L (48)0(ICW4 will be sent */)51(116)100(* off at this point\))109 L (49)0(outb\(Int0aux, VectorPIC\);)8(/* ICW2 - interrupt vector offset */)48(117)100(*/)109 L (50)0(outb\(Int0aux, 0x04\);)8(/* ICW3 - have slave on level 2 */)48(118 ilock\(&i8259lock\);)100 L (51)0(outb\(Int0aux, 0x01\);)8(/* ICW4 - 8086 mode, not buffered */)48(119 isr = inb\(Int0ctl\);)100 L (52)0(120 outb\(Int0ctl, EOI\);)100 L (53)0(/*)8(121 if\(irq >= 8\){)100 L (54)0(* Set up the second 8259 interrupt processor.)9(122)100(isr |= inb\(Int1ctl\)<<8;)116 L (55)0(* Make 8259 interrupts start at CPU vector VectorPIC+8.)9(123)100(outb\(Int1ctl, EOI\);)116 L (56)0(* Set the 8259 as slave with edge triggered)9(124 })100 L (57)0(* input with fully nested interrupts.)9(125 iunlock\(&i8259lock\);)100 L (58)0(*/)9(126)100 L (59)0(outb\(Int1ctl, \(1<<4\)|\(0<<3\)|\(1<<0\)\); /* ICW1 - master, edge triggered,)8(127 return isr & \(1<>8\) & 0xFF\);)8(132 {)100 L (65)0(133 int irq, irqbit;)100 L (66)0(/*)8(134)100 L (67)0(* pass #2 8259 interrupts to #1)9(135 /*)100 L (68)0(*/)9(136)100(* Given an IRQ, enable the corresponding interrupt in the i8259)109 L cleartomark showpage saveobj restore %%EndPage: 49 49 %%Page: 50 50 /saveobj save def mark 50 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/i8259.c Page 2)l ()l ()l (137)0(* and return the vector to be used. The i8259 is set to use a fixed)9 L (138)0(* range of vectors starting at VectorPIC.)9 L (139)0(*/)9 L (140 irq = v->irq;)l (141 if\(irq < 0 || irq > MaxIrqPIC\){)l (142)0(print\("i8259enable: irq %d out of range\\n", irq\);)16 L (143)0(return -1;)16 L (144 })l (145 irqbit = 1<>8\) & 0xFF\);)16 L (158)l (159 if\(i8259elcr & irqbit\))l (160)0(v->eoi = i8259isr;)16 L (161 else)l (162)0(v->isr = i8259isr;)16 L (163 iunlock\(&i8259lock\);)l (164)l (165 return VectorPIC+irq;)l (166 })l cleartomark showpage saveobj restore %%EndPage: 50 50 %%Page: 51 51 /saveobj save def mark 51 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/io.h Page 1)l ()l ()l (1 #define X86STEPPING\(x\) \(\(x\) & 0x0F\))0(69)100(BusMPSA,)108(/* MPSA */)140 L (2 #define X86MODEL\(x\))0(\(\(\(x\)>>4\) & 0x0F\))32(70)100(BusNUBUS,)108(/* Apple Macintosh NuBus */)140 L (3 #define X86FAMILY\(x\))0(\(\(\(x\)>>8\) & 0x0F\))32(71)100(BusPCI,)108(/* Peripheral Component Interconnect */)140 L (4)0(72)100(BusPCMCIA,)108(/* PC Memory Card International Association */)140 L (5 enum {)0(73)100(BusTC,)108(/* DEC TurboChannel */)140 L (6)0(VectorNMI)8(= 2,)24(/* non-maskable interrupt */)40(74)100(BusVL,)108(/* VESA Local bus */)140 L (7)0(VectorBPT)8(= 3,)24(/* breakpoint */)40(75)100(BusVME,)108(/* VMEbus */)140 L (8)0(VectorUD)8(= 6,)24(/* invalid opcode exception */)40(76)100(BusXPRESS,)108(/* Express System Bus */)140 L (9)0(VectorCNA)8(= 7,)24(/* coprocessor not available */)40(77 };)100 L (10)0(VectorCSO)8(= 9,)24(/* coprocessor segment overrun */)40(78)100 L (11)0(VectorPF)8(= 14,)24(/* page fault */)40(79 #define MKBUS\(t,b,d,f\) \(\(\(t\)<<24\)|\(\(\(b\)&0xFF\)<<16\)|\(\(\(d\)&0x1F\)<<11\)|\(\(\(f\)&0x07\)<<8\)\))100 L (12)0(VectorCERR)8(= 16,)24(/* coprocessor error */)40(80 #define BUSFNO\(tbdf\))100(\(\(\(tbdf\)>>8\)&0x07\))132 L (13)0(81 #define BUSDNO\(tbdf\))100(\(\(\(tbdf\)>>11\)&0x1F\))132 L (14)0(VectorPIC)8(= 32,)24(/* external i8259 interrupts */)40(82 #define BUSBNO\(tbdf\))100(\(\(\(tbdf\)>>16\)&0xFF\))132 L (15)0(IrqCLOCK)8(= 0,)24(83 #define BUSTYPE\(tbdf\) \(\(tbdf\)>>24\))100 L (16)0(IrqKBD)8(= 1,)24(84 #define BUSBDF\(tbdf\))100(\(\(tbdf\)&0x00FFFF00\))132 L (17)0(IrqUART1)8(= 3,)24(85 #define BUSUNKNOWN)100(\(-1\))132 L (18)0(IrqUART0)8(= 4,)24(86)100 L (19)0(IrqPCMCIA)8(= 5,)24(87 enum {)100 L (20)0(IrqFLOPPY)8(= 6,)24(88)100(MaxEISA)108(= 16,)124 L (21)0(IrqLPT)8(= 7,)24(89)100(CfgEISA)108(= 0xC80,)124 L (22)0(IrqIRQ7)8(= 7,)24(90 };)100 L (23)0(IrqAUX)8(= 12,)24(/* PS/2 port */)40(91)100 L (24)0(IrqIRQ13)8(= 13,)24(/* coprocessor on 386 */)40(92 /*)100 L (25)0(IrqATA0)8(= 14,)24(93 * PCI support code.)100 L (26)0(IrqATA1)8(= 15,)24(94 */)100 L (27)0(MaxIrqPIC)8(= 15,)24(95 enum {)100(/* type 0 and type 1 pre-defined header */)148 L (28)0(96)100(PciVID)108(= 0x00,)124(/* vendor ID */)140 L (29)0(VectorLAPIC = VectorPIC+16, /* local APIC interrupts */)8(97)100(PciDID)108(= 0x02,)124(/* device ID */)140 L (30)0(IrqLINT0)8(= 16,)24(/* LINT[01] must be offsets 0 and 1 */)40(98)100(PciPCR)108(= 0x04,)124(/* command */)140 L (31)0(IrqLINT1)8(= 17,)24(99)100(PciPSR)108(= 0x06,)124(/* status */)140 L (32)0(IrqTIMER)8(= 18,)24(100 PciRID)100(= 0x08,)124(/* revision ID */)140 L (33)0(IrqERROR)8(= 19,)24(101 PciCCRp)100(= 0x09,)124(/* programming interface class code */)140 L (34)0(IrqPCINT)8(= 20,)24(102 PciCCRu)100(= 0x0A,)124(/* sub-class code */)140 L (35)0(IrqSPURIOUS = 31,)8(/* must have bits [3-0] == 0x0F */)40(103 PciCCRb)100(= 0x0B,)124(/* base class code */)140 L (36)0(MaxIrqLAPIC = 31,)8(104 PciCLS)100(= 0x0C,)124(/* cache line size */)140 L (37)0(105 PciLTR)100(= 0x0D,)124(/* latency timer */)140 L (38)0(VectorSYSCALL = 64,)8(106 PciHDT)100(= 0x0E,)124(/* header type */)140 L (39)0(107 PciBST)100(= 0x0F,)124(/* BIST */)140 L (40)0(VectorAPIC)8(= 65,)24(/* external APIC interrupts */)40(108)100 L (41)0(MaxVectorAPIC = 255,)8(109 PciBAR0)100(= 0x10,)124(/* base address */)140 L (42 };)0(110 PciBAR1)100(= 0x14,)124 L (43)0(111)100 L (44 typedef struct Vctl {)0(112 PciINTL)100(= 0x3C,)124(/* interrupt line */)140 L (45)0(Vctl* next;)8(/* handlers on this vector */)40(113 PciINTP)100(= 0x3D,)124(/* interrupt pin */)140 L (46)0(114 };)100 L (47)0(char name[NAMELEN];)8(/* of driver */)40(115)100 L (48)0(int isintr;)8(/* interrupt or fault/trap */)40(116 enum {)100(/* type 0 pre-defined header */)148 L (49)0(int irq;)8(117 PciBAR2)100(= 0x18,)124 L (50)0(int tbdf;)8(118 PciBAR3)100(= 0x1C,)124 L (51)0(int \(*isr\)\(int\);)8(/* get isr bit for this irq */)40(119 PciBAR4)100(= 0x20,)124 L (52)0(int \(*eoi\)\(int\);)8(/* eoi */)40(120 PciBAR5)100(= 0x24,)124 L (53)0(121 PciCIS)100(= 0x28,)124(/* cardbus CIS pointer */)140 L (54)0(void \(*f\)\(Ureg*, void*\); /* handler to call */)8(122 PciSVID)100(= 0x2C,)124(/* subsystem vendor ID */)140 L (55)0(void* a;)8(/* argument to call it with */)40(123 PciSID)100(= 0x2E,)124(/* cardbus CIS pointer */)140 L (56 } Vctl;)0(124 PciEBAR0)100(= 0x30,)124(/* expansion ROM base address */)140 L (57)0(125 PciMGNT)100(= 0x3E,)124(/* burst period length */)140 L (58 enum {)0(126 PciMLT)100(= 0x3F,)124(/* maximum latency between bursts */)140 L (59)0(BusCBUS)8(= 0,)24(/* Corollary CBUS */)40(127 };)100 L (60)0(BusCBUSII,)8(/* Corollary CBUS II */)40(128)100 L (61)0(BusEISA,)8(/* Extended ISA */)40(129 enum {)100(/* type 1 pre-defined header */)148 L (62)0(BusFUTURE,)8(/* IEEE Futurebus */)40(130 PciPBN)100(= 0x18,)124(/* primary bus number */)140 L (63)0(BusINTERN,)8(/* Internal bus */)40(131 PciSBN)100(= 0x19,)124(/* secondary bus number */)140 L (64)0(BusISA,)8(/* Industry Standard Architecture */)40(132 PciUBN)100(= 0x1A,)124(/* subordinate bus number */)140 L (65)0(BusMBI,)8(/* Multibus I */)40(133 PciSLTR)100(= 0x1B,)124(/* secondary latency timer */)140 L (66)0(BusMBII,)8(/* Multibus II */)40(134 PciIBR)100(= 0x1C,)124(/* I/O base */)140 L (67)0(BusMCA,)8(/* Micro Channel Architecture */)40(135 PciILR)100(= 0x1D,)124(/* I/O limit */)140 L (68)0(BusMPI,)8(/* MPI */)40(136 PciSPSR)100(= 0x1E,)124(/* secondary status */)140 L cleartomark showpage saveobj restore %%EndPage: 51 51 %%Page: 52 52 /saveobj save def mark 52 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/io.h Page 2)l ()l ()l (137 PciMBR)0(= 0x20,)24(/* memory base */)40(205 };)100 L (138 PciMLR)0(= 0x22,)24(/* memory limit */)40(206)100 L (139 PciPMBR)0(= 0x24,)24(/* prefetchable memory base */)40(207 #define PCIWINDOW 0)100 L (140 PciPMLR)0(= 0x26,)24(/* prefetchable memory limit */)40(208 #define PCIWADDR\(va\))100(\(PADDR\(va\)+PCIWINDOW\))132 L (141 PciPUBR)0(= 0x28,)24(/* prefetchable base upper 32 bits */)40(209 #define ISAWINDOW 0)100 L (142 PciPULR)0(= 0x2C,)24(/* prefetchable limit upper 32 bits */)40(210 #define ISAWADDR\(va\))100(\(PADDR\(va\)+ISAWINDOW\))132 L (143 PciIUBR)0(= 0x30,)24(/* I/O base upper 16 bits */)40(211)100 L (144 PciIULR)0(= 0x32,)24(/* I/O limit upper 16 bits */)40(212 /*)100 L (145 PciEBAR1)0(= 0x28,)24(/* expansion ROM base address */)40(213 * PCMCIA support code.)100 L (146 PciBCR)0(= 0x3E,)24(/* bridge control register */)40(214 */)100 L (147 };)0(215 /*)100 L (148)0(216 * Map between ISA memory space and PCMCIA card memory space.)100 L (149 enum {)0(/* type 2 pre-defined header */)48(217 */)100 L (150 PciCBExCA)0(= 0x10,)24(218 struct PCMmap {)100 L (151 PciCBSPSR)0(= 0x16,)24(219 ulong ca;)100(/* card address */)140 L (152 PciCBPBN)0(= 0x18,)24(/* primary bus number */)40(220 ulong cea;)100(/* card end address */)140 L (153 PciCBSBN)0(= 0x19,)24(/* secondary bus number */)40(221 ulong isa;)100(/* ISA address */)140 L (154 PciCBUBN)0(= 0x1A,)24(/* subordinate bus number */)40(222 int len;)100(/* length of the ISA area */)140 L (155 PciCBSLTR)0(= 0x1B,)24(/* secondary latency timer */)40(223 int attr;)100(/* attribute memory */)140 L (156 PciCBMBR0)0(= 0x1C,)24(224 int ref;)100 L (157 PciCBMLR0)0(= 0x20,)24(225 };)100 L (158 PciCBMBR1)0(= 0x24,)24(226)100 L (159 PciCBMLR1)0(= 0x28,)24(227 /* SMBus transactions */)100 L (160 PciCBIBR0)0(= 0x2C,)24(/* I/O base */)40(228 enum)100 L (161 PciCBILR0)0(= 0x30,)24(/* I/O limit */)40(229 {)100 L (162 PciCBIBR1)0(= 0x34,)24(/* I/O base */)40(230 SMBquick,)100(/* sends address only */)132 L (163 PciCBILR1)0(= 0x38,)24(/* I/O limit */)40(231)100 L (164 PciCBSVID)0(= 0x40,)24(/* subsystem vendor ID */)40(232 /* write */)100 L (165 PciCBSID)0(= 0x42,)24(/* subsystem ID */)40(233 SMBsend,)100(/* sends address and cmd */)132 L (166 PciCBLMBAR)0(= 0x44,)24(/* legacy mode base address */)40(234 SMBbytewrite,)100(/* sends address and cmd and 1 byte */)132 L (167 };)0(235 SMBwordwrite,)100(/* sends address and cmd and 2 bytes */)132 L (168)0(236)100 L (169 typedef struct Pcisiz Pcisiz;)0(237 /* read */)100 L (170 struct Pcisiz)0(238 SMBrecv,)100(/* sends address, recvs 1 byte */)132 L (171 {)0(239 SMBbyteread,)100(/* sends address and cmd, recv's byte */)132 L (172 Pcidev* dev;)0(240 SMBwordread,)100(/* sends address and cmd, recv's 2 bytes */)132 L (173 int siz;)0(241 };)100 L (174 int bar;)0(242)100 L (175 };)0(243 typedef struct SMBus SMBus;)100 L (176)0(244 struct SMBus {)100 L (177 typedef struct Pcidev Pcidev;)0(245 QLock;)100(/* mutex */)124 L (178 struct Pcidev)0(246 Rendez r;)100(/* rendezvous point for completion interrupts */)124 L (179 {)0(247 void *arg; /* implementation dependent */)100 L (180 int tbdf;)0(/* type+bus+device+function */)40(248 ulong base; /* port or memory base of smbus */)100 L (181 ushort vid;)0(/* vendor ID */)40(249 int busy;)100 L (182 ushort did;)0(/* device ID */)40(250 void \(*transact\)\(SMBus*, int, int, int, uchar*\);)100 L (183)0(251 };)100 L (184 uchar rid;)l (185 uchar ccrp;)l (186 uchar ccru;)l (187 uchar ccrb;)l (188)l (189 struct {)l (190)0(ulong bar;)16(/* base address */)40 L (191)0(int size;)16 L (192 } mem[6];)l (193)l (194 uchar intl;)0(/* interrupt line */)40 L (195)l (196 Pcidev* list;)l (197 Pcidev* link;)0(/* next device on this bno */)40 L (198)l (199 Pcidev* bridge;)0(/* down a bus */)40 L (200 struct {)l (201)0(ulong bar;)16 L (202)0(int size;)16 L (203 } ioa, mema;)l (204 ulong pcr;)l cleartomark showpage saveobj restore %%EndPage: 52 52 %%Page: 53 53 /saveobj save def mark 53 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/kbd.c Page 1)l ()l ()l (1 #include "u.h")0(69 [0x58] KF|12, No, No, No, No, No, No, No,)100 L (2 #include "../port/lib.h")0(70 [0x60] No, No, No, No, No, No, No, No,)100 L (3 #include "mem.h")0(71 [0x68] No, No, No, No, No, No, No, No,)100 L (4 #include "dat.h")0(72 [0x70] No, No, No, No, No, No, No, No,)100 L (5 #include "fns.h")0(73 [0x78] No, View, No, Up, No, No, No, No,)100 L (6 #include "io.h")0(74 };)100 L (7 #include "../port/error.h")0(75)100 L (8)0(76 Rune kbtabshift[] =)100 L (9 enum {)0(77 {)100 L (10)0(Data=)8(0x60,)24(/* data port */)40(78 [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',)100 L (11)0(79 [0x08] '&', '*', '\(', '\)', '_', '+', '\\b', '\\t',)100 L (12)0(Status=)8(0x64,)24(/* status port */)40(80 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',)100 L (13)0(Inready=)9(0x01,)24(/* input character ready */)40(81 [0x18] 'O', 'P', '{', '}', '\\n', Ctrl, 'A', 'S',)100 L (14)0(Outbusy=)9(0x02,)24(/* output busy */)40(82 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',)100 L (15)0(Sysflag=)9(0x04,)24(/* system flag */)40(83 [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',)100 L (16)0(Cmddata=)9(0x08,)24(/* cmd==0, data==1 */)40(84 [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, '*',)100 L (17)0(Inhibit=)9(0x10,)24(/* keyboard/mouse inhibited */)40(85 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,)100 L (18)0(Minready=)9(0x20,)24(/* mouse character ready */)40(86 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',)100 L (19)0(Rtimeout=)9(0x40,)24(/* general timeout */)40(87 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',)100 L (20)0(Parity=)9(0x80,)24(88 [0x50] '2', '3', '0', '.', No, No, No, KF|11,)100 L (21)0(89 [0x58] KF|12, No, No, No, No, No, No, No,)100 L (22)0(Cmd=)8(0x64,)24(/* command port \(write only\) */)40(90 [0x60] No, No, No, No, No, No, No, No,)100 L (23)0(91 [0x68] No, No, No, No, No, No, No, No,)100 L (24)0(Spec=)8(0x80,)24(92 [0x70] No, No, No, No, No, No, No, No,)100 L (25)0(93 [0x78] No, Up, No, Up, No, No, No, No,)100 L (26)0(PF=)8(Spec|0x20,)24(/* num pad function key */)40(94 };)100 L (27)0(View=)8(Spec|0x00,)24(/* view \(shift window up\) */)40(95)100 L (28)0(KF=)8(0xF000, /* function key \(begin Unicode private space\) */)24(96 Rune kbtabesc1[] =)100 L (29)0(Shift=)8(Spec|0x60,)24(97 {)100 L (30)0(Break=)8(Spec|0x61,)24(98 [0x00] No, No, No, No, No, No, No, No,)100 L (31)0(Ctrl=)8(Spec|0x62,)24(99 [0x08] No, No, No, No, No, No, No, No,)100 L (32)0(Latin=)8(Spec|0x63,)24(100 [0x10] No, No, No, No, No, No, No, No,)100 L (33)0(Caps=)8(Spec|0x64,)24(101 [0x18] No, No, No, No, '\\n', Ctrl, No, No,)100 L (34)0(Num=)8(Spec|0x65,)24(102 [0x20] No, No, No, No, No, No, No, No,)100 L (35)0(Middle=)8(Spec|0x66,)24(103 [0x28] No, No, Shift, No, No, No, No, No,)100 L (36)0(No=)8(0x00,)24(/* peter */)40(104 [0x30] No, No, No, No, No, '/', No, Print,)100 L (37)0(105 [0x38] Latin, No, No, No, No, No, No, No,)100 L (38)0(Home=)8(KF|13,)24(106 [0x40] No, No, No, No, No, No, Break, Home,)100 L (39)0(Up=)8(KF|14,)24(107 [0x48] Up, Pgup, No, Left, No, Right, No, End,)100 L (40)0(Pgup=)8(KF|15,)24(108 [0x50] Down, Pgdown, Ins, Del, No, No, No, No,)100 L (41)0(Print=)8(KF|16,)24(109 [0x58] No, No, No, No, No, No, No, No,)100 L (42)0(Left=)8(KF|17,)24(110 [0x60] No, No, No, No, No, No, No, No,)100 L (43)0(Right=)8(KF|18,)24(111 [0x68] No, No, No, No, No, No, No, No,)100 L (44)0(End=)8('\\r',)24(112 [0x70] No, No, No, No, No, No, No, No,)100 L (45)0(Down=)8(View,)24(113 [0x78] No, Up, No, No, No, No, No, No,)100 L (46)0(Pgdown=)8(KF|19,)24(114 };)100 L (47)0(Ins=)8(KF|20,)24(115)100 L (48)0(Del=)8(0x7F,)24(116 enum)100 L (49)0(Scroll=)8(KF|21,)24(117 {)100 L (50 };)0(118 /* controller command byte */)100 L (51)0(119 Cscs1=)100(\(1<<6\),)124(/* scan code set 1 */)140 L (52 /*)0(120 Cauxdis=)100(\(1<<5\),)124(/* mouse disable */)140 L (53 * The codes at 0x79 and 0x81 are produed by the PFU Happy Hacking keyboard.)0(121 Ckbddis=)100(\(1<<4\),)124(/* kbd disable */)140 L (54 * A 'standard' keyboard doesn't produce anything above 0x58.)0(122 Csf=)100(\(1<<2\),)124(/* system flag */)140 L (55 */)0(123 Cauxint=)100(\(1<<1\),)124(/* mouse interrupt enable */)140 L (56 Rune kbtab[] =)0(124 Ckbdint=)100(\(1<<0\),)124(/* kbd interrupt enable */)140 L (57 {)0(125 };)100 L (58 [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',)0(126)100 L (59 [0x08] '7', '8', '9', '0', '-', '=', '\\b', '\\t',)0(127 static Lock i8042lock;)100 L (60 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',)0(128 static uchar ccc;)100 L (61 [0x18] 'o', 'p', '[', ']', '\\n', Ctrl, 'a', 's',)0(129 static void \(*auxputc\)\(int, int\);)100 L (62 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',)0(130)100 L (63 [0x28] '\\'', '`', Shift, '\\\\', 'z', 'x', 'c', 'v',)0(131 /*)100 L (64 [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, '*',)0(132 * wait for output no longer busy)100 L (65 [0x38] Latin, ' ', Ctrl, KF|1, KF|2, KF|3, KF|4, KF|5,)0(133 */)100 L (66 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, Scroll, '7',)0(134 static int)100 L (67 [0x48] '8', '9', '-', '4', '5', '6', '+', '1',)0(135 outready\(void\))100 L (68 [0x50] '2', '3', '0', '.', No, No, No, KF|11,)0(136 {)100 L cleartomark showpage saveobj restore %%EndPage: 53 53 %%Page: 54 54 /saveobj save def mark 54 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/kbd.c Page 2)l ()l ()l (137 int tries;)0(205 do{)100 L (138)0(206)100(if\(tries++ > 2\))116 L (139 for\(tries = 0; \(inb\(Status\) & Outbusy\); tries++\){)0(207)100(break;)124 L (140)0(if\(tries > 500\))16(208)100(if\(outready\(\) < 0\))116 L (141)0(return -1;)24(209)100(break;)124 L (142)0(delay\(2\);)16(210)100(outb\(Cmd, 0xD4\);)116 L (143 })0(211)100(if\(outready\(\) < 0\))116 L (144 return 0;)0(212)100(break;)124 L (145 })0(213)100(outb\(Data, cmd\);)116 L (146)0(214)100(if\(outready\(\) < 0\))116 L (147 /*)0(215)100(break;)124 L (148 * wait for input)0(216)100(if\(inready\(\) < 0\))116 L (149 */)0(217)100(break;)124 L (150 static int)0(218)100(c = inb\(Data\);)116 L (151 inready\(void\))0(219 } while\(c == 0xFE || c == 0\);)100 L (152 {)0(220 iunlock\(&i8042lock\);)100 L (153 int tries;)0(221)100 L (154)0(222 if\(c != 0xFA\){)100 L (155 for\(tries = 0; !\(inb\(Status\) & Inready\); tries++\){)0(223)100(print\("i8042: %2.2ux returned to the %2.2ux command\\n", c, cmd\);)116 L (156)0(if\(tries > 500\))16(224)100(return -1;)116 L (157)0(return -1;)24(225 })100 L (158)0(delay\(2\);)16(226 return 0;)100 L (159 })0(227 })100 L (160 return 0;)0(228)100 L (161 })0(229 /*)100 L (162)0(230 * keyboard interrupt)100 L (163 /*)0(231 */)100 L (164 * ask 8042 to reset the machine)0(232 static void)100 L (165 */)0(233 i8042intr\(Ureg*, void*\))100 L (166 void)0(234 {)100 L (167 i8042reset\(void\))0(235 int s, c, i;)100 L (168 {)0(236 static int esc1, esc2;)100 L (169 ushort *s = KADDR\(0x472\);)0(237 static int alt, caps, ctl, num, shift;)100 L (170 int i, x;)0(238 static int collecting, nk;)100 L (171)0(239 static Rune kc[5];)100 L (172 *s = 0x1234;)0(/* BIOS warm-boot flag */)32(240 int keyup;)100 L (173)0(241)100 L (174 /*)0(242 /*)100 L (175)0(* newer reset the machine command)9(243)100(* get status)109 L (176)0(*/)9(244)100(*/)109 L (177 outready\(\);)0(245 lock\(&i8042lock\);)100 L (178 outb\(Cmd, 0xFE\);)0(246 s = inb\(Status\);)100 L (179 outready\(\);)0(247 if\(!\(s&Inready\)\){)100 L (180)0(248)100(unlock\(&i8042lock\);)116 L (181 /*)0(249)100(return;)116 L (182)0(* Pulse it by hand \(old somewhat reliable\))9(250 })100 L (183)0(*/)9(251)100 L (184 x = 0xDF;)0(252 /*)100 L (185 for\(i = 0; i < 5; i++\){)0(253)100(* get the character)109 L (186)0(x ^= 1;)16(254)100(*/)109 L (187)0(outready\(\);)16(255 c = inb\(Data\);)100 L (188)0(outb\(Cmd, 0xD1\);)16(256 unlock\(&i8042lock\);)100 L (189)0(outready\(\);)16(257)100 L (190)0(outb\(Data, x\); /* toggle reset */)16(258 /*)100 L (191)0(delay\(100\);)16(259)100(* if it's the aux port...)109 L (192 })0(260)100(*/)109 L (193 })0(261 if\(s & Minready\){)100 L (194)0(262)100(if\(auxputc != nil\))116 L (195 int)0(263)100(auxputc\(c, shift\);)124 L (196 i8042auxcmd\(int cmd\))0(264)100(return;)116 L (197 {)0(265 })100 L (198 unsigned int c;)0(266)100 L (199 int tries;)0(267 /*)100 L (200)0(268)100(* e0's is the first of a 2 character sequence)109 L (201 c = 0;)0(269)100(*/)109 L (202 tries = 0;)0(270 if\(c == 0xe0\){)100 L (203)0(271)100(esc1 = 1;)116 L (204 ilock\(&i8042lock\);)0(272)100(return;)116 L cleartomark showpage saveobj restore %%EndPage: 54 54 %%Page: 55 55 /saveobj save def mark 55 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/kbd.c Page 3)l ()l ()l (273 } else if\(c == 0xe1\){)0(341)100(nk = 0;)116 L (274)0(esc2 = 2;)16(342)100(collecting = 0;)116 L (275)0(return;)16(343)100(return;)116 L (276 })0(344 } else {)100 L (277)0(345)100(switch\(c\){)116 L (278 keyup = c&0x80;)0(346)100(case Caps:)116 L (279 c &= 0x7f;)0(347)100(caps ^= 1;)124 L (280 if\(c > sizeof kbtab\){)0(348)100(return;)124 L (281)0(c |= keyup;)16(349)100(case Num:)116 L (282)0(if\(c != 0xFF\) /* these come fairly often: CAPSLOCK U Y */)16(350)100(num ^= 1;)124 L (283)0(print\("unknown key %ux\\n", c\);)24(351)100(return;)124 L (284)0(return;)16(352)100(case Shift:)116 L (285 })0(353)100(shift = 1;)124 L (286)0(354)100(return;)124 L (287 if\(esc1\){)0(355)100(case Latin:)116 L (288)0(c = kbtabesc1[c];)16(356)100(alt = 1;)124 L (289)0(esc1 = 0;)16(357)100(collecting = 1;)124 L (290 } else if\(esc2\){)0(358)100(nk = 0;)124 L (291)0(esc2--;)16(359)100(return;)124 L (292)0(return;)16(360)100(case Ctrl:)116 L (293 } else if\(shift\))0(361)100(ctl = 1;)124 L (294)0(c = kbtabshift[c];)16(362)100(return;)124 L (295 else)0(363)100(})116 L (296)0(c = kbtab[c];)16(364 })100 L (297)0(365 kbdputc\(kbdq, c\);)100 L (298 if\(caps && c<='z' && c>='a'\))0(366 })100 L (299)0(c += 'A' - 'a';)16(367)100 L (300)0(368 void)100 L (301 /*)0(369 i8042auxenable\(void \(*putc\)\(int, int\)\))100 L (302)0(* keyup only important for shifts)9(370 {)100 L (303)0(*/)9(371 char *err = "i8042: aux init failed\\n";)100 L (304 if\(keyup\){)0(372)100 L (305)0(switch\(c\){)16(373 /* enable kbd/aux xfers and interrupts */)100 L (306)0(case Latin:)16(374 ccc &= ~Cauxdis;)100 L (307)0(alt = 0;)24(375 ccc |= Cauxint;)100 L (308)0(break;)24(376)100 L (309)0(case Shift:)16(377 ilock\(&i8042lock\);)100 L (310)0(shift = 0;)24(378 if\(outready\(\) < 0\))100 L (311)0(break;)24(379)100(print\(err\);)116 L (312)0(case Ctrl:)16(380 outb\(Cmd, 0x60\);)100(/* write control register */)148 L (313)0(ctl = 0;)24(381 if\(outready\(\) < 0\))100 L (314)0(break;)24(382)100(print\(err\);)116 L (315)0(})16(383 outb\(Data, ccc\);)100 L (316)0(return;)16(384 if\(outready\(\) < 0\))100 L (317 })0(385)100(print\(err\);)116 L (318)0(386 outb\(Cmd, 0xA8\);)100(/* auxilliary device enable */)148 L (319 /*)0(387 if\(outready\(\) < 0\){)100 L (320)0(* normal character)9(388)100(iunlock\(&i8042lock\);)116 L (321)0(*/)9(389)100(return;)116 L (322 if\(!\(c & \(Spec|KF\)\)\){)0(390 })100 L (323)0(if\(ctl\){)16(391 auxputc = putc;)100 L (324)0(if\(alt && c == Del\))24(392 intrenable\(IrqAUX, i8042intr, 0, BUSUNKNOWN, "kbdaux"\);)100 L (325)0(exit\(0\);)32(393 iunlock\(&i8042lock\);)100 L (326)0(c &= 0x1f;)24(394 })100 L (327)0(})16(395)100 L (328)0(if\(!collecting\){)16(396 void)100 L (329)0(kbdputc\(kbdq, c\);)24(397 kbdinit\(void\))100 L (330)0(return;)24(398 {)100 L (331)0(})16(399 int c;)100 L (332)0(kc[nk++] = c;)16(400)100 L (333)0(c = latin1\(kc, nk\);)16(401 kbdq = qopen\(4*1024, 0, 0, 0\);)100 L (334)0(if\(c < -1\))16(/* need more keystrokes */)32(402 if\(kbdq == nil\))100 L (335)0(return;)24(403)100(panic\("kbdinit"\);)116 L (336)0(if\(c != -1\) /* valid sequence */)16(404 qnoblock\(kbdq, 1\);)100 L (337)0(kbdputc\(kbdq, c\);)24(405)100 L (338)0(else /* dump characters */)16(406 ioalloc\(Data, 1, 0, "kbd"\);)100 L (339)0(for\(i=0; i>8;)116 L (5 #include "fns.h")0(73)100(})108 L (6 #include "io.h")0(74)100 L (7 #include "ureg.h")0(75)100(/*)108 L (8 #include "init.h")0(76)100(* parse configuration args from dos file plan9.ini)109 L (9 #include "pool.h")0(77)100(*/)109 L (10)0(78)100(cp = BOOTARGS; /* where b.com leaves its config */)108 L (11 Mach *m;)0(79)100(cp[BOOTARGSLEN-1] = 0;)108 L (12)0(80)100 L (13 static uchar *sp;)0(/* stack pointer for /boot */)32(81)100(/*)108 L (14)0(82)100(* Strip out '\\r', change '\\t' -> ' '.)109 L (15 /*)0(83)100(*/)109 L (16 * Where configuration info is left for the loaded programme.)0(84)100(p = cp;)108 L (17 * This will turn into a structure as more is done by the boot loader)0(85)100(for\(q = cp; *q; q++\){)108 L (18 * \(e.g. why parse the .ini file twice?\).)0(86)100(if\(*q == '\\r'\))116 L (19 * There are 1024 bytes available at CONFADDR.)0(87)100(continue;)124 L (20 */)0(88)100(if\(*q == '\\t'\))116 L (21 #define BOOTLINE \(\(char*\)CONFADDR\))0(89)100(*q = ' ';)124 L (22 #define BOOTLINELEN)0(64)32(90)100(*p++ = *q;)116 L (23 #define BOOTARGS \(\(char*\)\(CONFADDR+BOOTLINELEN\)\))0(91)100(})108 L (24 #define BOOTARGSLEN \(1024-BOOTLINELEN\))0(92)100(*p = 0;)108 L (25 #define MAXCONF)0(32)32(93)100 L (26)0(94)100(n = getcfields\(cp, line, MAXCONF, "\\n"\);)108 L (27 char bootdisk[NAMELEN];)0(95)100(for\(i = 0; i < n; i++\){)108 L (28 char *confname[MAXCONF];)0(96)100(if\(*line[i] == '#'\))116 L (29 char *confval[MAXCONF];)0(97)100(continue;)124 L (30 int nconf;)0(98)100(cp = strchr\(line[i], '='\);)116 L (31)0(99)100(if\(cp == 0\))116 L (32 extern void ns16552install\(void\); /* botch: config */)0(100)100(continue;)124 L (33)0(101)100(*cp++ = 0;)116 L (34 static int isoldbcom;)0(102)100(if\(cp - line[i] >= NAMELEN+1\))116 L (35)0(103)100(*\(line[i]+NAMELEN-1\) = 0;)124 L (36 static int)0(104)100(confname[nconf] = line[i];)116 L (37 getcfields\(char* lp, char** fields, int n, char* sep\))0(105)100(confval[nconf] = cp;)116 L (38 {)0(106)100(nconf++;)116 L (39)0(int i;)8(107 })100 L (40)0(108 })100 L (41)0(for\(i = 0; lp && *lp && i < n; i++\){)8(109)100 L (42)0(while\(*lp && strchr\(sep, *lp\) != 0\))16(110 void)100 L (43)0(*lp++ = 0;)24(111 main\(void\))100 L (44)0(if\(*lp == 0\))16(112 {)100 L (45)0(break;)24(113 outb\(0x3F2, 0x00\);)100(/* botch: turn off the floppy motor */)148 L (46)0(fields[i] = lp;)16(114)100 L (47)0(while\(*lp && strchr\(sep, *lp\) == 0\){)16(115 /*)100 L (48)0(if\(*lp == '\\\\' && *\(lp+1\) == '\\n'\))24(116)100(* There is a little leeway here in the ordering but care must be)109 L (49)0(*lp++ = ' ';)32(117)100(* taken with dependencies:)109 L (50)0(lp++;)24(118)100(*)109(function)116(dependencies)140 L (51)0(})16(119)100(*)109(========)116(============)140 L (52)0(})8(120)100(*)109(machinit)116(depends on: m->machno, m->pdb)140 L (53)0(121)100(*)109(cpuidentify)116(depends on: m)140 L (54)0(return i;)8(122)100(*)109(confinit)116(calls: meminit)140 L (55 })0(123)100(*)109(meminit)116(depends on: cpuidentify \(needs to know processor)140 L (56)0(124)100(*)109(type for caching, etc.\))142 L (57 static void)0(125)100(*)109(archinit)116(depends on: meminit \(MP config table may be at the)140 L (58 options\(void\))0(126)100(*)109(top of system physical memory\);)142 L (59 {)0(127)100(*)109(conf.nmach \(not critical, mpinit will check\);)140 L (60)0(uchar *bda;)8(128)100(*)109(arch->intrinit)116(depends on: trapinit)140 L (61)0(long i, n;)8(129)100(*/)109 L (62)0(char *cp, *line[MAXCONF], *p, *q;)8(130 conf.nmach = 1;)100 L (63)0(131 MACHP\(0\) = \(Mach*\)CPU0MACH;)100 L (64)0(if\(strncmp\(BOOTARGS, "ZORT 0\\r\\n", 8\)\){)8(132 m->pdb = \(ulong*\)CPU0PDB;)100 L (65)0(isoldbcom = 1;)16(133 machinit\(\);)100 L (66)0(134 ioinit\(\);)100 L (67)0(memmove\(BOOTARGS, KADDR\(1024\), BOOTARGSLEN\);)16(135 active.machs = 1;)100 L (68)0(memmove\(BOOTLINE, KADDR\(0x100\), BOOTLINELEN\);)16(136 active.exiting = 0;)100 L cleartomark showpage saveobj restore %%EndPage: 57 57 %%Page: 58 58 /saveobj save def mark 58 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/main.c Page 2)l ()l ()l (137 options\(\);)0(205 up->slash->name = newcname\("/"\);)100 L (138 screeninit\(\);)0(206 up->dot = cclone\(up->slash, 0\);)100 L (139 cpuidentify\(\);)0(207)100 L (140 confinit\(\);)0(208 chandevinit\(\);)100 L (141 archinit\(\);)0(209)100 L (142 xinit\(\);)0(210 if\(!waserror\(\)\){)100 L (143 trapinit\(\);)0(211)100(strcpy\(tstr, arch->id\);)116 L (144 printinit\(\);)0(212)100(strcat\(tstr, " %s"\);)116 L (145 cpuidprint\(\);)0(213)100(ksetterm\(tstr\);)116 L (146 if\(isoldbcom\))0(214)100(ksetenv\("cputype", "386"\);)116 L (147)0(print\(" ****OLD B.COM - UPGRADE****\\n"\);)16(215)100(if\(cpuserver\))116 L (148 mmuinit\(\);)0(216)100(ksetenv\("service", "cpu"\);)124 L (149 if\(arch->intrinit\))0(217)100(else)116 L (150)0(arch->intrinit\(\);)16(218)100(ksetenv\("service", "terminal"\);)124 L (151 ns16552install\(\);)0(/* botch: config */)48(219)100(for\(i = 0; i < nconf; i++\))116 L (152 mathinit\(\);)0(220)100(if\(confname[i] && confname[i][0] != '*'\))124 L (153 kbdinit\(\);)0(221)100(ksetenv\(confname[i], confval[i]\);)132 L (154 if\(arch->clockenable\))0(222)100(poperror\(\);)116 L (155)0(arch->clockenable\(\);)16(223 })100 L (156 procinit0\(\);)0(224 kproc\("alarm", alarmkproc, 0\);)100 L (157 initseg\(\);)0(225 touser\(sp\);)100 L (158 links\(\);)0(226 })100 L (159 conf.monitor = 1;)0(227)100 L (160 chandevreset\(\);)0(228 void)100 L (161 pageinit\(\);)0(229 userinit\(void\))100 L (162 swapinit\(\);)0(230 {)100 L (163 userinit\(\);)0(231 Proc *p;)100 L (164 schedinit\(\);)0(232 Segment *s;)100 L (165 })0(233 KMap *k;)100 L (166)0(234 Page *pg;)100 L (167 void)0(235)100 L (168 machinit\(void\))0(236 p = newproc\(\);)100 L (169 {)0(237 p->pgrp = newpgrp\(\);)100 L (170 int machno;)0(238 p->egrp = smalloc\(sizeof\(Egrp\)\);)100 L (171 ulong *pdb;)0(239 p->egrp->ref = 1;)100 L (172)0(240 p->fgrp = dupfgrp\(nil\);)100 L (173 machno = m->machno;)0(241 p->rgrp = newrgrp\(\);)100 L (174 pdb = m->pdb;)0(242 p->procmode = 0640;)100 L (175 memset\(m, 0, sizeof\(Mach\)\);)0(243)100 L (176 m->machno = machno;)0(244 strcpy\(p->text, "*init*"\);)100 L (177 m->pdb = pdb;)0(245 strcpy\(p->user, eve\);)100 L (178 })0(246 p->fpstate = FPinit;)100 L (179)0(247 fpoff\(\);)100 L (180 void)0(248)100 L (181 ksetterm\(char *f\))0(249 /*)100 L (182 {)0(250)100(* Kernel Stack)109 L (183 char buf[2*NAMELEN];)0(251)100(*)109 L (184)0(252)100(* N.B. The -12 for the stack pointer is important.)109 L (185 sprint\(buf, f, conffile\);)0(253)100(*)109(4 bytes for gotolabel's return PC)116 L (186 ksetenv\("terminal", buf\);)0(254)100(*/)109 L (187 })0(255 p->sched.pc = \(ulong\)init0;)100 L (188)0(256 p->sched.sp = \(ulong\)p->kstack+KSTACK-\(1+MAXSYSARG\)*BY2WD;)100 L (189 void)0(257)100 L (190 init0\(void\))0(258 /*)100 L (191 {)0(259)100(* User Stack)109 L (192 int i;)0(260)100(*/)109 L (193 char tstr[32];)0(261 s = newseg\(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG\);)100 L (194)0(262 p->seg[SSEG] = s;)100 L (195 up->nerrlab = 0;)0(263 pg = newpage\(1, 0, USTKTOP-BY2PG\);)100 L (196)0(264 segpage\(s, pg\);)100 L (197 spllo\(\);)0(265 k = kmap\(pg\);)100 L (198)0(266 bootargs\(VA\(k\)\);)100 L (199 /*)0(267 kunmap\(k\);)100 L (200)0(* These are o.k. because rootinit is null.)9(268)100 L (201)0(* Then early kproc's will have a root and dot.)9(269 /*)100 L (202)0(*/)9(270)100(* Text)109 L (203 up->slash = namec\("#/", Atodir, 0, 0\);)0(271)100(*/)109 L (204 cnameclose\(up->slash->name\);)0(272 s = newseg\(SG_TEXT, UTZERO, 1\);)100 L cleartomark showpage saveobj restore %%EndPage: 58 58 %%Page: 59 59 /saveobj save def mark 59 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/main.c Page 3)l ()l ()l (273 s->flushme++;)0(341 void)100 L (274 p->seg[TSEG] = s;)0(342 addconf\(char *name, char *val\))100 L (275 pg = newpage\(1, 0, UTZERO\);)0(343 {)100 L (276 memset\(pg->cachectl, PG_TXTFLUSH, sizeof\(pg->cachectl\)\);)0(344 if\(nconf >= MAXCONF\))100 L (277 segpage\(s, pg\);)0(345)100(return;)116 L (278 k = kmap\(s->map[0]->pages[0]\);)0(346 confname[nconf] = name;)100 L (279 memmove\(\(ulong*\)VA\(k\), initcode, sizeof initcode\);)0(347 confval[nconf] = val;)100 L (280 kunmap\(k\);)0(348 nconf++;)100 L (281)0(349 })100 L (282 ready\(p\);)0(350)100 L (283 })0(351 char*)100 L (284)0(352 getconf\(char *name\))100 L (285 uchar *)0(353 {)100 L (286 pusharg\(char *p\))0(354 int i;)100 L (287 {)0(355)100 L (288 int n;)0(356 for\(i = 0; i < nconf; i++\))100 L (289)0(357)100(if\(cistrcmp\(confname[i], name\) == 0\))116 L (290 n = strlen\(p\)+1;)0(358)100(return confval[i];)124 L (291 sp -= n;)0(359 return 0;)100 L (292 memmove\(sp, p, n\);)0(360 })100 L (293 return sp;)0(361)100 L (294 })0(362 void)100 L (295)0(363 confinit\(void\))100 L (296 void)0(364 {)100 L (297 bootargs\(ulong base\))0(365 char *p;)100 L (298 {)0(366 int userpcnt;)100 L (299 int i, ac;)0(367 ulong kpages, maxmem;)100 L (300 uchar *av[32];)0(368)100 L (301 uchar **lsp;)0(369 if\(p = getconf\("*maxmem"\)\))100 L (302 char *cp = BOOTLINE;)0(370)100(maxmem = strtoul\(p, 0, 0\);)116 L (303 char buf[64];)0(371 else)100 L (304)0(372)100(maxmem = 0;)116 L (305 sp = \(uchar*\)base + BY2PG - MAXSYSARG*BY2WD;)0(373 if\(p = getconf\("*kernelpercent"\)\))100 L (306)0(374)100(userpcnt = 100 - strtol\(p, 0, 0\);)116 L (307 ac = 0;)0(375 else)100 L (308 av[ac++] = pusharg\("/386/9dos"\);)0(376)100(userpcnt = 0;)116 L (309 cp[BOOTLINELEN-1] = 0;)0(377)100 L (310 buf[0] = 0;)0(378 meminit\(maxmem\);)100 L (311 if\(strncmp\(cp, "fd", 2\) == 0\){)0(379)100 L (312)0(sprint\(buf, "local!#f/fd%lddisk", strtol\(cp+2, 0, 0\)\);)16(380 conf.npage = conf.npage0 + conf.npage1;)100 L (313)0(av[ac++] = pusharg\(buf\);)16(381)100 L (314 } else if\(strncmp\(cp, "sd", 2\) == 0\){)0(382 conf.nproc = 100 + \(\(conf.npage*BY2PG\)/MB\)*5;)100 L (315)0(sprint\(buf, "local!#S/sd%c%c/fs", *\(cp+2\), *\(cp+3\)\);)16(383 if\(cpuserver\))100 L (316)0(av[ac++] = pusharg\(buf\);)16(384)100(conf.nproc *= 3;)116 L (317 } else if\(strncmp\(cp, "ether", 5\) == 0\))0(385 if\(conf.nproc > 2000\))100 L (318)0(av[ac++] = pusharg\("-n"\);)16(386)100(conf.nproc = 2000;)116 L (319 if\(buf[0]\){)0(387 conf.nimage = 200;)100 L (320)0(cp = strchr\(buf, '!'\);)16(388 conf.nswap = conf.nproc*80;)100 L (321)0(if\(cp\){)16(389 conf.nswppo = 4096;)100 L (322)0(strcpy\(bootdisk, cp+1\);)24(390)100 L (323)0(addconf\("bootdisk", bootdisk\);)24(391 if\(cpuserver\) {)100 L (324)0(})16(392)100(if\(userpcnt < 10\))116 L (325 })0(393)100(userpcnt = 70;)124 L (326)0(394)100(kpages = conf.npage - \(conf.npage*userpcnt\)/100;)116 L (327 /* 4 byte word align stack */)0(395)100 L (328 sp = \(uchar*\)\(\(ulong\)sp & ~3\);)0(396)100(/*)116 L (329)0(397)100(* Hack for the big boys. Only good while physmem < 4GB.)117 L (330 /* build argc, argv on stack */)0(398)100(* Give the kernel a max. of 16MB + enough to allocate the)117 L (331 sp -= \(ac+1\)*sizeof\(sp\);)0(399)100(* page pool.)117 L (332 lsp = \(uchar**\)sp;)0(400)100(* This is an overestimate as conf.upages < conf.npages.)117 L (333 for\(i = 0; i < ac; i++\))0(401)100(* The patch of nimage is a band-aid, scanning the whole)117 L (334)0(*lsp++ = av[i] + \(\(USTKTOP - BY2PG\) - base\);)16(402)100(* page list in imagereclaim just takes too long.)117 L (335 *lsp = 0;)0(403)100(*/)117 L (336 sp += \(USTKTOP - BY2PG\) - base - sizeof\(ulong\);)0(404)100(if\(kpages > \(16*MB + conf.npage*sizeof\(Page\)\)/BY2PG\){)116 L (337 })0(405)100(kpages = \(16*MB + conf.npage*sizeof\(Page\)\)/BY2PG;)124 L (338)0(406)100(conf.nimage = 2000;)124 L (339 Conf)0(conf;)16(407)100(kpages += \(conf.nproc*KSTACK\)/BY2PG;)124 L (340)0(408)100(})116 L cleartomark showpage saveobj restore %%EndPage: 59 59 %%Page: 60 60 /saveobj save def mark 60 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/main.c Page 4)l ()l ()l (409 } else {)0(477)100(if\(!\(\(1<fpsave.pc\);)100 L (415)0(})16(483 postnote\(up, 1, note, NDebug\);)100 L (416)0(kpages = conf.npage - \(conf.npage*userpcnt\)/100;)16(484 })100 L (417)0(485)100 L (418)0(/*)16(486 /*)100 L (419)0(* Make sure terminals with low memory get at least)17(487 * math coprocessor error)100 L (420)0(* 4MB on the first Image chunk allocation.)17(488 */)100 L (421)0(*/)17(489 static void)100 L (422)0(if\(conf.npage*BY2PG < 16*MB\))16(490 matherror\(Ureg *ur, void*\))100 L (423)0(imagmem->minarena = 4*1024*1024;)24(491 {)100 L (424 })0(492 /*)100 L (425 conf.upages = conf.npage - kpages;)0(493)100(* a write cycle to port 0xF0 clears the interrupt latch attached)109 L (426 conf.ialloc = \(kpages/2\)*BY2PG;)0(494)100(* to the error# line from the 387)109 L (427)0(495)100(*/)109 L (428 /*)0(496 if\(!\(m->cpuiddx & 0x01\)\))100 L (429)0(* Guess how much is taken by the large permanent)9(497)100(outb\(0xF0, 0xFF\);)116 L (430)0(* datastructures. Mntcache and Mntrpc are not accounted for)9(498)100 L (431)0(* \(probably ~300KB\).)9(499 /*)100 L (432)0(*/)9(500)100(* save floating point state to check out error)109 L (433 kpages *= BY2PG;)0(501)100(*/)109 L (434 kpages -= conf.upages*sizeof\(Page\))0(502 fpenv\(&up->fpsave\);)100 L (435)0(+ conf.nproc*sizeof\(Proc\))16(503 mathnote\(\);)100 L (436)0(+ conf.nimage*sizeof\(Image\))16(504)100 L (437)0(+ conf.nswap)16(505 if\(ur->pc & KZERO\))100 L (438)0(+ conf.nswppo*sizeof\(Page\);)16(506)100(panic\("fp: status %lux fppc=0x%lux pc=0x%lux",)116 L (439 mainmem->maxsize = kpages;)0(507)100(up->fpsave.status, up->fpsave.pc, ur->pc\);)124 L (440 if\(!cpuserver\){)0(508 })100 L (441)0(/*)16(509)100 L (442)0(* give terminals lots of image memory, too; the dynamic)17(510 /*)100 L (443)0(* allocation will balance the load properly, hopefully.)17(511 * math coprocessor emulation fault)100 L (444)0(* be careful with 32-bit overflow.)17(512 */)100 L (445)0(*/)17(513 static void)100 L (446)0(imagmem->maxsize = kpages;)16(514 mathemu\(Ureg*, void*\))100 L (447 })0(515 {)100 L (448 })0(516 switch\(up->fpstate\){)100 L (449)0(517 case FPinit:)100 L (450 static char* mathmsg[] =)0(518)100(fpinit\(\);)116 L (451 {)0(519)100(up->fpstate = FPactive;)116 L (452 "invalid",)0(520)100(break;)116 L (453 "denormalized",)0(521 case FPinactive:)100 L (454 "div-by-zero",)0(522)100(/*)116 L (455 "overflow",)0(523)100(* Before restoring the state, check for any pending)117 L (456 "underflow",)0(524)100(* exceptions, there's no way to restore the state without)117 L (457 "precision",)0(525)100(* generating an unmasked exception.)117 L (458 "stack",)0(526)100(* More attention should probably be paid here to the)117 L (459 "error",)0(527)100(* exception masks and error summary.)117 L (460 };)0(528)100(*/)117 L (461)0(529)100(if\(\(up->fpsave.status & ~up->fpsave.control\) & 0x07F\){)116 L (462 static void)0(530)100(mathnote\(\);)124 L (463 mathnote\(void\))0(531)100(break;)124 L (464 {)0(532)100(})116 L (465 int i;)0(533)100(fprestore\(&up->fpsave\);)116 L (466 ulong status;)0(534)100(up->fpstate = FPactive;)116 L (467 char *msg, note[ERRLEN];)0(535)100(break;)116 L (468)0(536 case FPactive:)100 L (469 status = up->fpsave.status;)0(537)100(panic\("math emu", 0\);)116 L (470)0(538)100(break;)116 L (471 /*)0(539 })100 L (472)0(* Some attention should probably be paid here to the)9(540 })100 L (473)0(* exception masks and error summary.)9(541)100 L (474)0(*/)9(542 /*)100 L (475 msg = "unknown";)0(543 * math coprocessor segment overrun)100 L (476 for\(i = 0; i < 8; i++\){)0(544 */)100 L cleartomark showpage saveobj restore %%EndPage: 60 60 %%Page: 61 61 /saveobj save def mark 61 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/main.c Page 5)l ()l ()l (545 static void)0(613 else if\(m->machno == 0 && \(active.machs & \(1<machno\)\) == 0\))100 L (546 mathover\(Ureg*, void*\))0(614)100(active.ispanic = 0;)116 L (547 {)0(615 once = active.machs & \(1<machno\);)100 L (548 pexit\("math overrun", 0\);)0(616 active.machs &= ~\(1<machno\);)100 L (549 })0(617 active.exiting = 1;)100 L (550)0(618 unlock\(&active\);)100 L (551 void)0(619)100 L (552 mathinit\(void\))0(620 if\(once\))100 L (553 {)0(621)100(print\("cpu%d: exiting\\n", m->machno\);)116 L (554 trapenable\(VectorCERR, matherror, 0, "matherror"\);)0(622 spllo\(\);)100 L (555 if\(X86FAMILY\(m->cpuidax\) == 3\))0(623 for\(ms = 5*1000; ms > 0; ms -= TK2MS\(2\)\){)100 L (556)0(intrenable\(IrqIRQ13, matherror, 0, BUSUNKNOWN, "matherror"\);)16(624)100(delay\(TK2MS\(2\)\);)116 L (557 trapenable\(VectorCNA, mathemu, 0, "mathemu"\);)0(625)100(if\(active.machs == 0 && consactive\(\) == 0\))116 L (558 trapenable\(VectorCSO, mathover, 0, "mathover"\);)0(626)100(break;)124 L (559 })0(627 })100 L (560)0(628)100 L (561 /*)0(629 if\(active.ispanic && m->machno == 0\){)100 L (562 * set up floating point for a new process)0(630)100(if\(cpuserver\))116 L (563 */)0(631)100(delay\(10000\);)124 L (564 void)0(632)100(else)116 L (565 procsetup\(Proc *p\))0(633)100(for\(;;\);)124 L (566 {)0(634 })100 L (567 p->fpstate = FPinit;)0(635 else)100 L (568 fpoff\(\);)0(636)100(delay\(1000\);)116 L (569 })0(637)100 L (570)0(638 arch->reset\(\);)100 L (571 /*)0(639 })100 L (572 * Save the mach dependent part of the process state.)0(640)100 L (573 */)0(641 int)100 L (574 void)0(642 isaconfig\(char *class, int ctlrno, ISAConf *isa\))100 L (575 procsave\(Proc *p\))0(643 {)100 L (576 {)0(644 char cc[NAMELEN], *p, *q, *r;)100 L (577 if\(p->fpstate == FPactive\){)0(645 int n;)100 L (578)0(if\(p->state == Moribund\))16(646)100 L (579)0(fpoff\(\);)24(647 sprint\(cc, "%s%d", class, ctlrno\);)100 L (580)0(else{)16(648 for\(n = 0; n < nconf; n++\){)100 L (581)0(/*)24(649)100(if\(cistrncmp\(confname[n], cc, NAMELEN\)\))116 L (582)0(* Fpsave\(\) stores without handling pending)25(650)100(continue;)124 L (583)0(* unmasked exeptions. Postnote\(\) can't be called)25(651)100(isa->nopt = 0;)116 L (584)0(* here as sleep\(\) already has up->rlock, so)25(652)100(p = confval[n];)116 L (585)0(* the handling of pending exceptions is delayed)25(653)100(while\(*p\){)116 L (586)0(* until the process runs again and generates an)25(654)100(while\(*p == ' ' || *p == '\\t'\))124 L (587)0(* emulation fault to activate the FPU.)25(655)100(p++;)132 L (588)0(*/)25(656)100(if\(*p == '\\0'\))124 L (589)0(fpsave\(&up->fpsave\);)24(657)100(break;)132 L (590)0(})16(658)100(if\(cistrncmp\(p, "type=", 5\) == 0\){)124 L (591)0(p->fpstate = FPinactive;)16(659)100(p += 5;)132 L (592 })0(660)100(for\(q = isa->type; q < &isa->type[NAMELEN-1]; q++\){)132 L (593)0(661)100(if\(*p == '\\0' || *p == ' ' || *p == '\\t'\))140 L (594 /*)0(662)100(break;)148 L (595)0(* Switch to the prototype page tables for this processor.)9(663)100(*q = *p++;)140 L (596)0(* While this processor is in the scheduler, the process could run)9(664)100(})132 L (597)0(* on another processor and exit, returning the page tables to)9(665)100(*q = '\\0';)132 L (598)0(* the free list where they could be reallocated and overwritten.)9(666)100(})124 L (599)0(* When this processor eventually has to get an entry from the)9(667)100(else if\(cistrncmp\(p, "port=", 5\) == 0\))124 L (600)0(* trashed page tables it will crash.)9(668)100(isa->port = strtoul\(p+5, &p, 0\);)132 L (601)0(*/)9(669)100(else if\(cistrncmp\(p, "irq=", 4\) == 0\))124 L (602 mmuflushtlb\(PADDR\(m->pdb\)\);)0(670)100(isa->irq = strtoul\(p+4, &p, 0\);)132 L (603 })0(671)100(else if\(cistrncmp\(p, "dma=", 4\) == 0\))124 L (604)0(672)100(isa->dma = strtoul\(p+4, &p, 0\);)132 L (605 void)0(673)100(else if\(cistrncmp\(p, "mem=", 4\) == 0\))124 L (606 exit\(int ispanic\))0(674)100(isa->mem = strtoul\(p+4, &p, 0\);)132 L (607 {)0(675)100(else if\(cistrncmp\(p, "size=", 5\) == 0\))124 L (608 int ms, once;)0(676)100(isa->size = strtoul\(p+5, &p, 0\);)132 L (609)0(677)100(else if\(cistrncmp\(p, "freq=", 5\) == 0\))124 L (610 lock\(&active\);)0(678)100(isa->freq = strtoul\(p+5, &p, 0\);)132 L (611 if\(ispanic\))0(679)100(else if\(isa->nopt < NISAOPT\){)124 L (612)0(active.ispanic = ispanic;)16(680)100(r = isa->opt[isa->nopt];)132 L cleartomark showpage saveobj restore %%EndPage: 61 61 %%Page: 62 62 /saveobj save def mark 62 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/main.c Page 6)l ()l ()l (681)0(while\(*p && *p != ' ' && *p != '\\t'\){)32(749)100(if\(bc >= 'A' && bc <= 'Z'\))116 L (682)0(*r++ = *p++;)40(750)100(bc = 'a' + \(bc - 'A'\);)124 L (683)0(if\(r-isa->opt[isa->nopt] >= ISAOPTLEN-1\))40(751)100 L (684)0(break;)48(752)100(ac -= bc;)116 L (685)0(})32(753)100(if\(ac\))116 L (686)0(*r = '\\0';)32(754)100(return ac;)124 L (687)0(isa->nopt++;)32(755)100(if\(bc == 0\))116 L (688)0(})24(756)100(break;)124 L (689)0(while\(*p && *p != ' ' && *p != '\\t'\))24(757 })100 L (690)0(p++;)32(758)100 L (691)0(})16(759 return 0;)100 L (692)0(return 1;)16(760 })100 L (693 })l (694 return 0;)l (695 })l (696)l (697 /*)l (698 int)l (699 iprint\(char *fmt, ...\))l (700 {)l (701 char buf[PRINTSIZE];)l (702 int n;)l (703 va_list arg;)l (704)l (705 va_start\(arg, fmt\);)l (706 n = doprint\(buf, buf+sizeof\(buf\), fmt, arg\) - buf;)l (707 va_end\(arg\);)l (708)l (709 screenputs\(buf, n\);)l (710)l (711 return n;)l (712 })l (713 */)l (714)l (715 int)l (716 cistrcmp\(char *a, char *b\))l (717 {)l (718 int ac, bc;)l (719)l (720 for\(;;\){)l (721)0(ac = *a++;)16 L (722)0(bc = *b++;)16 L (723)l (724)0(if\(ac >= 'A' && ac <= 'Z'\))16 L (725)0(ac = 'a' + \(ac - 'A'\);)24 L (726)0(if\(bc >= 'A' && bc <= 'Z'\))16 L (727)0(bc = 'a' + \(bc - 'A'\);)24 L (728)0(ac -= bc;)16 L (729)0(if\(ac\))16 L (730)0(return ac;)24 L (731)0(if\(bc == 0\))16 L (732)0(break;)24 L (733 })l (734 return 0;)l (735 })l (736)l (737 int)l (738 cistrncmp\(char *a, char *b, int n\))l (739 {)l (740 unsigned ac, bc;)l (741)l (742 while\(n > 0\){)l (743)0(ac = *a++;)16 L (744)0(bc = *b++;)16 L (745)0(n--;)16 L (746)l (747)0(if\(ac >= 'A' && ac <= 'Z'\))16 L (748)0(ac = 'a' + \(ac - 'A'\);)24 L cleartomark showpage saveobj restore %%EndPage: 62 62 %%Page: 63 63 /saveobj save def mark 63 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/mem.h Page 1)l ()l ()l (1 /*)0(69)100 L (2)0(* Memory and machine-specific definitions. Used in C and assembler.)7(70 #define SELECTOR\(i, t, p\) \(\(\(i\)<<3\) | \(t\) | \(p\)\))100 L (3)0(*/)7(71)100 L (4)0(72 #define NULLSEL SELECTOR\(NULLSEG, SELGDT, 0\))100 L (5 /*)0(73 #define KESEL SELECTOR\(KESEG, SELGDT, 0\))100 L (6)0(* Sizes)7(74 #define KDSEL SELECTOR\(KDSEG, SELGDT, 0\))100 L (7)0(*/)7(75 #define UESEL SELECTOR\(UESEG, SELGDT, 3\))100 L (8 #define BI2BY)0(8)32(/* bits per byte */)56(76 #define UDSEL SELECTOR\(UDSEG, SELGDT, 3\))100 L (9 #define BI2WD)0(32)32(/* bits per word */)56(77 #define TSSSEL SELECTOR\(TSSSEG, SELGDT, 0\))100 L (10 #define BY2WD)0(4)32(/* bytes per word */)56(78)100 L (11 #define BY2V)0(8)32(/* bytes per double word */)56(79 /*)100 L (12 #define BY2PG)0(4096)32(/* bytes per page */)56(80 * fields in segment descriptors)100 L (13 #define WD2PG)0(\(BY2PG/BY2WD\))32(/* words per page */)56(81 */)100 L (14 #define PGSHIFT)0(12)32(/* log\(BY2PG\) */)56(82 #define SEGDATA \(0x10<<8\))100(/* data/stack segment */)140 L (15 #define ROUND\(s, sz\))0(\(\(\(s\)+\(\(sz\)-1\)\)&~\(\(sz\)-1\)\))32(83 #define SEGEXEC \(0x18<<8\))100(/* executable segment */)140 L (16 #define PGROUND\(s\))0(ROUND\(s, BY2PG\))32(84 #define SEGTSS \(0x9<<8\))100(/* TSS segment */)140 L (17 #define BLOCKALIGN)0(8)32(85 #define SEGCG \(0x0C<<8\))100(/* call gate */)140 L (18)0(86 #define SEGIG \(0x0E<<8\))100(/* interrupt gate */)140 L (19 #define MAXMACH)0(8)32(/* max # cpus system can run */)56(87 #define SEGTG \(0x0F<<8\))100(/* trap gate */)140 L (20 #define KSTACK)0(4096)32(/* Size of kernel stack */)56(88 #define SEGTYPE \(0x1F<<8\))100 L (21)0(89)100 L (22 /*)0(90 #define SEGP)100(\(1<<15\))124(/* segment present */)140 L (23 * Time)0(91 #define SEGPL\(x\) \(\(x\)<<13\))100(/* priority level */)140 L (24 */)0(92 #define SEGB)100(\(1<<22\))124(/* granularity 1==4k \(for expand-down\) */)140 L (25 #define HZ)0(\(82\))32(/* clock frequency */)56(93 #define SEGG)100(\(1<<23\))124(/* granularity 1==4k \(for other\) */)140 L (26 #define MS2HZ)0(\(1000/HZ\))32(/* millisec per clock tick */)56(94 #define SEGE)100(\(1<<10\))124(/* expand down */)140 L (27 #define TK2SEC\(t\))0(\(\(t\)/HZ\))32(/* ticks to seconds */)56(95 #define SEGW)100(\(1<<9\))124(/* writable \(for data/stack\) */)140 L (28 #define MS2TK\(t\))0(\(\(\(t\)*HZ\)/1000\))32(/* milliseconds to ticks */)56(96 #define SEGR \(1<<9\))100(/* readable \(for code\) */)140 L (29)0(97 #define SEGD)100(\(1<<22\))124(/* default 1==32bit \(for code\) */)140 L (30 /*)0(98)100 L (31 * Fundamental addresses)0(99 /*)100 L (32 */)0(100 * virtual MMU)100 L (33 #define IDTADDR)0(0x80000800)32(/* idt */)56(101 */)100 L (34 #define APBOOTSTRAP)0(0x80001000)32(/* AP bootstrap code */)56(102 #define PTEMAPMEM \(1024*1024\))100 L (35 #define CONFADDR 0x80001200)0(/* info passed from boot loader */)48(103 #define PTEPERTAB)100(\(PTEMAPMEM/BY2PG\))132 L (36 #define CPU0PDB)0(0x80002000)32(/* bootstrap processor PDB */)56(104 #define SEGMAPSIZE)100(1984)132 L (37 #define CPU0PTE)0(0x80003000)32(/* bootstrap processor PTE's for 0-4MB */ 105 #define SSEGMAPSIZE)56(16)132 L (38 #define MACHADDR 0x80004000)0(/* as seen by current processor */)48(106 #define PPN\(x\))100(\(\(x\)&~\(BY2PG-1\)\))132 L (39 #define CPU0MACH 0x80005000)0(/* Mach for bootstrap processor */)48(107)100 L (40 #define MACHSIZE)0(BY2PG)32(108 /*)100 L (41)0(109 * physical MMU)100 L (42 /*)0(110 */)100 L (43 * Address spaces)0(111 #define PTEVALID)100(\(1<<0\))132 L (44 *)0(112 #define PTEWT)100(\(1<<3\))132 L (45 * User is at 0-2GB)0(113 #define PTEUNCACHED \(1<<4\))100 L (46 * Kernel is at 2GB-4GB)0(114 #define PTEWRITE)100(\(1<<1\))132 L (47 */)0(115 #define PTERONLY)100(\(0<<1\))132 L (48 #define UZERO)0(0)32(/* base of user address space */)56(116 #define PTEKERNEL)100(\(0<<2\))132 L (49 #define UTZERO)0(\(UZERO+BY2PG\))32(/* first address in user text */)56(117 #define PTEUSER)100(\(1<<2\))132 L (50 #define KZERO)0(0x80000000)32(/* base of kernel address space */)56(118 #define PTESIZE)100(\(1<<7\))132 L (51 #define KTZERO)0(0x80100000)32(/* first address in kernel text */)56(119)100 L (52 #define USTKTOP)0(\(KZERO-BY2PG\))32(/* byte just beyond user stack */)56(120 #define getpgcolor\(a\) 0)100 L (53 #define USTKSIZE)0(\(16*1024*1024\))32(/* size of user stack */)56 L (54 #define TSTKTOP)0(\(USTKTOP-USTKSIZE\))32(/* end of new stack in sysexec */)56 L (55 #define TSTKSIZ 100)l (56)l (57 /*)l (58 * known x86 segments \(in GDT\) and their selectors)l (59 */)l (60 #define NULLSEG 0)0(/* null segment */)32 L (61 #define KDSEG 1)0(/* kernel data/stack */)32 L (62 #define KESEG 2)0(/* kernel executable */)32 L (63 #define UDSEG 3)0(/* user data/stack */)32 L (64 #define UESEG 4)0(/* user executable */)32 L (65 #define TSSSEG 5)0(/* task segment */)32 L (66)l (67 #define SELGDT \(0<<2\) /* selector is in gdt */)l (68 #define SELLDT \(1<<2\) /* selector is in ldt */)l cleartomark showpage saveobj restore %%EndPage: 63 63 %%Page: 64 64 /saveobj save def mark 64 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/memory.c Page 1)l ()l ()l (1 /*)0(69)100(&mapumb[nelem\(mapumb\)-1],)108 L (2)0(* Size memory and create the kernel page-tables on the fly while doing so.)7(70 };)100 L (3)0(* Called from main\(\), this code should only be run by the bootstrap processor.)7(71)100 L (4)0(*/)7(72 static Map mapumbrw[16];)100 L (5 #include "u.h")0(73 static RMap rmapumbrw = {)100 L (6 #include "../port/lib.h")0(74)100("UMB device memory",)108 L (7 #include "mem.h")0(75)100(mapumbrw,)108 L (8 #include "dat.h")0(76)100(&mapumbrw[nelem\(mapumbrw\)-1],)108 L (9 #include "fns.h")0(77 };)100 L (10 #include "io.h")0(78)100 L (11)0(79 void)100 L (12 #define MEMDEBUG 0)0(80 memdebug\(void\))100 L (13)0(81 {)100 L (14 #define PDX\(va\))0(\(\(\(\(ulong\)\(va\)\)>>22\) & 0x03FF\))32(82)100(Map *mp;)108 L (15 #define PTX\(va\))0(\(\(\(\(ulong\)\(va\)\)>>12\) & 0x03FF\))32(83)100(ulong maxpa, maxpa1, maxpa2;)108 L (16)0(84)100 L (17 enum {)0(85)100(if\(MEMDEBUG == 0\))108 L (18)0(MemUPA)8(= 0,)24(/* unbacked physical address */)40(86)100(return;)116 L (19)0(MemRAM)8(= 1,)24(/* physical memory */)40(87)100 L (20)0(MemUMB)8(= 2,)24(/* upper memory block \(<16MB\) */)40(88)100(maxpa = \(nvramread\(0x18\)<<8\)|nvramread\(0x17\);)108 L (21)0(NMemType)8(= 3,)24(89)100(maxpa1 = \(nvramread\(0x31\)<<8\)|nvramread\(0x30\);)108 L (22)0(90)100(maxpa2 = \(nvramread\(0x16\)<<8\)|nvramread\(0x15\);)108 L (23)0(KB)8(= 1024,)24(91)100(print\("maxpa = %luX -> %luX, maxpa1 = %luX maxpa2 = %luX\\n",)108 L (24)0(92)100(maxpa, MB+maxpa*KB, maxpa1, maxpa2\);)116 L (25)0(MemMinMB)8(= 4,)24(/* minimum physical memory \(<=4MB\) */)40(93)100 L (26)0(MemMaxMB)8(= 768,)24(/* maximum physical memory to check */)40(94)100(for\(mp = rmapram.map; mp->size; mp++\))108 L (27)0(95)100(print\("%8.8luX %8.8uX %8.8luX\\n", mp->addr, mp->size, mp->addr+mp->size\);)116 L (28)0(NMemBase)8(= 10,)24(96)100(for\(mp = rmapumb.map; mp->size; mp++\))108 L (29 };)0(97)100(print\("%8.8luX %8.8uX %8.8luX\\n", mp->addr, mp->size, mp->addr+mp->size\);)116 L (30)0(98)100(for\(mp = rmapumbrw.map; mp->size; mp++\))108 L (31 typedef struct {)0(99)100(print\("%8.8luX %8.8uX %8.8luX\\n", mp->addr, mp->size, mp->addr+mp->size\);)116 L (32)0(int size;)8(100 for\(mp = rmapupa.map; mp->size; mp++\))100 L (33)0(ulong addr;)8(101)100(print\("%8.8luX %8.8uX %8.8luX\\n", mp->addr, mp->size, mp->addr+mp->size\);)116 L (34 } Map;)0(102 })100 L (35)0(103)100 L (36 typedef struct {)0(104 void)100 L (37)0(char* name;)8(105 mapfree\(RMap* rmap, ulong addr, ulong size\))100 L (38)0(Map* map;)8(106 {)100 L (39)0(Map* mapend;)8(107 Map *mp;)100 L (40)0(108 ulong t;)100 L (41)0(Lock;)8(109)100 L (42 } RMap;)0(110 if\(size <= 0\))100 L (43)0(111)100(return;)116 L (44 static Map mapupa[16];)0(112)100 L (45 static RMap rmapupa = {)0(113 lock\(rmap\);)100 L (46)0("unallocated unbacked physical memory",)8(114 for\(mp = rmap->map; mp->addr <= addr && mp->size; mp++\))100 L (47)0(mapupa,)8(115)100(;)116 L (48)0(&mapupa[nelem\(mapupa\)-1],)8(116)100 L (49 };)0(117 if\(mp > rmap->map && \(mp-1\)->addr+\(mp-1\)->size == addr\){)100 L (50)0(118)100(\(mp-1\)->size += size;)116 L (51 static Map xmapupa[16];)0(119)100(if\(addr+size == mp->addr\){)116 L (52 static RMap xrmapupa = {)0(120)100(\(mp-1\)->size += mp->size;)124 L (53)0("unbacked physical memory",)8(121)100(while\(mp->size\){)124 L (54)0(xmapupa,)8(122)100(mp++;)132 L (55)0(&xmapupa[nelem\(xmapupa\)-1],)8(123)100(\(mp-1\)->addr = mp->addr;)132 L (56 };)0(124)100(\(mp-1\)->size = mp->size;)132 L (57)0(125)100(})124 L (58 static Map mapram[16];)0(126)100(})116 L (59 static RMap rmapram = {)0(127 })100 L (60)0("physical memory",)8(128 else{)100 L (61)0(mapram,)8(129)100(if\(addr+size == mp->addr && mp->size\){)116 L (62)0(&mapram[nelem\(mapram\)-1],)8(130)100(mp->addr -= size;)124 L (63 };)0(131)100(mp->size += size;)124 L (64)0(132)100(})116 L (65 static Map mapumb[64];)0(133)100(else do{)116 L (66 static RMap rmapumb = {)0(134)100(if\(mp >= rmap->mapend\){)124 L (67)0("upper memory block",)8(135)100(print\("mapfree: %s: losing 0x%luX, %ld\\n",)132 L (68)0(mapumb,)8(136)100(rmap->name, addr, size\);)140 L cleartomark showpage saveobj restore %%EndPage: 64 64 %%Page: 65 65 /saveobj save def mark 65 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/memory.c Page 2)l ()l ()l (137)0(break;)32(205 })100 L (138)0(})24(206)100 L (139)0(t = mp->addr;)24(207 static void)100 L (140)0(mp->addr = addr;)24(208 umbscan\(void\))100 L (141)0(addr = t;)24(209 {)100 L (142)0(t = mp->size;)24(210 uchar *p;)100 L (143)0(mp->size = size;)24(211)100 L (144)0(mp++;)24(212 /*)100 L (145)0(}while\(size = t\);)16(213)100(* Scan the Upper Memory Blocks \(0xA0000->0xF0000\) for pieces)109 L (146 })0(214)100(* which aren't used; they can be used later for devices which)109 L (147 unlock\(rmap\);)0(215)100(* want to allocate some virtual address space.)109 L (148 })0(216)100(* Check for two things:)109 L (149)0(217)100(* 1\) device BIOS ROM. This should start with a two-byte header)109 L (150 ulong)0(218)100(* of 0x55 0xAA, followed by a byte giving the size of the ROM)109 L (151 mapalloc\(RMap* rmap, ulong addr, int size, int align\))0(219)100(* in 512-byte chunks. These ROM's must start on a 2KB boundary.)109 L (152 {)0(220)100(* 2\) device memory. This is read-write.)109 L (153 Map *mp;)0(221)100(* There are some assumptions: there's VGA memory at 0xA0000 and)109 L (154 ulong maddr, oaddr;)0(222)100(* the VGA BIOS ROM is at 0xC0000. Also, if there's no ROM signature)109 L (155)0(223)100(* at 0xE0000 then the whole 64KB up to 0xF0000 is theoretically up)109 L (156 lock\(rmap\);)0(224)100(* for grabs; check anyway.)109 L (157 for\(mp = rmap->map; mp->size; mp++\){)0(225)100(*/)109 L (158)0(maddr = mp->addr;)16(226 p = KADDR\(0xC0000\);)100 L (159)0(227 while\(p < \(uchar*\)KADDR\(0xE0000\)\){)100 L (160)0(if\(addr\){)16(228)100(p[0] = 0xCC;)116 L (161)0(/*)24(229)100(p[2*KB-1] = 0xCC;)116 L (162)0(* A specific address range has been given:)25(230)100(if\(p[0] != 0xCC || p[2*KB-1] != 0xCC\){)116 L (163)0(* if the current map entry is greater then)25(231)100(p[0] = 0x55;)124 L (164)0(* the address is not in the map;)25(232)100(p[1] = 0xAA;)124 L (165)0(* if the current map entry does not overlap)25(233)100(p[2] = 4;)124 L (166)0(* the beginning of the requested range then)25(234)100(if\(p[0] == 0x55 && p[1] == 0xAA\){)124 L (167)0(* continue on to the next map entry;)25(235)100(p += p[2]*512;)132 L (168)0(* if the current map entry does not entirely)25(236)100(continue;)132 L (169)0(* contain the requested range then the range)25(237)100(})124 L (170)0(* is not in the map.)25(238)100(if\(p[0] == 0xFF && p[1] == 0xFF\))124 L (171)0(*/)25(239)100(mapfree\(&rmapumb, PADDR\(p\), 2*KB\);)132 L (172)0(if\(maddr > addr\))24(240)100(})116 L (173)0(break;)32(241)100(else)116 L (174)0(if\(maddr+mp->size < addr\))24(242)100(mapfree\(&rmapumbrw, PADDR\(p\), 2*KB\);)124 L (175)0(continue;)32(243)100(p += 2*KB;)116 L (176)0(if\(addr+size > maddr+mp->size\))24(244 })100 L (177)0(break;)32(245)100 L (178)0(maddr = addr;)24(246 p = KADDR\(0xE0000\);)100 L (179)0(})16(247 if\(p[0] != 0x55 || p[1] != 0xAA\){)100 L (180)0(248)100(p[0] = 0xCC;)116 L (181)0(if\(align > 0\))16(249)100(p[64*KB-1] = 0xCC;)116 L (182)0(maddr = \(\(maddr+align-1\)/align\)*align;)24(250)100(if\(p[0] != 0xCC && p[64*KB-1] != 0xCC\))116 L (183)0(if\(mp->addr+mp->size-maddr < size\))16(251)100(mapfree\(&rmapumb, PADDR\(p\), 64*KB\);)124 L (184)0(continue;)24(252 })100 L (185)0(253 })100 L (186)0(oaddr = mp->addr;)16(254)100 L (187)0(mp->addr = maddr+size;)16(255 static void)100 L (188)0(mp->size -= maddr-oaddr+size;)16(256 ramscan\(ulong maxmem\))100 L (189)0(if\(mp->size == 0\){)16(257 {)100 L (190)0(do{)24(258 ulong *k0, kzero, map, maxpa, pa, *pte, *table, *va, x;)100 L (191)0(mp++;)32(259 int nvalid[NMemType];)100 L (192)0(\(mp-1\)->addr = mp->addr;)32(260 uchar *bda;)100 L (193)0(}while\(\(mp-1\)->size = mp->size\);)24(261)100 L (194)0(})16(262 /*)100 L (195)0(263)100(* The bootstrap code has has created a prototype page)109 L (196)0(unlock\(rmap\);)16(264)100(* table which maps the first MemMinMB of physical memory to KZERO.)109 L (197)0(if\(oaddr != maddr\))16(265)100(* The page directory is at m->pdb and the first page of)109 L (198)0(mapfree\(rmap, oaddr, maddr-oaddr\);)24(266)100(* free memory is after the per-processor MMU information.)109 L (199)0(267)100(*/)109 L (200)0(return maddr;)16(268 /*)100 L (201 })0(269)100(* Initialise the memory bank information for conventional memory)109 L (202 unlock\(rmap\);)0(270)100(* \(i.e. less than 640KB\). The base is the first location after the)109 L (203)0(271)100(* bootstrap processor MMU information and the limit is obtained from)109 L (204 return 0;)0(272)100(* the BIOS data area.)109 L cleartomark showpage saveobj restore %%EndPage: 65 65 %%Page: 66 66 /saveobj save def mark 66 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/memory.c Page 3)l ()l ()l (273)0(*/)9(341)100(* chunk is marked uncached and added to the UMB pool if <16MB)117 L (274 x = PADDR\(CPU0MACH+BY2PG\);)0(342)100(* or is marked invalid and added to the UPA pool.)117 L (275 bda = \(uchar*\)KADDR\(0x400\);)0(343)100(*/)117 L (276 mapfree\(&rmapram, x, \(\(bda[0x14]<<8\)|bda[0x13]\)*KB-x\);)0(344)100(*va = x;)116 L (277)0(345)100(*k0 = ~x;)116 L (278 x = PADDR\(PGROUND\(\(ulong\)end\)\);)0(346)100(if\(*va == x\){)116 L (279 pa = MemMinMB*MB;)0(347)100(nvalid[MemRAM] += MB/BY2PG;)124 L (280 mapfree\(&rmapram, x, pa-x\);)0(348)100(mapfree\(&rmapram, pa, MB\);)124 L (281)0(349)100 L (282 /*)0(350)100(do{)124 L (283)0(* Check if the extended memory size can be obtained from the CMOS.)9(351)100(*pte++ = pa|PTEWRITE|PTEVALID;)132 L (284)0(* If it's 0 then it's either not known or >= 64MB. Always check)9(352)100(pa += BY2PG;)132 L (285)0(* at least 24MB in case there's a memory gap \(up to 8MB\) below 16MB;)9(353)100(}while\(pa % MB\);)124 L (286)0(* in this case the memory from the gap is remapped to the top of)9(354)100(mmuflushtlb\(PADDR\(m->pdb\)\);)124 L (287)0(* memory.)9(355 //)100(memset\(va, 0, MB\);)132 L (288)0(* The value in CMOS is supposed to be the number of KB above 1MB.)9(356)100(})116 L (289)0(*/)9(357)100(else if\(pa < 16*MB\){)116 L (290 if\(maxmem == 0\){)0(358)100(nvalid[MemUMB] += MB/BY2PG;)124 L (291)0(x = \(nvramread\(0x18\)<<8\)|nvramread\(0x17\);)16(359)100(mapfree\(&rmapumb, pa, MB\);)124 L (292)0(if\(x == 0 || x >= \(63*KB\)\))16(360)100 L (293)0(maxpa = MemMaxMB*MB;)24(361)100(do{)124 L (294)0(else)16(362)100(*pte++ = pa|PTEWRITE|PTEUNCACHED|PTEVALID;)132 L (295)0(maxpa = MB+x*KB;)24(363)100(pa += BY2PG;)132 L (296)0(if\(maxpa < 24*MB\))16(364)100(}while\(pa % MB\);)124 L (297)0(maxpa = 24*MB;)24(365)100(})116 L (298)0(maxmem = MemMaxMB*MB;)16(366)100(else{)116 L (299 })0(367)100(nvalid[MemUPA] += MB/BY2PG;)124 L (300 else)0(368)100(mapfree\(&rmapupa, pa, MB\);)124 L (301)0(maxpa = maxmem;)16(369)100 L (302)0(370)100(*pte = 0;)124 L (303 /*)0(371)100(pa += MB;)124 L (304)0(* March up memory from MemMinMB to maxpa 1MB at a time,)9(372)100(})116 L (305)0(* mapping the first page and checking the page can)9(373)100 L (306)0(* be written and read correctly. The page tables are created here)9(374)100(/*)116 L (307)0(* on the fly, allocating from low memory as necessary.)9(375)100(* Done with this 4MB chunk, review the options:)117 L (308)0(*/)9(376)100(* 1\) not physical memory and >=16MB - invalidate the PDB entry;)117 L (309 k0 = \(ulong*\)KADDR\(0\);)0(377)100(* 2\) physical memory - use the 4MB page extension if possible;)117 L (310 kzero = *k0;)0(378)100(* 3\) not physical memory and <16MB - use the 4MB page extension)117 L (311 map = 0;)0(379)100(* if possible;)117 L (312 x = 0x12345678;)0(380)100(* 4\) mixed or no 4MB page extension - commit the already)117 L (313 memset\(nvalid, 0, sizeof\(nvalid\)\);)0(381)100(* initialised space for the page table.)117 L (314 while\(pa < maxpa\){)0(382)100(*/)117 L (315)0(/*)16(383)100(if\(\(pa % \(4*MB\)\) == 0\){)116 L (316)0(* Map the page. Use mapalloc\(&rmapram, ...\) to make)17(384)100(table = &m->pdb[PDX\(va\)];)124 L (317)0(* the page table if necessary, it will be returned to the)17(385)100(if\(nvalid[MemUPA] == \(4*MB\)/BY2PG\))124 L (318)0(* pool later if it isn't needed.)17(386)100(*table = 0;)132 L (319)0(*/)17(387)100(else if\(nvalid[MemRAM] == \(4*MB\)/BY2PG && \(m->cpuiddx & 0x08\)\))124 L (320)0(va = KADDR\(pa\);)16(388)100(*table = \(pa - 4*MB\)|PTESIZE|PTEWRITE|PTEVALID;)132 L (321)0(table = &m->pdb[PDX\(va\)];)16(389)100(else if\(nvalid[MemUMB] == \(4*MB\)/BY2PG && \(m->cpuiddx & 0x08\)\))124 L (322)0(if\(*table == 0\){)16(390)100(*table = \(pa - 4*MB\)|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;)132 L (323)0(if\(map == 0 && \(map = mapalloc\(&rmapram, 0, BY2PG, BY2PG\)\) == 0\))24(391)100(else)124 L (324)0(break;)32(392)100(map = 0;)132 L (325)0(memset\(KADDR\(map\), 0, BY2PG\);)24(393)100(})116 L (326)0(*table = map|PTEWRITE|PTEVALID;)24(394)100 L (327)0(memset\(nvalid, 0, sizeof\(nvalid\)\);)24(395)100(mmuflushtlb\(PADDR\(m->pdb\)\);)116 L (328)0(})16(396)100(x += 0x3141526;)116 L (329)0(table = KADDR\(PPN\(*table\)\);)16(397 })100 L (330)0(pte = &table[PTX\(va\)];)16(398 if\(map\))100 L (331)0(399)100(mapfree\(&rmapram, map, BY2PG\);)116 L (332)0(*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;)16(400 if\(pa < maxmem\))100 L (333)0(mmuflushtlb\(PADDR\(m->pdb\)\);)16(401)100(mapfree\(&rmapupa, pa, maxmem-pa\);)116 L (334)0(402 if\(maxmem < 0xFFE00000\))100 L (335)0(/*)16(403)100(mapfree\(&rmapupa, maxmem, 0xFFE00000-maxmem\);)116 L (336)0(* Write a pattern to the page and write a different)17(404 if\(MEMDEBUG\))100 L (337)0(* pattern to a possible mirror at KZER0. If the data)17(405)100(print\("maxmem %luX %luX\\n", maxmem, 0xFFE00000-maxmem\);)116 L (338)0(* reads back correctly the chunk is some type of RAM \(possibly)17(406 *k0 = kzero;)100 L (339)0(* a linearly-mapped VGA framebuffer, for instance...\) and)17(407 })100 L (340)0(* can be cleared and added to the memory pool. If not, the)17(408)100 L cleartomark showpage saveobj restore %%EndPage: 66 66 %%Page: 67 67 /saveobj save def mark 67 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/memory.c Page 4)l ()l ()l (409 void)0(477 ulong a;)100 L (410 meminit\(ulong maxmem\))0(478 uchar *p;)100 L (411 {)0(479)100 L (412 Map *mp, *xmp;)0(480 if\(a = mapalloc\(&rmapumbrw, addr, size, align\)\))100 L (413 ulong pa, *pte;)0(481)100(return\(ulong\)KADDR\(a\);)116 L (414)0(482)100 L (415 /*)0(483 /*)100 L (416)0(* Set special attributes for memory between 640KB and 1MB:)9(484)100(* Perhaps the memory wasn't visible before)109 L (417)0(* VGA memory is writethrough;)9(485)100(* the interface is initialised, so try again.)109 L (418)0(* BIOS ROM's/UMB's are uncached;)9(486)100(*/)109 L (419)0(* then scan for useful memory.)9(487 if\(\(a = umbmalloc\(addr, size, align\)\) == 0\))100 L (420)0(*/)9(488)100(return 0;)116 L (421 for\(pa = 0xA0000; pa < 0xC0000; pa += BY2PG\){)0(489 p = \(uchar*\)a;)100 L (422)0(pte = mmuwalk\(m->pdb, \(ulong\)KADDR\(pa\), 2, 0\);)16(490 p[0] = 0xCC;)100 L (423)0(*pte |= PTEWT;)16(491 p[size-1] = 0xCC;)100 L (424 })0(492 if\(p[0] == 0xCC && p[size-1] == 0xCC\))100 L (425 for\(pa = 0xC0000; pa < 0x100000; pa += BY2PG\){)0(493)100(return a;)116 L (426)0(pte = mmuwalk\(m->pdb, \(ulong\)KADDR\(pa\), 2, 0\);)16(494 umbfree\(a, size\);)100 L (427)0(*pte |= PTEUNCACHED;)16(495)100 L (428 })0(496 return 0;)100 L (429 mmuflushtlb\(PADDR\(m->pdb\)\);)0(497 })100 L (430)0(498)100 L (431 umbscan\(\);)0(499 void)100 L (432 ramscan\(maxmem\);)0(500 umbrwfree\(ulong addr, int size\))100 L (433)0(501 {)100 L (434 /*)0(502 mapfree\(&rmapumbrw, PADDR\(addr\), size\);)100 L (435)0(* Set the conf entries describing two banks of allocatable memory.)9(503 })100 L (436)0(* Grab the first and largest entries in rmapram as left by ramscan\(\).)9(504)100 L (437)0(*)9(505 ulong)100 L (438)0(* It would be nice to have more than 2 memory banks describable in conf.)9(506 upamalloc\(ulong pa, int size, int align\))100 L (439)0(*/)9(507 {)100 L (440 mp = rmapram.map;)0(508 ulong a, ae;)100 L (441 conf.base0 = mp->addr;)0(509)100 L (442 conf.npage0 = mp->size/BY2PG;)0(510 if\(a = mapalloc\(&xrmapupa, pa, size, align\)\))100 L (443 mp++;)0(511)100(return a;)116 L (444 for\(xmp = 0; mp->size; mp++\){)0(512)100 L (445)0(if\(xmp == 0 || mp->size > xmp->size\))16(513 if\(\(a = mapalloc\(&rmapupa, pa, size, align\)\) == 0\){)100 L (446)0(xmp = mp;)24(514)100(memdebug\(\);)116 L (447 })0(515)100(return 0;)116 L (448)0(516 })100 L (449 if\(xmp\){)0(517)100 L (450)0(conf.base1 = xmp->addr;)16(518 /*)100 L (451)0(conf.npage1 = xmp->size/BY2PG;)16(519)100(* Upamalloc is a request to map a range of physical addresses.)109 L (452 })0(520)100(* Therefore, if pa is 0 mapalloc will choose the base address.)109 L (453 if\(MEMDEBUG\))0(521)100(* Note, however, mmukmap is always asked to give a 1-to-1 mapping)109 L (454)0(memdebug\(\);)16(522)100(* of va to pa.)109 L (455 })0(523 ae = mmukmap\(a, a, size\);)100 L (456)0(524)100(* ...but for the moment go back to the old scheme for VLB cards.)109 L (457 ulong)0(525)100(*/)109 L (458 umbmalloc\(ulong addr, int size, int align\))0(526 ae = mmukmap\(a, 0, size\);)100 L (459 {)0(527)100 L (460 ulong a;)0(528 /*)100 L (461)0(529)100(* Should check here that it was all delivered)109 L (462 if\(a = mapalloc\(&rmapumb, addr, size, align\)\))0(530)100(* and put it back and barf if not.)109 L (463)0(return \(ulong\)KADDR\(a\);)16(531)100(*/)109 L (464)0(532 USED\(ae\);)100 L (465 return 0;)0(533)100 L (466 })0(534 /*)100 L (467)0(535)100(* Be very careful this returns a PHYSICAL address)109 L (468 void)0(536)100(* mapped 1-to-1 with the virtual address.)109 L (469 umbfree\(ulong addr, int size\))0(537)100(* If a < KZERO it's probably not a good idea to)109 L (470 {)0(538)100(* try KADDR\(a\)...)109 L (471 mapfree\(&rmapumb, PADDR\(addr\), size\);)0(539)100(*/)109 L (472 })0(540 return a;)100 L (473)0(541 })100 L (474 ulong)0(542)100 L (475 umbrwmalloc\(ulong addr, int size, int align\))0(543 void)100 L (476 {)0(544 upafree\(ulong pa, int size\))100 L cleartomark showpage saveobj restore %%EndPage: 67 67 %%Page: 68 68 /saveobj save def mark 68 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/memory.c Page 5)l ()l ()l (545 {)l (546 mapfree\(&xrmapupa, pa, size\);)l (547 })l (548)l cleartomark showpage saveobj restore %%EndPage: 68 68 %%Page: 69 69 /saveobj save def mark 69 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/mmu.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(for\(x = KTZERO; x < \(ulong\)etext; x += BY2PG\){)108 L (2 #include "../port/lib.h")0(70)100(p = mmuwalk\(m->pdb, x, 2, 0\);)116 L (3 #include "mem.h")0(71)100(if\(p == nil\))116 L (4 #include "dat.h")0(72)100(panic\("mmuinit"\);)124 L (5 #include "fns.h")0(73)100(*p &= ~PTEWRITE;)116 L (6 #include "io.h")0(74)100(})108 L (7)0(75)100 L (8 #define DATASEGM\(p\) { 0xFFFF, SEGG|SEGB|\(0xF<<16\)|SEGP|SEGPL\(p\)|SEGDATA|SEGW })0(76)100(taskswitch\(PADDR\(m->pdb\), \(ulong\)m + BY2PG\);)108 L (9 #define EXECSEGM\(p\) { 0xFFFF, SEGG|SEGD|\(0xF<<16\)|SEGP|SEGPL\(p\)|SEGEXEC|SEGR })0(77)100(ltr\(TSSSEL\);)108 L (10 #define TSSSEGM\(b,p\) { \(\(b\)<<16\)|sizeof\(Tss\),\\)0(78 })100 L (11)0(\(\(b\)&0xFF000000\)|\(\(\(b\)>>16\)&0xFF\)|SEGTSS|SEGPL\(p\)|SEGP })26(79)100 L (12)0(80 void)100 L (13 Segdesc gdt[6] =)0(81 flushmmu\(void\))100 L (14 {)0(82 {)100 L (15 [NULLSEG] { 0, 0},)0(/* null descriptor */)40(83)100(int s;)108 L (16 [KDSEG])0(DATASEGM\(0\),)24(/* kernel data/stack */)48(84)100 L (17 [KESEG])0(EXECSEGM\(0\),)24(/* kernel code */)48(85)100(s = splhi\(\);)108 L (18 [UDSEG])0(DATASEGM\(3\),)24(/* user data/stack */)48(86)100(up->newtlb = 1;)108 L (19 [UESEG])0(EXECSEGM\(3\),)24(/* user code */)48(87)100(mmuswitch\(up\);)108 L (20 [TSSSEG] TSSSEGM\(0,0\),)0(/* tss segment */)40(88)100(splx\(s\);)108 L (21 };)0(89 })100 L (22)0(90)100 L (23 #define PDX\(va\))0(\(\(\(\(ulong\)\(va\)\)>>22\) & 0x03FF\))32(91 static void)100 L (24 #define PTX\(va\))0(\(\(\(\(ulong\)\(va\)\)>>12\) & 0x03FF\))32(92 mmuptefree\(Proc* proc\))100 L (25)0(93 {)100 L (26 static void)0(94)100(ulong *pdb;)108 L (27 taskswitch\(ulong pdb, ulong stack\))0(95)100(Page **last, *page;)108 L (28 {)0(96)100 L (29)0(Tss *tss;)8(97)100(if\(proc->mmupdb && proc->mmuused\){)108 L (30)0(98)100(pdb = \(ulong*\)proc->mmupdb->va;)116 L (31)0(tss = m->tss;)8(99)100(last = &proc->mmuused;)116 L (32)0(tss->ss0 = KDSEL;)8(100)100(for\(page = *last; page; page = page->next\){)116 L (33)0(tss->esp0 = stack;)8(101)100(pdb[page->daddr] = 0;)124 L (34)0(tss->ss1 = KDSEL;)8(102)100(last = &page->next;)124 L (35)0(tss->esp1 = stack;)8(103)100(})116 L (36)0(tss->ss2 = KDSEL;)8(104)100(*last = proc->mmufree;)116 L (37)0(tss->esp2 = stack;)8(105)100(proc->mmufree = proc->mmuused;)116 L (38)0(tss->cr3 = pdb;)8(106)100(proc->mmuused = 0;)116 L (39)0(putcr3\(pdb\);)8(107 })100 L (40 })0(108 })100 L (41)0(109)100 L (42 void)0(110 void)100 L (43 mmuinit\(void\))0(111 mmuswitch\(Proc* proc\))100 L (44 {)0(112 {)100 L (45)0(ulong x, *p;)8(113 ulong *pdb;)100 L (46)0(ushort ptr[3];)8(114)100 L (47)0(115 if\(proc->newtlb\){)100 L (48)0(m->tss = malloc\(sizeof\(Tss\)\);)8(116)100(mmuptefree\(proc\);)116 L (49)0(memset\(m->tss, 0, sizeof\(Tss\)\);)8(117)100(proc->newtlb = 0;)116 L (50)0(118 })100 L (51)0(memmove\(m->gdt, gdt, sizeof\(m->gdt\)\);)8(119)100 L (52)0(x = \(ulong\)m->tss;)8(120 if\(proc->mmupdb\){)100 L (53)0(m->gdt[TSSSEG].d0 = \(x<<16\)|sizeof\(Tss\);)8(121)100(pdb = \(ulong*\)proc->mmupdb->va;)116 L (54)0(m->gdt[TSSSEG].d1 = \(x&0xFF000000\)|\(\(x>>16\)&0xFF\)|SEGTSS|SEGPL\(0\)|SEGP;)8(122)100(pdb[PDX\(MACHADDR\)] = m->pdb[PDX\(MACHADDR\)];)116 L (55)0(123)100(taskswitch\(proc->mmupdb->pa, \(ulong\)\(proc->kstack+KSTACK\)\);)116 L (56)0(ptr[0] = sizeof\(m->gdt\);)8(124 })100 L (57)0(x = \(ulong\)m->gdt;)8(125 else)100 L (58)0(ptr[1] = x & 0xFFFF;)8(126)100(taskswitch\(PADDR\(m->pdb\), \(ulong\)\(proc->kstack+KSTACK\)\);)116 L (59)0(ptr[2] = \(x>>16\) & 0xFFFF;)8(127 })100 L (60)0(lgdt\(ptr\);)8(128)100 L (61)0(129 void)100 L (62)0(ptr[0] = sizeof\(Segdesc\)*256;)8(130 mmurelease\(Proc* proc\))100 L (63)0(x = IDTADDR;)8(131 {)100 L (64)0(ptr[1] = x & 0xFFFF;)8(132 Page *page, *next;)100 L (65)0(ptr[2] = \(x>>16\) & 0xFFFF;)8(133)100 L (66)0(lidt\(ptr\);)8(134 /*)100 L (67)0(135)100(* Release any pages allocated for a page directory base or page-tables)109 L (68)0(/* make kernel text unwritable */)8(136)100(* for this process:)109 L cleartomark showpage saveobj restore %%EndPage: 69 69 %%Page: 70 70 /saveobj save def mark 70 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/mmu.c Page 2)l ()l ()l (137)0(* switch to the prototype pdb for this processor \(m->pdb\);)9(205 pdb = \(ulong*\)up->mmupdb->va;)100 L (138)0(* call mmuptefree\(\) to place all pages used for page-tables \(proc->mmuused\))9(206 pdbx = PDX\(va\);)100 L (139)0(* onto the process' free list \(proc->mmufree\). This has the side-effect of)9(207)100 L (140)0(* cleaning any user entries in the pdb \(proc->mmupdb\);)9(208 if\(PPN\(pdb[pdbx]\) == 0\){)100 L (141)0(* if there's a pdb put it in the cache of pre-initialised pdb's)9(209)100(if\(up->mmufree == 0\){)116 L (142)0(* for this processor \(m->pdbpool\) or on the process' free list;)9(210)100(page = newpage\(1, 0, 0\);)124 L (143)0(* finally, place any pages freed back into the free pool \(palloc\).)9(211)100(page->va = VA\(kmap\(page\)\);)124 L (144)0(* This routine is only called from sched\(\) with palloc locked.)9(212)100(})116 L (145)0(*/)9(213)100(else {)116 L (146 taskswitch\(PADDR\(m->pdb\), \(ulong\)m + BY2PG\);)0(214)100(page = up->mmufree;)124 L (147 mmuptefree\(proc\);)0(215)100(up->mmufree = page->next;)124 L (148)0(216)100(memset\(\(void*\)page->va, 0, BY2PG\);)124 L (149 if\(proc->mmupdb\){)0(217)100(})116 L (150)0(if\(m->pdbcnt > 10\){)16(218)100(pdb[pdbx] = PPN\(page->pa\)|PTEUSER|PTEWRITE|PTEVALID;)116 L (151)0(proc->mmupdb->next = proc->mmufree;)24(219)100(page->daddr = pdbx;)116 L (152)0(proc->mmufree = proc->mmupdb;)24(220)100(page->next = up->mmuused;)116 L (153)0(})16(221)100(up->mmuused = page;)116 L (154)0(else{)16(222 })100 L (155)0(proc->mmupdb->next = m->pdbpool;)24(223)100 L (156)0(m->pdbpool = proc->mmupdb;)24(224 pte = KADDR\(PPN\(pdb[pdbx]\)\);)100 L (157)0(m->pdbcnt++;)24(225 pte[PTX\(va\)] = pa|PTEUSER;)100 L (158)0(})16(226)100 L (159)0(proc->mmupdb = 0;)16(227 s = splhi\(\);)100 L (160 })0(228 pdb[PDX\(MACHADDR\)] = m->pdb[PDX\(MACHADDR\)];)100 L (161)0(229 mmuflushtlb\(up->mmupdb->pa\);)100 L (162 for\(page = proc->mmufree; page; page = next\){)0(230 splx\(s\);)100 L (163)0(next = page->next;)16(231 })100 L (164)0(if\(--page->ref\))16(232)100 L (165)0(panic\("mmurelease: page->ref %d\\n", page->ref\);)24(233 ulong*)100 L (166)0(pagechainhead\(page\);)16(234 mmuwalk\(ulong* pdb, ulong va, int level, int create\))100 L (167 })0(235 {)100 L (168 if\(proc->mmufree && palloc.r.p\))0(236 ulong pa, *table;)100 L (169)0(wakeup\(&palloc.r\);)16(237)100 L (170 proc->mmufree = 0;)0(238 /*)100 L (171 })0(239)100(* Walk the page-table pointed to by pdb and return a pointer)109 L (172)0(240)100(* to the entry for virtual address va at the requested level.)109 L (173 static Page*)0(241)100(* If the entry is invalid and create isn't requested then bail)109 L (174 mmupdballoc\(void\))0(242)100(* out early. Otherwise, for the 2nd level walk, allocate a new)109 L (175 {)0(243)100(* page-table page and register it in the 1st level.)109 L (176 int s;)0(244)100(*/)109 L (177 Page *page;)0(245 table = &pdb[PDX\(va\)];)100 L (178)0(246 if\(!\(*table & PTEVALID\) && create == 0\))100 L (179 s = splhi\(\);)0(247)100(return 0;)116 L (180 if\(m->pdbpool == 0\){)0(248)100 L (181)0(spllo\(\);)16(249 switch\(level\){)100 L (182)0(page = newpage\(0, 0, 0\);)16(250)100 L (183)0(page->va = VA\(kmap\(page\)\);)16(251 default:)100 L (184)0(memmove\(\(void*\)page->va, m->pdb, BY2PG\);)16(252)100(return 0;)116 L (185 })0(253)100 L (186 else{)0(254 case 1:)100 L (187)0(page = m->pdbpool;)16(255)100(return table;)116 L (188)0(m->pdbpool = page->next;)16(256)100 L (189)0(m->pdbcnt--;)16(257 case 2:)100 L (190 })0(258)100(if\(*table & PTESIZE\))116 L (191 splx\(s\);)0(259)100(panic\("mmuwalk2: va %uX entry %uX\\n", va, *table\);)124 L (192 return page;)0(260)100(if\(!\(*table & PTEVALID\)\){)116 L (193 })0(261)100(pa = PADDR\(xspanalloc\(BY2PG, BY2PG, 0\)\);)124 L (194)0(262)100(*table = pa|PTEWRITE|PTEVALID;)124 L (195 void)0(263)100(})116 L (196 putmmu\(ulong va, ulong pa, Page*\))0(264)100(table = KADDR\(PPN\(*table\)\);)116 L (197 {)0(265)100 L (198 int pdbx;)0(266)100(return &table[PTX\(va\)];)116 L (199 Page *page;)0(267 })100 L (200 ulong *pdb, *pte;)0(268 })100 L (201 int s;)0(269)100 L (202)0(270 static Lock mmukmaplock;)100 L (203 if\(up->mmupdb == 0\))0(271)100 L (204)0(up->mmupdb = mmupdballoc\(\);)16(272 int)100 L cleartomark showpage saveobj restore %%EndPage: 70 70 %%Page: 71 71 /saveobj save def mark 71 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/mmu.c Page 3)l ()l ()l (273 mmukmapsync\(ulong va\))0(341)100(* If not, adjust pgsz up to the next 4MB boundary)133 L (274 {)0(342)100(* and continue.)133 L (275 Mach *mach0;)0(343)100(*/)133 L (276 ulong entry, *pte;)0(344)100(x = PPN\(*table\);)132 L (277)0(345)100(if\(x != pa\))132 L (278 mach0 = MACHP\(0\);)0(346)100(panic\("mmukmap1: pa %uX entry %uX\\n",)140 L (279)0(347)100(pa, *table\);)148 L (280 lock\(&mmukmaplock\);)0(348)100(x += 4*MB;)132 L (281)0(349)100(if\(pae <= x\){)132 L (282 if\(\(pte = mmuwalk\(mach0->pdb, va, 1, 0\)\) == nil\){)0(350)100(pa = pae;)140 L (283)0(unlock\(&mmukmaplock\);)16(351)100(break;)140 L (284)0(return 0;)16(352)100(})132 L (285 })0(353)100(pgsz = x - pa;)132 L (286 if\(!\(*pte & PTESIZE\) && mmuwalk\(mach0->pdb, va, 2, 0\) == nil\){)0(354)100(pa += pgsz;)132 L (287)0(unlock\(&mmukmaplock\);)16(355)100(va += pgsz;)132 L (288)0(return 0;)16(356)100 L (289 })0(357)100(continue;)132 L (290 entry = *pte;)0(358)100(})124 L (291)0(359)100(else{)124 L (292 if\(!\(m->pdb[PDX\(va\)] & PTEVALID\)\))0(360)100(/*)132 L (293)0(m->pdb[PDX\(va\)] = entry;)16(361)100(* Little page. Walk to the entry.)133 L (294)0(362)100(* If the entry is valid, set pgsz and continue.)133 L (295 if\(up && up->mmupdb\){)0(363)100(* If not, make it so, set pgsz, sync and continue.)133 L (296)0(\(\(ulong*\)up->mmupdb->va\)[PDX\(va\)] = entry;)16(364)100(*/)133 L (297)0(mmuflushtlb\(up->mmupdb->pa\);)16(365)100(pte = mmuwalk\(mach0->pdb, va, 2, 0\);)132 L (298 })0(366)100(if\(pte && *pte & PTEVALID\){)132 L (299 else)0(367)100(x = PPN\(*pte\);)140 L (300)0(mmuflushtlb\(PADDR\(m->pdb\)\);)16(368)100(if\(x != pa\))140 L (301)0(369)100(panic\("mmukmap2: pa %uX entry %uX\\n",)148 L (302 unlock\(&mmukmaplock\);)0(370)100(pa, *pte\);)156 L (303)0(371)100(pgsz = BY2PG;)140 L (304 return 1;)0(372)100(pa += pgsz;)140 L (305 })0(373)100(va += pgsz;)140 L (306)0(374)100(sync++;)140 L (307 ulong)0(375)100 L (308 mmukmap\(ulong pa, ulong va, int size\))0(376)100(continue;)140 L (309 {)0(377)100(})132 L (310 Mach *mach0;)0(378)100(})124 L (311 ulong ova, pae, *table, pgsz, *pte, x;)0(379)100(})116 L (312 int pse, sync;)0(380)100 L (313)0(381)100(/*)116 L (314 mach0 = MACHP\(0\);)0(382)100(* Not mapped. Check if it can be mapped using a big page -)117 L (315 if\(\(mach0->cpuiddx & 0x08\) && \(getcr4\(\) & 0x10\)\))0(383)100(* starts on a 4MB boundary, size >= 4MB and processor can do it.)117 L (316)0(pse = 1;)16(384)100(* If not a big page, walk the walk, talk the talk.)117 L (317 else)0(385)100(* Sync is set.)117 L (318)0(pse = 0;)16(386)100(*/)117 L (319 sync = 0;)0(387)100(if\(pse && \(pa % \(4*MB\)\) == 0 && \(pae >= pa+4*MB\)\){)116 L (320)0(388)100(*table = pa|PTESIZE|PTEWRITE|PTEUNCACHED|PTEVALID;)124 L (321 pa = PPN\(pa\);)0(389)100(pgsz = 4*MB;)124 L (322 if\(va == 0\))0(390)100(})116 L (323)0(va = \(ulong\)KADDR\(pa\);)16(391)100(else{)116 L (324 else)0(392)100(pte = mmuwalk\(mach0->pdb, va, 2, 1\);)124 L (325)0(va = PPN\(va\);)16(393)100(*pte = pa|PTEWRITE|PTEUNCACHED|PTEVALID;)124 L (326 ova = va;)0(394)100(pgsz = BY2PG;)124 L (327)0(395)100(})116 L (328 pae = pa + size;)0(396)100(pa += pgsz;)116 L (329 lock\(&mmukmaplock\);)0(397)100(va += pgsz;)116 L (330 while\(pa < pae\){)0(398)100(sync++;)116 L (331)0(table = &mach0->pdb[PDX\(va\)];)16(399 })100 L (332)0(/*)16(400 unlock\(&mmukmaplock\);)100 L (333)0(* Possibly already mapped.)17(401)100 L (334)0(*/)17(402 /*)100 L (335)0(if\(*table & PTEVALID\){)16(403)100(* If something was added)109 L (336)0(if\(*table & PTESIZE\){)24(404)100(* then need to sync up.)109 L (337)0(/*)32(405)100(*/)109 L (338)0(* Big page. Does it fit within?)33(406 if\(sync\))100 L (339)0(* If it does, adjust pgsz so the correct end can be)33(407)100(mmukmapsync\(ova\);)116 L (340)0(* returned and get out.)33(408)100 L cleartomark showpage saveobj restore %%EndPage: 71 71 %%Page: 72 72 /saveobj save def mark 72 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/mmu.c Page 4)l ()l ()l (409 return pa;)l (410 })l cleartomark showpage saveobj restore %%EndPage: 72 72 %%Page: 73 73 /saveobj save def mark 73 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/ns16552.h Page 1)l ()l ()l (1 /*)0(69)100(if\(n == 0\))116 L (2)0(* PC specific code for the ns16552. It includes support for the 2 built)7(70)100(return;)124 L (3)0(* in uarts plus up to 5 MP-008 8 uart ISA cards.)7(71)100(for\(i = 0; n; i++\){)116 L (4)0(*/)7(72)100(if\(n & 1\))124 L (5 enum)0(73)100(ns16552intrx\(ureg, \(void*\)\(mp->first+i\)\);)132 L (6 {)0(74)100(n >>= 1;)124 L (7)0(Maxcard= 5,)8(/* max serial cards */)32(75)100(})116 L (8)0(UartFREQ= 1843200,)8(76)100(})108 L (9)0(77 })100 L (10)0(Serial= 0,)8(78)100 L (11)0(Modem= 1,)8(79 /*)100 L (12 };)0(80 * install the uarts \(called by reset\))100 L (13)0(81 */)100 L (14 #define uartwrreg\(u,r,v\) outb\(\(u\)->port + r, \(u\)->sticky[r] | \(v\)\))0(82 void)100 L (15 #define uartrdreg\(u,r\))0(inb\(\(u\)->port + r\))40(83 ns16552install\(void\))100 L (16)0(84 {)100 L (17 void)0(ns16552setup\(ulong, ulong, char*, int\);)16(85)100(int i, j, port, nscard;)108 L (18 void)0(ns16552special\(int, int, Queue**, Queue**, int \(*\)\(Queue*, int\)\);)16(86)100(char *p, *q;)108 L (19 void)0(uartclock\(void\);)16(87)100(Scard *sc;)108 L (20 /*)0(88)100(char name[NAMELEN];)108 L (21 * definition of an optional serial card)0(89)100(static int already;)108 L (22 */)0(90)100 L (23 typedef struct Scard)0(91)100(if\(already\))108 L (24 {)0(92)100(return;)116 L (25)0(ISAConf;)8(/* card configuration */)24(93)100(already = 1;)108 L (26)0(int first; /* number of first port */)8(94)100 L (27 } Scard;)0(95)100(/* first two ports are always there and always the normal frequency */)108 L (28 static Scard *scard[Maxcard]; /* configs for the serial card */)0(96)100(if\(ioalloc\(0x3f8, 8, 0, "eia0"\) < 0\))108 L (29)0(97)100(print\("eia0: port %d in use\\n", 0x3f8\);)116 L (30 /* power management currently only makes sense on the AT&T safari */)0(98)100(ns16552setup\(0x3F8, UartFREQ, "eia0", Ns550\);)108 L (31 static void)0(99)100(intrenable\(IrqUART0, ns16552intrx, \(void*\)0, BUSUNKNOWN, "eia0"\);)108 L (32 uartpower\(int dev, int onoff\))0(100 if\(ioalloc\(0x2F8, 8, 0, "eia1"\) < 0\))100 L (33 {)0(101)100(print\("eia1: port %d in use\\n", 0x2F8\);)116 L (34)0(switch\(dev\){)8(102 ns16552setup\(0x2F8, UartFREQ, "eia1", Ns550\);)100 L (35)0(case Modem:)8(103 intrenable\(IrqUART1, ns16552intrx, \(void*\)1, BUSUNKNOWN, "eia1"\);)100 L (36)0(if\(\(*arch->modempower\)\(onoff\) < 0\))16(104 addclock0link\(uartclock\);)100 L (37)0(print\("can't turn %s modem speaker\\n", onoff?"on":"off"\);)24(105)100 L (38)0(break;)16(106 /* set up a serial console */)100 L (39)0(case Serial:)8(107 if\(p = getconf\("console"\)\){)100 L (40)0(if\(\(*arch->serialpower\)\(onoff\) < 0\))16(108)100(port = strtol\(p, &q, 0\);)116 L (41)0(print\("can't turn %s serial port power\\n", onoff?"on":"off"\);)24(109)100(if\(p != q && \(port == 0 || port == 1\)\))116 L (42)0(break;)16(110)100(ns16552special\(port, 9600, &kbdq, &printq, kbdcr2nl\);)124 L (43)0(})8(111 })100 L (44 })0(112)100 L (45)0(113 /* the rest come out of plan9.ini */)100 L (46 /*)0(114 nscard = 0;)100 L (47 * handle an interrupt to a single uart)0(115 for\(i = 0; i < Maxcard; i++\){)100 L (48 */)0(116)100(sc = scard[nscard] = xalloc\(sizeof\(Scard\)\);)116 L (49 static void)0(117)100(if\(isaconfig\("serial", i, sc\) == 0\){)116 L (50 ns16552intrx\(Ureg*, void* arg\))0(118)100(xfree\(sc\);)124 L (51 {)0(119)100(scard[nscard] = 0;)124 L (52)0(ns16552intr\(\(ulong\)arg\);)8(120)100(continue;)124 L (53 })0(121)100(})116 L (54)0(122)100 L (55 /*)0(123)100(snprint\(name, sizeof name, "eia%d00", nscard\);)116 L (56 * interrupts from the multiport card, MP-008. A polling port)0(124)100(if\(cistrcmp\(sc->type, "MP008"\) == 0\){)116 L (57 * tells which of 8 devices interrupted.)0(125)100(/*)124 L (58 */)0(126)100(* port gives base port address for uarts)125 L (59 static void)0(127)100(* irq is interrupt)125 L (60 mp008intr\(Ureg* ureg, void* arg\))0(128)100(* mem is the polling port)125 L (61 {)0(129)100(* size is the number of serial ports on the same polling port)125 L (62)0(int i, loops;)8(130)100(* freq is the baud rate generator frequency)125 L (63)0(uchar n;)8(131)100(*/)125 L (64)0(Scard *mp;)8(132)100(if\(sc->size == 0\))124 L (65)0(133)100(sc->size = 8;)132 L (66)0(mp = arg;)8(134)100(if\(sc->freq == 0\))124 L (67)0(for\(loops = 0; loops < 1024; loops++\){)8(135)100(sc->freq = UartFREQ;)132 L (68)0(n = ~inb\(mp->mem\);)16(136)100(sc->first = nuart;)124 L cleartomark showpage saveobj restore %%EndPage: 73 73 %%Page: 74 74 /saveobj save def mark 74 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/ns16552.h Page 2)l ()l ()l (137)0(if\(ioalloc\(sc->port, 8*sc->size, 0, name\) < 0\){)24 L (138)0(print\("mp008: port %lud in use\\n", sc->port\);)32 L (139)0(xfree\(sc\);)32 L (140)0(scard[nscard] = 0;)32 L (141)0(continue;)32 L (142)0(})24 L (143)0(intrenable\(sc->irq, mp008intr, sc, BUSUNKNOWN, name\);)24 L (144)0(port = sc->port;)24 L (145)0(for\(j=0; j < sc->size; j++\){)24 L (146)0(sprint\(name, "eia%d%2.2d", nscard, j\);)32 L (147)0(ns16552setup\(port, sc->freq, name, Ns550\);)32 L (148)0(port += 8;)32 L (149)0(})24 L (150)0(} else if\(cistrcmp\(sc->type, "turbo650"\) == 0\){)16 L (151)0(/*)24 L (152)0(* port gives base port address for the uart)25 L (153)0(* irq is interrupt)25 L (154)0(* freq is the baud rate generator frequency)25 L (155)0(*/)25 L (156)0(if\(sc->freq == 0\))24 L (157)0(sc->freq = UartFREQ*4;)32 L (158)0(if\(ioalloc\(sc->port, 8, 0, name\) < 0\){)24 L (159)0(print\("%s: port %lud in use\\n", name, sc->port\);)32 L (160)0(xfree\(sc\);)32 L (161)0(scard[nscard] = 0;)32 L (162)0(continue;)32 L (163)0(})24 L (164)0(ns16552setup\(sc->port, sc->freq, name, Ns650\);)24 L (165)l (166)0(/*)24 L (167)0(* multiply clock speed by 4)25 L (168)0(*/)25 L (169)0(if\(sc->mem == 0\))24 L (170)0(outb\(0x2c8, 0\);)32 L (171)0(else)24 L (172)0(outb\(sc->mem, 0\);)32 L (173)l (174)0(intrenable\(sc->irq, ns16552intrx, \(void*\)\(nuart-1\), BUSUNKNOWN, name\);)24 L (175)0(} else if\(cistrcmp\(sc->type, "com"\) == 0 && sc->port != 0x3F8 && sc->port != 0x2F8\))16 L (176)0(/*)24 L (177)0(* port gives base port address for the uart)25 L (178)0(* irq is interrupt)25 L (179)0(* freq is the baud rate generator frequency)25 L (180)0(*/)25 L (181)0(if\(sc->freq == 0\))24 L (182)0(sc->freq = UartFREQ;)32 L (183)0(if\(ioalloc\(sc->port, 8, 0, name\) < 0\){)24 L (184)0(print\("%s: port %lud in use\\n", name, sc->port\);)32 L (185)0(xfree\(sc\);)32 L (186)0(scard[nscard] = 0;)32 L (187)0(continue;)32 L (188)0(})24 L (189)0(ns16552setup\(sc->port, sc->freq, name, Ns550\);)24 L (190)0(intrenable\(sc->irq, ns16552intrx, \(void*\)\(nuart-1\), BUSUNKNOWN, name\);)24 L (191)0(})16 L (192)0(nscard++;)16 L (193 })l (194 })l cleartomark showpage saveobj restore %%EndPage: 74 74 %%Page: 75 75 /saveobj save def mark 75 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/segment.h Page 1)l ()l ()l (1 /*)l (2)0(* Attach segment types)7 L (3)0(*/)7 L (4 static Physseg physseg[10] = {)l (5)0({ SG_SHARED, "shared",)8(0,)40(SEGMAXSIZE, 0,)48(0 },)72 L (6)0({ SG_BSS,)8("memory",)24(0,)40(SEGMAXSIZE, 0,)48(0 },)72 L (7)0({ 0,)8(0,)24(0,)40(0,)48(0,)64(0 },)72 L (8 };)l cleartomark showpage saveobj restore %%EndPage: 75 75 %%Page: 76 76 /saveobj save def mark 76 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(error\(Ebadarg\);)116 L (2 #include "../port/lib.h")0(70)100 L (3 #include "mem.h")0(71)100(oldn = n;)108 L (4 #include "dat.h")0(72)100(for\(vno=0; vnonext\){)116 L (6 #include "io.h")0(74)100(m = snprint\(str, sizeof str, "%11d %11d %.*s\\n", vno, v->irq, NAMELEN, v->n)124 L (7 #include "ureg.h")0(75)100(if\(m <= offset\) /* if do not want this, skip entry */)124 L (8 #include "../port/error.h")0(76)100(offset -= m;)132 L (9)0(77)100(else{)124 L (10 void)0(noted\(Ureg*, ulong\);)16(78)100(/* skip offset bytes */)132 L (11)0(79)100(m -= offset;)132 L (12 static void debugbpt\(Ureg*, void*\);)0(80)100(p = str+offset;)132 L (13 static void fault386\(Ureg*, void*\);)0(81)100(offset = 0;)132 L (14)0(82)100 L (15 static Lock vctllock;)0(83)100(/* write at most max\(n,m\) bytes */)132 L (16 static Vctl *vctl[256];)0(84)100(if\(m > n\))132 L (17)0(85)100(m = n;)140 L (18 void)0(86)100(memmove\(buf, p, m\);)132 L (19 intrenable\(int irq, void \(*f\)\(Ureg*, void*\), void* a, int tbdf, char *name\))0(87)100(n -= m;)132 L (20 {)0(88)100(buf += m;)132 L (21)0(int vno;)8(89)100 L (22)0(Vctl *v, *p;)8(90)100(if\(n == 0\))132 L (23)0(91)100(return oldn;)140 L (24)0(v = xalloc\(sizeof\(Vctl\)\);)8(92)100(})124 L (25)0(v->isintr = 1;)8(93)100(})116 L (26)0(v->irq = irq;)8(94)100(})108 L (27)0(v->tbdf = tbdf;)8(95)100(return oldn - n;)108 L (28)0(v->f = f;)8(96 })100 L (29)0(v->a = a;)8(97)100 L (30)0(strncpy\(v->name, name, NAMELEN-1\);)8(98 void)100 L (31)0(v->name[NAMELEN-1] = 0;)8(99 trapenable\(int vno, void \(*f\)\(Ureg*, void*\), void* a, char *name\))100 L (32)0(100 {)100 L (33)0(ilock\(&vctllock\);)8(101 Vctl *v;)100 L (34)0(vno = arch->intrenable\(v\);)8(102)100 L (35)0(if\(vno == -1\){)8(103 if\(vno < 0 || vno >= VectorPIC\))100 L (36)0(iunlock\(&vctllock\);)16(104)100(panic\("trapenable: vno %d\\n", vno\);)116 L (37)0(print\("intrenable: couldn't enable irq %d, tbdf 0x%uX for %s\\n",)16(105 v = xalloc\(sizeof\(Vctl\)\);)100 L (38)0(irq, tbdf, v->name\);)24(106 v->tbdf = BUSUNKNOWN;)100 L (39)0(if\(p=vctl[vno]\){)16(107 v->f = f;)100 L (40)0(print\("intrenable: irq %d is already used by", irq\);)24(108 v->a = a;)100 L (41)0(for\(; p; p=p->next\))24(109 strncpy\(v->name, name, NAMELEN\);)100 L (42)0(print\(" %s", p->name\);)32(110 v->name[NAMELEN-1] = 0;)100 L (43)0(print\("\\n"\);)24(111)100 L (44)0(})16(112 lock\(&vctllock\);)100 L (45)0(xfree\(v\);)16(113 if\(vctl[vno]\))100 L (46)0(return;)16(114)100(v->next = vctl[vno]->next;)116 L (47)0(})8(115 vctl[vno] = v;)100 L (48)0(if\(vctl[vno]\){)8(116 unlock\(&vctllock\);)100 L (49)0(if\(vctl[vno]->isr != v->isr || vctl[vno]->eoi != v->eoi\))16(117 })100 L (50)0(panic\("intrenable: handler: %s %s %luX %luX %luX %luX\\n",)24(118)100 L (51)0(vctl[vno]->name, v->name,)32(119 static void)100 L (52)0(vctl[vno]->isr, v->isr, vctl[vno]->eoi, v->eoi\);)32(120 nmienable\(void\))100 L (53)0(v->next = vctl[vno];)16(121 {)100 L (54)0(})8(122 int x;)100 L (55)0(vctl[vno] = v;)8(123)100 L (56)0(iunlock\(&vctllock\);)8(124 /*)100 L (57 })0(125)100(* Hack: should be locked with NVRAM access.)109 L (58)0(126)100(*/)109 L (59 int)0(127 outb\(0x70, 0x80\);)100(/* NMI latch clear */)140 L (60 irqallocread\(char *buf, long n, vlong offset\))0(128 outb\(0x70, 0\);)100 L (61 {)0(129)100 L (62)0(int vno;)8(130 x = inb\(0x61\) & 0x07;)100(/* Enable NMI */)140 L (63)0(Vctl *v;)8(131 outb\(0x61, 0x08|x\);)100 L (64)0(long oldn;)8(132 outb\(0x61, x\);)100 L (65)0(char str[11+1+NAMELEN+1], *p;)8(133 })100 L (66)0(int m;)8(134)100 L (67)0(135 void)100 L (68)0(if\(n < 0 || offset < 0\))8(136 trapinit\(void\))100 L cleartomark showpage saveobj restore %%EndPage: 76 76 %%Page: 77 77 /saveobj save def mark 77 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 2)l ()l ()l (137 {)0(205 "29 \(reserved\)",)100 L (138 int d1, v;)0(206 "30 \(reserved\)",)100 L (139 ulong vaddr;)0(207 "31 \(reserved\)",)100 L (140 Segdesc *idt;)0(208 };)100 L (141)0(209)100 L (142 idt = \(Segdesc*\)IDTADDR;)0(210 /*)100 L (143 vaddr = \(ulong\)vectortable;)0(211 * All traps come here. It is slower to have all traps call trap\(\))100 L (144 for\(v = 0; v < 256; v++\){)0(212 * rather than directly vectoring the handler. However, this avoids a)100 L (145)0(d1 = \(vaddr & 0xFFFF0000\)|SEGP;)16(213 * lot of code duplication and possible bugs. The only exception is)100 L (146)0(switch\(v\){)16(214 * VectorSYSCALL.)100 L (147)0(215 * Trap is called with interrupts disabled via interrupt-gates.)100 L (148)0(case VectorBPT:)16(216 */)100 L (149)0(d1 |= SEGPL\(3\)|SEGIG;)24(217 void)100 L (150)0(break;)24(218 trap\(Ureg* ureg\))100 L (151)0(219 {)100 L (152)0(case VectorSYSCALL:)16(220 int i, vno, user;)100 L (153)0(d1 |= SEGPL\(3\)|SEGIG;)24(221 char buf[ERRLEN];)100 L (154)0(break;)24(222 Vctl *ctl, *v;)100 L (155)0(223 Mach *mach;)100 L (156)0(default:)16(224)100 L (157)0(d1 |= SEGPL\(0\)|SEGIG;)24(225 m->intrts = fastticks\(nil\);)100 L (158)0(break;)24(226 user = 0;)100 L (159)0(})16(227 if\(\(ureg->cs & 0xFFFF\) == UESEL\){)100 L (160)0(idt[v].d0 = \(vaddr & 0xFFFF\)|\(KESEL<<16\);)16(228)100(user = 1;)116 L (161)0(idt[v].d1 = d1;)16(229)100(up->dbgreg = ureg;)116 L (162)0(vaddr += 6;)16(230 })100 L (163 })0(231)100 L (164)0(232 vno = ureg->trap;)100 L (165 /*)0(233 if\(ctl = vctl[vno]\){)100 L (166)0(* Special traps.)9(234)100(if\(ctl->isintr\){)116 L (167)0(* Syscall\(\) is called directly without going through trap\(\).)9(235)100(m->intr++;)124 L (168)0(*/)9(236)100(if\(vno >= VectorPIC && vno != VectorSYSCALL\))124 L (169 trapenable\(VectorBPT, debugbpt, 0, "debugpt"\);)0(237)100(m->lastintr = ctl->irq;)132 L (170 trapenable\(VectorPF, fault386, 0, "fault386"\);)0(238)100(})116 L (171)0(239)100 L (172 nmienable\(\);)0(240)100(if\(ctl->isr\))116 L (173 })0(241)100(ctl->isr\(vno\);)124 L (174)0(242)100(for\(v = ctl; v != nil; v = v->next\){)116 L (175 static char* excname[32] = {)0(243)100(if\(v->f\))124 L (176 "divide error",)0(244)100(v->f\(ureg, v->a\);)132 L (177 "debug exception",)0(245)100(})116 L (178 "nonmaskable interrupt",)0(246)100(if\(ctl->eoi\))116 L (179 "breakpoint",)0(247)100(ctl->eoi\(vno\);)124 L (180 "overflow",)0(248)100 L (181 "bounds check",)0(249)100(/*)116 L (182 "invalid opcode",)0(250)100(* preemptive scheduling. to limit stack depth,)117 L (183 "coprocessor not available",)0(251)100(* make sure process has a chance to return from)117 L (184 "double fault",)0(252)100(* the current interrupt before being preempted a)117 L (185 "coprocessor segment overrun",)0(253)100(* second time.)117 L (186 "invalid TSS",)0(254)100(*/)117 L (187 "segment not present",)0(255)100(if\(ctl->isintr && ctl->irq != IrqTIMER && ctl->irq != IrqCLOCK\))116 L (188 "stack exception",)0(256)100(if\(up && up->state == Running\))116 L (189 "general protection violation",)0(257)100(if\(anyhigher\(\)\))116 L (190 "page fault",)0(258)100(if\(up->preempted == 0\))116 L (191 "15 \(reserved\)",)0(259)100(if\(!active.exiting\){)116 L (192 "coprocessor error",)0(260)100(up->preempted = 1;)124 L (193 "alignment check",)0(261)100(sched\(\);)124 L (194 "machine check",)0(262)100(splhi\(\);)124 L (195 "19 \(reserved\)",)0(263)100(up->preempted = 0;)124 L (196 "20 \(reserved\)",)0(264)100(return;)124 L (197 "21 \(reserved\)",)0(265)100(})116 L (198 "22 \(reserved\)",)0(266 })100 L (199 "23 \(reserved\)",)0(267 else if\(vno <= nelem\(excname\) && user\){)100 L (200 "24 \(reserved\)",)0(268)100(spllo\(\);)116 L (201 "25 \(reserved\)",)0(269)100(sprint\(buf, "sys: trap: %s", excname[vno]\);)116 L (202 "26 \(reserved\)",)0(270)100(postnote\(up, 1, buf, NDebug\);)116 L (203 "27 \(reserved\)",)0(271 })100 L (204 "28 \(reserved\)",)0(272 else if\(vno >= VectorPIC && vno != VectorSYSCALL\){)100 L cleartomark showpage saveobj restore %%EndPage: 77 77 %%Page: 78 78 /saveobj save def mark 78 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 3)l ()l ()l (273)0(/*)16(341 {)100 L (274)0(* An unknown interrupt.)17(342 extern ulong etext;)100 L (275)0(* Check for a default IRQ7. This can happen when)17(343 vlong mca, mct;)100 L (276)0(* the IRQ input goes away before the acknowledge.)17(344)100 L (277)0(* In this case, a 'default IRQ7' is generated, but)17(345 dumpregs2\(ureg\);)100 L (278)0(* the corresponding bit in the ISR isn't set.)17(346)100 L (279)0(* In fact, just ignore all such interrupts.)17(347 /*)100 L (280)0(*/)17(348)100(* Processor control registers.)109 L (281)0(print\("cpu%d: spurious interrupt %d, last %d",)16(349)100(* If machine check exception, time stamp counter, page size extensions)109 L (282)0(m->machno, vno, m->lastintr\);)24(350)100(* or enhanced virtual 8086 mode extensions are supported, there is a)109 L (283)0(for\(i = 0; i < 32; i++\){)16(351)100(* CR4. If there is a CR4 and machine check extensions, read the machine)109 L (284)0(if\(!\(active.machs & \(1<machno == mach->machno\))24(355)100(getcr0\(\), getcr2\(\), getcr3\(\)\);)116 L (288)0(continue;)32(356 if\(m->cpuiddx & 0x9A\){)100 L (289)0(print\(": cpu%d: last %d", mach->machno, mach->lastintr\);)24(357)100(print\(" CR4 %8.8lux", getcr4\(\)\);)116 L (290)0(})16(358)100(if\(\(m->cpuiddx & 0xA0\) == 0xA0\){)116 L (291)0(print\("\\n"\);)16(359)100(rdmsr\(0x00, &mca\);)124 L (292)0(m->spuriousintr++;)16(360)100(rdmsr\(0x01, &mct\);)124 L (293)0(return;)16(361)100(print\("\\n MCA %8.8llux MCT %8.8llux", mca, mct\);)124 L (294 })0(362)100(})116 L (295 else{)0(363 })100 L (296)0(if\(vno == VectorNMI\){)16(364 print\("\\n ur %lux up %lux\\n", ureg, up\);)100 L (297)0(nmienable\(\);)24(365 })100 L (298)0(if\(m->machno != 0\){)24(366)100 L (299)0(print\("cpu%d: PC %8.8luX\\n",)32(367)100 L (300)0(m->machno, ureg->pc\);)40(368 /*)100 L (301)0(for\(;;\);)32(369 * Fill in enough of Ureg to get a stack trace, and call a function.)100 L (302)0(})24(370 * Used by debugging interface rdb.)100 L (303)0(})16(371 */)100 L (304)0(dumpregs\(ureg\);)16(372 void)100 L (305)0(if\(vno < nelem\(excname\)\))16(373 callwithureg\(void \(*fn\)\(Ureg*\)\))100 L (306)0(panic\("%s", excname[vno]\);)24(374 {)100 L (307)0(panic\("unknown trap/intr: %d\\n", vno\);)16(375 Ureg ureg;)100 L (308 })0(376 ureg.pc = getcallerpc\(&fn\);)100 L (309)0(377 ureg.sp = \(ulong\)&fn;)100 L (310 if\(user && \(up->procctl || up->nnote\)\){)0(378 fn\(&ureg\);)100 L (311)0(splhi\(\);)16(379 })100 L (312)0(notify\(ureg\);)16(380)100 L (313 })0(381 static void)100 L (314 })0(382 _dumpstack\(Ureg *ureg\))100 L (315)0(383 {)100 L (316 /*)0(384 ulong l, v, i;)100 L (317 * dump registers)0(385 uchar *p;)100 L (318 */)0(386 extern ulong etext;)100 L (319 void)0(387)100 L (320 dumpregs2\(Ureg* ureg\))0(388 if\(up == 0\))100 L (321 {)0(389)100(return;)116 L (322 if\(up\))0(390)100 L (323)0(print\("cpu%d: registers for %s %lud\\n",)16(391 print\("ktrace /kernel/path %.8lux %.8lux\\n", ureg->pc, ureg->sp\);)100 L (324)0(m->machno, up->text, up->pid\);)24(392 i = 0;)100 L (325 else)0(393 for\(l=\(ulong\)&l; l<\(ulong\)\(up->kstack+KSTACK\); l+=4\){)100 L (326)0(print\("cpu%d: registers for kernel\\n", m->machno\);)16(394)100(v = *\(ulong*\)l;)116 L (327 print\("FLAGS=%luX TRAP=%luX ECODE=%luX PC=%luX",)0(395)100(if\(KTZERO < v && v < \(ulong\)&etext\){)116 L (328)0(ureg->flags, ureg->trap, ureg->ecode, ureg->pc\);)16(396)100(/*)124 L (329 print\(" SS=%4.4luX USP=%luX\\n", ureg->ss & 0xFFFF, ureg->usp\);)0(397)100(* Pick off general CALL \(0xE8\) and CALL indirect)125 L (330 print\(" AX %8.8luX BX %8.8luX CX %8.8luX DX %8.8luX\\n",)0(398)100(* through AX \(0xFFD0\).)125 L (331)0(ureg->ax, ureg->bx, ureg->cx, ureg->dx\);)16(399)100(*/)125 L (332 print\(" SI %8.8luX DI %8.8luX BP %8.8luX\\n",)0(400)100(p = \(uchar*\)v;)124 L (333)0(ureg->si, ureg->di, ureg->bp\);)16(401)100(if\(*\(p-5\) == 0xE8)124 L (334 print\(" CS %4.4luX DS %4.4luX ES %4.4luX FS %4.4luX GS %4.4luX\\n",)0(402)100(|| \(*\(p-2\) == 0xFF && *\(p-1\) == 0xD0\)\){)124 L (335)0(ureg->cs & 0xFFFF, ureg->ds & 0xFFFF, ureg->es & 0xFFFF,)16(403)100(print\("%.8lux=%.8lux ", l, v\);)132 L (336)0(ureg->fs & 0xFFFF, ureg->gs & 0xFFFF\);)16(404)100(i++;)132 L (337 })0(405)100(})124 L (338)0(406)100(})116 L (339 void)0(407)100(if\(i == 4\){)116 L (340 dumpregs\(Ureg* ureg\))0(408)100(i = 0;)124 L cleartomark showpage saveobj restore %%EndPage: 78 78 %%Page: 79 79 /saveobj save def mark 79 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 4)l ()l ()l (409)0(print\("\\n"\);)24(477 if\(\(ureg->cs & 0xFFFF\) != UESEL\))100 L (410)0(})16(478)100(panic\("syscall: cs 0x%4.4uX\\n", ureg->cs\);)116 L (411 })0(479)100 L (412 if\(i\))0(480 m->syscall++;)100 L (413)0(print\("\\n"\);)16(481 up->insyscall = 1;)100 L (414 })0(482 up->pc = ureg->pc;)100 L (415)0(483 up->dbgreg = ureg;)100 L (416 void)0(484)100 L (417 dumpstack\(void\))0(485 scallnr = ureg->ax;)100 L (418 {)0(486 up->scallnr = scallnr;)100 L (419 callwithureg\(_dumpstack\);)0(487 if\(scallnr == RFORK && up->fpstate == FPactive\){)100 L (420 })0(488)100(fpsave\(&up->fpsave\);)116 L (421)0(489)100(up->fpstate = FPinactive;)116 L (422 static void)0(490 })100 L (423 debugbpt\(Ureg* ureg, void*\))0(491 spllo\(\);)100 L (424 {)0(492)100 L (425 char buf[ERRLEN];)0(493 sp = ureg->usp;)100 L (426)0(494 up->nerrlab = 0;)100 L (427 if\(up == 0\))0(495 ret = -1;)100 L (428)0(panic\("kernel bpt"\);)16(496 if\(!waserror\(\)\){)100 L (429 /* restore pc to instruction that caused the trap */)0(497)100(if\(scallnr >= nsyscall\){)116 L (430 ureg->pc--;)0(498)100(pprint\("bad sys call number %d pc %lux\\n",)124 L (431 sprint\(buf, "sys: breakpoint"\);)0(499)100(scallnr, ureg->pc\);)132 L (432 postnote\(up, 1, buf, NDebug\);)0(500)100(postnote\(up, 1, "sys: bad sys call", NDebug\);)124 L (433 })0(501)100(error\(Ebadarg\);)124 L (434)0(502)100(})116 L (435 static void)0(503)100 L (436 fault386\(Ureg* ureg, void*\))0(504)100(if\(sp<\(USTKTOP-BY2PG\) || sp>\(USTKTOP-sizeof\(Sargs\)-BY2WD\)\))116 L (437 {)0(505)100(validaddr\(sp, sizeof\(Sargs\)+BY2WD, 0\);)124 L (438 ulong addr;)0(506)100 L (439 int read, user, n, insyscall;)0(507)100(up->s = *\(\(Sargs*\)\(sp+BY2WD\)\);)116 L (440 char buf[ERRLEN];)0(508)100(up->psstate = sysctab[scallnr];)116 L (441)0(509)100 L (442 addr = getcr2\(\);)0(510)100(ret = systab[scallnr]\(up->s.args\);)116 L (443 user = \(ureg->cs & 0xFFFF\) == UESEL;)0(511)100(poperror\(\);)116 L (444 if\(!user && mmukmapsync\(addr\)\))0(512 })100 L (445)0(return;)16(513 if\(up->nerrlab\){)100 L (446 read = !\(ureg->ecode & 2\);)0(514)100(print\("bad errstack [%d]: %d extra\\n", scallnr, up->nerrlab\);)116 L (447 insyscall = up->insyscall;)0(515)100(for\(i = 0; i < NERR; i++\))116 L (448 up->insyscall = 1;)0(516)100(print\("sp=%lux pc=%lux\\n",)124 L (449 n = fault\(addr, read\);)0(517)100(up->errlab[i].sp, up->errlab[i].pc\);)132 L (450 if\(n < 0\){)0(518)100(panic\("error stack"\);)116 L (451)0(if\(!user\){)16(519 })100 L (452)0(dumpregs\(ureg\);)24(520)100 L (453)0(panic\("fault: 0x%lux\\n", addr\);)24(521 up->insyscall = 0;)100 L (454)0(})16(522 up->psstate = 0;)100 L (455)0(sprint\(buf, "sys: trap: fault %s addr=0x%lux",)16(523)100 L (456)0(read? "read" : "write", addr\);)24(524 /*)100 L (457)0(postnote\(up, 1, buf, NDebug\);)16(525)100(* Put return value in frame. On the x86 the syscall is)109 L (458 })0(526)100(* just another trap and the return value from syscall is)109 L (459 up->insyscall = insyscall;)0(527)100(* ignored. On other machines the return value is put into)109 L (460 })0(528)100(* the results register by caller of syscall.)109 L (461)0(529)100(*/)109 L (462 /*)0(530 ureg->ax = ret;)100 L (463 * system calls)0(531)100 L (464 */)0(532 if\(scallnr == NOTED\))100 L (465 #include "../port/systab.h")0(533)100(noted\(ureg, *\(ulong*\)\(sp+BY2WD\)\);)116 L (466)0(534)100 L (467 /*)0(535 if\(scallnr!=RFORK && \(up->procctl || up->nnote\)\){)100 L (468 * Syscall is called directly from assembler without going through trap\(\).)0(536)100(splhi\(\);)116 L (469 */)0(537)100(notify\(ureg\);)116 L (470 void)0(538 })100 L (471 syscall\(Ureg* ureg\))0(539 })100 L (472 {)0(540)100 L (473 ulong sp;)0(541 /*)100 L (474 long ret;)0(542 * Call user, if necessary, with note.)100 L (475 int i, scallnr;)0(543 * Pass user the Ureg struct and the note on his stack.)100 L (476)0(544 */)100 L cleartomark showpage saveobj restore %%EndPage: 79 79 %%Page: 80 80 /saveobj save def mark 80 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 5)l ()l ()l (545 int)0(613 splx\(s\);)100 L (546 notify\(Ureg* ureg\))0(614 return 1;)100 L (547 {)0(615 })100 L (548 int l;)0(616)100 L (549 ulong s, sp;)0(617 /*)100 L (550 Note *n;)0(618 * Return user to state before notify\(\))100 L (551)0(619 */)100 L (552 if\(up->procctl\))0(620 void)100 L (553)0(procctl\(up\);)16(621 noted\(Ureg* ureg, ulong arg0\))100 L (554 if\(up->nnote == 0\))0(622 {)100 L (555)0(return 0;)16(623 Ureg *nureg;)100 L (556)0(624 ulong oureg, sp;)100 L (557 s = spllo\(\);)0(625)100 L (558 qlock\(&up->debug\);)0(626 qlock\(&up->debug\);)100 L (559 up->notepending = 0;)0(627 if\(arg0!=NRSTR && !up->notified\) {)100 L (560 n = &up->note[0];)0(628)100(qunlock\(&up->debug\);)116 L (561 if\(strncmp\(n->msg, "sys:", 4\) == 0\){)0(629)100(pprint\("call to noted\(\) when not notified\\n"\);)116 L (562)0(l = strlen\(n->msg\);)16(630)100(pexit\("Suicide", 0\);)116 L (563)0(if\(l > ERRLEN-15\))16(/* " pc=0x12345678\\0" */)40(631 })100 L (564)0(l = ERRLEN-15;)24(632 up->notified = 0;)100 L (565)0(sprint\(n->msg+l, " pc=0x%.8lux", ureg->pc\);)16(633)100 L (566 })0(634 nureg = up->ureg;)100(/* pointer to user returned Ureg struct */)132 L (567)0(635)100 L (568 if\(n->flag!=NUser && \(up->notified || up->notify==0\)\){)0(636 /* sanity clause */)100 L (569)0(if\(n->flag == NDebug\))16(637 oureg = \(ulong\)nureg;)100 L (570)0(pprint\("suicide: %s\\n", n->msg\);)24(638 if\(!okaddr\(\(ulong\)oureg-BY2WD, BY2WD+sizeof\(Ureg\), 0\)\){)100 L (571)0(qunlock\(&up->debug\);)16(639)100(pprint\("bad ureg in noted or call to noted when not notified\\n"\);)116 L (572)0(pexit\(n->msg, n->flag!=NDebug\);)16(640)100(qunlock\(&up->debug\);)116 L (573 })0(641)100(pexit\("Suicide", 0\);)116 L (574)0(642 })100 L (575 if\(up->notified\) {)0(643)100 L (576)0(qunlock\(&up->debug\);)16(644 /*)100 L (577)0(splhi\(\);)16(645)100(* Check the segment selectors are all valid, otherwise)109 L (578)0(return 0;)16(646)100(* a fault will be taken on attempting to return to the)109 L (579 })0(647)100(* user process.)109 L (580)0(648)100(* Take care with the comparisons as different processor)109 L (581 if\(!up->notify\){)0(649)100(* generations push segment descriptors in different ways.)109 L (582)0(qunlock\(&up->debug\);)16(650)100(*/)109 L (583)0(pexit\(n->msg, n->flag!=NDebug\);)16(651 if\(\(nureg->cs & 0xFFFF\) != UESEL || \(nureg->ss & 0xFFFF\) != UDSEL)100 L (584 })0(652)100(|| \(nureg->ds & 0xFFFF\) != UDSEL || \(nureg->es & 0xFFFF\) != UDSEL)110 L (585 sp = ureg->usp;)0(653)100(|| \(nureg->fs & 0xFFFF\) != UDSEL || \(nureg->gs & 0xFFFF\) != UDSEL\){)110 L (586 sp -= sizeof\(Ureg\);)0(654)100(pprint\("bad segment selector in noted\\n"\);)116 L (587)0(655)100(qunlock\(&up->debug\);)116 L (588 if\(!okaddr\(\(ulong\)up->notify, 1, 0\))0(656)100(pexit\("Suicide", 0\);)116 L (589 || !okaddr\(sp-ERRLEN-4*BY2WD, sizeof\(Ureg\)+ERRLEN+4*BY2WD, 1\)\){)0(657 })100 L (590)0(pprint\("suicide: bad address in notify\\n"\);)16(658)100 L (591)0(qunlock\(&up->debug\);)16(659 /* don't let user change system flags */)100 L (592)0(pexit\("Suicide", 0\);)16(660 nureg->flags = \(ureg->flags & ~0xCD5\) | \(nureg->flags & 0xCD5\);)100 L (593 })0(661)100 L (594)0(662 memmove\(ureg, nureg, sizeof\(Ureg\)\);)100 L (595 up->ureg = \(void*\)sp;)0(663)100 L (596 memmove\(\(Ureg*\)sp, ureg, sizeof\(Ureg\)\);)0(664 switch\(arg0\){)100 L (597 *\(Ureg**\)\(sp-BY2WD\) = up->ureg; /* word under Ureg is old up->ureg */)0(665 case NCONT:)100 L (598 up->ureg = \(void*\)sp;)0(666 case NRSTR:)100 L (599 sp -= BY2WD+ERRLEN;)0(667)100(if\(!okaddr\(nureg->pc, 1, 0\) || !okaddr\(nureg->usp, BY2WD, 0\)\){)116 L (600 memmove\(\(char*\)sp, up->note[0].msg, ERRLEN\);)0(668)100(qunlock\(&up->debug\);)124 L (601 sp -= 3*BY2WD;)0(669)100(pprint\("suicide: trap in noted\\n"\);)124 L (602 *\(ulong*\)\(sp+2*BY2WD\) = sp+3*BY2WD; /* arg 2 is string */)0(670)100(pexit\("Suicide", 0\);)124 L (603 *\(ulong*\)\(sp+1*BY2WD\) = \(ulong\)up->ureg;)0(/* arg 1 is ureg* */)56(671)100(})116 L (604 *\(ulong*\)\(sp+0*BY2WD\) = 0;)0(/* arg 0 is pc */)48(672)100(up->ureg = \(Ureg*\)\(*\(ulong*\)\(oureg-BY2WD\)\);)116 L (605 ureg->usp = sp;)0(673)100(qunlock\(&up->debug\);)116 L (606 ureg->pc = \(ulong\)up->notify;)0(674)100(break;)116 L (607 up->notified = 1;)0(675)100 L (608 up->nnote--;)0(676 case NSAVE:)100 L (609 memmove\(&up->lastnote, &up->note[0], sizeof\(Note\)\);)0(677)100(if\(!okaddr\(nureg->pc, BY2WD, 0\))116 L (610 memmove\(&up->note[0], &up->note[1], up->nnote*sizeof\(Note\)\);)0(678)100(|| !okaddr\(nureg->usp, BY2WD, 0\)\){)116 L (611)0(679)100(qunlock\(&up->debug\);)124 L (612 qunlock\(&up->debug\);)0(680)100(pprint\("suicide: trap in noted\\n"\);)124 L cleartomark showpage saveobj restore %%EndPage: 80 80 %%Page: 81 81 /saveobj save def mark 81 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/trap.c Page 6)l ()l ()l (681)0(pexit\("Suicide", 0\);)24(749 static void)100 L (682)0(})16(750 linkproc\(void\))100 L (683)0(qunlock\(&up->debug\);)16(751 {)100 L (684)0(sp = oureg-4*BY2WD-ERRLEN;)16(752 spllo\(\);)100 L (685)0(splhi\(\);)16(753 up->kpfun\(up->kparg\);)100 L (686)0(ureg->sp = sp;)16(754 })100 L (687)0(\(\(ulong*\)sp\)[1] = oureg;)16(/* arg 1 0\(FP\) is ureg* */)48(755)100 L (688)0(\(\(ulong*\)sp\)[0] = 0;)16(/* arg 0 is pc */)48(756 void)100 L (689)0(break;)16(757 kprocchild\(Proc* p, void \(*func\)\(void*\), void* arg\))100 L (690)0(758 {)100 L (691 default:)0(759 /*)100 L (692)0(pprint\("unknown noted arg 0x%lux\\n", arg0\);)16(760)100(* gotolabel\(\) needs a word on the stack in)109 L (693)0(up->lastnote.flag = NDebug;)16(761)100(* which to place the return PC used to jump)109 L (694)0(/* fall through */)16(762)100(* to linkproc\(\).)109 L (695)0(763)100(*/)109 L (696 case NDFLT:)0(764 p->sched.pc = \(ulong\)linkproc;)100 L (697)0(if\(up->lastnote.flag == NDebug\){)16(765 p->sched.sp = \(ulong\)p->kstack+KSTACK-BY2WD;)100 L (698)0(qunlock\(&up->debug\);)24(766)100 L (699)0(pprint\("suicide: %s\\n", up->lastnote.msg\);)24(767 p->kpfun = func;)100 L (700)0(} else)16(768 p->kparg = arg;)100 L (701)0(qunlock\(&up->debug\);)24(769 })100 L (702)0(pexit\(up->lastnote.msg, up->lastnote.flag!=NDebug\);)16(770)100 L (703 })0(771 void)100 L (704 })0(772 forkchild\(Proc *p, Ureg *ureg\))100 L (705)0(773 {)100 L (706 long)0(774 Ureg *cureg;)100 L (707 execregs\(ulong entry, ulong ssize, ulong nargs\))0(775)100 L (708 {)0(776 /*)100 L (709 ulong *sp;)0(777)100(* Add 2*BY2WD to the stack to account for)109 L (710 Ureg *ureg;)0(778)100(* - the return PC)109 L (711)0(779)100(* - trap's argument \(ur\))109 L (712 sp = \(ulong*\)\(USTKTOP - ssize\);)0(780)100(*/)109 L (713 *--sp = nargs;)0(781 p->sched.sp = \(ulong\)p->kstack+KSTACK-\(sizeof\(Ureg\)+2*BY2WD\);)100 L (714)0(782 p->sched.pc = \(ulong\)forkret;)100 L (715 ureg = up->dbgreg;)0(783)100 L (716 ureg->usp = \(ulong\)sp;)0(784 cureg = \(Ureg*\)\(p->sched.sp+2*BY2WD\);)100 L (717 ureg->pc = entry;)0(785 memmove\(cureg, ureg, sizeof\(Ureg\)\);)100 L (718 return USTKTOP-BY2WD;)0(/* address of user-level clock */)40(786 /* return value of syscall in child */)100 L (719 })0(787 cureg->ax = 0;)100 L (720)0(788)100 L (721 ulong)0(789 /* Things from bottom of syscall which were never executed */)100 L (722 userpc\(void\))0(790 p->psstate = 0;)100 L (723 {)0(791 p->insyscall = 0;)100 L (724 Ureg *ureg;)0(792 })100 L (725)0(793)100 L (726 ureg = \(Ureg*\)up->dbgreg;)0(794 /* Give enough context in the ureg to produce a kernel stack for)100 L (727 return ureg->pc;)0(795 * a sleeping process)100 L (728 })0(796 */)100 L (729)0(797 void)100 L (730 /* This routine must save the values of registers the user is not permitted)0(798 setkernur\(Ureg* ureg, Proc* p\))100 L (731 * to write from devproc and then restore the saved values before returning.)0(799 {)100 L (732 */)0(800 ureg->pc = p->sched.pc;)100 L (733 void)0(801 ureg->sp = p->sched.sp+4;)100 L (734 setregisters\(Ureg* ureg, char* pureg, char* uva, int n\))0(802 })100 L (735 {)0(803)100 L (736 ulong flags;)0(804 ulong)100 L (737 ulong cs;)0(805 dbgpc\(Proc *p\))100 L (738 ulong ss;)0(806 {)100 L (739)0(807 Ureg *ureg;)100 L (740 flags = ureg->flags;)0(808)100 L (741 cs = ureg->cs;)0(809 ureg = p->dbgreg;)100 L (742 ss = ureg->ss;)0(810 if\(ureg == 0\))100 L (743 memmove\(pureg, uva, n\);)0(811)100(return 0;)116 L (744 ureg->flags = \(ureg->flags & 0x00FF\) | \(flags & 0xFF00\);)0(812)100 L (745 ureg->cs = cs;)0(813 return ureg->pc;)100 L (746 ureg->ss = ss;)0(814 })100 L (747 })l (748)l cleartomark showpage saveobj restore %%EndPage: 81 81 %%Page: 82 82 /saveobj save def mark 82 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/vgas3.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(Pcidev *p;)108 L (2 #include "../port/lib.h")0(70)100(Physseg seg;)108 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72)100(osize = *size;)108 L (5 #include "fns.h")0(73)100(oaperture = scr->aperture;)108 L (6 #include "io.h")0(74)100(oapsize = scr->apsize;)108 L (7 #include "../port/error.h")0(75)100(wasupamem = scr->isupamem;)108 L (8)0(76)100(if\(wasupamem\))108 L (9 #define Image IMAGE)0(77)100(upafree\(oaperture, oapsize\);)116 L (10 #include )0(78)100(scr->isupamem = 0;)108 L (11 #include )0(79)100 L (12 #include )0(80)100(if\(p = pcimatch\(nil, 0x5333, 0\)\){)108 L (13 #include "screen.h")0(81)100(aperture = p->mem[0].bar & ~0x0F;)116 L (14)0(82)100(*size = p->mem[0].size;)116 L (15 static int)0(83)100(})108 L (16 s3pageset\(VGAscr* scr, int page\))0(84)100(else)108 L (17 {)0(85)100(aperture = 0;)116 L (18)0(uchar crt35, crt51;)8(86)100 L (19)0(int opage;)8(87)100(aperture = upamalloc\(aperture, *size, *align\);)108 L (20)0(88)100(if\(aperture == 0\){)108 L (21)0(crt35 = vgaxi\(Crtx, 0x35\);)8(89)100(if\(wasupamem && upamalloc\(oaperture, oapsize, 0\)\))116 L (22)0(if\(scr->gscreen->depth >= 8\){)8(90)100(scr->isupamem = 1;)124 L (23)0(/*)16(91)100(})108 L (24)0(* The S3 registers need to be unlocked for this.)17(92)100(else)108 L (25)0(* Let's hope they are already:)17(93)100(scr->isupamem = 1;)116 L (26)0(*)17(vgaxo\(Crtx, 0x38, 0x48\);)24(94)100 L (27)0(*)17(vgaxo\(Crtx, 0x39, 0xA0\);)24(95)100(if\(oaperture\))108 L (28)0(*)17(96)100(print\("warning \(BUG\): redefinition of aperture does not change s3screen segment\\n"\))116 L (29)0(* The page is 6 bits, the lower 4 bits in Crt35<3:0>,)17(97)100(memset\(&seg, 0, sizeof\(seg\)\);)108 L (30)0(* the upper 2 in Crt51<3:2>.)17(98)100(seg.attr = SG_PHYSICAL;)108 L (31)0(*/)17(99)100(seg.name = smalloc\(NAMELEN\);)108 L (32)0(vgaxo\(Crtx, 0x35, page & 0x0F\);)16(100 snprint\(seg.name, NAMELEN, "s3screen"\);)100 L (33)0(crt51 = vgaxi\(Crtx, 0x51\);)16(101 seg.pa = aperture;)100 L (34)0(vgaxo\(Crtx, 0x51, \(crt51 & ~0x0C\)|\(\(page & 0x30\)>>2\)\);)16(102 seg.size = osize;)100 L (35)0(opage = \(\(crt51 & 0x0C\)<<2\)|\(crt35 & 0x0F\);)16(103 addphysseg\(&seg\);)100 L (36)0(})8(104)100 L (37)0(else{)8(105 return aperture;)100 L (38)0(vgaxo\(Crtx, 0x35, \(page<<2\) & 0x0C\);)16(106 })100 L (39)0(opage = \(crt35>>2\) & 0x03;)16(107)100 L (40)0(})8(108 static void)100 L (41)0(109 s3vsyncactive\(void\))100 L (42)0(return opage;)8(110 {)100 L (43 })0(111 /*)100 L (44)0(112)100(* Hardware cursor information is fetched from display memory)109 L (45 static void)0(113)100(* during the horizontal blank active time. The 80x chips may hang)109 L (46 s3page\(VGAscr* scr, int page\))0(114)100(* if the cursor is turned on or off during this period.)109 L (47 {)0(115)100(*/)109 L (48)0(int id;)8(116 while\(\(vgai\(Status1\) & 0x08\) == 0\))100 L (49)0(117)100(;)116 L (50)0(id = \(vgaxi\(Crtx, 0x30\)<<8\)|vgaxi\(Crtx, 0x2E\);)8(118 })100 L (51)0(switch\(id\){)8(119)100 L (52)0(120 static void)100 L (53)0(case 0xE110:)8(/* ViRGE/GX2 */)48(121 s3disable\(VGAscr*\))100 L (54)0(break;)16(122 {)100 L (55)0(123 uchar crt45;)100 L (56)0(default:)8(124)100 L (57)0(lock\(&scr->devlock\);)16(125 /*)100 L (58)0(s3pageset\(scr, page\);)16(126)100(* Turn cursor off.)109 L (59)0(unlock\(&scr->devlock\);)16(127)100(*/)109 L (60)0(break;)16(128 crt45 = vgaxi\(Crtx, 0x45\) & 0xFE;)100 L (61)0(})8(129 s3vsyncactive\(\);)100 L (62 })0(130 vgaxo\(Crtx, 0x45, crt45\);)100 L (63)0(131 })100 L (64 static ulong)0(132)100 L (65 s3linear\(VGAscr* scr, int* size, int* align\))0(133 static void)100 L (66 {)0(134 s3enable\(VGAscr* scr\))100 L (67)0(ulong aperture, oaperture;)8(135 {)100 L (68)0(int osize, oapsize, wasupamem;)8(136 int i;)100 L cleartomark showpage saveobj restore %%EndPage: 82 82 %%Page: 83 83 /saveobj save def mark 83 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/vgas3.c Page 2)l ()l ()l (137 ulong storage;)0(205)100(* The cursor is set in Microsoft Windows format \(the ViRGE/GX2 no)109 L (138)0(206)100(* longer supports the X11 format\) which gives the following truth table:)109 L (139 s3disable\(scr\);)0(207)100(*)109(and xor colour)116 L (140)0(208)100(*)109(0 0 background colour)117 L (141 /*)0(209)100(*)109(0 1 foreground colour)117 L (142)0(* Cursor colours. Set both the CR0[EF] and the colour)9(210)100(*)109(1 0 current screen pixel)117 L (143)0(* stack in case we are using a 16-bit RAMDAC.)9(211)100(*)109(1 1 NOT current screen pixel)117 L (144)0(*/)9(212)100(* Put the cursor into the top-left of the 64x64 array.)109 L (145 vgaxo\(Crtx, 0x0E, Pwhite\);)0(213)100(*)109 L (146 vgaxo\(Crtx, 0x0F, Pblack\);)0(214)100(* The cursor pattern in memory is interleaved words of)109 L (147 vgaxi\(Crtx, 0x45\);)0(215)100(* AND and XOR patterns.)109 L (148)0(216)100(*/)109 L (149 for\(i = 0; i < 3; i++\))0(217 for\(y = 0; y < 64; y++\){)100 L (150)0(vgaxo\(Crtx, 0x4A, Pblack\);)16(218)100(for\(x = 0; x < 64/8; x += 2\){)116 L (151 vgaxi\(Crtx, 0x45\);)0(219)100(if\(x < 16/8 && y < 16\){)124 L (152 for\(i = 0; i < 3; i++\))0(220)100(*p++ = ~\(curs->clr[2*y + x]|curs->set[2*y + x]\);)132 L (153)0(vgaxo\(Crtx, 0x4B, Pwhite\);)16(221)100(*p++ = ~\(curs->clr[2*y + x+1]|curs->set[2*y + x+1]\);)132 L (154)0(222)100(*p++ = curs->set[2*y + x];)132 L (155 /*)0(223)100(*p++ = curs->set[2*y + x+1];)132 L (156)0(* Find a place for the cursor data in display memory.)9(224)100(})124 L (157)0(* Must be on a 1024-byte boundary.)9(225)100(else {)124 L (158)0(*/)9(226)100(*p++ = 0xFF;)132 L (159 storage = \(scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023\)/1024;)0(227)100(*p++ = 0xFF;)132 L (160 vgaxo\(Crtx, 0x4C, \(storage>>8\) & 0x0F\);)0(228)100(*p++ = 0x00;)132 L (161 vgaxo\(Crtx, 0x4D, storage & 0xFF\);)0(229)100(*p++ = 0x00;)132 L (162 storage *= 1024;)0(230)100(})124 L (163 scr->storage = storage;)0(231)100(})116 L (164)0(232 })100 L (165 /*)0(233)100 L (166)0(* Enable the cursor in Microsoft Windows format.)9(234 switch\(id\){)100 L (167)0(*/)9(235)100 L (168 vgaxo\(Crtx, 0x55, vgaxi\(Crtx, 0x55\) & ~0x10\);)0(236 case 0xE131:)100(/* ViRGE */)148 L (169 s3vsyncactive\(\);)0(237 case 0xE18A:)100(/* ViRGE/[DG]X */)148 L (170 vgaxo\(Crtx, 0x45, 0x01\);)0(238 case 0xE110:)100(/* ViRGE/GX2 */)148 L (171 })0(239 case 0xE13D:)100(/* ViRGE/VX */)148 L (172)0(240)100(break;)116 L (173 static void)0(241)100 L (174 s3load\(VGAscr* scr, Cursor* curs\))0(242 default:)100 L (175 {)0(243)100(s3pageset\(scr, opage\);)116 L (176 uchar *p;)0(244)100(unlock\(&scr->devlock\);)116 L (177 int id, opage, x, y;)0(245)100(break;)116 L (178)0(246 })100 L (179 /*)0(247)100 L (180)0(* Disable the cursor and)9(248 /*)100 L (181)0(* set the pointer to the two planes.)9(249)100(* Save the cursor hotpoint and enable the cursor.)109 L (182)0(*/)9(250)100(*/)109 L (183 s3disable\(scr\);)0(251 scr->offset = curs->offset;)100 L (184)0(252 s3vsyncactive\(\);)100 L (185 opage = 0;)0(253 vgaxo\(Crtx, 0x45, 0x01\);)100 L (186 p = KADDR\(scr->aperture\);)0(254 })100 L (187 id = \(vgaxi\(Crtx, 0x30\)<<8\)|vgaxi\(Crtx, 0x2E\);)0(255)100 L (188 switch\(id\){)0(256 static int)100 L (189)0(257 s3move\(VGAscr* scr, Point p\))100 L (190 case 0xE131:)0(/* ViRGE */)48(258 {)100 L (191 case 0xE18A:)0(/* ViRGE/[DG]X */)48(259 int x, xo, y, yo;)100 L (192 case 0xE110:)0(/* ViRGE/GX2 */)48(260)100 L (193 case 0xE13D:)0(/* ViRGE/VX */)48(261 /*)100 L (194)0(p += scr->storage;)16(262)100(* Mustn't position the cursor offscreen even partially,)109 L (195)0(break;)16(263)100(* or it disappears. Therefore, if x or y is -ve, adjust the)109 L (196)0(264)100(* cursor offset instead.)109 L (197 default:)0(265)100(* There seems to be a bug in that if the offset is 1, the)109 L (198)0(lock\(&scr->devlock\);)16(266)100(* cursor doesn't disappear off the left edge properly, so)109 L (199)0(opage = s3pageset\(scr, scr->storage>>16\);)16(267)100(* round it up to be even.)109 L (200)0(p += \(scr->storage & 0xFFFF\);)16(268)100(*/)109 L (201)0(break;)16(269 if\(\(x = p.x+scr->offset.x\) < 0\){)100 L (202 })0(270)100(xo = -x;)116 L (203)0(271)100(xo = \(\(xo+1\)/2\)*2;)116 L (204 /*)0(272)100(x = 0;)116 L cleartomark showpage saveobj restore %%EndPage: 83 83 %%Page: 84 84 /saveobj save def mark 84 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/vgas3.c Page 3)l ()l ()l (273 })0(341 x = 0;)100 L (274 else)0(342 while\(\(mmio[FifoStat]&mask\) != val && x++ < Maxloop\))100 L (275)0(xo = 0;)16(343)100(waitcount.linear++;)116 L (276 if\(\(y = p.y+scr->offset.y\) < 0\){)0(344 })100 L (277)0(yo = -y;)16(345)100 L (278)0(y = 0;)16(346 static void)100 L (279 })0(347 waitforfifo\(VGAscr *scr, int entries\))100 L (280 else)0(348 {)100 L (281)0(yo = 0;)16(349 ulong *mmio;)100 L (282)0(350 long x;)100 L (283 vgaxo\(Crtx, 0x46, \(x>>8\) & 0x07\);)0(351 static ulong nwaitforfifo;)100 L (284 vgaxo\(Crtx, 0x47, x & 0xFF\);)0(352)100 L (285 vgaxo\(Crtx, 0x49, y & 0xFF\);)0(353 mmio = scr->mmio;)100 L (286 vgaxo\(Crtx, 0x4E, xo\);)0(354 x = 0;)100 L (287 vgaxo\(Crtx, 0x4F, yo\);)0(355 while\(\(mmio[SubStat]&0x1F00\) < \(\(entries+2\)<<8\) && x++ < Maxloop\))100 L (288 vgaxo\(Crtx, 0x48, \(y>>8\) & 0x07\);)0(356)100(waitcount.fifo++;)116 L (289)0(357 })100 L (290 return 0;)0(358)100 L (291 })0(359 static void)100 L (292)0(360 waitforidle\(VGAscr *scr\))100 L (293 /*)0(361 {)100 L (294 * The manual gives byte offsets, but we want ulong offsets, hence /4.)0(362 ulong *mmio;)100 L (295 */)0(363 long x;)100 L (296 enum {)0(364)100 L (297 SrcBase = 0xA4D4/4,)0(365 mmio = scr->mmio;)100 L (298 DstBase = 0xA4D8/4,)0(366 x = 0;)100 L (299 Stride = 0xA4E4/4,)0(367 while\(\(mmio[SubStat]&0x3F00\) != 0x3000 && x++ < Maxloop\))100 L (300 FgrdData = 0xA4F4/4,)0(368)100(waitcount.idle++;)116 L (301 WidthHeight = 0xA504/4,)0(369 })100 L (302 SrcXY = 0xA508/4,)0(370)100 L (303 DestXY = 0xA50C/4,)0(371 static int)100 L (304 Command = 0xA500/4,)0(372 hwscroll\(VGAscr *scr, Rectangle r, Rectangle sr\))100 L (305 SubStat = 0x8504/4,)0(373 {)100 L (306 FifoStat = 0x850C/4,)0(374 enum { Bitbltop = 0xCC };)100(/* copy source */)140 L (307 };)0(375 ulong *mmio;)100 L (308)0(376 ulong cmd, stride;)100 L (309 /*)0(377 Point dp, sp;)100 L (310 * Wait for writes to VGA memory via linear aperture to flush.)0(378 int did, d;)100 L (311 */)0(379)100 L (312 enum {Maxloop = 1<<24};)0(380 d = scr->gscreen->depth;)100 L (313 struct {)0(381 did = \(d-8\)/8;)100 L (314 ulong linear;)0(382 cmd = 0x00000020|\(Bitbltop<<17\)|\(did<<2\);)100 L (315 ulong fifo;)0(383 stride = Dx\(scr->gscreen->r\)*d/8;)100 L (316 ulong idle;)0(384)100 L (317 } waitcount;)0(385 if\(r.min.x <= sr.min.x\){)100 L (318)0(386)100(cmd |= 1<<25;)116 L (319 static void)0(387)100(dp.x = r.min.x;)116 L (320 waitforlinearfifo\(VGAscr *scr\))0(388)100(sp.x = sr.min.x;)116 L (321 {)0(389 }else{)100 L (322 ulong *mmio;)0(390)100(dp.x = r.max.x-1;)116 L (323 long x;)0(391)100(sp.x = sr.max.x-1;)116 L (324 static ulong nwaitforlinearfifo;)0(392 })100 L (325 ulong mask, val;)0(393)100 L (326)0(394 if\(r.min.y <= sr.min.y\){)100 L (327 switch\(scr->id\){)0(395)100(cmd |= 1<<26;)116 L (328 default:)0(396)100(dp.y = r.min.y;)116 L (329)0(panic\("unknown scr->id in s3 waitforlinearfifo"\);)16(397)100(sp.y = sr.min.y;)116 L (330 case 0xE131: /* ViRGE */)0(398 }else{)100 L (331 case 0xE13D: /* ViRGE/VX */)0(399)100(dp.y = r.max.y-1;)116 L (332)0(mask = 0x0F<<6;)16(400)100(sp.y = sr.max.y-1;)116 L (333)0(val = 0x08<<6;)16(401 })100 L (334)0(break;)16(402)100 L (335 case 0xE110: /* ViRGE/GX2 */)0(403 mmio = scr->mmio;)100 L (336)0(mask = 0x1F<<6;)16(404 waitforlinearfifo\(scr\);)100 L (337)0(val = 0x10<<6;)16(405 waitforfifo\(scr, 7\);)100 L (338)0(break;)16(406 mmio[SrcBase] = scr->aperture;)100 L (339 })0(407 mmio[DstBase] = scr->aperture;)100 L (340 mmio = scr->mmio;)0(408 mmio[Stride] = \(stride<<16\)|stride;)100 L cleartomark showpage saveobj restore %%EndPage: 84 84 %%Page: 85 85 /saveobj save def mark 85 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/pc/vgas3.c Page 4)l ()l ()l (409 mmio[WidthHeight] = \(\(Dx\(r\)-1\)<<16\)|Dy\(r\);)0(477)100(* above.)109 L (410 mmio[SrcXY] = \(sp.x<<16\)|sp.y;)0(478)100(*/)109 L (411 mmio[DestXY] = \(dp.x<<16\)|dp.y;)0(479 switch\(id\){)100 L (412 mmio[Command] = cmd;)0(480 case 0xE131:)100(/* ViRGE */)148 L (413 waitforidle\(scr\);)0(481 case 0xE13D:)100(/* ViRGE/VX */)148 L (414 return 1;)0(482 case 0xE110:)100(/* ViRGE/GX2 */)148 L (415 })0(483)100(scr->mmio = \(ulong*\)\(scr->aperture+0x1000000\);)116 L (416)0(484)100(scr->fill = hwfill;)116 L (417 static int)0(485)100(scr->scroll = hwscroll;)116 L (418 hwfill\(VGAscr *scr, Rectangle r, ulong sval\))0(486)100(/* scr->blank = hwblank; */)116 L (419 {)0(487 })100 L (420 enum { Bitbltop = 0xCC };)0(/* copy source */)40(488 })100 L (421 ulong *mmio;)0(489)100 L (422 ulong cmd, stride;)0(490 VGAdev vgas3dev = {)100 L (423 int did, d;)0(491 "s3",)100 L (424)0(492)100 L (425 d = scr->gscreen->depth;)0(493 0,)100 L (426 did = \(d-8\)/8;)0(494 0,)100 L (427 cmd = 0x16000120|\(Bitbltop<<17\)|\(did<<2\);)0(495 s3page,)100 L (428 stride = Dx\(scr->gscreen->r\)*d/8;)0(496 s3linear,)100 L (429 mmio = scr->mmio;)0(497 s3drawinit,)100 L (430 waitforlinearfifo\(scr\);)0(498 };)100 L (431 waitforfifo\(scr, 8\);)0(499)100 L (432 mmio[SrcBase] = scr->aperture;)0(500 VGAcur vgas3cur = {)100 L (433 mmio[DstBase] = scr->aperture;)0(501 "s3hwgc",)100 L (434 mmio[DstBase] = scr->aperture;)0(502)100 L (435 mmio[Stride] = \(stride<<16\)|stride;)0(503 s3enable,)100 L (436 mmio[FgrdData] = sval;)0(504 s3disable,)100 L (437 mmio[WidthHeight] = \(\(Dx\(r\)-1\)<<16\)|Dy\(r\);)0(505 s3load,)100 L (438 mmio[DestXY] = \(r.min.x<<16\)|r.min.y;)0(506 s3move,)100 L (439 mmio[Command] = cmd;)0(507 };)100 L (440 waitforidle\(scr\);)l (441 return 1;)l (442 })l (443)l (444 enum {)l (445 CursorSyncCtl = 0x0D, /* in Seqx */)l (446 VsyncHi = 0x80,)l (447 VsyncLo = 0x40,)l (448 HsyncHi = 0x20,)l (449 HsyncLo = 0x10,)l (450 };)l (451)l (452 static void)l (453 s3blank\(int blank\))l (454 {)l (455 uchar x;)l (456)l (457 x = vgaxi\(Seqx, CursorSyncCtl\);)l (458 x &= ~0xF0;)l (459 if\(blank\))l (460)0(x |= VsyncLo | HsyncLo;)16 L (461 vgaxo\(Seqx, CursorSyncCtl, x\);)l (462 })l (463)l (464 static void)l (465 s3drawinit\(VGAscr *scr\))l (466 {)l (467 ulong id;)l (468)l (469 id = \(vgaxi\(Crtx, 0x30\)<<8\)|vgaxi\(Crtx, 0x2E\);)l (470 scr->id = id;)l (471)l (472 /*)l (473)0(* It's highly likely that other ViRGEs will work without)9 L (474)0(* change to the driver, with the exception of the size of)9 L (475)0(* the linear aperture memory write FIFO. Since we don't)9 L (476)0(* know that size, I'm not turning them on. See waitforlinearfifo)9 L cleartomark showpage saveobj restore %%EndPage: 85 85 %%Page: 86 86 /saveobj save def mark 86 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/alarm.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(break;)124 L (2 #include "../port/lib.h")0(70)100(wakeup\(p->trend\);)116 L (3 #include "mem.h")0(71)100(talarm.list = p->tlink;)116 L (4 #include "dat.h")0(72)100(p->trend = 0;)116 L (5 #include "fns.h")0(73)100(})108 L (6)0(74)100 L (7 Alarms alarms;)0(75)100(unlock\(&talarm\);)108 L (8 Rendez alarmr;)0(76 })100 L (9 Talarm talarm;)0(77)100 L (10)0(78 ulong)100 L (11 void)0(79 procalarm\(ulong time\))100 L (12 alarmkproc\(void*\))0(80 {)100 L (13 {)0(81)100(Proc **l, *f;)108 L (14)0(Proc *rp;)8(82)100(ulong when, old;)108 L (15)0(ulong now;)8(83)100 L (16)0(84)100(if\(up->alarm\))108 L (17)0(for\(;;\){)8(85)100(old = TK2MS\(up->alarm - MACHP\(0\)->ticks\);)116 L (18)0(now = MACHP\(0\)->ticks;)16(86)100(else)108 L (19)0(qlock\(&alarms\);)16(87)100(old = 0;)116 L (20)0(while\(\(rp = alarms.head\) && rp->alarm <= now\){)16(88)100(if\(time == 0\) {)108 L (21)0(if\(rp->alarm != 0L\){)24(89)100(up->alarm = 0;)116 L (22)0(if\(canqlock\(&rp->debug\)\){)32(90)100(return old;)116 L (23)0(if\(!waserror\(\)\){)40(91)100(})108 L (24)0(postnote\(rp, 0, "alarm", NUser\);)48(92)100(when = MS2TK\(time\)+MACHP\(0\)->ticks;)108 L (25)0(poperror\(\);)48(93)100 L (26)0(})40(94)100(qlock\(&alarms\);)108 L (27)0(qunlock\(&rp->debug\);)40(95)100(l = &alarms.head;)108 L (28)0(rp->alarm = 0L;)40(96)100(for\(f = *l; f; f = f->palarm\) {)108 L (29)0(}else)32(97)100(if\(up == f\){)116 L (30)0(break;)40(98)100(*l = f->palarm;)124 L (31)0(})24(99)100(break;)124 L (32)0(alarms.head = rp->palarm;)24(100)100(})116 L (33)0(})16(101)100(l = &f->palarm;)116 L (34)0(qunlock\(&alarms\);)16(102 })100 L (35)0(103)100 L (36)0(sleep\(&alarmr, return0, 0\);)16(104 up->palarm = 0;)100 L (37)0(})8(105 if\(alarms.head\) {)100 L (38 })0(106)100(l = &alarms.head;)116 L (39)0(107)100(for\(f = *l; f; f = f->palarm\) {)116 L (40 /*)0(108)100(if\(f->alarm > when\) {)124 L (41 * called every clock tick)0(109)100(up->palarm = f;)132 L (42 */)0(110)100(*l = up;)132 L (43 void)0(111)100(goto done;)132 L (44 checkalarms\(void\))0(112)100(})124 L (45 {)0(113)100(l = &f->palarm;)124 L (46)0(Proc *p;)8(114)100(})116 L (47)0(ulong now;)8(115)100(*l = up;)116 L (48)0(116 })100 L (49)0(p = alarms.head;)8(117 else)100 L (50)0(now = MACHP\(0\)->ticks;)8(118)100(alarms.head = up;)116 L (51)0(119 done:)100 L (52)0(if\(p && p->alarm <= now\))8(120 up->alarm = when;)100 L (53)0(wakeup\(&alarmr\);)16(121 qunlock\(&alarms\);)100 L (54)0(122)100 L (55)0(if\(talarm.list == 0 || !canlock\(&talarm\)\))8(123 return old;)100 L (56)0(return;)16(124 })100 L (57)l (58)0(for\(;;\) {)8 L (59)0(p = talarm.list;)16 L (60)0(if\(p == 0\))16 L (61)0(break;)24 L (62)l (63)0(if\(p->twhen == 0\) {)16 L (64)0(talarm.list = p->tlink;)24 L (65)0(p->trend = 0;)24 L (66)0(continue;)24 L (67)0(})16 L (68)0(if\(now < p->twhen\))16 L cleartomark showpage saveobj restore %%EndPage: 86 86 %%Page: 87 87 /saveobj save def mark 87 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/alloc.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(pv = p->private;)108 L (2 #include "../port/lib.h")0(70)100(va_start\(v, fmt\);)108 L (3 #include "mem.h")0(71)100(doprint\(pv->msg+strlen\(pv->msg\), pv->msg+sizeof pv->msg, fmt, v\);)108 L (4 #include "dat.h")0(72)100(va_end\(v\);)108 L (5 #include "fns.h")0(73 })100 L (6 #include "error.h")0(74)100 L (7 #include )0(75 static void)100 L (8)0(76 ppanic\(Pool *p, char *fmt, ...\))100 L (9 static void poolprint\(Pool*, char*, ...\);)0(77 {)100 L (10 static void ppanic\(Pool*, char*, ...\);)0(78)100(va_list v;)108 L (11 static void plock\(Pool*\);)0(79)100(Private *pv;)108 L (12 static void punlock\(Pool*\);)0(80)100(char msg[sizeof pv->msg];)108 L (13)0(81)100 L (14 typedef struct Private Private;)0(82)100(pv = p->private;)108 L (15 struct Private {)0(83)100(va_start\(v, fmt\);)108 L (16)0(Lock)8(lk;)24(84)100(doprint\(pv->msg+strlen\(pv->msg\), pv->msg+sizeof pv->msg, fmt, v\);)108 L (17)0(char)8(msg[256];)24(/* a rock for messages to be printed at unlock */)40(85)100(va_end\(v\);)108 L (18 };)0(86)100(memmove\(msg, pv->msg, sizeof msg\);)108 L (19)0(87)100(iunlock\(&pv->lk\);)108 L (20 static Private pmainpriv;)0(88)100(panic\("%s", msg\);)108 L (21 static Pool pmainmem = {)0(89 })100 L (22)0(.name= "Main",)8(90)100 L (23)0(.maxsize=)8(4*1024*1024,)24(91 static void)100 L (24)0(.minarena=)8(128*1024,)24(92 plock\(Pool *p\))100 L (25)0(.quantum=)8(32,)24(93 {)100 L (26)0(.alloc= xalloc,)8(94)100(Private *pv;)108 L (27)0(.merge= xmerge,)8(95)100 L (28)0(.flags= POOL_TOLERANCE,)8(96)100(pv = p->private;)108 L (29)0(97)100(ilock\(&pv->lk\);)108 L (30)0(.lock= plock,)8(98)100(pv->msg[0] = 0;)108 L (31)0(.unlock=)8(punlock,)24(99 })100 L (32)0(.print= poolprint,)8(100)100 L (33)0(.panic= ppanic,)8(101 static void)100 L (34)0(102 punlock\(Pool *p\))100 L (35)0(.private=)8(&pmainpriv,)24(103 {)100 L (36 };)0(104 Private *pv;)100 L (37)0(105 char msg[sizeof pv->msg];)100 L (38 static Private pimagpriv;)0(106)100 L (39 static Pool pimagmem = {)0(107 pv = p->private;)100 L (40)0(.name= "Image",)8(108 if\(pv->msg[0] == 0\){)100 L (41)0(.maxsize=)8(16*1024*1024,)24(109)100(iunlock\(&pv->lk\);)116 L (42)0(.minarena=)8(2*1024*1024,)24(110)100(return;)116 L (43)0(.quantum=)8(32,)24(111 })100 L (44)0(.alloc= xalloc,)8(112)100 L (45)0(.merge= xmerge,)8(113 memmove\(msg, pv->msg, sizeof msg\);)100 L (46)0(.flags= 0,)8(114 iunlock\(&pv->lk\);)100 L (47)0(115 print\("%.*s", sizeof pv->msg, msg\);)100 L (48)0(.lock= plock,)8(116 })100 L (49)0(.unlock=)8(punlock,)24(117)100 L (50)0(.print= poolprint,)8(118 void)100 L (51)0(.panic= ppanic,)8(119 poolsummary\(Pool *p\))100 L (52)0(120 {)100 L (53)0(.private=)8(&pimagpriv,)24(121 print\("%s max %lud cur %lud free %lud alloc %lud\\n", p->name,)100 L (54 };)0(122)100(p->maxsize, p->cursize, p->curfree, p->curalloc\);)116 L (55)0(123 })100 L (56 Pool* mainmem = &pmainmem;)0(124)100 L (57 Pool* imagmem = &pimagmem;)0(125 void)100 L (58)0(126 mallocsummary\(void\))100 L (59 /*)0(127 {)100 L (60 * because we can't print while we're holding the locks,)0(128 poolsummary\(mainmem\);)100 L (61 * we have the save the message and print it once we let go.)0(129 poolsummary\(imagmem\);)100 L (62 */)0(130 })100 L (63 static void)0(131)100 L (64 poolprint\(Pool *p, char *fmt, ...\))0(132 /* everything from here down should be the same in libc, libdebugmalloc, and the kernel */)100 L (65 {)0(133 /* - except the code for malloc\(\), which alternately doesn't clear or does. */)100 L (66)0(va_list v;)8(134 /* - except the code for smalloc\(\), which lives only in the kernel. */)100 L (67)0(Private *pv;)8(135)100 L (68)0(136 /*)100 L cleartomark showpage saveobj restore %%EndPage: 87 87 %%Page: 88 88 /saveobj save def mark 88 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/alloc.c Page 2)l ()l ()l (137 * Npadlong is the number of 32-bit longs to leave at the beginning of)0(205)100 L (138 * each allocated buffer for our own bookkeeping. We return to the callers)0(206 v = poolalloc\(mainmem, size+Npadlong*sizeof\(ulong\)\);)100 L (139 * a pointer that points immediately after our bookkeeping area. Incoming pointers)0(207 if\(Npadlong && v != nil\){)100 L (140 * must be decremented by that much, and outgoing pointers incremented.)0(208)100(v = \(ulong*\)v+Npadlong;)116 L (141 * The malloc tag is stored at MallocOffset from the beginning of the block,)0(209)100(setmalloctag\(v, getcallerpc\(&size\)\);)116 L (142 * and the realloc tag at ReallocOffset. The offsets are from the true beginning)0(210)100(setrealloctag\(v, 0\);)116 L (143 * of the block, not the beginning the caller sees.)0(211 })100 L (144 *)0(212 if\(clr && v != nil\))100 L (145 * The extra if\(Npadlong != 0\) in various places is a hint for the compiler to)0(213)100(memset\(v, 0, size\);)116 L (146 * compile out function calls that would otherwise be no-ops.)0(214 return v;)100 L (147 */)0(215 })100 L (148)0(216)100 L (149 /*)0(non tracing)16(217 void)100 L (150 *)0(218 free\(void *v\))100 L (151 enum {)0(219 {)100 L (152 Npadlong)0(= 0,)24(220 if\(v != nil\))100 L (153 MallocOffset = 0,)0(221)100(poolfree\(mainmem, \(ulong*\)v-Npadlong\);)116 L (154 ReallocOffset = 0,)0(222 })100 L (155 };)0(223)100 L (156 *)0(224 void*)100 L (157 */)0(225 realloc\(void *v, ulong size\))100 L (158)0(226 {)100 L (159 /* tracing */)0(227 void *nv;)100 L (160 enum {)0(228)100 L (161 Npadlong)0(= 2,)24(229 if\(v != nil\))100 L (162 MallocOffset = 0,)0(230)100(v = \(ulong*\)v-Npadlong;)116 L (163 ReallocOffset = 1)0(231 if\(Npadlong !=0 && size != 0\))100 L (164 };)0(232)100(size += Npadlong*sizeof\(ulong\);)116 L (165)0(233)100 L (166)0(234 if\(nv = poolrealloc\(mainmem, v, size\)\){)100 L (167 void*)0(235)100(nv = \(ulong*\)nv+Npadlong;)116 L (168 smalloc\(ulong size\))0(236)100(setrealloctag\(nv, getcallerpc\(&v\)\);)116 L (169 {)0(237)100(if\(v == nil\))116 L (170 void *v;)0(238)100(setmalloctag\(nv, getcallerpc\(&v\)\);)124 L (171)0(239 })100 L (172 for\(;;\) {)0(240 return nv;)100 L (173)0(v = poolalloc\(mainmem, size+Npadlong*sizeof\(ulong\)\);)16(241 })100 L (174)0(if\(v != nil\))16(242)100 L (175)0(break;)24(243 ulong)100 L (176)0(tsleep\(&up->sleep, return0, 0, 100\);)16(244 msize\(void *v\))100 L (177 })0(245 {)100 L (178 if\(Npadlong\){)0(246 return poolmsize\(mainmem, \(ulong*\)v-Npadlong\)-Npadlong*sizeof\(ulong\);)100 L (179)0(v = \(ulong*\)v+Npadlong;)16(247 })100 L (180)0(setmalloctag\(v, getcallerpc\(&size\)\);)16(248)100 L (181 })0(249 void*)100 L (182 memset\(v, 0, size\);)0(250 calloc\(ulong n, ulong szelem\))100 L (183 return v;)0(251 {)100 L (184 })0(252 void *v;)100 L (185)0(253 if\(v = mallocz\(n*szelem, 1\)\))100 L (186 void*)0(254)100(setmalloctag\(v, getcallerpc\(&n\)\);)116 L (187 malloc\(ulong size\))0(255 return v;)100 L (188 {)0(256 })100 L (189 void *v;)0(257)100 L (190)0(258 void)100 L (191 v = poolalloc\(mainmem, size+Npadlong*sizeof\(ulong\)\);)0(259 setmalloctag\(void *v, ulong pc\))100 L (192 if\(Npadlong && v != nil\) {)0(260 {)100 L (193)0(v = \(ulong*\)v+Npadlong;)16(261 ulong *u;)100 L (194)0(setmalloctag\(v, getcallerpc\(&size\)\);)16(262 USED\(v, pc\);)100 L (195)0(setrealloctag\(v, 0\);)16(263 if\(Npadlong <= MallocOffset || v == nil\))100 L (196)0(memset\(v, 0, size\);)16(264)100(return;)116 L (197 })0(265 u = v;)100 L (198 return v;)0(266 u[-Npadlong+MallocOffset] = pc;)100 L (199 })0(267 })100 L (200)0(268)100 L (201 void*)0(269 void)100 L (202 mallocz\(ulong size, int clr\))0(270 setrealloctag\(void *v, ulong pc\))100 L (203 {)0(271 {)100 L (204 void *v;)0(272 ulong *u;)100 L cleartomark showpage saveobj restore %%EndPage: 88 88 %%Page: 89 89 /saveobj save def mark 89 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/alloc.c Page 3)l ()l ()l (273 USED\(v, pc\);)l (274 if\(Npadlong <= ReallocOffset || v == nil\))l (275)0(return;)16 L (276 u = v;)l (277 u[-Npadlong+ReallocOffset] = pc;)l (278 })l (279)l (280 ulong)l (281 getmalloctag\(void *v\))l (282 {)l (283 USED\(v\);)l (284 if\(Npadlong <= MallocOffset\))l (285)0(return ~0;)16 L (286 return \(\(ulong*\)v\)[-Npadlong+MallocOffset];)l (287 })l (288)l (289 ulong)l (290 getrealloctag\(void *v\))l (291 {)l (292 USED\(v\);)l (293 if\(Npadlong <= ReallocOffset\))l (294)0(return \(\(ulong*\)v\)[-Npadlong+ReallocOffset];)16 L (295 return ~0;)l (296 })l cleartomark showpage saveobj restore %%EndPage: 89 89 %%Page: 90 90 /saveobj save def mark 90 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/allocb.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(print\("iallocb: limited %lud/%lud\\n",)116 L (2 #include "../port/lib.h")0(70)100(ialloc.bytes, conf.ialloc\);)124 L (3 #include "mem.h")0(71)100(return 0;)116 L (4 #include "dat.h")0(72)100(})108 L (5 #include "fns.h")0(73)100 L (6 #include "error.h")0(74)100(n = sizeof\(Block\) + size;)108 L (7 #include "pool.h")0(75)100(b = malloc\(n+Hdrspc\);)108 L (8)0(76)100(if\(b == 0\){)108 L (9 enum)0(77)100(print\("iallocb: no memory %lud/%lud\\n",)116 L (10 {)0(78)100(ialloc.bytes, conf.ialloc\);)124 L (11)0(Hdrspc)8(= 64,)24(/* leave room for high-level headers */)40(79)100(return nil;)116 L (12)0(Bdead)8(= 0x51494F42, /* "QIOB" */)24(80)100(})108 L (13 };)0(81)100(memset\(b, 0, sizeof\(Block\)\);)108 L (14)0(82)100 L (15 struct)0(83)100(/* align start of data portion by rounding up */)108 L (16 {)0(84)100(addr = \(ulong\)b;)108 L (17)0(Lock;)8(85)100(addr = ROUND\(addr + sizeof\(Block\), BLOCKALIGN\);)108 L (18)0(ulong bytes;)8(86)100(b->base = \(uchar*\)addr;)108 L (19 } ialloc;)0(87)100 L (20)0(88)100(/* align end of data portion by rounding down */)108 L (21 /*)0(89)100(b->lim = \(\(uchar*\)b\) + msize\(b\);)108 L (22 * allocate blocks, round the data base up to a multiple of BLOCKALIGN.)0(90)100(addr = \(ulong\)\(b->lim\);)108 L (23 */)0(91)100(addr = addr & ~\(BLOCKALIGN-1\);)108 L (24 Block*)0(92)100(b->lim = \(uchar*\)addr;)108 L (25 allocb\(int size\))0(93)100 L (26 {)0(94)100(/* leave sluff at beginning for added headers */)108 L (27)0(Block *b;)8(95)100(b->rp = b->lim - ROUND\(size, BLOCKALIGN\);)108 L (28)0(ulong addr;)8(96)100(if\(b->rp < b->base\))108 L (29)0(int n;)8(97)100(panic\("allocb"\);)116 L (30)0(98)100(b->wp = b->rp;)108 L (31)0(n = sizeof\(Block\) + size;)8(99)100 L (32)0(b = malloc\(n+Hdrspc\);)8(100 b->flag = BINTR;)100 L (33)0(if\(b == 0\))8(101)100 L (34)0(exhausted\("Blocks"\);)16(102 ilock\(&ialloc\);)100 L (35)0(memset\(b, 0, sizeof\(Block\)\);)8(103 ialloc.bytes += b->lim - b->base;)100 L (36)0(104 iunlock\(&ialloc\);)100 L (37)0(/* align start of data portion by rounding up */)8(105 setmalloctag\(b, getcallerpc\(&size\)\);)100 L (38)0(addr = \(ulong\)b;)8(106)100 L (39)0(addr = ROUND\(addr + sizeof\(Block\), BLOCKALIGN\);)8(107 return b;)100 L (40)0(b->base = \(uchar*\)addr;)8(108 })100 L (41)0(109)100 L (42)0(/* align end of data portion by rounding down */)8(110 void)100 L (43)0(b->lim = \(\(uchar*\)b\) + msize\(b\);)8(111 freeb\(Block *b\))100 L (44)0(addr = \(ulong\)\(b->lim\);)8(112 {)100 L (45)0(addr = addr & ~\(BLOCKALIGN-1\);)8(113 void *dead = \(void*\)Bdead;)100 L (46)0(b->lim = \(uchar*\)addr;)8(114)100 L (47)0(115 if\(b == nil\))100 L (48)0(/* leave sluff at beginning for added headers */)8(116)100(return;)116 L (49)0(b->rp = b->lim - ROUND\(size, BLOCKALIGN\);)8(117)100 L (50)0(if\(b->rp < b->base\))8(118 /*)100 L (51)0(panic\("allocb"\);)16(119)100(* drivers which perform non cache coherent DMA manage their own buffer)109 L (52)0(b->wp = b->rp;)8(120)100(* pool of uncached buffers and provide their own free routine.)109 L (53)0(setmalloctag\(b, getcallerpc\(&size\)\);)8(121)100(*/)109 L (54)0(122 if\(b->free\) {)100 L (55)0(return b;)8(123)100(b->free\(b\);)116 L (56 })0(124)100(return;)116 L (57)0(125 })100 L (58 /*)0(126 if\(b->flag & BINTR\) {)100 L (59 * interrupt time allocation)0(127)100(ilock\(&ialloc\);)116 L (60 */)0(128)100(ialloc.bytes -= b->lim - b->base;)116 L (61 Block*)0(129)100(iunlock\(&ialloc\);)116 L (62 iallocb\(int size\))0(130 })100 L (63 {)0(131)100 L (64)0(Block *b;)8(132 /* poison the block in case someone is still holding onto it */)100 L (65)0(ulong addr;)8(133 b->next = dead;)100 L (66)0(int n;)8(134 b->rp = dead;)100 L (67)0(135 b->wp = dead;)100 L (68)0(if\(ialloc.bytes > conf.ialloc\){)8(136 b->lim = dead;)100 L cleartomark showpage saveobj restore %%EndPage: 90 90 %%Page: 91 91 /saveobj save def mark 91 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/allocb.c Page 2)l ()l ()l (137 b->base = dead;)l (138)l (139 free\(b\);)l (140 })l (141)l (142 void)l (143 checkb\(Block *b, char *msg\))l (144 {)l (145 void *dead = \(void*\)Bdead;)l (146)l (147 if\(b == dead\))l (148)0(panic\("checkb b %s %lux", msg, b\);)16 L (149 if\(b->base == dead || b->lim == dead || b->next == dead)l (150)0(|| b->rp == dead || b->wp == dead\){)10 L (151)0(print\("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\\n",)16 L (152)0(b->base, b->lim, b->next\);)24 L (153)0(print\("checkb: rp 0x%8.8luX wp 0x%8.8luX\\n", b->rp, b->wp\);)16 L (154)0(panic\("checkb dead: %s\\n", msg\);)16 L (155 })l (156)l (157 if\(b->base > b->lim\))l (158)0(panic\("checkb 0 %s %lux %lux", msg, b->base, b->lim\);)16 L (159 if\(b->rp < b->base\))l (160)0(panic\("checkb 1 %s %lux %lux", msg, b->base, b->rp\);)16 L (161 if\(b->wp < b->base\))l (162)0(panic\("checkb 2 %s %lux %lux", msg, b->base, b->wp\);)16 L (163 if\(b->rp > b->lim\))l (164)0(panic\("checkb 3 %s %lux %lux", msg, b->rp, b->lim\);)16 L (165 if\(b->wp > b->lim\))l (166)0(panic\("checkb 4 %s %lux %lux", msg, b->wp, b->lim\);)16 L (167)l (168 })l (169)l (170 void)l (171 iallocsummary\(void\))l (172 {)l (173 print\("ialloc %lud/%lud\\n", ialloc.bytes, conf.ialloc\);)l (174 })l cleartomark showpage saveobj restore %%EndPage: 91 91 %%Page: 92 92 /saveobj save def mark 92 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/auth.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(cryptalloc.free = xalloc\(sizeof\(Crypt\)*conf.nproc\);)108 L (2 #include "../port/lib.h")0(70)100(if\(cryptalloc.free == 0\))108 L (3 #include "mem.h")0(71)100(panic\("newcrypt"\);)116 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(for\(c = cryptalloc.free; c < cryptalloc.free+conf.nproc-1; c++\))108 L (6 #include "../port/error.h")0(74)100(c->next = c+1;)116 L (7)0(75)100 L (8 typedef struct Crypt)0(Crypt;)32(76)100(palloc.cmembase = \(ulong\)cryptalloc.free;)108 L (9 struct Crypt)0(77)100(palloc.cmemtop = palloc.cmembase+\(sizeof\(Crypt\)*conf.nproc\);)108 L (10 {)0(78)100(unlock\(&cryptalloc\);)108 L (11)0(Crypt)8(*next;)24(79)100(return newcrypt\(\);)108 L (12)0(Ticket)8(t;)24(80 })100 L (13)0(Authenticator a;)8(81)100 L (14)0(char)8(tbuf[TICKETLEN];)24(/* remote ticket */)48(82 void)100 L (15 };)0(83 freecrypt\(Crypt *c\))100 L (16)0(84 {)100 L (17 typedef struct Session Session;)0(85)100(lock\(&cryptalloc\);)108 L (18 struct Session)0(86)100(c->next = cryptalloc.free;)108 L (19 {)0(87)100(cryptalloc.free = c;)108 L (20)0(Lock;)8(88)100(unlock\(&cryptalloc\);)108 L (21)0(Lock send;)8(89 })100 L (22)0(Crypt *cache;)8(/* cache of tickets */)40(90)100 L (23)0(char cchal[CHALLEN];)8(/* client challenge */)40(91 /*)100 L (24)0(char schal[CHALLEN];)8(/* server challenge */)40(92 * return the info received in the session message on this channel.)100 L (25)0(char authid[NAMELEN];)8(/* server encryption uid */)40(93 * if no session message has been exchanged, do it.)100 L (26)0(char authdom[DOMLEN];)8(/* server encryption domain */)40(94 */)100 L (27)0(ulong cid;)8(/* challenge id */)40(95 long)100 L (28)0(int valid;)8(96 sysfsession\(ulong *arg\))100 L (29 };)0(97 {)100 L (30)0(98)100(int i, n;)108 L (31 struct)0(99)100(Chan *c;)108 L (32 {)0(100 Crypt *cp;)100 L (33)0(Lock;)8(101 Session *s;)100 L (34)0(Crypt)8(*free;)24(102 Ticketreq tr;)100 L (35 } cryptalloc;)0(103 Fcall f;)100 L (36)0(104 char buf[MAXMSG];)100 L (37 char)0(eve[NAMELEN];)16(105)100 L (38 char)0(evekey[DESKEYLEN];)16(106 validaddr\(arg[1], TICKREQLEN, 1\);)100 L (39 char)0(hostdomain[DOMLEN];)16(107 c = fdtochan\(arg[0], OWRITE, 0, 1\);)100 L (40)0(108 if\(waserror\(\)\){)100 L (41 /*)0(109)100(cclose\(c\);)116 L (42 * return true if current user is eve)0(110)100(nexterror\(\);)116 L (43 */)0(111 })100 L (44 int)0(112)100 L (45 iseve\(void\))0(113 /* add a session structure to the channel if it has none */)100 L (46 {)0(114 lock\(c\);)100 L (47)0(return strcmp\(eve, up->user\) == 0;)8(115 s = c->session;)100 L (48 })0(116 if\(s == 0\){)100 L (49)0(117)100(s = malloc\(sizeof\(Session\)\);)116 L (50 /*)0(118)100(if\(s == 0\){)116 L (51 * crypt entries are allocated from a pool rather than allocated using malloc so)0(119)100(unlock\(c\);)124 L (52 * the memory can be protected from reading by devproc. The base and top of the)0(120)100(error\(Enomem\);)124 L (53 * crypt arena is stored in palloc for devproc.)0(121)100(})116 L (54 */)0(122)100(c->session = s;)116 L (55 Crypt*)0(123 })100 L (56 newcrypt\(void\))0(124 unlock\(c\);)100 L (57 {)0(125)100 L (58)0(Crypt *c;)8(126 /* back off if someone else is doing an fsession */)100 L (59)0(127 while\(!canlock\(&s->send\)\))100 L (60)0(lock\(&cryptalloc\);)8(128)100(sched\(\);)116 L (61)0(if\(cryptalloc.free\) {)8(129)100 L (62)0(c = cryptalloc.free;)16(130 if\(s->valid == 0 && \(c->flag & CMSG\) == 0\){)100 L (63)0(cryptalloc.free = c->next;)16(131)100 L (64)0(unlock\(&cryptalloc\);)16(132)100(/*)116 L (65)0(memset\(c, 0, sizeof\(Crypt\)\);)16(133)100(* Exchange a session message with the server.)117 L (66)0(return c;)16(134)100(* If an error occurs reading or writing,)117 L (67)0(})8(135)100(* assume this is a mount of a mount and turn off)117 L (68)0(136)100(* authentication.)117 L cleartomark showpage saveobj restore %%EndPage: 92 92 %%Page: 93 93 /saveobj save def mark 93 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/auth.c Page 2)l ()l ()l (137)0(*/)17(205 */)100 L (138)0(if\(!waserror\(\)\){)16(206 long)100 L (139)0(for\(i = 0; i < CHALLEN; i++\))24(207 sysfauth\(ulong *arg\))100 L (140)0(s->cchal[i] = nrand\(256\);)32(208 {)100 L (141)0(f.tag = NOTAG;)24(209 Chan *c;)100 L (142)0(f.type = Tsession;)24(210 char *ta;)100 L (143)0(memmove\(f.chal, s->cchal, CHALLEN\);)24(211 Session *s;)100 L (144)0(n = convS2M\(&f, buf\);)24(212 Crypt *cp, *ncp, **l;)100 L (145)0(if\(devtab[c->type]->write\(c, buf, n, 0\) != n\))24(213 char tbuf[2*TICKETLEN];)100 L (146)0(error\(Emountrpc\);)32(214)100 L (147)0(n = devtab[c->type]->read\(c, buf, sizeof buf, 0\);)24(215 validaddr\(arg[1], 2*TICKETLEN, 0\);)100 L (148)0(if\(n == 2 && buf[0] == 'O' && buf[1] == 'K'\))24(216 c = fdtochan\(arg[0], OWRITE, 0, 1\);)100 L (149)0(n = devtab[c->type]->read\(c, buf, sizeof buf, 0\);)32(217 s = c->session;)100 L (150)0(poperror\(\);)24(218 if\(s == 0\){)100 L (151)0(if\(convM2S\(buf, &f, n\) == 0\){)24(219)100(cclose\(c\);)116 L (152)0(unlock\(&s->send\);)32(220)100(error\("fauth must follow fsession"\);)116 L (153)0(error\(Emountrpc\);)32(221 })100 L (154)0(})24(222 cp = newcrypt\(\);)100 L (155)0(switch\(f.type\){)24(223 if\(waserror\(\)\){)100 L (156)0(case Rsession:)24(224)100(cclose\(c\);)116 L (157)0(memmove\(s->schal, f.chal, CHALLEN\);)32(225)100(freecrypt\(cp\);)116 L (158)0(memmove\(s->authid, f.authid, NAMELEN\);)32(226)100(nexterror\(\);)116 L (159)0(memmove\(s->authdom, f.authdom, DOMLEN\);)32(227 })100 L (160)0(break;)32(228)100 L (161)0(case Rerror:)24(229 /* ticket supplied, use it */)100 L (162)0(unlock\(&s->send\);)32(230 ta = \(char*\)arg[1];)100 L (163)0(error\(f.ename\);)32(231 memmove\(tbuf, ta, 2*TICKETLEN\);)100 L (164)0(default:)24(232 convM2T\(tbuf, &cp->t, evekey\);)100 L (165)0(unlock\(&s->send\);)32(233 if\(cp->t.num != AuthTc\))100 L (166)0(error\(Emountrpc\);)32(234)100(error\("bad AuthTc in ticket"\);)116 L (167)0(})24(235 if\(strncmp\(up->user, cp->t.cuid, NAMELEN\) != 0\))100 L (168)0(})16(236)100(error\("bad uid in ticket"\);)116 L (169)0(s->valid = 1;)16(237 if\(memcmp\(cp->t.chal, s->schal, CHALLEN\) != 0\))100 L (170 })0(238)100(error\("bad chal in ticket"\);)116 L (171 unlock\(&s->send\);)0(239 memmove\(cp->tbuf, tbuf+TICKETLEN, TICKETLEN\);)100 L (172)0(240)100 L (173 /*)0(241 /* string onto local list, replace old version */)100 L (174)0(* If server requires no ticket, or user is "none", or a ticket)9(242 lock\(s\);)100 L (175)0(* is already cached, zero the request type)9(243 l = &s->cache;)100 L (176)0(*/)9(244 for\(ncp = s->cache; ncp; ncp = *l\){)100 L (177 tr.type = AuthTreq;)0(245)100(if\(strcmp\(ncp->t.cuid, up->user\) == 0\){)116 L (178 if\(strcmp\(up->user, "none"\) == 0 || s->authid[0] == 0\))0(246)100(*l = ncp->next;)124 L (179)0(tr.type = 0;)16(247)100(freecrypt\(ncp\);)124 L (180 else{)0(248)100(break;)124 L (181)0(lock\(s\);)16(249)100(})116 L (182)0(for\(cp = s->cache; cp; cp = cp->next\))16(250)100(l = &ncp->next;)116 L (183)0(if\(strcmp\(cp->t.cuid, up->user\) == 0\){)24(251 })100 L (184)0(tr.type = 0;)32(252 cp->next = s->cache;)100 L (185)0(break;)32(253 s->cache = cp;)100 L (186)0(})24(254 unlock\(s\);)100 L (187)0(unlock\(s\);)16(255 cclose\(c\);)100 L (188 })0(256 poperror\(\);)100 L (189)0(257 return 0;)100 L (190 /* create ticket request */)0(258 })100 L (191 memmove\(tr.chal, s->schal, CHALLEN\);)0(259)100 L (192 memmove\(tr.authid, s->authid, NAMELEN\);)0(260 /*)100 L (193 memmove\(tr.authdom, s->authdom, DOMLEN\);)0(261 * free a session created by fsession)100 L (194 memmove\(tr.uid, up->user, NAMELEN\);)0(262 */)100 L (195 memmove\(tr.hostid, eve, NAMELEN\);)0(263 void)100 L (196 convTR2M\(&tr, \(char*\)arg[1]\);)0(264 freesession\(Session *s\))100 L (197)0(265 {)100 L (198 cclose\(c\);)0(266 Crypt *cp, *next;)100 L (199 poperror\(\);)0(267)100 L (200 return 0;)0(268 for\(cp = s->cache; cp; cp = next\) {)100 L (201 })0(269)100(next = cp->next;)116 L (202)0(270)100(freecrypt\(cp\);)116 L (203 /*)0(271 })100 L (204 * attach tickets to a session)0(272 free\(s\);)100 L cleartomark showpage saveobj restore %%EndPage: 93 93 %%Page: 94 94 /saveobj save def mark 94 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/auth.c Page 3)l ()l ()l (273 })0(341)100(break;)124 L (274)0(342 unlock\(s\);)100 L (275 /*)0(343)100 L (276 * called by mattach\(\) to fill in the Tattach message)0(344 /* we're getting around authentication */)100 L (277 */)0(345 if\(s == 0 || cp == 0 || s->authid[0] == 0 || strcmp\(up->user, "none"\) == 0\))100 L (278 ulong)0(346)100(return;)116 L (279 authrequest\(Session *s, Fcall *f\))0(347)100 L (280 {)0(348 convM2A\(f->rauth, &cp->a, cp->t.key\);)100 L (281 Crypt *cp;)0(349 if\(cp->a.num != AuthAs\){)100 L (282 ulong id, dofree;)0(350)100(print\("bad encryption type\\n"\);)116 L (283)0(351)100(error\("server lies"\);)116 L (284 /* no authentication if user is "none" or if no ticket required by remote */)0(352 })100 L (285 if\(s == 0 || s->authid[0] == 0 || strcmp\(up->user, "none"\) == 0\){)0(353 if\(memcmp\(cp->a.chal, s->cchal, sizeof\(cp->a.chal\)\)\){)100 L (286)0(memset\(f->ticket, 0, TICKETLEN\);)16(354)100(print\("bad returned challenge\\n"\);)116 L (287)0(memset\(f->auth, 0, AUTHENTLEN\);)16(355)100(error\("server lies"\);)116 L (288)0(return 0;)16(356 })100 L (289 })0(357 if\(cp->a.id != id\){)100 L (290)0(358)100(print\("bad returned id\\n"\);)116 L (291 /* look for ticket in cache */)0(359)100(error\("server lies"\);)116 L (292 dofree = 0;)0(360 })100 L (293 lock\(s\);)0(361 })100 L (294 for\(cp = s->cache; cp; cp = cp->next\))0(362)100 L (295)0(if\(strcmp\(cp->t.cuid, up->user\) == 0\))16(363 /*)100 L (296)0(break;)24(364 * called by devcons\(\) for #c/authenticate)100 L (297)0(365 *)100 L (298 id = s->cid++;)0(366 * The protocol is)100 L (299 unlock\(s\);)0(367 *)100(1\) read ticket request from #c/authenticate)116 L (300)0(368 *)100(2\) write ticket+authenticator to #c/authenticate. if it matches)116 L (301 if\(cp == 0\){)0(369 *)100(the challenge the user is changed to the suid field of the ticket)118 L (302)0(/*)16(370 *)100(3\) read authenticator \(to confirm this is the server advertised\))116 L (303)0(* create a ticket using hostkey, this solves the)17(371 */)100 L (304)0(* chicken and egg problem)17(372 long)100 L (305)0(*/)17(373 authread\(Chan *c, char *a, int n\))100 L (306)0(cp = newcrypt\(\);)16(374 {)100 L (307)0(cp->t.num = AuthTs;)16(375 Crypt *cp;)100 L (308)0(memmove\(cp->t.chal, s->schal, CHALLEN\);)16(376 int i;)100 L (309)0(memmove\(cp->t.cuid, up->user, NAMELEN\);)16(377 Ticketreq tr;)100 L (310)0(memmove\(cp->t.suid, up->user, NAMELEN\);)16(378)100 L (311)0(memmove\(cp->t.key, evekey, DESKEYLEN\);)16(379 if\(c->aux == 0\){)100 L (312)0(convT2M\(&cp->t, f->ticket, evekey\);)16(380)100(/*)116 L (313)0(dofree = 1;)16(381)100(* first read returns a ticket request)117 L (314 } else)0(382)100(*/)117 L (315)0(memmove\(f->ticket, cp->tbuf, TICKETLEN\);)16(383)100(if\(n != TICKREQLEN\))116 L (316)0(384)100(error\(Ebadarg\);)124 L (317 /* create an authenticator */)0(385)100(c->aux = newcrypt\(\);)116 L (318 memmove\(cp->a.chal, s->schal, CHALLEN\);)0(386)100(cp = c->aux;)116 L (319 cp->a.num = AuthAc;)0(387)100 L (320 cp->a.id = id;)0(388)100(memset\(&tr, 0, sizeof\(tr\)\);)116 L (321 convA2M\(&cp->a, f->auth, cp->t.key\);)0(389)100(tr.type = AuthTreq;)116 L (322 if\(dofree\))0(390)100(strcpy\(tr.hostid, eve\);)116 L (323)0(freecrypt\(cp\);)16(391)100(strcpy\(tr.authid, eve\);)116 L (324 return id;)0(392)100(strcpy\(tr.authdom, hostdomain\);)116 L (325 })0(393)100(strcpy\(tr.uid, up->user\);)116 L (326)0(394)100(for\(i = 0; i < CHALLEN; i++\))116 L (327 /*)0(395)100(tr.chal[i] = nrand\(256\);)124 L (328 * called by mattach\(\) to check the Rattach message)0(396)100(memmove\(cp->a.chal, tr.chal, CHALLEN\);)116 L (329 */)0(397)100(convTR2M\(&tr, a\);)116 L (330 void)0(398 } else {)100 L (331 authreply\(Session *s, ulong id, Fcall *f\))0(399)100(/*)116 L (332 {)0(400)100(* subsequent read returns an authenticator)117 L (333 Crypt *cp;)0(401)100(*/)117 L (334)0(402)100(if\(n < AUTHENTLEN\))116 L (335 if\(s == 0\))0(403)100(error\(Ebadarg\);)124 L (336)0(return;)16(404)100(cp = c->aux;)116 L (337)0(405)100 L (338 lock\(s\);)0(406)100(cp->a.num = AuthAs;)116 L (339 for\(cp = s->cache; cp; cp = cp->next\))0(407)100(memmove\(cp->a.chal, cp->t.chal, CHALLEN\);)116 L (340)0(if\(strcmp\(cp->t.cuid, up->user\) == 0\))16(408)100(cp->a.id = 0;)116 L cleartomark showpage saveobj restore %%EndPage: 94 94 %%Page: 95 95 /saveobj save def mark 95 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/auth.c Page 4)l ()l ()l (409)0(convA2M\(&cp->a, cp->tbuf, cp->t.key\);)16(477 }else{)100 L (410)0(memmove\(a, cp->tbuf, AUTHENTLEN\);)16(478)100(id = 0;)116 L (411)0(479)100(chal = cp->t.chal;)116 L (412)0(if\(n >= AUTHENTLEN + TICKETLEN\))16(480 })100 L (413)0(convT2M\(&cp->t, a+AUTHENTLEN, nil\);)24(481 if\(cp->a.num != AuthAs || memcmp\(chal, cp->a.chal, CHALLEN\) || cp->a.id != id\))100 L (414)0(482)100(error\(Eperm\);)116 L (415)0(freecrypt\(cp\);)16(483)100 L (416)0(c->aux = 0;)16(484 return n;)100 L (417 })0(485 })100 L (418 return n;)0(486)100 L (419 })0(487 /*)100 L (420)0(488 * reading authcheck after writing into it yields the)100 L (421 long)0(489 * unencrypted ticket)100 L (422 authwrite\(Chan *c, char *a, int n\))0(490 */)100 L (423 {)0(491 long)100 L (424 Crypt *cp;)0(492 authcheckread\(Chan *c, char *a, int n\))100 L (425)0(493 {)100 L (426 if\(n != TICKETLEN+AUTHENTLEN\))0(494 Crypt *cp;)100 L (427)0(error\(Ebadarg\);)16(495)100 L (428 if\(c->aux == 0\))0(496 cp = c->aux;)100 L (429)0(error\(Ebadarg\);)16(497 if\(cp == nil\))100 L (430 cp = c->aux;)0(498)100(error\(Ebadarg\);)116 L (431)0(499 if\(n < TICKETLEN\))100 L (432 memmove\(cp->tbuf, a, TICKETLEN\);)0(500)100(error\(Ebadarg\);)116 L (433 convM2T\(cp->tbuf, &cp->t, evekey\);)0(501 convT2M\(&cp->t, a, nil\);)100 L (434 if\(cp->t.num != AuthTs || memcmp\(cp->a.chal, cp->t.chal, CHALLEN\)\))0(502 return sizeof\(cp->t\);)100 L (435)0(error\(Eperm\);)16(503 })100 L (436)0(504)100 L (437 memmove\(cp->tbuf, a+TICKETLEN, AUTHENTLEN\);)0(505 /*)100 L (438 convM2A\(cp->tbuf, &cp->a, cp->t.key\);)0(506 * called by devcons\(\) for #c/authenticator)100 L (439 if\(cp->a.num != AuthAc || memcmp\(cp->a.chal, cp->t.chal, CHALLEN\)\))0(507 *)100 L (440)0(error\(Eperm\);)16(508 * a read after a write of a ticket \(or ticket+id\) returns an authenticator)100 L (441)0(509 * for that ticket.)100 L (442 memmove\(up->user, cp->t.suid, NAMELEN\);)0(510 */)100 L (443 return n;)0(511 long)100 L (444 })0(512 authentwrite\(Chan *c, char *a, int n\))100 L (445)0(513 {)100 L (446 /*)0(514 Crypt *cp;)100 L (447 * called by devcons\(\) for #c/authcheck)0(515)100 L (448 *)0(516 if\(n != TICKETLEN && n != TICKETLEN+4\))100 L (449 * a write of a ticket+authenticator [+challenge+id] succeeds if they match)0(517)100(error\(Ebadarg\);)116 L (450 */)0(518 if\(c->aux == 0\))100 L (451 long)0(519)100(c->aux = newcrypt\(\);)116 L (452 authcheck\(Chan *c, char *a, int n\))0(520 cp = c->aux;)100 L (453 {)0(521)100 L (454 Crypt *cp;)0(522 memmove\(cp->tbuf, a, TICKETLEN\);)100 L (455 char *chal;)0(523 convM2T\(cp->tbuf, &cp->t, evekey\);)100 L (456 ulong id;)0(524 if\(cp->t.num != AuthTc || strcmp\(cp->t.cuid, up->user\)\){)100 L (457)0(525)100(freecrypt\(cp\);)116 L (458 if\(n != TICKETLEN+AUTHENTLEN && n != TICKETLEN+AUTHENTLEN+CHALLEN+4\))0(526)100(c->aux = 0;)116 L (459)0(error\(Ebadarg\);)16(527)100(error\(Ebadarg\);)116 L (460 if\(c->aux == 0\))0(528 })100 L (461)0(c->aux = newcrypt\(\);)16(529 if\(n == TICKETLEN+4\){)100 L (462 cp = c->aux;)0(530)100(uchar *p = \(uchar *\)&a[TICKETLEN];)116 L (463)0(531)100(cp->a.id = p[0] | \(p[1]<<8\) | \(p[2]<<16\) | \(p[3]<<24\);)116 L (464 memmove\(cp->tbuf, a, TICKETLEN\);)0(532 }else)100 L (465 convM2T\(cp->tbuf, &cp->t, evekey\);)0(533)100(cp->a.id = 0;)116 L (466 if\(cp->t.num != AuthTc\))0(534)100 L (467)0(error\(Ebadarg\);)16(535 return n;)100 L (468 if\(strcmp\(up->user, cp->t.cuid\)\))0(536 })100 L (469)0(error\(cp->t.cuid\);)16(537)100 L (470)0(538 /*)100 L (471 memmove\(cp->tbuf, a+TICKETLEN, AUTHENTLEN\);)0(539 * create an authenticator and return it and optionally the)100 L (472 convM2A\(cp->tbuf, &cp->a, cp->t.key\);)0(540 * unencrypted ticket)100 L (473 if\(n == TICKETLEN+AUTHENTLEN+CHALLEN+4\){)0(541 */)100 L (474)0(uchar *p = \(uchar *\)&a[TICKETLEN+AUTHENTLEN+CHALLEN];)16(542 long)100 L (475)0(id = p[0] | \(p[1]<<8\) | \(p[2]<<16\) | \(p[3]<<24\);)16(543 authentread\(Chan *c, char *a, int n\))100 L (476)0(chal = &a[TICKETLEN+AUTHENTLEN];)16(544 {)100 L cleartomark showpage saveobj restore %%EndPage: 95 95 %%Page: 96 96 /saveobj save def mark 96 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/auth.c Page 5)l ()l ()l (545 Crypt *cp;)0(613 *)100 L (546)0(614 * writing hostowner also sets user)100 L (547 cp = c->aux;)0(615 */)100 L (548 if\(cp == 0\))0(616 long)100 L (549)0(error\("authenticator read must follow a write"\);)16(617 hostownerwrite\(char *a, int n\))100 L (550)0(618 {)100 L (551 cp->a.num = AuthAc;)0(619 char buf[NAMELEN];)100 L (552 memmove\(cp->a.chal, cp->t.chal, CHALLEN\);)0(620)100 L (553 convA2M\(&cp->a, cp->tbuf, cp->t.key\);)0(621 if\(!iseve\(\)\))100 L (554)0(622)100(error\(Eperm\);)116 L (555 if\(n >= AUTHENTLEN\))0(623 if\(n >= NAMELEN\))100 L (556)0(memmove\(a, cp->tbuf, AUTHENTLEN\);)16(624)100(error\(Ebadarg\);)116 L (557 return n;)0(625 memset\(buf, 0, NAMELEN\);)100 L (558 })0(626 strncpy\(buf, a, n\);)100 L (559)0(627 if\(buf[0] == 0\))100 L (560 void)0(628)100(error\(Ebadarg\);)116 L (561 authclose\(Chan *c\))0(629 renameuser\(eve, buf\);)100 L (562 {)0(630 memmove\(eve, buf, NAMELEN\);)100 L (563 if\(c->aux\))0(631 memmove\(up->user, buf, NAMELEN\);)100 L (564)0(freecrypt\(c->aux\);)16(632 up->basepri = PriNormal;)100 L (565 c->aux = 0;)0(633 return n;)100 L (566 })0(634 })100 L (567)0(635)100 L (568 /*)0(636 long)100 L (569 * called by devcons\(\) for key device)0(637 hostdomainwrite\(char *a, int n\))100 L (570 */)0(638 {)100 L (571 long)0(639 char buf[DOMLEN];)100 L (572 keyread\(char *a, int n, long offset\))0(640)100 L (573 {)0(641 if\(!iseve\(\)\))100 L (574 if\(n= DOMLEN\))100 L (576 if\(!cpuserver || !iseve\(\)\))0(644)100(error\(Ebadarg\);)116 L (577)0(error\(Eperm\);)16(645 memset\(buf, 0, DOMLEN\);)100 L (578 memmove\(a, evekey, DESKEYLEN\);)0(646 strncpy\(buf, a, n\);)100 L (579 return DESKEYLEN;)0(647 if\(buf[0] == 0\))100 L (580 })0(648)100(error\(Ebadarg\);)116 L (581)0(649 memmove\(hostdomain, buf, DOMLEN\);)100 L (582 long)0(650 return n;)100 L (583 keywrite\(char *a, int n\))0(651 })100 L (584 {)l (585 if\(n != DESKEYLEN\))l (586)0(error\(Ebadarg\);)16 L (587 if\(!iseve\(\)\))l (588)0(error\(Eperm\);)16 L (589 memmove\(evekey, a, DESKEYLEN\);)l (590 return DESKEYLEN;)l (591 })l (592)l (593 /*)l (594 * called by devcons\(\) for user device)l (595 *)l (596 * anyone can become none)l (597 */)l (598 long)l (599 userwrite\(char *a, int n\))l (600 {)l (601 if\(n >= NAMELEN\))l (602)0(error\(Ebadarg\);)16 L (603 if\(strcmp\(a, "none"\) != 0\))l (604)0(error\(Eperm\);)16 L (605 memset\(up->user, 0, NAMELEN\);)l (606 strcpy\(up->user, "none"\);)l (607 up->basepri = PriNormal;)l (608 return n;)l (609 })l (610)l (611 /*)l (612 * called by devcons\(\) for host owner/domain)l cleartomark showpage saveobj restore %%EndPage: 96 96 %%Page: 97 97 /saveobj save def mark 97 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/cache.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(ecache.free++;)108 L (2 #include "../port/lib.h")0(70)100(unlock\(&ecache\);)108 L (3 #include "mem.h")0(71 })100 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73 static Extent*)100 L (6 #include "../port/error.h")0(74 extentalloc\(void\))100 L (7)0(75 {)100 L (8 enum)0(76)100(Extent *e;)108 L (9 {)0(77)100(int i;)108 L (10)0(NHASH)8(= 128,)24(78)100 L (11)0(MAXCACHE)8(= 1024*1024,)24(79)100(lock\(&ecache\);)108 L (12)0(NFILE)8(= 4096,)24(80)100(if\(ecache.head == nil\){)108 L (13)0(NEXTENT)8(= 200,)24(/* extent allocation size */)40(81)100(e = xalloc\(NEXTENT*sizeof\(Extent\)\);)116 L (14 };)0(82)100(if\(e == nil\){)116 L (15)0(83)100(unlock\(&ecache\);)124 L (16 typedef struct Extent Extent;)0(84)100(return nil;)124 L (17 struct Extent)0(85)100(})116 L (18 {)0(86)100(for\(i = 0; i < NEXTENT; i++\){)116 L (19)0(int bid;)8(87)100(e->next = ecache.head;)124 L (20)0(ulong start;)8(88)100(ecache.head = e;)124 L (21)0(int len;)8(89)100(e++;)124 L (22)0(Page *cache;)8(90)100(})116 L (23)0(Extent *next;)8(91)100(ecache.free += NEXTENT;)116 L (24 };)0(92)100(ecache.total += NEXTENT;)116 L (25)0(93)100(})108 L (26 typedef struct Mntcache Mntcache;)0(94)100 L (27 struct Mntcache)0(95)100(e = ecache.head;)108 L (28 {)0(96)100(ecache.head = e->next;)108 L (29)0(Qid;)8(97)100(memset\(e, 0, sizeof\(Extent\)\);)108 L (30)0(int dev;)8(98)100(ecache.free--;)108 L (31)0(int type;)8(99)100(unlock\(&ecache\);)108 L (32)0(QLock;)8(100)100 L (33)0(Extent *list;)8(101 return e;)100 L (34)0(Mntcache *hash;)8(102 })100 L (35)0(Mntcache *prev;)8(103)100 L (36)0(Mntcache *next;)8(104 void)100 L (37 };)0(105 cinit\(void\))100 L (38)0(106 {)100 L (39 typedef struct Cache Cache;)0(107 int i;)100 L (40 struct Cache)0(108 Mntcache *m;)100 L (41 {)0(109)100 L (42)0(Lock;)8(110 cache.head = xalloc\(sizeof\(Mntcache\)*NFILE\);)100 L (43)0(int)8(pgno;)24(111 m = cache.head;)100 L (44)0(Mntcache)8(*head;)24(112)100 L (45)0(Mntcache)8(*tail;)24(113 if\(conf.npage*BY2PG > 200*MB\))100 L (46)0(Mntcache)8(*hash[NHASH];)24(114)100(maxcache = 10*MAXCACHE;)116 L (47 };)0(115)100 L (48)0(116 for\(i = 0; i < NFILE-1; i++\) {)100 L (49 typedef struct Ecache Ecache;)0(117)100(m->next = m+1;)116 L (50 struct Ecache)0(118)100(m->prev = m-1;)116 L (51 {)0(119)100(m++;)116 L (52)0(Lock;)8(120 })100 L (53)0(int total;)8(121)100 L (54)0(int free;)8(122 cache.tail = m;)100 L (55)0(Extent* head;)8(123 cache.tail->next = 0;)100 L (56 };)0(124 cache.head->prev = 0;)100 L (57)0(125)100 L (58 static Image fscache;)0(126 fscache.notext = 1;)100 L (59 static Cache cache;)0(127 })100 L (60 static Ecache ecache;)0(128)100 L (61 static int maxcache = MAXCACHE;)0(129 void)100 L (62)0(130 cprint\(Chan *c, Mntcache *m, char *s\))100 L (63 static void)0(131 {)100 L (64 extentfree\(Extent* e\))0(132 ulong o;)100 L (65 {)0(133 int nb, ct;)100 L (66)0(lock\(&ecache\);)8(134 Extent *e;)100 L (67)0(e->next = ecache.head;)8(135)100 L (68)0(ecache.head = e;)8(136 nb = 0;)100 L cleartomark showpage saveobj restore %%EndPage: 97 97 %%Page: 98 98 /saveobj save def mark 98 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/cache.c Page 2)l ()l ()l (137 ct = 1;)0(205)100(m->next = 0;)116 L (138 o = 0;)0(206 })100 L (139 if\(m->list\))0(207 })100 L (140)0(o = m->list->start;)16(208)100 L (141 for\(e = m->list; e; e = e->next\) {)0(209 void)100 L (142)0(nb += e->len;)16(210 copen\(Chan *c\))100 L (143)0(if\(o != e->start\))16(211 {)100 L (144)0(ct = 0;)24(212 int h;)100 L (145)0(o = e->start+e->len;)16(213 Extent *e, *next;)100 L (146 })0(214 Mntcache *m, *f, **l;)100 L (147 pprint\("%s: 0x%lux.0x%lux %d %d %s \(%d %c\)\\n",)0(215)100 L (148 s, m->path, m->vers, m->type, m->dev, c->name, nb, ct ? 'C' : 'N'\);)0(216 if\(c->qid.path&CHDIR\))100 L (149)0(217)100(return;)116 L (150 for\(e = m->list; e; e = e->next\) {)0(218)100 L (151)0(pprint\("\\t%4d %5d %4d %lux\\n",)16(219 h = c->qid.path%NHASH;)100 L (152)0(e->bid, e->start, e->len, e->cache\);)24(220 lock\(&cache\);)100 L (153 })0(221 for\(m = cache.hash[h]; m; m = m->hash\) {)100 L (154 })0(222)100(if\(m->path == c->qid.path\))116 L (155)0(223)100(if\(m->dev == c->dev && m->type == c->type\) {)116 L (156 Page*)0(224)100(c->mcp = m;)124 L (157 cpage\(Extent *e\))0(225)100(ctail\(m\);)124 L (158 {)0(226)100(unlock\(&cache\);)124 L (159 /* Easy consistency check */)0(227)100 L (160 if\(e->cache->daddr != e->bid\))0(228)100(/* File was updated, invalidate cache */)124 L (161)0(return 0;)16(229)100(if\(m->vers != c->qid.vers\) {)124 L (162)0(230)100(m->vers = c->qid.vers;)132 L (163 return lookpage\(&fscache, e->bid\);)0(231)100(qlock\(m\);)132 L (164 })0(232)100(cnodata\(m\);)132 L (165)0(233)100(qunlock\(m\);)132 L (166 void)0(234)100(})124 L (167 cnodata\(Mntcache *m\))0(235)100(return;)124 L (168 {)0(236)100(})116 L (169 Extent *e, *n;)0(237 })100 L (170)0(238)100 L (171 /*)0(239 /* LRU the cache headers */)100 L (172)0(* Invalidate all extent data)9(240 m = cache.head;)100 L (173)0(* Image lru will waste the pages)9(241 l = &cache.hash[m->path%NHASH];)100 L (174)0(*/)9(242 for\(f = *l; f; f = f->hash\) {)100 L (175 for\(e = m->list; e; e = n\) {)0(243)100(if\(f == m\) {)116 L (176)0(n = e->next;)16(244)100(*l = m->hash;)124 L (177)0(extentfree\(e\);)16(245)100(break;)124 L (178 })0(246)100(})116 L (179 m->list = 0;)0(247)100(l = &f->hash;)116 L (180 })0(248 })100 L (181)0(249)100 L (182 void)0(250 m->Qid = c->qid;)100 L (183 ctail\(Mntcache *m\))0(251 m->dev = c->dev;)100 L (184 {)0(252 m->type = c->type;)100 L (185 /* Unlink and send to the tail */)0(253)100 L (186 if\(m->prev\))0(254 l = &cache.hash[h];)100 L (187)0(m->prev->next = m->next;)16(255 m->hash = *l;)100 L (188 else)0(256 *l = m;)100 L (189)0(cache.head = m->next;)16(257 ctail\(m\);)100 L (190 if\(m->next\))0(258)100 L (191)0(m->next->prev = m->prev;)16(259 qlock\(m\);)100 L (192 else)0(260 c->mcp = m;)100 L (193)0(cache.tail = m->prev;)16(261 e = m->list;)100 L (194)0(262 m->list = 0;)100 L (195 if\(cache.tail\) {)0(263 unlock\(&cache\);)100 L (196)0(m->prev = cache.tail;)16(264)100 L (197)0(cache.tail->next = m;)16(265 while\(e\) {)100 L (198)0(m->next = 0;)16(266)100(next = e->next;)116 L (199)0(cache.tail = m;)16(267)100(extentfree\(e\);)116 L (200 })0(268)100(e = next;)116 L (201 else {)0(269 })100 L (202)0(cache.head = m;)16(270 qunlock\(m\);)100 L (203)0(cache.tail = m;)16(271 })100 L (204)0(m->prev = 0;)16(272)100 L cleartomark showpage saveobj restore %%EndPage: 98 98 %%Page: 99 99 /saveobj save def mark 99 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/cache.c Page 3)l ()l ()l (273 static int)0(341)100(putpage\(p\);)124 L (274 cdev\(Mntcache *m, Chan *c\))0(342)100(qunlock\(m\);)124 L (275 {)0(343)100(nexterror\(\);)124 L (276 if\(m->path != c->qid.path\))0(344)100(})116 L (277)0(return 0;)16(345)100 L (278 if\(m->dev != c->dev\))0(346)100(memmove\(buf, \(uchar*\)VA\(k\) + o, l\);)116 L (279)0(return 0;)16(347)100 L (280 if\(m->type != c->type\))0(348)100(poperror\(\);)116 L (281)0(return 0;)16(349)100(kunmap\(k\);)116 L (282 if\(m->vers != c->qid.vers\))0(350)100 L (283)0(return 0;)16(351)100(putpage\(p\);)116 L (284 return 1;)0(352)100 L (285 })0(353)100(buf += l;)116 L (286)0(354)100(len -= l;)116 L (287 int)0(355)100(offset += l;)116 L (288 cread\(Chan *c, uchar *buf, int len, vlong off\))0(356)100(total += l;)116 L (289 {)0(357)100(t = &e->next;)116 L (290 KMap *k;)0(358)100(e = e->next;)116 L (291 Page *p;)0(359)100(if\(e == 0 || e->start != offset\))116 L (292 Mntcache *m;)0(360)100(break;)124 L (293 Extent *e, **t;)0(361 })100 L (294 int o, l, total;)0(362)100 L (295 ulong offset;)0(363 qunlock\(m\);)100 L (296)0(364 return total;)100 L (297 if\(off+len > maxcache\))0(365 })100 L (298)0(return 0;)16(366)100 L (299)0(367 Extent*)100 L (300 m = c->mcp;)0(368 cchain\(uchar *buf, ulong offset, int len, Extent **tail\))100 L (301 if\(m == 0\))0(369 {)100 L (302)0(return 0;)16(370 int l;)100 L (303)0(371 Page *p;)100 L (304 qlock\(m\);)0(372 KMap *k;)100 L (305 if\(cdev\(m, c\) == 0\) {)0(373 Extent *e, *start, **t;)100 L (306)0(qunlock\(m\);)16(374)100 L (307)0(return 0;)16(375 start = 0;)100 L (308 })0(376 *tail = 0;)100 L (309)0(377 t = &start;)100 L (310 offset = off;)0(378 while\(len\) {)100 L (311 t = &m->list;)0(379)100(e = extentalloc\(\);)116 L (312 for\(e = *t; e; e = e->next\) {)0(380)100(if\(e == 0\))116 L (313)0(if\(offset >= e->start && offset < e->start+e->len\))16(381)100(break;)124 L (314)0(break;)24(382)100 L (315)0(t = &e->next;)16(383)100(p = auxpage\(\);)116 L (316 })0(384)100(if\(p == 0\) {)116 L (317)0(385)100(extentfree\(e\);)124 L (318 if\(e == 0\) {)0(386)100(break;)124 L (319)0(qunlock\(m\);)16(387)100(})116 L (320)0(return 0;)16(388)100(l = len;)116 L (321 })0(389)100(if\(l > BY2PG\))116 L (322)0(390)100(l = BY2PG;)124 L (323 total = 0;)0(391)100 L (324 while\(len\) {)0(392)100(e->cache = p;)116 L (325)0(p = cpage\(e\);)16(393)100(e->start = offset;)116 L (326)0(if\(p == 0\) {)16(394)100(e->len = l;)116 L (327)0(*t = e->next;)24(395)100 L (328)0(extentfree\(e\);)24(396)100(lock\(&cache\);)116 L (329)0(qunlock\(m\);)24(397)100(e->bid = cache.pgno;)116 L (330)0(return total;)24(398)100(cache.pgno += BY2PG;)116 L (331)0(})16(399)100(/* wrap the counter; low bits are unused by pghash but checked by lookpage */)116 L (332)0(400)100(if\(\(cache.pgno & ~\(BY2PG-1\)\) == 0\){)116 L (333)0(o = offset - e->start;)16(401)100(if\(cache.pgno == BY2PG-1\){)124 L (334)0(l = len;)16(402)100(print\("cache wrapped\\n"\);)132 L (335)0(if\(l > e->len-o\))16(403)100(cache.pgno = 0;)132 L (336)0(l = e->len-o;)24(404)100(}else)124 L (337)0(405)100(cache.pgno++;)132 L (338)0(k = kmap\(p\);)16(406)100(})116 L (339)0(if\(waserror\(\)\) {)16(407)100(unlock\(&cache\);)116 L (340)0(kunmap\(k\);)24(408)100 L cleartomark showpage saveobj restore %%EndPage: 99 99 %%Page: 100 100 /saveobj save def mark 100 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/cache.c Page 4)l ()l ()l (409)0(p->daddr = e->bid;)16(477)100(return;)116 L (410)0(k = kmap\(p\);)16(478 })100 L (411)0(if\(waserror\(\)\) {)16(/* buf may be virtual */)48(479)100 L (412)0(kunmap\(k\);)24(480 /*)100 L (413)0(nexterror\(\);)24(481)100(* Find the insertion point)109 L (414)0(})16(482)100(*/)109 L (415)0(memmove\(\(void*\)VA\(k\), buf, l\);)16(483 offset = off;)100 L (416)0(poperror\(\);)16(484 p = 0;)100 L (417)0(kunmap\(k\);)16(485 for\(f = m->list; f; f = f->next\) {)100 L (418)0(486)100(if\(f->start > offset\))116 L (419)0(cachepage\(p, &fscache\);)16(487)100(break;)124 L (420)0(putpage\(p\);)16(488)100(p = f;)116 L (421)0(489 })100 L (422)0(buf += l;)16(490)100 L (423)0(offset += l;)16(491 /* trim if there is a successor */)100 L (424)0(len -= l;)16(492 eblock = offset+len;)100 L (425)0(493 if\(f != 0 && eblock > f->start\) {)100 L (426)0(*t = e;)16(494)100(len -= \(eblock - f->start\);)116 L (427)0(*tail = e;)16(495)100(if\(len <= 0\) {)116 L (428)0(t = &e->next;)16(496)100(qunlock\(m\);)124 L (429 })0(497)100(return;)124 L (430)0(498)100(})116 L (431 return start;)0(499 })100 L (432 })0(500)100 L (433)0(501 if\(p == 0\) {)100(/* at the head */)132 L (434 int)0(502)100(e = cchain\(buf, offset, len, &tail\);)116 L (435 cpgmove\(Extent *e, uchar *buf, int boff, int len\))0(503)100(if\(e != 0\) {)116 L (436 {)0(504)100(m->list = e;)124 L (437 Page *p;)0(505)100(tail->next = f;)124 L (438 KMap *k;)0(506)100(})116 L (439)0(507)100(qunlock\(m\);)116 L (440 p = cpage\(e\);)0(508)100(return;)116 L (441 if\(p == 0\))0(509 })100 L (442)0(return 0;)16(510)100 L (443)0(511 /* trim to the predecessor */)100 L (444 k = kmap\(p\);)0(512 ee = p->start+p->len;)100 L (445 if\(waserror\(\)\) {)0(/* Since buf may be virtual */)40(513 if\(offset < ee\) {)100 L (446)0(kunmap\(k\);)16(514)100(o = ee - offset;)116 L (447)0(nexterror\(\);)16(515)100(len -= o;)116 L (448 })0(516)100(if\(len <= 0\) {)116 L (449)0(517)100(qunlock\(m\);)124 L (450 memmove\(\(uchar*\)VA\(k\)+boff, buf, len\);)0(518)100(return;)124 L (451)0(519)100(})116 L (452 poperror\(\);)0(520)100(buf += o;)116 L (453 kunmap\(k\);)0(521)100(offset += o;)116 L (454 putpage\(p\);)0(522 })100 L (455)0(523)100 L (456 return 1;)0(524 /* try and pack data into the predecessor */)100 L (457 })0(525 if\(offset == ee && p->len < BY2PG\) {)100 L (458)0(526)100(o = len;)116 L (459 void)0(527)100(if\(o > BY2PG - p->len\))116 L (460 cupdate\(Chan *c, uchar *buf, int len, vlong off\))0(528)100(o = BY2PG - p->len;)124 L (461 {)0(529)100(if\(cpgmove\(p, buf, p->len, o\)\) {)116 L (462 Mntcache *m;)0(530)100(p->len += o;)124 L (463 Extent *tail;)0(531)100(buf += o;)124 L (464 Extent *e, *f, *p;)0(532)100(len -= o;)124 L (465 int o, ee, eblock;)0(533)100(offset += o;)124 L (466 ulong offset;)0(534)100(if\(len <= 0\) {)124 L (467)0(535 if \(f && p->start + p->len > f->start\) print\("CACHE: p->start=%uld p->len=%d f->start=%uld\\n")100 L (468 if\(off > maxcache || len == 0\))0(536 art, p->len, f->start\);)100 L (469)0(return;)16(537)100(qunlock\(m\);)132 L (470)0(538)100(return;)132 L (471 m = c->mcp;)0(539)100(})124 L (472 if\(m == 0\))0(540)100(})116 L (473)0(return;)16(541 })100 L (474 qlock\(m\);)0(542)100 L (475 if\(cdev\(m, c\) == 0\) {)0(543 e = cchain\(buf, offset, len, &tail\);)100 L (476)0(qunlock\(m\);)16(544 if\(e != 0\) {)100 L cleartomark showpage saveobj restore %%EndPage: 100 100 %%Page: 101 101 /saveobj save def mark 101 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/cache.c Page 5)l ()l ()l (545)0(p->next = e;)16(613)100(tail->next = f;)116 L (546)0(tail->next = f;)16(614)100(f = e;)116 L (547 })0(615 })100 L (548 qunlock\(m\);)0(616)100 L (549 })0(617 if\(p == 0\))100 L (550)0(618)100(m->list = f;)116 L (551 void)0(619 else)100 L (552 cwrite\(Chan* c, uchar *buf, int len, vlong off\))0(620)100(p->next = f;)116 L (553 {)0(621 qunlock\(m\);)100 L (554 int o, eo;)0(622 })100 L (555 Mntcache *m;)l (556 ulong eblock, ee;)l (557 Extent *p, *f, *e, *tail;)l (558 ulong offset;)l (559)l (560 if\(off > maxcache || len == 0\))l (561)0(return;)16 L (562)l (563 m = c->mcp;)l (564 if\(m == 0\))l (565)0(return;)16 L (566)l (567 qlock\(m\);)l (568 if\(cdev\(m, c\) == 0\) {)l (569)0(qunlock\(m\);)16 L (570)0(return;)16 L (571 })l (572)l (573 offset = off;)l (574 m->vers++;)l (575 c->qid.vers++;)l (576)l (577 p = 0;)l (578 for\(f = m->list; f; f = f->next\) {)l (579)0(if\(f->start >= offset\))16 L (580)0(break;)24 L (581)0(p = f;)16 L (582 })l (583)l (584 if\(p != 0\) {)l (585)0(ee = p->start+p->len;)16 L (586)0(eo = offset - p->start;)16 L (587)0(/* pack in predecessor if there is space */)16 L (588)0(if\(offset <= ee && eo < BY2PG\) {)16 L (589)0(o = len;)24 L (590)0(if\(o > BY2PG - eo\))24 L (591)0(o = BY2PG - eo;)32 L (592)0(if\(cpgmove\(p, buf, eo, o\)\) {)24 L (593)0(if\(eo+o > p->len\))32 L (594)0(p->len = eo+o;)40 L (595)0(buf += o;)32 L (596)0(len -= o;)32 L (597)0(offset += o;)32 L (598)0(})24 L (599)0(})16 L (600 })l (601)l (602 /* free the overlap -- it's a rare case */)l (603 eblock = offset+len;)l (604 while\(f && f->start < eblock\) {)l (605)0(e = f->next;)16 L (606)0(extentfree\(f\);)16 L (607)0(f = e;)16 L (608 })l (609)l (610 /* link the block \(if any\) into the middle */)l (611 e = cchain\(buf, offset, len, &tail\);)l (612 if\(e != 0\) {)l cleartomark showpage saveobj restore %%EndPage: 101 101 %%Page: 102 102 /saveobj save def mark 102 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 1)l ()l ()l (1 #include "u.h")0(69 {)100 L (2 #include "../port/lib.h")0(70)100(Chan *c;)108 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72)100(lock\(&chanalloc\);)108 L (5 #include "fns.h")0(73)100(c = chanalloc.free;)108 L (6 #include "../port/error.h")0(74)100(if\(c != 0\))108 L (7)0(75)100(chanalloc.free = c->next;)116 L (8 enum)0(76)100(unlock\(&chanalloc\);)108 L (9 {)0(77)100 L (10)0(CNAMESLOP)8(= 20)24(78)100(if\(c == 0\) {)108 L (11 };)0(79)100(c = smalloc\(sizeof\(Chan\)\);)116 L (12)0(80)100(lock\(&chanalloc\);)116 L (13 struct)0(81)100(c->fid = ++chanalloc.fid;)116 L (14 {)0(82)100(c->link = chanalloc.list;)116 L (15)0(Lock;)8(83)100(chanalloc.list = c;)116 L (16)0(int fid;)8(84)100(unlock\(&chanalloc\);)116 L (17)0(Chan *free;)8(85)100(})108 L (18)0(Chan *list;)8(86)100 L (19 }chanalloc;)0(87)100(/* if you get an error before associating with a dev,)108 L (20)0(88)100(close calls rootclose, a nop */)111 L (21 #define SEP\(c\) \(\(c\) == 0 || \(c\) == '/'\))0(89)100(c->type = 0;)108 L (22 void cleancname\(Cname*\);)0(90)100(c->flag = 0;)108 L (23)0(91)100(c->ref = 1;)108 L (24 int)0(92)100(c->dev = 0;)108 L (25 incref\(Ref *r\))0(93)100(c->offset = 0;)108 L (26 {)0(94)100(c->mh = 0;)108 L (27)0(int x;)8(95)100(c->xmh = 0;)108 L (28)0(96)100(c->uri = 0;)108 L (29)0(lock\(r\);)8(97)100(c->aux = 0;)108 L (30)0(x = ++r->ref;)8(98)100(c->mchan = 0;)108 L (31)0(unlock\(r\);)8(99)100(c->mcp = 0;)108 L (32)0(return x;)8(100 c->mqid = \(Qid\){0, 0};)100 L (33 })0(101 c->name = 0;)100 L (34)0(102 return c;)100 L (35 int)0(103 })100 L (36 decref\(Ref *r\))0(104)100 L (37 {)0(105 static Ref ncname;)100 L (38)0(int x;)8(106)100 L (39)0(107 Cname*)100 L (40)0(lock\(r\);)8(108 newcname\(char *s\))100 L (41)0(x = --r->ref;)8(109 {)100 L (42)0(unlock\(r\);)8(110 Cname *n;)100 L (43)0(if\(x < 0\))8(111 int i;)100 L (44)0(panic\("decref"\);)16(112)100 L (45)0(113 n = smalloc\(sizeof\(Cname\)\);)100 L (46)0(return x;)8(114 i = strlen\(s\);)100 L (47 })0(115 n->len = i;)100 L (48)0(116 n->alen = i+CNAMESLOP;)100 L (49 void)0(117 n->s = smalloc\(n->alen\);)100 L (50 chandevreset\(void\))0(118 memmove\(n->s, s, i+1\);)100 L (51 {)0(119 n->ref = 1;)100 L (52)0(int i;)8(120 incref\(&ncname\);)100 L (53)0(121 return n;)100 L (54)0(for\(i=0; devtab[i] != nil; i++\))8(122 })100 L (55)0(devtab[i]->reset\(\);)16(123)100 L (56 })0(124 void)100 L (57)0(125 cnameclose\(Cname *n\))100 L (58 void)0(126 {)100 L (59 chandevinit\(void\))0(127 if\(n == 0\))100 L (60 {)0(128)100(return;)116 L (61)0(int i;)8(129 if\(decref\(n\)\))100 L (62)0(130)100(return;)116 L (63)0(for\(i=0; devtab[i] != nil; i++\))8(131 decref\(&ncname\);)100 L (64)0(devtab[i]->init\(\);)16(132 free\(n->s\);)100 L (65 })0(133 free\(n\);)100 L (66)0(134 })100 L (67 Chan*)0(135)100 L (68 newchan\(void\))0(136 Cname*)100 L cleartomark showpage saveobj restore %%EndPage: 102 102 %%Page: 103 103 /saveobj save def mark 103 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 2)l ()l ()l (137 addelem\(Cname *n, char *s\))0(205 int)100 L (138 {)0(206 eqqid\(Qid a, Qid b\))100 L (139 int i, a;)0(207 {)100 L (140 char *t;)0(208 return a.path==b.path && a.vers==b.vers;)100 L (141 Cname *new;)0(209 })100 L (142)0(210)100 L (143 if\(n->ref > 1\){)0(211 int)100 L (144)0(/* copy on write */)16(212 eqchan\(Chan *a, Chan *b, int pathonly\))100 L (145)0(new = newcname\(n->s\);)16(213 {)100 L (146)0(cnameclose\(n\);)16(214 if\(a->qid.path != b->qid.path\))100 L (147)0(n = new;)16(215)100(return 0;)116 L (148 })0(216 if\(!pathonly && a->qid.vers!=b->qid.vers\))100 L (149)0(217)100(return 0;)116 L (150 i = strlen\(s\);)0(218 if\(a->type != b->type\))100 L (151 if\(n->len+1+i+1 > n->alen\){)0(219)100(return 0;)116 L (152)0(a = n->len+1+i+1 + CNAMESLOP;)16(220 if\(a->dev != b->dev\))100 L (153)0(t = smalloc\(a\);)16(221)100(return 0;)116 L (154)0(memmove\(t, n->s, n->len+1\);)16(222 return 1;)100 L (155)0(free\(n->s\);)16(223 })100 L (156)0(n->s = t;)16(224)100 L (157)0(n->alen = a;)16(225 int)100 L (158 })0(226 cmount\(Chan *new, Chan *old, int flag, char *spec\))100 L (159 if\(n->len>0 && n->s[n->len-1]!='/' && s[0]!='/'\))0(/* don't insert extra slash if one 227 {)64 L (160)0(n->s[n->len++] = '/';)16(228 Pgrp *pg;)100 L (161 memmove\(n->s+n->len, s, i+1\);)0(229 int order, flg;)100 L (162 n->len += i;)0(230 Mhead *m, **l;)100 L (163 return n;)0(231 Mount *nm, *f, *um, **h;)100 L (164 })0(232)100 L (165)0(233 if\(CHDIR & \(old->qid.path^new->qid.path\)\))100 L (166 void)0(234)100(error\(Emount\);)116 L (167 chanfree\(Chan *c\))0(235)100 L (168 {)0(236 order = flag&MORDER;)100 L (169 c->flag = CFREE;)0(237)100 L (170)0(238 if\(\(old->qid.path&CHDIR\)==0 && order != MREPL\))100 L (171 if\(c->session\){)0(239)100(error\(Emount\);)116 L (172)0(freesession\(c->session\);)16(240)100 L (173)0(c->session = 0;)16(241 pg = up->pgrp;)100 L (174 })0(242 wlock\(&pg->ns\);)100 L (175)0(243)100 L (176 if\(c->mh != nil\){)0(244 l = &MOUNTH\(pg, old\);)100 L (177)0(putmhead\(c->mh\);)16(245 for\(m = *l; m; m = m->hash\) {)100 L (178)0(c->mh = nil;)16(246)100(if\(eqchan\(m->from, old, 1\)\))116 L (179 })0(247)100(break;)124 L (180)0(248)100(l = &m->hash;)116 L (181 cnameclose\(c->name\);)0(249 })100 L (182)0(250)100 L (183 lock\(&chanalloc\);)0(251 if\(m == 0\) {)100 L (184 c->next = chanalloc.free;)0(252)100(/*)116 L (185 chanalloc.free = c;)0(253)100(* nothing mounted here yet. create a mount)117 L (186 unlock\(&chanalloc\);)0(254)100(* head and add to the hash table.)117 L (187 })0(255)100(*/)117 L (188)0(256)100(m = smalloc\(sizeof\(Mhead\)\);)116 L (189 void)0(257)100(m->ref = 1;)116 L (190 cclose\(Chan *c\))0(258)100(m->from = old;)116 L (191 {)0(259)100(incref\(old\);)116 L (192 if\(c->flag&CFREE\))0(260)100(m->hash = *l;)116 L (193)0(panic\("cclose %lux", getcallerpc\(&c\)\);)16(261)100(*l = m;)116 L (194 if\(decref\(c\)\))0(262)100 L (195)0(return;)16(263)100(/*)116 L (196)0(264)100(* if this is a union mount, add the old)117 L (197 if\(!waserror\(\)\) {)0(265)100(* node to the mount chain.)117 L (198)0(devtab[c->type]->close\(c\);)16(266)100(*/)117 L (199)0(poperror\(\);)16(267)100(if\(order != MREPL\))116 L (200 })0(268)100(m->mount = newmount\(m, old, 0, 0\);)124 L (201)0(269 })100 L (202 chanfree\(c\);)0(270 wlock\(&m->lock\);)100 L (203 })0(271 if\(waserror\(\)\){)100 L (204)0(272)100(wunlock\(&m->lock\);)116 L cleartomark showpage saveobj restore %%EndPage: 103 103 %%Page: 104 104 /saveobj save def mark 104 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 3)l ()l ()l (273)0(nexterror\(\);)16(341 wlock\(&m->lock\);)100 L (274 })0(342 if\(mounted == 0\) {)100 L (275 wunlock\(&pg->ns\);)0(343)100(*l = m->hash;)116 L (276)0(344)100(wunlock\(&pg->ns\);)116 L (277 nm = newmount\(m, new, flag, spec\);)0(345)100(mountfree\(m->mount\);)116 L (278 if\(new->mh != nil && new->mh->mount != nil\) {)0(346)100(m->mount = nil;)116 L (279)0(/*)16(347)100(cclose\(m->from\);)116 L (280)0(* copy a union when binding it onto a directory)17(348)100(wunlock\(&m->lock\);)116 L (281)0(*/)17(349)100(putmhead\(m\);)116 L (282)0(flg = order;)16(350)100(return;)116 L (283)0(if\(order == MREPL\))16(351 })100 L (284)0(flg = MAFTER;)24(352 wunlock\(&pg->ns\);)100 L (285)0(h = &nm->next;)16(353)100 L (286)0(um = new->mh->mount;)16(354 p = &m->mount;)100 L (287)0(for\(um = um->next; um; um = um->next\) {)16(355 for\(f = *p; f; f = f->next\) {)100 L (288)0(f = newmount\(m, um->to, flg, um->spec\);)24(356)100(/* BUG: Needs to be 2 pass */)116 L (289)0(*h = f;)24(357)100(if\(eqchan\(f->to, mounted, 1\) ||)116 L (290)0(h = &f->next;)24(358)100(\(f->to->mchan && eqchan\(f->to->mchan, mounted, 1\)\)\) {)118 L (291)0(})16(359)100(*p = f->next;)124 L (292 })0(360)100(f->next = 0;)124 L (293)0(361)100(mountfree\(f\);)124 L (294 if\(m->mount && order == MREPL\) {)0(362)100(if\(m->mount == nil\) {)124 L (295)0(mountfree\(m->mount\);)16(363)100(*l = m->hash;)132 L (296)0(m->mount = 0;)16(364)100(wunlock\(&pg->ns\);)132 L (297 })0(365)100(cclose\(m->from\);)132 L (298)0(366)100(wunlock\(&m->lock\);)132 L (299 if\(flag & MCREATE\))0(367)100(putmhead\(m\);)132 L (300)0(new->flag |= CCREATE;)16(368)100(return;)132 L (301)0(369)100(})124 L (302 if\(m->mount && order == MAFTER\) {)0(370)100(wunlock\(&m->lock\);)124 L (303)0(for\(f = m->mount; f->next; f = f->next\))16(371)100(return;)124 L (304)0(;)24(372)100(})116 L (305)0(f->next = nm;)16(373)100(p = &f->next;)116 L (306 })0(374 })100 L (307 else {)0(375 wunlock\(&m->lock\);)100 L (308)0(for\(f = nm; f->next; f = f->next\))16(376 error\(Eunion\);)100 L (309)0(;)24(377 })100 L (310)0(f->next = m->mount;)16(378)100 L (311)0(m->mount = nm;)16(379 Chan*)100 L (312 })0(380 cclone\(Chan *c, Chan *nc\))100 L (313)0(381 {)100 L (314 wunlock\(&m->lock\);)0(382 nc = devtab[c->type]->clone\(c, nc\);)100 L (315 poperror\(\);)0(383 if\(nc != nil\){)100 L (316 return nm->mountid;)0(384)100(nc->name = c->name;)116 L (317 })0(385)100(if\(c->name\))116 L (318)0(386)100(incref\(c->name\);)124 L (319 void)0(387 })100 L (320 cunmount\(Chan *mnt, Chan *mounted\))0(388 return nc;)100 L (321 {)0(389 })100 L (322 Pgrp *pg;)0(390)100 L (323 Mhead *m, **l;)0(391 Chan*)100 L (324 Mount *f, **p;)0(392 domount\(Chan *c\))100 L (325)0(393 {)100 L (326 pg = up->pgrp;)0(394 Pgrp *pg;)100 L (327 wlock\(&pg->ns\);)0(395 Chan *nc;)100 L (328)0(396 Mhead *m;)100 L (329 l = &MOUNTH\(pg, mnt\);)0(397)100 L (330 for\(m = *l; m; m = m->hash\) {)0(398 pg = up->pgrp;)100 L (331)0(if\(eqchan\(m->from, mnt, 1\)\))16(399 rlock\(&pg->ns\);)100 L (332)0(break;)24(400 if\(c->mh\){)100 L (333)0(l = &m->hash;)16(401)100(putmhead\(c->mh\);)116 L (334 })0(402)100(c->mh = 0;)116 L (335)0(403 })100 L (336 if\(m == 0\) {)0(404)100 L (337)0(wunlock\(&pg->ns\);)16(405 for\(m = MOUNTH\(pg, c\); m; m = m->hash\){)100 L (338)0(error\(Eunmount\);)16(406)100(rlock\(&m->lock\);)116 L (339 })0(407)100(if\(eqchan\(m->from, c, 1\)\) {)116 L (340)0(408)100(if\(waserror\(\)\) {)124 L cleartomark showpage saveobj restore %%EndPage: 104 104 %%Page: 105 105 /saveobj save def mark 105 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 4)l ()l ()l (409)0(runlock\(&m->lock\);)32(477 Chan *)100 L (410)0(nexterror\(\);)32(478 updatecname\(Chan *c, char *name, int dotdot\))100 L (411)0(})24(479 {)100 L (412)0(runlock\(&pg->ns\);)24(480 if\(c->name == nil\))100 L (413)0(nc = cclone\(m->mount->to, 0\);)24(481)100(c->name = newcname\(name\);)116 L (414)0(if\(nc->mh != nil\))24(482 else)100 L (415)0(putmhead\(nc->mh\);)32(483)100(c->name = addelem\(c->name, name\);)116 L (416)0(nc->mh = m;)24(484)100 L (417)0(nc->xmh = m;)24(485 if\(dotdot\){)100 L (418)0(incref\(m\);)24(486)100(cleancname\(c->name\); /* could be cheaper */)116 L (419)0(cnameclose\(nc->name\);)24(487)100(c = undomount\(c\);)116 L (420)0(nc->name = c->name;)24(488 })100 L (421)0(incref\(c->name\);)24(489 return c;)100 L (422)0(cclose\(c\);)24(490 })100 L (423)0(c = nc;)24(491)100 L (424)0(poperror\(\);)24(492 int)100 L (425)0(runlock\(&m->lock\);)24(493 walk\(Chan **cp, char *name, int domnt\))100 L (426)0(return c;)24(494 {)100 L (427)0(})16(495 Chan *c, *ac;)100 L (428)0(runlock\(&m->lock\);)16(496 Mount *f;)100 L (429 })0(497 int dotdot;)100 L (430)0(498)100 L (431 runlock\(&pg->ns\);)0(499 ac = *cp;)100 L (432 return c;)0(500)100 L (433 })0(501 if\(name[0] == '\\0'\))100 L (434)0(502)100(return 0;)116 L (435 Chan*)0(503)100 L (436 undomount\(Chan *c\))0(504 dotdot = 0;)100 L (437 {)0(505 if\(name[0] == '.' && name[1] == '.' && name[2] == '\\0'\) {)100 L (438 Chan *nc;)0(506)100(*cp = ac = undomount\(ac\);)116 L (439 Pgrp *pg;)0(507)100(dotdot = 1;)116 L (440 Mount *t;)0(508 })100 L (441 Mhead **h, **he, *f;)0(509)100 L (442)0(510 ac->flag &= ~CCREATE; /* not inherited through a walk */)100 L (443 pg = up->pgrp;)0(511 if\(devtab[ac->type]->walk\(ac, name\) != 0\) {)100 L (444 rlock\(&pg->ns\);)0(512)100(/* walk succeeded: update name associated with *cp \(ac\) */)116 L (445 if\(waserror\(\)\) {)0(513)100(*cp = updatecname\(*cp, name, dotdot\);)116 L (446)0(runlock\(&pg->ns\);)16(514)100(if\(domnt\))116 L (447)0(nexterror\(\);)16(515)100(*cp = domount\(*cp\);)124 L (448 })0(516)100(return 0;)116 L (449)0(517 })100 L (450 he = &pg->mnthash[MNTHASH];)0(518)100 L (451 for\(h = pg->mnthash; h < he; h++\) {)0(519 if\(ac->mh == nil\))100 L (452)0(for\(f = *h; f; f = f->hash\) {)16(520)100(return -1;)116 L (453)0(for\(t = f->mount; t; t = t->next\) {)24(521)100 L (454)0(if\(eqchan\(c, t->to, 1\)\) {)32(522 c = nil;)100 L (455)0(/*)40(523)100 L (456)0(* We want to come out on the left hand side of the mount 524 rlock\(&ac->mh->lock\);)41 L (457)0(* point using the element of the union that we entered on. 525 if\(waserror\(\)\) {)41 L (458)0(* To do this, find the element that has a from name of 526)41(runlock\(&ac->mh->lock\);)116 L (459)0(* c->name->s.)41(527)100(if\(c\))116 L (460)0(*/)41(528)100(cclose\(c\);)124 L (461)0(if\(strcmp\(t->head->from->name->s, c->name->s\) != 0\))40(529)100(nexterror\(\);)116 L (462)0(continue;)48(530 })100 L (463)0(nc = cclone\(t->head->from, 0\);)40(531 for\(f = ac->mh->mount; f; f = f->next\) {)100 L (464)0(/* don't need to update nc->name because c->name is same! * 532)40(c = cclone\(f->to, 0\);)116 L (465)0(cclose\(c\);)40(533)100(c->flag &= ~CCREATE; /* not inherited through a walk */)116 L (466)0(c = nc;)40(534)100(if\(devtab[c->type]->walk\(c, name\) != 0\))116 L (467)0(break;)40(535)100(break;)124 L (468)0(})32(536)100(cclose\(c\);)116 L (469)0(})24(537)100(c = nil;)116 L (470)0(})16(538 })100 L (471 })0(539 poperror\(\);)100 L (472 poperror\(\);)0(540 runlock\(&ac->mh->lock\);)100 L (473 runlock\(&pg->ns\);)0(541)100 L (474 return c;)0(542 if\(c == nil\))100 L (475 })0(543)100(return -1;)116 L (476)0(544)100 L cleartomark showpage saveobj restore %%EndPage: 105 105 %%Page: 106 106 /saveobj save def mark 106 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 5)l ()l ()l (545 if\(c->mh\){)0(613)100 L (546)0(putmhead\(c->mh\);)16(614)100(/*)116 L (547)0(c->mh = nil;)16(615)100(* The correct name is #i rather than #i/,)117 L (548 })0(616)100(* but the correct name of #/ is #/.)117 L (549)0(617)100(*/)117 L (550 /* replace c->name by ac->name */)0(618)100(if\(strcmp\(p, "/"\)==0 && n->s[1] != '/'\))116 L (551 cnameclose\(c->name\);)0(619)100(*p = '\\0';)124 L (552 c->name = ac->name;)0(620 }else)100 L (553 if\(ac->name\))0(621)100(cleanname\(n->s\);)116 L (554)0(incref\(ac->name\);)16(622 n->len = strlen\(n->s\);)100 L (555 c = updatecname\(c, name, dotdot\);)0(623 })100 L (556 cclose\(ac\);)0(624)100 L (557 *cp = c;)0(625 /*)100 L (558)0(626 * Turn a name into a channel.)100 L (559 if\(domnt\))0(627 * &name[0] is known to be a valid address. It may be a kernel address.)100 L (560)0(*cp = domount\(c\);)16(628 */)100 L (561 return 0;)0(629 Chan*)100 L (562 })0(630 namec\(char *name, int amode, int omode, ulong perm\))100 L (563)0(631 {)100 L (564 /*)0(632 Rune r;)100 L (565 * c is a mounted non-creatable directory. find a creatable one.)0(633 char *p;)100 L (566 */)0(634 char *elem;)100 L (567 Chan*)0(635 Cname *cname;)100 L (568 createdir\(Chan *c\))0(636 int t, n, newname;)100 L (569 {)0(637 int mntok, isdot;)100 L (570 Chan *nc;)0(638 Chan *c, *cc;)100 L (571 Mount *f;)0(639 char createerr[ERRLEN];)100 L (572)0(640)100 L (573 rlock\(&c->mh->lock\);)0(641 if\(name[0] == 0\))100 L (574 if\(waserror\(\)\) {)0(642)100(error\(Enonexist\);)116 L (575)0(runlock\(&c->mh->lock\);)16(643)100 L (576)0(nexterror\(\);)16(644 if\(!\(\(ulong\)name & KZERO\)\) {)100 L (577 })0(645)100(p = name;)116 L (578 for\(f = c->mh->mount; f; f = f->next\) {)0(646)100(t = BY2PG-\(\(ulong\)p&\(BY2PG-1\)\);)116 L (579)0(if\(f->to->flag&CCREATE\) {)16(647)100(while\(vmemchr\(p, 0, t\) == 0\) {)116 L (580)0(nc = cclone\(f->to, 0\);)24(648)100(p += t;)124 L (581)0(if\(nc->mh != nil\))24(649)100(t = BY2PG;)124 L (582)0(putmhead\(nc->mh\);)32(650)100(})116 L (583)0(nc->mh = c->mh;)24(651 })100 L (584)0(incref\(c->mh\);)24(652)100 L (585)0(runlock\(&c->mh->lock\);)24(653 newname = 1;)100 L (586)0(poperror\(\);)24(654 cname = nil;)100 L (587)0(cclose\(c\);)24(655 if\(waserror\(\)\){)100 L (588)0(return nc;)24(656)100(cnameclose\(cname\);)116 L (589)0(})16(657)100(nexterror\(\);)116 L (590 })0(658 })100 L (591 error\(Enocreate\);)0(659)100 L (592 return 0;)0(660 elem = up->elem;)100 L (593 })0(661 mntok = 1;)100 L (594)0(662 isdot = 0;)100 L (595 void)0(663 switch\(name[0]\) {)100 L (596 saveregisters\(void\))0(664 case '/':)100 L (597 {)0(665)100(cname = newcname\(name\); /* save this before advancing */)116 L (598 })0(666)100(name = skipslash\(name\);)116 L (599)0(667)100(c = cclone\(up->slash, 0\);)116 L (600 /*)0(668)100(break;)116 L (601 * In place, rewrite name to compress multiple /, eliminate ., and process ..)0(669 case '#':)100 L (602 */)0(670)100(cname = newcname\(name\); /* save this before advancing */)116 L (603 void)0(671)100(mntok = 0;)116 L (604 cleancname\(Cname *n\))0(672)100(elem[0] = 0;)116 L (605 {)0(673)100(n = 0;)116 L (606 char *p;)0(674)100(while\(*name && \(*name != '/' || n < 2\)\){)116 L (607)0(675)100(if\(n >= NAMELEN-1\))124 L (608 if\(n->s[0] == '#'\){)0(676)100(error\(Efilename\);)132 L (609)0(p = strchr\(n->s, '/'\);)16(677)100(elem[n++] = *name++;)124 L (610)0(if\(p == nil\))16(678)100(})116 L (611)0(return;)24(679)100(elem[n] = '\\0';)116 L (612)0(cleanname\(p\);)16(680)100(/*)116 L cleartomark showpage saveobj restore %%EndPage: 106 106 %%Page: 107 107 /saveobj save def mark 107 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 6)l ()l ()l (681)0(* noattach is sandboxing.)17(749)100(if\(walk\(&c, elem, 0\) < 0\))116 L (682)0(*)17(750)100(error\(Enonexist\);)124 L (683)0(* the OK exceptions are:)17(751)100(if\(!\(c->qid.path & CHDIR\)\))116 L (684)0(*)17(| it only gives access to pipes you create)24(752)100(error\(Enotdir\);)124 L (685)0(*)17(d this process's file descriptors)24(753)100(break;)116 L (686)0(*)17(e this process's environment)24(754)100 L (687)0(* the iffy exceptions are:)17(755 case Aopen:)100 L (688)0(*)17(c time and pid, but also cons and consctl)24(756)100(if\(isdot\))116 L (689)0(*)17(p control of your own processes \(and unfortunately)24(757)100(c = domount\(c\);)124 L (690)0(*)17(any others left unprotected\))27(758)100(else {)116 L (691)0(*/)17(759)100(if\(walk\(&c, elem, mntok\) < 0\))124 L (692)0(n = chartorune\(&r, elem+1\)+1;)16(760)100(error\(Enonexist\);)132 L (693)0(/* actually / is caught by parsing earlier */)16(761)100(})116 L (694)0(if\(utfrune\("M", r\)\))16(762 Open:)100 L (695)0(error\(Enoattach\);)24(763)100(/* else error\(\) in open has wrong value of c saved */)116 L (696)0(if\(up->pgrp->noattach && utfrune\("|decp", r\)\))16(764)100(saveregisters\(\);)116 L (697)0(error\(Enoattach\);)24(765)100 L (698)0(t = devno\(r, 1\);)16(766)100(if\(omode == OEXEC\))116 L (699)0(if\(t == -1\))16(767)100(c->flag &= ~CCACHE;)124 L (700)0(error\(Ebadsharp\);)24(768)100 L (701)0(769)100(cc = c;)116 L (702)0(c = devtab[t]->attach\(elem+n\);)16(770)100(c = devtab[c->type]->open\(c, omode&~OCEXEC\);)116 L (703)0(name = skipslash\(name\);)16(771)100(if\(cc != c\))116 L (704)0(break;)16(772)100(newname = 0;)124 L (705 default:)0(773)100 L (706)0(cname = newcname\(up->dot->name->s\);)16(774)100(if\(omode & OCEXEC\))116 L (707)0(cname = addelem\(cname, name\);)16(775)100(c->flag |= CCEXEC;)124 L (708)0(c = cclone\(up->dot, 0\);)16(776)100(if\(omode & ORCLOSE\))116 L (709)0(name = skipslash\(name\);)16(777)100(c->flag |= CRCLOSE;)124 L (710)0(if\(*name == 0\))16(778)100(break;)116 L (711)0(isdot = 1;)24(779)100 L (712 })0(780 case Amount:)100 L (713)0(781)100(/*)116 L (714 if\(waserror\(\)\){)0(782)100(* When mounting on an already mounted upon directory,)117 L (715)0(cclose\(c\);)16(783)100(* one wants subsequent mounts to be attached to the)117 L (716)0(nexterror\(\);)16(784)100(* original directory, not the replacement.)117 L (717 })0(785)100(*/)117 L (718)0(786)100(if\(walk\(&c, elem, 0\) < 0\))116 L (719 name = nextelem\(name, elem\);)0(787)100(error\(Enonexist\);)124 L (720)0(788)100(break;)116 L (721 /*)0(789)100 L (722)0(* If mounting, don't follow the mount entry for root or the)9(790 case Acreate:)100 L (723)0(* current directory.)9(791)100(if\(isdot\))116 L (724)0(*/)9(792)100(error\(Eisdir\);)124 L (725 if\(mntok && !isdot && !\(amode==Amount && elem[0]==0\)\))0(793)100 L (726)0(c = domount\(c\);)16(/* see case Atodir below */)48(794)100(/*)116 L (727)0(795)100(* Walk the element before trying to create it)117 L (728 while\(*name\) {)0(796)100(* to see if it exists. We clone the channel)117 L (729)0(if\(walk\(&c, elem, mntok\) < 0\))16(797)100(* first, just in case someone is trying to)117 L (730)0(error\(Enonexist\);)24(798)100(* use clwalk outside the kernel.)117 L (731)0(name = nextelem\(name, elem\);)16(799)100(*/)117 L (732 })0(800)100(cc = cclone\(c, 0\);)116 L (733)0(801)100(if\(waserror\(\)\){)116 L (734 switch\(amode\) {)0(802)100(cclose\(cc\);)124 L (735 case Aaccess:)0(803)100(nexterror\(\);)124 L (736)0(if\(isdot\) {)16(804)100(})116 L (737)0(c = domount\(c\);)24(805)100(nameok\(elem, 0\);)116 L (738)0(break;)24(806)100(if\(walk\(&cc, elem, 1\) == 0\){)116 L (739)0(})16(807)100(poperror\(\);)124 L (740)0(if\(walk\(&c, elem, mntok\) < 0\))16(808)100(cclose\(c\);)124 L (741)0(error\(Enonexist\);)24(809)100(c = cc;)124 L (742)0(break;)16(810)100(omode |= OTRUNC;)124 L (743)0(811)100(goto Open;)124 L (744 case Atodir:)0(812)100(})116 L (745)0(/*)16(813)100(cclose\(cc\);)116 L (746)0(* Directories \(e.g. for cd\) are left before the mount point,)17(814)100(poperror\(\);)116 L (747)0(* so one may mount on / or . and see the effect.)17(815)100 L (748)0(*/)17(816)100(/*)116 L cleartomark showpage saveobj restore %%EndPage: 107 107 %%Page: 108 108 /saveobj save def mark 108 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/chan.c Page 7)l ()l ()l (817)0(* the file didn't exist, try the create)17(885 nameok\(char *elem, int slashok\))100 L (818)0(*/)17(886 {)100 L (819)0(if\(c->mh != nil && !\(c->flag&CCREATE\)\))16(887 char *eelem;)100 L (820)0(c = createdir\(c\);)24(888)100 L (821)0(889 eelem = elem+NAMELEN;)100 L (822)0(/*)16(890 while\(*elem\) {)100 L (823)0(* protect against the open/create race.)17(891)100(if\(isfrog[*\(uchar*\)elem]\))116 L (824)0(* This is not a complete fix. It just reduces the window.)17(892)100(if\(!slashok || *elem!='/'\))124 L (825)0(*/)17(893)100(error\(Ebadchar\);)132 L (826)0(if\(waserror\(\)\) {)16(894)100(elem++;)116 L (827)0(strcpy\(createerr, up->error\);)24(895)100(if\(elem >= eelem\))116 L (828)0(if\(walk\(&c, elem, 1\) < 0\))24(896)100(error\(Efilename\);)124 L (829)0(error\(createerr\);)32(897 })100 L (830)0(omode |= OTRUNC;)24(898 })100 L (831)0(goto Open;)24(899)100 L (832)0(})16(900 /*)100 L (833)0(devtab[c->type]->create\(c, elem, omode&~OCEXEC, perm\);)16(901 * name[0] should not be a slash.)100 L (834)0(if\(omode & OCEXEC\))16(902 */)100 L (835)0(c->flag |= CCEXEC;)24(903 char*)100 L (836)0(if\(omode & ORCLOSE\))16(904 nextelem\(char *name, char *elem\))100 L (837)0(c->flag |= CRCLOSE;)24(905 {)100 L (838)0(poperror\(\);)16(906 int w;)100 L (839)0(break;)16(907 char *end;)100 L (840)0(908 Rune r;)100 L (841 default:)0(909)100 L (842)0(panic\("unknown namec access %d\\n", amode\);)16(910 if\(*name == '/'\))100 L (843 })0(911)100(error\(Efilename\);)116 L (844)0(912 end = utfrune\(name, '/'\);)100 L (845 poperror\(\);)0(913 if\(end == 0\))100 L (846)0(914)100(end = strchr\(name, 0\);)116 L (847 if\(newname\){)0(915 w = end-name;)100 L (848)0(cleancname\(cname\);)16(916 if\(w >= NAMELEN\))100 L (849)0(cnameclose\(c->name\);)16(917)100(error\(Efilename\);)116 L (850)0(c->name = cname;)16(918 memmove\(elem, name, w\);)100 L (851 }else)0(919 elem[w] = 0;)100 L (852)0(cnameclose\(cname\);)16(920 while\(name < end\){)100 L (853)0(921)100(name += chartorune\(&r, name\);)116 L (854 poperror\(\);)0(922)100(if\(rqid.path & CHDIR\))100 L (864)0(Again:)10(932)100(return;)116 L (865 while\(*name == '/'\))0(933 error\(Enotdir\);)100 L (866)0(name++;)16(934 })100 L (867 if\(*name=='.' && \(name[1]==0 || name[1]=='/'\)\){)0(935)100 L (868)0(name++;)16(936 void)100 L (869)0(goto Again;)16(937 putmhead\(Mhead *m\))100 L (870 })0(938 {)100 L (871 return name;)0(939 if\(decref\(m\) == 0\))100 L (872 })0(940)100(free\(m\);)116 L (873)0(941 })100 L (874 char isfrog[256]={)l (875 /*NUL*/ 1, 1, 1, 1, 1, 1, 1, 1,)l (876 /*BKS*/ 1, 1, 1, 1, 1, 1, 1, 1,)l (877 /*DLE*/ 1, 1, 1, 1, 1, 1, 1, 1,)l (878 /*CAN*/ 1, 1, 1, 1, 1, 1, 1, 1,)l (879 /*)0([' '] 1,)16(rob - let's try this out */)32 L (880 ['/'] 1,)l (881 [0x7f] 1,)l (882 };)l (883)l (884 void)l cleartomark showpage saveobj restore %%EndPage: 108 108 %%Page: 109 109 /saveobj save def mark 109 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/dev.c Page 1)l ()l ()l (1 #include "u.h")0(69 {)100 L (2 #include "../port/lib.h")0(70 })100 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72 Chan*)100 L (5 #include "fns.h")0(73 devattach\(int tc, char *spec\))100 L (6 #include "../port/error.h")0(74 {)100 L (7)0(75)100(Chan *c;)108 L (8 extern ulong)0(kerndate;)24(76)100(char buf[NAMELEN+4];)108 L (9)0(77)100 L (10 int)0(78)100(c = newchan\(\);)108 L (11 devno\(int c, int user\))0(79)100(c->qid = \(Qid\){CHDIR, 0};)108 L (12 {)0(80)100(c->type = devno\(tc, 0\);)108 L (13)0(int i;)8(81)100(sprint\(buf, "#%C%s", tc, spec==nil? "" : spec\);)108 L (14)0(82)100(c->name = newcname\(buf\);)108 L (15)0(for\(i = 0; devtab[i] != nil; i++\) {)8(83)100(return c;)108 L (16)0(if\(devtab[i]->dc == c\))16(84 })100 L (17)0(return i;)24(85)100 L (18)0(})8(86 Chan*)100 L (19)0(if\(user == 0\))8(87 devclone\(Chan *c, Chan *nc\))100 L (20)0(panic\("devno %C 0x%ux", c, c\);)16(88 {)100 L (21)0(89)100(if\(c->flag & COPEN\))108 L (22)0(return -1;)8(90)100(panic\("clone of open file type %C\\n", devtab[c->type]->dc\);)116 L (23 })0(91)100 L (24)0(92)100(if\(nc == 0\))108 L (25 void)0(93)100(nc = newchan\(\);)116 L (26 devdir\(Chan *c, Qid qid, char *n, vlong length, char *user, long perm, Dir *db\))0(94)100 L (27 {)0(95)100(nc->type = c->type;)108 L (28)0(strcpy\(db->name, n\);)8(96)100(nc->dev = c->dev;)108 L (29)0(db->qid = qid;)8(97)100(nc->mode = c->mode;)108 L (30)0(db->type = devtab[c->type]->dc;)8(98)100(nc->qid = c->qid;)108 L (31)0(db->dev = c->dev;)8(99)100(nc->offset = c->offset;)108 L (32)0(if\(qid.path & CHDIR\))8(100 nc->flag = c->flag;)100 L (33)0(db->mode = CHDIR|perm;)16(101 nc->mh = c->mh;)100 L (34)0(else)8(102 if\(c->mh != nil\))100 L (35)0(db->mode = perm;)16(103)100(incref\(c->mh\);)116 L (36)0(if\(c->flag&CMSG\))8(104 nc->mountid = c->mountid;)100 L (37)0(db->mode |= CHMOUNT;)16(105 nc->aux = c->aux;)100 L (38)0(db->atime = seconds\(\);)8(106 nc->mchan = c->mchan;)100 L (39)0(db->mtime = kerndate;)8(107 nc->mqid = c->mqid;)100 L (40)0(db->length = length;)8(108 nc->mcp = c->mcp;)100 L (41)0(memmove\(db->uid, user, NAMELEN\);)8(109 return nc;)100 L (42)0(memmove\(db->gid, eve, NAMELEN\);)8(110 })100 L (43 })0(111)100 L (44)0(112 int)100 L (45 //)0(113 devwalk\(Chan *c, char *name, Dirtab *tab, int ntab, Devgen *gen\))100 L (46 // the zeroth element of the table MUST be the directory itself for ..)0(114 {)100 L (47 //)0(115 long i;)100 L (48 int)0(116 Dir dir;)100 L (49 devgen\(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp\))0(117)100 L (50 {)0(118 isdir\(c\);)100 L (51)0(if\(tab==0\))8(119 if\(name[0]=='.' && name[1]==0\))100 L (52)0(return -1;)16(120)100(return 1;)116 L (53)0(if\(i!=DEVDOTDOT\){)8(121 if\(name[0]=='.' && name[1]=='.' && name[2]==0\){)100 L (54)0(if\(i>=ntab\))16(122)100(\(*gen\)\(c, tab, ntab, DEVDOTDOT, &dir\);)116 L (55)0(return -1;)24(123)100(c->qid = dir.qid;)116 L (56)0(tab += i;)16(124)100(return 1;)116 L (57)0(})8(125 })100 L (58)0(devdir\(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp\);)8(126 for\(i=0;; i++\) {)100 L (59)0(return 1;)8(127)100(switch\(\(*gen\)\(c, tab, ntab, i, &dir\)\){)116 L (60 })0(128)100(case -1:)116 L (61)0(129)100(strncpy\(up->error, Enonexist, NAMELEN\);)124 L (62 void)0(130)100(return 0;)124 L (63 devreset\(void\))0(131)100(case 0:)116 L (64 {)0(132)100(continue;)124 L (65 })0(133)100(case 1:)116 L (66)0(134)100(if\(strcmp\(name, dir.name\) == 0\){)124 L (67 void)0(135)100(c->qid = dir.qid;)132 L (68 devinit\(void\))0(136)100(return 1;)132 L cleartomark showpage saveobj restore %%EndPage: 109 109 %%Page: 110 110 /saveobj save def mark 110 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/dev.c Page 2)l ()l ()l (137)0(})24(205)100(break;)124 L (138)0(continue;)24(206)100(})116 L (139)0(})16(207 })100 L (140 })0(208)100 L (141 return 0;)0(209 return m;)100 L (142 })0(210 })100 L (143)0(211)100 L (144 void)0(212 Chan*)100 L (145 devstat\(Chan *c, char *db, Dirtab *tab, int ntab, Devgen *gen\))0(213 devopen\(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen\))100 L (146 {)0(214 {)100 L (147 int i;)0(215 int i;)100 L (148 Dir dir;)0(216 Dir dir;)100 L (149 char *p, *elem;)0(217 ulong t, mode;)100 L (150)0(218 static int access[] = { 0400, 0200, 0600, 0100 };)100 L (151 for\(i=0;; i++\))0(219)100 L (152)0(switch\(\(*gen\)\(c, tab, ntab, i, &dir\)\){)16(220 for\(i=0;; i++\) {)100 L (153)0(case -1:)16(221)100(switch\(\(*gen\)\(c, tab, ntab, i, &dir\)\){)116 L (154)0(if\(c->qid.path & CHDIR\){)24(222)100(case -1:)116 L (155)0(if\(c->name == nil\))32(223)100(goto Return;)124 L (156)0(elem = "???";)40(224)100(case 0:)116 L (157)0(else if\(strcmp\(c->name->s, "/"\) == 0\))32(225)100(break;)124 L (158)0(elem = "/";)40(226)100(case 1:)116 L (159)0(else)32(227)100(if\(c->qid.path == dir.qid.path\) {)124 L (160)0(for\(elem=p=c->name->s; *p; p++\))40(228)100(if\(strcmp\(up->user, dir.uid\) == 0\))132 L (161)0(if\(*p == '/'\))48(229)100(mode = dir.mode;)140 L (162)0(elem = p+1;)56(230)100(else)132 L (163)0(devdir\(c, c->qid, elem, i*DIRLEN, eve, CHDIR|0555, &dir\);)32(231)100(if\(strcmp\(up->user, eve\) == 0\))132 L (164)0(convD2M\(&dir, db\);)32(232)100(mode = dir.mode<<3;)140 L (165)0(return;)32(233)100(else)132 L (166)0(})24(234)100(mode = dir.mode<<6;)140 L (167)0(print\("%s %s: devstat %C %lux\\n",)24(235)100 L (168)0(up->text, up->user,)32(236)100(t = access[omode&3];)132 L (169)0(devtab[c->type]->dc, c->qid.path\);)32(237)100(if\(\(t & mode\) == t\))132 L (170)0(238)100(goto Return;)140 L (171)0(error\(Enonexist\);)24(239)100(error\(Eperm\);)132 L (172)0(case 0:)16(240)100(})124 L (173)0(break;)24(241)100(break;)124 L (174)0(case 1:)16(242)100(})116 L (175)0(if\(c->qid.path == dir.qid.path\) {)24(243 })100 L (176)0(if\(c->flag&CMSG\))32(244 Return:)100 L (177)0(dir.mode |= CHMOUNT;)40(245 c->offset = 0;)100 L (178)0(convD2M\(&dir, db\);)32(246 if\(\(c->qid.path&CHDIR\) && omode!=OREAD\))100 L (179)0(return;)32(247)100(error\(Eperm\);)116 L (180)0(})24(248 c->mode = openmode\(omode\);)100 L (181)0(break;)24(249 c->flag |= COPEN;)100 L (182)0(})16(250 return c;)100 L (183 })0(251 })100 L (184)0(252)100 L (185 long)0(253 void)100 L (186 devdirread\(Chan *c, char *d, long n, Dirtab *tab, int ntab, Devgen *gen\))0(254 devcreate\(Chan*, char*, int, ulong\))100 L (187 {)0(255 {)100 L (188 long k, m;)0(256 error\(Eperm\);)100 L (189 Dir dir;)0(257 })100 L (190)0(258)100 L (191 k = c->offset/DIRLEN;)0(259 Block*)100 L (192 for\(m=0; moffset += DIRLEN;)24(266)100(error\(Enomem\);)116 L (199)0(break;)24(267 if\(waserror\(\)\) {)100 L (200)0(268)100(freeb\(bp\);)116 L (201)0(case 1:)16(269)100(nexterror\(\);)116 L (202)0(convD2M\(&dir, d\);)24(270 })100 L (203)0(m += DIRLEN;)24(271 bp->wp += devtab[c->type]->read\(c, bp->wp, n, offset\);)100 L (204)0(d += DIRLEN;)24(272 poperror\(\);)100 L cleartomark showpage saveobj restore %%EndPage: 110 110 %%Page: 111 111 /saveobj save def mark 111 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/dev.c Page 3)l ()l ()l (273 return bp;)l (274 })l (275)l (276 long)l (277 devbwrite\(Chan *c, Block *bp, ulong offset\))l (278 {)l (279 long n;)l (280)l (281 n = devtab[c->type]->write\(c, bp->rp, BLEN\(bp\), offset\);)l (282 freeb\(bp\);)l (283)l (284 return n;)l (285 })l (286)l (287 void)l (288 devremove\(Chan*\))l (289 {)l (290 error\(Eperm\);)l (291 })l (292)l (293 void)l (294 devwstat\(Chan*, char*\))l (295 {)l (296 error\(Eperm\);)l (297 })l cleartomark showpage saveobj restore %%EndPage: 111 111 %%Page: 112 112 /saveobj save def mark 112 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 1)l ()l ()l (1 #include "u.h")0(69 */)100 L (2 #include "../port/lib.h")0(70 static void)100 L (3 #include "mem.h")0(71 putstrn0\(char *str, int n, int usewrite\))100 L (4 #include "dat.h")0(72 {)100 L (5 #include "fns.h")0(73)100(int m;)108 L (6 #include "../port/error.h")0(74)100(char *t;)108 L (7)0(75)100(char buf[PRINTSIZE+2];)108 L (8 void)0(\(*consdebug\)\(void\) = nil;)16(76)100 L (9)0(77)100(/*)108 L (10 Queue* kbdq;)0(/* unprocessed console input */)40(78)100(* if there's an attached bit mapped display,)109 L (11 Queue* lineq;)0(/* processed console input */)40(79)100(* put the message there. screenputs is defined)109 L (12 Queue* printq;)0(/* console output */)40(80)100(* as a null macro for systems that have no such)109 L (13)0(81)100(* display.)109 L (14 static struct)0(82)100(*/)109 L (15 {)0(83)100(screenputs\(str, n\);)108 L (16)0(QLock;)8(84)100 L (17)0(85)100(/*)108 L (18)0(int raw;)8(/* true if we shouldn't process input */)32(86)100(* if there's a serial line being used as a console,)109 L (19)0(int ctl;)8(/* number of opens to the control file */)32(87)100(* put the message there.)109 L (20)0(int x;)8(/* index into line */)32(88)100(*/)109 L (21)0(char line[1024]; /* current input line */)8(89)100(if\(printq == 0\))108 L (22)0(90)100(return;)116 L (23)0(Rune c;)8(91)100 L (24)0(int count;)8(92)100(while\(n > 0\) {)108 L (25)0(int repeat;)8(93)100(t = memchr\(str, '\\n', n\);)116 L (26)0(int ctlpoff;)8(94)100(if\(t\) {)116 L (27 } kbd;)0(95)100(m = t - str;)124 L (28)0(96)100(memmove\(buf, str, m\);)124 L (29 char)0(sysname[NAMELEN];)16(97)100(buf[m] = '\\r';)124 L (30 vlong fasthz;)0(98)100(buf[m+1] = '\\n';)124 L (31)0(99)100(if\(usewrite\))124 L (32 static ulong)0(randomread\(void*, ulong\);)24(100)100(qwrite\(printq, buf, m+2\);)132 L (33 static void)0(randominit\(void\);)24(101)100(else)124 L (34 static void)0(seedrand\(void\);)24(102)100(qiwrite\(printq, buf, m+2\);)132 L (35 static int)0(readtime\(ulong, char*, int\);)24(103)100(str = t + 1;)124 L (36 static int)0(readbintime\(char*, int\);)24(104)100(n -= m + 1;)124 L (37 static int)0(writetime\(char*, int\);)24(105)100(} else {)116 L (38 static int)0(writebintime\(char*, int\);)24(106)100(if\(usewrite\))124 L (39)0(107)100(qwrite\(printq, str, n\);)132 L (40 void)0(108)100(else)124 L (41 printinit\(void\))0(109)100(qiwrite\(printq, str, n\);)132 L (42 {)0(110)100(break;)124 L (43)0(lineq = qopen\(2*1024, 0, 0, 0\);)8(111)100(})116 L (44)0(if\(lineq == nil\))8(112 })100 L (45)0(panic\("printinit"\);)16(113 })100 L (46)0(qnoblock\(lineq, 1\);)8(114)100 L (47 })0(115 void)100 L (48)0(116 putstrn\(char *str, int n\))100 L (49 int)0(117 {)100 L (50 consactive\(void\))0(118 putstrn0\(str, n, 0\);)100 L (51 {)0(119 })100 L (52)0(if\(printq\))8(120)100 L (53)0(return qlen\(printq\) > 0;)16(121 int)100 L (54)0(return 0;)8(122 snprint\(char *s, int n, char *fmt, ...\))100 L (55 })0(123 {)100 L (56)0(124 va_list arg;)100 L (57 void)0(125)100 L (58 prflush\(void\))0(126 va_start\(arg, fmt\);)100 L (59 {)0(127 n = doprint\(s, s+n, fmt, arg\) - s;)100 L (60)0(while\(consactive\(\)\))8(128 va_end\(arg\);)100 L (61)0(;)16(129 return n;)100 L (62 })0(130 })100 L (63)0(131)100 L (64 /*)0(132 int)100 L (65 * Print a string on the console. Convert \\n to \\r\\n for serial)0(133 sprint\(char *s, char *fmt, ...\))100 L (66 * line consoles. Locking of the queues is left up to the screen)0(134 {)100 L (67 * or uart code. Multi-line messages to serial consoles may get)0(135 int n;)100 L (68 * interspersed with other messages.)0(136 va_list arg;)100 L cleartomark showpage saveobj restore %%EndPage: 112 112 %%Page: 113 113 /saveobj save def mark 113 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 2)l ()l ()l (137)0(205)100 L (138 va_start\(arg, fmt\);)0(206 void)100 L (139 n = doprint\(s, s+PRINTSIZE, fmt, arg\) - s;)0(207 _assert\(char *fmt\))100 L (140 va_end\(arg\);)0(208 {)100 L (141 return n;)0(209 panic\("assert failed: %s", fmt\);)100 L (142 })0(210 })100 L (143)0(211)100 L (144 int noprint;)0(212 int)100 L (145)0(213 pprint\(char *fmt, ...\))100 L (146 int)0(214 {)100 L (147 print\(char *fmt, ...\))0(215 int n;)100 L (148 {)0(216 Chan *c;)100 L (149 int n;)0(217 va_list arg;)100 L (150 va_list arg;)0(218 char buf[2*PRINTSIZE];)100 L (151 char buf[PRINTSIZE];)0(219)100 L (152)0(220 if\(up == nil || up->fgrp == nil\))100 L (153 if\(noprint\))0(221)100(return 0;)116 L (154)0(return -1;)16(222)100 L (155)0(223 c = up->fgrp->fd[2];)100 L (156 va_start\(arg, fmt\);)0(224 if\(c==0 || \(c->mode!=OWRITE && c->mode!=ORDWR\)\))100 L (157 n = doprint\(buf, buf+sizeof\(buf\), fmt, arg\) - buf;)0(225)100(return 0;)116 L (158 va_end\(arg\);)0(226 n = sprint\(buf, "%s %lud: ", up->text, up->pid\);)100 L (159 putstrn\(buf, n\);)0(227 va_start\(arg, fmt\);)100 L (160)0(228 n = doprint\(buf+n, buf+sizeof\(buf\), fmt, arg\) - buf;)100 L (161 return n;)0(229 va_end\(arg\);)100 L (162 })0(230)100 L (163)0(231 if\(waserror\(\)\))100 L (164 int)0(232)100(return 0;)116 L (165 iprint\(char *fmt, ...\))0(233 devtab[c->type]->write\(c, buf, n, c->offset\);)100 L (166 {)0(234 poperror\(\);)100 L (167 int n, s;)0(235)100 L (168 va_list arg;)0(236 lock\(c\);)100 L (169 char buf[PRINTSIZE];)0(237 c->offset += n;)100 L (170)0(238 unlock\(c\);)100 L (171 s = splhi\(\);)0(239)100 L (172 va_start\(arg, fmt\);)0(240 return n;)100 L (173 n = doprint\(buf, buf+sizeof\(buf\), fmt, arg\) - buf;)0(241 })100 L (174 va_end\(arg\);)0(242)100 L (175 serialputs\(buf, n\);)0(243 void)100 L (176 //)0(screenputs\(buf, n\);)16(244 echo\(Rune r, char *buf, int n\))100 L (177 splx\(s\);)0(245 {)100 L (178)0(246 static int ctrlt, pid;)100 L (179 return n;)0(247 extern ulong etext;)100 L (180 })0(248 int x;)100 L (181)0(249)100 L (182 void)0(250 /*)100 L (183 panic\(char *fmt, ...\))0(251)100(* ^p hack)109 L (184 {)0(252)100(*/)109 L (185 int n;)0(253 if\(r==0x10 && cpuserver && !kbd.ctlpoff\){)100 L (186 va_list arg;)0(254)100(lock\(&active\);)116 L (187 char buf[PRINTSIZE];)0(255)100(active.exiting = 1;)116 L (188)0(256)100(unlock\(&active\);)116 L (189 splhi\(\);)0(257 })100 L (190 strcpy\(buf, "panic: "\);)0(258)100 L (191 va_start\(arg, fmt\);)0(259 /*)100 L (192 n = doprint\(buf+strlen\(buf\), buf+sizeof\(buf\), fmt, arg\) - buf;)0(260)100(* ^t hack BUG)109 L (193 va_end\(arg\);)0(261)100(*/)109 L (194 buf[n] = '\\n';)0(262 if\(ctrlt == 2\){)100 L (195 serialputs\(buf, n+1\);)0(263)100(ctrlt = 0;)116 L (196 if\(consdebug\))0(264)100(switch\(r\){)116 L (197)0(consdebug\(\);)16(265)100(case 0x14:)116 L (198 putstrn\(buf, n+1\);)0(266)100(break; /* pass it on */)124 L (199 spllo\(\);)0(267)100(case 's':)116 L (200 prflush\(\);)0(268)100(dumpstack\(\);)124 L (201 dumpstack\(\);)0(269)100(break;)124 L (202)0(270)100(case 'x':)116 L (203 exit\(1\);)0(271)100(xsummary\(\);)124 L (204 })0(272)100(ixsummary\(\);)124 L cleartomark showpage saveobj restore %%EndPage: 113 113 %%Page: 114 114 /saveobj save def mark 114 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 3)l ()l ()l (273)0(mallocsummary\(\);)24(341 /*)100 L (274)0(pagersummary\(\);)24(342 * Put character, possibly a rune, into read queue at interrupt time.)100 L (275)0(break;)24(343 * Called at interrupt time to process a character.)100 L (276)0(case 'd':)16(344 */)100 L (277)0(if\(consdebug == nil\))24(345 int)100 L (278)0(consdebug = rdb;)32(346 kbdputc\(Queue*, int ch\))100 L (279)0(else)24(347 {)100 L (280)0(consdebug = nil;)32(348 int n;)100 L (281)0(print\("consdebug now 0x%p\\n", consdebug\);)24(349 char buf[3];)100 L (282)0(return;)24(350 Rune r;)100 L (283)0(case 'D':)16(351)100 L (284)0(if\(consdebug == nil\))24(352 r = ch;)100 L (285)0(consdebug = rdb;)32(353 n = runetochar\(buf, &r\);)100 L (286)0(consdebug\(\);)24(354 if\(n == 0\))100 L (287)0(return;)24(355)100(return 0;)116 L (288)0(case 'p':)16(356 echo\(r, buf, n\);)100 L (289)0(x = spllo\(\);)24(357 kbd.c = r;)100 L (290)0(procdump\(\);)24(358 qproduce\(kbdq, buf, n\);)100 L (291)0(splx\(x\);)24(359 return 0;)100 L (292)0(return;)24(360 })100 L (293)0(case 'q':)16(361)100 L (294)0(scheddump\(\);)24(362 void)100 L (295)0(break;)24(363 kbdrepeat\(int rep\))100 L (296)0(case 'k':)16(364 {)100 L (297)0(if\(!cpuserver\))24(365 kbd.repeat = rep;)100 L (298)0(killbig\(\);)32(366 kbd.count = 0;)100 L (299)0(break;)24(367 })100 L (300)0(case 'r':)16(368)100 L (301)0(exit\(0\);)24(369 void)100 L (302)0(break;)24(370 kbdclock\(void\))100 L (303)0(})16(371 {)100 L (304 })0(372 if\(kbd.repeat == 0\))100 L (305 else if\(r == 0x14\){)0(373)100(return;)116 L (306)0(ctrlt++;)16(374 if\(kbd.repeat==1 && ++kbd.count>HZ\){)100 L (307)0(return;)16(375)100(kbd.repeat = 2;)116 L (308 })0(376)100(kbd.count = 0;)116 L (309 ctrlt = 0;)0(377)100(return;)116 L (310 if\(kbd.raw\))0(378 })100 L (311)0(return;)16(379 if\(++kbd.count&1\))100 L (312)0(380)100(kbdputc\(kbdq, kbd.c\);)116 L (313 /*)0(381 })100 L (314)0(* finally, the actual echoing)9(382)100 L (315)0(*/)9(383 enum{)100 L (316 if\(r == '\\n'\){)0(384 Qdir,)100 L (317)0(if\(printq\))16(385 Qauth,)100 L (318)0(qiwrite\(printq, "\\r", 1\);)24(386 Qauthcheck,)100 L (319 } else if\(r == 0x15\){)0(387 Qauthent,)100 L (320)0(buf = "^U\\n";)16(388 Qbintime,)100 L (321)0(n = 3;)16(389 Qcons,)100 L (322 })0(390 Qconsctl,)100 L (323 screenputs\(buf, n\);)0(391 Qcputime,)100 L (324 if\(printq\))0(392 Qdrivers,)100 L (325)0(qiwrite\(printq, buf, n\);)16(393 Qkey,)100 L (326 })0(394 Qhostdomain,)100 L (327)0(395 Qhostowner,)100 L (328 /*)0(396 Qnull,)100 L (329 * Called by a uart interrupt for console input.)0(397 Qpgrpid,)100 L (330 *)0(398 Qpid,)100 L (331 * turn '\\r' into '\\n' before putting it into the queue.)0(399 Qppid,)100 L (332 */)0(400 Qrandom,)100 L (333 int)0(401 Qreboot,)100 L (334 kbdcr2nl\(Queue *q, int ch\))0(402 Qswap,)100 L (335 {)0(403 Qsysname,)100 L (336 if\(ch == '\\r'\))0(404 Qsysstat,)100 L (337)0(ch = '\\n';)16(405 Qtime,)100 L (338 return kbdputc\(q, ch\);)0(406 Quser,)100 L (339 })0(407 Qzero,)100 L (340)0(408 };)100 L cleartomark showpage saveobj restore %%EndPage: 114 114 %%Page: 115 115 /saveobj save def mark 115 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 4)l ()l ()l (409)0(477 static Chan*)100 L (410 enum)0(478 consattach\(char *spec\))100 L (411 {)0(479 {)100 L (412 VLNUMSIZE=)0(22,)24(480 return devattach\('c', spec\);)100 L (413 };)0(481 })100 L (414)0(482)100 L (415 static Dirtab consdir[]={)0(483 static int)100 L (416 "authenticate", {Qauth},)0(0,)40(0666,)56(484 conswalk\(Chan *c, char *name\))100 L (417 "authcheck", {Qauthcheck}, 0,)0(0666,)56(485 {)100 L (418 "authenticator", {Qauthent}, 0,)0(0666,)56(486 return devwalk\(c, name, consdir, nelem\(consdir\), devgen\);)100 L (419 "bintime",)0({Qbintime}, 24,)24(0664,)56(487 })100 L (420 "cons",)0({Qcons},)24(0,)40(0660,)56(488)100 L (421 "consctl",)0({Qconsctl}, 0,)24(0220,)56(489 static void)100 L (422 "cputime",)0({Qcputime}, 6*NUMSIZE,)24(0444,)56(490 consstat\(Chan *c, char *dp\))100 L (423 "drivers",)0({Qdrivers}, 0,)24(0644,)56(491 {)100 L (424 "hostdomain", {Qhostdomain}, DOMLEN,)0(0664,)56(492 devstat\(c, dp, consdir, nelem\(consdir\), devgen\);)100 L (425 "hostowner", {Qhostowner}, NAMELEN,)0(0664,)56(493 })100 L (426 "key",)0({Qkey},)24(DESKEYLEN,)40(0622,)56(494)100 L (427 "null",)0({Qnull},)24(0,)40(0666,)56(495 static Chan*)100 L (428 "pgrpid",)0({Qpgrpid},)24(NUMSIZE,)40(0444,)56(496 consopen\(Chan *c, int omode\))100 L (429 "pid",)0({Qpid},)24(NUMSIZE,)40(0444,)56(497 {)100 L (430 "ppid",)0({Qppid},)24(NUMSIZE,)40(0444,)56(498 c->aux = 0;)100 L (431 "random",)0({Qrandom},)24(0,)40(0664,)56(499 switch\(c->qid.path\){)100 L (432 "reboot",)0({Qreboot},)24(0,)40(0664,)56(500 case Qconsctl:)100 L (433 "swap",)0({Qswap},)24(0,)40(0664,)56(501)100(if\(!iseve\(\)\))116 L (434 "sysname",)0({Qsysname}, 0,)24(0664,)56(502)100(error\(Eperm\);)124 L (435 "sysstat",)0({Qsysstat}, 0,)24(0666,)56(503)100(qlock\(&kbd\);)116 L (436 "time",)0({Qtime},)24(NUMSIZE+3*VLNUMSIZE, 0664,)40(504)100(kbd.ctl++;)116 L (437 "user",)0({Quser},)24(NAMELEN,)40(0666,)56(505)100(qunlock\(&kbd\);)116 L (438 "zero",)0({Qzero},)24(0,)40(0444,)56(506)100(break;)116 L (439 };)0(507 })100 L (440)0(508 return devopen\(c, omode, consdir, nelem\(consdir\), devgen\);)100 L (441 int)0(509 })100 L (442 readnum\(ulong off, char *buf, ulong n, ulong val, int size\))0(510)100 L (443 {)0(511 static void)100 L (444 char tmp[64];)0(512 consclose\(Chan *c\))100 L (445)0(513 {)100 L (446 snprint\(tmp, sizeof\(tmp\), "%*.0lud", size-1, val\);)0(514 /* last close of control file turns off raw */)100 L (447 tmp[size-1] = ' ';)0(515 switch\(c->qid.path\){)100 L (448 if\(off >= size\))0(516 case Qconsctl:)100 L (449)0(return 0;)16(517)100(if\(c->flag&COPEN\){)116 L (450 if\(off+n > size\))0(518)100(qlock\(&kbd\);)124 L (451)0(n = size-off;)16(519)100(if\(--kbd.ctl == 0\))124 L (452 memmove\(buf, tmp+off, n\);)0(520)100(kbd.raw = 0;)132 L (453 return n;)0(521)100(qunlock\(&kbd\);)124 L (454 })0(522)100(})116 L (455)0(523)100(break;)116 L (456 int)0(524 case Qauth:)100 L (457 readstr\(ulong off, char *buf, ulong n, char *str\))0(525 case Qauthcheck:)100 L (458 {)0(526 case Qauthent:)100 L (459 int size;)0(527)100(authclose\(c\);)116 L (460)0(528 })100 L (461 size = strlen\(str\);)0(529 })100 L (462 if\(off >= size\))0(530)100 L (463)0(return 0;)16(531 static long)100 L (464 if\(off+n > size\))0(532 consread\(Chan *c, void *buf, long n, vlong off\))100 L (465)0(n = size-off;)16(533 {)100 L (466 memmove\(buf, str+off, n\);)0(534 ulong l;)100 L (467 return n;)0(535 Mach *mp;)100 L (468 })0(536 char *b, *bp;)100 L (469)0(537 char tmp[128];)100(/* must be >= 6*NUMSIZE */)132 L (470 static void)0(538 char *cbuf = buf;)100 L (471 consinit\(void\))0(539 int ch, i, k, id, eol;)100 L (472 {)0(540 vlong offset = off;)100 L (473 todinit\(\);)0(541)100 L (474 randominit\(\);)0(542 if\(n <= 0\))100 L (475 })0(543)100(return n;)116 L (476)0(544 switch\(c->qid.path & ~CHDIR\){)100 L cleartomark showpage saveobj restore %%EndPage: 115 115 %%Page: 116 116 /saveobj save def mark 116 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 5)l ()l ()l (545 case Qdir:)0(613)100(if\(i == TReal\))124 L (546)0(return devdirread\(c, buf, n, consdir, nelem\(consdir\), devgen\);)16(614)100(l = MACHP\(0\)->ticks - l;)132 L (547)0(615)100(l = TK2MS\(l\);)124 L (548 case Qcons:)0(616)100(readnum\(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE\);)124 L (549)0(qlock\(&kbd\);)16(617)100(})116 L (550)0(if\(waserror\(\)\) {)16(618)100(memmove\(buf, tmp+k, n\);)116 L (551)0(qunlock\(&kbd\);)24(619)100(return n;)116 L (552)0(nexterror\(\);)24(620)100 L (553)0(})16(621 case Qpgrpid:)100 L (554)0(if\(kbd.raw\) {)16(622)100(return readnum\(\(ulong\)offset, buf, n, up->pgrp->pgrpid, NUMSIZE\);)116 L (555)0(if\(qcanread\(lineq\)\))24(623)100 L (556)0(n = qread\(lineq, buf, n\);)32(624 case Qpid:)100 L (557)0(else {)24(625)100(return readnum\(\(ulong\)offset, buf, n, up->pid, NUMSIZE\);)116 L (558)0(/* read as much as possible */)32(626)100 L (559)0(do {)32(627 case Qppid:)100 L (560)0(i = qread\(kbdq, cbuf, n\);)40(628)100(return readnum\(\(ulong\)offset, buf, n, up->parentpid, NUMSIZE\);)116 L (561)0(cbuf += i;)40(629)100 L (562)0(n -= i;)40(630 case Qtime:)100 L (563)0(} while \(n>0 && qcanread\(kbdq\)\);)32(631)100(return readtime\(\(ulong\)offset, buf, n\);)116 L (564)0(n = cbuf - \(char*\)buf;)32(632)100 L (565)0(})24(633 case Qbintime:)100 L (566)0(} else {)16(634)100(return readbintime\(buf, n\);)116 L (567)0(while\(!qcanread\(lineq\)\) {)24(635)100 L (568)0(qread\(kbdq, &kbd.line[kbd.x], 1\);)32(636 case Qkey:)100 L (569)0(ch = kbd.line[kbd.x];)32(637)100(return keyread\(buf, n, offset\);)116 L (570)0(if\(kbd.raw\){)32(638)100 L (571)0(qiwrite\(lineq, kbd.line, kbd.x+1\);)40(639 case Qauth:)100 L (572)0(kbd.x = 0;)40(640)100(return authread\(c, cbuf, n\);)116 L (573)0(continue;)40(641)100 L (574)0(})32(642 case Qauthcheck:)100 L (575)0(eol = 0;)32(643)100(return authcheckread\(c, cbuf, n\);)116 L (576)0(switch\(ch\){)32(644)100 L (577)0(case '\\b':)32(645 case Qauthent:)100 L (578)0(if\(kbd.x\))40(646)100(return authentread\(c, cbuf, n\);)116 L (579)0(kbd.x--;)48(647)100 L (580)0(break;)40(648 case Qhostowner:)100 L (581)0(case 0x15:)32(649)100(return readstr\(\(ulong\)offset, buf, n, eve\);)116 L (582)0(kbd.x = 0;)40(650)100 L (583)0(break;)40(651 case Qhostdomain:)100 L (584)0(case '\\n':)32(652)100(return readstr\(\(ulong\)offset, buf, n, hostdomain\);)116 L (585)0(case 0x04:)32(653)100 L (586)0(eol = 1;)40(654 case Quser:)100 L (587)0(default:)32(655)100(return readstr\(\(ulong\)offset, buf, n, up->user\);)116 L (588)0(kbd.line[kbd.x++] = ch;)40(656)100 L (589)0(break;)40(657 case Qnull:)100 L (590)0(})32(658)100(return 0;)116 L (591)0(if\(kbd.x == sizeof\(kbd.line\) || eol\){)32(659)100 L (592)0(if\(ch == 0x04\))40(660 case Qsysstat:)100 L (593)0(kbd.x--;)48(661)100(b = smalloc\(conf.nmach*\(NUMSIZE*8+1\) + 1\);)116(/* +1 for NUL */)164 L (594)0(qwrite\(lineq, kbd.line, kbd.x\);)40(662)100(bp = b;)116 L (595)0(kbd.x = 0;)40(663)100(for\(id = 0; id < 32; id++\) {)116 L (596)0(})32(664)100(if\(active.machs & \(1<cs, NUMSIZE\);)132 L (601)0(poperror\(\);)16(669)100(bp += NUMSIZE;)132 L (602)0(return n;)16(670)100(readnum\(0, bp, NUMSIZE, mp->intr, NUMSIZE\);)132 L (603)0(671)100(bp += NUMSIZE;)132 L (604 case Qcputime:)0(672)100(readnum\(0, bp, NUMSIZE, mp->syscall, NUMSIZE\);)132 L (605)0(k = offset;)16(673)100(bp += NUMSIZE;)132 L (606)0(if\(k >= 6*NUMSIZE\))16(674)100(readnum\(0, bp, NUMSIZE, mp->pfault, NUMSIZE\);)132 L (607)0(return 0;)24(675)100(bp += NUMSIZE;)132 L (608)0(if\(k+n > 6*NUMSIZE\))16(676)100(readnum\(0, bp, NUMSIZE, mp->tlbfault, NUMSIZE\);)132 L (609)0(n = 6*NUMSIZE - k;)24(677)100(bp += NUMSIZE;)132 L (610)0(/* easiest to format in a separate buffer and copy out */)16(678)100(readnum\(0, bp, NUMSIZE, mp->tlbpurge, NUMSIZE\);)132 L (611)0(for\(i=0; i<6 && NUMSIZE*itime[i];)24(680)100(readnum\(0, bp, NUMSIZE, mp->load, NUMSIZE\);)132 L cleartomark showpage saveobj restore %%EndPage: 116 116 %%Page: 117 117 /saveobj save def mark 117 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 6)l ()l ()l (681)0(bp += NUMSIZE;)32(749)100(})116 L (682)0(*bp++ = '\\n';)32(750)100(break;)116 L (683)0(})24(751)100 L (684)0(})16(752 case Qconsctl:)100 L (685)0(n = readstr\(\(ulong\)offset, buf, n, b\);)16(753)100(if\(n >= sizeof\(buf\)\))116 L (686)0(free\(b\);)16(754)100(n = sizeof\(buf\)-1;)124 L (687)0(return n;)16(755)100(strncpy\(buf, a, n\);)116 L (688)0(756)100(buf[n] = 0;)116 L (689 case Qswap:)0(757)100(for\(a = buf; a;\){)116 L (690)0(sprint\(tmp, "%lud/%lud memory %lud/%lud swap\\n",)16(758)100(if\(strncmp\(a, "rawon", 5\) == 0\){)124 L (691)0(palloc.user-palloc.freecount,)24(759)100(qlock\(&kbd\);)132 L (692)0(palloc.user, conf.nswap-swapalloc.free, conf.nswap\);)24(760)100(if\(kbd.x\){)132 L (693)0(761)100(qwrite\(kbdq, kbd.line, kbd.x\);)140 L (694)0(return readstr\(\(ulong\)offset, buf, n, tmp\);)16(762)100(kbd.x = 0;)140 L (695)0(763)100(})132 L (696 case Qsysname:)0(764)100(kbd.raw = 1;)132 L (697)0(return readstr\(\(ulong\)offset, buf, n, sysname\);)16(765)100(qunlock\(&kbd\);)132 L (698)0(766)100(} else if\(strncmp\(a, "rawoff", 6\) == 0\){)124 L (699 case Qrandom:)0(767)100(kbd.raw = 0;)132 L (700)0(return randomread\(buf, n\);)16(768)100(kbd.x = 0;)132 L (701)0(769)100(} else if\(strncmp\(a, "ctlpon", 6\) == 0\){)124 L (702 case Qdrivers:)0(770)100(kbd.ctlpoff = 0;)132 L (703)0(b = malloc\(READSTR\);)16(771)100(} else if\(strncmp\(a, "ctlpoff", 7\) == 0\){)124 L (704)0(if\(b == nil\))16(772)100(kbd.ctlpoff = 1;)132 L (705)0(error\(Enomem\);)24(773)100(})124 L (706)0(n = 0;)16(774)100(if\(a = strchr\(a, ' '\)\))124 L (707)0(for\(i = 0; devtab[i] != nil; i++\))16(775)100(a++;)132 L (708)0(n += snprint\(b+n, READSTR-n, "#%C %s\\n", devtab[i]->dc, devtab[i]->name\); 776)24(})116 L (709)0(n = readstr\(\(ulong\)offset, buf, n, b\);)16(777)100(break;)116 L (710)0(free\(b\);)16(778)100 L (711)0(return n;)16(779 case Qtime:)100 L (712)0(780)100(if\(!iseve\(\)\))116 L (713 case Qzero:)0(781)100(error\(Eperm\);)124 L (714)0(memset\(buf, 0, n\);)16(782)100(return writetime\(a, n\);)116 L (715)0(return n;)16(783)100 L (716)0(784 case Qbintime:)100 L (717 default:)0(785)100(if\(!iseve\(\)\))116 L (718)0(print\("consread %lux\\n", c->qid.path\);)16(786)100(error\(Eperm\);)124 L (719)0(error\(Egreg\);)16(787)100(return writebintime\(a, n\);)116 L (720 })0(788)100 L (721 return -1;)0(/* never reached */)32(789 case Qkey:)100 L (722 })0(790)100(return keywrite\(a, n\);)116 L (723)0(791)100 L (724 static long)0(792 case Qhostowner:)100 L (725 conswrite\(Chan *c, void *va, long n, vlong off\))0(793)100(return hostownerwrite\(a, n\);)116 L (726 {)0(794)100 L (727 char buf[256];)0(795 case Qhostdomain:)100 L (728 long l, bp;)0(796)100(return hostdomainwrite\(a, n\);)116 L (729 char *a = va;)0(797)100 L (730 Mach *mp;)0(798 case Quser:)100 L (731 int id, fd;)0(799)100(return userwrite\(a, n\);)116 L (732 Chan *swc;)0(800)100 L (733 ulong offset = off;)0(801 case Qauth:)100 L (734)0(802)100(return authwrite\(c, a, n\);)116 L (735 switch\(c->qid.path\){)0(803)100 L (736 case Qcons:)0(804 case Qauthcheck:)100 L (737)0(/*)16(805)100(return authcheck\(c, a, n\);)116 L (738)0(* Can't page fault in putstrn, so copy the data locally.)17(806)100 L (739)0(*/)17(807 case Qauthent:)100 L (740)0(l = n;)16(808)100(return authentwrite\(c, a, n\);)116 L (741)0(while\(l > 0\){)16(809)100 L (742)0(bp = l;)24(810 case Qnull:)100 L (743)0(if\(bp > sizeof buf\))24(811)100(break;)116 L (744)0(bp = sizeof buf;)32(812)100 L (745)0(memmove\(buf, a, bp\);)24(813 case Qreboot:)100 L (746)0(putstrn0\(a, bp, 1\);)24(814)100(if\(!iseve\(\)\))116 L (747)0(a += bp;)24(815)100(error\(Eperm\);)124 L (748)0(l -= bp;)24(816)100(if\(strncmp\(a, "reboot", 6\) == 0\){)116 L cleartomark showpage saveobj restore %%EndPage: 117 117 %%Page: 118 118 /saveobj save def mark 118 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 7)l ()l ()l (817)0(print\("conswrite: reboot\\n"\);)24(885 setterm\(char *f\))100 L (818)0(exit\(0\);)24(886 {)100 L (819)0(})16(887 char buf[2*NAMELEN];)100 L (820)0(if\(strncmp\(a, "malloc", 6\) == 0\){)16(/* rsc bug */)56(888)100 L (821)0(a = malloc\(2\);)24(889 sprint\(buf, f, conffile\);)100 L (822)0(strcpy\(a, "hi"\);)24(890 ksetenv\("terminal", buf\);)100 L (823)0(free\(a\);)24(891 })100 L (824)0(a = malloc\(2\);)24(892)100 L (825)0(strcpy\(a, "helo"\);)24(893 Dev consdevtab = {)100 L (826)0(free\(a\);)24(894 'c',)100 L (827)0(panic\("not reached conswrite"\);)24(895 "cons",)100 L (828)0(})16(896)100 L (829)0(if\(strncmp\(a, "panic", 5\) == 0\))16(897 devreset,)100 L (830)0(panic\("/dev/reboot"\);)24(898 consinit,)100 L (831)0(break;)16(899 consattach,)100 L (832)0(900 devclone,)100 L (833 case Qsysstat:)0(901 conswalk,)100 L (834)0(for\(id = 0; id < 32; id++\) {)16(902 consstat,)100 L (835)0(if\(active.machs & \(1<cs = 0;)32(905 consclose,)100 L (838)0(mp->intr = 0;)32(906 consread,)100 L (839)0(mp->syscall = 0;)32(907 devbread,)100 L (840)0(mp->pfault = 0;)32(908 conswrite,)100 L (841)0(mp->tlbfault = 0;)32(909 devbwrite,)100 L (842)0(mp->tlbpurge = 0;)32(910 devremove,)100 L (843)0(})24(911 devwstat,)100 L (844)0(})16(912 };)100 L (845)0(break;)16(913)100 L (846)0(914 struct Rb)100 L (847 case Qswap:)0(915 {)100 L (848)0(if\(n >= sizeof buf\))16(916 QLock;)100 L (849)0(error\(Egreg\);)24(917 Rendez producer;)100 L (850)0(memmove\(buf, va, n\); /* so we can NUL-terminate */)16(918 Rendez consumer;)100 L (851)0(buf[n] = 0;)16(919 ulong randomcount;)100 L (852)0(/* start a pager if not already started */)16(920 uchar buf[1024];)100 L (853)0(if\(strncmp\(buf, "start", 5\) == 0\){)16(921 uchar *ep;)100 L (854)0(kickpager\(\);)24(922 uchar *rp;)100 L (855)0(break;)24(923 uchar *wp;)100 L (856)0(})16(924 uchar next;)100 L (857)0(if\(cpuserver && !iseve\(\)\))16(925 uchar wakeme;)100 L (858)0(error\(Eperm\);)24(926 ushort bits;)100 L (859)0(if\(buf[0]<'0' || '9'= NAMELEN\))16(937 nrand\(int n\))100 L (870)0(error\(Ebadarg\);)24(938 {)100 L (871)0(strncpy\(sysname, a, n\);)16(939 if\(rb.randn == 0\))100 L (872)0(sysname[n] = 0;)16(940)100(seedrand\(\);)116 L (873)0(if\(sysname[n-1] == '\\n'\))16(941 rb.randn = rb.randn*1103515245 + 12345 + MACHP\(0\)->ticks;)100 L (874)0(sysname[n-1] = 0;)24(942 return \(rb.randn>>16\) % n;)100 L (875)0(break;)16(943 })100 L (876)0(944)100 L (877 default:)0(945 int)100 L (878)0(print\("conswrite: %lud\\n", c->qid.path\);)16(946 rand\(void\))100 L (879)0(error\(Egreg\);)16(947 {)100 L (880 })0(948 nrand\(1\);)100 L (881 return n;)0(949 return rb.randn;)100 L (882 })0(950 })100 L (883)0(951)100 L (884 void)0(952)100 L cleartomark showpage saveobj restore %%EndPage: 118 118 %%Page: 119 119 /saveobj save def mark 119 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 8)l ()l ()l (953 static int)0(1021 /*)100 L (954 rbnotfull\(void*\))0(1022 * consume random bytes from a circular buffer)100 L (955 {)0(1023 */)100 L (956 int i;)0(1024 static ulong)100 L (957)0(1025 randomread\(void *xp, ulong n\))100 L (958 i = rb.rp - rb.wp;)0(1026 {)100 L (959 return i != 1 && i != \(1 - sizeof\(rb.buf\)\);)0(1027 uchar *e, *p;)100 L (960 })0(1028 ulong x;)100 L (961)0(1029)100 L (962 static int)0(1030 p = xp;)100 L (963 rbnotempty\(void*\))0(1031)100 L (964 {)0(1032 if\(waserror\(\)\){)100 L (965 return rb.wp != rb.rp;)0(1033)100(qunlock\(&rb\);)116 L (966 })0(1034)100(nexterror\(\);)116 L (967)0(1035 })100 L (968 void)0(1036)100 L (969 genrandom\(void*\))0(1037 qlock\(&rb\);)100 L (970 {)0(1038 for\(e = p + n; p < e; \){)100 L (971 up->basepri = PriNormal;)0(1039)100(if\(rb.wp == rb.rp\){)116 L (972 up->priority = up->basepri;)0(1040)100(rb.wakeme = 1;)124 L (973)0(1041)100(wakeup\(&rb.producer\);)124 L (974 for\(;;\){)0(1042)100(sleep\(&rb.consumer, rbnotempty, 0\);)124 L (975)0(for\(;;\))16(1043)100(rb.wakeme = 0;)124 L (976)0(if\(++rb.randomcount > 100000\))24(1044)100(continue;)124 L (977)0(break;)32(1045)100(})116 L (978)0(if\(anyhigher\(\)\))16(1046)100 L (979)0(sched\(\);)24(1047)100(/*)116 L (980)0(if\(!rbnotfull\(0\)\))16(1048)100(* beating clocks will be precictable if)117 L (981)0(sleep\(&rb.producer, rbnotfull, 0\);)24(1049)100(* they are synchronized. Use a cheap pseudo)117 L (982 })0(1050)100(* random number generator to obscure any cycles.)117 L (983 })0(1051)100(*/)117 L (984)0(1052)100(x = rb.randn*1103515245 ^ *rb.rp;)116 L (985 /*)0(1053)100(*p++ = rb.randn = x;)116 L (986 * produce random bits in a circular buffer)0(1054)100 L (987 */)0(1055)100(if\(rb.rp+1 == rb.ep\))116 L (988 static void)0(1056)100(rb.rp = rb.buf;)124 L (989 randomclock\(void\))0(1057)100(else)116 L (990 {)0(1058)100(rb.rp = rb.rp+1;)124 L (991 if\(rb.randomcount == 0 || !rbnotfull\(0\)\))0(1059 })100 L (992)0(return;)16(1060 qunlock\(&rb\);)100 L (993)0(1061 poperror\(\);)100 L (994 rb.bits = \(rb.bits<<2\) ^ rb.randomcount;)0(1062)100 L (995 rb.randomcount = 0;)0(1063 wakeup\(&rb.producer\);)100 L (996)0(1064)100 L (997 rb.next++;)0(1065 return n;)100 L (998 if\(rb.next != 8/2\))0(1066 })100 L (999)0(return;)16(1067)100 L (1000 rb.next = 0;)0(1068 static uvlong uvorder = 0x0001020304050607ULL;)100 L (1001)0(1069)100 L (1002 *rb.wp ^= rb.bits;)0(1070 static uchar*)100 L (1003 if\(rb.wp+1 == rb.ep\))0(1071 le2vlong\(vlong *to, uchar *f\))100 L (1004)0(rb.wp = rb.buf;)16(1072 {)100 L (1005 else)0(1073 uchar *t, *o;)100 L (1006)0(rb.wp = rb.wp+1;)16(1074 int i;)100 L (1007)0(1075)100 L (1008 if\(rb.wakeme\))0(1076 t = \(uchar*\)to;)100 L (1009)0(wakeup\(&rb.consumer\);)16(1077 o = \(uchar*\)&uvorder;)100 L (1010 })0(1078 for\(i = 0; i < sizeof\(vlong\); i++\))100 L (1011)0(1079)100(t[o[i]] = f[i];)116 L (1012 static void)0(1080 return f+sizeof\(vlong\);)100 L (1013 randominit\(void\))0(1081 })100 L (1014 {)0(1082)100 L (1015 addclock0link\(randomclock\);)0(1083 static uchar*)100 L (1016 rb.ep = rb.buf + sizeof\(rb.buf\);)0(1084 vlong2le\(uchar *t, vlong from\))100 L (1017 rb.rp = rb.wp = rb.buf;)0(1085 {)100 L (1018 kproc\("genrandom", genrandom, 0\);)0(1086 uchar *f, *o;)100 L (1019 })0(1087 int i;)100 L (1020)0(1088)100 L cleartomark showpage saveobj restore %%EndPage: 119 119 %%Page: 120 120 /saveobj save def mark 120 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 9)l ()l ()l (1089 f = \(uchar*\)&from;)0(1157 {)100 L (1090 o = \(uchar*\)&uvorder;)0(1158 char b[13];)100 L (1091 for\(i = 0; i < sizeof\(vlong\); i++\))0(1159 long i;)100 L (1092)0(t[i] = f[o[i]];)16(1160 vlong now;)100 L (1093 return t+sizeof\(vlong\);)0(1161)100 L (1094 })0(1162 if\(n >= sizeof\(b\)\))100 L (1095)0(1163)100(error\(Ebadtimectl\);)116 L (1096 static long order = 0x00010203;)0(1164 strncpy\(b, buf, n\);)100 L (1097)0(1165 b[n] = 0;)100 L (1098 static uchar*)0(1166 i = strtol\(b, 0, 0\);)100 L (1099 le2long\(long *to, uchar *f\))0(1167 if\(i <= 0\))100 L (1100 {)0(1168)100(error\(Ebadtimectl\);)116 L (1101 uchar *t, *o;)0(1169 now = i*1000000000LL;)100 L (1102 int i;)0(1170 todset\(now, 0, 0\);)100 L (1103)0(1171 return n;)100 L (1104 t = \(uchar*\)to;)0(1172 })100 L (1105 o = \(uchar*\)ℴ)0(1173)100 L (1106 for\(i = 0; i < sizeof\(long\); i++\))0(1174 /*)100 L (1107)0(t[o[i]] = f[i];)16(1175 * read binary time info. all numbers are little endian.)100 L (1108 return f+sizeof\(long\);)0(1176 * ticks and nsec are syncronized.)100 L (1109 })0(1177 */)100 L (1110)0(1178 static int)100 L (1111 static uchar*)0(1179 readbintime\(char *buf, int n\))100 L (1112 long2le\(uchar *t, long from\))0(1180 {)100 L (1113 {)0(1181 int i;)100 L (1114 uchar *f, *o;)0(1182 vlong nsec, ticks;)100 L (1115 int i;)0(1183 uchar *b = \(uchar*\)buf;)100 L (1116)0(1184)100 L (1117 f = \(uchar*\)&from;)0(1185 i = 0;)100 L (1118 o = \(uchar*\)ℴ)0(1186 if\(fasthz == 0LL\))100 L (1119 for\(i = 0; i < sizeof\(long\); i++\))0(1187)100(fastticks\(\(uvlong*\)&fasthz\);)116 L (1120)0(t[i] = f[o[i]];)16(1188 nsec = todget\(&ticks\);)100 L (1121 return t+sizeof\(long\);)0(1189 if\(n >= 3*sizeof\(uvlong\)\){)100 L (1122 })0(1190)100(vlong2le\(b+2*sizeof\(uvlong\), fasthz\);)116 L (1123)0(1191)100(i += sizeof\(uvlong\);)116 L (1124 char *Ebadtimectl = "bad time control";)0(1192 })100 L (1125)0(1193 if\(n >= 2*sizeof\(uvlong\)\){)100 L (1126 /*)0(1194)100(vlong2le\(b+sizeof\(uvlong\), ticks\);)116 L (1127 * like the old #c/time but with added info. Return)0(1195)100(i += sizeof\(uvlong\);)116 L (1128 *)0(1196 })100 L (1129 *)0(secs nanosecs)16(fastticks)40(fasthz)56(1197 if\(n >= 8\){)100 L (1130 */)0(1198)100(vlong2le\(b, nsec\);)116 L (1131 static int)0(1199)100(i += sizeof\(vlong\);)116 L (1132 readtime\(ulong off, char *buf, int n\))0(1200 })100 L (1133 {)0(1201 return i;)100 L (1134 vlong nsec, ticks;)0(1202 })100 L (1135 long sec;)0(1203)100 L (1136 char str[7*NUMSIZE+4]; // extra 4 bytes are null plus doprint)0(1204 /*)100 L (1137)0(// reserving space for a frigging UTF)32(1205 * set any of the following)100 L (1138)0(// char)32(1206 *)100(- time in nsec)116 L (1139)0(1207 *)100(- nsec trim applied over some seconds)116 L (1140 nsec = todget\(&ticks\);)0(1208 *)100(- clock frequency)116 L (1141 if\(fasthz == 0LL\))0(1209 */)100 L (1142)0(fastticks\(\(uvlong*\)&fasthz\);)16(1210 static int)100 L (1143 sec = nsec/1000000000ULL;)0(1211 writebintime\(char *buf, int n\))100 L (1144 snprint\(str, sizeof\(str\), "%*.0lud %*.0llud %*.0llud %*.0llud ",)0(1212 {)100 L (1145)0(NUMSIZE-1, sec,)16(1213 uchar *p;)100 L (1146)0(VLNUMSIZE-1, nsec,)16(1214 vlong delta;)100 L (1147)0(VLNUMSIZE-1, ticks,)16(1215 long period;)100 L (1148)0(VLNUMSIZE-1, fasthz\);)16(1216)100 L (1149 return readstr\(off, buf, n, str\);)0(1217 n--;)100 L (1150 })0(1218 p = \(uchar*\)buf + 1;)100 L (1151)0(1219 switch\(*buf\){)100 L (1152 /*)0(1220 case 'n':)100 L (1153 * set the time in seconds)0(1221)100(if\(n < sizeof\(vlong\)\))116 L (1154 */)0(1222)100(error\(Ebadtimectl\);)124 L (1155 static int)0(1223)100(le2vlong\(&delta, p\);)116 L (1156 writetime\(char *buf, int n\))0(1224)100(todset\(delta, 0, 0\);)116 L cleartomark showpage saveobj restore %%EndPage: 120 120 %%Page: 121 121 /saveobj save def mark 121 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devcons.c Page 10)l ()l ()l (1225)0(break;)16 L (1226 case 'd':)l (1227)0(if\(n < sizeof\(vlong\)+sizeof\(long\)\))16 L (1228)0(error\(Ebadtimectl\);)24 L (1229)0(p = le2vlong\(&delta, p\);)16 L (1230)0(le2long\(&period, p\);)16 L (1231)0(todset\(-1, delta, period\);)16 L (1232)0(break;)16 L (1233 case 'f':)l (1234)0(if\(n < sizeof\(uvlong\)\))16 L (1235)0(error\(Ebadtimectl\);)24 L (1236)0(le2vlong\(&fasthz, p\);)16 L (1237)0(todsetfreq\(fasthz\);)16 L (1238)0(break;)16 L (1239 })l (1240 return n;)l (1241 })l cleartomark showpage saveobj restore %%EndPage: 121 121 %%Page: 122 122 /saveobj save def mark 122 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devkprof.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(kprof.maxpc = \(ulong\)etext;)108 L (2 #include "../port/lib.h")0(70)100(kprof.nbuf = \(kprof.maxpc-kprof.minpc\) >> LRES;)108 L (3 #include "mem.h")0(71)100(n = kprof.nbuf*SZ;)108 L (4 #include "dat.h")0(72)100(if\(kprof.buf == 0\) {)108 L (5 #include "fns.h")0(73)100(kprof.buf = xalloc\(n\);)116 L (6 #include "../port/error.h")0(74)100(if\(kprof.buf == 0\))116 L (7)0(75)100(error\(Enomem\);)124 L (8)0(76)100(})108 L (9 #define LRES 3)0(/* log of PC resolution */)40(77)100(kproftab[0].length = n;)108 L (10 #define SZ)0(4)24(/* sizeof of count cell; well known as 4 */)40(78)100(return devattach\('T', spec\);)108 L (11)0(79 })100 L (12 struct)0(80)100 L (13 {)0(81 static int)100 L (14)0(int minpc;)8(82 kprofwalk\(Chan *c, char *name\))100 L (15)0(int maxpc;)8(83 {)100 L (16)0(int nbuf;)8(84)100(return devwalk\(c, name, kproftab, nelem\(kproftab\), devgen\);)108 L (17)0(int time;)8(85 })100 L (18)0(ulong *buf;)8(86)100 L (19 }kprof;)0(87 static void)100 L (20)0(88 kprofstat\(Chan *c, char *db\))100 L (21 enum{)0(89 {)100 L (22)0(Kprofdirqid,)8(90)100(devstat\(c, db, kproftab, nelem\(kproftab\), devgen\);)108 L (23)0(Kprofdataqid,)8(91 })100 L (24)0(Kprofctlqid,)8(92)100 L (25 };)0(93 static Chan*)100 L (26 Dirtab kproftab[]={)0(94 kprofopen\(Chan *c, int omode\))100 L (27)0("kpdata",)8({Kprofdataqid},)24(0,)48(0600,)56(95 {)100 L (28)0("kpctl",)8({Kprofctlqid},)24(0,)48(0600,)56(96)100(if\(c->qid.path == CHDIR\){)108 L (29 };)0(97)100(if\(omode != OREAD\))116 L (30)0(98)100(error\(Eperm\);)124 L (31 static void)0(99)100(})108 L (32 _kproftimer\(ulong pc\))0(100 c->mode = openmode\(omode\);)100 L (33 {)0(101 c->flag |= COPEN;)100 L (34)0(extern void spldone\(void\);)8(102 c->offset = 0;)100 L (35)0(103 return c;)100 L (36)0(if\(kprof.time == 0\))8(104 })100 L (37)0(return;)16(105)100 L (38)0(/*)8(106 static void)100 L (39)0(* if the pc is coming out of spllo or splx,)9(107 kprofclose\(Chan*\))100 L (40)0(* use the pc saved when we went splhi.)9(108 {)100 L (41)0(*/)9(109 })100 L (42)0(if\(pc>=\(ulong\)spllo && pc<=\(ulong\)spldone\))8(110)100 L (43)0(pc = m->splpc;)16(111 static long)100 L (44)0(112 kprofread\(Chan *c, void *va, long n, vlong off\))100 L (45)0(kprof.buf[0] += TK2MS\(1\);)8(113 {)100 L (46)0(if\(kprof.minpc<=pc && pc>= LRES;)16(116 uchar *a, *ea;)100 L (49)0(kprof.buf[pc] += TK2MS\(1\);)16(117 ulong offset = off;)100 L (50)0(}else)8(118)100 L (51)0(kprof.buf[1] += TK2MS\(1\);)16(119 switch\(c->qid.path & ~CHDIR\){)100 L (52 })0(120 case Kprofdirqid:)100 L (53)0(121)100(return devdirread\(c, va, n, kproftab, nelem\(kproftab\), devgen\);)116 L (54 static void)0(122)100 L (55 kprofinit\(void\))0(123 case Kprofdataqid:)100 L (56 {)0(124)100(end = kprof.nbuf*SZ;)116 L (57)0(if\(SZ != sizeof kprof.buf[0]\))8(125)100(if\(offset & \(SZ-1\)\))116 L (58)0(panic\("kprof size"\);)16(126)100(error\(Ebadarg\);)124 L (59)0(kproftimer = _kproftimer;)8(127)100(if\(offset >= end\){)116 L (60 })0(128)100(n = 0;)124 L (61)0(129)100(break;)124 L (62 static Chan*)0(130)100(})116 L (63 kprofattach\(char *spec\))0(131)100(if\(offset+n > end\))116 L (64 {)0(132)100(n = end-offset;)124 L (65)0(ulong n;)8(133)100(n &= ~\(SZ-1\);)116 L (66)0(134)100(a = va;)116 L (67)0(/* allocate when first used */)8(135)100(ea = a + n;)116 L (68)0(kprof.minpc = KTZERO;)8(136)100(bp = kprof.buf + offset/SZ;)116 L cleartomark showpage saveobj restore %%EndPage: 122 122 %%Page: 123 123 /saveobj save def mark 123 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devkprof.c Page 2)l ()l ()l (137)0(while\(a < ea\){)16 L (138)0(w = *bp++;)24 L (139)0(*a++ = w>>24;)24 L (140)0(*a++ = w>>16;)24 L (141)0(*a++ = w>>8;)24 L (142)0(*a++ = w>>0;)24 L (143)0(})16 L (144)0(break;)16 L (145)l (146 default:)l (147)0(n = 0;)16 L (148)0(break;)16 L (149 })l (150 return n;)l (151 })l (152)l (153 static long)l (154 kprofwrite\(Chan *c, void *a, long n, vlong\))l (155 {)l (156 switch\(\(int\)\(c->qid.path&~CHDIR\)\){)l (157 case Kprofctlqid:)l (158)0(if\(strncmp\(a, "startclr", 8\) == 0\){)16 L (159)0(memset\(\(char *\)kprof.buf, 0, kprof.nbuf*SZ\);)24 L (160)0(kprof.time = 1;)24 L (161)0(}else if\(strncmp\(a, "start", 5\) == 0\))16 L (162)0(kprof.time = 1;)24 L (163)0(else if\(strncmp\(a, "stop", 4\) == 0\))16 L (164)0(kprof.time = 0;)24 L (165)0(break;)16 L (166 default:)l (167)0(error\(Ebadusefd\);)16 L (168 })l (169 return n;)l (170 })l (171)l (172 Dev kprofdevtab = {)l (173 'T',)l (174 "kprof",)l (175)l (176 devreset,)l (177 kprofinit,)l (178 kprofattach,)l (179 devclone,)l (180 kprofwalk,)l (181 kprofstat,)l (182 kprofopen,)l (183 devcreate,)l (184 kprofclose,)l (185 kprofread,)l (186 devbread,)l (187 kprofwrite,)l (188 devbwrite,)l (189 devremove,)l (190 devwstat,)l (191 };)l cleartomark showpage saveobj restore %%EndPage: 123 123 %%Page: 124 124 /saveobj save def mark 124 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 1)l ()l ()l (1 #include "u.h")0(69)100 L (2 #include "../port/lib.h")0(70)100(cinit\(\);)108 L (3 #include "mem.h")0(71 })100 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73 static Chan*)100 L (6 #include "../port/error.h")0(74 mntattach\(char *muxattach\))100 L (7)0(75 {)100 L (8 struct Mntrpc)0(76)100(Mnt *m;)108 L (9 {)0(77)100(Chan *c, *mc;)108 L (10)0(Chan* c;)8(/* Channel for whom we are working */)32(78)100(char buf[NAMELEN];)108 L (11)0(Mntrpc* list;)8(/* Free/pending list */)32(79)100(struct bogus{)108 L (12)0(Fcall request;)8(/* Outgoing file system protocol message */)32(80)100(Chan *chan;)116 L (13)0(Fcall reply;)8(/* Incoming reply */)32(81)100(char *spec;)116 L (14)0(Mnt* m;)8(/* Mount device during rpc */)32(82)100(int flags;)116 L (15)0(Rendez r;)8(/* Place to hang out */)32(83)100(}bogus;)108 L (16)0(char* rpc;)8(/* I/O Data buffer */)32(84)100 L (17)0(char done;)8(/* Rpc completed */)32(85)100(bogus = *\(\(struct bogus *\)muxattach\);)108 L (18)0(uvlong stime;)8(/* start time for mnt statistics */)32(86)100(c = bogus.chan;)108 L (19)0(ulong reqlen;)8(/* request length for mnt statistics */)32(87)100 L (20)0(ulong replen;)8(/* reply length for mnt statistics */)32(88)100(lock\(&mntalloc\);)108 L (21)0(Mntrpc* flushed;)8(/* message this one flushes */)32(89)100(for\(m = mntalloc.list; m; m = m->list\) {)108 L (22 };)0(90)100(if\(m->c == c && m->id\) {)116 L (23)0(91)100(lock\(m\);)124 L (24 struct Mntalloc)0(92)100(if\(m->id && m->ref > 0 && m->c == c\) {)124 L (25 {)0(93)100(m->ref++;)132 L (26)0(Lock;)8(94)100(unlock\(m\);)132 L (27)0(Mnt* list;)8(/* Mount devices in use */)32(95)100(unlock\(&mntalloc\);)132 L (28)0(Mnt* mntfree;)8(/* Free list */)32(96)100(c = mntchan\(\);)132 L (29)0(Mntrpc* rpcfree;)8(97)100(if\(waserror\(\)\) {)132 L (30)0(int nrpcfree;)8(98)100(chanfree\(c\);)140 L (31)0(int nrpcused;)8(99)100(nexterror\(\);)140 L (32)0(ulong id;)8(100)100(})132 L (33)0(int rpctag;)8(101)100(mattach\(m, c, bogus.spec\);)132 L (34 }mntalloc;)0(102)100(poperror\(\);)132 L (35)0(103)100(if\(bogus.flags&MCACHE\))132 L (36 void)0(mattach\(Mnt*, Chan*, char*\);)16(104)100(c->flag |= CCACHE;)140 L (37 void)0(mntauth\(Mnt*, Mntrpc*, char*, ushort\);)16(105)100(return c;)132 L (38 Mnt*)0(mntchk\(Chan*\);)16(106)100(})124 L (39 void)0(mntdirfix\(uchar*, Chan*\);)16(107)100(unlock\(m\);)124 L (40 Mntrpc* mntflushalloc\(Mntrpc*\);)0(108)100(})116 L (41 void)0(mntflushfree\(Mnt*, Mntrpc*\);)16(109 })100 L (42 void)0(mntfree\(Mntrpc*\);)16(110)100 L (43 void)0(mntgate\(Mnt*\);)16(111 m = mntalloc.mntfree;)100 L (44 void)0(mntpntfree\(Mnt*\);)16(112 if\(m != 0\))100 L (45 void)0(mntqrm\(Mnt*, Mntrpc*\);)16(113)100(mntalloc.mntfree = m->list;)116 L (46 Mntrpc* mntralloc\(Chan*\);)0(114 else {)100 L (47 long)0(mntrdwr\(int, Chan*, void*, long, vlong\);)16(115)100(m = malloc\(sizeof\(Mnt\)\);)116 L (48 long)0(mnt9prdwr\(int, Chan*, void*, long, vlong\);)16(116)100(if\(m == 0\) {)116 L (49 void)0(mntrpcread\(Mnt*, Mntrpc*\);)16(117)100(unlock\(&mntalloc\);)124 L (50 void)0(mountio\(Mnt*, Mntrpc*\);)16(118)100(exhausted\("mount devices"\);)124 L (51 void)0(mountmux\(Mnt*, Mntrpc*\);)16(119)100(})116 L (52 void)0(mountrpc\(Mnt*, Mntrpc*\);)16(120 })100 L (53 int)0(rpcattn\(void*\);)16(121 m->list = mntalloc.list;)100 L (54 void)0(mclose\(Mnt*, Chan*\);)16(122 mntalloc.list = m;)100 L (55 Chan* mntchan\(void\);)0(123 m->id = mntalloc.id++;)100 L (56)0(124 unlock\(&mntalloc\);)100 L (57 void \(*mntstats\)\(int, Chan*, uvlong, ulong\);)0(125)100 L (58)0(126 lock\(m\);)100 L (59 enum)0(127 m->ref = 1;)100 L (60 {)0(128 m->queue = 0;)100 L (61)0(Tagspace)8(= 1,)24(129 m->rip = 0;)100 L (62 };)0(130 m->c = c;)100 L (63)0(131 m->c->flag |= CMSG;)100 L (64 static void)0(132 if\(strncmp\(bogus.spec, "mntblk=", 7\) == 0\) {)100 L (65 mntreset\(void\))0(133)100(m->blocksize = strtoul\(bogus.spec+7, 0, 0\);)116 L (66 {)0(134)100(if\(m->blocksize > MAXFDATA\))116 L (67)0(mntalloc.id = 1;)8(135)100(m->blocksize = MAXFDATA;)124 L (68)0(mntalloc.rpctag = Tagspace;)8(136)100(print\("mount blk %d\\n", m->blocksize\);)116 L cleartomark showpage saveobj restore %%EndPage: 124 124 %%Page: 125 125 /saveobj save def mark 125 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 2)l ()l ()l (137)0(bogus.spec = "";)16(205 c->mntptr = m;)100 L (138 })0(206)100 L (139 else)0(207 if\(waserror\(\)\) {)100 L (140)0(m->blocksize = MAXFDATA;)16(208)100(mntfree\(r\);)116 L (141 m->flags = bogus.flags & ~MCACHE;)0(209)100(nexterror\(\);)116 L (142)0(210 })100 L (143 incref\(m->c\);)0(211)100 L (144)0(212 r->request.type = Tattach;)100 L (145 sprint\(buf, "#M%lud", m->id\);)0(213 r->request.fid = c->fid;)100 L (146)0(214 memmove\(r->request.uname, up->user, NAMELEN\);)100 L (147 unlock\(m\);)0(215 strncpy\(r->request.aname, spec, NAMELEN\);)100 L (148)0(216 id = authrequest\(m->c->session, &r->request\);)100 L (149 c = mntchan\(\);)0(217 mountrpc\(m, r\);)100 L (150 if\(waserror\(\)\) {)0(218 authreply\(m->c->session, id, &r->reply\);)100 L (151)0(mclose\(m, c\);)16(219)100 L (152)0(/* Close must not be called since it will)16(220 c->qid = r->reply.qid;)100 L (153)0(* call mnt recursively)17(221 c->mchan = m->c;)100 L (154)0(*/)17(222 c->mqid = c->qid;)100 L (155)0(chanfree\(c\);)16(223)100 L (156)0(nexterror\(\);)16(224 poperror\(\);)100 L (157 })0(225 mntfree\(r\);)100 L (158)0(226 })100 L (159 mattach\(m, c, bogus.spec\);)0(227)100 L (160 poperror\(\);)0(228 static Chan*)100 L (161)0(229 mntclone\(Chan *c, Chan *nc\))100 L (162 /*)0(230 {)100 L (163)0(* Detect a recursive mount for a mount point served by exportfs.)9(231 Mnt *m;)100 L (164)0(* If CHDIR is clear in the returned qid, the foreign server is)9(232 Mntrpc *r;)100 L (165)0(* requesting the mount point be folded into the connection)9(233 int alloc = 0;)100 L (166)0(* to the exportfs. In this case the remote mount driver does)9(234)100 L (167)0(* the multiplexing.)9(235 m = mntchk\(c\);)100 L (168)0(*/)9(236 r = mntralloc\(c\);)100 L (169 mc = m->c;)0(237 if\(nc == 0\) {)100 L (170 if\(mc->type == devno\('M', 0\) && \(c->qid.path&CHDIR\) == 0\) {)0(238)100(nc = newchan\(\);)116 L (171)0(mclose\(m, c\);)16(239)100(alloc = 1;)116 L (172)0(c->qid.path |= CHDIR;)16(240 })100 L (173)0(c->mntptr = mc->mntptr;)16(241 if\(waserror\(\)\) {)100 L (174)0(c->mchan = c->mntptr->c;)16(242)100(mntfree\(r\);)116 L (175)0(c->mqid = c->qid;)16(243)100(if\(alloc\))116 L (176)0(incref\(c->mntptr\);)16(244)100(cclose\(nc\);)124 L (177 })0(245)100(nexterror\(\);)116 L (178)0(246 })100 L (179 if\(bogus.flags & MCACHE\))0(247)100 L (180)0(c->flag |= CCACHE;)16(248 r->request.type = Tclone;)100 L (181)0(249 r->request.fid = c->fid;)100 L (182 return c;)0(250 r->request.newfid = nc->fid;)100 L (183 })0(251 mountrpc\(m, r\);)100 L (184)0(252)100 L (185 Chan*)0(253 devclone\(c, nc\);)100 L (186 mntchan\(void\))0(254 nc->mqid = c->qid;)100 L (187 {)0(255 incref\(m\);)100 L (188 Chan *c;)0(256)100 L (189)0(257 USED\(alloc\);)100 L (190 c = devattach\('M', 0\);)0(258 poperror\(\);)100 L (191 lock\(&mntalloc\);)0(259 mntfree\(r\);)100 L (192 c->dev = mntalloc.id++;)0(260 return nc;)100 L (193 unlock\(&mntalloc\);)0(261 })100 L (194)0(262)100 L (195 return c;)0(263 static int)100 L (196 })0(264 mntwalk\(Chan *c, char *name\))100 L (197)0(265 {)100 L (198 void)0(266 Mnt *m;)100 L (199 mattach\(Mnt *m, Chan *c, char *spec\))0(267 Mntrpc *r;)100 L (200 {)0(268)100 L (201 ulong id;)0(269 m = mntchk\(c\);)100 L (202 Mntrpc *r;)0(270 r = mntralloc\(c\);)100 L (203)0(271 if\(waserror\(\)\) {)100 L (204 r = mntralloc\(0\);)0(272)100(mntfree\(r\);)116 L cleartomark showpage saveobj restore %%EndPage: 125 125 %%Page: 126 126 /saveobj save def mark 126 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 3)l ()l ()l (273)0(return 0;)16(341 {)100 L (274 })0(342 Mnt *m;)100 L (275 r->request.type = Twalk;)0(343 Mntrpc *r;)100 L (276 r->request.fid = c->fid;)0(344)100 L (277 strncpy\(r->request.name, name, NAMELEN\);)0(345 m = mntchk\(c\);)100 L (278 mountrpc\(m, r\);)0(346 r = mntralloc\(c\);)100 L (279)0(347 if\(waserror\(\)\) {)100 L (280 c->qid = r->reply.qid;)0(348)100(mntfree\(r\);)116 L (281)0(349)100(nexterror\(\);)116 L (282 poperror\(\);)0(350 })100 L (283 mntfree\(r\);)0(351 r->request.type = Tcreate;)100 L (284 return 1;)0(352 r->request.fid = c->fid;)100 L (285 })0(353 r->request.mode = omode;)100 L (286)0(354 r->request.perm = perm;)100 L (287 static void)0(355 strncpy\(r->request.name, name, NAMELEN\);)100 L (288 mntstat\(Chan *c, char *dp\))0(356 mountrpc\(m, r\);)100 L (289 {)0(357)100 L (290 Mnt *m;)0(358 c->qid = r->reply.qid;)100 L (291 Mntrpc *r;)0(359 c->flag |= COPEN;)100 L (292)0(360 c->mode = openmode\(omode\);)100 L (293 m = mntchk\(c\);)0(361 poperror\(\);)100 L (294 r = mntralloc\(c\);)0(362 mntfree\(r\);)100 L (295 if\(waserror\(\)\) {)0(363)100 L (296)0(mntfree\(r\);)16(364 if\(c->flag & CCACHE\))100 L (297)0(nexterror\(\);)16(365)100(copen\(c\);)116 L (298 })0(366 })100 L (299 r->request.type = Tstat;)0(367)100 L (300 r->request.fid = c->fid;)0(368 static void)100 L (301 mountrpc\(m, r\);)0(369 mntclunk\(Chan *c, int t\))100 L (302)0(370 {)100 L (303 memmove\(dp, r->reply.stat, DIRLEN\);)0(371 Mnt *m;)100 L (304 mntdirfix\(\(uchar*\)dp, c\);)0(372 Mntrpc *r;)100 L (305 poperror\(\);)0(373)100 L (306 mntfree\(r\);)0(374 m = mntchk\(c\);)100 L (307 })0(375 r = mntralloc\(c\);)100 L (308)0(376 if\(waserror\(\)\){)100 L (309 static Chan*)0(377)100(mntfree\(r\);)116 L (310 mntopen\(Chan *c, int omode\))0(378)100(mclose\(m, c\);)116 L (311 {)0(379)100(nexterror\(\);)116 L (312 Mnt *m;)0(380 })100 L (313 Mntrpc *r;)0(381)100 L (314)0(382 r->request.type = t;)100 L (315 m = mntchk\(c\);)0(383 r->request.fid = c->fid;)100 L (316 r = mntralloc\(c\);)0(384 mountrpc\(m, r\);)100 L (317 if\(waserror\(\)\) {)0(385 mntfree\(r\);)100 L (318)0(mntfree\(r\);)16(386 mclose\(m, c\);)100 L (319)0(nexterror\(\);)16(387 poperror\(\);)100 L (320 })0(388 })100 L (321 r->request.type = Topen;)0(389)100 L (322 r->request.fid = c->fid;)0(390 void)100 L (323 r->request.mode = omode;)0(391 mclose\(Mnt *m, Chan*\))100 L (324 mountrpc\(m, r\);)0(392 {)100 L (325)0(393 Mntrpc *q, *r;)100 L (326 c->qid = r->reply.qid;)0(394)100 L (327 c->offset = 0;)0(395 if\(decref\(m\) != 0\))100 L (328 c->mode = openmode\(omode\);)0(396)100(return;)116 L (329 c->flag |= COPEN;)0(397)100 L (330 poperror\(\);)0(398 for\(q = m->queue; q; q = r\) {)100 L (331 mntfree\(r\);)0(399)100(r = q->list;)116 L (332)0(400)100(mntfree\(q\);)116 L (333 if\(c->flag & CCACHE\))0(401 })100 L (334)0(copen\(c\);)16(402 m->id = 0;)100 L (335)0(403 cclose\(m->c\);)100 L (336 return c;)0(404 mntpntfree\(m\);)100 L (337 })0(405 })100 L (338)0(406)100 L (339 static void)0(407 void)100 L (340 mntcreate\(Chan *c, char *name, int omode, ulong perm\))0(408 mntpntfree\(Mnt *m\))100 L cleartomark showpage saveobj restore %%EndPage: 126 126 %%Page: 127 127 /saveobj save def mark 127 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 4)l ()l ()l (409 {)0(477)100 L (410 Mnt *f, **l;)0(478 p = buf;)100 L (411)0(479 if\(cache\) {)100 L (412 lock\(&mntalloc\);)0(480)100(nc = cread\(c, buf, n, off\);)116 L (413 l = &mntalloc.list;)0(481)100(if\(nc > 0\) {)116 L (414 for\(f = *l; f; f = f->list\) {)0(482)100(n -= nc;)124 L (415)0(if\(f == m\) {)16(483)100(if\(n == 0\))124 L (416)0(*l = m->list;)24(484)100(return nc;)132 L (417)0(break;)24(485)100(p += nc;)124 L (418)0(})16(486)100(off += nc;)124 L (419)0(l = &f->list;)16(487)100(})116 L (420 })0(488)100(n = mntrdwr\(Tread, c, p, n, off\);)116 L (421)0(489)100(cupdate\(c, p, n, off\);)116 L (422 m->list = mntalloc.mntfree;)0(490)100(return n + nc;)116 L (423 mntalloc.mntfree = m;)0(491 })100 L (424 unlock\(&mntalloc\);)0(492)100 L (425 })0(493 n = mntrdwr\(Tread, c, buf, n, off\);)100 L (426)0(494 if\(isdir\) {)100 L (427 static void)0(495)100(for\(e = &p[n]; p < e; p += DIRLEN\))116 L (428 mntclose\(Chan *c\))0(496)100(mntdirfix\(p, c\);)124 L (429 {)0(497 })100 L (430 mntclunk\(c, Tclunk\);)0(498)100 L (431 })0(499 return n;)100 L (432)0(500 })100 L (433 static void)0(501)100 L (434 mntremove\(Chan *c\))0(502 long)100 L (435 {)0(503 mntwrite9p\(Chan *c, void *buf, long n, vlong off\))100 L (436 mntclunk\(c, Tremove\);)0(504 {)100 L (437 })0(505 return mnt9prdwr\(Twrite, c, buf, n, off\);)100 L (438)0(506 })100 L (439 static void)0(507)100 L (440 mntwstat\(Chan *c, char *dp\))0(508 static long)100 L (441 {)0(509 mntwrite\(Chan *c, void *buf, long n, vlong off\))100 L (442 Mnt *m;)0(510 {)100 L (443 Mntrpc *r;)0(511 return mntrdwr\(Twrite, c, buf, n, off\);)100 L (444)0(512 })100 L (445 m = mntchk\(c\);)0(513)100 L (446 r = mntralloc\(c\);)0(514 long)100 L (447 if\(waserror\(\)\) {)0(515 mnt9prdwr\(int type, Chan *c, void *buf, long n, vlong off\))100 L (448)0(mntfree\(r\);)16(516 {)100 L (449)0(nexterror\(\);)16(517 Mnt *m;)100 L (450 })0(518 ulong nr;)100 L (451 r->request.type = Twstat;)0(519 Mntrpc *r;)100 L (452 r->request.fid = c->fid;)0(520)100 L (453 memmove\(r->request.stat, dp, DIRLEN\);)0(521 if\(n > MAXRPC-32\) {)100 L (454 mountrpc\(m, r\);)0(522)100(if\(type == Twrite\))116 L (455 poperror\(\);)0(523)100(error\("write9p too long"\);)124 L (456 mntfree\(r\);)0(524)100(n = MAXRPC-32;)116 L (457 })0(525 })100 L (458)0(526)100 L (459 long)0(527 m = mntchk\(c\);)100 L (460 mntread9p\(Chan *c, void *buf, long n, vlong off\))0(528 r = mntralloc\(c\);)100 L (461 {)0(529 if\(waserror\(\)\) {)100 L (462 return mnt9prdwr\(Tread, c, buf, n, off\);)0(530)100(mntfree\(r\);)116 L (463 })0(531)100(nexterror\(\);)116 L (464)0(532 })100 L (465 static long)0(533 r->request.type = type;)100 L (466 mntread\(Chan *c, void *buf, long n, vlong off\))0(534 r->request.fid = c->fid;)100 L (467 {)0(535 r->request.offset = off;)100 L (468 uchar *p, *e;)0(536 r->request.data = buf;)100 L (469 int nc, cache, isdir;)0(537 r->request.count = n;)100 L (470)0(538 mountrpc\(m, r\);)100 L (471 isdir = 0;)0(539 nr = r->reply.count;)100 L (472 cache = c->flag & CCACHE;)0(540 if\(nr > r->request.count\))100 L (473 if\(c->qid.path & CHDIR\) {)0(541)100(nr = r->request.count;)116 L (474)0(cache = 0;)16(542)100 L (475)0(isdir = 1;)16(543 if\(type == Tread\))100 L (476 })0(544)100(memmove\(buf, r->reply.data, nr\);)116 L cleartomark showpage saveobj restore %%EndPage: 127 127 %%Page: 128 128 /saveobj save def mark 128 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 5)l ()l ()l (545)0(613)100 L (546 poperror\(\);)0(614 mountio\(m, r\);)100 L (547 mntfree\(r\);)0(615)100 L (548 return nr;)0(616 t = r->reply.type;)100 L (549 })0(617 switch\(t\) {)100 L (550)0(618 case Rerror:)100 L (551 long)0(619)100(error\(r->reply.ename\);)116 L (552 mntrdwr\(int type, Chan *c, void *buf, long n, vlong off\))0(620 case Rflush:)100 L (553 {)0(621)100(error\(Eintr\);)116 L (554 Mnt *m;)0(622 default:)100 L (555 Mntrpc *r;)0(623)100(if\(t == r->request.type+1\))116 L (556 char *uba;)0(624)100(break;)124 L (557 int cache;)0(625)100(print\("mnt: proc %s %lud: mismatch rep 0x%lux tag %d fid %d T%d R%d rp %d\\n",)116 L (558 ulong cnt, nr, nreq;)0(626)100(up->text, up->pid,)124 L (559)0(627)100(r, r->request.tag, r->request.fid, r->request.type, r->reply.type,)124 L (560 m = mntchk\(c\);)0(628)100(r->reply.tag\);)124 L (561 uba = buf;)0(629)100(error\(Emountrpc\);)116 L (562 cnt = 0;)0(630 })100 L (563 cache = c->flag & CCACHE;)0(631 })100 L (564 if\(c->qid.path & CHDIR\))0(632)100 L (565)0(cache = 0;)16(633 void)100 L (566 for\(;;\) {)0(634 mountio\(Mnt *m, Mntrpc *r\))100 L (567)0(r = mntralloc\(c\);)16(635 {)100 L (568)0(if\(waserror\(\)\) {)16(636 int n;)100 L (569)0(mntfree\(r\);)24(637)100 L (570)0(nexterror\(\);)24(638 while\(waserror\(\)\) {)100 L (571)0(})16(639)100(if\(m->rip == up\))116 L (572)0(r->request.type = type;)16(640)100(mntgate\(m\);)124 L (573)0(r->request.fid = c->fid;)16(641)100(if\(strcmp\(up->error, Eintr\) != 0\){)116 L (574)0(r->request.offset = off;)16(642)100(mntflushfree\(m, r\);)124 L (575)0(r->request.data = uba;)16(643)100(nexterror\(\);)124 L (576)0(if\(n > m->blocksize\){)16(644)100(})116 L (577)0(if\(c->qid.path & CHDIR\))24(645)100(r = mntflushalloc\(r\);)116 L (578)0(r->request.count = \(m->blocksize/DIRLEN\)*DIRLEN;)32(646 })100 L (579)0(else)24(647)100 L (580)0(r->request.count = m->blocksize;)32(648 lock\(m\);)100 L (581)0(} else)16(649 r->m = m;)100 L (582)0(r->request.count = n;)24(650 r->list = m->queue;)100 L (583)0(mountrpc\(m, r\);)16(651 m->queue = r;)100 L (584)0(nreq = r->request.count;)16(652 unlock\(m\);)100 L (585)0(nr = r->reply.count;)16(653)100 L (586)0(if\(nr > nreq\))16(654 /* Transmit a file system rpc */)100 L (587)0(nr = nreq;)24(655 n = convS2M\(&r->request, r->rpc\);)100 L (588)0(656 if\(n < 0\))100 L (589)0(if\(type == Tread\))16(657)100(panic\("bad message type in mountio"\);)116 L (590)0(memmove\(uba, r->reply.data, nr\);)24(658 if\(devtab[m->c->type]->dc == L'M'\){)100 L (591)0(else if\(cache\))16(659)100(if\(mnt9prdwr\(Twrite, m->c, r->rpc, n, 0\) != n\))116 L (592)0(cwrite\(c, \(uchar*\)uba, nr, off\);)24(660)100(error\(Emountrpc\);)124 L (593)0(661 }else{)100 L (594)0(poperror\(\);)16(662)100(if\(devtab[m->c->type]->write\(m->c, r->rpc, n, 0\) != n\))116 L (595)0(mntfree\(r\);)16(663)100(error\(Emountrpc\);)124 L (596)0(off += nr;)16(664 })100 L (597)0(uba += nr;)16(665 r->stime = fastticks\(nil\);)100 L (598)0(cnt += nr;)16(666 r->reqlen = n;)100 L (599)0(n -= nr;)16(667)100 L (600)0(if\(nr != nreq || n == 0 || up->nnote\))16(668 /* Gate readers onto the mount point one at a time */)100 L (601)0(break;)24(669 for\(;;\) {)100 L (602 })0(670)100(lock\(m\);)116 L (603 return cnt;)0(671)100(if\(m->rip == 0\))116 L (604 })0(672)100(break;)124 L (605)0(673)100(unlock\(m\);)116 L (606 void)0(674)100(sleep\(&r->r, rpcattn, r\);)116 L (607 mountrpc\(Mnt *m, Mntrpc *r\))0(675)100(if\(r->done\){)116 L (608 {)0(676)100(poperror\(\);)124 L (609 int t;)0(677)100(mntflushfree\(m, r\);)124 L (610)0(678)100(return;)124 L (611 r->reply.tag = 0;)0(679)100(})116 L (612 r->reply.type = Tmax; /* can't ever be a valid message type */)0(680 })100 L cleartomark showpage saveobj restore %%EndPage: 128 128 %%Page: 129 129 /saveobj save def mark 129 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 6)l ()l ()l (681 m->rip = up;)0(749)100(})124 L (682 unlock\(m\);)0(750)100(q->done = 1;)124 L (683 while\(r->done == 0\) {)0(751)100(unlock\(m\);)124 L (684)0(mntrpcread\(m, r\);)16(752)100(if\(mntstats != nil\))124 L (685)0(mountmux\(m, r\);)16(753)100(\(*mntstats\)\(q->request.type,)132 L (686 })0(754)100(m->c, q->stime,)140 L (687 mntgate\(m\);)0(755)100(q->reqlen + r->replen\);)140 L (688 poperror\(\);)0(756)100(if\(q != r\))124 L (689 mntflushfree\(m, r\);)0(757)100(wakeup\(&q->r\);)132 L (690 })0(758)100(return;)124 L (691)0(759)100(})116 L (692 void)0(760)100(l = &q->list;)116 L (693 mntrpcread\(Mnt *m, Mntrpc *r\))0(761 })100 L (694 {)0(762 unlock\(m\);)100 L (695 int n;)0(763 })100 L (696)0(764)100 L (697 for\(;;\) {)0(765 /*)100 L (698)0(r->reply.type = 0;)16(766 * Create a new flush request and chain the previous)100 L (699)0(r->reply.tag = 0;)16(767 * requests from it)100 L (700)0(if\(devtab[m->c->type]->dc == L'M'\))16(768 */)100 L (701)0(n = mnt9prdwr\(Tread, m->c, r->rpc, MAXRPC, 0\);)24(769 Mntrpc*)100 L (702)0(else)16(770 mntflushalloc\(Mntrpc *r\))100 L (703)0(n = devtab[m->c->type]->read\(m->c, r->rpc, MAXRPC, 0\);)24(771 {)100 L (704)0(if\(n == 0\))16(772 Mntrpc *fr;)100 L (705)0(continue;)24(773)100 L (706)0(774 fr = mntralloc\(0\);)100 L (707)0(r->replen = n;)16(775)100 L (708)0(if\(convM2S\(r->rpc, &r->reply, n\) != 0\))16(776 fr->request.type = Tflush;)100 L (709)0(return;)24(777 if\(r->request.type == Tflush\))100 L (710 })0(778)100(fr->request.oldtag = r->request.oldtag;)116 L (711 })0(779 else)100 L (712)0(780)100(fr->request.oldtag = r->request.tag;)116 L (713 void)0(781 fr->flushed = r;)100 L (714 mntgate\(Mnt *m\))0(782)100 L (715 {)0(783 return fr;)100 L (716 Mntrpc *q;)0(784 })100 L (717)0(785)100 L (718 lock\(m\);)0(786 /*)100 L (719 m->rip = 0;)0(787 * Free a chain of flushes. Remove each unanswered)100 L (720 for\(q = m->queue; q; q = q->list\) {)0(788 * flush and the original message from the unanswered)100 L (721)0(if\(q->done == 0\))16(789 * request queue. Mark the original message as done)100 L (722)0(if\(wakeup\(&q->r\)\))16(790 * and if it hasn't been answered set the reply to to)100 L (723)0(break;)24(791 * Rflush.)100 L (724 })0(792 */)100 L (725 unlock\(m\);)0(793 void)100 L (726 })0(794 mntflushfree\(Mnt *m, Mntrpc *r\))100 L (727)0(795 {)100 L (728 void)0(796 Mntrpc *fr;)100 L (729 mountmux\(Mnt *m, Mntrpc *r\))0(797)100 L (730 {)0(798 while\(r\){)100 L (731 char *dp;)0(799)100(fr = r->flushed;)116 L (732 Mntrpc **l, *q;)0(800)100(if\(!r->done\){)116 L (733)0(801)100(r->reply.type = Rflush;)124 L (734 lock\(m\);)0(802)100(mntqrm\(m, r\);)124 L (735 l = &m->queue;)0(803)100(})116 L (736 for\(q = *l; q; q = q->list\) {)0(804)100(if\(fr\))116 L (737)0(/* look for a reply to a message */)16(805)100(mntfree\(r\);)124 L (738)0(if\(q->request.tag == r->reply.tag\) {)16(806)100(r = fr;)116 L (739)0(*l = q->list;)24(807 })100 L (740)0(if\(q != r\) {)24(808 })100 L (741)0(/*)32(809)100 L (742)0(* Completed someone else.)33(810 Mntrpc*)100 L (743)0(* Trade pointers to receive buffer.)33(811 mntralloc\(Chan *c\))100 L (744)0(*/)33(812 {)100 L (745)0(dp = q->rpc;)32(813 Mntrpc *new;)100 L (746)0(q->rpc = r->rpc;)32(814)100 L (747)0(r->rpc = dp;)32(815 lock\(&mntalloc\);)100 L (748)0(q->reply = r->reply;)32(816 new = mntalloc.rpcfree;)100 L cleartomark showpage saveobj restore %%EndPage: 129 129 %%Page: 130 130 /saveobj save def mark 130 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmnt.c Page 7)l ()l ()l (817 if\(new == nil\){)0(885 {)100 L (818)0(new = malloc\(sizeof\(Mntrpc\)\);)16(886 Mnt *m;)100 L (819)0(if\(new == nil\) {)16(887)100 L (820)0(unlock\(&mntalloc\);)24(888 m = c->mntptr;)100 L (821)0(exhausted\("mount rpc header"\);)24(889)100 L (822)0(})16(890 /*)100 L (823)0(/*)16(891)100(* Was it closed and reused)109 L (824)0(* The header is split from the data buffer as)17(892)100(*/)109 L (825)0(* mountmux may swap the buffer with another header.)17(893 if\(m->id == 0 || m->id >= c->dev\))100 L (826)0(*/)17(894)100(error\(Eshutdown\);)116 L (827)0(new->rpc = mallocz\(MAXRPC, 0\);)16(895)100 L (828)0(if\(new->rpc == nil\){)16(896 return m;)100 L (829)0(free\(new\);)24(897 })100 L (830)0(unlock\(&mntalloc\);)24(898)100 L (831)0(exhausted\("mount rpc buffer"\);)24(899 void)100 L (832)0(})16(900 mntdirfix\(uchar *dirbuf, Chan *c\))100 L (833)0(new->request.tag = mntalloc.rpctag++;)16(901 {)100 L (834 })0(902 int r;)100 L (835 else {)0(903)100 L (836)0(mntalloc.rpcfree = new->list;)16(904 r = devtab[c->type]->dc;)100 L (837)0(mntalloc.nrpcfree--;)16(905 dirbuf[DIRLEN-4] = r>>0;)100 L (838 })0(906 dirbuf[DIRLEN-3] = r>>8;)100 L (839 mntalloc.nrpcused++;)0(907 dirbuf[DIRLEN-2] = c->dev;)100 L (840 unlock\(&mntalloc\);)0(908 dirbuf[DIRLEN-1] = c->dev>>8;)100 L (841 new->c = c;)0(909 })100 L (842 new->done = 0;)0(910)100 L (843 new->flushed = nil;)0(911 int)100 L (844 return new;)0(912 rpcattn\(void *v\))100 L (845 })0(913 {)100 L (846)0(914 Mntrpc *r;)100 L (847 void)0(915)100 L (848 mntfree\(Mntrpc *r\))0(916 r = v;)100 L (849 {)0(917 return r->done || r->m->rip == 0;)100 L (850 lock\(&mntalloc\);)0(918 })100 L (851 if\(mntalloc.nrpcfree >= 10\){)0(919)100 L (852)0(free\(r->rpc\);)16(920 Dev mntdevtab = {)100 L (853)0(free\(r\);)16(921 'M',)100 L (854 })0(922 "mnt",)100 L (855 else{)0(923)100 L (856)0(r->list = mntalloc.rpcfree;)16(924 mntreset,)100 L (857)0(mntalloc.rpcfree = r;)16(925 devinit,)100 L (858)0(mntalloc.nrpcfree++;)16(926 mntattach,)100 L (859 })0(927 mntclone,)100 L (860 mntalloc.nrpcused--;)0(928 mntwalk,)100 L (861 unlock\(&mntalloc\);)0(929 mntstat,)100 L (862 })0(930 mntopen,)100 L (863)0(931 mntcreate,)100 L (864 void)0(932 mntclose,)100 L (865 mntqrm\(Mnt *m, Mntrpc *r\))0(933 mntread,)100 L (866 {)0(934 devbread,)100 L (867 Mntrpc **l, *f;)0(935 mntwrite,)100 L (868)0(936 devbwrite,)100 L (869 lock\(m\);)0(937 mntremove,)100 L (870 r->done = 1;)0(938 mntwstat,)100 L (871)0(939 };)100 L (872 l = &m->queue;)l (873 for\(f = *l; f; f = f->list\) {)l (874)0(if\(f == r\) {)16 L (875)0(*l = r->list;)24 L (876)0(break;)24 L (877)0(})16 L (878)0(l = &f->list;)16 L (879 })l (880 unlock\(m\);)l (881 })l (882)l (883 Mnt*)l (884 mntchk\(Chan *c\))l cleartomark showpage saveobj restore %%EndPage: 130 130 %%Page: 131 131 /saveobj save def mark 131 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmouse.c Page 1)l ()l ()l (1 #include "u.h")0(69)100 L (2 #include "../port/lib.h")0(70 static uchar buttonmap[8] = {)100 L (3 #include "mem.h")0(71)100(0, 1, 2, 3, 4, 5, 6, 7,)108 L (4 #include "dat.h")0(72 };)100 L (5 #include "fns.h")0(73 static int mouseswap;)100 L (6 #include "../port/error.h")0(74)100 L (7)0(75 extern Memimage*)100(gscreen;)132 L (8 #define Image IMAGE)0(76)100 L (9 #include )0(77 static void)100 L (10 #include )0(78 mousereset\(void\))100 L (11 #include )0(79 {)100 L (12 #include "screen.h")0(80)100(if\(!conf.monitor\))108 L (13)0(81)100(return;)116 L (14 typedef struct Mouseinfo Mouseinfo;)0(82)100 L (15 typedef struct Mousestate Mousestate;)0(83)100(curs = arrow;)108 L (16)0(84)100(Cursortocursor\(&arrow\);)108 L (17 struct Mousestate)0(85)100(addclock0link\(mouseclock\);)108 L (18 {)0(86 })100 L (19)0(Point xy;)8(/* mouse.xy */)40(87)100 L (20)0(int buttons;)8(/* mouse.buttons */)40(88 static void)100 L (21)0(ulong counter;)8(/* increments every update */)32(89 mouseinit\(void\))100 L (22)0(ulong msec; /* time of last event */)8(90 {)100 L (23 };)0(91)100(if\(!conf.monitor\))108 L (24)0(92)100(return;)116 L (25 struct Mouseinfo)0(93)100 L (26 {)0(94)100(cursoron\(1\);)108 L (27)0(Mousestate;)8(95 })100 L (28)0(int dx;)8(96)100 L (29)0(int dy;)8(97 static Chan*)100 L (30)0(int track;)8(/* dx & dy updated */)32(98 mouseattach\(char *spec\))100 L (31)0(int redraw;)8(/* update cursor on screen */)32(99 {)100 L (32)0(ulong lastcounter; /* value when /dev/mouse read */)8(100 if\(!conf.monitor\))100 L (33)0(Rendez r;)8(101)100(error\(Egreg\);)116 L (34)0(Ref;)8(102 return devattach\('m', spec\);)100 L (35)0(QLock;)8(103 })100 L (36)0(int open;)8(104)100 L (37)0(int inopen;)8(105 static Chan*)100 L (38)0(int acceleration;)8(106 mouseclone\(Chan *c, Chan *nc\))100 L (39)0(int maxacc;)8(107 {)100 L (40)0(Mousestate)8(queue[16];)24(/* circular buffer of click events */)40(108 nc = devclone\(c, nc\);)100 L (41)0(int ri; /* read index into queue */)8(109 if\(c->qid.path != CHDIR\))100 L (42)0(int wi; /* write index into queue */)8(110)100(incref\(&mouse\);)116 L (43)0(uchar qfull; /* queue is full */)8(111 return nc;)100 L (44 };)0(112 })100 L (45)0(113)100 L (46 Mouseinfo mouse;)0(114 static int)100 L (47 Cursorinfo)0(cursor;)24(115 mousewalk\(Chan *c, char *name\))100 L (48 int)0(mouseshifted;)24(116 {)100 L (49 Cursor)0(curs;)24(117 return devwalk\(c, name, mousedir, nelem\(mousedir\), devgen\);)100 L (50)0(118 })100 L (51 void)0(Cursortocursor\(Cursor*\);)16(119)100 L (52 int)0(mousechanged\(void*\);)16(120 static void)100 L (53 static void mouseclock\(void\);)0(121 mousestat\(Chan *c, char *db\))100 L (54)0(122 {)100 L (55 enum{)0(123 devstat\(c, db, mousedir, nelem\(mousedir\), devgen\);)100 L (56)0(Qdir,)8(124 })100 L (57)0(Qcursor,)8(125)100 L (58)0(Qmouse,)8(126 static Chan*)100 L (59)0(Qmousein,)8(127 mouseopen\(Chan *c, int omode\))100 L (60)0(Qmousectl,)8(128 {)100 L (61 };)0(129 switch\(c->qid.path\){)100 L (62)0(130 case CHDIR:)100 L (63 static Dirtab mousedir[]={)0(131)100(if\(omode != OREAD\))116 L (64)0("cursor",)8({Qcursor},)24(0,)40(0666,)64(132)100(error\(Eperm\);)124 L (65)0("mouse",)8({Qmouse},)24(0,)40(0666,)64(133)100(break;)116 L (66)0("mousein",)8({Qmousein}, 0,)24(0220,)64(134 case Qmouse:)100 L (67)0("mousectl", {Qmousectl}, 0,)8(0220,)64(135)100(lock\(&mouse\);)116 L (68 };)0(136)100(if\(mouse.open\){)116 L cleartomark showpage saveobj restore %%EndPage: 131 131 %%Page: 132 132 /saveobj save def mark 132 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmouse.c Page 2)l ()l ()l (137)0(unlock\(&mouse\);)24(205 case CHDIR:)100 L (138)0(error\(Einuse\);)24(206)100(return devdirread\(c, va, n, mousedir, nelem\(mousedir\), devgen\);)116 L (139)0(})16(207)100 L (140)0(mouse.open = 1;)16(208 case Qcursor:)100 L (141)0(mouse.ref++;)16(209)100(if\(offset != 0\))116 L (142)0(unlock\(&mouse\);)16(210)100(return 0;)124 L (143)0(break;)16(211)100(if\(n < 2*4+2*2*16\))116 L (144 case Qmousein:)0(212)100(error\(Eshort\);)124 L (145)0(error\("disabled"\);)16(213)100(n = 2*4+2*2*16;)116 L (146)0(lock\(&mouse\);)16(214)100(lock\(&cursor\);)116 L (147)0(if\(mouse.inopen\){)16(215)100(BPLONG\(p+0, curs.offset.x\);)116 L (148)0(unlock\(&mouse\);)24(216)100(BPLONG\(p+4, curs.offset.y\);)116 L (149)0(error\(Einuse\);)24(217)100(memmove\(p+8, curs.clr, 2*16\);)116 L (150)0(})16(218)100(memmove\(p+40, curs.set, 2*16\);)116 L (151)0(mouse.inopen = 1;)16(219)100(unlock\(&cursor\);)116 L (152)0(unlock\(&mouse\);)16(220)100(return n;)116 L (153)0(break;)16(221)100 L (154 default:)0(222 case Qmouse:)100 L (155)0(incref\(&mouse\);)16(223)100(while\(mousechanged\(0\) == 0\))116 L (156 })0(224)100(sleep\(&mouse.r, mousechanged, 0\);)124 L (157 c->mode = openmode\(omode\);)0(225)100 L (158 c->flag |= COPEN;)0(226)100(mouse.qfull = 0;)116 L (159 c->offset = 0;)0(227)100 L (160 return c;)0(228)100(/*)116 L (161 })0(229)100(* No lock of the indicies is necessary here, because ri is only)117 L (162)0(230)100(* updated by us, and there is only one mouse reader)117 L (163 static void)0(231)100(* at a time. I suppose that more than one process)117 L (164 mousecreate\(Chan*, char*, int, ulong\))0(232)100(* could try to read the fd at one time, but such behavior)117 L (165 {)0(233)100(* is degenerate and already violates the calling)117 L (166 if\(!conf.monitor\))0(234)100(* conventions for sleep above.)117 L (167)0(error\(Egreg\);)16(235)100(*/)117 L (168 error\(Eperm\);)0(236)100(if\(mouse.ri != mouse.wi\) {)116 L (169 })0(237)100(m = mouse.queue[mouse.ri];)124 L (170)0(238)100(if\(++mouse.ri == nelem\(mouse.queue\)\))124 L (171 static void)0(239)100(mouse.ri = 0;)132 L (172 mouseclose\(Chan *c\))0(240)100(} else {)116 L (173 {)0(241)100(while\(!canlock\(&cursor\)\))124 L (174 if\(c->qid.path!=CHDIR && \(c->flag&COPEN\)\){)0(242)100(tsleep\(&up->sleep, return0, 0, TK2MS\(1\)\);)132 L (175)0(lock\(&mouse\);)16(243)100 L (176)0(if\(c->qid.path == Qmouse\))16(244)100(m = mouse.Mousestate;)124 L (177)0(mouse.open = 0;)24(245)100(unlock\(&cursor\);)124 L (178)0(else if\(c->qid.path == Qmousein\){)16(246)100(})116 L (179)0(mouse.inopen = 0;)24(247)100 L (180)0(unlock\(&mouse\);)24(248)100(sprint\(buf, "m%11d %11d %11d %11lud",)116 L (181)0(return;)24(249)100(m.xy.x, m.xy.y,)124 L (182)0(})16(250)100(buttonmap[m.buttons&7],)124 L (183)0(if\(--mouse.ref == 0\){)16(251)100(m.msec\);)124 L (184)0(cursoroff\(1\);)24(252)100(mouse.lastcounter = m.counter;)116 L (185)0(curs = arrow;)24(253)100(if\(n > 1+4*12\))116 L (186)0(Cursortocursor\(&arrow\);)24(254)100(n = 1+4*12;)124 L (187)0(cursoron\(1\);)24(255)100(memmove\(va, buf, n\);)116 L (188)0(})16(256)100(return n;)116 L (189)0(unlock\(&mouse\);)16(257 })100 L (190 })0(258 return 0;)100 L (191 })0(259 })100 L (192)0(260)100 L (193)0(261 static void)100 L (194 static long)0(262 setbuttonmap\(char* map\))100 L (195 mouseread\(Chan *c, void *va, long n, vlong off\))0(263 {)100 L (196 {)0(264 int i, x, one, two, three;)100 L (197 char buf[4*12+1];)0(265)100 L (198 uchar *p;)0(266 one = two = three = 0;)100 L (199 static int map[8] = {0, 4, 2, 6, 1, 5, 3, 7 };)0(267 for\(i = 0; i < 3; i++\){)100 L (200 ulong offset = off;)0(268)100(if\(map[i] == 0\))116 L (201 Mousestate m;)0(269)100(error\(Ebadarg\);)124 L (202)0(270)100(if\(map[i] == '1'\){)116 L (203 p = va;)0(271)100(if\(one\))124 L (204 switch\(c->qid.path\){)0(272)100(error\(Ebadarg\);)132 L cleartomark showpage saveobj restore %%EndPage: 132 132 %%Page: 133 133 /saveobj save def mark 133 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmouse.c Page 3)l ()l ()l (273)0(one = 1< sizeof buf-1\))116 L (297)0(x |= two;)24(365)100(n = sizeof buf -1;)124 L (298)0(if\(i & 4\))16(366)100(memmove\(buf, va, n\);)116 L (299)0(x |= three;)24(367)100(buf[n] = 0;)116 L (300)0(buttonmap[x] = i;)16(368)100(p = 0;)116 L (301 })0(369)100(pt.x = strtol\(buf+1, &p, 0\);)116 L (302 })0(370)100(if\(p == 0\))116 L (303)0(371)100(error\(Eshort\);)124 L (304 static long)0(372)100(pt.y = strtol\(p, &p, 0\);)116 L (305 mousewrite\(Chan *c, void *va, long n, vlong\))0(373)100(if\(p == 0\))116 L (306 {)0(374)100(error\(Eshort\);)124 L (307 char *p;)0(375)100(b = strtol\(p, &p, 0\);)116 L (308 Point pt;)0(376)100(mousetrack\(b, pt.x, pt.y\);)116 L (309 char buf[64], *field[3];)0(377)100(return n;)116 L (310 int nf, b;)0(378)100 L (311)0(379 case Qmouse:)100 L (312 p = va;)0(380)100(if\(n > sizeof buf-1\))116 L (313 switch\(c->qid.path\){)0(381)100(n = sizeof buf -1;)124 L (314 case CHDIR:)0(382)100(memmove\(buf, va, n\);)116 L (315)0(error\(Eisdir\);)16(383)100(buf[n] = 0;)116 L (316)0(384)100(p = 0;)116 L (317 case Qcursor:)0(385)100(pt.x = strtoul\(buf+1, &p, 0\);)116 L (318)0(cursoroff\(1\);)16(386)100(if\(p == 0\))116 L (319)0(if\(n < 2*4+2*2*16\){)16(387)100(error\(Eshort\);)124 L (320)0(curs = arrow;)24(388)100(pt.y = strtoul\(p, 0, 0\);)116 L (321)0(Cursortocursor\(&arrow\);)24(389)100(qlock\(&mouse\);)116 L (322)0(}else{)16(390)100(if\(ptinrect\(pt, gscreen->r\)\){)116 L (323)0(n = 2*4+2*2*16;)24(391)100(mouse.xy = pt;)124 L (324)0(curs.offset.x = BGLONG\(p+0\);)24(392)100(mouse.redraw = 1;)124 L (325)0(curs.offset.y = BGLONG\(p+4\);)24(393)100(mouse.track = 1;)124 L (326)0(memmove\(curs.clr, p+8, 2*16\);)24(394)100(mouseclock\(\);)124 L (327)0(memmove\(curs.set, p+40, 2*16\);)24(395)100(})116 L (328)0(Cursortocursor\(&curs\);)24(396)100(qunlock\(&mouse\);)116 L (329)0(})16(397)100(return n;)116 L (330)0(qlock\(&mouse\);)16(398 })100 L (331)0(mouse.redraw = 1;)16(399)100 L (332)0(mouseclock\(\);)16(400 error\(Egreg\);)100 L (333)0(qunlock\(&mouse\);)16(401 return -1;)100 L (334)0(cursoron\(1\);)16(402 })100 L (335)0(return n;)16(403)100 L (336)0(404 Dev mousedevtab = {)100 L (337 case Qmousectl:)0(405 'm',)100 L (338)0(if\(n >= sizeof\(buf\)\))16(406 "mouse",)100 L (339)0(n = sizeof\(buf\)-1;)24(407)100 L (340)0(strncpy\(buf, va, n\);)16(408 mousereset,)100 L cleartomark showpage saveobj restore %%EndPage: 133 133 %%Page: 134 134 /saveobj save def mark 134 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmouse.c Page 4)l ()l ()l (409 mouseinit,)0(477 default:)100 L (410 mouseattach,)0(478)100(x *= mouse.maxacc;)116 L (411 mouseclone,)0(479)100(break;)116 L (412 mousewalk,)0(480 })100 L (413 mousestat,)0(481 return sign*x;)100 L (414 mouseopen,)0(482 })100 L (415 mousecreate,)0(483)100 L (416 mouseclose,)0(484 /*)100 L (417 mouseread,)0(485 * called at interrupt level to update the structure and)100 L (418 devbread,)0(486 * awaken any waiting procs.)100 L (419 mousewrite,)0(487 */)100 L (420 devbwrite,)0(488 void)100 L (421 devremove,)0(489 mousetrack\(int b, int dx, int dy\))100 L (422 devwstat,)0(490 {)100 L (423 };)0(491 int x, y, lastb;)100 L (424)0(492)100 L (425 void)0(493 if\(gscreen==nil\))100 L (426 Cursortocursor\(Cursor *c\))0(494)100(return;)116 L (427 {)0(495)100 L (428 lock\(&cursor\);)0(496 if\(mouse.acceleration\){)100 L (429 memmove\(&cursor.Cursor, c, sizeof\(Cursor\)\);)0(497)100(dx = scale\(dx\);)116 L (430 setcursor\(c\);)0(498)100(dy = scale\(dy\);)116 L (431 unlock\(&cursor\);)0(499 })100 L (432 })0(500 x = mouse.xy.x + dx;)100 L (433)0(501 if\(x < gscreen->r.min.x\))100 L (434)0(502)100(x = gscreen->r.min.x;)116 L (435 /*)0(503 if\(x >= gscreen->r.max.x\))100 L (436 * called by the clock routine to redraw the cursor)0(504)100(x = gscreen->r.max.x;)116 L (437 */)0(505 y = mouse.xy.y + dy;)100 L (438 static void)0(506 if\(y < gscreen->r.min.y\))100 L (439 mouseclock\(void\))0(507)100(y = gscreen->r.min.y;)116 L (440 {)0(508 if\(y >= gscreen->r.max.y\))100 L (441 if\(mouse.track\){)0(509)100(y = gscreen->r.max.y;)116 L (442)0(mousetrack\(mouse.buttons, mouse.dx, mouse.dy\);)16(510)100 L (443)0(mouse.track = 0;)16(511 lastb = mouse.buttons;)100 L (444)0(mouse.dx = 0;)16(512 mouse.xy = Pt\(x, y\);)100 L (445)0(mouse.dy = 0;)16(513 mouse.buttons = b;)100 L (446 })0(514 mouse.redraw = 1;)100 L (447 if\(mouse.redraw && canlock\(&cursor\)\){)0(515 mouse.counter++;)100 L (448)0(mouse.redraw = 0;)16(516 mouse.msec = TK2MS\(MACHP\(0\)->ticks\);)100 L (449)0(cursoroff\(0\);)16(517)100 L (450)0(mouse.redraw = cursoron\(0\);)16(518 /*)100 L (451)0(unlock\(&cursor\);)16(519)100(* if the queue fills, we discard the entire queue and don't)109 L (452 })0(520)100(* queue any more events until a reader polls the mouse.)109 L (453 drawactive\(0\);)0(521)100(*/)109 L (454 })0(522 if\(!mouse.qfull && lastb != b\) {)100(/* add to ring */)148 L (455)0(523)100(mouse.queue[mouse.wi] = mouse.Mousestate;)116 L (456 static int)0(524)100(if\(++mouse.wi == nelem\(mouse.queue\)\))116 L (457 scale\(int x\))0(525)100(mouse.wi = 0;)124 L (458 {)0(526)100(if\(mouse.wi == mouse.ri\))116 L (459 int sign = 1;)0(527)100(mouse.qfull = 1;)124 L (460)0(528 })100 L (461 if\(x < 0\){)0(529 wakeup\(&mouse.r\);)100 L (462)0(sign = -1;)16(530 drawactive\(1\);)100 L (463)0(x = -x;)16(531 })100 L (464 })0(532)100 L (465 switch\(x\){)0(533 /*)100 L (466 case 0:)0(534 * microsoft 3 button, 7 bit bytes)100 L (467 case 1:)0(535 *)100 L (468 case 2:)0(536 *)100(byte 0 -)116(1 L R Y7 Y6 X7 X6)132 L (469 case 3:)0(537 *)100(byte 1 -)116(0 X5 X4 X3 X2 X1 X0)132 L (470)0(break;)16(538 *)100(byte 2 -)116(0 Y5 Y4 Y3 Y2 Y1 Y0)132 L (471 case 4:)0(539 *)100(byte 3 -)116(0 M x x x x x \(optional\))132 L (472)0(x = 6 + \(mouse.acceleration>>2\);)16(540 *)100 L (473)0(break;)16(541 * shift & right button is the same as middle button \(for 2 button mice\))100 L (474 case 5:)0(542 */)100 L (475)0(x = 9 + \(mouse.acceleration>>1\);)16(543 int)100 L (476)0(break;)16(544 m3mouseputc\(Queue*, int c\))100 L cleartomark showpage saveobj restore %%EndPage: 134 134 %%Page: 135 135 /saveobj save def mark 135 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devmouse.c Page 5)l ()l ()l (545 {)0(613 Point)100 L (546 static uchar msg[3];)0(614 mousexy\(void\))100 L (547 static int nb;)0(615 {)100 L (548 static int middle;)0(616 return mouse.xy;)100 L (549 static uchar b[] = { 0, 4, 1, 5, 0, 2, 1, 5 };)0(617 })100 L (550 short x;)0(618)100 L (551 int dx, dy, newbuttons;)0(619 void)100 L (552)0(620 mouseaccelerate\(int x\))100 L (553 if\(nb==0\){)0(621 {)100 L (554)0(/*)16(622 mouse.acceleration = x;)100 L (555)0(* an extra byte comes for middle button motion.)17(623 if\(mouse.acceleration < 3\))100 L (556)0(* only two possible values for the extra byte.)17(624)100(mouse.maxacc = 2;)116 L (557)0(*/)17(625 else)100 L (558)0(if\(c == 0x00 || c == 0x20\){)16(626)100(mouse.maxacc = mouse.acceleration;)116 L (559)0(/* an extra byte gets sent for the middle button */)24(627 })100 L (560)0(middle = \(c&0x20\) ? 2 : 0;)24 L (561)0(newbuttons = \(mouse.buttons & ~2\) | middle;)24 L (562)0(mousetrack\(newbuttons, 0, 0\);)24 L (563)0(return 0;)24 L (564)0(})16 L (565 })l (566 msg[nb] = c;)l (567 if\(++nb == 3\){)l (568)0(nb = 0;)16 L (569)0(newbuttons = middle | b[\(msg[0]>>4\)&3 | \(mouseshifted ? 4 : 0\)];)16 L (570)0(x = \(msg[0]&0x3\)<<14;)16 L (571)0(dx = \(x>>8\) | msg[1];)16 L (572)0(x = \(msg[0]&0xc\)<<12;)16 L (573)0(dy = \(x>>8\) | msg[2];)16 L (574)0(mousetrack\(newbuttons, dx, dy\);)16 L (575 })l (576 return 0;)l (577 })l (578)l (579 /*)l (580 * Logitech 5 byte packed binary mouse format, 8 bit bytes)l (581 *)l (582 * shift & right button is the same as middle button \(for 2 button mice\))l (583 */)l (584 int)l (585 mouseputc\(Queue*, int c\))l (586 {)l (587 static short msg[5];)l (588 static int nb;)l (589 static uchar b[] = {0, 4, 2, 6, 1, 5, 3, 7, 0, 2, 2, 6, 1, 5, 3, 7};)l (590 int dx, dy, newbuttons;)l (591)l (592 if\(\(c&0xF0\) == 0x80\))l (593)0(nb=0;)16 L (594 msg[nb] = c;)l (595 if\(c & 0x80\))l (596)0(msg[nb] |= ~0xFF;)16(/* sign extend */)40 L (597 if\(++nb == 5\){)l (598)0(newbuttons = b[\(\(msg[0]&7\)^7\) | \(mouseshifted ? 8 : 0\)];)16 L (599)0(dx = msg[1]+msg[3];)16 L (600)0(dy = -\(msg[2]+msg[4]\);)16 L (601)0(mousetrack\(newbuttons, dx, dy\);)16 L (602)0(nb = 0;)16 L (603 })l (604 return 0;)l (605 })l (606)l (607 int)l (608 mousechanged\(void*\))l (609 {)l (610 return mouse.lastcounter != mouse.counter;)l (611 })l (612)l cleartomark showpage saveobj restore %%EndPage: 135 135 %%Page: 136 136 /saveobj save def mark 136 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(Dcd= \(1<<7\),)109(/* complement of data carrier detect line */)132 L (2 #include "../port/lib.h")0(70)100(Scratch=7,)108(/* scratchpad */)132 L (3 #include "mem.h")0(71)100(Dlsb= 0,)108(/* divisor lsb */)132 L (4 #include "dat.h")0(72)100(Dmsb= 1,)108(/* divisor msb */)132 L (5 #include "fns.h")0(73)100(Efr= 2,)108(/* enhanced features for 16C650 */)132 L (6 #include "io.h")0(74)100(Eena= \(1<<4\),)109(/* enable enhanced bits in normal registers */)132 L (7 #include "../port/error.h")0(75)100(Arts= \(1<<6\),)109(/* auto rts */)132 L (8)0(76)100(Acts= \(1<<7\),)109(/* auto cts */)132 L (9 #include "../port/netif.h")0(77)100 L (10)0(78)100(CTLS= 023,)108 L (11 /*)0(79)100(CTLQ= 021,)108 L (12 * Driver for the ns16552.)0(80)100 L (13 */)0(81)100(Stagesize= 1024,)108 L (14 enum)0(82)100(Nuart= 32,)108(/* max per machine */)132 L (15 {)0(83)100 L (16)0(/*)8(84)100(Ns450= 0,)108 L (17)0(* register numbers)9(85)100(Ns550,)108 L (18)0(*/)9(86)100(Ns650,)108 L (19)0(Data= 0,)8(/* xmit/rcv buffer */)32(87 };)100 L (20)0(Iena= 1,)8(/* interrupt enable */)32(88)100 L (21)0(Ircv= \(1<<0\),)9(/* for char rcv'd */)32(89 typedef struct Uart Uart;)100 L (22)0(Ixmt= \(1<<1\),)9(/* for xmit buffer empty */)32(90 struct Uart)100 L (23)0(Irstat=\(1<<2\),)9(/* for change in rcv'er status */)32(91 {)100 L (24)0(Imstat=\(1<<3\),)9(/* for change in modem status */)32(92)100(QLock;)108 L (25)0(Isleep=\(1<<4\),)9(/* put in sleep mode; 16C650 */)32(93)100(int opens;)108 L (26)0(Ixoff= \(1<<5\),)9(/* for xoff received; 16C650 */)32(94)100 L (27)0(Irts= \(1<<6\),)9(/* for !rts asserted in auto mode; 16C650 */)32(95)100(int enabled;)108 L (28)0(Icts= \(1<<7\),)9(/* for !cts asserted in auto mode; 16C650 */)32(96)100(Uart *elist;)108(/* next enabled interface */)140 L (29)0(Istat= 2,)8(/* interrupt flag \(read\) */)32(97)100(char name[NAMELEN];)108 L (30)0(Fenabd=\(3<<6\),)9(/* on if fifo's enabled */)32(98)100 L (31)0(Irctsd=\(1<<4\),)9(/* auto rts or cts changed state */)32(99)100(uchar sticky[8];)108(/* sticky write register values */)140 L (32)0(Fifoctl=2,)8(/* fifo control \(write\) */)32(100 uchar osticky[8];)100(/* kernel saved sticky write register values */)140 L (33)0(Fena= \(1<<0\),)9(/* enable xmit/rcv fifos */)32(101 ulong port;)100(/* io ports */)140 L (34)0(Ftrig4=)9(\(1<<6\),)24(/* trigger after 4 input characters */)40(102 ulong freq;)100(/* clock frequency */)140 L (35)0(Ftrig24=)9(\(2<<6\),)24(/* trigger after 24 input characters */)40(103 uchar mask;)100(/* bits/char */)140 L (36)0(Fclear=\(3<<1\),)9(/* clear xmit & rcv fifos */)32(104 int dev;)100 L (37)0(Format= 3,)8(/* byte format */)32(105 int baud;)100(/* baud rate */)140 L (38)0(Bits8= \(3<<0\),)9(/* 8 bits/byte */)32(106)100 L (39)0(Stop2= \(1<<2\),)9(/* 2 stop bits */)32(107 uchar istat;)100(/* last istat read */)140 L (40)0(Pena= \(1<<3\),)9(/* generate parity */)32(108 int frame;)100(/* framing errors */)140 L (41)0(Peven= \(1<<4\),)9(/* even parity */)32(109 int overrun;)100(/* rcvr overruns */)140 L (42)0(Pforce=\(1<<5\),)9(/* force parity */)32(110)100 L (43)0(Break= \(1<<6\),)9(/* generate a break */)32(111 /* buffers */)100 L (44)0(Dra= \(1<<7\),)9(/* address the divisor */)32(112 int \(*putc\)\(Queue*, int\);)100 L (45)0(Ers= 0xbf,)9(/* enable enhaced register set on 16C650 */)32(113 Queue *iq;)100 L (46)0(Mctl= 4,)8(/* modem control */)32(114 Queue *oq;)100 L (47)0(Dtr= \(1<<0\),)9(/* data terminal ready */)32(115)100 L (48)0(Rts= \(1<<1\),)9(/* request to send */)32(116 Lock flock;)100(/* fifo */)140 L (49)0(Ri= \(1<<2\),)9(/* ring */)32(117 uchar fifoon;)100(/* fifo's enabled */)140 L (50)0(Inton= \(1<<3\),)9(/* turn on interrupts */)32(118 uchar type;)100(/* chip version */)140 L (51)0(Loop= \(1<<4\),)9(/* loop back */)32(119)100 L (52)0(Intsel=\(1<<5\),)9(/* NO! open source interrupts; 16C650 */)32(120 Lock rlock;)100(/* receive */)140 L (53)0(Irda= \(1<<6\),)9(/* infrared interface; 16C650 */)32(121 uchar istage[Stagesize];)100 L (54)0(Cdiv= \(1<<7\),)9(/* divide clock by four; 16C650 */)32(122 uchar *ip;)100 L (55)0(Lstat= 5,)8(/* line status */)32(123 uchar *ie;)100 L (56)0(Inready=\(1<<0\),)9(/* receive buffer full */)32(124)100 L (57)0(Oerror=\(1<<1\),)9(/* receiver overrun */)32(125 int haveinput;)100 L (58)0(Perror=\(1<<2\),)9(/* receiver parity error */)32(126)100 L (59)0(Ferror=\(1<<3\),)9(/* rcv framing error */)32(127 Lock tlock;)100(/* transmit */)140 L (60)0(Outready=\(1<<5\),)9(/* output buffer full */)32(128 uchar ostage[Stagesize];)100 L (61)0(Mstat= 6,)8(/* modem status */)32(129 uchar *op;)100 L (62)0(Ctsc= \(1<<0\),)9(/* clear to send changed */)32(130 uchar *oe;)100 L (63)0(Dsrc= \(1<<1\),)9(/* data set ready changed */)32(131)100 L (64)0(Rire= \(1<<2\),)9(/* rising edge of ring indicator */)32(132 int modem;)100(/* hardware flow control on */)140 L (65)0(Dcdc= \(1<<3\),)9(/* data carrier detect changed */)32(133 int xonoff;)100(/* software flow control on */)140 L (66)0(Cts= \(1<<4\),)9(/* complement of clear to send line */)32(134 int blocked;)100 L (67)0(Dsr= \(1<<5\),)9(/* complement of data set ready line */)32(135 int cts, dsr, dcd, dcdts;)100(/* keep track of modem status */)148 L (68)0(Ring= \(1<<6\),)9(/* complement of ring indicator line */)32(136 int ctsbackoff;)100 L cleartomark showpage saveobj restore %%EndPage: 136 136 %%Page: 137 137 /saveobj save def mark 137 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 2)l ()l ()l (137 int hup_dsr, hup_dcd;)0(/* send hangup upstream? */)40(205 {)100 L (138 int dohup;)0(206 switch\(type\){)100 L (139)0(207 case 'e':)100 L (140 int kinuse;)0(/* device in use by kernel */)32(208)100(p->sticky[Format] |= Pena|Peven;)116 L (141)0(209)100(break;)116 L (142 Rendez r;)0(210 case 'o':)100 L (143 };)0(211)100(p->sticky[Format] &= ~Peven;)116 L (144)0(212)100(p->sticky[Format] |= Pena;)116 L (145 static Uart *uart[Nuart];)0(213)100(break;)116 L (146 static int nuart;)0(214 default:)100 L (147)0(215)100(p->sticky[Format] &= ~\(Pena|Peven\);)116 L (148 struct Uartalloc {)0(216)100(break;)116 L (149 Lock;)0(217 })100 L (150 Uart *elist; /* list of enabled interfaces */)0(218 uartwrreg\(p, Format, 0\);)100 L (151 } uartalloc;)0(219 })100 L (152)0(220)100 L (153 void ns16552intr\(int\);)0(221 /*)100 L (154)0(222 * set bits/character, default 8)100 L (155 /*)0(223 */)100 L (156 * means the kernel is using this for debugging output)0(224 void)100 L (157 */)0(225 ns16552bits\(Uart *p, int bits\))100 L (158 static char)0(Ekinuse[] = "device in use by kernel";)24(226 {)100 L (159)0(227 if\(bits < 5 || bits > 8\))100 L (160 /*)0(228)100(error\(Ebadarg\);)116 L (161 * pick up architecture specific routines and definitions)0(229)100 L (162 */)0(230 p->sticky[Format] &= ~3;)100 L (163 #include "ns16552.h")0(231 p->sticky[Format] |= bits-5;)100 L (164)0(232)100 L (165 /*)0(233 uartwrreg\(p, Format, 0\);)100 L (166 * set the baud rate by calculating and setting the baudrate)0(234 })100 L (167 * generator constant. This will work with fairly non-standard)0(235)100 L (168 * baud rates.)0(236 /*)100 L (169 */)0(237 * toggle DTR)100 L (170 static void)0(238 */)100 L (171 ns16552setbaud\(Uart *p, int rate\))0(239 void)100 L (172 {)0(240 ns16552dtr\(Uart *p, int n\))100 L (173 ulong brconst;)0(241 {)100 L (174)0(242 if\(n\))100 L (175 if\(rate <= 0\))0(243)100(p->sticky[Mctl] |= Dtr;)116 L (176)0(return;)16(244 else)100 L (177)0(245)100(p->sticky[Mctl] &= ~Dtr;)116 L (178 brconst = \(p->freq+8*rate-1\)/\(16*rate\);)0(246)100 L (179)0(247 uartwrreg\(p, Mctl, 0\);)100 L (180 uartwrreg\(p, Format, Dra\);)0(248 })100 L (181 outb\(p->port + Dmsb, \(brconst>>8\) & 0xff\);)0(249)100 L (182 outb\(p->port + Dlsb, brconst & 0xff\);)0(250 /*)100 L (183 uartwrreg\(p, Format, 0\);)0(251 * toggle RTS)100 L (184)0(252 */)100 L (185 p->baud = rate;)0(253 void)100 L (186 })0(254 ns16552rts\(Uart *p, int n\))100 L (187)0(255 {)100 L (188 /*)0(256 if\(n\))100 L (189 * decide if we should hangup when dsr or dcd drops.)0(257)100(p->sticky[Mctl] |= Rts;)116 L (190 */)0(258 else)100 L (191 static void)0(259)100(p->sticky[Mctl] &= ~Rts;)116 L (192 ns16552dsrhup\(Uart *p, int n\))0(260)100 L (193 {)0(261 uartwrreg\(p, Mctl, 0\);)100 L (194 p->hup_dsr = n;)0(262 })100 L (195 })0(263)100 L (196)0(264 /*)100 L (197 static void)0(265 * save dcd timestamps for gps clock)100 L (198 ns16552dcdhup\(Uart *p, int n\))0(266 */)100 L (199 {)0(267 static void)100 L (200 p->hup_dcd = n;)0(268 ns16552dcdts\(Uart *p, int n\))100 L (201 })0(269 {)100 L (202)0(270 p->dcdts = n;)100 L (203 static void)0(271 })100 L (204 ns16552parity\(Uart *p, char type\))0(272)100 L cleartomark showpage saveobj restore %%EndPage: 137 137 %%Page: 138 138 /saveobj save def mark 138 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 3)l ()l ()l (273 /*)0(341)100(p->cts = uartrdreg\(p, Mstat\) & Cts;)124 L (274 * send break)0(342)100(})116 L (275 */)0(343 } else {)100 L (276 static void)0(344)100(if\(p->type == Ns650\){)116 L (277 ns16552break\(Uart *p, int ms\))0(345)100(outb\(p->port + Format, 0xbf\);)124 L (278 {)0(346)100(outb\(p->port + Efr, Eena|Arts|Acts\);)124 L (279 if\(ms == 0\))0(347)100(uartwrreg\(p, Format, 0\);)124 L (280)0(ms = 200;)16(348)100(} else {)116 L (281)0(349)100(p->sticky[Iena] &= ~Imstat;)124 L (282 uartwrreg\(p, Format, Break\);)0(350)100(uartwrreg\(p, Iena, 0\);)124 L (283 tsleep\(&up->sleep, return0, 0, ms\);)0(351)100(p->modem = 0;)124 L (284 uartwrreg\(p, Format, 0\);)0(352)100(})116 L (285 })0(353)100(p->cts = 1;)116 L (286)0(354 })100 L (287 static void)0(355 iunlock\(&p->tlock\);)100 L (288 ns16552fifoon\(Uart *p\))0(356)100 L (289 {)0(357 ilock\(&p->flock\);)100 L (290 ulong i, x;)0(358 if\(n\))100 L (291)0(359)100(/* turn on fifo's */)116 L (292 if\(p->type < Ns550\))0(360)100(ns16552fifoon\(p\);)116 L (293)0(return;)16(361 else {)100 L (294)0(362)100(/* turn off fifo's */)116 L (295 x = splhi\(\);)0(363)100(p->fifoon = 0;)116 L (296)0(364)100(uartwrreg\(p, Fifoctl, 0\);)116 L (297 /* reset fifos */)0(365 })100 L (298 uartwrreg\(p, Fifoctl, Fclear\);)0(366 iunlock\(&p->flock\);)100 L (299)0(367 })100 L (300 /* empty buffer and interrupt conditions */)0(368)100 L (301 for\(i = 0; i < 16; i++\){)0(369 /*)100 L (302)0(if\(uartrdreg\(p, Istat\)\))16(370 * turn on a port's interrupts. set DTR and RTS)100 L (303)0(;)24(371 */)100 L (304)0(if\(uartrdreg\(p, Data\)\))16(372 static void)100 L (305)0(;)24(373 ns16552enable\(Uart *p\))100 L (306 })0(374 {)100 L (307)0(375 Uart **l;)100 L (308 /* turn on fifo */)0(376)100 L (309 p->fifoon = 1;)0(377 if\(p->enabled\))100 L (310 if\(p->type == Ns650\))0(378)100(return;)116 L (311)0(uartwrreg\(p, Fifoctl, Fena|Ftrig24\);)16(379)100 L (312 else)0(380 uartpower\(p->dev, 1\);)100 L (313)0(uartwrreg\(p, Fifoctl, Fena|Ftrig4\);)16(381)100 L (314)0(382 p->hup_dsr = p->hup_dcd = 0;)100 L (315 if\(\(p->istat & Fenabd\) == 0\){)0(383 p->cts = p->dsr = p->dcd = 0;)100 L (316)0(/* didn't work, must be an earlier chip type */)16(384)100 L (317)0(p->type = Ns450;)16(385 /*)100 L (318 })0(386)100(* turn on interrupts)109 L (319)0(387)100(*/)109 L (320 splx\(x\);)0(388 p->sticky[Iena] = Ircv | Ixmt | Irstat;)100 L (321 })0(389 uartwrreg\(p, Iena, 0\);)100 L (322)0(390)100 L (323 /*)0(391 /*)100 L (324 * modem flow control on/off \(rts/cts\))0(392)100(* turn on DTR and RTS)109 L (325 */)0(393)100(*/)109 L (326 static void)0(394 ns16552dtr\(p, 1\);)100 L (327 ns16552mflow\(Uart *p, int n\))0(395 ns16552rts\(p, 1\);)100 L (328 {)0(396)100 L (329)0(397 /*)100 L (330 ilock\(&p->tlock\);)0(398)100(* assume we can send)109 L (331 if\(n\){)0(399)100(*/)109 L (332)0(if\(p->type == Ns650\){)16(400 ilock\(&p->tlock\);)100 L (333)0(outb\(p->port + Format, 0xbf\);)24(401 p->cts = 1;)100 L (334)0(outb\(p->port + Efr, Eena|Arts|Acts\);)24(402 p->blocked = 0;)100 L (335)0(uartwrreg\(p, Format, 0\);)24(403 iunlock\(&p->tlock\);)100 L (336)0(p->cts = 1;)24(404)100 L (337)0(} else {)16(405 /*)100 L (338)0(p->sticky[Iena] |= Imstat;)24(406)100(* set baud rate to the last used)109 L (339)0(uartwrreg\(p, Iena, 0\);)24(407)100(*/)109 L (340)0(p->modem = 1;)24(408 ns16552setbaud\(p, p->baud\);)100 L cleartomark showpage saveobj restore %%EndPage: 138 138 %%Page: 139 139 /saveobj save def mark 139 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 4)l ()l ()l (409)0(477)100(return 0;)116 L (410 lock\(&uartalloc\);)0(478 p->op = p->ostage;)100 L (411 for\(l = &uartalloc.elist; *l; l = &\(*l\)->elist\){)0(479 p->oe = p->ostage + n;)100 L (412)0(if\(*l == p\))16(480 return n;)100 L (413)0(break;)24(481 })100 L (414 })0(482)100 L (415 if\(*l == 0\){)0(483 /*)100 L (416)0(p->elist = uartalloc.elist;)16(484 * \(re\)start output)100 L (417)0(uartalloc.elist = p;)16(485 */)100 L (418 })0(486 static void)100 L (419 p->enabled = 1;)0(487 ns16552kick0\(void *v\))100 L (420 unlock\(&uartalloc\);)0(488 {)100 L (421 })0(489 int i;)100 L (422)0(490 Uart *p;)100 L (423 /*)0(491)100 L (424 * turn off a port's interrupts. reset DTR and RTS)0(492 p = v;)100 L (425 */)0(493 if\(p->cts == 0 || p->blocked\))100 L (426 static void)0(494)100(return;)116 L (427 ns16552disable\(Uart *p\))0(495)100 L (428 {)0(496 /*)100 L (429 Uart **l;)0(497)100(* 128 here is an arbitrary limit to make sure)109 L (430)0(498)100(* we don't stay in this loop too long. If the)109 L (431 /*)0(499)100(* chips output queue is longer than 128, too)109 L (432)0(* turn off interrupts)9(500)100(* bad -- presotto)109 L (433)0(*/)9(501)100(*/)109 L (434 p->sticky[Iena] = 0;)0(502 for\(i = 0; i < 128; i++\){)100 L (435 uartwrreg\(p, Iena, 0\);)0(503)100(if\(!\(uartrdreg\(p, Lstat\) & Outready\)\))116 L (436)0(504)100(break;)124 L (437 /*)0(505)100(if\(p->op >= p->oe && stageoutput\(p\) == 0\))116 L (438)0(* revert to default settings)9(506)100(break;)124 L (439)0(*/)9(507)100(outb\(p->port + Data, *\(p->op++\)\);)116 L (440 p->sticky[Format] = Bits8;)0(508 })100 L (441 uartwrreg\(p, Format, 0\);)0(509 })100 L (442)0(510)100 L (443 /*)0(511 static void)100 L (444)0(* turn off DTR, RTS, hardware flow control & fifo's)9(512 ns16552kick\(void *v\))100 L (445)0(*/)9(513 {)100 L (446 ns16552dtr\(p, 0\);)0(514 Uart *p;)100 L (447 ns16552rts\(p, 0\);)0(515)100 L (448 ns16552mflow\(p, 0\);)0(516 p = v;)100 L (449 ilock\(&p->tlock\);)0(517 ilock\(&p->tlock\);)100 L (450 p->xonoff = p->blocked = 0;)0(518 ns16552kick0\(p\);)100 L (451 iunlock\(&p->tlock\);)0(519 iunlock\(&p->tlock\);)100 L (452)0(520 })100 L (453 uartpower\(p->dev, 0\);)0(521)100 L (454)0(522 /*)100 L (455 lock\(&uartalloc\);)0(523 * restart input if it's off)100 L (456 for\(l = &uartalloc.elist; *l; l = &\(*l\)->elist\){)0(524 */)100 L (457)0(if\(*l == p\){)16(525 static void)100 L (458)0(*l = p->elist;)24(526 ns16552flow\(void *v\))100 L (459)0(break;)24(527 {)100 L (460)0(})16(528 Uart *p;)100 L (461 })0(529)100 L (462 p->enabled = 0;)0(530 p = v;)100 L (463 unlock\(&uartalloc\);)0(531 if\(p->modem\){)100 L (464 })0(532)100(ns16552rts\(p, 1\);)116 L (465)0(533)100(ilock\(&p->rlock\);)116 L (466 /*)0(534)100(p->haveinput = 1;)116 L (467 * put some bytes into the local queue to avoid calling)0(535)100(iunlock\(&p->rlock\);)116 L (468 * qconsume for every character)0(536 })100 L (469 */)0(537 })100 L (470 static int)0(538)100 L (471 stageoutput\(Uart *p\))0(539 /*)100 L (472 {)0(540 * default is 9600 baud, 1 stop bit, 8 bit chars, no interrupts,)100 L (473 int n;)0(541 * transmit and receive enabled, interrupts disabled.)100 L (474)0(542 */)100 L (475 n = qconsume\(p->oq, p->ostage, Stagesize\);)0(543 static void)100 L (476 if\(n <= 0\))0(544 ns16552setup0\(Uart *p\))100 L cleartomark showpage saveobj restore %%EndPage: 139 139 %%Page: 140 140 /saveobj save def mark 140 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 5)l ()l ()l (545 {)0(613 * handle an interrupt to a single uart)100 L (546 memset\(p->sticky, 0, sizeof\(p->sticky\)\);)0(614 */)100 L (547 /*)0(615 void)100 L (548)0(* set rate to 9600 baud.)9(616 ns16552intr\(int dev\))100 L (549)0(* 8 bits/character.)9(617 {)100 L (550)0(* 1 stop bit.)9(618 uchar ch;)100 L (551)0(* interrupts enabled.)9(619 int s, l, loops;)100 L (552)0(*/)9(620 Uart *p = uart[dev];)100 L (553 p->sticky[Format] = Bits8;)0(621)100 L (554 uartwrreg\(p, Format, 0\);)0(622 for\(loops = 0;; loops++\){)100 L (555 p->sticky[Mctl] |= Inton;)0(623)100(p->istat = s = uartrdreg\(p, Istat\);)116 L (556 uartwrreg\(p, Mctl, 0x0\);)0(624)100(if\(loops > 10000000\){)116 L (557)0(625)100(print\("lstat %ux mstat %ux istat %ux iena %ux ferr %d oerr %d",)124 L (558 ns16552setbaud\(p, 9600\);)0(626)100(uartrdreg\(p, Lstat\), uartrdreg\(p, Mstat\),)132 L (559)0(627)100(s, uartrdreg\(p, Iena\), p->frame, p->overrun\);)132 L (560 p->iq = qopen\(4*1024, 0, ns16552flow, p\);)0(628)100(panic\("ns16552intr"\);)124 L (561 p->oq = qopen\(4*1024, 0, ns16552kick, p\);)0(629)100(})116 L (562 if\(p->iq == nil || p->oq == nil\))0(630)100(switch\(s&0x3f\){)116 L (563)0(panic\("ns16552setup0"\);)16(631)100(case 6: /* receiver line status */)116 L (564)0(632)100(l = uartrdreg\(p, Lstat\);)124 L (565 p->ip = p->istage;)0(633)100(if\(l & Ferror\))124 L (566 p->ie = &p->istage[Stagesize];)0(634)100(p->frame++;)132 L (567 p->op = p->ostage;)0(635)100(if\(l & Oerror\))124 L (568 p->oe = p->ostage;)0(636)100(p->overrun++;)132 L (569 })0(637)100(break;)124 L (570)0(638)100 L (571 /*)0(639)100(case 4: /* received data available */)116 L (572 * called by main\(\) to create a new duart)0(640)100(case 12:)116 L (573 */)0(641)100(ch = uartrdreg\(p, Data\) & 0xff;)124 L (574 void)0(642)100(if\(p->xonoff\){)124 L (575 ns16552setup\(ulong port, ulong freq, char *name, int type\))0(643)100(if\(ch == CTLS\){)132 L (576 {)0(644)100(p->blocked = 1;)140 L (577 Uart *p;)0(645)100(}else if \(ch == CTLQ\){)132 L (578)0(646)100(p->blocked = 0;)140 L (579 if\(nuart >= Nuart\))0(647)100(p->ctsbackoff = 2; /* clock gets output going again */)140 L (580)0(return;)16(648)100(})132 L (581)0(649)100(})124 L (582 p = xalloc\(sizeof\(Uart\)\);)0(650)100(if\(p->putc\))124 L (583 uart[nuart] = p;)0(651)100(p->putc\(p->iq, ch\);)132 L (584 strcpy\(p->name, name\);)0(652)100(else {)124 L (585 p->dev = nuart;)0(653)100(ilock\(&p->rlock\);)132 L (586 nuart++;)0(654)100(if\(p->ip < p->ie\))132 L (587 p->port = port;)0(655)100(*p->ip++ = ch;)140 L (588 p->freq = freq;)0(656)100(p->haveinput = 1;)132 L (589 p->type = type;)0(657)100(iunlock\(&p->rlock\);)132 L (590 ns16552setup0\(p\);)0(658)100(})124 L (591 })0(659)100(break;)124 L (592)0(660)100 L (593 /*)0(661)100(case 2: /* transmitter not full */)116 L (594 * called by main\(\) to configure a duart port as a console or a mouse)0(662)100(ns16552kick\(p\);)124 L (595 */)0(663)100(break;)124 L (596 void)0(664)100 L (597 ns16552special\(int port, int baud, Queue **in, Queue **out, int \(*putc\)\(Queue*, int\)\))0(665)100(case 0: /* modem status */)116 L (598 {)0(666)100(ch = uartrdreg\(p, Mstat\);)124 L (599 Uart *p = uart[port];)0(667)100(if\(ch & Ctsc\){)124 L (600)0(668)100(l = p->cts;)132 L (601 ns16552enable\(p\);)0(669)100(p->cts = ch & Cts;)132 L (602 if\(baud\))0(670)100(if\(l == 0 && p->cts\))132 L (603)0(ns16552setbaud\(p, baud\);)16(671)100(p->ctsbackoff = 2; /* clock gets output going again */)140 L (604 p->putc = putc;)0(672)100(})124 L (605 if\(in\))0(673)100(if \(ch & Dsrc\) {)124 L (606)0(*in = p->iq;)16(674)100(l = ch & Dsr;)132 L (607 if\(out\))0(675)100(if\(p->hup_dsr && p->dsr && !l\))132 L (608)0(*out = p->oq;)16(676)100(p->dohup = 1; /* clock peforms hangup */)140 L (609 p->opens++;)0(677)100(p->dsr = l;)132 L (610 })0(678)100(})124 L (611)0(679)100(if \(ch & Dcdc\) {)124 L (612 /*)0(680)100(l = ch & Dcd;)132 L cleartomark showpage saveobj restore %%EndPage: 140 140 %%Page: 141 141 /saveobj save def mark 141 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 6)l ()l ()l (681)0(if\(l == 0 && p->dcd != 0 && p->dcdts && saveintrts != nil\))32(749)100(ns16552kick0\(p\);)140 L (682)0(\(*saveintrts\)\(\);)40(750)100(})124 L (683)0(if\(p->hup_dcd && p->dcd && !l\))32(751)100(iunlock\(&p->tlock\);)124 L (684)0(p->dohup = 1; /* clock peforms hangup */)40(752)100(})116 L (685)0(p->dcd = l;)32(753 })100 L (686)0(})24(754 })100 L (687)0(break;)24(755)100 L (688)0(756 Dirtab *ns16552dir;)100 L (689)0(default:)16(757 int ndir;)100 L (690)0(if\(s&1\))24(758)100 L (691)0(return;)32(759 static void)100 L (692)0(print\("weird modem interrupt #%2.2ux\\n", s\);)24(760 setlength\(int i\))100 L (693)0(break;)24(761 {)100 L (694)0(})16(762 Uart *p;)100 L (695 })0(763)100 L (696 })0(764 if\(i > 0\){)100 L (697)0(765)100(p = uart[i];)116 L (698 /*)0(766)100(if\(p && p->opens && p->iq\))116 L (699 * we save up input characters till clock time)0(767)100(ns16552dir[3*i].length = qlen\(p->iq\);)124 L (700 *)0(768 } else for\(i = 0; i < nuart; i++\){)100 L (701 * There's also a bit of code to get a stalled print going.)0(769)100(p = uart[i];)116 L (702 * It shouldn't happen, but it does. Obviously I don't)0(770)100(if\(p && p->opens && p->iq\))116 L (703 * understand something. Since it was there, I bundled a)0(771)100(ns16552dir[3*i].length = qlen\(p->iq\);)124 L (704 * restart after flow control with it to give some hysteresis)0(772 })100 L (705 * to the hardware flow control. This makes compressing)0(773 })100 L (706 * modems happier but will probably bother something else.)0(774)100 L (707 *)0(-- presotto)17(775 /*)100 L (708 */)0(776 * all uarts must be ns16552setup\(\) by this point or inside of ns16552install\(\))100 L (709 void)0(777 */)100 L (710 uartclock\(void\))0(778 static void)100 L (711 {)0(779 ns16552reset\(void\))100 L (712 int n;)0(780 {)100 L (713 Uart *p;)0(781 int i;)100 L (714)0(782 Dirtab *dp;)100 L (715 for\(p = uartalloc.elist; p; p = p->elist\){)0(783)100 L (716)0(784 ns16552install\(\);)100(/* architecture specific */)132 L (717)0(/* this amortizes cost of qproduce to many chars */)16(785)100 L (718)0(if\(p->haveinput\){)16(786 ndir = 3*nuart;)100 L (719)0(ilock\(&p->rlock\);)24(787 ns16552dir = xalloc\(ndir * sizeof\(Dirtab\)\);)100 L (720)0(if\(p->haveinput\){)24(788 dp = ns16552dir;)100 L (721)0(n = p->ip - p->istage;)32(789 for\(i = 0; i < nuart; i++\){)100 L (722)0(if\(n > 0 && p->iq\){)32(790)100(/* 3 directory entries per port */)116 L (723)0(if\(n > Stagesize\))40(791)100(strcpy\(dp->name, uart[i]->name\);)116 L (724)0(panic\("uartclock"\);)48(792)100(dp->qid.path = NETQID\(i, Ndataqid\);)116 L (725)0(if\(qproduce\(p->iq, p->istage, n\) < 0\))40(793)100(dp->perm = 0660;)116 L (726)0(ns16552rts\(p, 0\);)48(794)100(dp++;)116 L (727)0(else)40(795)100(sprint\(dp->name, "%sctl", uart[i]->name\);)116 L (728)0(p->ip = p->istage;)48(796)100(dp->qid.path = NETQID\(i, Nctlqid\);)116 L (729)0(})32(797)100(dp->perm = 0660;)116 L (730)0(p->haveinput = 0;)32(798)100(dp++;)116 L (731)0(})24(799)100(sprint\(dp->name, "%sstat", uart[i]->name\);)116 L (732)0(iunlock\(&p->rlock\);)24(800)100(dp->qid.path = NETQID\(i, Nstatqid\);)116 L (733)0(})16(801)100(dp->perm = 0444;)116 L (734)0(if\(p->dohup\){)16(802)100(dp++;)116 L (735)0(ilock\(&p->rlock\);)24(803 })100 L (736)0(if\(p->dohup\){)24(804 })100 L (737)0(qhangup\(p->iq, 0\);)32(805)100 L (738)0(qhangup\(p->oq, 0\);)32(806 static Chan*)100 L (739)0(})24(807 ns16552attach\(char *spec\))100 L (740)0(p->dohup = 0;)24(808 {)100 L (741)0(iunlock\(&p->rlock\);)24(809 return devattach\('t', spec\);)100 L (742)0(})16(810 })100 L (743)0(811)100 L (744)0(/* this adds hysteresis to hardware/software flow control */)16(812 static int)100 L (745)0(if\(p->ctsbackoff\){)16(813 ns16552walk\(Chan *c, char *name\))100 L (746)0(ilock\(&p->tlock\);)24(814 {)100 L (747)0(if\(p->ctsbackoff\){)24(815 return devwalk\(c, name, ns16552dir, ndir, devgen\);)100 L (748)0(if\(--\(p->ctsbackoff\) == 0\))32(816 })100 L cleartomark showpage saveobj restore %%EndPage: 141 141 %%Page: 142 142 /saveobj save def mark 142 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 7)l ()l ()l (817)0(885)100 L (818 static void)0(886 str[0] = 0;)100 L (819 ns16552stat\(Chan *c, char *dp\))0(887 tstat = p->sticky[Mctl];)100 L (820 {)0(888 mstat = uartrdreg\(p, Mstat\);)100 L (821 if\(NETTYPE\(c->qid.path\) == Ndataqid\))0(889 istat = p->sticky[Iena];)100 L (822)0(setlength\(NETID\(c->qid.path\)\);)16(890 fstat = p->sticky[Format];)100 L (823 devstat\(c, dp, ns16552dir, ndir, devgen\);)0(891 snprint\(str, sizeof str,)100 L (824 })0(892)100("b%d c%d d%d e%d l%d m%d p%c r%d s%d\\n")116 L (825)0(893)100("%d %d %d%s%s%s%s%s\\n",)116 L (826 static Chan*)0(894)100 L (827 ns16552open\(Chan *c, int omode\))0(895)100(p->baud,)116 L (828 {)0(896)100(p->hup_dcd,)116 L (829 Uart *p;)0(897)100(\(tstat & Dtr\) != 0,)116 L (830)0(898)100(p->hup_dsr,)116 L (831 c = devopen\(c, omode, ns16552dir, ndir, devgen\);)0(899)100(\(fstat & Bits8\) + 5,)116 L (832)0(900)100(\(istat & Imstat\) != 0,)116 L (833 switch\(NETTYPE\(c->qid.path\)\){)0(901)100(\(fstat & Pena\) ? \(\(fstat & Peven\) ? 'e' : 'o'\) : 'n',)116 L (834 case Nctlqid:)0(902)100(\(tstat & Rts\) != 0,)116 L (835 case Ndataqid:)0(903)100(\(fstat & Stop2\) ? 2 : 1,)116 L (836)0(p = uart[NETID\(c->qid.path\)];)16(904)100 L (837)0(if\(p->kinuse\))16(905)100(p->dev,)116 L (838)0(error\(Ekinuse\);)24(906)100(p->frame,)116 L (839)0(qlock\(p\);)16(907)100(p->overrun,)116 L (840)0(if\(p->opens++ == 0\){)16(908)100(p->fifoon)116(? " fifo" : "",)132 L (841)0(ns16552enable\(p\);)24(909)100(\(mstat & Cts\) ? " cts" : "",)116 L (842)0(qreopen\(p->iq\);)24(910)100(\(mstat & Dsr\) ? " dsr" : "",)116 L (843)0(qreopen\(p->oq\);)24(911)100(\(mstat & Dcd\) ? " dcd" : "",)116 L (844)0(})16(912)100(\(mstat & Ring\) ? " ring" : "")116 L (845)0(qunlock\(p\);)16(913 \);)100 L (846)0(break;)16(914 return readstr\(offset, buf, n, str\);)100 L (847 })0(915 })100 L (848)0(916)100 L (849 return c;)0(917 static long)100 L (850 })0(918 ns16552read\(Chan *c, void *buf, long n, vlong off\))100 L (851)0(919 {)100 L (852 static void)0(920 Uart *p;)100 L (853 ns16552close\(Chan *c\))0(921 ulong offset = off;)100 L (854 {)0(922)100 L (855 Uart *p;)0(923 if\(c->qid.path & CHDIR\){)100 L (856)0(924)100(setlength\(-1\);)116 L (857 if\(c->qid.path & CHDIR\))0(925)100(return devdirread\(c, buf, n, ns16552dir, ndir, devgen\);)116 L (858)0(return;)16(926 })100 L (859 if\(\(c->flag & COPEN\) == 0\))0(927)100 L (860)0(return;)16(928 p = uart[NETID\(c->qid.path\)];)100 L (861 switch\(NETTYPE\(c->qid.path\)\){)0(929 if\(p->kinuse\))100 L (862 case Ndataqid:)0(930)100(error\(Ekinuse\);)116 L (863 case Nctlqid:)0(931 switch\(NETTYPE\(c->qid.path\)\){)100 L (864)0(p = uart[NETID\(c->qid.path\)];)16(932 case Ndataqid:)100 L (865)0(if\(p->kinuse\))16(933)100(return qread\(p->iq, buf, n\);)116 L (866)0(error\(Ekinuse\);)24(934 case Nctlqid:)100 L (867)0(qlock\(p\);)16(935)100(return readnum\(offset, buf, n, NETID\(c->qid.path\), NUMSIZE\);)116 L (868)0(if\(--\(p->opens\) == 0\){)16(936 case Nstatqid:)100 L (869)0(ns16552disable\(p\);)24(937)100(return uartstatus\(c, p, buf, n, offset\);)116 L (870)0(qclose\(p->iq\);)24(938 })100 L (871)0(qclose\(p->oq\);)24(939)100 L (872)0(p->ip = p->istage;)24(940 return 0;)100 L (873)0(p->dcd = p->dsr = p->dohup = 0;)24(941 })100 L (874)0(})16(942)100 L (875)0(qunlock\(p\);)16(943 static void)100 L (876)0(break;)16(944 ns16552ctl\(Uart *p, char *cmd\))100 L (877 })0(945 {)100 L (878 })0(946 int i, n;)100 L (879)0(947)100 L (880 static long)0(948 /* let output drain for a while */)100 L (881 uartstatus\(Chan*, Uart *p, void *buf, long n, long offset\))0(949 for\(i = 0; i < 16 && qlen\(p->oq\); i++\))100 L (882 {)0(950)100(tsleep\(&p->r, \(int\(*\)\(void*\)\)qlen, p->oq, 125\);)116 L (883 uchar mstat, fstat, istat, tstat;)0(951)100 L (884 char str[256];)0(952 if\(strncmp\(cmd, "break", 5\) == 0\){)100 L cleartomark showpage saveobj restore %%EndPage: 142 142 %%Page: 143 143 /saveobj save def mark 143 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 8)l ()l ()l (953)0(ns16552break\(p, 0\);)16(1021)100(break;)116 L (954)0(return;)16(1022 case 'X':)100 L (955 })0(1023 case 'x':)100 L (956)0(1024)100(ilock\(&p->tlock\);)116 L (957)0(1025)100(p->xonoff = n;)116 L (958 n = atoi\(cmd+1\);)0(1026)100(iunlock\(&p->tlock\);)116 L (959 switch\(*cmd\){)0(1027)100(break;)116 L (960 case 'B':)0(1028 })100 L (961 case 'b':)0(1029 })100 L (962)0(ns16552setbaud\(p, n\);)16(1030)100 L (963)0(break;)16(1031 static long)100 L (964 case 'C':)0(1032 ns16552write\(Chan *c, void *buf, long n, vlong\))100 L (965 case 'c':)0(1033 {)100 L (966)0(ns16552dcdhup\(p, n\);)16(1034 Uart *p;)100 L (967)0(break;)16(1035 char cmd[32];)100 L (968 case 'D':)0(1036)100 L (969 case 'd':)0(1037 if\(c->qid.path & CHDIR\))100 L (970)0(ns16552dtr\(p, n\);)16(1038)100(error\(Eperm\);)116 L (971)0(break;)16(1039)100 L (972 case 'E':)0(1040 p = uart[NETID\(c->qid.path\)];)100 L (973 case 'e':)0(1041 if\(p->kinuse\))100 L (974)0(ns16552dsrhup\(p, n\);)16(1042)100(error\(Ekinuse\);)116 L (975)0(break;)16(1043)100 L (976 case 'f':)0(1044 /*)100 L (977 case 'F':)0(1045 * The fifo's turn themselves off sometimes.)100 L (978)0(qflush\(p->oq\);)16(1046 * It must be something I don't understand. -- presotto)100 L (979)0(break;)16(1047 */)100 L (980 case 'H':)0(1048 lock\(&p->flock\);)100 L (981 case 'h':)0(1049 if\(\(p->istat & Fenabd\) == 0 && p->fifoon && p->type < Ns550\))100 L (982)0(qhangup\(p->iq, 0\);)16(1050)100(ns16552fifoon\(p\);)116 L (983)0(qhangup\(p->oq, 0\);)16(1051 unlock\(&p->flock\);)100 L (984)0(break;)16(1052)100 L (985 case 'L':)0(1053 switch\(NETTYPE\(c->qid.path\)\){)100 L (986 case 'l':)0(1054 case Ndataqid:)100 L (987)0(ns16552bits\(p, n\);)16(1055)100(return qwrite\(p->oq, buf, n\);)116 L (988)0(break;)16(1056 case Nctlqid:)100 L (989 case 'm':)0(1057)100(if\(n >= sizeof\(cmd\)\))116 L (990 case 'M':)0(1058)100(n = sizeof\(cmd\)-1;)124 L (991)0(ns16552mflow\(p, n\);)16(1059)100(memmove\(cmd, buf, n\);)116 L (992)0(break;)16(1060)100(cmd[n] = 0;)116 L (993 case 'n':)0(1061)100(ns16552ctl\(p, cmd\);)116 L (994 case 'N':)0(1062)100(return n;)116 L (995)0(qnoblock\(p->oq, n\);)16(1063 })100 L (996)0(break;)16(1064 })100 L (997 case 'P':)0(1065)100 L (998 case 'p':)0(1066 static void)100 L (999)0(ns16552parity\(p, *\(cmd+1\)\);)16(1067 ns16552wstat\(Chan *c, char *dp\))100 L (1000)0(break;)16(1068 {)100 L (1001 case 'K':)0(1069 Dir d;)100 L (1002 case 'k':)0(1070 Dirtab *dt;)100 L (1003)0(ns16552break\(p, n\);)16(1071)100 L (1004)0(break;)16(1072 if\(!iseve\(\)\))100 L (1005 case 'R':)0(1073)100(error\(Eperm\);)116 L (1006 case 'r':)0(1074 if\(CHDIR & c->qid.path\))100 L (1007)0(ns16552rts\(p, n\);)16(1075)100(error\(Eperm\);)116 L (1008)0(break;)16(1076 if\(NETTYPE\(c->qid.path\) == Nstatqid\))100 L (1009 case 'Q':)0(1077)100(error\(Eperm\);)116 L (1010 case 'q':)0(1078)100 L (1011)0(qsetlimit\(p->iq, n\);)16(1079 dt = &ns16552dir[3 * NETID\(c->qid.path\)];)100 L (1012)0(qsetlimit\(p->oq, n\);)16(1080 convM2D\(dp, &d\);)100 L (1013)0(break;)16(1081 d.mode &= 0666;)100 L (1014 case 'T':)0(1082 dt[0].perm = dt[1].perm = d.mode;)100 L (1015 case 't':)0(1083 })100 L (1016)0(ns16552dcdts\(p, n\);)16(1084)100 L (1017)0(break;)16(1085 Dev ns16552devtab = {)100 L (1018 case 'W':)0(1086 't',)100 L (1019 case 'w':)0(1087 "ns16552",)100 L (1020)0(/* obsolete */)16(1088)100 L cleartomark showpage saveobj restore %%EndPage: 143 143 %%Page: 144 144 /saveobj save def mark 144 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devns16552.c Page 9)l ()l ()l (1089 ns16552reset,)0(1157 /* BUG should be configurable */)100 L (1090 devinit,)0(1158 enum {)100 L (1091 ns16552attach,)0(1159 WHICH = 0,)100 L (1092 devclone,)0(1160 RATE = 9600,)100 L (1093 ns16552walk,)0(1161 };)100 L (1094 ns16552stat,)0(1162)100 L (1095 ns16552open,)0(1163 int)100 L (1096 devcreate,)0(1164 serialgetc\(void\))100 L (1097 ns16552close,)0(1165 {)100 L (1098 ns16552read,)0(1166 Uart *p;)100 L (1099 devbread,)0(1167 int c;)100 L (1100 ns16552write,)0(1168)100 L (1101 devbwrite,)0(1169 if\(\(p=uart[WHICH]\) == nil\))100 L (1102 devremove,)0(1170)100(return -1;)116 L (1103 ns16552wstat,)0(1171 if\(!p->kinuse\))100 L (1104 };)0(1172)100(ns16552setuppoll\(p, RATE\);)116 L (1105)0(1173)100 L (1106 /*)0(1174 while\(\(uartrdreg\(p, Lstat\)&Inready\) == 0\))100 L (1107 * Polling I/O routines for kernel debugging helps.)0(1175)100(;)116 L (1108 */)0(1176 c = inb\(p->port+Data\) & 0xFF;)100 L (1109 static void)0(1177 return c;)100 L (1110 ns16552setuppoll\(Uart *p, int rate\))0(1178 // there should be a restore here but i think it will slow things down too much.)100 L (1111 {)0(1179 })100 L (1112 ulong brconst;)0(1180)100 L (1113)0(1181 static void)100 L (1114 /*)0(1182 serialputc\(Uart *p, int c\))100 L (1115 * 8 bits/character, 1 stop bit;)0(1183 {)100 L (1116 * set rate to rate baud;)0(1184 while\(\(uartrdreg\(p, Lstat\)&Outready\) == 0\))100 L (1117 * turn on Rts and Dtr.)0(1185)100(;)116 L (1118 */)0(1186 outb\(p->port+Data, c\);)100 L (1119 memmove\(p->osticky, p->sticky, sizeof p->osticky\);)0(1187 while\(\(uartrdreg\(p, Lstat\)&Outready\) == 0\))100 L (1120)0(1188)100(;)116 L (1121 p->sticky[Format] = Bits8;)0(1189 })100 L (1122 uartwrreg\(p, Format, 0\);)0(1190)100 L (1123)0(1191 void)100 L (1124 brconst = \(UartFREQ+8*rate-1\)/\(16*rate\);)0(1192 serialputs\(char *s, int n\))100 L (1125 uartwrreg\(p, Format, Dra\);)0(1193 {)100 L (1126 outb\(p->port+Dmsb, \(brconst>>8\) & 0xff\);)0(1194 Uart *p;)100 L (1127 outb\(p->port+Dlsb, brconst & 0xff\);)0(1195)100 L (1128 uartwrreg\(p, Format, 0\);)0(1196 if\(\(p=uart[WHICH]\) == nil\))100 L (1129)0(1197)100(return;)116 L (1130 p->sticky[Mctl] = Rts|Dtr;)0(1198 if\(!p->kinuse\))100 L (1131 uartwrreg\(p, Mctl, 0\);)0(1199)100(ns16552setuppoll\(p, RATE\);)116 L (1132)0(1200)100 L (1133 p->kinuse = 1;)0(1201 while\(n-- > 0\){)100 L (1134 })0(1202)100(serialputc\(p, *s\);)116 L (1135)0(1203)100(if\(*s == '\\n'\))116 L (1136 /*)0(1204)100(serialputc\(p, '\\r'\);)124 L (1137 * Restore serial state from before kernel took over.)0(1205)100(s++;)116 L (1138 */)0(1206 })100 L (1139 static void)0(1207 ns16552restore\(p\);)100 L (1140 ns16552restore\(Uart *p\))0(1208 })100 L (1141 {)l (1142 ulong brconst;)l (1143)l (1144 memmove\(p->sticky, p->osticky, sizeof p->sticky\);)l (1145 uartwrreg\(p, Format, 0\);)l (1146)l (1147 brconst = \(UartFREQ+8*p->baud-1\)/\(16*p->baud\);)l (1148 uartwrreg\(p, Format, Dra\);)l (1149 outb\(p->port+Dmsb, \(brconst>>8\) & 0xff\);)l (1150 outb\(p->port+Dlsb, brconst & 0xff\);)l (1151 uartwrreg\(p, Format, 0\);)l (1152)l (1153 uartwrreg\(p, Mctl, 0\);)l (1154 p->kinuse = 0;)l (1155 })l (1156)l cleartomark showpage saveobj restore %%EndPage: 144 144 %%Page: 145 145 /saveobj save def mark 145 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devpipe.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(free\(p\);)116 L (2 #include "../port/lib.h")0(70)100(exhausted\("memory"\);)116 L (3 #include "mem.h")0(71)100(})108 L (4 #include "dat.h")0(72)100(p->q[1] = qopen\(conf.pipeqsize, 0, 0, 0\);)108 L (5 #include "fns.h")0(73)100(if\(p->q[1] == 0\){)108 L (6 #include "../port/error.h")0(74)100(free\(p->q[0]\);)116 L (7)0(75)100(free\(p\);)116 L (8 #include "netif.h")0(76)100(exhausted\("memory"\);)116 L (9)0(77)100(})108 L (10 typedef struct Pipe)0(Pipe;)32(78)100 L (11 struct Pipe)0(79)100(lock\(&pipealloc\);)108 L (12 {)0(80)100(p->path = ++pipealloc.path;)108 L (13)0(QLock;)8(81)100(unlock\(&pipealloc\);)108 L (14)0(Pipe *next;)8(82)100 L (15)0(int ref;)8(83)100(c->qid = \(Qid\){CHDIR|NETQID\(2*p->path, Qdir\), 0};)108 L (16)0(ulong path;)8(84)100(c->aux = p;)108 L (17)0(Queue *q[2];)8(85)100(c->dev = 0;)108 L (18)0(int qref[2];)8(86)100(return c;)108 L (19 };)0(87 })100 L (20)0(88)100 L (21 struct)0(89 static Chan*)100 L (22 {)0(90 pipeclone\(Chan *c, Chan *nc\))100 L (23)0(Lock;)8(91 {)100 L (24)0(ulong path;)8(92)100(Pipe *p;)108 L (25 } pipealloc;)0(93)100 L (26)0(94)100(p = c->aux;)108 L (27 enum)0(95)100(nc = devclone\(c, nc\);)108 L (28 {)0(96)100(qlock\(p\);)108 L (29)0(Qdir,)8(97)100(p->ref++;)108 L (30)0(Qdata0,)8(98)100(if\(c->flag & COPEN\){)108 L (31)0(Qdata1,)8(99)100(switch\(NETTYPE\(c->qid.path\)\){)116 L (32 };)0(100)100(case Qdata0:)116 L (33)0(101)100(p->qref[0]++;)124 L (34 Dirtab pipedir[] =)0(102)100(break;)124 L (35 {)0(103)100(case Qdata1:)116 L (36)0("data",)8({Qdata0},)24(0,)40(0600,)64(104)100(p->qref[1]++;)124 L (37)0("data1",)8({Qdata1},)24(0,)40(0600,)64(105)100(break;)124 L (38 };)0(106)100(})116 L (39 #define NPIPEDIR 2)0(107 })100 L (40)0(108 qunlock\(p\);)100 L (41 static void)0(109 return nc;)100 L (42 pipeinit\(void\))0(110 })100 L (43 {)0(111)100 L (44)0(if\(conf.pipeqsize == 0\){)8(112 static int)100 L (45)0(if\(conf.nmach > 1\))16(113 pipegen\(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp\))100 L (46)0(conf.pipeqsize = 256*1024;)24(114 {)100 L (47)0(else)16(115 int id;)100 L (48)0(conf.pipeqsize = 32*1024;)24(116 int len;)100 L (49)0(})8(117 Pipe *p;)100 L (50 })0(118)100 L (51)0(119 if\(i == DEVDOTDOT\){)100 L (52 /*)0(120)100(devdir\(c, c->qid, "#|", 0, eve, CHDIR|0555, dp\);)116 L (53 * create a pipe, no streams are created until an open)0(121)100(return 1;)116 L (54 */)0(122 })100 L (55 static Chan*)0(123)100 L (56 pipeattach\(char *spec\))0(124 id = NETID\(c->qid.path\);)100 L (57 {)0(125 if\(i > 1\))100 L (58)0(Pipe *p;)8(126)100(id++;)116 L (59)0(Chan *c;)8(127 if\(tab==0 || i>=ntab\))100 L (60)0(128)100(return -1;)116 L (61)0(c = devattach\('|', spec\);)8(129 tab += i;)100 L (62)0(p = malloc\(sizeof\(Pipe\)\);)8(130 p = c->aux;)100 L (63)0(if\(p == 0\))8(131 switch\(tab->qid.path\){)100 L (64)0(exhausted\("memory"\);)16(132 case Qdata0:)100 L (65)0(p->ref = 1;)8(133)100(len = qlen\(p->q[0]\);)116 L (66)0(134)100(break;)116 L (67)0(p->q[0] = qopen\(conf.pipeqsize, 0, 0, 0\);)8(135 case Qdata1:)100 L (68)0(if\(p->q[0] == 0\){)8(136)100(len = qlen\(p->q[1]\);)116 L cleartomark showpage saveobj restore %%EndPage: 145 145 %%Page: 146 146 /saveobj save def mark 146 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devpipe.c Page 2)l ()l ()l (137)0(break;)16(205)100 L (138 default:)0(206 c->mode = openmode\(omode\);)100 L (139)0(len = tab->length;)16(207 c->flag |= COPEN;)100 L (140)0(break;)16(208 c->offset = 0;)100 L (141 })0(209 return c;)100 L (142 devdir\(c, \(Qid\){NETQID\(id, tab->qid.path\),0}, tab->name, len, eve, tab->perm, dp\);)0(210 })100 L (143 return 1;)0(211)100 L (144 })0(212 static void)100 L (145)0(213 pipeclose\(Chan *c\))100 L (146)0(214 {)100 L (147 static int)0(215 Pipe *p;)100 L (148 pipewalk\(Chan *c, char *name\))0(216)100 L (149 {)0(217 p = c->aux;)100 L (150 return devwalk\(c, name, pipedir, NPIPEDIR, pipegen\);)0(218 qlock\(p\);)100 L (151 })0(219)100 L (152)0(220 if\(c->flag & COPEN\){)100 L (153 static void)0(221)100(/*)116 L (154 pipestat\(Chan *c, char *db\))0(222)100(* closing either side hangs up the stream)117 L (155 {)0(223)100(*/)117 L (156 Pipe *p;)0(224)100(switch\(NETTYPE\(c->qid.path\)\){)116 L (157 Dir dir;)0(225)100(case Qdata0:)116 L (158)0(226)100(p->qref[0]--;)124 L (159 p = c->aux;)0(227)100(if\(p->qref[0] == 0\){)124 L (160)0(228)100(qhangup\(p->q[1], 0\);)132 L (161 switch\(NETTYPE\(c->qid.path\)\){)0(229)100(qclose\(p->q[0]\);)132 L (162 case Qdir:)0(230)100(})124 L (163)0(devdir\(c, c->qid, ".", 2*DIRLEN, eve, CHDIR|0555, &dir\);)16(231)100(break;)124 L (164)0(break;)16(232)100(case Qdata1:)116 L (165 case Qdata0:)0(233)100(p->qref[1]--;)124 L (166)0(devdir\(c, c->qid, "data", qlen\(p->q[0]\), eve, 0660, &dir\);)16(234)100(if\(p->qref[1] == 0\){)124 L (167)0(break;)16(235)100(qhangup\(p->q[0], 0\);)132 L (168 case Qdata1:)0(236)100(qclose\(p->q[1]\);)132 L (169)0(devdir\(c, c->qid, "data1", qlen\(p->q[1]\), eve, 0660, &dir\);)16(237)100(})124 L (170)0(break;)16(238)100(break;)124 L (171 default:)0(239)100(})116 L (172)0(panic\("pipestat"\);)16(240 })100 L (173 })0(241)100 L (174 convD2M\(&dir, db\);)0(242)100 L (175 })0(243 /*)100 L (176)0(244)100(* if both sides are closed, they are reusable)109 L (177 /*)0(245)100(*/)109 L (178 * if the stream doesn't exist, create it)0(246 if\(p->qref[0] == 0 && p->qref[1] == 0\){)100 L (179 */)0(247)100(qreopen\(p->q[0]\);)116 L (180 static Chan*)0(248)100(qreopen\(p->q[1]\);)116 L (181 pipeopen\(Chan *c, int omode\))0(249 })100 L (182 {)0(250)100 L (183 Pipe *p;)0(251 /*)100 L (184)0(252)100(* free the structure on last close)109 L (185 if\(c->qid.path & CHDIR\){)0(253)100(*/)109 L (186)0(if\(omode != OREAD\))16(254 p->ref--;)100 L (187)0(error\(Ebadarg\);)24(255 if\(p->ref == 0\){)100 L (188)0(c->mode = omode;)16(256)100(qunlock\(p\);)116 L (189)0(c->flag |= COPEN;)16(257)100(free\(p->q[0]\);)116 L (190)0(c->offset = 0;)16(258)100(free\(p->q[1]\);)116 L (191)0(return c;)16(259)100(free\(p\);)116 L (192 })0(260 } else)100 L (193)0(261)100(qunlock\(p\);)116 L (194 p = c->aux;)0(262 })100 L (195 qlock\(p\);)0(263)100 L (196 switch\(NETTYPE\(c->qid.path\)\){)0(264 static long)100 L (197 case Qdata0:)0(265 piperead\(Chan *c, void *va, long n, vlong\))100 L (198)0(p->qref[0]++;)16(266 {)100 L (199)0(break;)16(267 Pipe *p;)100 L (200 case Qdata1:)0(268)100 L (201)0(p->qref[1]++;)16(269 p = c->aux;)100 L (202)0(break;)16(270)100 L (203 })0(271 switch\(NETTYPE\(c->qid.path\)\){)100 L (204 qunlock\(p\);)0(272 case Qdir:)100 L cleartomark showpage saveobj restore %%EndPage: 146 146 %%Page: 147 147 /saveobj save def mark 147 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devpipe.c Page 3)l ()l ()l (273)0(return devdirread\(c, va, n, pipedir, NPIPEDIR, pipegen\);)16(341 long n;)100 L (274 case Qdata0:)0(342 Pipe *p;)100 L (275)0(return qread\(p->q[0], va, n\);)16(343)100 L (276 case Qdata1:)0(344 if\(waserror\(\)\) {)100 L (277)0(return qread\(p->q[1], va, n\);)16(345)100(/* avoid notes when pipe is a mounted queue */)116 L (278 default:)0(346)100(if\(\(c->flag & CMSG\) == 0\))116 L (279)0(panic\("piperead"\);)16(347)100(postnote\(up, 1, "sys: write on closed pipe", NUser\);)124 L (280 })0(348)100(nexterror\(\);)116 L (281 return -1;)0(/* not reached */)24(349 })100 L (282 })0(350)100 L (283)0(351 p = c->aux;)100 L (284 static Block*)0(352 switch\(NETTYPE\(c->qid.path\)\){)100 L (285 pipebread\(Chan *c, long n, ulong offset\))0(353 case Qdata0:)100 L (286 {)0(354)100(n = qbwrite\(p->q[1], bp\);)116 L (287 Pipe *p;)0(355)100(break;)116 L (288)0(356)100 L (289 p = c->aux;)0(357 case Qdata1:)100 L (290)0(358)100(n = qbwrite\(p->q[0], bp\);)116 L (291 switch\(NETTYPE\(c->qid.path\)\){)0(359)100(break;)116 L (292 case Qdata0:)0(360)100 L (293)0(return qbread\(p->q[0], n\);)16(361 default:)100 L (294 case Qdata1:)0(362)100(n = 0;)116 L (295)0(return qbread\(p->q[1], n\);)16(363)100(panic\("pipebwrite"\);)116 L (296 })0(364 })100 L (297)0(365)100 L (298 return devbread\(c, n, offset\);)0(366 poperror\(\);)100 L (299 })0(367 return n;)100 L (300)0(368 })100 L (301 /*)0(369)100 L (302 * a write to a closed pipe causes a note to be sent to)0(370 Dev pipedevtab = {)100 L (303 * the process.)0(371 '|',)100 L (304 */)0(372 "pipe",)100 L (305 static long)0(373)100 L (306 pipewrite\(Chan *c, void *va, long n, vlong\))0(374 devreset,)100 L (307 {)0(375 pipeinit,)100 L (308 Pipe *p;)0(376 pipeattach,)100 L (309)0(377 pipeclone,)100 L (310 if\(!islo\(\)\))0(378 pipewalk,)100 L (311)0(print\("pipewrite hi %lux\\n", getcallerpc\(&c\)\);)16(379 pipestat,)100 L (312 if\(waserror\(\)\) {)0(380 pipeopen,)100 L (313)0(/* avoid notes when pipe is a mounted queue */)16(381 devcreate,)100 L (314)0(if\(\(c->flag & CMSG\) == 0\))16(382 pipeclose,)100 L (315)0(postnote\(up, 1, "sys: write on closed pipe", NUser\);)24(383 piperead,)100 L (316)0(nexterror\(\);)16(384 pipebread,)100 L (317 })0(385 pipewrite,)100 L (318)0(386 pipebwrite,)100 L (319 p = c->aux;)0(387 devremove,)100 L (320)0(388 devwstat,)100 L (321 switch\(NETTYPE\(c->qid.path\)\){)0(389 };)100 L (322 case Qdata0:)l (323)0(n = qwrite\(p->q[1], va, n\);)16 L (324)0(break;)16 L (325)l (326 case Qdata1:)l (327)0(n = qwrite\(p->q[0], va, n\);)16 L (328)0(break;)16 L (329)l (330 default:)l (331)0(panic\("pipewrite"\);)16 L (332 })l (333)l (334 poperror\(\);)l (335 return n;)l (336 })l (337)l (338 static long)l (339 pipebwrite\(Chan *c, Block *bp, ulong\))l (340 {)l cleartomark showpage saveobj restore %%EndPage: 147 147 %%Page: 148 148 /saveobj save def mark 148 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 1)l ()l ()l (1 #include "u.h")0(69 void)100(procctlreq\(Proc*, char*, int\);)116 L (2 #include "../port/lib.h")0(70 int)100(procctlmemio\(Proc*, ulong, int, void*, int\);)116 L (3 #include "mem.h")0(71 Chan* proctext\(Chan*, Proc*\);)100 L (4 #include "dat.h")0(72 Segment* txt2data\(Proc*, Segment*\);)100 L (5 #include "fns.h")0(73 int)100(procstopped\(void*\);)116 L (6 #include "../port/error.h")0(74 void)100(mntscan\(Mntwalk*, Proc*\);)116 L (7 #include "ureg.h")0(75)100 L (8)0(76 static int)100 L (9 enum)0(77 procgen\(Chan *c, Dirtab *tab, int, int s, Dir *dp\))100 L (10 {)0(78 {)100 L (11)0(Qctl,)8(79)100(Qid qid;)108 L (12)0(Qdir,)8(80)100(Proc *p;)108 L (13)0(Qfd,)8(81)100(Segment *q;)108 L (14)0(Qfpregs,)8(82)100(char buf[NAMELEN];)108 L (15)0(Qkregs,)8(83)100(ulong pid, path, perm, len;)108 L (16)0(Qmem,)8(84)100 L (17)0(Qnote,)8(85)100(if\(s == DEVDOTDOT\){)108 L (18)0(Qnoteid,)8(86)100(c->qid.path = CHDIR;)116 L (19)0(Qnotepg,)8(87)100(devdir\(c, c->qid, "#p", 0, eve, 0555, dp\);)116 L (20)0(Qns,)8(88)100(return 1;)116 L (21)0(Qproc,)8(89)100(})108 L (22)0(Qregs,)8(90)100 L (23)0(Qsegment,)8(91)100(if\(c->qid.path == CHDIR\){)108 L (24)0(Qstatus,)8(92)100(if\(s >= conf.nproc\))116 L (25)0(Qtext,)8(93)100(return -1;)124 L (26)0(Qwait,)8(94)100(p = proctab\(s\);)116 L (27)0(Qprofile,)8(95)100(pid = p->pid;)116 L (28 };)0(96)100(if\(pid == 0\))116 L (29)0(97)100(return 0;)124 L (30 #define STATSIZE)0(\(2*NAMELEN+12+9*12\))32(98)100(sprint\(buf, "%lud", pid\);)116 L (31 Dirtab procdir[] =)0(99)100(qid = \(Qid\){CHDIR|\(\(s+1\)<user, CHDIR|0555, dp\);)116 L (33)0("ctl",)8({Qctl},)24(0,)40(0000,)64(101)100(return 1;)116 L (34)0("fd",)8({Qfd},)24(0,)40(0000,)64(102 })100 L (35)0("fpregs",)8({Qfpregs},)24(sizeof\(FPsave\),)40(0000,)64(103 if\(s >= nelem\(procdir\)\))100 L (36)0("kregs",)8({Qkregs},)24(sizeof\(Ureg\),)40(0440,)64(104)100(return -1;)116 L (37)0("mem",)8({Qmem},)24(0,)40(0000,)64(105 if\(tab\))100 L (38)0("note",)8({Qnote},)24(0,)40(0000,)64(106)100(panic\("procgen"\);)116 L (39)0("noteid",)8({Qnoteid},)24(0,)40(0666,)64(107)100 L (40)0("notepg",)8({Qnotepg},)24(0,)40(0000,)64(108 tab = &procdir[s];)100 L (41)0("ns",)8({Qns},)24(0,)40(0444,)64(109 path = c->qid.path&~\(CHDIR|\(\(1<qid\)\);)100 L (44)0("segment",)8({Qsegment}, 0,)24(0444,)64(112 perm = tab->perm;)100 L (45)0("status",)8({Qstatus},)24(STATSIZE,)40(0444,)64(113 if\(perm == 0\))100 L (46)0("text",)8({Qtext},)24(0,)40(0000,)64(114)100(perm = p->procmode;)116 L (47)0("wait",)8({Qwait},)24(0,)40(0400,)64(115)100 L (48)0("profile",)8({Qprofile}, 0,)24(0400,)64(116 len = tab->length;)100 L (49 };)0(117 switch\(QID\(c->qid\)\) {)100 L (50)0(118 case Qwait:)100 L (51 /* Segment type from portdat.h */)0(119)100(len = p->nwait * sizeof\(Waitmsg\);)116 L (52 char *sname[]={ "Text", "Data", "Bss", "Stack", "Shared", "Phys", "Shdata", "Map" };)0(120)100(break;)116 L (53)0(121 case Qprofile:)100 L (54 /*)0(122)100(q = p->seg[TSEG];)116 L (55 * Qids are, in path:)0(123)100(if\(q && q->profile\) {)116 L (56 *)0(4 bits of file type \(qids above\))17(124)100(len = \(q->top-q->base\)>>LRESPROF;)124 L (57 *)0(23 bits of process slot number + 1)16(125)100(len *= sizeof\(*q->profile\);)124 L (58 *)0(in vers,)21(126)100(})116 L (59 *)0(32 bits of pid, for consistency checking)16(127)100(break;)116 L (60 * If notepg, c->pgrpid.path is pgrp slot, .vers is noteid.)0(128 })100 L (61 */)0(129)100 L (62 #define QSHIFT 5)0(/* location in qid of proc slot # */)32(130 qid = \(Qid\){path|tab->qid.path, c->qid.vers};)100 L (63)0(131 devdir\(c, qid, tab->name, len, p->user, perm, dp\);)100 L (64 #define QID\(q\))0(\(\(\(q\).path&0x0000001F\)>>0\))32(132 return 1;)100 L (65 #define SLOT\(q\))0(\(\(\(\(q\).path&0x07FFFFFE0\)>>QSHIFT\)-1\))32(133 })100 L (66 #define PID\(q\))0(\(\(q\).vers\))32(134)100 L (67 #define NOTEID\(q\))0(\(\(q\).vers\))32(135 static void)100 L (68)0(136 procinit\(void\))100 L cleartomark showpage saveobj restore %%EndPage: 148 148 %%Page: 149 149 /saveobj save def mark 149 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 2)l ()l ()l (137 {)0(205 case Qmem:)100 L (138 if\(conf.nproc >= \(1<<\(16-QSHIFT\)\)-1\))0(206 case Qstatus:)100 L (139)0(print\("warning: too many procs for devproc\\n"\);)16(207 case Qwait:)100 L (140 })0(208 case Qregs:)100 L (141)0(209 case Qfpregs:)100 L (142 static Chan*)0(210)100(break;)116 L (143 procattach\(char *spec\))0(211)100 L (144 {)0(212 case Qns:)100 L (145 return devattach\('p', spec\);)0(213)100(if\(omode != OREAD\))116 L (146 })0(214)100(error\(Eperm\);)124 L (147)0(215)100(c->aux = malloc\(sizeof\(Mntwalk\)\);)116 L (148 static int)0(216)100(break;)116 L (149 procwalk\(Chan *c, char *name\))0(217)100 L (150 {)0(218 case Qnotepg:)100 L (151 return devwalk\(c, name, 0, 0, procgen\);)0(219)100(pg = p->pgrp;)116 L (152 })0(220)100(if\(pg == nil\))116 L (153)0(221)100(error\(Eprocdied\);)124 L (154 static void)0(222)100(if\(omode!=OWRITE || pg->pgrpid == 1\))116 L (155 procstat\(Chan *c, char *db\))0(223)100(error\(Eperm\);)124 L (156 {)0(224)100(c->pgrpid.path = pg->pgrpid+1;)116 L (157 devstat\(c, db, 0, 0, procgen\);)0(225)100(c->pgrpid.vers = p->noteid;)116 L (158 })0(226)100(break;)116 L (159)0(227)100 L (160 static Chan*)0(228 default:)100 L (161 procopen\(Chan *c, int omode\))0(229)100(pprint\("procopen %lux\\n", c->qid\);)116 L (162 {)0(230)100(error\(Egreg\);)116 L (163 Proc *p;)0(231 })100 L (164 Pgrp *pg;)0(232)100 L (165 Chan *tc;)0(233 /* Affix pid to qid */)100 L (166 int pid;)0(234 if\(p->state != Dead\))100 L (167)0(235)100(c->qid.vers = p->pid;)116 L (168 if\(c->qid.path & CHDIR\))0(236)100 L (169)0(return devopen\(c, omode, 0, 0, procgen\);)16(237 /* make sure the process slot didn't get reallocated while we were playing */)100 L (170)0(238 coherence\(\);)100 L (171 p = proctab\(SLOT\(c->qid\)\);)0(239 if\(p->pid != pid\))100 L (172 qlock\(&p->debug\);)0(240)100(error\(Eprocdied\);)116 L (173 if\(waserror\(\)\){)0(241)100 L (174)0(qunlock\(&p->debug\);)16(242 tc = devopen\(c, omode, 0, 0, procgen\);)100 L (175)0(nexterror\(\);)16(243 qunlock\(&p->debug\);)100 L (176 })0(244 poperror\(\);)100 L (177 pid = PID\(c->qid\);)0(245)100 L (178 if\(p->pid != pid\))0(246 return tc;)100 L (179)0(error\(Eprocdied\);)16(247 })100 L (180)0(248)100 L (181 omode = openmode\(omode\);)0(249 static void)100 L (182)0(250 procwstat\(Chan *c, char *db\))100 L (183 switch\(QID\(c->qid\)\){)0(251 {)100 L (184 case Qtext:)0(252 Proc *p;)100 L (185)0(if\(omode != OREAD\))16(253 Dir d;)100 L (186)0(error\(Eperm\);)24(254)100 L (187)0(tc = proctext\(c, p\);)16(255 if\(c->qid.path&CHDIR\))100 L (188)0(tc->offset = 0;)16(256)100(error\(Eperm\);)116 L (189)0(qunlock\(&p->debug\);)16(257)100 L (190)0(poperror\(\);)16(258 p = proctab\(SLOT\(c->qid\)\);)100 L (191)0(return tc;)16(259 if\(waserror\(\)\){)100 L (192)0(260)100(qunlock\(&p->debug\);)116 L (193 case Qproc:)0(261)100(nexterror\(\);)116 L (194 case Qkregs:)0(262 })100 L (195 case Qsegment:)0(263 qlock\(&p->debug\);)100 L (196 case Qprofile:)0(264)100 L (197 case Qfd:)0(265 if\(p->pid != PID\(c->qid\)\))100 L (198)0(if\(omode != OREAD\))16(266)100(error\(Eprocdied\);)116 L (199)0(error\(Eperm\);)24(267)100 L (200)0(break;)16(268 if\(strcmp\(up->user, p->user\) != 0 && strcmp\(up->user, eve\) != 0\))100 L (201)0(269)100(error\(Eperm\);)116 L (202 case Qctl:)0(270)100 L (203 case Qnote:)0(271 convM2D\(db, &d\);)100 L (204 case Qnoteid:)0(272 if\(strcmp\(d.uid, p->user\) != 0\){)100 L cleartomark showpage saveobj restore %%EndPage: 149 149 %%Page: 150 150 /saveobj save def mark 150 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 3)l ()l ()l (273)0(if\(strcmp\(up->user, eve\) != 0\))16(341)100(free\(c->aux\);)116 L (274)0(error\(Eperm\);)24(342 })100 L (275)0(else {)16(343)100 L (276)0(strncpy\(p->user, d.uid, sizeof\(p->user\)\);)24(344 static void)100 L (277)0(p->user[sizeof\(p->user\)-1] = 0;)24(345 int2flag\(int flag, char *s\))100 L (278)0(})16(346 {)100 L (279 })0(347 if\(flag == 0\){)100 L (280 p->procmode = d.mode&0777;)0(348)100(*s = '\\0';)116 L (281)0(349)100(return;)116 L (282 poperror\(\);)0(350 })100 L (283 qunlock\(&p->debug\);)0(351 *s++ = '-';)100 L (284 })0(352 if\(flag & MAFTER\))100 L (285)0(353)100(*s++ = 'a';)116 L (286 static int)0(354 if\(flag & MBEFORE\))100 L (287 procfds\(Proc *p, char *va, int count, long offset\))0(355)100(*s++ = 'b';)116 L (288 {)0(356 if\(flag & MCREATE\))100 L (289 Fgrp *f;)0(357)100(*s++ = 'c';)116 L (290 Chan *c;)0(358 if\(flag & MCACHE\))100 L (291 int n, i;)0(359)100(*s++ = 'C';)116 L (292)0(360 *s = '\\0';)100 L (293 qlock\(&p->debug\);)0(361 })100 L (294 f = p->fgrp;)0(362)100 L (295 if\(f == nil\){)0(363 static long)100 L (296)0(qunlock\(&p->debug\);)16(364 procread\(Chan *c, void *va, long n, vlong off\))100 L (297)0(return 0;)16(365 {)100 L (298 })0(366 long l;)100 L (299 lock\(f\);)0(367 Proc *p;)100 L (300 if\(waserror\(\)\){)0(368 Waitq *wq;)100 L (301)0(unlock\(f\);)16(369 Ureg kur;)100 L (302)0(qunlock\(&p->debug\);)16(370 uchar *rptr;)100 L (303)0(nexterror\(\);)16(371 Mntwalk *mw;)100 L (304 })0(372 Segment *sg, *s;)100 L (305)0(373 char *a = va, *sps;)100 L (306 n = readstr\(0, va, count, p->dot->name->s\);)0(374 int i, j, rsize, pid;)100 L (307 n += snprint\(va+n, count-n, "\\n"\);)0(375 char statbuf[NSEG*32], *srv, flag[10];)100 L (308 for\(i = 0; i <= f->maxfd; i++\) {)0(376 ulong offset = off;)100 L (309)0(c = f->fd[i];)16(377)100 L (310)0(if\(c == nil\))16(378 if\(c->qid.path & CHDIR\))100 L (311)0(continue;)24(379)100(return devdirread\(c, a, n, 0, 0, procgen\);)116 L (312)0(n += snprint\(va+n, count-n, "%3d %.2s %C %4ld %.8lux.%.8lud %8lld ",)16(380)100 L (313)0(i,)24(381 p = proctab\(SLOT\(c->qid\)\);)100 L (314)0(&"r w rw"[\(c->mode&3\)<<1],)24(382 if\(p->pid != PID\(c->qid\)\))100 L (315)0(devtab[c->type]->dc, c->dev,)24(383)100(error\(Eprocdied\);)116 L (316)0(c->qid.path, c->qid.vers,)24(384)100 L (317)0(c->offset\);)24(385 switch\(QID\(c->qid\)\){)100 L (318)0(n += readstr\(0, va+n, count-n, c->name->s\);)16(386 case Qmem:)100 L (319)0(n += snprint\(va+n, count-n, "\\n"\);)16(387)100(if\(offset < KZERO)116 L (320)0(if\(offset > 0\) {)16(388)100(|| \(offset >= USTKTOP-USTKSIZE && offset < USTKTOP\)\))116 L (321)0(offset -= n;)24(389)100(return procctlmemio\(p, offset, n, va, 1\);)124 L (322)0(if\(offset < 0\) {)24(390)100 L (323)0(memmove\(va, va+n+offset, -offset\);)32(391)100(/* Protect crypt key memory */)116 L (324)0(n = -offset;)32(392)100(if\(offset+n >= palloc.cmembase && offset < palloc.cmemtop\))116 L (325)0(})24(393)100(error\(Eperm\);)124 L (326)0(else)24(394)100 L (327)0(n = 0;)32(395)100(/* validate physical kernel addresses */)116 L (328)0(})16(396)100(if\(offset < \(ulong\)end\) {)116 L (329 })0(397)100(if\(offset+n > \(ulong\)end\))124 L (330 unlock\(f\);)0(398)100(n = \(ulong\)end - offset;)132 L (331 qunlock\(&p->debug\);)0(399)100(memmove\(a, \(char*\)offset, n\);)124 L (332 poperror\(\);)0(400)100(return n;)124 L (333)0(401)100(})116 L (334 return n;)0(402)100(if\(offset >= conf.base0 && offset < conf.npage0\){)116 L (335 })0(403)100(if\(offset+n > conf.npage0\))124 L (336)0(404)100(n = conf.npage0 - offset;)132 L (337 static void)0(405)100(memmove\(a, \(char*\)offset, n\);)124 L (338 procclose\(Chan * c\))0(406)100(return n;)124 L (339 {)0(407)100(})116 L (340 if\(QID\(c->qid\) == Qns && c->aux != 0\))0(408)100(if\(offset >= conf.base1 && offset < conf.npage1\){)116 L cleartomark showpage saveobj restore %%EndPage: 150 150 %%Page: 151 151 /saveobj save def mark 151 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 4)l ()l ()l (409)0(if\(offset+n > conf.npage1\))24(477)100(error\(Enoreg\);)124 L (410)0(n = conf.npage1 - offset;)32(478)100(if\(offset >= rsize\))116 L (411)0(memmove\(a, \(char*\)offset, n\);)24(479)100(return 0;)124 L (412)0(return n;)24(480)100(if\(offset+n > rsize\))116 L (413)0(})16(481)100(n = rsize - offset;)124 L (414)0(error\(Ebadarg\);)16(482)100(memmove\(a, rptr+offset, n\);)116 L (415 case Qprofile:)0(483)100(return n;)116 L (416)0(s = p->seg[TSEG];)16(484)100 L (417)0(if\(s == 0 || s->profile == 0\))16(485 case Qstatus:)100 L (418)0(error\("profile is off"\);)24(486)100(if\(offset >= STATSIZE\))116 L (419)0(i = \(s->top-s->base\)>>LRESPROF;)16(487)100(return 0;)124 L (420)0(i *= sizeof\(*s->profile\);)16(488)100(if\(offset+n > STATSIZE\))116 L (421)0(if\(offset >= i\))16(489)100(n = STATSIZE - offset;)124 L (422)0(return 0;)24(490)100 L (423)0(if\(offset+n > i\))16(491)100(sps = p->psstate;)116 L (424)0(n = i - offset;)24(492)100(if\(sps == 0\))116 L (425)0(memmove\(a, \(\(char*\)s->profile\)+offset, n\);)16(493)100(sps = statename[p->state];)124 L (426)0(return n;)16(494)100(memset\(statbuf, ' ', sizeof statbuf\);)116 L (427)0(495)100(memmove\(statbuf+0*NAMELEN, p->text, strlen\(p->text\)\);)116 L (428 case Qnote:)0(496)100(memmove\(statbuf+1*NAMELEN, p->user, strlen\(p->user\)\);)116 L (429)0(qlock\(&p->debug\);)16(497)100(memmove\(statbuf+2*NAMELEN, sps, strlen\(sps\)\);)116 L (430)0(if\(waserror\(\)\){)16(498)100(j = 2*NAMELEN + 12;)116 L (431)0(qunlock\(&p->debug\);)24(499)100 L (432)0(nexterror\(\);)24(500)100(for\(i = 0; i < 6; i++\) {)116 L (433)0(})16(501)100(l = p->time[i];)124 L (434)0(if\(p->pid != PID\(c->qid\)\))16(502)100(if\(i == TReal\))124 L (435)0(error\(Eprocdied\);)24(503)100(l = MACHP\(0\)->ticks - l;)132 L (436)0(if\(n < ERRLEN\))16(504)100(l = TK2MS\(l\);)124 L (437)0(error\(Etoosmall\);)24(505)100(readnum\(0, statbuf+j+NUMSIZE*i, NUMSIZE, l, NUMSIZE\);)124 L (438)0(if\(p->nnote == 0\))16(506)100(})116 L (439)0(n = 0;)24(507)100(/* ignore stack, which is mostly non-existent */)116 L (440)0(else {)16(508)100(l = 0;)116 L (441)0(memmove\(va, p->note[0].msg, ERRLEN\);)24(509)100(for\(i=1; innote--;)24(510)100(s = p->seg[i];)124 L (443)0(memmove\(p->note, p->note+1, p->nnote*sizeof\(Note\)\);)24(511)100(if\(s\))124 L (444)0(n = ERRLEN;)24(512)100(l += s->top - s->base;)132 L (445)0(})16(513)100(})116 L (446)0(if\(p->nnote == 0\))16(514)100(readnum\(0, statbuf+j+NUMSIZE*6, NUMSIZE, l>>10, NUMSIZE\);)116 L (447)0(p->notepending = 0;)24(515)100(readnum\(0, statbuf+j+NUMSIZE*7, NUMSIZE, p->basepri, NUMSIZE\);)116 L (448)0(poperror\(\);)16(516)100(readnum\(0, statbuf+j+NUMSIZE*8, NUMSIZE, p->priority, NUMSIZE\);)116 L (449)0(qunlock\(&p->debug\);)16(517)100(memmove\(a, statbuf+offset, n\);)116 L (450)0(return n;)16(518)100(return n;)116 L (451)0(519)100 L (452 case Qproc:)0(520 case Qsegment:)100 L (453)0(if\(offset >= sizeof\(Proc\)\))16(521)100(j = 0;)116 L (454)0(return 0;)24(522)100(for\(i = 0; i < NSEG; i++\) {)116 L (455)0(if\(offset+n > sizeof\(Proc\)\))16(523)100(sg = p->seg[i];)124 L (456)0(n = sizeof\(Proc\) - offset;)24(524)100(if\(sg == 0\))124 L (457)0(memmove\(a, \(\(char*\)p\)+offset, n\);)16(525)100(continue;)132 L (458)0(return n;)16(526)100(j += sprint\(statbuf+j, "%-6s %c%c %.8lux %.8lux %4ld\\n",)124 L (459)0(527)100(sname[sg->type&SG_TYPE],)132 L (460 case Qregs:)0(528)100(sg->type&SG_RONLY ? 'R' : ' ',)132 L (461)0(rptr = \(uchar*\)p->dbgreg;)16(529)100(sg->profile ? 'P' : ' ',)132 L (462)0(rsize = sizeof\(Ureg\);)16(530)100(sg->base, sg->top, sg->ref\);)132 L (463)0(goto regread;)16(531)100(})116 L (464)0(532)100(if\(offset >= j\))116 L (465 case Qkregs:)0(533)100(return 0;)124 L (466)0(memset\(&kur, 0, sizeof\(Ureg\)\);)16(534)100(if\(offset+n > j\))116 L (467)0(setkernur\(&kur, p\);)16(535)100(n = j-offset;)124 L (468)0(rptr = \(uchar*\)&kur;)16(536)100(if\(n == 0 && offset == 0\))116 L (469)0(rsize = sizeof\(Ureg\);)16(537)100(exhausted\("segments"\);)124 L (470)0(goto regread;)16(538)100(memmove\(a, &statbuf[offset], n\);)116 L (471)0(539)100(return n;)116 L (472 case Qfpregs:)0(540)100 L (473)0(rptr = \(uchar*\)&p->fpsave;)16(541 case Qwait:)100 L (474)0(rsize = sizeof\(FPsave\);)16(542)100(if\(n < sizeof\(Waitmsg\)\))116 L (475 regread:)0(543)100(error\(Etoosmall\);)124 L (476)0(if\(rptr == 0\))16(544)100 L cleartomark showpage saveobj restore %%EndPage: 151 151 %%Page: 152 152 /saveobj save def mark 152 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 5)l ()l ()l (545)0(if\(!canqlock\(&p->qwaitr\)\))16(613 case Qnoteid:)100 L (546)0(error\(Einuse\);)24(614)100(return readnum\(offset, va, n, p->noteid, NUMSIZE\);)116 L (547)0(615 case Qfd:)100 L (548)0(if\(waserror\(\)\) {)16(616)100(return procfds\(p, va, n, offset\);)116 L (549)0(qunlock\(&p->qwaitr\);)24(617 })100 L (550)0(nexterror\(\);)24(618 error\(Egreg\);)100 L (551)0(})16(619 return 0;)100(/* not reached */)132 L (552)0(620 })100 L (553)0(lock\(&p->exl\);)16(621)100 L (554)0(if\(up == p && p->nchild == 0 && p->waitq == 0\) {)16(622 void)100 L (555)0(unlock\(&p->exl\);)24(623 mntscan\(Mntwalk *mw, Proc *p\))100 L (556)0(error\(Enochild\);)24(624 {)100 L (557)0(})16(625 Pgrp *pg;)100 L (558)0(pid = p->pid;)16(626 Mount *t;)100 L (559)0(while\(p->waitq == 0\) {)16(627 Mhead *f;)100 L (560)0(unlock\(&p->exl\);)24(628 int nxt, i;)100 L (561)0(sleep\(&p->waitr, haswaitq, p\);)24(629 ulong last, bestmid;)100 L (562)0(if\(p->pid != pid\))24(630)100 L (563)0(error\(Eprocdied\);)32(631 pg = p->pgrp;)100 L (564)0(lock\(&p->exl\);)24(632 rlock\(&pg->ns\);)100 L (565)0(})16(633)100 L (566)0(wq = p->waitq;)16(634 nxt = 0;)100 L (567)0(p->waitq = wq->next;)16(635 bestmid = ~0;)100 L (568)0(p->nwait--;)16(636)100 L (569)0(unlock\(&p->exl\);)16(637 last = 0;)100 L (570)0(638 if\(mw->mh\))100 L (571)0(qunlock\(&p->qwaitr\);)16(639)100(last = mw->cm->mountid;)116 L (572)0(poperror\(\);)16(640)100 L (573)0(memmove\(a, &wq->w, sizeof\(Waitmsg\)\);)16(641 for\(i = 0; i < MNTHASH; i++\) {)100 L (574)0(free\(wq\);)16(642)100(for\(f = pg->mnthash[i]; f; f = f->hash\) {)116 L (575)0(return sizeof\(Waitmsg\);)16(643)100(for\(t = f->mount; t; t = t->next\) {)124 L (576)0(644)100(if\(mw->mh == 0 ||)132 L (577 case Qns:)0(645)100(\(t->mountid > last && t->mountid < bestmid\)\) {)134 L (578)0(qlock\(&p->debug\);)16(646)100(mw->cm = t;)140 L (579)0(if\(waserror\(\)\){)16(647)100(mw->mh = f;)140 L (580)0(qunlock\(&p->debug\);)24(648)100(bestmid = mw->cm->mountid;)140 L (581)0(nexterror\(\);)24(649)100(nxt = 1;)140 L (582)0(})16(650)100(})132 L (583)0(if\(p->pgrp == nil || p->pid != PID\(c->qid\)\))16(651)100(})124 L (584)0(error\(Eprocdied\);)24(652)100(})116 L (585)0(mw = c->aux;)16(653 })100 L (586)0(if\(mw->cddone\){)16(654 if\(nxt == 0\))100 L (587)0(qunlock\(&p->debug\);)24(655)100(mw->mh = 0;)116 L (588)0(poperror\(\);)24(656)100 L (589)0(return 0;)24(657 runlock\(&pg->ns\);)100 L (590)0(})16(658 })100 L (591)0(mntscan\(mw, p\);)16(659)100 L (592)0(if\(mw->mh == 0\){)16(660 static long)100 L (593)0(mw->cddone = 1;)24(661 procwrite\(Chan *c, void *va, long n, vlong off\))100 L (594)0(i = snprint\(a, n, "cd %s\\n", p->dot->name->s\);)24(662 {)100 L (595)0(qunlock\(&p->debug\);)24(663 int id;)100 L (596)0(poperror\(\);)24(664 Proc *p, *t, *et;)100 L (597)0(return i;)24(665 char *a, buf[ERRLEN];)100 L (598)0(})16(666 ulong offset = off;)100 L (599)0(int2flag\(mw->cm->flag, flag\);)16(667)100 L (600)0(if\(strcmp\(mw->cm->to->name->s, "#M"\) == 0\){)16(668 a = va;)100 L (601)0(srv = srvname\(mw->cm->to->mchan\);)24(669 if\(c->qid.path & CHDIR\))100 L (602)0(i = snprint\(a, n, "mount %s %s %s %.*s\\n", flag,)24(670)100(error\(Eisdir\);)116 L (603)0(srv==nil? mw->cm->to->mchan->name->s : srv,)32(671)100 L (604)0(mw->mh->from->name->s, NAMELEN, mw->cm->spec\);)32(672 p = proctab\(SLOT\(c->qid\)\);)100 L (605)0(free\(srv\);)24(673)100 L (606)0(}else)16(674 /* Use the remembered noteid in the channel rather)100 L (607)0(i = snprint\(a, n, "bind %s %s %s\\n", flag,)24(675)100(* than the process pgrpid)109 L (608)0(mw->cm->to->name->s, mw->mh->from->name->s\);)32(676)100(*/)109 L (609)0(qunlock\(&p->debug\);)16(677 if\(QID\(c->qid\) == Qnotepg\) {)100 L (610)0(poperror\(\);)16(678)100(pgrpnote\(NOTEID\(c->pgrpid\), va, n, NUser\);)116 L (611)0(return i;)16(679)100(return n;)116 L (612)0(680 })100 L cleartomark showpage saveobj restore %%EndPage: 152 152 %%Page: 153 153 /saveobj save def mark 153 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 6)l ()l ()l (681)0(749)100(pprint\("unknown qid in procwrite\\n"\);)116 L (682 qlock\(&p->debug\);)0(750)100(error\(Egreg\);)116 L (683 if\(waserror\(\)\){)0(751 })100 L (684)0(qunlock\(&p->debug\);)16(752 poperror\(\);)100 L (685)0(nexterror\(\);)16(753 qunlock\(&p->debug\);)100 L (686 })0(754 return n;)100 L (687 if\(p->pid != PID\(c->qid\)\))0(755 })100 L (688)0(error\(Eprocdied\);)16(756)100 L (689)0(757 Dev procdevtab = {)100 L (690 switch\(QID\(c->qid\)\){)0(758 'p',)100 L (691 case Qmem:)0(759 "proc",)100 L (692)0(if\(p->state != Stopped\))16(760)100 L (693)0(error\(Ebadctl\);)24(761 devreset,)100 L (694)0(762 procinit,)100 L (695)0(n = procctlmemio\(p, offset, n, va, 0\);)16(763 procattach,)100 L (696)0(break;)16(764 devclone,)100 L (697)0(765 procwalk,)100 L (698 case Qregs:)0(766 procstat,)100 L (699)0(if\(offset >= sizeof\(Ureg\)\))16(767 procopen,)100 L (700)0(return 0;)24(768 devcreate,)100 L (701)0(if\(offset+n > sizeof\(Ureg\)\))16(769 procclose,)100 L (702)0(n = sizeof\(Ureg\) - offset;)24(770 procread,)100 L (703)0(if\(p->dbgreg == 0\))16(771 devbread,)100 L (704)0(error\(Enoreg\);)24(772 procwrite,)100 L (705)0(setregisters\(p->dbgreg, \(char*\)\(p->dbgreg\)+offset, va, n\);)16(773 devbwrite,)100 L (706)0(break;)16(774 devremove,)100 L (707)0(775 procwstat,)100 L (708 case Qfpregs:)0(776 };)100 L (709)0(if\(offset >= sizeof\(FPsave\)\))16(777)100 L (710)0(return 0;)24(778 Chan*)100 L (711)0(if\(offset+n > sizeof\(FPsave\)\))16(779 proctext\(Chan *c, Proc *p\))100 L (712)0(n = sizeof\(FPsave\) - offset;)24(780 {)100 L (713)0(memmove\(\(uchar*\)&p->fpsave+offset, va, n\);)16(781 Chan *tc;)100 L (714)0(break;)16(782 Image *i;)100 L (715)0(783 Segment *s;)100 L (716 case Qctl:)0(784)100 L (717)0(procctlreq\(p, va, n\);)16(785 s = p->seg[TSEG];)100 L (718)0(break;)16(786 if\(s == 0\))100 L (719)0(787)100(error\(Enonexist\);)116 L (720 case Qnote:)0(788 if\(p->state==Dead\))100 L (721)0(if\(p->kp\))16(789)100(error\(Eprocdied\);)116 L (722)0(error\(Eperm\);)24(790)100 L (723)0(if\(n >= ERRLEN-1\))16(791 lock\(s\);)100 L (724)0(error\(Etoobig\);)24(792 i = s->image;)100 L (725)0(memmove\(buf, va, n\);)16(793 if\(i == 0\) {)100 L (726)0(buf[n] = 0;)16(794)100(unlock\(s\);)116 L (727)0(if\(!postnote\(p, 0, buf, NUser\)\))16(795)100(error\(Eprocdied\);)116 L (728)0(error\("note not posted"\);)24(796 })100 L (729)0(break;)16(797 unlock\(s\);)100 L (730 case Qnoteid:)0(798)100 L (731)0(id = atoi\(a\);)16(799 lock\(i\);)100 L (732)0(if\(id == p->pid\) {)16(800 if\(waserror\(\)\) {)100 L (733)0(p->noteid = id;)24(801)100(unlock\(i\);)116 L (734)0(break;)24(802)100(nexterror\(\);)116 L (735)0(})16(803 })100 L (736)0(t = proctab\(0\);)16(804)100 L (737)0(for\(et = t+conf.nproc; t < et; t++\) {)16(805 tc = i->c;)100 L (738)0(if\(id == t->noteid\) {)24(806 if\(tc == 0\))100 L (739)0(if\(strcmp\(p->user, t->user\) != 0\))32(807)100(error\(Eprocdied\);)116 L (740)0(error\(Eperm\);)40(808)100 L (741)0(p->noteid = id;)32(809 if\(incref\(tc\) == 1 || \(tc->flag&COPEN\) == 0 || tc->mode!=OREAD\) {)100 L (742)0(break;)32(810)100(cclose\(tc\);)116 L (743)0(})24(811)100(error\(Eprocdied\);)116 L (744)0(})16(812 })100 L (745)0(if\(p->noteid != id\))16(813)100 L (746)0(error\(Ebadarg\);)24(814 if\(p->pid != PID\(c->qid\)\))100 L (747)0(break;)16(815)100(error\(Eprocdied\);)116 L (748 default:)0(816)100 L cleartomark showpage saveobj restore %%EndPage: 153 153 %%Page: 154 154 /saveobj save def mark 154 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 7)l ()l ()l (817 unlock\(i\);)0(885 else)100 L (818 poperror\(\);)0(886 if\(strncmp\(buf, "kill", 4\) == 0\) {)100 L (819)0(887)100(switch\(p->state\) {)116 L (820 return tc;)0(888)100(case Broken:)116 L (821 })0(889)100(unbreak\(p\);)124 L (822)0(890)100(break;)124 L (823 void)0(891)100(case Stopped:)116 L (824 procstopwait\(Proc *p, int ctl\))0(892)100(postnote\(p, 0, "sys: killed", NExit\);)124 L (825 {)0(893)100(p->procctl = Proc_exitme;)124 L (826 int pid;)0(894)100(ready\(p\);)124 L (827)0(895)100(break;)124 L (828 if\(p->pdbg\))0(896)100(default:)116 L (829)0(error\(Einuse\);)16(897)100(postnote\(p, 0, "sys: killed", NExit\);)124 L (830 if\(procstopped\(p\)\))0(898)100(p->procctl = Proc_exitme;)124 L (831)0(return;)16(899)100(})116 L (832)0(900 })100 L (833 if\(ctl != 0\))0(901 else)100 L (834)0(p->procctl = ctl;)16(902 if\(strncmp\(buf, "hang", 4\) == 0\))100 L (835 p->pdbg = up;)0(903)100(p->hang = 1;)116 L (836 pid = p->pid;)0(904 else)100 L (837 qunlock\(&p->debug\);)0(905 if\(strncmp\(buf, "nohang", 6\) == 0\))100 L (838 up->psstate = "Stopwait";)0(906)100(p->hang = 0;)116 L (839 if\(waserror\(\)\) {)0(907 else)100 L (840)0(p->pdbg = 0;)16(908 if\(strncmp\(buf, "waitstop", 8\) == 0\))100 L (841)0(qlock\(&p->debug\);)16(909)100(procstopwait\(p, 0\);)116 L (842)0(nexterror\(\);)16(910 else)100 L (843 })0(911 if\(strncmp\(buf, "startstop", 9\) == 0\) {)100 L (844 sleep\(&up->sleep, procstopped, p\);)0(912)100(if\(p->state != Stopped\))116 L (845 poperror\(\);)0(913)100(error\(Ebadctl\);)124 L (846 qlock\(&p->debug\);)0(914)100(p->procctl = Proc_traceme;)116 L (847 if\(p->pid != pid\))0(915)100(ready\(p\);)116 L (848)0(error\(Eprocdied\);)16(916)100(procstopwait\(p, Proc_traceme\);)116 L (849 })0(917 })100 L (850)0(918 else)100 L (851 void)0(919 if\(strncmp\(buf, "start", 5\) == 0\) {)100 L (852 procctlfgrp\(Fgrp *f\))0(920)100(if\(p->state != Stopped\))116 L (853 {)0(921)100(error\(Ebadctl\);)124 L (854 int i;)0(922)100(ready\(p\);)116 L (855 Chan *c;)0(923 })100 L (856)0(924 else)100 L (857 lock\(f\);)0(925 if\(strncmp\(buf, "closefiles", 10\) == 0\){)100 L (858 f->ref++;)0(926)100(qlock\(&p->debug\);)116 L (859 for\(i = 0; i < f->maxfd; i++\) {)0(927)100(if\(waserror\(\)\){)116 L (860)0(c = f->fd[i];)16(928)100(qunlock\(&p->debug\);)124 L (861)0(if\(c != 0\) {)16(929)100(nexterror\(\);)124 L (862)0(f->fd[i] = 0;)24(930)100(})116 L (863)0(unlock\(f\);)24(931)100(if\(p->fgrp == nil\))116 L (864)0(cclose\(c\);)24(932)100(error\(Eprocdied\);)124 L (865)0(lock\(f\);)24(933)100(procctlfgrp\(p->fgrp\);)116 L (866)0(})16(934)100(qunlock\(&p->debug\);)116 L (867 })0(935)100(poperror\(\);)116 L (868 unlock\(f\);)0(936 })100 L (869 closefgrp\(f\);)0(937 else)100 L (870 })0(938 if\(strncmp\(buf, "pri", 3\) == 0\) {)100 L (871)0(939)100(if\(n < 4\))116 L (872 void)0(940)100(error\(Ebadctl\);)124 L (873 procctlreq\(Proc *p, char *va, int n\))0(941)100(i = atoi\(buf+4\);)116 L (874 {)0(942)100(if\(i < 0\))116 L (875 Segment *s;)0(943)100(i = 0;)124 L (876 int i, npc;)0(944)100(if\(i >= Nrq\))116 L (877 char buf[NAMELEN];)0(945)100(i = Nrq - 1;)124 L (878)0(946)100(if\(i > p->basepri && !iseve\(\)\))116 L (879 if\(n > NAMELEN\))0(947)100(error\(Eperm\);)124 L (880)0(n = NAMELEN;)16(948)100(p->basepri = i;)116 L (881 strncpy\(buf, va, n\);)0(949 })100 L (882)0(950 else)100 L (883 if\(strncmp\(buf, "stop", 4\) == 0\))0(951 if\(strncmp\(buf, "wired", 5\) == 0\) {)100 L (884)0(procstopwait\(p, Proc_stopme\);)16(952)100(if\(n < 6\))116 L cleartomark showpage saveobj restore %%EndPage: 154 154 %%Page: 155 155 /saveobj save def mark 155 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 8)l ()l ()l (953)0(error\(Ebadctl\);)24(1021 if\(n > l\))100 L (954)0(i = atoi\(buf+6\);)16(1022)100(n = l;)116 L (955)0(procwired\(p, i\);)16(1023)100 L (956 })0(1024 k = kmap\(pg\);)100 L (957 else)0(1025 if\(waserror\(\)\) {)100 L (958 if\(strncmp\(buf, "profile", 7\) == 0\) {)0(1026)100(s->steal--;)116 L (959)0(s = p->seg[TSEG];)16(1027)100(kunmap\(k\);)116 L (960)0(if\(s == 0 || \(s->type&SG_TYPE\) != SG_TEXT\))16(1028)100(nexterror\(\);)116 L (961)0(error\(Ebadctl\);)24(1029 })100 L (962)0(if\(s->profile != 0\))16(1030 b = \(char*\)VA\(k\);)100 L (963)0(free\(s->profile\);)24(1031 b += offset&\(BY2PG-1\);)100 L (964)0(npc = \(s->top-s->base\)>>LRESPROF;)16(1032 if\(read == 1\))100 L (965)0(s->profile = malloc\(npc*sizeof\(*s->profile\)\);)16(1033)100(memmove\(a, b, n\);)116(/* This can fault */)140 L (966)0(if\(s->profile == 0\))16(1034 else)100 L (967)0(error\(Enomem\);)24(1035)100(memmove\(b, a, n\);)116 L (968 })0(1036 kunmap\(k\);)100 L (969 else)0(1037 poperror\(\);)100 L (970)0(error\(Ebadctl\);)16(1038)100 L (971 })0(1039 /* Ensure the process sees text page changes */)100 L (972)0(1040 if\(s->flushme\))100 L (973 int)0(1041)100(memset\(pg->cachectl, PG_TXTFLUSH, sizeof\(pg->cachectl\)\);)116 L (974 procstopped\(void *a\))0(1042)100 L (975 {)0(1043 s->steal--;)100 L (976 Proc *p = a;)0(1044)100 L (977 return p->state == Stopped;)0(1045 if\(read == 0\))100 L (978 })0(1046)100(p->newtlb = 1;)116 L (979)0(1047)100 L (980 int)0(1048 return n;)100 L (981 procctlmemio\(Proc *p, ulong offset, int n, void *va, int read\))0(1049 })100 L (982 {)0(1050)100 L (983 KMap *k;)0(1051 Segment*)100 L (984 Pte *pte;)0(1052 txt2data\(Proc *p, Segment *s\))100 L (985 Page *pg;)0(1053 {)100 L (986 Segment *s;)0(1054 int i;)100 L (987 ulong soff, l;)0(1055 Segment *ps;)100 L (988 char *a = va, *b;)0(1056)100 L (989)0(1057 ps = newseg\(SG_DATA, s->base, s->size\);)100 L (990 for\(;;\) {)0(1058 ps->image = s->image;)100 L (991)0(s = seg\(p, offset, 1\);)16(1059 incref\(ps->image\);)100 L (992)0(if\(s == 0\))16(1060 ps->fstart = s->fstart;)100 L (993)0(error\(Ebadarg\);)24(1061 ps->flen = s->flen;)100 L (994)0(1062 ps->flushme = 1;)100 L (995)0(if\(offset+n >= s->top\))16(1063)100 L (996)0(n = s->top-offset;)24(1064 qlock\(&p->seglock\);)100 L (997)0(1065 for\(i = 0; i < NSEG; i++\))100 L (998)0(if\(!read && \(s->type&SG_TYPE\) == SG_TEXT\))16(1066)100(if\(p->seg[i] == s\))116 L (999)0(s = txt2data\(p, s\);)24(1067)100(break;)124 L (1000)0(1068 if\(p->seg[i] != s\))100 L (1001)0(s->steal++;)16(1069)100(panic\("segment gone"\);)116 L (1002)0(soff = offset-s->base;)16(1070)100 L (1003)0(if\(waserror\(\)\) {)16(1071 qunlock\(&s->lk\);)100 L (1004)0(s->steal--;)24(1072 putseg\(s\);)100 L (1005)0(nexterror\(\);)24(1073 qlock\(&ps->lk\);)100 L (1006)0(})16(1074 p->seg[i] = ps;)100 L (1007)0(if\(fixfault\(s, offset, read, 0\) == 0\))16(1075 qunlock\(&p->seglock\);)100 L (1008)0(break;)24(1076)100 L (1009)0(poperror\(\);)16(1077 return ps;)100 L (1010)0(s->steal--;)16(1078 })100 L (1011 })0(1079)100 L (1012 poperror\(\);)0(1080 Segment*)100 L (1013 pte = s->map[soff/PTEMAPMEM];)0(1081 data2txt\(Segment *s\))100 L (1014 if\(pte == 0\))0(1082 {)100 L (1015)0(panic\("procctlmemio"\);)16(1083 Segment *ps;)100 L (1016 pg = pte->pages[\(soff&\(PTEMAPMEM-1\)\)/BY2PG];)0(1084)100 L (1017 if\(pagedout\(pg\)\))0(1085 ps = newseg\(SG_TEXT, s->base, s->size\);)100 L (1018)0(panic\("procctlmemio1"\);)16(1086 ps->image = s->image;)100 L (1019)0(1087 incref\(ps->image\);)100 L (1020 l = BY2PG - \(offset&\(BY2PG-1\)\);)0(1088 ps->fstart = s->fstart;)100 L cleartomark showpage saveobj restore %%EndPage: 155 155 %%Page: 156 156 /saveobj save def mark 156 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devproc.c Page 9)l ()l ()l (1089 ps->flen = s->flen;)l (1090 ps->flushme = 1;)l (1091)l (1092 return ps;)l (1093 })l cleartomark showpage saveobj restore %%EndPage: 156 156 %%Page: 157 157 /saveobj save def mark 157 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devroot.c Page 1)l ()l ()l (1 #include "u.h")0(69 * add a root file)100 L (2 #include "../port/lib.h")0(70 */)100 L (3 #include "mem.h")0(71 static void)100 L (4 #include "dat.h")0(72 addrootdir\(char *name\))100 L (5 #include "fns.h")0(73 {)100 L (6 #include "../port/error.h")0(74)100(addroot\(name, nil, 0, CHDIR|0555\);)108 L (7)0(75 })100 L (8 enum{)0(76)100 L (9)0(Qdir= 0,)8(77 static void)100 L (10)0(78 rootreset\(void\))100 L (11)0(Nfiles=32,)8(/* max root files */)24(79 {)100 L (12 };)0(80)100(addrootdir\("bin"\);)108 L (13)0(81)100(addrootdir\("dev"\);)108 L (14 extern ulong)0(bootlen;)24(82)100(addrootdir\("env"\);)108 L (15 extern uchar)0(bootcode[];)24(83)100(addrootdir\("net"\);)108 L (16)0(84)100(addrootdir\("net.alt"\);)108 L (17 Dirtab rootdir[Nfiles];)0(85)100(addrootdir\("proc"\);)108 L (18)0(86)100(addrootdir\("root"\);)108 L (19 static uchar)0(*rootdata[Nfiles];)24(87)100(addrootdir\("srv"\);)108 L (20 static int)0(nroot = 0;)24(88)100 L (21)0(89)100(addrootfile\("boot", bootcode, bootlen\); /* always have a boot file */)108 L (22 typedef struct Recover Recover;)0(90 })100 L (23 struct Recover)0(91)100 L (24 {)0(92 static Chan*)100 L (25)0(int len;)8(93 rootattach\(char *spec\))100 L (26)0(char *req;)8(94 {)100 L (27)0(Recover *next;)8(95)100(return devattach\('/', spec\);)108 L (28 };)0(96 })100 L (29)0(97)100 L (30 struct)0(98 static int)100 L (31 {)0(99 rootwalk\(Chan *c, char *name\))100 L (32)0(Lock;)8(100 {)100 L (33)0(QLock;)8(101 if\(strcmp\(name, ".."\) == 0\) {)100 L (34)0(Rendez;)8(102)100(c->qid.path = Qdir|CHDIR;)116 L (35)0(Recover *q;)8(103)100(return 1;)116 L (36 }reclist;)0(104 })100 L (37)0(105 if\(\(c->qid.path & ~CHDIR\) != Qdir\))100 L (38 /*)0(106)100(return 0;)116 L (39 * add a root file)0(107 return devwalk\(c, name, rootdir, nroot, devgen\);)100 L (40 */)0(108 })100 L (41 static void)0(109)100 L (42 addroot\(char *name, uchar *contents, ulong len, int perm\))0(110 static void)100 L (43 {)0(111 rootstat\(Chan *c, char *dp\))100 L (44)0(Dirtab *d;)8(112 {)100 L (45)0(113 devstat\(c, dp, rootdir, nroot, devgen\);)100 L (46)0(if\(nroot >= Nfiles\))8(114 })100 L (47)0(panic\("too many root files"\);)16(115)100 L (48)0(rootdata[nroot] = contents;)8(116 static Chan*)100 L (49)0(d = &rootdir[nroot];)8(117 rootopen\(Chan *c, int omode\))100 L (50)0(strcpy\(d->name, name\);)8(118 {)100 L (51)0(d->length = len;)8(119 switch\(c->qid.path & ~CHDIR\) {)100 L (52)0(d->perm = perm;)8(120 default:)100 L (53)0(d->qid.path = nroot+1;)8(121)100(break;)116 L (54)0(if\(perm & CHDIR\))8(122 })100 L (55)0(d->qid.path |= CHDIR;)16(123)100 L (56)0(nroot++;)8(124 return devopen\(c, omode, rootdir, nroot, devgen\);)100 L (57 })0(125 })100 L (58)0(126)100 L (59 /*)0(127 /*)100 L (60 * add a root file)0(128 * sysremove\(\) knows this is a nop)100 L (61 */)0(129 */)100 L (62 void)0(130 static void)100 L (63 addrootfile\(char *name, uchar *contents, ulong len\))0(131 rootclose\(Chan *c\))100 L (64 {)0(132 {)100 L (65)0(addroot\(name, contents, len, 0555\);)8(133 switch\(c->qid.path\) {)100 L (66 })0(134 default:)100 L (67)0(135)100(break;)116 L (68 /*)0(136 })100 L cleartomark showpage saveobj restore %%EndPage: 157 157 %%Page: 158 158 /saveobj save def mark 158 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/devroot.c Page 2)l ()l ()l (137 })0(205 rootwrite,)100 L (138)0(206 devbwrite,)100 L (139 static int)0(207 devremove,)100 L (140 rdrdy\(void*\))0(208 devwstat,)100 L (141 {)0(209 };)100 L (142 return reclist.q != 0;)l (143 })l (144)l (145 static long)l (146 rootread\(Chan *c, void *buf, long n, vlong off\))l (147 {)l (148 ulong t;)l (149 Dirtab *d;)l (150 uchar *data;)l (151 ulong offset = off;)l (152)l (153 t = c->qid.path & ~CHDIR;)l (154 switch\(t\){)l (155 case Qdir:)l (156)0(return devdirread\(c, buf, n, rootdir, nroot, devgen\);)16 L (157 })l (158)l (159 d = &rootdir[t-1];)l (160 data = rootdata[t-1];)l (161 if\(offset >= d->length\))l (162)0(return 0;)16 L (163 if\(offset+n > d->length\))l (164)0(n = d->length - offset;)16 L (165 memmove\(buf, data+offset, n\);)l (166 return n;)l (167 })l (168)l (169 static long)l (170 rootwrite\(Chan *c, void*, long, vlong\))l (171 {)l (172 switch\(c->qid.path & ~CHDIR\){)l (173 default:)l (174)0(error\(Egreg\);)16 L (175 })l (176 return 0;)l (177 })l (178)l (179 static void)l (180 rootcreate\(Chan *c, char *name, int mode, ulong perm\))l (181 {)l (182 if\(!iseve\(\) || c->qid.path != \(CHDIR|Qdir\) ||)l (183)0(\(perm & CHDIR\) == 0 || mode != OREAD\))11 L (184)0(error\(Eperm\);)16 L (185 addrootdir\(name\);)l (186 c->flag |= COPEN;)l (187 c->mode = OREAD;)l (188 })l (189)l (190 Dev rootdevtab = {)l (191 '/',)l (192 "root",)l (193)l (194 rootreset,)l (195 devinit,)l (196 rootattach,)l (197 devclone,)l (198 rootwalk,)l (199 rootstat,)l (200 rootopen,)l (201 rootcreate,)l (202 rootclose,)l (203 rootread,)l (204 devbread,)l cleartomark showpage saveobj restore %%EndPage: 158 158 %%Page: 159 159 /saveobj save def mark 159 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/fault.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(pg = &etp->pages[\(soff&\(PTEMAPMEM-1\)\)/BY2PG];)108 L (2 #include "../port/lib.h")0(70)100(type = s->type&SG_TYPE;)108 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72)100(if\(pg < etp->first\))108 L (5 #include "fns.h")0(73)100(etp->first = pg;)116 L (6 #include "../port/error.h")0(74)100(if\(pg > etp->last\))108 L (7)0(75)100(etp->last = pg;)116 L (8 int)0(76)100 L (9 fault\(ulong addr, int read\))0(77)100(switch\(type\) {)108 L (10 {)0(78)100(default:)108 L (11)0(Segment *s;)8(79)100(panic\("fault"\);)116 L (12)0(char *sps;)8(80)100(break;)116 L (13)0(81)100 L (14)0(sps = up->psstate;)8(82)100(case SG_TEXT:)108(/* Demand load */)140 L (15)0(up->psstate = "Fault";)8(83)100(if\(pagedout\(*pg\)\))116 L (16)0(spllo\(\);)8(84)100(pio\(s, addr, soff, pg\);)124 L (17)0(85)100 L (18)0(m->pfault++;)8(86)100(mmuphys = PPN\(\(*pg\)->pa\) | PTERONLY|PTEVALID;)116 L (19)0(for\(;;\) {)8(87)100(\(*pg\)->modref = PG_REF;)116 L (20)0(s = seg\(up, addr, 1\);)16(/* leaves s->lk qlocked if seg != nil */)48(88)100(break;)116 L (21)0(if\(s == 0\) {)16(89)100 L (22)0(up->psstate = sps;)24(90)100(case SG_BSS:)108 L (23)0(return -1;)24(91)100(case SG_SHARED:)108(/* Zero fill on demand */)140 L (24)0(})16(92)100(case SG_STACK:)108 L (25)0(93)100(case SG_MAP:)108 L (26)0(if\(!read && \(s->type&SG_RONLY\)\) {)16(94)100(if\(*pg == 0\) {)116 L (27)0(qunlock\(&s->lk\);)24(95)100(if\(type == SG_MAP\) {)124 L (28)0(up->psstate = sps;)24(96)100(sprint\(buf, "map 0x%lux %c", va, read ? 'r' : 'w'\);)132 L (29)0(return -1;)24(97)100(postnote\(up, 1, buf, NDebug\);)132 L (30)0(})16(98)100(})124 L (31)0(99)100(new = newpage\(1, &s, addr\);)124 L (32)0(if\(fixfault\(s, addr, read, 1\) == 0\))16(100)100(if\(s == 0\))124 L (33)0(break;)24(101)100(return -1;)132 L (34)0(})8(102)100 L (35)0(103)100(*pg = new;)124 L (36)0(up->psstate = sps;)8(104)100(})116 L (37)0(return 0;)8(105)100(goto common;)116 L (38 })0(106)100 L (39)0(107 case SG_DATA:)100 L (40 static void)0(108 case SG_SHDATA:)100 L (41 faulterror\(char *s, int freemem\))0(109 common:)100(/* Demand load/pagein/copy on write */)132 L (42 {)0(110)100(if\(pagedout\(*pg\)\))116 L (43)0(if\(up->nerrlab\) {)8(111)100(pio\(s, addr, soff, pg\);)124 L (44)0(postnote\(up, 1, s, NDebug\);)16(112)100 L (45)0(error\(s\);)16(113)100(if\(read && conf.copymode == 0\) {)116 L (46)0(})8(114)100(mmuphys = PPN\(\(*pg\)->pa\)|PTERONLY|PTEVALID;)124 L (47)0(pexit\(s, freemem\);)8(115)100(\(*pg\)->modref |= PG_REF;)124 L (48 })0(116)100(break;)124 L (49)0(117)100(})116 L (50 int)0(118)100 L (51 fixfault\(Segment *s, ulong addr, int read, int doputmmu\))0(119)100(lkp = *pg;)116 L (52 {)0(120)100(lock\(lkp\);)116 L (53)0(int type;)8(121)100 L (54)0(int ref;)8(122)100(if\(lkp->image == &swapimage\))116 L (55)0(Pte **p, *etp;)8(123)100(ref = lkp->ref + swapcount\(lkp->daddr\);)124 L (56)0(char buf[ERRLEN];)8(124)100(else)116 L (57)0(ulong va, mmuphys=0, soff;)8(125)100(ref = lkp->ref;)124 L (58)0(Page **pg, *lkp, *new;)8(126)100(if\(ref > 1\) {)116 L (59)0(Page *\(*fn\)\(Segment*, ulong\);)8(127)100(unlock\(lkp\);)124 L (60)0(128)100 L (61)0(va = addr;)8(129)100(if\(swapfull\(\)\){)124 L (62)0(addr &= ~\(BY2PG-1\);)8(130)100(qunlock\(&s->lk\);)132 L (63)0(soff = addr-s->base;)8(131)100(pprint\("swap space full\\n"\);)132 L (64)0(p = &s->map[soff/PTEMAPMEM];)8(132)100(faulterror\(Enoswap, 1\);)132 L (65)0(if\(*p == 0\))8(133)100(})124 L (66)0(*p = ptealloc\(\);)16(134)100 L (67)0(135)100(new = newpage\(0, &s, addr\);)124 L (68)0(etp = *p;)8(136)100(if\(s == 0\))124 L cleartomark showpage saveobj restore %%EndPage: 159 159 %%Page: 160 160 /saveobj save def mark 160 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/fault.c Page 2)l ()l ()l (137)0(return -1;)32(205)100(*p = new;)124 L (138)0(*pg = new;)24(206)100(return;)124 L (139)0(copypage\(lkp, *pg\);)24(207)100(})116 L (140)0(putpage\(lkp\);)24(208 })100 L (141)0(})16(209)100 L (142)0(else {)16(210)100 L (143)0(/* save a copy of the original for the image cache */)24(211 qunlock\(&s->lk\);)100 L (144)0(if\(lkp->image && !swapfull\(\)\))24(212)100 L (145)0(duppage\(lkp\);)32(213 new = newpage\(0, 0, addr\);)100 L (146)0(214 k = kmap\(new\);)100 L (147)0(unlock\(lkp\);)24(215 kaddr = \(char*\)VA\(k\);)100 L (148)0(})16(216)100 L (149)0(mmuphys = PPN\(\(*pg\)->pa\) | PTEWRITE|PTEVALID;)16(217 if\(loadrec == 0\) {)100(/* This is demand load */)148 L (150)0(\(*pg\)->modref = PG_MOD|PG_REF;)16(218)100(c = s->image->c;)116 L (151)0(break;)16(219)100(while\(waserror\(\)\) {)116 L (152)0(220)100(if\(strcmp\(up->error, Eintr\) == 0\))124 L (153 case SG_PHYSICAL:)0(221)100(continue;)132 L (154)0(if\(*pg == 0\) {)16(222)100(kunmap\(k\);)124 L (155)0(fn = s->pseg->pgalloc;)24(223)100(putpage\(new\);)124 L (156)0(if\(fn\))24(224)100(faulterror\("sys: demand load I/O error", 0\);)124 L (157)0(*pg = \(*fn\)\(s, addr\);)32(225)100(})116 L (158)0(else {)24(226)100 L (159)0(new = smalloc\(sizeof\(Page\)\);)32(227)100(ask = s->flen-soff;)116 L (160)0(new->va = addr;)32(228)100(if\(ask > BY2PG\))116 L (161)0(new->pa = s->pseg->pa+\(addr-s->base\);)32(229)100(ask = BY2PG;)124 L (162)0(new->ref = 1;)32(230)100 L (163)0(*pg = new;)32(231)100(n = devtab[c->type]->read\(c, kaddr, ask, daddr\);)116 L (164)0(})24(232)100(if\(n != ask\))116 L (165)0(})16(233)100(faulterror\(Eioload, 0\);)124 L (166)0(234)100(if\(ask < BY2PG\))116 L (167)0(mmuphys = PPN\(\(*pg\)->pa\) |PTEWRITE|PTEUNCACHED|PTEVALID;)16(235)100(memset\(kaddr+ask, 0, BY2PG-ask\);)124 L (168)0(\(*pg\)->modref = PG_MOD|PG_REF;)16(236)100 L (169)0(break;)16(237)100(poperror\(\);)116 L (170 })0(238)100(kunmap\(k\);)116 L (171 qunlock\(&s->lk\);)0(239)100(qlock\(&s->lk\);)116 L (172)0(240)100 L (173 if\(doputmmu\))0(241)100(/*)116 L (174)0(putmmu\(addr, mmuphys, *pg\);)16(242)100(* race, another proc may have gotten here first while)117 L (175)0(243)100(* s->lk was unlocked)117 L (176 return 0;)0(244)100(*/)117 L (177 })0(245)100(if\(*p == 0\) {)116 L (178)0(246)100(new->daddr = daddr;)124 L (179 void)0(247)100(cachepage\(new, s->image\);)124 L (180 pio\(Segment *s, ulong addr, ulong soff, Page **p\))0(248)100(*p = new;)124 L (181 {)0(249)100(})116 L (182 Page *new;)0(250)100(else)116 L (183 KMap *k;)0(251)100(putpage\(new\);)124 L (184 Chan *c;)0(252 })100 L (185 int n, ask;)0(253 else {)100(/* This is paged out */)140 L (186 char *kaddr;)0(254)100(c = swapimage.c;)116 L (187 ulong daddr;)0(255)100(if\(waserror\(\)\) {)116 L (188 Page *loadrec;)0(256)100(kunmap\(k\);)124 L (189)0(257)100(putpage\(new\);)124 L (190 retry:)0(258)100(qlock\(&s->lk\);)124 L (191 loadrec = *p;)0(259)100(qunlock\(&s->lk\);)124 L (192 if\(loadrec == 0\) {)0(/* from a text/data image */)32(260)100(faulterror\("sys: page in I/O error", 0\);)124 L (193)0(daddr = s->fstart+soff;)16(261)100(})116 L (194)0(new = lookpage\(s->image, daddr\);)16(262)100 L (195)0(if\(new != nil\) {)16(263)100(n = devtab[c->type]->read\(c, kaddr, BY2PG, daddr\);)116 L (196)0(*p = new;)24(264)100(if\(n != BY2PG\))116 L (197)0(return;)24(265)100(faulterror\(Eioload, 0\);)124 L (198)0(})16(266)100 L (199 })0(267)100(poperror\(\);)116 L (200 else {)0(/* from a swap image */)32(268)100(kunmap\(k\);)116 L (201)0(daddr = swapaddr\(loadrec\);)16(269)100(qlock\(&s->lk\);)116 L (202)0(new = lookpage\(&swapimage, daddr\);)16(270)100 L (203)0(if\(new != nil\) {)16(271)100(/*)116 L (204)0(putswap\(loadrec\);)24(272)100(* race, another proc may have gotten here first)117 L cleartomark showpage saveobj restore %%EndPage: 160 160 %%Page: 161 161 /saveobj save def mark 161 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/fault.c Page 3)l ()l ()l (273)0(* \(and the pager may have run on that page\) while)17(341)100 L (274)0(* s->lk was unlocked)17(342 a = \(ulong\)s;)100 L (275)0(*/)17(343 m = BY2PG - \(a & \(BY2PG-1\)\);)100 L (276)0(if\(*p != loadrec\){)16(344 if\(m < n\){)100 L (277)0(if\(!pagedout\(*p\)\){)24(345)100(t = vmemchr\(s, c, m\);)116 L (278)0(/* another process did it for me */)32(346)100(if\(t\))116 L (279)0(putpage\(new\);)32(347)100(return t;)124 L (280)0(goto done;)32(348)100(if\(!\(a & KZERO\)\))116 L (281)0(} else {)24(349)100(validaddr\(a+m, 1, 0\);)124 L (282)0(/* another process and the pager got in */)32(350)100(return vmemchr\(\(void*\)\(a+m\), c, n-m\);)116 L (283)0(putpage\(new\);)32(351 })100 L (284)0(goto retry;)32(352 /*)100 L (285)0(})24(353)100(* All in one page)109 L (286)0(})16(354)100(*/)109 L (287)0(355 return memchr\(s, c, n\);)100 L (288)0(new->daddr = daddr;)16(356 })100 L (289)0(cachepage\(new, &swapimage\);)16(357)100 L (290)0(*p = new;)16(358 Segment*)100 L (291)0(putswap\(loadrec\);)16(359 seg\(Proc *p, ulong addr, int dolock\))100 L (292 })0(360 {)100 L (293)0(361 Segment **s, **et, *n;)100 L (294 done:)0(362)100 L (295 if\(s->flushme\))0(363 et = &p->seg[NSEG];)100 L (296)0(memset\(\(*p\)->cachectl, PG_TXTFLUSH, sizeof\(\(*p\)->cachectl\)\);)16(364 for\(s = p->seg; s < et; s++\) {)100 L (297 })0(365)100(n = *s;)116 L (298)0(366)100(if\(n == 0\))116 L (299 /*)0(367)100(continue;)124 L (300 * Called only in a system call)0(368)100(if\(addr >= n->base && addr < n->top\) {)116 L (301 */)0(369)100(if\(dolock == 0\))124 L (302 int)0(370)100(return n;)132 L (303 okaddr\(ulong addr, ulong len, int write\))0(371)100 L (304 {)0(372)100(qlock\(&n->lk\);)124 L (305 Segment *s;)0(373)100(if\(addr >= n->base && addr < n->top\))124 L (306)0(374)100(return n;)132 L (307 if\(\(long\)len >= 0\) {)0(375)100(qunlock\(&n->lk\);)124 L (308)0(for\(;;\) {)16(376)100(})116 L (309)0(s = seg\(up, addr, 0\);)24(377 })100 L (310)0(if\(s == 0 || \(write && \(s->type&SG_RONLY\)\)\))24(378)100 L (311)0(break;)32(379 return 0;)100 L (312)0(380 })100 L (313)0(if\(addr+len > s->top\) {)24 L (314)0(len -= s->top - addr;)32 L (315)0(addr = s->top;)32 L (316)0(continue;)32 L (317)0(})24 L (318)0(return 1;)24 L (319)0(})16 L (320 })l (321 pprint\("suicide: invalid address 0x%lux in sys call pc=0x%lux\\n", addr, userpc\(\)\);)l (322 return 0;)l (323 })l (324)l (325 void)l (326 validaddr\(ulong addr, ulong len, int write\))l (327 {)l (328 if\(!okaddr\(addr, len, write\)\))l (329)0(pexit\("Suicide", 0\);)16 L (330 })l (331)l (332 /*)l (333 * &s[0] is known to be a valid address.)l (334 */)l (335 void*)l (336 vmemchr\(void *s, int c, int n\))l (337 {)l (338 int m;)l (339 char *t;)l (340 ulong a;)l cleartomark showpage saveobj restore %%EndPage: 161 161 %%Page: 162 162 /saveobj save def mark 162 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/page.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(panic\("pageunchain"\);)116 L (2 #include "../port/lib.h")0(70)100(if\(p->prev\))108 L (3 #include "mem.h")0(71)100(p->prev->next = p->next;)116 L (4 #include "dat.h")0(72)100(else)108 L (5 #include "fns.h")0(73)100(palloc.head = p->next;)116 L (6 #include "../port/error.h")0(74)100(if\(p->next\))108 L (7)0(75)100(p->next->prev = p->prev;)116 L (8 #define pghash\(daddr\) palloc.hash[\(daddr>>PGSHIFT\)&\(PGHSIZE-1\)])0(76)100(else)108 L (9)0(77)100(palloc.tail = p->prev;)116 L (10 struct Palloc palloc;)0(78)100(p->prev = p->next = nil;)108 L (11)0(79)100(palloc.freecount--;)108 L (12 void)0(80 })100 L (13 pageinit\(void\))0(81)100 L (14 {)0(82 void)100 L (15)0(int color;)8(83 pagechaintail\(Page *p\))100 L (16)0(Page *p;)8(84 {)100 L (17)0(ulong np, vm, pm;)8(85)100(if\(canlock\(&palloc\)\))108 L (18)0(86)100(panic\("pagechaintail"\);)116 L (19)0(np = palloc.np0+palloc.np1;)8(87)100(if\(palloc.tail\) {)108 L (20)0(palloc.head = xalloc\(np*sizeof\(Page\)\);)8(88)100(p->prev = palloc.tail;)116 L (21)0(if\(palloc.head == 0\))8(89)100(palloc.tail->next = p;)116 L (22)0(panic\("pageinit"\);)16(90)100(})108 L (23)0(91)100(else {)108 L (24)0(color = 0;)8(92)100(palloc.head = p;)116 L (25)0(p = palloc.head;)8(93)100(p->prev = 0;)116 L (26)0(while\(palloc.np0 > 0\) {)8(94)100(})108 L (27)0(p->prev = p-1;)16(95)100(palloc.tail = p;)108 L (28)0(p->next = p+1;)16(96)100(p->next = 0;)108 L (29)0(p->pa = palloc.p0;)16(97)100(palloc.freecount++;)108 L (30)0(p->color = color;)16(98 })100 L (31)0(palloc.freecount++;)16(99)100 L (32)0(color = \(color+1\)%NCOLOR;)16(100 void)100 L (33)0(palloc.p0 += BY2PG;)16(101 pagechainhead\(Page *p\))100 L (34)0(palloc.np0--;)16(102 {)100 L (35)0(p++;)16(103 if\(canlock\(&palloc\)\))100 L (36)0(})8(104)100(panic\("pagechainhead"\);)116 L (37)0(while\(palloc.np1 > 0\) {)8(105 if\(palloc.head\) {)100 L (38)0(p->prev = p-1;)16(106)100(p->next = palloc.head;)116 L (39)0(p->next = p+1;)16(107)100(palloc.head->prev = p;)116 L (40)0(p->pa = palloc.p1;)16(108 })100 L (41)0(p->color = color;)16(109 else {)100 L (42)0(palloc.freecount++;)16(110)100(palloc.tail = p;)116 L (43)0(color = \(color+1\)%NCOLOR;)16(111)100(p->next = 0;)116 L (44)0(palloc.p1 += BY2PG;)16(112 })100 L (45)0(palloc.np1--;)16(113 palloc.head = p;)100 L (46)0(p++;)16(114 p->prev = 0;)100 L (47)0(})8(115 palloc.freecount++;)100 L (48)0(palloc.tail = p - 1;)8(116 })100 L (49)0(palloc.head->prev = 0;)8(117)100 L (50)0(palloc.tail->next = 0;)8(118 Page*)100 L (51)0(119 newpage\(int clear, Segment **s, ulong va\))100 L (52)0(palloc.user = p - palloc.head;)8(120 {)100 L (53)0(pm = palloc.user*BY2PG/1024;)8(121 Page *p;)100 L (54)0(vm = pm + \(conf.nswap*BY2PG\)/1024;)8(122 KMap *k;)100 L (55)0(123 uchar ct;)100 L (56)0(/* Pageing numbers */)8(124 int i, hw, dontalloc, color;)100 L (57)0(swapalloc.highwater = \(palloc.user*5\)/100;)8(125)100 L (58)0(swapalloc.headroom = swapalloc.highwater + \(swapalloc.highwater/4\);)8(126 lock\(&palloc\);)100 L (59)0(127 color = getpgcolor\(va\);)100 L (60)0(print\("%lud free pages\\n", palloc.user\);)8(128 hw = swapalloc.highwater;)100 L (61)0(print\("%ludK bytes\\n", pm\);)8(129 for\(;;\) {)100 L (62)0(print\("%ludK swap\\n", vm\);)8(130)100(if\(palloc.freecount > hw\))116 L (63 })0(131)100(break;)124 L (64)0(132)100(if\(up->kp && palloc.freecount > 0\))116 L (65 static void)0(133)100(break;)124 L (66 pageunchain\(Page *p\))0(134)100 L (67 {)0(135)100(unlock\(&palloc\);)116 L (68)0(if\(canlock\(&palloc\)\))8(136)100(dontalloc = 0;)116 L cleartomark showpage saveobj restore %%EndPage: 162 162 %%Page: 163 163 /saveobj save def mark 163 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/page.c Page 2)l ()l ()l (137)0(if\(s && *s\) {)16(205 return palloc.freecount >= swapalloc.highwater;)100 L (138)0(qunlock\(&\(\(*s\)->lk\)\);)24(206 })100 L (139)0(*s = 0;)24(207)100 L (140)0(dontalloc = 1;)24(208 void)100 L (141)0(})16(209 putpage\(Page *p\))100 L (142)0(qlock\(&palloc.pwait\); /* Hold memory requesters here */)16(210 {)100 L (143)0(211 if\(onswap\(p\)\) {)100 L (144)0(while\(waserror\(\)\))16(/* Ignore interrupts */)40(212)100(putswap\(p\);)116 L (145)0(;)24(213)100(return;)116 L (146)0(214 })100 L (147)0(kickpager\(\);)16(215)100 L (148)0(tsleep\(&palloc.r, ispages, 0, 1000\);)16(216 lock\(&palloc\);)100 L (149)0(217 lock\(p\);)100 L (150)0(poperror\(\);)16(218)100 L (151)0(219 if\(p->ref == 0\))100 L (152)0(qunlock\(&palloc.pwait\);)16(220)100(panic\("putpage"\);)116 L (153)0(221)100 L (154)0(/*)16(222 if\(--p->ref > 0\) {)100 L (155)0(* If called from fault and we lost the segment from)17(223)100(unlock\(p\);)116 L (156)0(* underneath don't waste time allocating and freeing)17(224)100(unlock\(&palloc\);)116 L (157)0(* a page. Fault will call newpage again when it has)17(225)100(return;)116 L (158)0(* reacquired the segment locks)17(226 })100 L (159)0(*/)17(227)100 L (160)0(if\(dontalloc\))16(228 if\(p->image && p->image != &swapimage\))100 L (161)0(return 0;)24(229)100(pagechaintail\(p\);)116 L (162)0(230 else)100 L (163)0(lock\(&palloc\);)16(231)100(pagechainhead\(p\);)116 L (164 })0(232)100 L (165)0(233 if\(palloc.r.p != 0\))100 L (166 /* First try for our colour */)0(234)100(wakeup\(&palloc.r\);)116 L (167 for\(p = palloc.head; p; p = p->next\))0(235)100 L (168)0(if\(p->color == color\))16(236 unlock\(p\);)100 L (169)0(break;)24(237 unlock\(&palloc\);)100 L (170)0(238 })100 L (171 ct = PG_NOFLUSH;)0(239)100 L (172 if\(p == 0\) {)0(240 Page*)100 L (173)0(p = palloc.head;)16(241 auxpage\(\))100 L (174)0(p->color = color;)16(242 {)100 L (175)0(ct = PG_NEWCOL;)16(243 Page *p;)100 L (176 })0(244)100 L (177)0(245 lock\(&palloc\);)100 L (178 pageunchain\(p\);)0(246 p = palloc.head;)100 L (179)0(247 if\(palloc.freecount < swapalloc.highwater\) {)100 L (180 lock\(p\);)0(248)100(unlock\(&palloc\);)116 L (181 if\(p->ref != 0\))0(249)100(return 0;)116 L (182)0(panic\("newpage"\);)16(250 })100 L (183)0(251 pageunchain\(p\);)100 L (184 uncachepage\(p\);)0(252)100 L (185 p->ref++;)0(253 lock\(p\);)100 L (186 p->va = va;)0(254 if\(p->ref != 0\))100 L (187 p->modref = 0;)0(255)100(panic\("auxpage"\);)116 L (188 for\(i = 0; i < MAXMACH; i++\))0(256 p->ref++;)100 L (189)0(p->cachectl[i] = ct;)16(257 uncachepage\(p\);)100 L (190 unlock\(p\);)0(258 unlock\(p\);)100 L (191 unlock\(&palloc\);)0(259 unlock\(&palloc\);)100 L (192)0(260)100 L (193 if\(clear\) {)0(261 return p;)100 L (194)0(k = kmap\(p\);)16(262 })100 L (195)0(memset\(\(void*\)VA\(k\), 0, BY2PG\);)16(263)100 L (196)0(kunmap\(k\);)16(264 void)100 L (197 })0(265 duppage\(Page *p\))100(/* Always call with p locked */)148 L (198)0(266 {)100 L (199 return p;)0(267 Page *np;)100 L (200 })0(268 int color;)100 L (201)0(269 int retries;)100 L (202 int)0(270)100 L (203 ispages\(void*\))0(271 retries = 0;)100 L (204 {)0(272 retry:)100 L cleartomark showpage saveobj restore %%EndPage: 163 163 %%Page: 164 164 /saveobj save def mark 164 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/page.c Page 3)l ()l ()l (273)0(341)100 L (274 if\(retries++ > 10000\))0(342 void)100 L (275)0(panic\("duppage %d", retries\);)16(343 uncachepage\(Page *p\))100(/* Always called with a locked page */)148 L (276)0(344 {)100 L (277 /* don't dup pages with no image */)0(345 Page **l, *f;)100 L (278 if\(p->ref == 0 || p->image == nil || p->image->notext\))0(346)100 L (279)0(return;)16(347 if\(p->image == 0\))100 L (280)0(348)100(return;)116 L (281 /*)0(349)100 L (282)0(* normal lock ordering is to call)9(350 lock\(&palloc.hashlock\);)100 L (283)0(* lock\(&palloc\) before lock\(p\).)9(351 l = &pghash\(p->daddr\);)100 L (284)0(* To avoid deadlock, we have to drop)9(352 for\(f = *l; f; f = f->hash\) {)100 L (285)0(* our locks and try again.)9(353)100(if\(f == p\) {)116 L (286)0(*/)9(354)100(*l = p->hash;)124 L (287 if\(!canlock\(&palloc\)\){)0(355)100(break;)124 L (288)0(unlock\(p\);)16(356)100(})116 L (289)0(if\(up\))16(357)100(l = &f->hash;)116 L (290)0(sched\(\);)24(358 })100 L (291)0(lock\(p\);)16(359 unlock\(&palloc.hashlock\);)100 L (292)0(goto retry;)16(360 putimage\(p->image\);)100 L (293 })0(361 p->image = 0;)100 L (294)0(362 p->daddr = 0;)100 L (295 /* No freelist cache when memory is very low */)0(363 })100 L (296 if\(palloc.freecount < swapalloc.highwater\) {)0(364)100 L (297)0(unlock\(&palloc\);)16(365 void)100 L (298)0(uncachepage\(p\);)16(366 cachepage\(Page *p, Image *i\))100 L (299)0(return;)16(367 {)100 L (300 })0(368 Page **l;)100 L (301)0(369)100 L (302 color = getpgcolor\(p->va\);)0(370 /* If this ever happens it should be fixed by calling)100 L (303 for\(np = palloc.head; np; np = np->next\))0(371)100(* uncachepage instead of panic. I think there is a race)109 L (304)0(if\(np->color == color\))16(372)100(* with pio in which this can happen. Calling uncachepage is)109 L (305)0(break;)24(373)100(* correct - I just wanted to see if we got here.)109 L (306)0(374)100(*/)109 L (307 /* No page of the correct color */)0(375 if\(p->image\))100 L (308 if\(np == 0\) {)0(376)100(panic\("cachepage"\);)116 L (309)0(unlock\(&palloc\);)16(377)100 L (310)0(uncachepage\(p\);)16(378 incref\(i\);)100 L (311)0(return;)16(379 lock\(&palloc.hashlock\);)100 L (312 })0(380 p->image = i;)100 L (313)0(381 l = &pghash\(p->daddr\);)100 L (314 pageunchain\(np\);)0(382 p->hash = *l;)100 L (315 pagechaintail\(np\);)0(383 *l = p;)100 L (316)0(384 unlock\(&palloc.hashlock\);)100 L (317 lock\(np\);)0(385 })100 L (318 unlock\(&palloc\);)0(386)100 L (319)0(387 void)100 L (320 /* Cache the new version */)0(388 cachedel\(Image *i, ulong daddr\))100 L (321 uncachepage\(np\);)0(389 {)100 L (322 np->va = p->va;)0(390 Page *f, **l;)100 L (323 np->daddr = p->daddr;)0(391)100 L (324 copypage\(p, np\);)0(392 lock\(&palloc.hashlock\);)100 L (325 cachepage\(np, p->image\);)0(393 l = &pghash\(daddr\);)100 L (326 unlock\(np\);)0(394 for\(f = *l; f; f = f->hash\) {)100 L (327 uncachepage\(p\);)0(395)100(if\(f->image == i && f->daddr == daddr\) {)116 L (328 })0(396)100(lock\(f\);)124 L (329)0(397)100(if\(f->image == i && f->daddr == daddr\){)124 L (330 void)0(398)100(*l = f->hash;)132 L (331 copypage\(Page *f, Page *t\))0(399)100(putimage\(f->image\);)132 L (332 {)0(400)100(f->image = 0;)132 L (333 KMap *ks, *kd;)0(401)100(f->daddr = 0;)132 L (334)0(402)100(})124 L (335 ks = kmap\(f\);)0(403)100(unlock\(f\);)124 L (336 kd = kmap\(t\);)0(404)100(break;)124 L (337 memmove\(\(void*\)VA\(kd\), \(void*\)VA\(ks\), BY2PG\);)0(405)100(})116 L (338 kunmap\(ks\);)0(406)100(l = &f->hash;)116 L (339 kunmap\(kd\);)0(407 })100 L (340 })0(408 unlock\(&palloc.hashlock\);)100 L cleartomark showpage saveobj restore %%EndPage: 164 164 %%Page: 165 165 /saveobj save def mark 165 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/page.c Page 4)l ()l ()l (409 })0(477 void)100 L (410)0(478 freepte\(Segment *s, Pte *p\))100 L (411 Page *)0(479 {)100 L (412 lookpage\(Image *i, ulong daddr\))0(480 int ref;)100 L (413 {)0(481 void \(*fn\)\(Page*\);)100 L (414 Page *f;)0(482 Page *pt, **pg, **ptop;)100 L (415)0(483)100 L (416 lock\(&palloc.hashlock\);)0(484 switch\(s->type&SG_TYPE\) {)100 L (417 for\(f = pghash\(daddr\); f; f = f->hash\) {)0(485 case SG_PHYSICAL:)100 L (418)0(if\(f->image == i && f->daddr == daddr\) {)16(486)100(fn = s->pseg->pgfree;)116 L (419)0(unlock\(&palloc.hashlock\);)24(487)100(ptop = &p->pages[PTEPERTAB];)116 L (420)0(488)100(if\(fn\) {)116 L (421)0(lock\(&palloc\);)24(489)100(for\(pg = p->pages; pg < ptop; pg++\) {)124 L (422)0(lock\(f\);)24(490)100(if\(*pg == 0\))132 L (423)0(if\(f->image != i || f->daddr != daddr\) {)24(491)100(continue;)140 L (424)0(unlock\(f\);)32(492)100(\(*fn\)\(*pg\);)132 L (425)0(unlock\(&palloc\);)32(493)100(*pg = 0;)132 L (426)0(return 0;)32(494)100(})124 L (427)0(})24(495)100(break;)124 L (428)0(if\(++f->ref == 1\))24(496)100(})116 L (429)0(pageunchain\(f\);)32(497)100(for\(pg = p->pages; pg < ptop; pg++\) {)116 L (430)0(unlock\(&palloc\);)24(498)100(pt = *pg;)124 L (431)0(unlock\(f\);)24(499)100(if\(pt == 0\))124 L (432)0(500)100(continue;)132 L (433)0(return f;)24(501)100(lock\(pt\);)124 L (434)0(})16(502)100(ref = --pt->ref;)124 L (435 })0(503)100(unlock\(pt\);)124 L (436 unlock\(&palloc.hashlock\);)0(504)100(if\(ref == 0\))124 L (437)0(505)100(free\(pt\);)132 L (438 return 0;)0(506)100(})116 L (439 })0(507)100(break;)116 L (440)0(508 default:)100 L (441 Pte*)0(509)100(for\(pg = p->first; pg <= p->last; pg++\))116 L (442 ptecpy\(Pte *old\))0(510)100(if\(*pg\) {)124 L (443 {)0(511)100(putpage\(*pg\);)132 L (444 Pte *new;)0(512)100(*pg = 0;)132 L (445 Page **src, **dst;)0(513)100(})124 L (446)0(514 })100 L (447 new = ptealloc\(\);)0(515 free\(p\);)100 L (448 dst = &new->pages[old->first-old->pages];)0(516 })100 L (449 new->first = dst;)l (450 for\(src = old->first; src <= old->last; src++, dst++\))l (451)0(if\(*src\) {)16 L (452)0(if\(onswap\(*src\)\))24 L (453)0(dupswap\(*src\);)32 L (454)0(else {)24 L (455)0(lock\(*src\);)32 L (456)0(\(*src\)->ref++;)32 L (457)0(unlock\(*src\);)32 L (458)0(})24 L (459)0(new->last = dst;)24 L (460)0(*dst = *src;)24 L (461)0(})16 L (462)l (463 return new;)l (464 })l (465)l (466 Pte*)l (467 ptealloc\(void\))l (468 {)l (469 Pte *new;)l (470)l (471 new = smalloc\(sizeof\(Pte\)\);)l (472 new->first = &new->pages[PTEPERTAB];)l (473 new->last = new->pages;)l (474 return new;)l (475 })l (476)l cleartomark showpage saveobj restore %%EndPage: 165 165 %%Page: 166 166 /saveobj save def mark 166 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/pgrp.c Page 1)l ()l ()l (1 #include "u.h")0(69)100 L (2 #include "../port/lib.h")0(70 void)100 L (3 #include "mem.h")0(71 closepgrp\(Pgrp *p\))100 L (4 #include "dat.h")0(72 {)100 L (5 #include "fns.h")0(73)100(Mhead **h, **e, *f, *next;)108 L (6 #include "../port/error.h")0(74)100 L (7)0(75)100(if\(decref\(p\) != 0\))108 L (8 static Ref pgrpid;)0(76)100(return;)116 L (9 static Ref mountid;)0(77)100 L (10)0(78)100(qlock\(&p->debug\);)108 L (11 void)0(79)100(wlock\(&p->ns\);)108 L (12 pgrpnote\(ulong noteid, char *a, long n, int flag\))0(80)100(p->pgrpid = -1;)108 L (13 {)0(81)100 L (14)0(Proc *p, *ep;)8(82)100(e = &p->mnthash[MNTHASH];)108 L (15)0(char buf[ERRLEN];)8(83)100(for\(h = p->mnthash; h < e; h++\) {)108 L (16)0(84)100(for\(f = *h; f; f = next\) {)116 L (17)0(if\(n >= ERRLEN-1\))8(85)100(wlock\(&f->lock\);)124 L (18)0(error\(Etoobig\);)16(86)100(cclose\(f->from\);)124 L (19)0(87)100(mountfree\(f->mount\);)124 L (20)0(memmove\(buf, a, n\);)8(88)100(f->mount = nil;)124 L (21)0(buf[n] = 0;)8(89)100(next = f->hash;)124 L (22)0(p = proctab\(0\);)8(90)100(wunlock\(&f->lock\);)124 L (23)0(ep = p+conf.nproc;)8(91)100(putmhead\(f\);)124 L (24)0(for\(; p < ep; p++\) {)8(92)100(})116 L (25)0(if\(p->state == Dead\))16(93)100(})108 L (26)0(continue;)24(94)100(wunlock\(&p->ns\);)108 L (27)0(if\(up != p && p->noteid == noteid && p->kp == 0\) {)16(95)100(qunlock\(&p->debug\);)108 L (28)0(qlock\(&p->debug\);)24(96)100(free\(p\);)108 L (29)0(if\(p->pid == 0 || p->noteid != noteid\){)24(97 })100 L (30)0(qunlock\(&p->debug\);)32(98)100 L (31)0(continue;)32(99 void)100 L (32)0(})24(100 pgrpinsert\(Mount **order, Mount *m\))100 L (33)0(if\(!waserror\(\)\) {)24(101 {)100 L (34)0(postnote\(p, 0, buf, flag\);)32(102 Mount *f;)100 L (35)0(poperror\(\);)32(103)100 L (36)0(})24(104 m->order = 0;)100 L (37)0(qunlock\(&p->debug\);)24(105 if\(*order == 0\) {)100 L (38)0(})16(106)100(*order = m;)116 L (39)0(})8(107)100(return;)116 L (40 })0(108 })100 L (41)0(109 for\(f = *order; f; f = f->order\) {)100 L (42 Pgrp*)0(110)100(if\(m->mountid < f->mountid\) {)116 L (43 newpgrp\(void\))0(111)100(m->order = f;)124 L (44 {)0(112)100(*order = m;)124 L (45)0(Pgrp *p;)8(113)100(return;)124 L (46)0(114)100(})116 L (47)0(p = smalloc\(sizeof\(Pgrp\)\);)8(115)100(order = &f->order;)116 L (48)0(p->ref = 1;)8(116 })100 L (49)0(p->pgrpid = incref\(&pgrpid\);)8(117 *order = m;)100 L (50)0(return p;)8(118 })100 L (51 })0(119)100 L (52)0(120 /*)100 L (53 Rgrp*)0(121 * pgrpcpy MUST preserve the mountid allocation order of the parent group)100 L (54 newrgrp\(void\))0(122 */)100 L (55 {)0(123 void)100 L (56)0(Rgrp *r;)8(124 pgrpcpy\(Pgrp *to, Pgrp *from\))100 L (57)0(125 {)100 L (58)0(r = smalloc\(sizeof\(Rgrp\)\);)8(126 int i;)100 L (59)0(r->ref = 1;)8(127 Mount *n, *m, **link, *order;)100 L (60)0(return r;)8(128 Mhead *f, **tom, **l, *mh;)100 L (61 })0(129)100 L (62)0(130 wlock\(&from->ns\);)100 L (63 void)0(131 order = 0;)100 L (64 closergrp\(Rgrp *r\))0(132 tom = to->mnthash;)100 L (65 {)0(133 for\(i = 0; i < MNTHASH; i++\) {)100 L (66)0(if\(decref\(r\) == 0\))8(134)100(l = tom++;)116 L (67)0(free\(r\);)16(135)100(for\(f = from->mnthash[i]; f; f = f->hash\) {)116 L (68 })0(136)100(rlock\(&f->lock\);)124 L cleartomark showpage saveobj restore %%EndPage: 166 166 %%Page: 167 167 /saveobj save def mark 167 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/pgrp.c Page 2)l ()l ()l (137)0(mh = smalloc\(sizeof\(Mhead\)\);)24(205 unlock\(f\);)100 L (138)0(mh->from = f->from;)24(206)100 L (139)0(mh->ref = 1;)24(207 return new;)100 L (140)0(incref\(mh->from\);)24(208 })100 L (141)0(*l = mh;)24(209)100 L (142)0(l = &mh->hash;)24(210 void)100 L (143)0(link = &mh->mount;)24(211 closefgrp\(Fgrp *f\))100 L (144)0(for\(m = f->mount; m; m = m->next\) {)24(212 {)100 L (145)0(n = smalloc\(sizeof\(Mount\)\);)32(213 int i;)100 L (146)0(n->to = m->to;)32(214 Chan *c;)100 L (147)0(incref\(n->to\);)32(215)100 L (148)0(n->head = mh;)32(216 if\(f == 0\))100 L (149)0(n->flag = m->flag;)32(217)100(return;)116 L (150)0(if\(m->spec[0] != 0\))32(218)100 L (151)0(strncpy\(n->spec, m->spec, NAMELEN\);)40(219 if\(decref\(f\) != 0\))100 L (152)0(m->copy = n;)32(220)100(return;)116 L (153)0(pgrpinsert\(&order, m\);)32(221)100 L (154)0(*link = n;)32(222 for\(i = 0; i <= f->maxfd; i++\))100 L (155)0(link = &n->next;)32(223)100(if\(c = f->fd[i]\))116 L (156)0(})24(224)100(cclose\(c\);)124 L (157)0(runlock\(&f->lock\);)24(225)100 L (158)0(})16(226 free\(f->fd\);)100 L (159 })0(227 free\(f\);)100 L (160 /*)0(228 })100 L (161)0(* Allocate mount ids in the same sequence as the parent group)9(229)100 L (162)0(*/)9(230 Mount*)100 L (163 lock\(&mountid\);)0(231 newmount\(Mhead *mh, Chan *to, int flag, char *spec\))100 L (164 for\(m = order; m; m = m->order\))0(232 {)100 L (165)0(m->copy->mountid = mountid.ref++;)16(233 Mount *m;)100 L (166 unlock\(&mountid\);)0(234)100 L (167 wunlock\(&from->ns\);)0(235 m = smalloc\(sizeof\(Mount\)\);)100 L (168 })0(236 m->to = to;)100 L (169)0(237 m->head = mh;)100 L (170 Fgrp*)0(238 incref\(to\);)100 L (171 dupfgrp\(Fgrp *f\))0(239 m->mountid = incref\(&mountid\);)100 L (172 {)0(240 m->flag = flag;)100 L (173 Fgrp *new;)0(241 if\(spec != 0\))100 L (174 Chan *c;)0(242)100(strncpy\(m->spec, spec, NAMELEN\);)116 L (175 int i;)0(243)100 L (176)0(244 return m;)100 L (177 new = smalloc\(sizeof\(Fgrp\)\);)0(245 })100 L (178 if\(f == nil\){)0(246)100 L (179)0(new->fd = smalloc\(DELTAFD*sizeof\(Chan*\)\);)16(247 void)100 L (180)0(new->nfd = DELTAFD;)16(248 mountfree\(Mount *m\))100 L (181)0(new->ref = 1;)16(249 {)100 L (182)0(return new;)16(250 Mount *f;)100 L (183 })0(251)100 L (184)0(252 while\(m\) {)100 L (185 lock\(f\);)0(253)100(f = m->next;)116 L (186 /* Make new fd list shorter if possible, preserving quantization */)0(254)100(cclose\(m->to\);)116 L (187 new->nfd = f->maxfd+1;)0(255)100(m->mountid = 0;)116 L (188 i = new->nfd%DELTAFD;)0(256)100(free\(m\);)116 L (189 if\(i != 0\))0(257)100(m = f;)116 L (190)0(new->nfd += DELTAFD - i;)16(258 })100 L (191 new->fd = malloc\(new->nfd*sizeof\(Chan*\)\);)0(259 })100 L (192 if\(new->fd == 0\){)0(260)100 L (193)0(unlock\(f\);)16(261 void)100 L (194)0(error\("no memory for fgrp"\);)16(262 resrcwait\(char *reason\))100 L (195 })0(263 {)100 L (196 new->ref = 1;)0(264 char *p;)100 L (197)0(265)100 L (198 new->maxfd = f->maxfd;)0(266 if\(up == 0\))100 L (199 for\(i = 0; i <= f->maxfd; i++\) {)0(267)100(panic\("resrcwait"\);)116 L (200)0(if\(c = f->fd[i]\){)16(268)100 L (201)0(incref\(c\);)24(269 p = up->psstate;)100 L (202)0(new->fd[i] = c;)24(270 if\(reason\) {)100 L (203)0(})16(271)100(up->psstate = reason;)116 L (204 })0(272)100(print\("%s\\n", reason\);)116 L cleartomark showpage saveobj restore %%EndPage: 167 167 %%Page: 168 168 /saveobj save def mark 168 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/pgrp.c Page 3)l ()l ()l (273 })l (274)l (275 tsleep\(&up->sleep, return0, 0, 300\);)l (276 up->psstate = p;)l (277 })l cleartomark showpage saveobj restore %%EndPage: 168 168 %%Page: 169 169 /saveobj save def mark 169 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portdat.h Page 1)l ()l ()l (1 typedef struct Alarms Alarms;)0(69 {)100 L (2 typedef struct Block)0(Block;)32(70)100(Lock use;)108 L (3 typedef struct Chan)0(Chan;)32(71)100(Proc *head;)108(/* list of waiting processes */)132 L (4 typedef struct Cmdbuf Cmdbuf;)0(72)100(Proc *tail;)108 L (5 typedef struct Cname)0(Cname;)32(73)100(ulong wpc;)108(/* pc of writer */)132 L (6 typedef struct Crypt)0(Crypt;)32(74)100(Proc *wproc;)108(/* writing proc */)132 L (7 typedef struct Dev)0(Dev;)32(75)100(int readers;)108(/* number of readers */)132 L (8 typedef struct Dirtab Dirtab;)0(76)100(int writer;)108(/* number of writers */)132 L (9 typedef struct Egrp)0(Egrp;)32(77 };)100 L (10 typedef struct Evalue Evalue;)0(78)100 L (11 typedef struct Fgrp)0(Fgrp;)32(79 struct Talarm)100 L (12 typedef struct Image)0(Image;)32(80 {)100 L (13 typedef struct List)0(List;)32(81)100(Lock;)108 L (14 typedef struct Log)0(Log;)32(82)100(Proc *list;)108 L (15 typedef struct Logflag Logflag;)0(83 };)100 L (16 typedef struct Mntcache Mntcache;)0(84)100 L (17 typedef struct Mount)0(Mount;)32(85 struct Alarms)100 L (18 typedef struct Mntrpc Mntrpc;)0(86 {)100 L (19 typedef struct Mntwalk Mntwalk;)0(87)100(QLock;)108 L (20 typedef struct Mnt)0(Mnt;)32(88)100(Proc *head;)108 L (21 typedef struct Mhead)0(Mhead;)32(89 };)100 L (22 typedef struct Note)0(Note;)32(90)100 L (23 typedef struct Page)0(Page;)32(91 #define MAXSYSARG 5)100(/* for mount\(fd, mpt, flag, arg, srv\) */)132 L (24 typedef struct Palloc Palloc;)0(92 struct Sargs)100 L (25 typedef struct Pgrps)0(Pgrps;)32(93 {)100 L (26 typedef struct Pgrp)0(Pgrp;)32(94)100(ulong args[MAXSYSARG];)108 L (27 typedef struct Physseg Physseg;)0(95 };)100 L (28 typedef struct Proc)0(Proc;)32(96)100 L (29 typedef struct Pte)0(Pte;)32(97 /*)100 L (30 typedef struct Pthash Pthash;)0(98 * Access types in namec & channel flags)100 L (31 typedef struct QLock)0(QLock;)32(99 */)100 L (32 typedef struct Queue)0(Queue;)32(100 enum)100 L (33 typedef struct Ref)0(Ref;)32(101 {)100 L (34 typedef struct Rendez Rendez;)0(102 Aaccess,)100(/* as in access, stat */)140 L (35 typedef struct Rgrp)0(Rgrp;)32(103 Atodir,)100(/* as in chdir */)140 L (36 typedef struct RWlock RWlock;)0(104 Aopen,)100(/* for i/o */)140 L (37 typedef struct Sargs)0(Sargs;)32(105 Amount,)100(/* to be mounted upon */)140 L (38 typedef struct Segment Segment;)0(106 Acreate,)100(/* file is to be created */)140 L (39 typedef struct Session Session;)0(107)100 L (40 typedef struct Talarm Talarm;)0(108 COPEN = 0x0001,)100(/* for i/o */)140 L (41 typedef struct Target Target;)0(109 CMSG = 0x0002,)100(/* the message channel for a mount */)140 L (42 typedef struct Waitq)0(Waitq;)32(110 CCREATE = 0x0004,)100(/* permits creation if c->mnt */)140 L (43 typedef int Devgen\(Chan*, Dirtab*, int, int, Dir*\);)0(111 CCEXEC = 0x0008,)100(/* close on exec */)140 L (44)0(112 CFREE = 0x0010,)100(/* not in use */)140 L (45)0(113 CRCLOSE = 0x0020,)100(/* remove on close */)140 L (46 #include )0(114 CCACHE = 0x0080,)100(/* client cache */)140 L (47 #include )0(115 };)100 L (48)0(116)100 L (49 struct Ref)0(117 enum)100 L (50 {)0(118 {)100 L (51)0(Lock;)8(119 BINTR =)100(\(1<<0\),)124 L (52)0(long ref;)8(120 BFREE =)100(\(1<<1\),)124 L (53 };)0(121 };)100 L (54)0(122)100 L (55 struct Rendez)0(123 struct Block)100 L (56 {)0(124 {)100 L (57)0(Proc *p;)8(125 Block* next;)100 L (58 };)0(126 Block* list;)100 L (59)0(127 uchar* rp;)100(/* first unconsumed byte */)140 L (60 struct QLock)0(128 uchar* wp;)100(/* first empty byte */)140 L (61 {)0(129 uchar* lim;)100(/* 1 past the end of the buffer */)140 L (62)0(Lock use;)8(/* to access Qlock structure */)40(130 uchar* base;)100(/* start of the buffer */)140 L (63)0(Proc *head;)8(/* next process waiting for object */)40(131 void \(*free\)\(Block*\);)100 L (64)0(Proc *tail;)8(/* last process waiting for object */)40(132 ulong flag;)100 L (65)0(int locked;)8(/* flag */)40(133 };)100 L (66 };)0(134 #define BLEN\(s\) \(\(s\)->wp - \(s\)->rp\))100 L (67)0(135 #define BALLOC\(s\) \(\(s\)->lim - \(s\)->base\))100 L (68 struct RWlock)0(136)100 L cleartomark showpage saveobj restore %%EndPage: 169 169 %%Page: 170 170 /saveobj save def mark 170 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portdat.h Page 2)l ()l ()l (137 struct Chan)0(205 enum)100 L (138 {)0(206 {)100 L (139 Ref;)0(207 NSMAX =)100(1000,)124 L (140 Chan* next;)0(/* allocation */)40(208 NSLOG =)100(7,)124 L (141 Chan* link;)0(209 NSCACHE =)100(\(1<rendhash[\(s\)%RENDHASH]\))100 L (326 Page **first;)0(/* First used entry */)40(394 #define MOUNTH\(p,s\))100(\(\(p\)->mnthash[\(s\)->qid.path%MNTHASH]\))132 L (327 Page **last;)0(/* Last used entry */)40(395)100 L (328 Pte *next;)0(/* Free list */)40(396 struct Pgrp)100 L (329 };)0(397 {)100 L (330)0(398 Ref;)100(/* also used as a lock when mounting */)140 L (331 /* Segment types */)0(399 int noattach;)100 L (332 enum)0(400 ulong pgrpid;)100 L (333 {)0(401 QLock debug;)100(/* single access via devproc.c */)140 L (334 SG_TYPE)0(= 07,)24(/* Mask type of segment */)40(402 RWlock ns;)100(/* Namespace n read/one write lock */)140 L (335 SG_TEXT)0(= 00,)24(403 QLock nsh;)100 L (336 SG_DATA)0(= 01,)24(404 Mhead *mnthash[MNTHASH];)100 L (337 SG_BSS)0(= 02,)24(405 };)100 L (338 SG_STACK)0(= 03,)24(406)100 L (339 SG_SHARED)0(= 04,)24(407 struct Rgrp)100 L (340 SG_PHYSICAL = 05,)0(408 {)100 L cleartomark showpage saveobj restore %%EndPage: 171 171 %%Page: 172 172 /saveobj save def mark 172 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portdat.h Page 4)l ()l ()l (409 Ref;)0(477 RFCENVG)100(= \(1<<11\),)124 L (410 Proc *rendhash[RENDHASH]; /* Rendezvous tag hash */)0(478 RFCFDG)100(= \(1<<12\),)124 L (411 };)0(479 RFREND)100(= \(1<<13\),)124 L (412)0(480 RFNOMNT)100(= \(1<<14\),)124 L (413 struct Egrp)0(481 };)100 L (414 {)0(482)100 L (415 Ref;)0(483 /*)100 L (416 QLock;)0(484 * process memory segments - NSEG always last !)100 L (417 Evalue *entries;)0(485 */)100 L (418 ulong path; /* qid.path of next Evalue to be allocated */)0(486 enum)100 L (419 ulong vers; /* of Egrp */)0(487 {)100 L (420 };)0(488 SSEG, TSEG, DSEG, BSEG, ESEG, LSEG, SEG1, SEG2, SEG3, SEG4, NSEG)100 L (421)0(489 };)100 L (422 struct Evalue)0(490)100 L (423 {)0(491 enum)100 L (424 char *name;)0(492 {)100 L (425 char *value;)0(493 Dead = 0,)100(/* Process states */)132 L (426 int len;)0(494 Moribund,)100 L (427 Evalue *link;)0(495 Ready,)100 L (428 Qid qid;)0(496 Scheding,)100 L (429 };)0(497 Running,)100 L (430)0(498 Queueing,)100 L (431 struct Fgrp)0(499 QueueingR,)100 L (432 {)0(500 QueueingW,)100 L (433 Ref;)0(501 Wakeme,)100 L (434 Chan **fd;)0(502 Broken,)100 L (435 int nfd;)0(/* number allocated */)40(503 Stopped,)100 L (436 int maxfd;)0(/* highest fd in use */)40(504 Rendezvous,)100 L (437 };)0(505)100 L (438)0(506 Proc_stopme = 1,)100(/* devproc requests */)132 L (439 enum)0(507 Proc_exitme,)100 L (440 {)0(508 Proc_traceme,)100 L (441 DELTAFD = 20)0(/* incremental increase in Fgrp.fd's */)32(509 Proc_exitbig,)100 L (442 };)0(510)100 L (443)0(511 TUser = 0,)100(/* Proc.time */)132 L (444 struct Palloc)0(512 TSys,)100 L (445 {)0(513 TReal,)100 L (446 Lock;)0(514 TCUser,)100 L (447 ulong p0, p1;)0(/* base of pages in bank 0/1 */)40(515 TCSys,)100 L (448 ulong np0, np1;)0(/* number of pages in bank 0/1 */)40(516 TCReal,)100 L (449 Page *head;)0(/* most recently used */)40(517)100 L (450 Page *tail;)0(/* least recently used */)40(518 NERR = 15,)100 L (451 ulong freecount;)0(/* how many pages on free list now */)40(519 NNOTE = 5,)100 L (452 ulong user;)0(/* how many user pages */)40(520)100 L (453 Page *hash[PGHSIZE];)0(521 Nrq)100(= 20, /* number of scheduler priority levels */)124 L (454 Lock hashlock;)0(522 PriLock)100(= 0, /* priority for processes waiting on a lock */)124 L (455 Rendez r;)0(/* Sleep for free mem */)40(523 PriNormal)100(= 10, /* base priority for normal processes */)124 L (456 QLock pwait;)0(/* Queue of procs waiting for memory */)40(524 PriKproc)100(= 13, /* base priority for kernel processes */)124 L (457 ulong cmembase;)0(/* Key memory */)40(525 PriRoot)100(= 13, /* base priority for root processes */)124 L (458 ulong cmemtop;)0(526 };)100 L (459 };)0(527)100 L (460)0(528 struct Proc)100 L (461 struct Waitq)0(529 {)100 L (462 {)0(530 Label sched;)100(/* known to l.s */)132 L (463 Waitmsg w;)0(531 char *kstack;)100(/* known to l.s */)132 L (464 Waitq *next;)0(532 Mach *mach;)100(/* machine running this proc */)132 L (465 };)0(533 char text[NAMELEN];)100 L (466)0(534 char user[NAMELEN];)100 L (467 enum)0(535 Proc *rnext;)100(/* next process in run queue */)132 L (468 {)0(536 Proc *qnext;)100(/* next process on queue for a QLock */)132 L (469 RFNAMEG)0(= \(1<<0\),)24(537 QLock *qlock;)100(/* addrof qlock being queued for DEBUG */)132 L (470 RFENVG)0(= \(1<<1\),)24(538 int state;)100 L (471 RFFDG)0(= \(1<<2\),)24(539 char *psstate;)100(/* What /proc/#/status reports */)132 L (472 RFNOTEG)0(= \(1<<3\),)24(540 Segment *seg[NSEG];)100 L (473 RFPROC)0(= \(1<<4\),)24(541 QLock seglock;)100(/* locked whenever seg[] changes */)132 L (474 RFMEM)0(= \(1<<5\),)24(542 ulong pid;)100 L (475 RFNOWAIT)0(= \(1<<6\),)24(543 ulong noteid;)100(/* Equivalent of note group */)132 L (476 RFCNAMEG)0(= \(1<<10\),)24(544)100 L cleartomark showpage saveobj restore %%EndPage: 172 172 %%Page: 173 173 /saveobj save def mark 173 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portdat.h Page 5)l ()l ()l (545 Lock exl;)0(/* Lock count and waitq */)32(613 ulong art;)100(/* avg # ticks used since last blocked */)132 L (546 Waitq *waitq;)0(/* Exited processes wait children */)32(614 ulong movetime;)100(/* last time process switched processors */)132 L (547 int nchild;)0(/* Number of living children */)32(615 ulong readytime;)100(/* time process went ready */)132 L (548 int nwait;)0(/* Number of uncollected wait records */)32(616 int preempted;)100(/* true if this process hasn't finished the interrupt)132 L (549 QLock qwaitr;)0(617)100(* that last preempted it)133 L (550 Rendez waitr;)0(/* Place to hang out in wait */)32(618)100(*/)133 L (551 Proc *parent;)0(619 ulong qpc;)100(/* pc calling last blocking qlock */)132 L (552)0(620)100 L (553 Pgrp *pgrp;)0(/* Process group for namespace */)32(621 void *ureg;)100(/* User registers for notes */)132 L (554 Egrp *egrp;)0(/* Environment group */)32(622 void *dbgreg;)100(/* User registers for devproc */)132 L (555 Fgrp *fgrp;)0(/* File descriptor group */)32(623 Notsave;)100 L (556 Rgrp *rgrp;)0(/* Rendez group */)32(624)100 L (557)0(625 /*)100 L (558 ulong parentpid;)0(626)100(* machine specific MMU)109 L (559 ulong time[6];)0(/* User, Sys, Real; child U, S, R */)32(627)100(*/)109 L (560 short insyscall;)0(628 PMMU;)100 L (561 int fpstate;)0(629 };)100 L (562)0(630)100 L (563 QLock debug;)0(/* to access debugging elements of User */)32(631 enum)100 L (564 Proc *pdbg;)0(/* the debugging process */)32(632 {)100 L (565 ulong procmode;)0(/* proc device file mode */)32(633 PRINTSIZE = 256,)100 L (566 int hang;)0(/* hang at next exec for debug */)32(634 MAXCRYPT =)100(127,)124 L (567 int procctl;)0(/* Control for /proc debugging */)32(635 NUMSIZE =)100(12,)124(/* size of formatted number */)140 L (568 ulong pc;)0(/* DEBUG only */)32(636 MB =)100(\(1024*1024\),)124 L (569)0(637 READSTR =)100(1000,)124(/* temporary buffer size for device reads */)140 L (570 Lock rlock;)0(/* sync sleep/wakeup with postnote */)32(638 };)100 L (571 Rendez *r;)0(/* rendezvous point slept on */)32(639)100 L (572 Rendez sleep;)0(/* place for syssleep/debug */)32(640 extern Conf conf;)100 L (573 int notepending; /* note issued but not acted on */)0(641 extern char* conffile;)100 L (574 int kp;)0(/* true if a kernel process */)32(642 extern int cpuserver;)100 L (575 Proc *palarm;)0(/* Next alarm time */)32(643 extern Dev* devtab[];)100 L (576 ulong alarm;)0(/* Time of call */)32(644 extern char)100(eve[];)124 L (577 int newtlb;)0(/* Pager has changed my pte's, I must flush */)32(645 extern char hostdomain[];)100 L (578)0(646 extern uchar initcode[];)100 L (579 ulong rendtag;)0(/* Tag for rendezvous */)32(647 extern FPsave initfp;)100 L (580 ulong rendval;)0(/* Value for rendezvous */)32(648 extern Queue* kbdq;)100 L (581 Proc *rendhash;)0(/* Hash list for tag values */)32(649 extern Ref)100(noteidalloc;)124 L (582)0(650 extern int nrdy;)100 L (583 ulong twhen;)0(651 extern Palloc palloc;)100 L (584 Rendez *trend;)0(652 extern Queue *printq;)100 L (585 Proc *tlink;)0(653 extern char* statename[];)100 L (586 int \(*tfn\)\(void*\);)0(654 extern Image swapimage;)100 L (587 void \(*kpfun\)\(void*\);)0(655 extern char sysname[NAMELEN];)100 L (588 void *kparg;)0(656 extern Pthash syspt;)100 L (589)0(657 extern Talarm talarm;)100 L (590 FPsave fpsave;)0(/* address of this is known by db */)32(658)100 L (591 int scallnr;)0(/* sys call number - known by db */)32(659 enum)100 L (592 Sargs s;)0(/* address of this is known by db */)32(660 {)100 L (593 int nerrlab;)0(661 CHDIR =)100(0x80000000L,)124 L (594 Label errlab[NERR];)0(662 CHAPPEND =)100(0x40000000L,)124 L (595 char error[ERRLEN];)0(663 CHEXCL =)100(0x20000000L,)124 L (596 char elem[NAMELEN]; /* last name element from namec */)0(664 CHMOUNT =)100(0x10000000L,)124 L (597 Chan *slash;)0(665 };)100 L (598 Chan *dot;)0(666)100 L (599)0(667 /*)100 L (600 Note note[NNOTE];)0(668 * auth messages)100 L (601 short nnote;)0(669 */)100 L (602 short notified;)0(/* sysnoted is due */)32(670 enum)100 L (603 Note lastnote;)0(671 {)100 L (604 int \(*notify\)\(void*, char*\);)0(672 FScchal = 1,)100 L (605)0(673 FSschal,)100 L (606 int lockwait;)0(/* waiting for lock to be released */)32(674 FSok,)100 L (607)0(675 FSctick,)100 L (608 Mach *wired;)0(676 FSstick,)100 L (609 Mach *mp;)0(/* machine this process last ran on */)32(677 FSerr,)100 L (610 ulong priority;)0(/* priority level */)32(678)100 L (611 ulong basepri;)0(/* base priority level */)32(679 RXschal = 0,)100 L (612 ulong rt;)0(/* # ticks used since last blocked */)32(680 RXstick = 1,)100 L cleartomark showpage saveobj restore %%EndPage: 173 173 %%Page: 174 174 /saveobj save def mark 174 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portdat.h Page 6)l ()l ()l (681)0(749 #pragma varargck)100(type "S" Rune*)132 L (682 AUTHLEN = 8,)0(750 #pragma varargck)100(type "r" void)132 L (683 };)0(751 #pragma varargck)100(type "%" void)132 L (684)0(752 #pragma varargck)100(type "I" uchar*)132 L (685 enum)0(753 #pragma varargck)100(type "V" uchar*)132 L (686 {)0(754 #pragma varargck)100(type "E" uchar*)132 L (687 LRESPROF)0(= 3,)24(755 #pragma varargck)100(type "M" uchar*)132 L (688 };)0(756 #pragma varargck)100(type "p" void*)132 L (689)l (690 /*)l (691 * action log)l (692 */)l (693 struct Log {)l (694 Lock;)l (695 int opens;)l (696 char* buf;)l (697 char *end;)l (698 char *rptr;)l (699 int len;)l (700)l (701 int logmask;)0(/* mask of things to debug */)32 L (702)l (703 QLock readq;)l (704 Rendez readr;)l (705 };)l (706)l (707 struct Logflag {)l (708 char* name;)l (709 int mask;)l (710 };)l (711)l (712 struct Cmdbuf)l (713 {)l (714 char buf[256];)l (715 char *f[16];)l (716 int nf;)l (717 };)l (718)l (719 extern int nsyscall;)l (720)l (721 #define DEVDOTDOT -1)l (722)l (723 #pragma varargck)0(argpos print 1)32 L (724 #pragma varargck)0(argpos snprint 3)32 L (725 #pragma varargck)0(argpos sprint 2)32 L (726 #pragma varargck)0(argpos fprint 2)32 L (727)l (728 #pragma varargck)0(type "lld" vlong)32 L (729 #pragma varargck)0(type "llx" vlong)32 L (730 #pragma varargck)0(type "lld" uvlong)32 L (731 #pragma varargck)0(type "llx" uvlong)32 L (732 #pragma varargck)0(type "lx" void*)32 L (733 #pragma varargck)0(type "ld" long)32 L (734 #pragma varargck)0(type "lx" long)32 L (735 #pragma varargck)0(type "ld" ulong)32 L (736 #pragma varargck)0(type "lx" ulong)32 L (737 #pragma varargck)0(type "d" int)32 L (738 #pragma varargck)0(type "x" int)32 L (739 #pragma varargck)0(type "c" int)32 L (740 #pragma varargck)0(type "C" int)32 L (741 #pragma varargck)0(type "d" uint)32 L (742 #pragma varargck)0(type "x" uint)32 L (743 #pragma varargck)0(type "c" uint)32 L (744 #pragma varargck)0(type "C" uint)32 L (745 #pragma varargck)0(type "f" double)32 L (746 #pragma varargck)0(type "e" double)32 L (747 #pragma varargck)0(type "g" double)32 L (748 #pragma varargck)0(type "s" char*)32 L cleartomark showpage saveobj restore %%EndPage: 174 174 %%Page: 175 175 /saveobj save def mark 175 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portfns.h Page 1)l ()l ()l (1 void)0(accounttime\(void\);)24(69 Chan*)100(devclone\(Chan*, Chan*\);)124 L (2 void)0(addclock0link\(void \(*\)\(void\)\);)24(70 void)100(devcreate\(Chan*, char*, int, ulong\);)124 L (3 int)0(addphysseg\(Physseg*\);)24(71 void)100(devdir\(Chan*, Qid, char*, vlong, char*, long, Dir*\);)124 L (4 void)0(addrootfile\(char*, uchar*, ulong\);)24(72 long)100(devdirread\(Chan*, char*, long, Dirtab*, int, Devgen*\);)124 L (5 Block*)0(adjustblock\(Block*, int\);)24(73 Devgen)100(devgen;)124 L (6 void)0(alarmkproc\(void*\);)24(74 void)100(devinit\(void\);)124 L (7 Block*)0(allocb\(int\);)24(75 int)100(devno\(int, int\);)124 L (8 int)0(anyhigher\(void\);)24(76 Chan*)100(devopen\(Chan*, int, Dirtab*, int, Devgen*\);)124 L (9 int)0(anyready\(void\);)24(77 void)100(devremove\(Chan*\);)124 L (10 #define assert\(x\))0(if\(x\);else panic\("assert\(x\) failed"\);)32(78 void)100(devreset\(void\);)124 L (11 void)0(_assert\(char*\);)24(79 void)100(devstat\(Chan*, char*, Dirtab*, int, Devgen*\);)124 L (12 Image*)0(attachimage\(int, Chan*, ulong, ulong\);)24(80 int)100(devwalk\(Chan*, char*, Dirtab*, int, Devgen*\);)124 L (13 long)0(authcheck\(Chan*, char*, int\);)24(81 void)100(devwstat\(Chan*, char*\);)124 L (14 long)0(authcheckread\(Chan*, char*, int n\);)24(82 Chan*)100(domount\(Chan*\);)124 L (15 void)0(authclose\(Chan*\);)24(83 void)100(drawactive\(int\);)124 L (16 long)0(authentread\(Chan*, char*, int\);)24(84 void)100(drawcmap\(void\);)124 L (17 long)0(authentwrite\(Chan*, char*, int\);)24(85 void)100(dumpaproc\(Proc*\);)124 L (18 long)0(authread\(Chan*, char*, int\);)24(86 void)100(dumpqueues\(void\);)124 L (19 void)0(authreply\(Session*, ulong, Fcall*\);)24(87 void)100(dumpregs\(Ureg*\);)124 L (20 ulong)0(authrequest\(Session*, Fcall*\);)24(88 void)100(dumpstack\(void\);)124 L (21 long)0(authwrite\(Chan*, char*, int\);)24(89 Fgrp*)100(dupfgrp\(Fgrp*\);)124 L (22 Page*)0(auxpage\(void\);)24(90 void)100(duppage\(Page*\);)124 L (23 int)0(blocklen\(Block*\);)24(91 void)100(dupswap\(Page*\);)124 L (24 void)0(cachedel\(Image*, ulong\);)24(92 int)100(encrypt\(void*, void*, int\);)124 L (25 void)0(cachepage\(Page*, Image*\);)24(93 void)100(envcpy\(Egrp*, Egrp*\);)124 L (26 void)0(callwithureg\(void\(*\)\(Ureg*\)\);)24(94 int)100(eqchan\(Chan*, Chan*, int\);)124 L (27 int)0(cangetc\(void*\);)24(95 int)100(eqqid\(Qid, Qid\);)124 L (28 int)0(canlock\(Lock*\);)24(96 void)100(error\(char*\);)124 L (29 int)0(canpage\(Proc*\);)24(97 long)100(execregs\(ulong, ulong, ulong\);)124 L (30 int)0(canputc\(void*\);)24(98 void)100(exhausted\(char*\);)124 L (31 int)0(canqlock\(QLock*\);)24(99 void)100(exit\(int\);)124 L (32 int)0(canrlock\(RWlock*\);)24(100 vlong)100(fastticks\(uvlong*\);)124 L (33 void)0(chandevinit\(void\);)24(101 int)100(fault\(ulong, int\);)124 L (34 void)0(chandevreset\(void\);)24(102 void)100(fdclose\(int, int\);)124 L (35 void)0(chanfree\(Chan*\);)24(103 Chan*)100(fdtochan\(int, int, int, int\);)124 L (36 void)0(chanrec\(Mnt*\);)24(104 int)100(fixfault\(Segment*, ulong, int, int\);)124 L (37 void)0(checkalarms\(void\);)24(105 void)100(flushmmu\(void\);)124 L (38 void)0(checkb\(Block*, char*\);)24(106 void)100(forkchild\(Proc*, Ureg*\);)124 L (39 void)0(cinit\(void\);)24(107 void)100(forkret\(void\);)124 L (40 Chan*)0(cclone\(Chan*, Chan*\);)24(108 void)100(free\(void*\);)124 L (41 void)0(cclose\(Chan*\);)24(109 void)100(freeb\(Block*\);)124 L (42 void)0(closeegrp\(Egrp*\);)24(110 void)100(freeblist\(Block*\);)124 L (43 void)0(closefgrp\(Fgrp*\);)24(111 int)100(freebroken\(void\);)124 L (44 void)0(closemount\(Mount*\);)24(112 void)100(freechan\(Chan*\);)124 L (45 void)0(closepgrp\(Pgrp*\);)24(113 void)100(freepte\(Segment*, Pte*\);)124 L (46 void)0(closergrp\(Rgrp*\);)24(114 void)100(freesegs\(int\);)124 L (47 long)0(clrfpintr\(void\);)24(115 void)100(freesession\(Session*\);)124 L (48 int)0(cmount\(Chan*, Chan*, int, char*\);)24(116 void)100(getcolor\(ulong, ulong*, ulong*, ulong*\);)124 L (49 void)0(cnameclose\(Cname*\);)24(117 ulong)100(getmalloctag\(void*\);)124 L (50 void)0(confinit\(void\);)24(118 ulong)100(getrealloctag\(void*\);)124 L (51 void)0(confinit1\(int\);)24(119 void)100(gotolabel\(Label*\);)124 L (52 int)0(consactive\(void\);)24(120 int)100(haswaitq\(void*\);)124 L (53 void)0(\(*consdebug\)\(void\);)24(121 long)100(hostdomainwrite\(char*, int\);)124 L (54 void)0(copen\(Chan*\);)24(122 long)100(hostownerwrite\(char*, int\);)124 L (55 Block*)0(concatblock\(Block*\);)24(123 void)100(iallocinit\(void\);)124 L (56 Block*)0(copyblock\(Block*, int\);)24(124 Block*)100(iallocb\(int\);)124 L (57 void)0(copypage\(Page*, Page*\);)24(125 void)100(iallocsummary\(void\);)124 L (58 int)0(cread\(Chan*, uchar*, int, vlong\);)24(126 long)100(ibrk\(ulong, int\);)124 L (59 void)0(cunmount\(Chan*, Chan*\);)24(127 void)100(ilock\(Lock*\);)124 L (60 void)0(cupdate\(Chan*, uchar*, int, vlong\);)24(128 void)100(iunlock\(Lock*\);)124 L (61 void)0(cwrite\(Chan*, uchar*, int, vlong\);)24(129 int)100(incref\(Ref*\);)124 L (62 ulong)0(dbgpc\(Proc*\);)24(130 void)100(initseg\(void\);)124 L (63 int)0(decref\(Ref*\);)24(131 void)100(isdir\(Chan*\);)124 L (64 int)0(decrypt\(void*, void*, int\);)24(132 int)100(iseve\(void\);)124 L (65 void)0(delay\(int\);)24(133 int)100(islo\(void\);)124 L (66 Chan*)0(devattach\(int, char*\);)24(134 int)100(ispages\(void*\);)124 L (67 Block*)0(devbread\(Chan*, long, ulong\);)24(135 void)100(ixsummary\(void\);)124 L (68 long)0(devbwrite\(Chan*, Block*, ulong\);)24(136 void)100(kbdclock\(void\);)124 L cleartomark showpage saveobj restore %%EndPage: 175 175 %%Page: 176 176 /saveobj save def mark 176 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portfns.h Page 2)l ()l ()l (137 int)0(kbdcr2nl\(Queue*, int\);)24(205 void)100(procctl\(Proc*\);)124 L (138 int)0(kbdputc\(Queue*, int\);)24(206 void)100(procdump\(void\);)124 L (139 void)0(kbdrepeat\(int\);)24(207 void)100(procinit0\(void\);)124 L (140 long)0(keyread\(char*, int, long\);)24(208 void)100(procflushseg\(Segment*\);)124 L (141 long)0(keywrite\(char*, int\);)24(209 Proc*)100(proctab\(int\);)124 L (142 void)0(kickpager\(void\);)24(210 void)100(procwired\(Proc*, int\);)124 L (143 void)0(killbig\(void\);)24(211 Pte*)100(ptealloc\(void\);)124 L (144 int)0(kprint\(char*, ...\);)24(212 Pte*)100(ptecpy\(Pte*\);)124 L (145 void)0(kproc\(char*, void\(*\)\(void*\), void*\);)24(213 int)100(pullblock\(Block**, int\);)124 L (146 void)0(kprocchild\(Proc*, void \(*\)\(void*\), void*\);)24(214 Block*)100(pullupblock\(Block*, int\);)124 L (147 void)0(\(*kproftimer\)\(ulong\);)24(215 void)100(putimage\(Image*\);)124 L (148 void)0(ksetenv\(char*, char*\);)24(216 void)100(putmhead\(Mhead*\);)124 L (149 long)0(latin1\(Rune*, int\);)24(217 void)100(putmmu\(ulong, ulong, Page*\);)124 L (150 void)0(lock\(Lock*\);)24(218 void)100(putpage\(Page*\);)124 L (151 void)0(lockinit\(void\);)24(219 void)100(putseg\(Segment*\);)124 L (152 void)0(logopen\(Log*\);)24(220 void)100(putstr\(char*\);)124 L (153 void)0(logclose\(Log*\);)24(221 void)100(putstr\(char*\);)124 L (154 char*)0(logctl\(Log*, int, char**, Logflag*\);)24(222 void)100(putstrn\(char*, int\);)124 L (155 long)0(logread\(Log*, void*, ulong, long\);)24(223 void)100(putswap\(Page*\);)124 L (156 void)0(log\(Log*, int, char*, ...\);)24(224 ulong)100(pwait\(Waitmsg*\);)124 L (157 Page*)0(lookpage\(Image*, ulong\);)24(225 Block*)100(qbread\(Queue*, int\);)124 L (158 void)0(machinit\(void\);)24(226 long)100(qbwrite\(Queue*, Block*\);)124 L (159 void*)0(mallocz\(ulong, int\);)24(227 int)100(qcanread\(Queue*\);)124 L (160 void*)0(malloc\(ulong\);)24(228 void)100(qclose\(Queue*\);)124 L (161 void)0(mallocsummary\(void\);)24(229 int)100(qconsume\(Queue*, void*, int\);)124 L (162 void)0(mfreeseg\(Segment*, ulong, int\);)24(230 Block*)100(qcopy\(Queue*, int, ulong\);)124 L (163 void)0(microdelay\(int\);)24(231 void)100(qdiscard\(Queue*, int\);)124 L (164 void)0(mmurelease\(Proc*\);)24(232 void)100(qflush\(Queue*\);)124 L (165 void)0(mmuswitch\(Proc*\);)24(233 int)100(qfull\(Queue*\);)124 L (166 void)0(mntdump\(void\);)24(234 Block*)100(qget\(Queue*\);)124 L (167 long)0(mntread9p\(Chan*, void*, long, vlong\);)24(235 void)100(qhangup\(Queue*, char*\);)124 L (168 long)0(mntwrite9p\(Chan*, void*, long, vlong\);)24(236 int)100(qisclosed\(Queue*\);)124 L (169 void)0(mountfree\(Mount*\);)24(237 void)100(qinit\(void\);)124 L (170 ulong)0(msize\(void*\);)24(238 int)100(qiwrite\(Queue*, void*, int\);)124 L (171 Chan*)0(namec\(char*, int, int, ulong\);)24(239 int)100(qlen\(Queue*\);)124 L (172 void)0(nameok\(char*, int\);)24(240 void)100(qlock\(QLock*\);)124 L (173 #define)0(nelem\(x\))24(\(sizeof\(x\)/sizeof\(x[0]\)\))40(241 Queue*)100(qopen\(int, int, void \(*\)\(void*\), void*\);)124 L (174 Chan*)0(newchan\(void\);)24(242 int)100(qpass\(Queue*, Block*\);)124 L (175 Mount*)0(newmount\(Mhead*, Chan*, int, char*\);)24(243 int)100(qpassnolim\(Queue*, Block*\);)124 L (176 Page*)0(newpage\(int, Segment **, ulong\);)24(244 int)100(qproduce\(Queue*, void*, int\);)124 L (177 Pgrp*)0(newpgrp\(void\);)24(245 long)100(qread\(Queue*, void*, int\);)124 L (178 Rgrp*)0(newrgrp\(void\);)24(246 void)100(qreopen\(Queue*\);)124 L (179 Proc*)0(newproc\(void\);)24(247 void)100(qunlock\(QLock*\);)124 L (180 char*)0(nextelem\(char*, char*\);)24(248 int)100(qwindow\(Queue*\);)124 L (181 void)0(nexterror\(void\);)24(249 int)100(qwrite\(Queue*, void*, int\);)124 L (182 Cname*)0(newcname\(char*\);)24(250 void)100(qsetlimit\(Queue*, int\);)124 L (183 int)0(notify\(Ureg*\);)24(251 void)100(qnoblock\(Queue*, int\);)124 L (184 int)0(nrand\(int\);)24(252 int)100(rand\(void\);)124 L (185 int)0(okaddr\(ulong, ulong, int\);)24(253 void)100(rdb\(void\);)124 L (186 int)0(openmode\(ulong\);)24(254 int)100(readnum\(ulong, char*, ulong, ulong, int\);)124 L (187 Block*)0(packblock\(Block*\);)24(255 int)100(readstr\(ulong, char*, ulong, char*\);)124 L (188 Block*)0(padblock\(Block*, int\);)24(256 void)100(ready\(Proc*\);)124 L (189 void)0(pagechainhead\(Page*\);)24(257 void)100(relocateseg\(Segment*, ulong\);)124 L (190 void)0(pageinit\(void\);)24(258 void)100(renameuser\(char*, char*\);)124 L (191 void)0(pagersummary\(void\);)24(259 void)100(resched\(char*\);)124 L (192 void)0(panic\(char*, ...\);)24(260 void)100(resrcwait\(char*\);)124 L (193 Cmdbuf*)0(parsecmd\(char *a, int n\);)24(261 int)100(return0\(void*\);)124 L (194 void)0(pexit\(char*, int\);)24(262 void)100(rlock\(RWlock*\);)124 L (195 void)0(pgrpcpy\(Pgrp*, Pgrp*\);)24(263 void)100(rootreq\(Chan*, Mnt*\);)124 L (196 void)0(pgrpnote\(ulong, char*, long, int\);)24(264 long)100(rtctime\(void\);)124 L (197 Pgrp*)0(pgrptab\(int\);)24(265 void)100(runlock\(RWlock*\);)124 L (198 void)0(pio\(Segment *, ulong, ulong, Page **\);)24(266 Proc*)100(runproc\(void\);)124 L (199 #define)0(poperror\(\))24(up->nerrlab--)48(267 void)100(savefpregs\(FPsave*\);)124 L (200 int)0(postnote\(Proc*, int, char*, int\);)24(268 void)100(\(*saveintrts\)\(void\);)124 L (201 int)0(pprint\(char*, ...\);)24(269 void)100(sched\(void\);)124 L (202 void)0(printinit\(void\);)24(270 void)100(scheddump\(void\);)124 L (203 ulong)0(procalarm\(ulong\);)24(271 void)100(schedinit\(void\);)124 L (204 int)0(proccounter\(char *name\);)24(272 int)100(screenbits\(void\);)124 L cleartomark showpage saveobj restore %%EndPage: 176 176 %%Page: 177 177 /saveobj save def mark 177 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/portfns.h Page 3)l ()l ()l (273 long)0(seconds\(void\);)24 L (274 ulong)0(segattach\(Proc*, ulong, char *, ulong, ulong\);)24 L (275 void)0(segclock\(ulong\);)24 L (276 void)0(segpage\(Segment*, Page*\);)24 L (277 int)0(serialgetc\(void\);)24 L (278 void)0(serialputs\(char*, int\);)24 L (279 int)0(setcolor\(ulong, ulong, ulong, ulong\);)24 L (280 void)0(setkernur\(Ureg*, Proc*\);)24 L (281 int)0(setlabel\(Label*\);)24 L (282 void)0(setmalloctag\(void*, ulong\);)24 L (283 void)0(setrealloctag\(void*, ulong\);)24 L (284 void)0(setregisters\(Ureg*, char*, char*, int\);)24 L (285 void)0(setswapchan\(Chan*\);)24 L (286 char*)0(skipslash\(char*\);)24 L (287 void)0(sleep\(Rendez*, int\(*\)\(void*\), void*\);)24 L (288 void*)0(smalloc\(ulong\);)24 L (289 int)0(splhi\(void\);)24 L (290 int)0(spllo\(void\);)24 L (291 void)0(splx\(int\);)24 L (292 void)0(splxpc\(int\);)24 L (293 char* srvname\(Chan*\);)l (294 int)0(swapcount\(ulong\);)24 L (295 int)0(swapfull\(void\);)24 L (296 void)0(swapinit\(void\);)24 L (297 vlong)0(todget\(vlong*\);)24 L (298 void)0(todfix\(void\);)24 L (299 void)0(todsetfreq\(vlong\);)24 L (300 void)0(todinit\(void\);)24 L (301 void)0(todset\(vlong, vlong, int\);)24 L (302 Block*)0(trimblock\(Block*, int, int\);)24 L (303 void)0(tsleep\(Rendez*, int \(*\)\(void*\), void*, int\);)24 L (304 void)0(unbreak\(Proc*\);)24 L (305 void)0(uncachepage\(Page*\);)24 L (306 long)0(unionread\(Chan*, void*, long\);)24 L (307 void)0(unlock\(Lock*\);)24 L (308 Chan*)0(undomount\(Chan*\);)24 L (309 void)0(userinit\(void\);)24 L (310 ulong)0(userpc\(void\);)24 L (311 long)0(userwrite\(char*, int\);)24 L (312 void)0(validaddr\(ulong, ulong, int\);)24 L (313 void)0(vcacheinval\(Page*, ulong\);)24 L (314 void*)0(vmemchr\(void*, int, int\);)24 L (315 int)0(wakeup\(Rendez*\);)24 L (316 int)0(walk\(Chan**, char*, int\);)24 L (317 int)0(walkname\(Chan**, char*, int\);)24 L (318 void)0(wlock\(RWlock*\);)24 L (319 void)0(wunlock\(RWlock*\);)24 L (320 void*)0(xalloc\(ulong\);)24 L (321 void*)0(xallocz\(ulong, int\);)24 L (322 void)0(xfree\(void*\);)24 L (323 void)0(xhole\(ulong, ulong\);)24 L (324 void)0(xinit\(void\);)24 L (325 int)0(xmerge\(void*, void*\);)24 L (326 void*)0(xspanalloc\(ulong, int, ulong\);)24 L (327 void)0(xsummary\(void\);)24 L (328 Segment* data2txt\(Segment*\);)l (329 Segment* dupseg\(Segment**, int, int\);)l (330 Segment* newseg\(int, ulong, ulong\);)l (331 Segment* seg\(Proc*, ulong, int\);)l (332 void)0(hnputv\(void*, vlong\);)24 L (333 void)0(hnputl\(void*, ulong\);)24 L (334 void)0(hnputs\(void*, ushort\);)24 L (335 vlong)0(nhgetv\(void*\);)24 L (336 ulong)0(nhgetl\(void*\);)24 L (337 ushort)0(nhgets\(void*\);)24 L cleartomark showpage saveobj restore %%EndPage: 177 177 %%Page: 178 178 /saveobj save def mark 178 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(*)125(palloc)132 L (2 #include "../port/lib.h")0(70)100(*/)125 L (3 #include "mem.h")0(71)100(mmurelease\(up\);)124 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(up->qnext = procalloc.free;)124 L (6 #include "../port/error.h")0(74)100(procalloc.free = up;)124 L (7)0(75)100 L (8 Ref)0(pidalloc;)16(76)100(unlock\(&palloc\);)124 L (9 Ref)0(noteidalloc;)16(77)100(unlock\(&procalloc\);)124 L (10)0(78)100(break;)124 L (11 struct)0(79)100(})116 L (12 {)0(80)100(up->mach = 0;)116 L (13)0(Lock;)8(81)100(up = 0;)116 L (14)0(Proc* arena;)8(82)100(})108 L (15)0(Proc* free;)8(83)100(sched\(\);)108 L (16 }procalloc;)0(84 })100 L (17)0(85)100 L (18 struct)0(86 /*)100 L (19 {)0(87 * If changing this routine, look also at sleep\(\). It)100 L (20)0(Lock;)8(88 * contains a copy of the guts of sched\(\).)100 L (21)0(Waitq* free;)8(89 */)100 L (22 }waitqalloc;)0(90 void)100 L (23)0(91 sched\(void\))100 L (24 typedef struct)0(92 {)100 L (25 {)0(93)100(if\(up\) {)108 L (26)0(Lock;)8(94)100(splhi\(\);)116 L (27)0(Proc* head;)8(95)100 L (28)0(Proc* tail;)8(96)100(/* statistics */)116 L (29)0(int n;)8(97)100(m->cs++;)116 L (30 } Schedq;)0(98)100 L (31)0(99)100(procsave\(up\);)116 L (32 int)0(nrdy;)16(100)100(if\(setlabel\(&up->sched\)\) {)116 L (33 Schedq runq[Nrq];)0(101)100(procrestore\(up\);)124 L (34)0(102)100(spllo\(\);)124 L (35 char *statename[] =)0(103)100(return;)124 L (36 {)0(/* BUG: generate automatically */)24(104)100(})116 L (37)0("Dead",)8(105)100(gotolabel\(&m->sched\);)116 L (38)0("Moribund",)8(106 })100 L (39)0("Ready",)8(107 up = runproc\(\);)100 L (40)0("Scheding",)8(108 up->state = Running;)100 L (41)0("Running",)8(109 up->mach = MACHP\(m->machno\);)100 L (42)0("Queueing",)8(110 m->proc = up;)100 L (43)0("QueueingR",)8(111 mmuswitch\(up\);)100 L (44)0("QueueingW",)8(112 gotolabel\(&up->sched\);)100 L (45)0("Wakeme",)8(113 })100 L (46)0("Broken",)8(114)100 L (47)0("Stopped",)8(115 int)100 L (48)0("Rendez",)8(116 anyready\(void\))100 L (49 };)0(117 {)100 L (50)0(118 return nrdy;)100 L (51 /*)0(119 })100 L (52 * Always splhi\(\)'ed.)0(120)100 L (53 */)0(121 int)100 L (54 void)0(122 anyhigher\(void\))100 L (55 schedinit\(void\))0(/* never returns */)32(123 {)100 L (56 {)0(124 Schedq *rq;)100 L (57)0(setlabel\(&m->sched\);)8(125)100 L (58)0(if\(up\) {)8(126 if\(nrdy == 0\))100 L (59)0(m->proc = 0;)16(127)100(return 0;)116 L (60)0(switch\(up->state\) {)16(128)100 L (61)0(case Running:)16(129 for\(rq = &runq[Nrq-1]; rq > &runq[up->priority]; rq--\))100 L (62)0(ready\(up\);)24(130)100(if\(rq->head != nil\))116 L (63)0(break;)24(131)100(return 1;)124 L (64)0(case Moribund:)16(132)100 L (65)0(up->state = Dead;)24(133 return 0;)100 L (66)0(/*)24(134 })100 L (67)0(* Holding locks from pexit:)25(135)100 L (68)0(*)25(procalloc)32(136 enum)100 L cleartomark showpage saveobj restore %%EndPage: 178 178 %%Page: 179 179 /saveobj save def mark 179 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 2)l ()l ()l (137 {)0(205)100(/*)124 L (138 Squantum = \(HZ+Nrq-1\)/Nrq,)0(206)100(* once in a while, run process that's been waiting longest)125 L (139 };)0(207)100(* regardless of movetime)125 L (140)0(208)100(*/)125 L (141 void)0(209)100(rt = 0xffffffff;)124 L (142 ready\(Proc *p\))0(210)100(xrq = nil;)124 L (143 {)0(211)100(for\(rq = runq; rq < &runq[Nrq]; rq++\){)124 L (144 int s, pri;)0(212)100(p = rq->head;)132 L (145 Schedq *rq;)0(213)100(if\(p == 0\))132 L (146)0(214)100(continue;)140 L (147 s = splhi\(\);)0(215)100(if\(p->readytime < rt\){)132 L (148)0(216)100(xrq = rq;)140 L (149 /* history counts */)0(217)100(rt = p->readytime;)140 L (150 if\(p->state == Running\){)0(218)100(})132 L (151)0(p->rt++;)16(219)100(})124 L (152)0(pri = \(\(p->art + \(p->rt<<1\)\)>>2\)/Squantum;)16(220)100(if\(xrq != nil\){)124 L (153 } else {)0(221)100(rq = xrq;)132 L (154)0(p->art = \(p->art + \(p->rt<<1\)\)>>2;)16(222)100(p = rq->head;)132 L (155)0(p->rt = 0;)16(223)100(if\(p != nil && p->wired == nil\))132 L (156)0(pri = p->art/Squantum;)16(224)100(p->movetime = 0;)140 L (157 })0(225)100(goto found;)132 L (158 pri = p->basepri - pri;)0(226)100(})124 L (159 if\(pri < 0\))0(227)100(} else {)116 L (160)0(pri = 0;)16(228)100(/*)124 L (161)0(229)100(* get highest priority process that this)125 L (162 /* the only intersection between the classes is at PriNormal */)0(230)100(* processor can run given affinity constraints)125 L (163 if\(pri < PriNormal && p->basepri > PriNormal\))0(231)100(*/)125 L (164)0(pri = PriNormal;)16(232)100(for\(rq = &runq[Nrq-1]; rq >= runq; rq--\){)124 L (165)0(233)100(p = rq->head;)132 L (166 /* stick at low priority any process waiting for a lock */)0(234)100(if\(p == 0\))132 L (167 if\(p->lockwait\))0(235)100(continue;)140 L (168)0(pri = PriLock;)16(236)100(for\(; p; p = p->rnext\){)132 L (169)0(237)100(if\(p->mp == MACHP\(m->machno\))140 L (170 p->priority = pri;)0(238)100(|| p->movetime < MACHP\(0\)->ticks\))140 L (171 rq = &runq[p->priority];)0(239)100(goto found;)148 L (172)0(240)100(})132 L (173 lock\(runq\);)0(241)100(})124 L (174 p->rnext = 0;)0(242)100(})116 L (175 if\(rq->tail\))0(243 })100 L (176)0(rq->tail->rnext = p;)16(244)100 L (177 else)0(245 found:)100 L (178)0(rq->head = p;)16(246 splhi\(\);)100 L (179 rq->tail = p;)0(247 if\(!canlock\(runq\)\))100 L (180 rq->n++;)0(248)100(goto loop;)116 L (181 nrdy++;)0(249)100 L (182 p->readytime = m->ticks;)0(250 l = 0;)100 L (183 p->state = Ready;)0(251 for\(p = rq->head; p; p = p->rnext\){)100 L (184 unlock\(runq\);)0(252)100(if\(p->mp == MACHP\(m->machno\) || p->movetime < MACHP\(0\)->ticks\))116 L (185 splx\(s\);)0(253)100(break;)124 L (186 })0(254)100(l = p;)116 L (187)0(255 })100 L (188 Proc*)0(256)100 L (189 runproc\(void\))0(257 /*)100 L (190 {)0(258)100(* p->mach==0 only when process state is saved)109 L (191 Schedq *rq, *xrq;)0(259)100(*/)109 L (192 Proc *p, *l;)0(260 if\(p == 0 || p->mach\){)100 L (193 ulong rt;)0(261)100(unlock\(runq\);)116 L (194)0(262)100(goto loop;)116 L (195 loop:)0(263 })100 L (196)0(264 if\(p->rnext == 0\))100 L (197 /*)0(265)100(rq->tail = l;)116 L (198)0(* find a process that last ran on this processor \(affinity\),)9(266 if\(l\))100 L (199)0(* or one that hasn't moved in a while \(load balancing\).)9(267)100(l->rnext = p->rnext;)116 L (200)0(*/)9(268 else)100 L (201 spllo\(\);)0(269)100(rq->head = p->rnext;)116 L (202 for\(;;\){)0(270 rq->n--;)100 L (203)0(idlehands\(\);)16(271 nrdy--;)100 L (204)0(if\(\(++\(m->fairness\) & 0x3\) == 0\){)16(272 if\(p->state != Ready\))100 L cleartomark showpage saveobj restore %%EndPage: 179 179 %%Page: 180 180 /saveobj save def mark 180 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 3)l ()l ()l (273)0(print\("runproc %s %lud %s\\n", p->text, p->pid, statename[p->state]\);)16(341 p->noteid = incref\(¬eidalloc\);)100 L (274 unlock\(runq\);)0(342 if\(p->pid==0 || p->noteid==0\))100 L (275)0(343)100(panic\("pidalloc"\);)116 L (276 p->state = Scheding;)0(344 if\(p->kstack == 0\))100 L (277 if\(p->mp != MACHP\(m->machno\)\))0(345)100(p->kstack = smalloc\(KSTACK\);)116 L (278)0(p->movetime = MACHP\(0\)->ticks + HZ/10;)16(346)100 L (279 p->mp = MACHP\(m->machno\);)0(347 return p;)100 L (280 return p;)0(348 })100 L (281 })0(349)100 L (282)0(350 /*)100 L (283 int)0(351 * wire this proc to a machine)100 L (284 canpage\(Proc *p\))0(352 */)100 L (285 {)0(353 void)100 L (286 int ok = 0;)0(354 procwired\(Proc *p, int bm\))100 L (287)0(355 {)100 L (288 splhi\(\);)0(356 Proc *pp;)100 L (289 lock\(runq\);)0(357 int i;)100 L (290 /* Only reliable way to see if we are Running */)0(358 char nwired[MAXMACH];)100 L (291 if\(p->mach == 0\) {)0(359 Mach *wm;)100 L (292)0(p->newtlb = 1;)16(360)100 L (293)0(ok = 1;)16(361 if\(bm < 0\){)100 L (294 })0(362)100(/* pick a machine to wire to */)116 L (295 unlock\(runq\);)0(363)100(memset\(nwired, 0, sizeof\(nwired\)\);)116 L (296 spllo\(\);)0(364)100(p->wired = 0;)116 L (297)0(365)100(pp = proctab\(0\);)116 L (298 return ok;)0(366)100(for\(i=0; iwired;)124 L (300)0(368)100(if\(wm && pp->pid\))124 L (301 Proc*)0(369)100(nwired[wm->machno]++;)132 L (302 newproc\(void\))0(370)100(})116 L (303 {)0(371)100(bm = 0;)116 L (304 Proc *p;)0(372)100(for\(i=0; iwired = MACHP\(bm\);)100 L (313)0(lock\(&procalloc\);)16(381 p->movetime = 0xffffffff;)100 L (314 })0(382 p->mp = p->wired;)100 L (315 procalloc.free = p->qnext;)0(383 })100 L (316 unlock\(&procalloc\);)0(384)100 L (317)0(385 void)100 L (318 p->state = Scheding;)0(386 procinit0\(void\))100(/* bad planning - clashes with devproc.c */)132 L (319 p->psstate = "New";)0(387 {)100 L (320 p->mach = 0;)0(388 Proc *p;)100 L (321 p->qnext = 0;)0(389 int i;)100 L (322 p->nchild = 0;)0(390)100 L (323 p->nwait = 0;)0(391 procalloc.free = xalloc\(conf.nproc*sizeof\(Proc\)\);)100 L (324 p->waitq = 0;)0(392 if\(procalloc.free == nil\))100 L (325 p->pgrp = 0;)0(393)100(panic\("cannot allocate %d procs\\n", conf.nproc\);)116 L (326 p->egrp = 0;)0(394 procalloc.arena = procalloc.free;)100 L (327 p->fgrp = 0;)0(395)100 L (328 p->rgrp = 0;)0(396 p = procalloc.free;)100 L (329 p->pdbg = 0;)0(397 for\(i=0; ifpstate = FPinit;)0(398)100(p->qnext = p+1;)116 L (331 p->kp = 0;)0(399 p->qnext = 0;)100 L (332 p->procctl = 0;)0(400 })100 L (333 p->notepending = 0;)0(401)100 L (334 p->mp = 0;)0(402)100 L (335 p->movetime = 0;)0(403 /*)100 L (336 p->wired = 0;)0(404 * Sleep, postnote, and wakeup are complicated by the)100 L (337 p->ureg = 0;)0(405 * fact that at least one of them must indirect)100 L (338 p->error[0] = '\\0';)0(406 * through an unlocked structure to find the synchronizing)100 L (339 memset\(p->seg, 0, sizeof p->seg\);)0(407 * lock structure. This is because sleep\(\))100 L (340 p->pid = incref\(&pidalloc\);)0(408 * and wakeup\(\) share direct knowledge only of r while)100 L cleartomark showpage saveobj restore %%EndPage: 180 180 %%Page: 181 181 /saveobj save def mark 181 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 4)l ()l ()l (409 * sleep\(\) and postnote\(\) share knowledge only of p. We've)0(477)100(* if condition happened or a note is pending)117 L (410 * chosen to put the synchronization lock in p, i.e.,)0(478)100(* never mind)117 L (411 * p->rlock. Therefore the interaction between sleep\(\))0(479)100(*/)117 L (412 * and postnote\(\) is completely synchronized by keeping)0(480)100(r->p = nil;)116 L (413 * p->rlock locked in sleep until the process has)0(481)100(unlock\(&up->rlock\);)116 L (414 * saved all the information it needs to become dormant.)0(482 } else {)100 L (415 *)0(483)100(/*)116 L (416 * However, wakeup\(\) can only find what process is sleeping)0(484)100(* now we are committed to)117 L (417 * by looking at r->p. A wakeup looks like:)0(485)100(* change state and call scheduler)117 L (418 *)0(486)100(*/)117 L (419 *)0(1\) set condition that sleep checks with \(*f\)\(\))16(487)100(up->state = Wakeme;)116 L (420 *)0(2\) is p = r->p non zero)16(488)100(up->r = r;)116 L (421 *)0(3\) lock\(p->rlock\))16(489)100 L (422 *)0(4\) check r->p == p)16(490)100(/* statistics */)116 L (423 *)0(5\) ...)16(491)100(m->cs++;)116 L (424 *)0(492)100 L (425 * A sleep looks like)0(493)100(procsave\(up\);)116 L (426 *)0(494)100(if\(setlabel\(&up->sched\)\) {)116 L (427 *)0(a\) lock\(p->rlock\))16(495)100(/*)124 L (428 *)0(b\) r->p = up)16(496)100(* here when the process is awakened)125 L (429 *)0(c\) check condition)16(497)100(*/)125 L (430 *)0(d\) ...)16(498)100(procrestore\(up\);)124 L (431 *)0(499)100(spllo\(\);)124 L (432 * On a multiprocessor, two processors)0(500)100(} else {)116 L (433 * may not see writes occur in the same order. The coherence\(\))0(501)100(/*)124 L (434 * instruction ensures that a processor has flushed all its)0(502)100(* here to go to sleep \(i.e. stop Running\))125 L (435 * writes to memory so that those writes will be seen by other)0(503)100(*/)125 L (436 * processors and that the processor will see all writes flushed)0(504)100(unlock\(&up->rlock\);)124 L (437 * by other processors.)0(505)100(gotolabel\(&m->sched\);)124 L (438 *)0(506)100(})116 L (439 * To make the above sequence work on a multiprocessor, we need)0(507 })100 L (440 * to put a coherence\(\) call between \(1\) and \(2\) and between)0(508)100 L (441 * \(b\) and \(c\). That way we're guaranteed that if \(1\) and)0(509 if\(up->notepending\) {)100 L (442 * \(2\) occur after \(c\), the wakeup process will know)0(510)100(up->notepending = 0;)116 L (443 * which process is about to sleep and will enter its)0(511)100(splx\(s\);)116 L (444 * critical section. If it doesn't, the sleep could proceed)0(512)100(error\(Eintr\);)116 L (445 * while the waker returns without doing anything.)0(513 })100 L (446 * Similarly, if \(b\) and \(c\) occur after \(2\),)0(514)100 L (447 * the sleeper needs coherence to see that the condition was)0(515 splx\(s\);)100 L (448 * set. Otherwise it could sleep even though the wakeup)0(516 })100 L (449 * had already decided there was nothing to do.)0(517)100 L (450 *)0(518 int)100 L (451 *)0(jmk & presotto)16(519 tfn\(void *arg\))100 L (452 */)0(520 {)100 L (453 void)0(521 return MACHP\(0\)->ticks >= up->twhen || up->tfn\(arg\);)100 L (454 sleep\(Rendez *r, int \(*f\)\(void*\), void *arg\))0(522 })100 L (455 {)0(523)100 L (456 int s;)0(524 void)100 L (457)0(525 tsleep\(Rendez *r, int \(*fn\)\(void*\), void *arg, int ms\))100 L (458 s = splhi\(\);)0(526 {)100 L (459)0(527 ulong when;)100 L (460 lock\(&up->rlock\);)0(528 Proc *f, **l;)100 L (461 if\(r->p\){)0(529)100 L (462)0(print\("double sleep %lud %lud\\n", r->p->pid, up->pid\);)16(530 /* avoid overflows at the cost of precision */)100 L (463)0(dumpstack\(\);)16(531 if\(ms >= 1000000\))100 L (464 })0(532)100(when = ms/\(1000/HZ\);)116 L (465)0(533 else)100 L (466 /*)0(534)100(when = MS2TK\(ms\);)116 L (467)0(* Wakeup only knows there may be something to do by testing)9(535 when += MACHP\(0\)->ticks;)100 L (468)0(* r->p in order to get something to lock on.)9(536)100 L (469)0(* Flush that information out to memory in case the sleep is)9(537 lock\(&talarm\);)100 L (470)0(* committed.)9(538 /* take out of list if checkalarm didn't */)100 L (471)0(*/)9(539 if\(up->trend\) {)100 L (472 r->p = up;)0(540)100(l = &talarm.list;)116 L (473 coherence\(\);)0(541)100(for\(f = *l; f; f = f->tlink\) {)116 L (474)0(542)100(if\(f == up\) {)124 L (475 if\(\(*f\)\(arg\) || up->notepending\){)0(543)100(*l = up->tlink;)132 L (476)0(/*)16(544)100(break;)132 L cleartomark showpage saveobj restore %%EndPage: 181 181 %%Page: 182 182 /saveobj save def mark 182 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 5)l ()l ()l (545)0(})24(613 int s, ret;)100 L (546)0(l = &f->tlink;)24(614 Rendez *r;)100 L (547)0(})16(615 Proc *d, **l;)100 L (548 })0(616)100 L (549 /* insert in increasing time order */)0(617 if\(dolock\))100 L (550 l = &talarm.list;)0(618)100(qlock\(&p->debug\);)116 L (551 for\(f = *l; f; f = f->tlink\) {)0(619)100 L (552)0(if\(f->twhen >= when\))16(620 //)100(if\(p->kp\))116 L (553)0(break;)24(621 //)100(print\("sending %s to kproc %lud %s\\n", n, p->pid, p->text\);)124 L (554)0(l = &f->tlink;)16(622)100 L (555 })0(623 if\(flag != NUser && \(p->notify == 0 || p->notified\)\))100 L (556 up->trend = r;)0(624)100(p->nnote = 0;)116 L (557 up->twhen = when;)0(625)100 L (558 up->tfn = fn;)0(626 ret = 0;)100 L (559 up->tlink = *l;)0(627 if\(p->nnote < NNOTE\) {)100 L (560 *l = up;)0(628)100(strcpy\(p->note[p->nnote].msg, n\);)116 L (561 unlock\(&talarm\);)0(629)100(p->note[p->nnote++].flag = flag;)116 L (562)0(630)100(ret = 1;)116 L (563 if\(waserror\(\)\){)0(631 })100 L (564)0(up->twhen = 0;)16(632 p->notepending = 1;)100 L (565)0(nexterror\(\);)16(633 if\(dolock\))100 L (566 })0(634)100(qunlock\(&p->debug\);)116 L (567 sleep\(r, tfn, arg\);)0(635)100 L (568 up->twhen = 0;)0(636 s = splhi\(\);)100 L (569 poperror\(\);)0(637 lock\(&p->rlock\);)100 L (570 })0(638 r = p->r;)100 L (571)0(639 if\(r\){)100 L (572 /*)0(640)100(if\(r->p != p || p->r != r || p->state != Wakeme\))116 L (573 * Expects that only one process can call wakeup for any given Rendez)0(641)100(panic\("postnote: state %d %d %d", r->p != p, p->r != r, p->state\);)124 L (574 */)0(642)100(r->p = 0;)116 L (575 int)0(643)100(p->r = 0;)116 L (576 wakeup\(Rendez *r\))0(644)100(ready\(p\);)116 L (577 {)0(645 })100 L (578 Proc *p;)0(646 unlock\(&p->rlock\);)100 L (579 int s, rv;)0(647 splx\(s\);)100 L (580)0(648)100 L (581 /*)0(649 if\(p->state != Rendezvous\))100 L (582)0(* this makes sure that the condition sleep checks)9(650)100(return ret;)116 L (583)0(* with its \(*f\)\(void\) is visible to it)9(651)100 L (584)0(*/)9(652 /* Try and pull out of a rendezvous */)100 L (585 coherence\(\);)0(653 lock\(p->rgrp\);)100 L (586)0(654 if\(p->state == Rendezvous\) {)100 L (587 rv = 0;)0(655)100(p->rendval = ~0;)116 L (588 p = r->p;)0(656)100(l = &REND\(p->rgrp, p->rendtag\);)116 L (589 if\(p == 0\))0(657)100(for\(d = *l; d; d = d->rendhash\) {)116 L (590)0(return rv;)16(658)100(if\(d == p\) {)124 L (591)0(659)100(*l = p->rendhash;)132 L (592 s = splhi\(\);)0(660)100(break;)132 L (593 lock\(&p->rlock\);)0(661)100(})124 L (594)0(662)100(l = &d->rendhash;)124 L (595 if\(r->p == p && p->r == r\){)0(663)100(})116 L (596)0(r->p = 0;)16(664)100(ready\(p\);)116 L (597)0(if\(p->state != Wakeme\))16(665 })100 L (598)0(panic\("wakeup: state"\);)24(666 unlock\(p->rgrp\);)100 L (599)0(p->r = 0;)16(667 return ret;)100 L (600)0(ready\(p\);)16(668 })100 L (601)0(rv = 1;)16(669)100 L (602 })0(670 /*)100 L (603)0(671 * weird thing: keep at most NBROKEN around)100 L (604 unlock\(&p->rlock\);)0(672 */)100 L (605 splx\(s\);)0(673 #define NBROKEN 4)100 L (606)0(674 struct)100 L (607 return rv;)0(675 {)100 L (608 })0(676 QLock;)100 L (609)0(677 int n;)100 L (610 int)0(678 Proc *p[NBROKEN];)100 L (611 postnote\(Proc *p, int dolock, char *n, int flag\))0(679 }broken;)100 L (612 {)0(680)100 L cleartomark showpage saveobj restore %%EndPage: 182 182 %%Page: 183 183 /saveobj save def mark 183 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 6)l ()l ()l (681 void)0(749 fgrp = up->fgrp;)100 L (682 addbroken\(Proc *p\))0(750 up->fgrp = nil;)100 L (683 {)0(751 egrp = up->egrp;)100 L (684 qlock\(&broken\);)0(752 up->egrp = nil;)100 L (685 if\(broken.n == NBROKEN\) {)0(753 rgrp = up->rgrp;)100 L (686)0(ready\(broken.p[0]\);)16(754 up->rgrp = nil;)100 L (687)0(memmove\(&broken.p[0], &broken.p[1], sizeof\(Proc*\)*\(NBROKEN-1\)\);)16(755 pgrp = up->pgrp;)100 L (688)0(--broken.n;)16(756 up->pgrp = nil;)100 L (689 })0(757 dot = up->dot;)100 L (690 broken.p[broken.n++] = p;)0(758 up->dot = nil;)100 L (691 qunlock\(&broken\);)0(759 qunlock\(&up->debug\);)100 L (692)0(760)100 L (693 p->state = Broken;)0(761 if\(fgrp\))100 L (694 p->psstate = 0;)0(762)100(closefgrp\(fgrp\);)116 L (695 sched\(\);)0(763 if\(egrp\))100 L (696 })0(764)100(closeegrp\(egrp\);)116 L (697)0(765 if\(rgrp\))100 L (698 void)0(766)100(closergrp\(rgrp\);)116 L (699 unbreak\(Proc *p\))0(767 if\(dot\))100 L (700 {)0(768)100(cclose\(dot\);)116 L (701 int b;)0(769 if\(pgrp\))100 L (702)0(770)100(closepgrp\(pgrp\);)116 L (703 qlock\(&broken\);)0(771)100 L (704 for\(b=0; b < broken.n; b++\))0(772 /*)100 L (705)0(if\(broken.p[b] == p\) {)16(773)100(* if not a kernel process and have a parent,)109 L (706)0(broken.n--;)24(774)100(* do some housekeeping.)109 L (707)0(memmove\(&broken.p[b], &broken.p[b+1],)24(775)100(*/)109 L (708)0(sizeof\(Proc*\)*\(NBROKEN-\(b+1\)\)\);)40(776 if\(up->kp == 0\) {)100 L (709)0(ready\(p\);)24(777)100(p = up->parent;)116 L (710)0(break;)24(778)100(if\(p == 0\) {)116 L (711)0(})16(779)100(if\(exitstr == 0\))124 L (712 qunlock\(&broken\);)0(780)100(exitstr = "unknown";)132 L (713 })0(781)100(panic\("boot process died: %s", exitstr\);)124 L (714)0(782)100(})116 L (715 int)0(783)100 L (716 freebroken\(void\))0(784)100(while\(waserror\(\)\))116 L (717 {)0(785)100(;)124 L (718 int i, n;)0(786)100 L (719)0(787)100(wq = smalloc\(sizeof\(Waitq\)\);)116 L (720 qlock\(&broken\);)0(788)100(poperror\(\);)116 L (721 n = broken.n;)0(789)100 L (722 for\(i=0; iw.pid, NUMSIZE, up->pid, NUMSIZE\);)116 L (723)0(ready\(broken.p[i]\);)16(791)100(utime = up->time[TUser] + up->time[TCUser];)116 L (724)0(broken.p[i] = 0;)16(792)100(stime = up->time[TSys] + up->time[TCSys];)116 L (725 })0(793)100(readnum\(0, &wq->w.time[TUser*12], NUMSIZE,)116 L (726 broken.n = 0;)0(794)100(TK2MS\(utime\), NUMSIZE\);)124 L (727 qunlock\(&broken\);)0(795)100(readnum\(0, &wq->w.time[TSys*12], NUMSIZE,)116 L (728 return n;)0(796)100(TK2MS\(stime\), NUMSIZE\);)124 L (729 })0(797)100(readnum\(0, &wq->w.time[TReal*12], NUMSIZE,)116 L (730)0(798)100(TK2MS\(MACHP\(0\)->ticks - up->time[TReal]\), NUMSIZE\);)124 L (731 void)0(799)100(if\(exitstr && exitstr[0]\){)116 L (732 pexit\(char *exitstr, int freemem\))0(800)100(n = sprint\(wq->w.msg, "%s %lud:", up->text, up->pid\);)124 L (733 {)0(801)100(strncpy\(wq->w.msg+n, exitstr, ERRLEN-n\);)124 L (734 int n;)0(802)100(wq->w.msg[ERRLEN-1] = 0;)124 L (735 Proc *p;)0(803)100(})116 L (736 Segment **s, **es;)0(804)100(else)116 L (737 long utime, stime;)0(805)100(wq->w.msg[0] = '\\0';)124 L (738 Waitq *wq, *f, *next;)0(806)100 L (739 Fgrp *fgrp;)0(807)100(lock\(&p->exl\);)116 L (740 Egrp *egrp;)0(808)100(/*)116 L (741 Rgrp *rgrp;)0(809)100(* If my parent is no longer alive, or if there would be more)117 L (742 Pgrp *pgrp;)0(810)100(* than 128 zombie child processes for my parent, then don't)117 L (743 Chan *dot;)0(811)100(* leave a wait record behind. This helps prevent badly)117 L (744)0(812)100(* written daemon processes from accumulating lots of wait)117 L (745 up->alarm = 0;)0(813)100(* records.)117 L (746)0(814)100(*/)117 L (747 /* nil out all the resources under lock \(free later\) */)0(815)100(if\(p->pid == up->parentpid && p->state != Broken && p->nwait < 128\) {)116 L (748 qlock\(&up->debug\);)0(816)100(p->nchild--;)124 L cleartomark showpage saveobj restore %%EndPage: 183 183 %%Page: 184 184 /saveobj save def mark 184 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 7)l ()l ()l (817)0(p->time[TCUser] += utime;)24(885 ulong cpid;)100 L (818)0(p->time[TCSys] += stime;)24(886 Waitq *wq;)100 L (819)0(887)100 L (820)0(wq->next = p->waitq;)24(888 if\(!canqlock\(&up->qwaitr\)\))100 L (821)0(p->waitq = wq;)24(889)100(error\(Einuse\);)116 L (822)0(p->nwait++;)24(890)100 L (823)0(891 if\(waserror\(\)\) {)100 L (824)0(wakeup\(&p->waitr\);)24(892)100(qunlock\(&up->qwaitr\);)116 L (825)0(unlock\(&p->exl\);)24(893)100(nexterror\(\);)116 L (826)0(})16(894 })100 L (827)0(else {)16(895)100 L (828)0(unlock\(&p->exl\);)24(896 lock\(&up->exl\);)100 L (829)0(free\(wq\);)24(897 if\(up->nchild == 0 && up->waitq == 0\) {)100 L (830)0(})16(898)100(unlock\(&up->exl\);)116 L (831 })0(899)100(error\(Enochild\);)116 L (832)0(900 })100 L (833 if\(!freemem\))0(901 unlock\(&up->exl\);)100 L (834)0(addbroken\(up\);)16(902)100 L (835)0(903 sleep\(&up->waitr, haswaitq, up\);)100 L (836 qlock\(&up->seglock\);)0(904)100 L (837 es = &up->seg[NSEG];)0(905 lock\(&up->exl\);)100 L (838 for\(s = up->seg; s < es; s++\) {)0(906 wq = up->waitq;)100 L (839)0(if\(*s\) {)16(907 up->waitq = wq->next;)100 L (840)0(putseg\(*s\);)24(908 up->nwait--;)100 L (841)0(*s = 0;)24(909 unlock\(&up->exl\);)100 L (842)0(})16(910)100 L (843 })0(911 qunlock\(&up->qwaitr\);)100 L (844 qunlock\(&up->seglock\);)0(912 poperror\(\);)100 L (845)0(913)100 L (846 lock\(&up->exl\);)0(/* Prevent my children from leaving waits */)32(914 if\(w\))100 L (847 up->pid = 0;)0(915)100(memmove\(w, &wq->w, sizeof\(Waitmsg\)\);)116 L (848 wakeup\(&up->waitr\);)0(916 cpid = atoi\(wq->w.pid\);)100 L (849 unlock\(&up->exl\);)0(917 free\(wq\);)100 L (850)0(918 return cpid;)100 L (851 for\(f = up->waitq; f; f = next\) {)0(919 })100 L (852)0(next = f->next;)16(920)100 L (853)0(free\(f\);)16(921 Proc*)100 L (854 })0(922 proctab\(int i\))100 L (855)0(923 {)100 L (856 /* release debuggers */)0(924 return &procalloc.arena[i];)100 L (857 qlock\(&up->debug\);)0(925 })100 L (858 if\(up->pdbg\) {)0(926)100 L (859)0(wakeup\(&up->pdbg->sleep\);)16(927 void)100 L (860)0(up->pdbg = 0;)16(928 dumpaproc\(Proc *p\))100 L (861 })0(929 {)100 L (862 qunlock\(&up->debug\);)0(930 ulong bss;)100 L (863)0(931 char *s;)100 L (864 /* Sched must not loop for these locks */)0(932)100 L (865 lock\(&procalloc\);)0(933 if\(p == 0\))100 L (866 lock\(&palloc\);)0(934)100(return;)116 L (867)0(935)100 L (868 up->state = Moribund;)0(936 bss = 0;)100 L (869 sched\(\);)0(937 if\(p->seg[BSEG]\))100 L (870 panic\("pexit"\);)0(938)100(bss = p->seg[BSEG]->top;)116 L (871 })0(939)100 L (872)0(940 s = p->psstate;)100 L (873 int)0(941 if\(s == 0\))100 L (874 haswaitq\(void *x\))0(942)100(s = "kproc";)116 L (875 {)0(943 print\("%3lud:%10s pc %8lux dbgpc %8lux %8s \(%s\) ut %ld st %ld bss %lux qpc %lux\\n",)100 L (876 Proc *p;)0(944)100(p->pid, p->text, p->pc, dbgpc\(p\), s, statename[p->state],)116 L (877)0(945)100(p->time[0], p->time[1], bss, p->qpc\);)116 L (878 p = \(Proc *\)x;)0(946 })100 L (879 return p->waitq != 0;)0(947)100 L (880 })0(948 void)100 L (881)0(949 procdump\(void\))100 L (882 ulong)0(950 {)100 L (883 pwait\(Waitmsg *w\))0(951 int i;)100 L (884 {)0(952 Proc *p;)100 L cleartomark showpage saveobj restore %%EndPage: 184 184 %%Page: 185 185 /saveobj save def mark 185 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 8)l ()l ()l (953)0(1021)100(continue;)124 L (954 if\(up\))0(1022)100(print\("rq%ld:", rq-runq\);)116 L (955)0(print\("up %lud\\n", up->pid\);)16(1023)100(for\(p = rq->head; p; p = p->rnext\))116 L (956 else)0(1024)100(print\(" %lud\(%lud, %lud\)", p->pid, m->ticks - p->readytime,)124 L (957)0(print\("no current process\\n"\);)16(1025)100(MACHP\(0\)->ticks - p->movetime\);)132 L (958 for\(i=0; istate == Dead\))16(1028 })100 L (961)0(continue;)24(1029 print\("nrdy %d\\n", nrdy\);)100 L (962)0(1030 })100 L (963)0(dumpaproc\(p\);)16(1031)100 L (964)0(delay\(150\);)16(1032 void)100 L (965 })0(1033 kproc\(char *name, void \(*func\)\(void *\), void *arg\))100 L (966 })0(1034 {)100 L (967)0(1035 Proc *p;)100 L (968 /*)0(1036 static Pgrp *kpgrp;)100 L (969 * wait till all processes have flushed their mmu)0(1037)100 L (970 * state about segement s)0(1038 p = newproc\(\);)100 L (971 */)0(1039 p->psstate = 0;)100 L (972 void)0(1040 p->procmode = 0644;)100 L (973 procflushseg\(Segment *s\))0(1041 p->kp = 1;)100 L (974 {)0(1042)100 L (975 int i, ns, nm, nwait;)0(1043 p->fpsave = up->fpsave;)100 L (976 Proc *p;)0(1044 p->scallnr = up->scallnr;)100 L (977)0(1045 p->s = up->s;)100 L (978 /*)0(1046 p->nerrlab = 0;)100 L (979)0(* tell all processes with this)9(1047 p->slash = up->slash;)100 L (980)0(* segment to flush their mmu's)9(1048 p->dot = up->dot;)100 L (981)0(*/)9(1049 incref\(p->dot\);)100 L (982 nwait = 0;)0(1050)100 L (983 for\(i=0; inote, up->note, sizeof\(p->note\)\);)100 L (984)0(p = &procalloc.arena[i];)16(1052 p->nnote = up->nnote;)100 L (985)0(if\(p->state == Dead\))16(1053 p->notified = 0;)100 L (986)0(continue;)24(1054 p->lastnote = up->lastnote;)100 L (987)0(for\(ns = 0; ns < NSEG; ns++\))16(1055 p->notify = up->notify;)100 L (988)0(if\(p->seg[ns] == s\){)24(1056 p->ureg = 0;)100 L (989)0(p->newtlb = 1;)32(1057 p->dbgreg = 0;)100 L (990)0(for\(nm = 0; nm < conf.nmach; nm++\){)32(1058)100 L (991)0(if\(MACHP\(nm\)->proc == p\){)40(1059 p->basepri = PriKproc;)100 L (992)0(MACHP\(nm\)->flushmmu = 1;)48(1060 p->priority = p->basepri;)100 L (993)0(nwait++;)48(1061)100 L (994)0(})40(1062 kprocchild\(p, func, arg\);)100 L (995)0(})32(1063)100 L (996)0(break;)32(1064 strcpy\(p->user, eve\);)100 L (997)0(})24(1065 if\(kpgrp == 0\))100 L (998 })0(1066)100(kpgrp = newpgrp\(\);)116 L (999)0(1067 p->pgrp = kpgrp;)100 L (1000 if\(nwait == 0\))0(1068 incref\(kpgrp\);)100 L (1001)0(return;)16(1069)100 L (1002)0(1070 strcpy\(p->text, name\);)100 L (1003 /*)0(1071)100 L (1004 * wait for all processors to take a clock interrupt)0(1072 p->nchild = 0;)100 L (1005 * and flush their mmu's)0(1073 p->parent = 0;)100 L (1006 */)0(1074 memset\(p->time, 0, sizeof\(p->time\)\);)100 L (1007 for\(nm = 0; nm < conf.nmach; nm++\))0(1075 p->time[TReal] = MACHP\(0\)->ticks;)100 L (1008)0(if\(MACHP\(nm\) != m\))16(1076 ready\(p\);)100 L (1009)0(while\(MACHP\(nm\)->flushmmu\))24(1077 /*)100 L (1010)0(sched\(\);)32(1078 * since the bss/data segments are now shareable,)100 L (1011 })0(1079 * any mmu info about this process is now stale)100 L (1012)0(1080 * and has to be discarded.)100 L (1013 void)0(1081 */)100 L (1014 scheddump\(void\))0(1082 flushmmu\(\);)100 L (1015 {)0(1083 })100 L (1016 Proc *p;)0(1084)100 L (1017 Schedq *rq;)0(1085 /*)100 L (1018)0(1086 * called splhi\(\) by notify\(\). See comment in notify for the)100 L (1019 for\(rq = &runq[Nrq-1]; rq >= runq; rq--\){)0(1087 * reasoning.)100 L (1020)0(if\(rq->head == 0\))16(1088 */)100 L cleartomark showpage saveobj restore %%EndPage: 185 185 %%Page: 186 186 /saveobj save def mark 186 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 9)l ()l ()l (1089 void)0(1157 killbig\(void\))100 L (1090 procctl\(Proc *p\))0(1158 {)100 L (1091 {)0(1159 int i;)100 L (1092 char *state;)0(1160 Segment *s;)100 L (1093 ulong s;)0(1161 ulong l, max;)100 L (1094)0(1162 Proc *p, *ep, *kp;)100 L (1095 switch\(p->procctl\) {)0(1163)100 L (1096 case Proc_exitbig:)0(1164 max = 0;)100 L (1097)0(spllo\(\);)16(1165 kp = 0;)100 L (1098)0(pexit\("Killed: Insufficient physical memory", 1\);)16(1166 ep = procalloc.arena+conf.nproc;)100 L (1099)0(1167 for\(p = procalloc.arena; p < ep; p++\) {)100 L (1100 case Proc_exitme:)0(1168)100(if\(p->state == Dead || p->kp\))116 L (1101)0(spllo\(\);)16(/* pexit has locks in it */)40(1169)100(continue;)124 L (1102)0(pexit\("Killed", 1\);)16(1170)100(l = 0;)116 L (1103)0(1171)100(for\(i=1; iseg[i];)124 L (1105)0(if\(p->nnote == 0\))16(1173)100(if\(s != 0\))124 L (1106)0(return;)24(1174)100(l += s->top - s->base;)132 L (1107)0(/* No break */)16(1175)100(})116 L (1108)0(1176)100(if\(l > max\) {)116 L (1109 case Proc_stopme:)0(1177)100(kp = p;)124 L (1110)0(p->procctl = 0;)16(1178)100(max = l;)124 L (1111)0(state = p->psstate;)16(1179)100(})116 L (1112)0(p->psstate = "Stopped";)16(1180 })100 L (1113)0(/* free a waiting debugger */)16(1181 kp->procctl = Proc_exitbig;)100 L (1114)0(s = spllo\(\);)16(1182 for\(i = 0; i < NSEG; i++\) {)100 L (1115)0(qlock\(&p->debug\);)16(1183)100(s = kp->seg[i];)116 L (1116)0(if\(p->pdbg\) {)16(1184)100(if\(s != 0 && canqlock\(&s->lk\)\) {)116 L (1117)0(wakeup\(&p->pdbg->sleep\);)24(1185)100(mfreeseg\(s, s->base, \(s->top - s->base\)/BY2PG\);)124 L (1118)0(p->pdbg = 0;)24(1186)100(qunlock\(&s->lk\);)124 L (1119)0(})16(1187)100(})116 L (1120)0(qunlock\(&p->debug\);)16(1188 })100 L (1121)0(splhi\(\);)16(1189 print\("%lud: %s killed because no swap configured\\n", kp->pid, kp->text\);)100 L (1122)0(p->state = Stopped;)16(1190 })100 L (1123)0(sched\(\);)16(1191)100 L (1124)0(p->psstate = state;)16(1192 /*)100 L (1125)0(splx\(s\);)16(1193 * change ownership to 'new' of all processes owned by 'old'. Used when)100 L (1126)0(return;)16(1194 * eve changes.)100 L (1127 })0(1195 */)100 L (1128 })0(1196 void)100 L (1129)0(1197 renameuser\(char *old, char *new\))100 L (1130 #include "errstr.h")0(1198 {)100 L (1131)0(1199 Proc *p, *ep;)100 L (1132 void)0(1200)100 L (1133 error\(char *err\))0(1201 ep = procalloc.arena+conf.nproc;)100 L (1134 {)0(1202 for\(p = procalloc.arena; p < ep; p++\))100 L (1135 spllo\(\);)0(1203)100(if\(strcmp\(old, p->user\) == 0\))116 L (1136 strncpy\(up->error, err, ERRLEN\);)0(1204)100(memmove\(p->user, new, NAMELEN\);)124 L (1137 nexterror\(\);)0(1205 })100 L (1138 })0(1206)100 L (1139)0(1207 /*)100 L (1140 void)0(1208 * time accounting called by clock\(\) splhi'd)100 L (1141 nexterror\(void\))0(1209 */)100 L (1142 {)0(1210 void)100 L (1143 gotolabel\(&up->errlab[--up->nerrlab]\);)0(1211 accounttime\(void\))100 L (1144 })0(1212 {)100 L (1145)0(1213 Proc *p;)100 L (1146 void)0(1214 int n;)100 L (1147 exhausted\(char *resource\))0(1215 static int nrun;)100 L (1148 {)0(1216)100 L (1149 char buf[ERRLEN];)0(1217 p = m->proc;)100 L (1150)0(1218 if\(p\) {)100 L (1151 sprint\(buf, "no free %s", resource\);)0(1219)100(nrun++;)116 L (1152 iprint\("%s\\n", buf\);)0(1220)100(p->time[p->insyscall]++;)116 L (1153 error\(buf\);)0(1221 })100 L (1154 })0(1222)100 L (1155)0(1223 /* only one processor gets to compute system load averages */)100 L (1156 void)0(1224 if\(m->machno != 0\))100 L cleartomark showpage saveobj restore %%EndPage: 186 186 %%Page: 187 187 /saveobj save def mark 187 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/proc.c Page 10)l ()l ()l (1225)0(return;)16 L (1226)l (1227 /* calculate decaying load average */)l (1228 n = nrun;)l (1229 nrun = 0;)l (1230)l (1231 n = \(nrdy+n\)*1000;)l (1232 m->load = \(m->load*19+n\)/20;)l (1233 })l cleartomark showpage saveobj restore %%EndPage: 187 187 %%Page: 188 188 /saveobj save def mark 188 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(print\("consume %lud, produce %lud, qcopy %lud\\n",)108 L (2 #include "../port/lib.h")0(70)100(consumecnt, producecnt, qcopycnt\);)116 L (3 #include "mem.h")0(71 })100 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73 /*)100 L (6 #include "../port/error.h")0(74 * free a list of blocks)100 L (7)0(75 */)100 L (8 static ulong padblockcnt;)0(76 void)100 L (9 static ulong concatblockcnt;)0(77 freeblist\(Block *b\))100 L (10 static ulong pullupblockcnt;)0(78 {)100 L (11 static ulong copyblockcnt;)0(79)100(Block *next;)108 L (12 static ulong consumecnt;)0(80)100 L (13 static ulong producecnt;)0(81)100(for\(; b != 0; b = next\){)108 L (14 static ulong qcopycnt;)0(82)100(next = b->next;)116 L (15)0(83)100(b->next = 0;)116 L (16 static int debugging;)0(84)100(freeb\(b\);)116 L (17)0(85)100(})108 L (18 #define QDEBUG if\(0\))0(86 })100 L (19)0(87)100 L (20 /*)0(88 /*)100 L (21 * IO queues)0(89 * pad a block to the front \(or the back if size is negative\))100 L (22 */)0(90 */)100 L (23 typedef struct Queue)0(Queue;)32(91 Block*)100 L (24)0(92 padblock\(Block *bp, int size\))100 L (25 struct Queue)0(93 {)100 L (26 {)0(94)100(int n;)108 L (27)0(Lock;)8(95)100(Block *nbp;)108 L (28)0(96)100 L (29)0(Block* bfirst;)8(/* buffer */)32(97)100(QDEBUG checkb\(bp, "padblock 1"\);)108 L (30)0(Block* blast;)8(98)100(if\(size >= 0\){)108 L (31)0(99)100(if\(bp->rp - bp->base >= size\){)116 L (32)0(int len;)8(/* bytes allocated to queue */)32(100)100(bp->rp -= size;)124 L (33)0(int dlen;)8(/* data bytes in queue */)32(101)100(return bp;)124 L (34)0(int limit;)8(/* max bytes in queue */)32(102)100(})116 L (35)0(int inilim;)8(/* initial limit */)32(103)100 L (36)0(int state;)8(104)100(if\(bp->next\))116 L (37)0(int noblock;)8(/* true if writes return immediately when q full */)32(105)100(panic\("padblock 0x%uX", getcallerpc\(&bp\)\);)124 L (38)0(int eof;)8(/* number of eofs read by user */)32(106)100(n = BLEN\(bp\);)116 L (39)0(107)100(padblockcnt++;)116 L (40)0(void \(*kick\)\(void*\); /* restart output */)8(108)100(nbp = allocb\(size+n\);)116 L (41)0(void* arg;)8(/* argument to kick */)32(109)100(nbp->rp += size;)116 L (42)0(110)100(nbp->wp = nbp->rp;)116 L (43)0(QLock rlock;)8(/* mutex for reading processes */)32(111)100(memmove\(nbp->wp, bp->rp, n\);)116 L (44)0(Rendez rr;)8(/* process waiting to read */)32(112)100(nbp->wp += n;)116 L (45)0(QLock wlock;)8(/* mutex for writing processes */)32(113)100(freeb\(bp\);)116 L (46)0(Rendez wr;)8(/* process waiting to write */)32(114)100(nbp->rp -= size;)116 L (47)0(115 } else {)100 L (48)0(char err[ERRLEN];)8(116)100(size = -size;)116 L (49 };)0(117)100 L (50)0(118)100(if\(bp->next\))116 L (51 enum)0(119)100(panic\("padblock 0x%uX", getcallerpc\(&bp\)\);)124 L (52 {)0(120)100 L (53)0(/* Queue.state */)8(121)100(if\(bp->lim - bp->wp >= size\))116 L (54)0(Qstarve)8(= \(1<<0\),)24(/* consumer starved */)40(122)100(return bp;)124 L (55)0(Qmsg)8(= \(1<<1\),)24(/* message stream */)40(123)100 L (56)0(Qclosed)8(= \(1<<2\),)24(124)100(n = BLEN\(bp\);)116 L (57)0(Qflow)8(= \(1<<3\),)24(125)100(padblockcnt++;)116 L (58)0(126)100(nbp = allocb\(size+n\);)116 L (59)0(Maxatomic)8(= 32*1024,)24(127)100(memmove\(nbp->wp, bp->rp, n\);)116 L (60 };)0(128)100(nbp->wp += n;)116 L (61)0(129)100(freeb\(bp\);)116 L (62 void)0(130 })100 L (63 ixsummary\(void\))0(131 QDEBUG checkb\(nbp, "padblock 1"\);)100 L (64 {)0(132 return nbp;)100 L (65)0(debugging ^= 1;)8(133 })100 L (66)0(iallocsummary\(\);)8(134)100 L (67)0(print\("pad %lud, concat %lud, pullup %lud, copy %lud\\n",)8(135 /*)100 L (68)0(padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt\);)16(136 * return count of bytes in a string of blocks)100 L cleartomark showpage saveobj restore %%EndPage: 188 188 %%Page: 189 189 /saveobj save def mark 189 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 2)l ()l ()l (137 */)0(205 n -= BLEN\(bp\);)100 L (138 int)0(206 while\(nbp = bp->next\){)100 L (139 blocklen\(Block *bp\))0(207)100(i = BLEN\(nbp\);)116 L (140 {)0(208)100(if\(i > n\) {)116 L (141 int len;)0(209)100(memmove\(bp->wp, nbp->rp, n\);)124 L (142)0(210)100(pullupblockcnt++;)124 L (143 len = 0;)0(211)100(bp->wp += n;)124 L (144 while\(bp\) {)0(212)100(nbp->rp += n;)124 L (145)0(len += BLEN\(bp\);)16(213)100(QDEBUG checkb\(bp, "pullupblock 1"\);)124 L (146)0(bp = bp->next;)16(214)100(return bp;)124 L (147 })0(215)100(})116 L (148 return len;)0(216)100(else {)116 L (149 })0(217)100(memmove\(bp->wp, nbp->rp, i\);)124 L (150)0(218)100(pullupblockcnt++;)124 L (151 /*)0(219)100(bp->wp += i;)124 L (152 * copy the string of blocks into)0(220)100(bp->next = nbp->next;)124 L (153 * a single block and free the string)0(221)100(nbp->next = 0;)124 L (154 */)0(222)100(freeb\(nbp\);)124 L (155 Block*)0(223)100(n -= i;)124 L (156 concatblock\(Block *bp\))0(224)100(if\(n == 0\){)124 L (157 {)0(225)100(QDEBUG checkb\(bp, "pullupblock 2"\);)132 L (158 int len;)0(226)100(return bp;)132 L (159 Block *nb, *f;)0(227)100(})124 L (160)0(228)100(})116 L (161 if\(bp->next == 0\))0(229 })100 L (162)0(return bp;)16(230 freeb\(bp\);)100 L (163)0(231 return 0;)100 L (164 nb = allocb\(blocklen\(bp\)\);)0(232 })100 L (165 for\(f = bp; f; f = f->next\) {)0(233)100 L (166)0(len = BLEN\(f\);)16(234 /*)100 L (167)0(memmove\(nb->wp, f->rp, len\);)16(235 * trim to len bytes starting at offset)100 L (168)0(nb->wp += len;)16(236 */)100 L (169 })0(237 Block *)100 L (170 concatblockcnt += BLEN\(nb\);)0(238 trimblock\(Block *bp, int offset, int len\))100 L (171 freeblist\(bp\);)0(239 {)100 L (172 QDEBUG checkb\(nb, "concatblock 1"\);)0(240 ulong l;)100 L (173 return nb;)0(241 Block *nb, *startb;)100 L (174 })0(242)100 L (175)0(243 QDEBUG checkb\(bp, "trimblock 1"\);)100 L (176 /*)0(244 if\(blocklen\(bp\) < offset+len\) {)100 L (177 * make sure the first block has at least n bytes)0(245)100(freeblist\(bp\);)116 L (178 */)0(246)100(return nil;)116 L (179 Block*)0(247 })100 L (180 pullupblock\(Block *bp, int n\))0(248)100 L (181 {)0(249 while\(\(l = BLEN\(bp\)\) < offset\) {)100 L (182 int i;)0(250)100(offset -= l;)116 L (183 Block *nbp;)0(251)100(nb = bp->next;)116 L (184)0(252)100(bp->next = nil;)116 L (185 /*)0(253)100(freeb\(bp\);)116 L (186)0(* this should almost always be true, it's)9(254)100(bp = nb;)116 L (187)0(* just to avoid every caller checking.)9(255 })100 L (188)0(*/)9(256)100 L (189 if\(BLEN\(bp\) >= n\))0(257 startb = bp;)100 L (190)0(return bp;)16(258 bp->rp += offset;)100 L (191)0(259)100 L (192 /*)0(260 while\(\(l = BLEN\(bp\)\) < len\) {)100 L (193)0(* if not enough room in the first block,)9(261)100(len -= l;)116 L (194)0(* add another to the front of the list.)9(262)100(bp = bp->next;)116 L (195)0(*/)9(263 })100 L (196 if\(bp->lim - bp->rp < n\){)0(264)100 L (197)0(nbp = allocb\(n\);)16(265 bp->wp -= \(BLEN\(bp\) - len\);)100 L (198)0(nbp->next = bp;)16(266)100 L (199)0(bp = nbp;)16(267 if\(bp->next\) {)100 L (200 })0(268)100(freeblist\(bp->next\);)116 L (201)0(269)100(bp->next = nil;)116 L (202 /*)0(270 })100 L (203)0(* copy bytes from the trailing blocks into the first)9(271)100 L (204)0(*/)9(272 return startb;)100 L cleartomark showpage saveobj restore %%EndPage: 189 189 %%Page: 190 190 /saveobj save def mark 190 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 3)l ()l ()l (273 })0(341 Block *bp;)100 L (274)0(342 int n, bytes;)100 L (275 /*)0(343)100 L (276 * copy 'count' bytes into a new block)0(344 bytes = 0;)100 L (277 */)0(345 if\(bph == nil\))100 L (278 Block*)0(346)100(return 0;)116 L (279 copyblock\(Block *bp, int count\))0(347)100 L (280 {)0(348 while\(*bph != nil && count != 0\) {)100 L (281 int l;)0(349)100(bp = *bph;)116 L (282 Block *nbp;)0(350)100(n = BLEN\(bp\);)116 L (283)0(351)100(if\(count < n\))116 L (284 QDEBUG checkb\(bp, "copyblock 0"\);)0(352)100(n = count;)124 L (285 nbp = allocb\(count\);)0(353)100(bytes += n;)116 L (286 for\(; count > 0 && bp != 0; bp = bp->next\){)0(354)100(count -= n;)116 L (287)0(l = BLEN\(bp\);)16(355)100(bp->rp += n;)116 L (288)0(if\(l > count\))16(356)100(QDEBUG checkb\(bp, "pullblock "\);)116 L (289)0(l = count;)24(357)100(if\(BLEN\(bp\) == 0\) {)116 L (290)0(memmove\(nbp->wp, bp->rp, l\);)16(358)100(*bph = bp->next;)124 L (291)0(nbp->wp += l;)16(359)100(bp->next = nil;)124 L (292)0(count -= l;)16(360)100(freeb\(bp\);)124 L (293 })0(361)100(})116 L (294 if\(count > 0\){)0(362 })100 L (295)0(memset\(nbp->wp, 0, count\);)16(363 return bytes;)100 L (296)0(nbp->wp += count;)16(364 })100 L (297 })0(365)100 L (298 copyblockcnt++;)0(366 /*)100 L (299 QDEBUG checkb\(nbp, "copyblock 1"\);)0(367 * get next block from a queue, return null if nothing there)100 L (300)0(368 */)100 L (301 return nbp;)0(369 Block*)100 L (302 })0(370 qget\(Queue *q\))100 L (303)0(371 {)100 L (304 Block*)0(372 int dowakeup;)100 L (305 adjustblock\(Block* bp, int len\))0(373 Block *b;)100 L (306 {)0(374)100 L (307 int n;)0(375 /* sync with qwrite */)100 L (308 Block *nbp;)0(376 ilock\(q\);)100 L (309)0(377)100 L (310 if\(len < 0\){)0(378 b = q->bfirst;)100 L (311)0(freeb\(bp\);)16(379 if\(b == 0\){)100 L (312)0(return nil;)16(380)100(q->state |= Qstarve;)116 L (313 })0(381)100(iunlock\(q\);)116 L (314)0(382)100(return 0;)116 L (315 if\(bp->rp+len > bp->lim\){)0(383 })100 L (316)0(nbp = copyblock\(bp, len\);)16(384 q->bfirst = b->next;)100 L (317)0(freeblist\(bp\);)16(385 b->next = 0;)100 L (318)0(QDEBUG checkb\(nbp, "adjustblock 1"\);)16(386 q->len -= BALLOC\(b\);)100 L (319)0(387 q->dlen -= BLEN\(b\);)100 L (320)0(return nbp;)16(388 QDEBUG checkb\(b, "qget"\);)100 L (321 })0(389)100 L (322)0(390 /* if writer flow controlled, restart */)100 L (323 n = BLEN\(bp\);)0(391 if\(\(q->state & Qflow\) && q->len < q->limit/2\){)100 L (324 if\(len > n\))0(392)100(q->state &= ~Qflow;)116 L (325)0(memset\(bp->wp, 0, len-n\);)16(393)100(dowakeup = 1;)116 L (326 bp->wp = bp->rp+len;)0(394 } else)100 L (327 QDEBUG checkb\(bp, "adjustblock 2"\);)0(395)100(dowakeup = 0;)116 L (328)0(396)100 L (329 return bp;)0(397 iunlock\(q\);)100 L (330 })0(398)100 L (331)0(399 if\(dowakeup\))100 L (332)0(400)100(wakeup\(&q->wr\);)116 L (333 /*)0(401)100 L (334 * throw away up to count bytes from a)0(402 return b;)100 L (335 * list of blocks. Return count of bytes)0(403 })100 L (336 * thrown away.)0(404)100 L (337 */)0(405 /*)100 L (338 int)0(406 * throw away the next 'len' bytes in the queue)100 L (339 pullblock\(Block **bph, int count\))0(407 */)100 L (340 {)0(408 void)100 L cleartomark showpage saveobj restore %%EndPage: 190 190 %%Page: 191 191 /saveobj save def mark 191 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 4)l ()l ()l (409 qdiscard\(Queue *q, int len\))0(477)100(b->next = tofree;)116 L (410 {)0(478)100(tofree = b;)116 L (411 Block *b;)0(479 };)100 L (412 int dowakeup, n, sofar;)0(480)100 L (413)0(481 if\(n < len\))100 L (414 ilock\(q\);)0(482)100(len = n;)116 L (415 for\(sofar = 0; sofar < len; sofar += n\){)0(483 memmove\(p, b->rp, len\);)100 L (416)0(b = q->bfirst;)16(484 consumecnt += n;)100 L (417)0(if\(b == nil\))16(485 if\(\(q->state & Qmsg\) || len == n\))100 L (418)0(break;)24(486)100(q->bfirst = b->next;)116 L (419)0(QDEBUG checkb\(b, "qdiscard"\);)16(487 b->rp += len;)100 L (420)0(n = BLEN\(b\);)16(488 q->dlen -= len;)100 L (421)0(if\(n <= len - sofar\){)16(489)100 L (422)0(q->bfirst = b->next;)24(490 /* discard the block if we're done with it */)100 L (423)0(b->next = 0;)24(491 if\(\(q->state & Qmsg\) || len == n\){)100 L (424)0(q->len -= BALLOC\(b\);)24(492)100(b->next = 0;)116 L (425)0(q->dlen -= BLEN\(b\);)24(493)100(q->len -= BALLOC\(b\);)116 L (426)0(freeb\(b\);)24(494)100(q->dlen -= BLEN\(b\);)116 L (427)0(} else {)16(495)100 L (428)0(n = len - sofar;)24(496)100(/* remember to free this */)116 L (429)0(b->rp += n;)24(497)100(b->next = tofree;)116 L (430)0(q->dlen -= n;)24(498)100(tofree = b;)116 L (431)0(})16(499 })100 L (432 })0(500)100 L (433)0(501 /* if writer flow controlled, restart */)100 L (434 /* if writer flow controlled, restart */)0(502 if\(\(q->state & Qflow\) && q->len < q->limit/2\){)100 L (435 if\(\(q->state & Qflow\) && q->len < q->limit/2\){)0(503)100(q->state &= ~Qflow;)116 L (436)0(q->state &= ~Qflow;)16(504)100(dowakeup = 1;)116 L (437)0(dowakeup = 1;)16(505 } else)100 L (438 } else)0(506)100(dowakeup = 0;)116 L (439)0(dowakeup = 0;)16(507)100 L (440)0(508 iunlock\(q\);)100 L (441 iunlock\(q\);)0(509)100 L (442)0(510 if\(dowakeup\))100 L (443 if\(dowakeup\))0(511)100(wakeup\(&q->wr\);)116 L (444)0(wakeup\(&q->wr\);)16(512)100 L (445 })0(513 if\(tofree != nil\))100 L (446)0(514)100(freeblist\(tofree\);)116 L (447 /*)0(515)100 L (448 * Interrupt level copy out of a queue, return # bytes copied.)0(516 return len;)100 L (449 */)0(517 })100 L (450 int)0(518)100 L (451 qconsume\(Queue *q, void *vp, int len\))0(519 int)100 L (452 {)0(520 qpass\(Queue *q, Block *b\))100 L (453 Block *b;)0(521 {)100 L (454 int n, dowakeup;)0(522 int dlen, len, dowakeup;)100 L (455 uchar *p = vp;)0(523)100 L (456 Block *tofree = nil;)0(524 /* sync with qread */)100 L (457)0(525 dowakeup = 0;)100 L (458 /* sync with qwrite */)0(526 ilock\(q\);)100 L (459 ilock\(q\);)0(527 if\(q->len >= q->limit\){)100 L (460)0(528)100(freeblist\(b\);)116 L (461 for\(;;\) {)0(529)100(iunlock\(q\);)116 L (462)0(b = q->bfirst;)16(530)100(return -1;)116 L (463)0(if\(b == 0\){)16(531 })100 L (464)0(q->state |= Qstarve;)24(532)100 L (465)0(iunlock\(q\);)24(533 /* add buffer to queue */)100 L (466)0(return -1;)24(534 if\(q->bfirst\))100 L (467)0(})16(535)100(q->blast->next = b;)116 L (468)0(QDEBUG checkb\(b, "qconsume 1"\);)16(536 else)100 L (469)0(537)100(q->bfirst = b;)116 L (470)0(n = BLEN\(b\);)16(538 len = BALLOC\(b\);)100 L (471)0(if\(n > 0\))16(539 dlen = BLEN\(b\);)100 L (472)0(break;)24(540 QDEBUG checkb\(b, "qpass"\);)100 L (473)0(q->bfirst = b->next;)16(541 while\(b->next\){)100 L (474)0(q->len -= BALLOC\(b\);)16(542)100(b = b->next;)116 L (475)0(543)100(QDEBUG checkb\(b, "qpass"\);)116 L (476)0(/* remember to free this */)16(544)100(len += BALLOC\(b\);)116 L cleartomark showpage saveobj restore %%EndPage: 191 191 %%Page: 192 192 /saveobj save def mark 192 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 5)l ()l ()l (545)0(dlen += BLEN\(b\);)16(613 packblock\(Block *bp\))100 L (546 })0(614 {)100 L (547 q->blast = b;)0(615 Block **l, *nbp;)100 L (548 q->len += len;)0(616 int n;)100 L (549 q->dlen += dlen;)0(617)100 L (550)0(618 for\(l = &bp; *l; l = &\(*l\)->next\){)100 L (551 if\(q->len >= q->limit/2\))0(619)100(nbp = *l;)116 L (552)0(q->state |= Qflow;)16(620)100(n = BLEN\(nbp\);)116 L (553)0(621)100(if\(\(n<<2\) < BALLOC\(nbp\)\){)116 L (554 if\(q->state & Qstarve\){)0(622)100(*l = allocb\(n\);)124 L (555)0(q->state &= ~Qstarve;)16(623)100(memmove\(\(*l\)->wp, nbp->rp, n\);)124 L (556)0(dowakeup = 1;)16(624)100(\(*l\)->wp += n;)124 L (557 })0(625)100(\(*l\)->next = nbp->next;)124 L (558 iunlock\(q\);)0(626)100(freeb\(nbp\);)124 L (559)0(627)100(})116 L (560 if\(dowakeup\))0(628 })100 L (561)0(wakeup\(&q->rr\);)16(629)100 L (562)0(630 return bp;)100 L (563 return len;)0(631 })100 L (564 })0(632)100 L (565)0(633 int)100 L (566 int)0(634 qproduce\(Queue *q, void *vp, int len\))100 L (567 qpassnolim\(Queue *q, Block *b\))0(635 {)100 L (568 {)0(636 Block *b;)100 L (569 int dlen, len, dowakeup;)0(637 int dowakeup;)100 L (570)0(638 uchar *p = vp;)100 L (571 /* sync with qread */)0(639)100 L (572 dowakeup = 0;)0(640 /* sync with qread */)100 L (573 ilock\(q\);)0(641 dowakeup = 0;)100 L (574)0(642 ilock\(q\);)100 L (575 /* add buffer to queue */)0(643)100 L (576 if\(q->bfirst\))0(644 /* no waiting receivers, room in buffer? */)100 L (577)0(q->blast->next = b;)16(645 if\(q->len >= q->limit\){)100 L (578 else)0(646)100(q->state |= Qflow;)116 L (579)0(q->bfirst = b;)16(647)100(iunlock\(q\);)116 L (580 len = BALLOC\(b\);)0(648)100(return -1;)116 L (581 dlen = BLEN\(b\);)0(649 })100 L (582 QDEBUG checkb\(b, "qpass"\);)0(650)100 L (583 while\(b->next\){)0(651 /* save in buffer */)100 L (584)0(b = b->next;)16(652 b = iallocb\(len\);)100 L (585)0(QDEBUG checkb\(b, "qpass"\);)16(653 if\(b == 0\){)100 L (586)0(len += BALLOC\(b\);)16(654)100(iunlock\(q\);)116 L (587)0(dlen += BLEN\(b\);)16(655)100(return 0;)116 L (588 })0(656 })100 L (589 q->blast = b;)0(657 memmove\(b->wp, p, len\);)100 L (590 q->len += len;)0(658 producecnt += len;)100 L (591 q->dlen += dlen;)0(659 b->wp += len;)100 L (592)0(660 if\(q->bfirst\))100 L (593 if\(q->len >= q->limit/2\))0(661)100(q->blast->next = b;)116 L (594)0(q->state |= Qflow;)16(662 else)100 L (595)0(663)100(q->bfirst = b;)116 L (596 if\(q->state & Qstarve\){)0(664 q->blast = b;)100 L (597)0(q->state &= ~Qstarve;)16(665 /* b->next = 0; done by iallocb\(\) */)100 L (598)0(dowakeup = 1;)16(666 q->len += BALLOC\(b\);)100 L (599 })0(667 q->dlen += BLEN\(b\);)100 L (600 iunlock\(q\);)0(668 QDEBUG checkb\(b, "qproduce"\);)100 L (601)0(669)100 L (602 if\(dowakeup\))0(670 if\(q->state & Qstarve\){)100 L (603)0(wakeup\(&q->rr\);)16(671)100(q->state &= ~Qstarve;)116 L (604)0(672)100(dowakeup = 1;)116 L (605 return len;)0(673 })100 L (606 })0(674)100 L (607)0(675 if\(q->len >= q->limit\))100 L (608 /*)0(676)100(q->state |= Qflow;)116 L (609 * if the allocated space is way out of line with the used)0(677 iunlock\(q\);)100 L (610 * space, reallocate to a smaller block)0(678)100 L (611 */)0(679 if\(dowakeup\))100 L (612 Block*)0(680)100(wakeup\(&q->rr\);)116 L cleartomark showpage saveobj restore %%EndPage: 192 192 %%Page: 193 193 /saveobj save def mark 193 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 6)l ()l ()l (681)0(749 q->limit = q->inilim = limit;)100 L (682 return len;)0(750 q->kick = kick;)100 L (683 })0(751 q->arg = arg;)100 L (684)0(752 q->state = msg ? Qmsg : 0;)100 L (685 /*)0(753 q->state |= Qstarve;)100 L (686 * copy from offset in the queue)0(754 q->eof = 0;)100 L (687 */)0(755 q->noblock = 0;)100 L (688 Block*)0(756 iunlock\(q\);)100 L (689 qcopy\(Queue *q, int len, ulong offset\))0(757)100 L (690 {)0(758 return q;)100 L (691 int sofar;)0(759 })100 L (692 int n;)0(760)100 L (693 Block *b, *nb;)0(761 static int)100 L (694 uchar *p;)0(762 notempty\(void *a\))100 L (695)0(763 {)100 L (696 nb = allocb\(len\);)0(764 Queue *q = a;)100 L (697)0(765)100 L (698 ilock\(q\);)0(766 return \(q->state & Qclosed\) || q->bfirst != 0;)100 L (699)0(767 })100 L (700 /* go to offset */)0(768)100 L (701 b = q->bfirst;)0(769 /*)100 L (702 for\(sofar = 0; ; sofar += n\){)0(770 * get next block from a queue \(up to a limit\))100 L (703)0(if\(b == nil\){)16(771 */)100 L (704)0(iunlock\(q\);)24(772 Block*)100 L (705)0(return nb;)24(773 qbread\(Queue *q, int len\))100 L (706)0(})16(774 {)100 L (707)0(n = BLEN\(b\);)16(775 Block *b, *nb;)100 L (708)0(if\(sofar + n > offset\){)16(776 int n, dowakeup;)100 L (709)0(p = b->rp + offset - sofar;)24(777)100 L (710)0(n -= offset - sofar;)24(778 qlock\(&q->rlock\);)100 L (711)0(break;)24(779 if\(waserror\(\)\){)100 L (712)0(})16(780)100(qunlock\(&q->rlock\);)116 L (713)0(QDEBUG checkb\(b, "qcopy"\);)16(781)100(nexterror\(\);)116 L (714)0(b = b->next;)16(782 })100 L (715 })0(783)100 L (716)0(784 /* wait for data */)100 L (717 /* copy bytes from there */)0(785 for\(;;\){)100 L (718 for\(sofar = 0; sofar < len;\){)0(786)100(/* sync with qwrite/qproduce */)116 L (719)0(if\(n > len - sofar\))16(787)100(ilock\(q\);)116 L (720)0(n = len - sofar;)24(788)100 L (721)0(memmove\(nb->wp, p, n\);)16(789)100(b = q->bfirst;)116 L (722)0(qcopycnt += n;)16(790)100(if\(b\){)116 L (723)0(sofar += n;)16(791)100(QDEBUG checkb\(b, "qbread 0"\);)124 L (724)0(nb->wp += n;)16(792)100(break;)124 L (725)0(b = b->next;)16(793)100(})116 L (726)0(if\(b == nil\))16(794)100 L (727)0(break;)24(795)100(if\(q->state & Qclosed\){)116 L (728)0(n = BLEN\(b\);)16(796)100(iunlock\(q\);)124 L (729)0(p = b->rp;)16(797)100(poperror\(\);)124 L (730 })0(798)100(qunlock\(&q->rlock\);)124 L (731 iunlock\(q\);)0(799)100(if\(++q->eof > 3\))124 L (732)0(800)100(error\(q->err\);)132 L (733 return nb;)0(801)100(return 0;)124 L (734 })0(802)100(})116 L (735)0(803)100 L (736 /*)0(804)100(q->state |= Qstarve; /* flag requesting producer to wake me */)116 L (737 * called by non-interrupt code)0(805)100(iunlock\(q\);)116 L (738 */)0(806)100(sleep\(&q->rr, notempty, q\);)116 L (739 Queue*)0(807 })100 L (740 qopen\(int limit, int msg, void \(*kick\)\(void*\), void *arg\))0(808)100 L (741 {)0(809 /* remove a buffered block */)100 L (742 Queue *q;)0(810 q->bfirst = b->next;)100 L (743)0(811 b->next = 0;)100 L (744 q = malloc\(sizeof\(Queue\)\);)0(812 n = BLEN\(b\);)100 L (745 if\(q == 0\))0(813 q->dlen -= n;)100 L (746)0(return 0;)16(814 q->len -= BALLOC\(b\);)100 L (747)0(815 QDEBUG checkb\(b, "qbread 1"\);)100 L (748 ilock\(q\);)0(816)100 L cleartomark showpage saveobj restore %%EndPage: 193 193 %%Page: 194 194 /saveobj save def mark 194 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 7)l ()l ()l (817 /* split block if it's too big and this is not a message-oriented queue */)0(885 })100 L (818 nb = b;)0(886)100 L (819 if\(n > len\){)0(887 /*)100 L (820)0(if\(\(q->state&Qmsg\) == 0\){)16(888 * add a block to a queue obeying flow control)100 L (821)0(iunlock\(q\);)24(889 */)100 L (822)0(890 long)100 L (823)0(n -= len;)24(891 qbwrite\(Queue *q, Block *b\))100 L (824)0(b = allocb\(n\);)24(892 {)100 L (825)0(memmove\(b->wp, nb->rp+len, n\);)24(893 int n, dowakeup;)100 L (826)0(b->wp += n;)24(894)100 L (827)0(895 dowakeup = 0;)100 L (828)0(ilock\(q\);)24(896 n = BLEN\(b\);)100 L (829)0(b->next = q->bfirst;)24(897 qlock\(&q->wlock\);)100 L (830)0(if\(q->bfirst == 0\))24(898 if\(waserror\(\)\){)100 L (831)0(q->blast = b;)32(899)100(qunlock\(&q->wlock\);)116 L (832)0(q->bfirst = b;)24(900)100(nexterror\(\);)116 L (833)0(q->len += BALLOC\(b\);)24(901 })100 L (834)0(q->dlen += n;)24(902)100 L (835)0(})16(903 /* flow control */)100 L (836)0(nb->wp = nb->rp + len;)16(904 for\(;;\){)100 L (837 })0(905)100(ilock\(q\);)116 L (838)0(906)100 L (839 /* if writer flow controlled, restart */)0(907)100(if\(q->state & Qclosed\){)116 L (840 if\(\(q->state & Qflow\) && q->len < q->limit/2\){)0(908)100(iunlock\(q\);)124 L (841)0(q->state &= ~Qflow;)16(909)100(freeb\(b\);)124 L (842)0(dowakeup = 1;)16(910)100(error\(q->err\);)124 L (843 } else)0(911)100(})116 L (844)0(dowakeup = 0;)16(912)100 L (845)0(913)100(if\(q->len < q->limit\))116 L (846 iunlock\(q\);)0(914)100(break;)124 L (847)0(915)100 L (848 /* wakeup flow controlled writers */)0(916)100(if\(q->noblock\){)116 L (849 if\(dowakeup\){)0(917)100(iunlock\(q\);)124 L (850)0(if\(q->kick\))16(918)100(freeb\(b\);)124 L (851)0(q->kick\(q->arg\);)24(919)100(qunlock\(&q->wlock\);)124 L (852)0(wakeup\(&q->wr\);)16(920)100(poperror\(\);)124 L (853 })0(921)100(return n;)124 L (854)0(922)100(})116 L (855 poperror\(\);)0(923)100 L (856 qunlock\(&q->rlock\);)0(924)100(q->state |= Qflow;)116 L (857 return nb;)0(925)100(iunlock\(q\);)116 L (858 })0(926)100(sleep\(&q->wr, qnotfull, q\);)116 L (859)0(927 })100 L (860 /*)0(928)100 L (861 * read a queue. if no data is queued, post a Block)0(929 if\(q->bfirst\))100 L (862 * and wait on its Rendez.)0(930)100(q->blast->next = b;)116 L (863 */)0(931 else)100 L (864 long)0(932)100(q->bfirst = b;)116 L (865 qread\(Queue *q, void *vp, int len\))0(933 q->blast = b;)100 L (866 {)0(934 b->next = 0;)100 L (867 Block *b;)0(935 q->len += BALLOC\(b\);)100 L (868)0(936 q->dlen += n;)100 L (869 b = qbread\(q, len\);)0(937 QDEBUG checkb\(b, "qbwrite"\);)100 L (870 if\(b == 0\))0(938)100 L (871)0(return 0;)16(939 if\(q->state & Qstarve\){)100 L (872)0(940)100(q->state &= ~Qstarve;)116 L (873 len = BLEN\(b\);)0(941)100(dowakeup = 1;)116 L (874 memmove\(vp, b->rp, len\);)0(942 })100 L (875 freeb\(b\);)0(943)100 L (876 return len;)0(944 iunlock\(q\);)100 L (877 })0(945)100 L (878)0(946 if\(dowakeup\){)100 L (879 static int)0(947)100(if\(q->kick\))116 L (880 qnotfull\(void *a\))0(948)100(q->kick\(q->arg\);)124 L (881 {)0(949)100(wakeup\(&q->rr\);)116 L (882 Queue *q = a;)0(950 })100 L (883)0(951)100 L (884 return q->len < q->limit || \(q->state & Qclosed\);)0(952 qunlock\(&q->wlock\);)100 L cleartomark showpage saveobj restore %%EndPage: 194 194 %%Page: 195 195 /saveobj save def mark 195 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 8)l ()l ()l (953 poperror\(\);)0(1021)100(q->blast->next = b;)124 L (954 return n;)0(1022)100(else)116 L (955 })0(1023)100(q->bfirst = b;)124 L (956)0(1024)100(q->blast = b;)116 L (957 /*)0(1025)100(q->len += BALLOC\(b\);)116 L (958 * write to a queue. only Maxatomic bytes at a time is atomic.)0(1026)100(q->dlen += n;)116 L (959 */)0(1027)100 L (960 int)0(1028)100(if\(q->state & Qstarve\){)116 L (961 qwrite\(Queue *q, void *vp, int len\))0(1029)100(q->state &= ~Qstarve;)124 L (962 {)0(1030)100(dowakeup = 1;)124 L (963 int n, sofar;)0(1031)100(})116 L (964 Block *b;)0(1032)100 L (965 uchar *p = vp;)0(1033)100(iunlock\(q\);)116 L (966)0(1034)100 L (967 QDEBUG if\(islo\(\) == 0\))0(1035)100(if\(dowakeup\){)116 L (968)0(print\("qwrite hi %lux\\n", getcallerpc\(&q\)\);)16(1036)100(if\(q->kick\))124 L (969)0(1037)100(q->kick\(q->arg\);)132 L (970 sofar = 0;)0(1038)100(wakeup\(&q->rr\);)124 L (971 do {)0(1039)100(})116 L (972)0(n = len-sofar;)16(1040)100 L (973)0(if\(n > Maxatomic\))16(1041)100(sofar += n;)116 L (974)0(n = Maxatomic;)24(1042 } while\(sofar < len && \(q->state & Qmsg\) == 0\);)100 L (975)0(1043)100 L (976)0(b = allocb\(n\);)16(1044 return len;)100 L (977)0(setmalloctag\(b, \(up->text[0]<<24\)|\(up->text[1]<<16\)|\(up->text[2]<<8\)|up->text[3]\); 1045 })16 L (978)0(if\(waserror\(\)\){)16(1046)100 L (979)0(freeb\(b\);)24(1047 /*)100 L (980)0(nexterror\(\);)24(1048 * be extremely careful when calling this,)100 L (981)0(})16(1049 * as there is no reference accounting)100 L (982)0(memmove\(b->wp, p+sofar, n\);)16(1050 */)100 L (983)0(poperror\(\);)16(1051 void)100 L (984)0(b->wp += n;)16(1052 qfree\(Queue *q\))100 L (985)0(1053 {)100 L (986)0(qbwrite\(q, b\);)16(1054 qclose\(q\);)100 L (987)0(1055 free\(q\);)100 L (988)0(sofar += n;)16(1056 })100 L (989 } while\(sofar < len && \(q->state & Qmsg\) == 0\);)0(1057)100 L (990)0(1058 /*)100 L (991 return len;)0(1059 * Mark a queue as closed. No further IO is permitted.)100 L (992 })0(1060 * All blocks are released.)100 L (993)0(1061 */)100 L (994 /*)0(1062 void)100 L (995 * used by print\(\) to write to a queue. Since we may be splhi or not in)0(1063 qclose\(Queue *q\))100 L (996 * a process, don't qlock.)0(1064 {)100 L (997 */)0(1065 Block *bfirst;)100 L (998 int)0(1066)100 L (999 qiwrite\(Queue *q, void *vp, int len\))0(1067 if\(q == nil\))100 L (1000 {)0(1068)100(return;)116 L (1001 int n, sofar, dowakeup;)0(1069)100 L (1002 Block *b;)0(1070 /* mark it */)100 L (1003 uchar *p = vp;)0(1071 ilock\(q\);)100 L (1004)0(1072 q->state |= Qclosed;)100 L (1005 dowakeup = 0;)0(1073 q->state &= ~\(Qflow|Qstarve\);)100 L (1006)0(1074 strcpy\(q->err, Ehungup\);)100 L (1007 sofar = 0;)0(1075 bfirst = q->bfirst;)100 L (1008 do {)0(1076 q->bfirst = 0;)100 L (1009)0(n = len-sofar;)16(1077 q->len = 0;)100 L (1010)0(if\(n > Maxatomic\))16(1078 q->dlen = 0;)100 L (1011)0(n = Maxatomic;)24(1079 q->noblock = 0;)100 L (1012)0(1080 iunlock\(q\);)100 L (1013)0(b = allocb\(n\);)16(1081)100 L (1014)0(memmove\(b->wp, p+sofar, n\);)16(1082 /* free queued blocks */)100 L (1015)0(b->wp += n;)16(1083 freeblist\(bfirst\);)100 L (1016)0(1084)100 L (1017)0(ilock\(q\);)16(1085 /* wake up readers/writers */)100 L (1018)0(1086 wakeup\(&q->rr\);)100 L (1019)0(QDEBUG checkb\(b, "qiwrite"\);)16(1087 wakeup\(&q->wr\);)100 L (1020)0(if\(q->bfirst\))16(1088 })100 L cleartomark showpage saveobj restore %%EndPage: 195 195 %%Page: 196 196 /saveobj save def mark 196 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qio.c Page 9)l ()l ()l (1089)0(1157 /*)100 L (1090 /*)0(1158 * return true if we can read without blocking)100 L (1091 * Mark a queue as closed. Wakeup any readers. Don't remove queued)0(1159 */)100 L (1092 * blocks.)0(1160 int)100 L (1093 */)0(1161 qcanread\(Queue *q\))100 L (1094 void)0(1162 {)100 L (1095 qhangup\(Queue *q, char *msg\))0(1163 return q->bfirst!=0;)100 L (1096 {)0(1164 })100 L (1097 /* mark it */)0(1165)100 L (1098 ilock\(q\);)0(1166 /*)100 L (1099 q->state |= Qclosed;)0(1167 * change queue limit)100 L (1100 if\(msg == 0 || *msg == 0\))0(1168 */)100 L (1101)0(strcpy\(q->err, Ehungup\);)16(1169 void)100 L (1102 else)0(1170 qsetlimit\(Queue *q, int limit\))100 L (1103)0(strncpy\(q->err, msg, ERRLEN-1\);)16(1171 {)100 L (1104 iunlock\(q\);)0(1172 q->limit = limit;)100 L (1105)0(1173 })100 L (1106 /* wake up readers/writers */)0(1174)100 L (1107 wakeup\(&q->rr\);)0(1175 /*)100 L (1108 wakeup\(&q->wr\);)0(1176 * set blocking/nonblocking)100 L (1109 })0(1177 */)100 L (1110)0(1178 void)100 L (1111 /*)0(1179 qnoblock\(Queue *q, int onoff\))100 L (1112 * return non-zero if the q is hungup)0(1180 {)100 L (1113 */)0(1181 q->noblock = onoff;)100 L (1114 int)0(1182 })100 L (1115 qisclosed\(Queue *q\))0(1183)100 L (1116 {)0(1184 /*)100 L (1117 return q->state & Qclosed;)0(1185 * flush the output queue)100 L (1118 })0(1186 */)100 L (1119)0(1187 void)100 L (1120 /*)0(1188 qflush\(Queue *q\))100 L (1121 * mark a queue as no longer hung up)0(1189 {)100 L (1122 */)0(1190 Block *bfirst;)100 L (1123 void)0(1191)100 L (1124 qreopen\(Queue *q\))0(1192 /* mark it */)100 L (1125 {)0(1193 ilock\(q\);)100 L (1126 ilock\(q\);)0(1194 bfirst = q->bfirst;)100 L (1127 q->state &= ~Qclosed;)0(1195 q->bfirst = 0;)100 L (1128 q->state |= Qstarve;)0(1196 q->len = 0;)100 L (1129 q->eof = 0;)0(1197 q->dlen = 0;)100 L (1130 q->limit = q->inilim;)0(1198 iunlock\(q\);)100 L (1131 iunlock\(q\);)0(1199)100 L (1132 })0(1200 /* free queued blocks */)100 L (1133)0(1201 freeblist\(bfirst\);)100 L (1134 /*)0(1202)100 L (1135 * return bytes queued)0(1203 /* wake up readers/writers */)100 L (1136 */)0(1204 wakeup\(&q->wr\);)100 L (1137 int)0(1205 })100 L (1138 qlen\(Queue *q\))0(1206)100 L (1139 {)0(1207 int)100 L (1140 return q->dlen;)0(1208 qfull\(Queue *q\))100 L (1141 })0(1209 {)100 L (1142)0(1210 return q->state & Qflow;)100 L (1143 /*)0(1211 })100 L (1144 * return space remaining before flow control)0(1212)100 L (1145 */)0(1213 int)100 L (1146 int)0(1214 qstate\(Queue *q\))100 L (1147 qwindow\(Queue *q\))0(1215 {)100 L (1148 {)0(1216 return q->state;)100 L (1149 int l;)0(1217 })100 L (1150)l (1151 l = q->limit - q->len;)l (1152 if\(l < 0\))l (1153)0(l = 0;)16 L (1154 return l;)l (1155 })l (1156)l cleartomark showpage saveobj restore %%EndPage: 196 196 %%Page: 197 197 /saveobj save def mark 197 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qlock.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(q->tail = 0;)124 L (2 #include "../port/lib.h")0(70)100(unlock\(&q->use\);)116 L (3 #include "mem.h")0(71)100(ready\(p\);)116 L (4 #include "dat.h")0(72)100(return;)116 L (5 #include "fns.h")0(73)100(})108 L (6)0(74)100(q->locked = 0;)108 L (7 struct {)0(75)100(unlock\(&q->use\);)108 L (8)0(ulong rlock;)8(76 })100 L (9)0(ulong rlockq;)8(77)100 L (10)0(ulong wlock;)8(78 void)100 L (11)0(ulong wlockq;)8(79 rlock\(RWlock *q\))100 L (12)0(ulong qlock;)8(80 {)100 L (13)0(ulong qlockq;)8(81)100(Proc *p, *mp;)108 L (14 } rwstats;)0(82)100 L (15)0(83)100(lock\(&q->use\);)108 L (16 void)0(84 rwstats.rlock++;)100 L (17 qlock\(QLock *q\))0(85)100(if\(q->writer == 0 && q->head == nil\){)108 L (18 {)0(86)100(/* no writer, go for it */)116 L (19)0(Proc *p, *mp;)8(87)100(q->readers++;)116 L (20)0(88)100(unlock\(&q->use\);)116 L (21)0(lock\(&q->use\);)8(89)100(return;)116 L (22 rwstats.qlock++;)0(90)100(})108 L (23)0(if\(!q->locked\) {)8(91)100 L (24)0(q->locked = 1;)16(92 rwstats.rlockq++;)100 L (25)0(unlock\(&q->use\);)16(93)100(p = q->tail;)108 L (26)0(return;)16(94)100(mp = up;)108 L (27)0(})8(95)100(if\(mp == nil\))108 L (28 rwstats.qlockq++;)0(96)100(panic\("rlock"\);)116 L (29)0(p = q->tail;)8(97)100(if\(p == 0\))108 L (30)0(mp = up;)8(98)100(q->head = mp;)116 L (31)0(if\(mp == nil\))8(99)100(else)108 L (32)0(panic\("qlock"\);)16(100)100(p->qnext = mp;)116 L (33)0(if\(p == 0\))8(101 q->tail = mp;)100 L (34)0(q->head = mp;)16(102 mp->qnext = 0;)100 L (35)0(else)8(103 mp->state = QueueingR;)100 L (36)0(p->qnext = mp;)16(104 unlock\(&q->use\);)100 L (37)0(q->tail = mp;)8(105 sched\(\);)100 L (38)0(mp->qnext = 0;)8(106 })100 L (39)0(mp->state = Queueing;)8(107)100 L (40)0(up->qpc = getcallerpc\(&q\);)8(108 void)100 L (41)0(unlock\(&q->use\);)8(109 runlock\(RWlock *q\))100 L (42)0(sched\(\);)8(110 {)100 L (43 })0(111 Proc *p;)100 L (44)0(112)100 L (45 int)0(113 lock\(&q->use\);)100 L (46 canqlock\(QLock *q\))0(114 p = q->head;)100 L (47 {)0(115 if\(--\(q->readers\) > 0 || p == nil\){)100 L (48)0(if\(!canlock\(&q->use\)\))8(116)100(unlock\(&q->use\);)116 L (49)0(return 0;)16(117)100(return;)116 L (50)0(if\(q->locked\){)8(118 })100 L (51)0(unlock\(&q->use\);)16(119)100 L (52)0(return 0;)16(120 /* start waiting writer */)100 L (53)0(})8(121 if\(p->state != QueueingW\))100 L (54)0(q->locked = 1;)8(122)100(panic\("runlock"\);)116 L (55)0(unlock\(&q->use\);)8(123 q->head = p->qnext;)100 L (56)0(return 1;)8(124 if\(q->head == 0\))100 L (57 })0(125)100(q->tail = 0;)116 L (58)0(126 q->writer = 1;)100 L (59 void)0(127 unlock\(&q->use\);)100 L (60 qunlock\(QLock *q\))0(128 ready\(p\);)100 L (61 {)0(129 })100 L (62)0(Proc *p;)8(130)100 L (63)0(131 void)100 L (64)0(lock\(&q->use\);)8(132 wlock\(RWlock *q\))100 L (65)0(p = q->head;)8(133 {)100 L (66)0(if\(p\) {)8(134 Proc *p, *mp;)100 L (67)0(q->head = p->qnext;)16(135)100 L (68)0(if\(q->head == 0\))16(136 lock\(&q->use\);)100 L cleartomark showpage saveobj restore %%EndPage: 197 197 %%Page: 198 198 /saveobj save def mark 198 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/qlock.c Page 2)l ()l ()l (137 rwstats.wlock++;)0(205 {)100 L (138 if\(q->readers == 0 && q->writer == 0\){)0(206 lock\(&q->use\);)100 L (139)0(/* noone waiting, go for it */)16(207 rwstats.rlock++;)100 L (140)0(q->wpc = getcallerpc\(&q\);)16(208 if\(q->writer == 0 && q->head == nil\){)100 L (141)0(q->wproc = up;)16(209)100(/* no writer, go for it */)116 L (142)0(q->writer = 1;)16(210)100(q->readers++;)116 L (143)0(unlock\(&q->use\);)16(211)100(unlock\(&q->use\);)116 L (144)0(return;)16(212)100(return 1;)116 L (145 })0(213 })100 L (146)0(214 unlock\(&q->use\);)100 L (147 /* wait */)0(215 return 0;)100 L (148 rwstats.wlockq++;)0(216 })100 L (149 p = q->tail;)l (150 mp = up;)l (151 if\(mp == nil\))l (152)0(panic\("wlock"\);)16 L (153 if\(p == nil\))l (154)0(q->head = mp;)16 L (155 else)l (156)0(p->qnext = mp;)16 L (157 q->tail = mp;)l (158 mp->qnext = 0;)l (159 mp->state = QueueingW;)l (160 unlock\(&q->use\);)l (161 sched\(\);)l (162 })l (163)l (164 void)l (165 wunlock\(RWlock *q\))l (166 {)l (167 Proc *p;)l (168)l (169 lock\(&q->use\);)l (170 p = q->head;)l (171 if\(p == nil\){)l (172)0(q->writer = 0;)16 L (173)0(unlock\(&q->use\);)16 L (174)0(return;)16 L (175 })l (176 if\(p->state == QueueingW\){)l (177)0(/* start waiting writer */)16 L (178)0(q->head = p->qnext;)16 L (179)0(if\(q->head == nil\))16 L (180)0(q->tail = nil;)24 L (181)0(unlock\(&q->use\);)16 L (182)0(ready\(p\);)16 L (183)0(return;)16 L (184 })l (185)l (186 if\(p->state != QueueingR\))l (187)0(panic\("wunlock"\);)16 L (188)l (189 /* waken waiting readers */)l (190 while\(q->head != nil && q->head->state == QueueingR\){)l (191)0(p = q->head;)16 L (192)0(q->head = p->qnext;)16 L (193)0(q->readers++;)16 L (194)0(ready\(p\);)16 L (195 })l (196 if\(q->head == nil\))l (197)0(q->tail = nil;)16 L (198 q->writer = 0;)l (199 unlock\(&q->use\);)l (200 })l (201)l (202 /* same as rlock but punts if there are any readers waiting */)l (203 int)l (204 canrlock\(RWlock *q\))l cleartomark showpage saveobj restore %%EndPage: 198 198 %%Page: 199 199 /saveobj save def mark 199 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(if\(mapsize > \(SEGMAPSIZE*PTEPERTAB\)\))116 L (2 #include "../port/lib.h")0(70)100(mapsize = \(SEGMAPSIZE*PTEPERTAB\);)124 L (3 #include "mem.h")0(71)100(s->map = smalloc\(mapsize*sizeof\(Pte*\)\);)116 L (4 #include "dat.h")0(72)100(s->mapsize = mapsize;)116 L (5 #include "fns.h")0(73)100(})108 L (6 #include "../port/error.h")0(74)100(else{)108 L (7)0(75)100(s->map = s->ssegmap;)116 L (8 static void)0(imagereclaim\(void\);)24(76)100(s->mapsize = nelem\(s->ssegmap\);)116 L (9 static void)0(imagechanreclaim\(void\);)24(77)100(})108 L (10)0(78)100 L (11 /* System specific segattach devices */)0(79)100(return s;)108 L (12 #include "io.h")0(80 })100 L (13 #include "segment.h")0(81)100 L (14)0(82 void)100 L (15 static Lock physseglock;)0(83 putseg\(Segment *s\))100 L (16)0(84 {)100 L (17 #define NFREECHAN 64)0(85)100(Pte **pp, **emap;)108 L (18 #define IHASHSIZE 64)0(86)100(Image *i;)108 L (19 #define ihash\(s\) imagealloc.hash[s%IHASHSIZE])0(87)100 L (20 static struct)0(88)100(if\(s == 0\))108 L (21 {)0(89)100(return;)116 L (22)0(Lock;)8(90)100 L (23)0(Image *free;)8(91)100(i = s->image;)108 L (24)0(Image *hash[IHASHSIZE];)8(92)100(if\(i != 0\) {)108 L (25)0(QLock ireclaim;)8(/* mutex on reclaiming free images */)32(93)100(lock\(i\);)116 L (26)0(94)100(lock\(s\);)116 L (27)0(Chan **freechan; /* free image channels */)8(95)100(if\(i->s == s && s->ref == 1\))116 L (28)0(int nfreechan;)8(/* number of free channels */)32(96)100(i->s = 0;)124 L (29)0(int szfreechan; /* size of freechan array */)8(97)100(unlock\(i\);)116 L (30)0(QLock fcreclaim;)8(/* mutex on reclaiming free channels */)32(98)100(})108 L (31 }imagealloc;)0(99)100(else)108 L (32)0(100)100(lock\(s\);)116 L (33 void)0(101)100 L (34 initseg\(void\))0(102 s->ref--;)100 L (35 {)0(103 if\(s->ref != 0\) {)100 L (36)0(Image *i, *ie;)8(104)100(unlock\(s\);)116 L (37)0(105)100(return;)116 L (38)0(imagealloc.free = xalloc\(conf.nimage*sizeof\(Image\)\);)8(106 })100 L (39)0(ie = &imagealloc.free[conf.nimage-1];)8(107)100 L (40)0(for\(i = imagealloc.free; i < ie; i++\))8(108 qlock\(&s->lk\);)100 L (41)0(i->next = i+1;)16(109 if\(i\))100 L (42)0(i->next = 0;)8(110)100(putimage\(i\);)116 L (43)0(imagealloc.freechan = malloc\(NFREECHAN * sizeof\(Chan*\)\);)8(111)100 L (44)0(imagealloc.szfreechan = NFREECHAN;)8(112 emap = &s->map[s->mapsize];)100 L (45 })0(113 for\(pp = s->map; pp < emap; pp++\))100 L (46)0(114)100(if\(*pp\))116 L (47 Segment *)0(115)100(freepte\(s, *pp\);)124 L (48 newseg\(int type, ulong base, ulong size\))0(116)100 L (49 {)0(117 qunlock\(&s->lk\);)100 L (50)0(Segment *s;)8(118 if\(s->map != s->ssegmap\))100 L (51)0(int mapsize;)8(119)100(free\(s->map\);)116 L (52)0(120 if\(s->profile != 0\))100 L (53)0(if\(size > \(SEGMAPSIZE*PTEPERTAB\)\))8(121)100(free\(s->profile\);)116 L (54)0(error\(Enovmem\);)16(122 free\(s\);)100 L (55)0(123 })100 L (56)0(if\(swapfull\(\)\))8(124)100 L (57)0(error\(Enoswap\);)16(125 void)100 L (58)0(126 relocateseg\(Segment *s, ulong offset\))100 L (59)0(s = smalloc\(sizeof\(Segment\)\);)8(127 {)100 L (60)0(s->ref = 1;)8(128 Page **pg, *x;)100 L (61)0(s->type = type;)8(129 Pte *pte, **p, **endpte;)100 L (62)0(s->base = base;)8(130)100 L (63)0(s->top = base+\(size*BY2PG\);)8(131 endpte = &s->map[s->mapsize];)100 L (64)0(s->size = size;)8(132 for\(p = s->map; p < endpte; p++\) {)100 L (65)0(133)100(if\(*p == 0\))116 L (66)0(mapsize = ROUND\(size, PTEPERTAB\)/PTEPERTAB;)8(134)100(continue;)124 L (67)0(if\(mapsize > nelem\(s->ssegmap\)\){)8(135)100(pte = *p;)116 L (68)0(mapsize *= 2;)16(136)100(for\(pg = pte->first; pg <= pte->last; pg++\) {)116 L cleartomark showpage saveobj restore %%EndPage: 199 199 %%Page: 200 200 /saveobj save def mark 200 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 2)l ()l ()l (137)0(if\(x = *pg\))24(205)100 L (138)0(x->va += offset;)32(206)100(incref\(s->image\);)116 L (139)0(})16(207)100(n->image = s->image;)116 L (140 })0(208)100(n->fstart = s->fstart;)116 L (141 })0(209)100(n->flen = s->flen;)116 L (142)0(210)100(break;)116 L (143 Segment*)0(211 })100 L (144 dupseg\(Segment **seg, int segno, int share\))0(212 size = s->mapsize;)100 L (145 {)0(213 for\(i = 0; i < size; i++\))100 L (146 int i, size;)0(214)100(if\(pte = s->map[i]\))116 L (147 Pte *pte;)0(215)100(n->map[i] = ptecpy\(pte\);)124 L (148 Segment *n, *s;)0(216)100 L (149)0(217 n->flushme = s->flushme;)100 L (150 SET\(n\);)0(218 qunlock\(&s->lk\);)100 L (151 s = seg[segno];)0(219 return n;)100 L (152)0(220 })100 L (153 switch\(s->type&SG_TYPE\) {)0(221)100 L (154 case SG_TEXT:)0(/* New segment shares pte set */)32(222 void)100 L (155 case SG_SHARED:)0(223 segpage\(Segment *s, Page *p\))100 L (156 case SG_PHYSICAL:)0(224 {)100 L (157 case SG_SHDATA:)0(225 Pte **pte;)100 L (158)0(incref\(s\);)16(226 ulong off;)100 L (159)0(return s;)16(227 Page **pg;)100 L (160)0(228)100 L (161 case SG_STACK:)0(229 if\(p->va < s->base || p->va >= s->top\))100 L (162)0(qlock\(&s->lk\);)16(230)100(panic\("segpage"\);)116 L (163)0(if\(waserror\(\)\){)16(231)100 L (164)0(qunlock\(&s->lk\);)24(232 off = p->va - s->base;)100 L (165)0(nexterror\(\);)24(233 pte = &s->map[off/PTEMAPMEM];)100 L (166)0(})16(234 if\(*pte == 0\))100 L (167)0(n = newseg\(s->type, s->base, s->size\);)16(235)100(*pte = ptealloc\(\);)116 L (168)0(poperror\(\);)16(236)100 L (169)0(break;)16(237 pg = &\(*pte\)->pages[\(off&\(PTEMAPMEM-1\)\)/BY2PG];)100 L (170)0(238 *pg = p;)100 L (171 case SG_BSS:)0(/* Just copy on write */)32(239 if\(pg < \(*pte\)->first\))100 L (172 case SG_MAP:)0(240)100(\(*pte\)->first = pg;)116 L (173)0(qlock\(&s->lk\);)16(241 if\(pg > \(*pte\)->last\))100 L (174)0(if\(share && s->ref == 1\) {)16(242)100(\(*pte\)->last = pg;)116 L (175)0(s->type = \(s->type&~SG_TYPE\)|SG_SHARED;)24(243 })100 L (176)0(incref\(s\);)24(244)100 L (177)0(qunlock\(&s->lk\);)24(245 Image*)100 L (178)0(return s;)24(246 attachimage\(int type, Chan *c, ulong base, ulong len\))100 L (179)0(})16(247 {)100 L (180)0(if\(waserror\(\)\){)16(248 Image *i, **l;)100 L (181)0(qunlock\(&s->lk\);)24(249)100 L (182)0(nexterror\(\);)24(250 /* reclaim any free channels from reclaimed segments */)100 L (183)0(})16(251 if\(imagealloc.nfreechan\))100 L (184)0(n = newseg\(s->type, s->base, s->size\);)16(252)100(imagechanreclaim\(\);)116 L (185)0(poperror\(\);)16(253)100 L (186)0(break;)16(254 lock\(&imagealloc\);)100 L (187)0(255)100 L (188 case SG_DATA:)0(/* Copy on write plus demand load info */)32(256 /*)100 L (189)0(if\(segno == TSEG\))16(257)100(* Search the image cache for remains of the text from a previous)109 L (190)0(return data2txt\(s\);)24(258)100(* or currently running incarnation)109 L (191)0(259)100(*/)109 L (192)0(qlock\(&s->lk\);)16(260 for\(i = ihash\(c->qid.path\); i; i = i->hash\) {)100 L (193)0(if\(share && s->ref == 1\) {)16(261)100(if\(c->qid.path == i->qid.path\) {)116 L (194)0(s->type = \(s->type&~SG_TYPE\)|SG_SHDATA;)24(262)100(lock\(i\);)124 L (195)0(incref\(s\);)24(263)100(if\(eqqid\(c->qid, i->qid\) &&)124 L (196)0(qunlock\(&s->lk\);)24(264)100(eqqid\(c->mqid, i->mqid\) &&)127 L (197)0(return s;)24(265)100(c->mchan == i->mchan &&)127 L (198)0(})16(266)100(c->type == i->type\) {)127 L (199)0(if\(waserror\(\)\){)16(267)100(i->ref++;)132 L (200)0(qunlock\(&s->lk\);)24(268)100(goto found;)132 L (201)0(nexterror\(\);)24(269)100(})124 L (202)0(})16(270)100(unlock\(i\);)124 L (203)0(n = newseg\(s->type, s->base, s->size\);)16(271)100(})116 L (204)0(poperror\(\);)16(272 })100 L cleartomark showpage saveobj restore %%EndPage: 200 200 %%Page: 201 201 /saveobj save def mark 201 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 3)l ()l ()l (273)0(341)100(unlock\(p\);)124 L (274 /*)0(342)100(})116 L (275)0(* imagereclaim dumps pages from the free list which are cached by image)9(343 })100 L (276)0(* structures. This should free some image structures.)9(344 ticks = fastticks\(nil\) - ticks;)100 L (277)0(*/)9(345 unlock\(&palloc\);)100 L (278 while\(!\(i = imagealloc.free\)\) {)0(346 irstats.loops++;)100 L (279)0(unlock\(&imagealloc\);)16(347 irstats.ticks += ticks;)100 L (280)0(imagereclaim\(\);)16(348 if\(ticks > irstats.maxt\))100 L (281)0(sched\(\);)16(349)100(irstats.maxt = ticks;)116 L (282)0(lock\(&imagealloc\);)16(350 //print\("T%llud+", ticks\);)100 L (283 })0(351 qunlock\(&imagealloc.ireclaim\);)100 L (284)0(352 })100 L (285 imagealloc.free = i->next;)0(353)100 L (286)0(354 /*)100 L (287 lock\(i\);)0(355 * since close can block, this has to be called outside of)100 L (288 incref\(c\);)0(356 * spin locks.)100 L (289 i->c = c;)0(357 */)100 L (290 i->type = c->type;)0(358 static void)100 L (291 i->qid = c->qid;)0(359 imagechanreclaim\(void\))100 L (292 i->mqid = c->mqid;)0(360 {)100 L (293 i->mchan = c->mchan;)0(361 Chan *c;)100 L (294 i->ref = 1;)0(362)100 L (295 l = &ihash\(c->qid.path\);)0(363 /* Somebody is already cleaning the image chans */)100 L (296 i->hash = *l;)0(364 if\(!canqlock\(&imagealloc.fcreclaim\)\))100 L (297 *l = i;)0(365)100(return;)116 L (298 found:)0(366)100 L (299 unlock\(&imagealloc\);)0(367 /*)100 L (300)0(368)100(* We don't have to recheck that nfreechan > 0 after we)109 L (301 if\(i->s == 0\) {)0(369)100(* acquire the lock, because we're the only ones who decrement)109 L (302)0(/* Disaster after commit in exec */)16(370)100(* it \(the other lock contender increments it\), and there's only)109 L (303)0(if\(waserror\(\)\) {)16(371)100(* one of us thanks to the qlock above.)109 L (304)0(unlock\(i\);)24(372)100(*/)109 L (305)0(pexit\(Enovmem, 1\);)24(373 while\(imagealloc.nfreechan > 0\){)100 L (306)0(})16(374)100(lock\(&imagealloc\);)116 L (307)0(i->s = newseg\(type, base, len\);)16(375)100(imagealloc.nfreechan--;)116 L (308)0(i->s->image = i;)16(376)100(c = imagealloc.freechan[imagealloc.nfreechan];)116 L (309)0(poperror\(\);)16(377)100(unlock\(&imagealloc\);)116 L (310 })0(378)100(cclose\(c\);)116 L (311 else)0(379 })100 L (312)0(incref\(i->s\);)16(380)100 L (313)0(381 qunlock\(&imagealloc.fcreclaim\);)100 L (314 return i;)0(382 })100 L (315 })0(383)100 L (316)0(384 void)100 L (317 static struct {)0(385 putimage\(Image *i\))100 L (318 int calls;)0(/* times imagereclaim was called */)40(386 {)100 L (319 int loops;)0(/* times the main loop was run */)40(387 Chan *c, **cp;)100 L (320 uvlong ticks;)0(/* total time in the main loop */)40(388 Image *f, **l;)100 L (321 uvlong maxt;)0(/* longest time in main loop */)40(389)100 L (322 } irstats;)0(390 if\(i->notext\))100 L (323)0(391)100(return;)116 L (324 static void)0(392)100 L (325 imagereclaim\(void\))0(393 lock\(i\);)100 L (326 {)0(394 if\(--i->ref == 0\) {)100 L (327 Page *p;)0(395)100(l = &ihash\(i->qid.path\);)116 L (328 uvlong ticks;)0(396)100(i->qid = \(Qid\){~0, ~0};)116 L (329)0(397)100(unlock\(i\);)116 L (330 irstats.calls++;)0(398)100(c = i->c;)116 L (331 /* Somebody is already cleaning the page cache */)0(399)100 L (332 if\(!canqlock\(&imagealloc.ireclaim\)\))0(400)100(lock\(&imagealloc\);)116 L (333)0(return;)16(401)100(for\(f = *l; f; f = f->hash\) {)116 L (334)0(402)100(if\(f == i\) {)124 L (335 lock\(&palloc\);)0(403)100(*l = i->hash;)132 L (336 ticks = fastticks\(nil\);)0(404)100(break;)132 L (337 for\(p = palloc.head; p; p = p->next\) {)0(405)100(})124 L (338)0(if\(p->ref == 0 && p->image && canlock\(p\)\) {)16(406)100(l = &f->hash;)124 L (339)0(if\(p->ref == 0\))24(407)100(})116 L (340)0(uncachepage\(p\);)32(408)100 L cleartomark showpage saveobj restore %%EndPage: 201 201 %%Page: 202 202 /saveobj save def mark 202 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 4)l ()l ()l (409)0(i->next = imagealloc.free;)16(477)100(})116 L (410)0(imagealloc.free = i;)16(478 })100 L (411)0(479)100 L (412)0(/* defer freeing channel till we're out of spin lock's */)16(480 if\(newsize > \(SEGMAPSIZE*PTEPERTAB\)\) {)100 L (413)0(if\(imagealloc.nfreechan == imagealloc.szfreechan\){)16(481)100(qunlock\(&s->lk\);)116 L (414)0(imagealloc.szfreechan += NFREECHAN;)24(482)100(error\(Enovmem\);)116 L (415)0(cp = malloc\(imagealloc.szfreechan*sizeof\(Chan*\)\);)24(483 })100 L (416)0(if\(cp == nil\))24(484 mapsize = ROUND\(newsize, PTEPERTAB\)/PTEPERTAB;)100 L (417)0(panic\("putimage"\);)32(485 if\(mapsize > s->mapsize\){)100 L (418)0(memmove\(cp, imagealloc.freechan, imagealloc.nfreechan*sizeof\(Chan*\)\);)24(486)100(map = smalloc\(mapsize*sizeof\(Pte*\)\);)116 L (419)0(free\(imagealloc.freechan\);)24(487)100(memmove\(map, s->map, s->mapsize*sizeof\(Pte*\)\);)116 L (420)0(imagealloc.freechan = cp;)24(488)100(if\(s->map != s->ssegmap\))116 L (421)0(})16(489)100(free\(s->map\);)124 L (422)0(imagealloc.freechan[imagealloc.nfreechan++] = c;)16(490)100(s->map = map;)116 L (423)0(unlock\(&imagealloc\);)16(491)100(s->mapsize = mapsize;)116 L (424)0(492 })100 L (425)0(return;)16(493)100 L (426 })0(494 s->top = newtop;)100 L (427 unlock\(i\);)0(495 s->size = newsize;)100 L (428 })0(496 qunlock\(&s->lk\);)100 L (429)0(497 return 0;)100 L (430 long)0(498 })100 L (431 ibrk\(ulong addr, int seg\))0(499)100 L (432 {)0(500 /*)100 L (433 Segment *s, *ns;)0(501 * called with s->lk locked)100 L (434 ulong newtop, newsize;)0(502 */)100 L (435 int i, mapsize;)0(503 void)100 L (436 Pte **map;)0(504 mfreeseg\(Segment *s, ulong start, int pages\))100 L (437)0(505 {)100 L (438 s = up->seg[seg];)0(506 int i, j, size;)100 L (439 if\(s == 0\))0(507 ulong soff;)100 L (440)0(error\(Ebadarg\);)16(508 Page *pg;)100 L (441)0(509 Page *list;)100 L (442 if\(addr == 0\))0(510)100 L (443)0(return s->base;)16(511 soff = start-s->base;)100 L (444)0(512 j = \(soff&\(PTEMAPMEM-1\)\)/BY2PG;)100 L (445 qlock\(&s->lk\);)0(513)100 L (446)0(514 size = s->mapsize;)100 L (447 /* We may start with the bss overlapping the data */)0(515 list = nil;)100 L (448 if\(addr < s->base\) {)0(516 for\(i = soff/PTEMAPMEM; i < size; i++\) {)100 L (449)0(if\(seg != BSEG || up->seg[DSEG] == 0 || addr < up->seg[DSEG]->base\) {)16(517)100(if\(pages <= 0\))116 L (450)0(qunlock\(&s->lk\);)24(518)100(break;)124 L (451)0(error\(Enovmem\);)24(519)100(if\(s->map[i] == 0\) {)116 L (452)0(})16(520)100(pages -= PTEPERTAB-j;)124 L (453)0(addr = s->base;)16(521)100(j = 0;)124 L (454 })0(522)100(continue;)124 L (455)0(523)100(})116 L (456 newtop = PGROUND\(addr\);)0(524)100(while\(j < PTEPERTAB\) {)116 L (457 newsize = \(newtop-s->base\)/BY2PG;)0(525)100(pg = s->map[i]->pages[j];)124 L (458 if\(newtop < s->top\) {)0(526)100(if\(pg\){)124 L (459)0(mfreeseg\(s, newtop, \(s->top-newtop\)/BY2PG\);)16(527)100(s->map[i]->pages[j] = 0;)132 L (460)0(qunlock\(&s->lk\);)16(528)100(pg->next = list;)132 L (461)0(flushmmu\(\);)16(529)100(list = pg;)132 L (462)0(return 0;)16(530)100(})124 L (463 })0(531)100(if\(--pages == 0\))124 L (464)0(532)100(goto out;)132 L (465 if\(swapfull\(\)\){)0(533)100(j++;)124 L (466)0(qunlock\(&s->lk\);)16(534)100(})116 L (467)0(error\(Enoswap\);)16(535)100(j = 0;)116 L (468 })0(536 })100 L (469)0(537 out:)100 L (470 for\(i = 0; i < NSEG; i++\) {)0(538 /* flush this seg in all other processes */)100 L (471)0(ns = up->seg[i];)16(539 i = s->type&SG_TYPE;)100 L (472)0(if\(ns == 0 || ns == s\))16(540 switch\(i\){)100 L (473)0(continue;)24(541 case SG_SHARED:)100 L (474)0(if\(newtop >= ns->base && newtop < ns->top\) {)16(542 case SG_SHDATA:)100 L (475)0(qunlock\(&s->lk\);)24(543)100(procflushseg\(s\);)116 L (476)0(error\(Esoverlap\);)24(544)100(break;)116 L cleartomark showpage saveobj restore %%EndPage: 202 202 %%Page: 203 203 /saveobj save def mark 203 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 5)l ()l ()l (545 })0(613 for\(sno = 0; sno < NSEG; sno++\))100 L (546)0(614)100(if\(p->seg[sno] == nil && sno != ESEG\))116 L (547 /* free the pages */)0(615)100(break;)124 L (548 for\(pg = list; pg != nil; pg = list\){)0(616)100 L (549)0(list = list->next;)16(617 if\(sno == NSEG\))100 L (550)0(putpage\(pg\);)16(618)100(error\(Enovmem\);)116 L (551 })0(619)100 L (552 })0(620 len = PGROUND\(len\);)100 L (553)0(621 if\(len == 0\))100 L (554 Segment*)0(622)100(error\(Ebadarg\);)116 L (555 isoverlap\(Proc *p, ulong va, int len\))0(623)100 L (556 {)0(624 /*)100 L (557 int i;)0(625)100(* Find a hole in the address space.)109 L (558 Segment *ns;)0(626)100(* Starting at the lowest possible stack address - len,)109 L (559 ulong newtop;)0(627)100(* check for an overlapping segment, and repeat at the)109 L (560)0(628)100(* base of that segment - len until either a hole is found)109 L (561 newtop = va+len;)0(629)100(* or the address space is exhausted.)109 L (562 for\(i = 0; i < NSEG; i++\) {)0(630)100(*/)109 L (563)0(ns = p->seg[i];)16(631 if\(va == 0\) {)100 L (564)0(if\(ns == 0\))16(632)100(va = p->seg[SSEG]->base - len;)116 L (565)0(continue;)24(633)100(for\(;;\) {)116 L (566)0(if\(\(newtop > ns->base && newtop <= ns->top\) ||)16(634)100(os = isoverlap\(p, va, len\);)124 L (567)0(\(va >= ns->base && va < ns->top\)\))19(635)100(if\(os == nil\))124 L (568)0(return ns;)24(636)100(break;)132 L (569 })0(637)100(va = os->base;)124 L (570 return nil;)0(638)100(if\(len > va\))124 L (571 })0(639)100(error\(Enovmem\);)132 L (572)0(640)100(va -= len;)124 L (573 int)0(641)100(})116 L (574 addphysseg\(Physseg* new\))0(642 })100 L (575 {)0(643)100 L (576 Physseg *ps;)0(644 va = va&~\(BY2PG-1\);)100 L (577)0(645 if\(isoverlap\(p, va, len\) != nil\))100 L (578 /*)0(646)100(error\(Esoverlap\);)116 L (579)0(* Check not already entered and there is room)9(647)100 L (580)0(* for a new entry and the terminating null entry.)9(648 for\(ps = physseg; ps->name; ps++\))100 L (581)0(*/)9(649)100(if\(strcmp\(name, ps->name\) == 0\))116 L (582 lock\(&physseglock\);)0(650)100(goto found;)124 L (583 for\(ps = physseg; ps->name; ps++\){)0(651)100 L (584)0(if\(strcmp\(ps->name, new->name\) == 0\){)16(652 error\(Ebadarg\);)100 L (585)0(unlock\(&physseglock\);)24(653 found:)100 L (586)0(return -1;)24(654 if\(len > ps->size\))100 L (587)0(})16(655)100(error\(Enovmem\);)116 L (588 })0(656)100 L (589 if\(ps-physseg >= nelem\(physseg\)-2\){)0(657 attr &= ~SG_TYPE;)100(/* Turn off what is not allowed */)140 L (590)0(unlock\(&physseglock\);)16(658 attr |= ps->attr;)100(/* Copy in defaults */)140 L (591)0(return -1;)16(659)100 L (592 })0(660 s = newseg\(attr, va, len/BY2PG\);)100 L (593)0(661 s->pseg = ps;)100 L (594 *ps = *new;)0(662 p->seg[sno] = s;)100 L (595 unlock\(&physseglock\);)0(663)100 L (596)0(664 return va;)100 L (597 return 0;)0(665 })100 L (598 })0(666)100 L (599)0(667 void)100 L (600 ulong)0(668 pteflush\(Pte *pte, int s, int e\))100 L (601 segattach\(Proc *p, ulong attr, char *name, ulong va, ulong len\))0(669 {)100 L (602 {)0(670 int i;)100 L (603 int sno;)0(671 Page *p;)100 L (604 Segment *s, *os;)0(672)100 L (605 Physseg *ps;)0(673 for\(i = s; i < e; i++\) {)100 L (606)0(674)100(p = pte->pages[i];)116 L (607 if\(va != 0 && \(va&KZERO\) == KZERO\))0(/* BUG: Only ok for now */)48(675)100(if\(pagedout\(p\) == 0\))116 L (608)0(error\(Ebadarg\);)16(676)100(memset\(p->cachectl, PG_TXTFLUSH, sizeof\(p->cachectl\)\);)124 L (609)0(677 })100 L (610 validaddr\(\(ulong\)name, 1, 0\);)0(678 })100 L (611 vmemchr\(name, 0, ~0\);)0(679)100 L (612)0(680 long)100 L cleartomark showpage saveobj restore %%EndPage: 203 203 %%Page: 204 204 /saveobj save def mark 204 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/segment.c Page 6)l ()l ()l (681 syssegflush\(ulong *arg\))l (682 {)l (683 Segment *s;)l (684 ulong addr, l;)l (685 Pte *pte;)l (686 int chunk, ps, pe, len;)l (687)l (688 addr = arg[0];)l (689 len = arg[1];)l (690)l (691 while\(len > 0\) {)l (692)0(s = seg\(up, addr, 1\);)16 L (693)0(if\(s == 0\))16 L (694)0(error\(Ebadarg\);)24 L (695)l (696)0(s->flushme = 1;)16 L (697 more:)l (698)0(l = len;)16 L (699)0(if\(addr+l > s->top\))16 L (700)0(l = s->top - addr;)24 L (701)l (702)0(ps = addr-s->base;)16 L (703)0(pte = s->map[ps/PTEMAPMEM];)16 L (704)0(ps &= PTEMAPMEM-1;)16 L (705)0(pe = PTEMAPMEM;)16 L (706)0(if\(pe-ps > l\){)16 L (707)0(pe = ps + l;)24 L (708)0(pe = \(pe+BY2PG-1\)&~\(BY2PG-1\);)24 L (709)0(})16 L (710)0(if\(pe == ps\) {)16 L (711)0(qunlock\(&s->lk\);)24 L (712)0(error\(Ebadarg\);)24 L (713)0(})16 L (714)l (715)0(if\(pte\))16 L (716)0(pteflush\(pte, ps/BY2PG, pe/BY2PG\);)24 L (717)l (718)0(chunk = pe-ps;)16 L (719)0(len -= chunk;)16 L (720)0(addr += chunk;)16 L (721)l (722)0(if\(len > 0 && addr < s->top\))16 L (723)0(goto more;)24 L (724)l (725)0(qunlock\(&s->lk\);)16 L (726 })l (727 flushmmu\(\);)l (728 return 0;)l (729 })l (730)l (731 void)l (732 segclock\(ulong pc\))l (733 {)l (734 Segment *s;)l (735)l (736 s = up->seg[TSEG];)l (737 if\(s == 0 || s->profile == 0\))l (738)0(return;)16 L (739)l (740 s->profile[0] += TK2MS\(1\);)l (741 if\(pc >= s->base && pc < s->top\) {)l (742)0(pc -= s->base;)16 L (743)0(s->profile[pc>>LRESPROF] += TK2MS\(1\);)16 L (744 })l (745 })l cleartomark showpage saveobj restore %%EndPage: 204 204 %%Page: 205 205 /saveobj save def mark 205 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/swap.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(})108 L (2 #include "../port/lib.h")0(70)100(if\(*idx >= 254\))108 L (3 #include "mem.h")0(71)100(panic\("putswap %lux == %ud", p, *idx\);)116 L (4 #include "dat.h")0(72)100(unlock\(&swapalloc\);)108 L (5 #include "fns.h")0(73 })100 L (6 #include "../port/error.h")0(74)100 L (7)0(75 void)100 L (8 static int)0(canflush\(Proc*, Segment*\);)24(76 dupswap\(Page *p\))100 L (9 static void)0(executeio\(void\);)24(77 {)100 L (10 static int)0(needpages\(void*\);)24(78)100(lock\(&swapalloc\);)108 L (11 static void)0(pageout\(Proc*, Segment*\);)24(79)100(if\(++swapalloc.swmap[\(\(ulong\)p\)/BY2PG] == 0\))108 L (12 static void)0(pagepte\(int, Page**\);)24(80)100(panic\("dupswap"\);)116 L (13 static void)0(pager\(void*\);)24(81)100(unlock\(&swapalloc\);)108 L (14)0(82 })100 L (15)0(Image swapimage;)8(83)100 L (16 static int swopen;)0(84 int)100 L (17 static Page **iolist;)0(85 swapcount\(ulong daddr\))100 L (18 static int ioptr;)0(86 {)100 L (19)0(87)100(return swapalloc.swmap[daddr/BY2PG];)108 L (20 void)0(88 })100 L (21 swapinit\(void\))0(89)100 L (22 {)0(90 void)100 L (23)0(swapalloc.swmap = xalloc\(conf.nswap\);)8(91 kickpager\(void\))100 L (24)0(swapalloc.top = &swapalloc.swmap[conf.nswap];)8(92 {)100 L (25)0(swapalloc.alloc = swapalloc.swmap;)8(93)100(static int started;)108 L (26)0(swapalloc.last = swapalloc.swmap;)8(94)100 L (27)0(swapalloc.free = conf.nswap;)8(95)100(if\(started\))108 L (28)0(iolist = xalloc\(conf.nswppo*sizeof\(Page*\)\);)8(96)100(wakeup\(&swapalloc.r\);)116 L (29)0(if\(swapalloc.swmap == 0 || iolist == 0\))8(97)100(else {)108 L (30)0(panic\("swapinit: not enough memory"\);)16(98)100(kproc\("pager", pager, 0\);)116 L (31)0(99)100(started = 1;)116 L (32)0(swapimage.notext = 1;)8(100 })100 L (33 })0(101 })100 L (34)0(102)100 L (35 ulong)0(103 static void)100 L (36 newswap\(void\))0(104 pager\(void *junk\))100 L (37 {)0(105 {)100 L (38)0(uchar *look;)8(106 int i;)100 L (39)0(107 Segment *s;)100 L (40)0(lock\(&swapalloc\);)8(108 Proc *p, *ep;)100 L (41)0(109)100 L (42)0(if\(swapalloc.free == 0\){)8(110 if\(waserror\(\)\))100 L (43)0(unlock\(&swapalloc\);)16(111)100(panic\("pager: os error\\n"\);)116 L (44)0(return ~0;)16(112)100 L (45)0(})8(113 p = proctab\(0\);)100 L (46)0(114 ep = &p[conf.nproc];)100 L (47)0(look = memchr\(swapalloc.last, 0, swapalloc.top-swapalloc.last\);)8(115)100 L (48)0(if\(look == 0\))8(116 loop:)100 L (49)0(panic\("inconsistent swap"\);)16(117 up->psstate = "Idle";)100 L (50)0(118 sleep\(&swapalloc.r, needpages, 0\);)100 L (51)0(*look = 1;)8(119)100 L (52)0(swapalloc.last = look;)8(120 while\(needpages\(junk\)\) {)100 L (53)0(swapalloc.free--;)8(121)100 L (54)0(unlock\(&swapalloc\);)8(122)100(if\(swapimage.c\) {)116 L (55)0(return \(look-swapalloc.swmap\) * BY2PG;)8(123)100(p++;)124 L (56 })0(124)100(if\(p >= ep\))124 L (57)0(125)100(p = proctab\(0\);)132 L (58 void)0(126)100 L (59 putswap\(Page *p\))0(127)100(if\(p->state == Dead || p->kp\))124 L (60 {)0(128)100(continue;)132 L (61)0(uchar *idx;)8(129)100 L (62)0(130)100(if\(!canqlock\(&p->seglock\)\))124 L (63)0(lock\(&swapalloc\);)8(131)100(continue;)132(/* process changing its segments */)156 L (64)0(idx = &swapalloc.swmap[\(\(ulong\)p\)/BY2PG];)8(132)100 L (65)0(if\(--\(*idx\) == 0\) {)8(133)100(for\(i = 0; i < NSEG; i++\) {)124 L (66)0(swapalloc.free++;)16(134)100(if\(!needpages\(junk\)\){)132 L (67)0(if\(idx < swapalloc.last\))16(135)100(qunlock\(&p->seglock\);)140 L (68)0(swapalloc.last = idx;)24(136)100(goto loop;)140 L cleartomark showpage saveobj restore %%EndPage: 205 205 %%Page: 206 206 /saveobj save def mark 206 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/swap.c Page 2)l ()l ()l (137)0(})32(205)100 L (138)0(206 /* Pass through the pte tables looking for memory pages to swap out */)100 L (139)0(if\(s = p->seg[i]\) {)32(207 type = s->type&SG_TYPE;)100 L (140)0(switch\(s->type&SG_TYPE\) {)40(208 size = s->mapsize;)100 L (141)0(default:)40(209 for\(i = 0; i < size; i++\) {)100 L (142)0(break;)48(210)100(l = s->map[i];)116 L (143)0(case SG_TEXT:)40(211)100(if\(l == 0\))116 L (144)0(pageout\(p, s\);)48(212)100(continue;)124 L (145)0(break;)48(213)100(for\(pg = l->first; pg < l->last; pg++\) {)116 L (146)0(case SG_DATA:)40(214)100(entry = *pg;)124 L (147)0(case SG_BSS:)40(215)100(if\(pagedout\(entry\)\))124 L (148)0(case SG_STACK:)40(216)100(continue;)132 L (149)0(case SG_SHARED:)40(217)100 L (150)0(case SG_SHDATA:)40(218)100(if\(entry->modref & PG_REF\) {)124 L (151)0(case SG_MAP:)40(219)100(entry->modref &= ~PG_REF;)132 L (152)0(up->psstate = "Pageout";)48(220)100(continue;)132 L (153)0(pageout\(p, s\);)48(221)100(})124 L (154)0(if\(ioptr != 0\) {)48(222)100 L (155)0(up->psstate = "I/O";)56(223)100(pagepte\(type, pg\);)124 L (156)0(executeio\(\);)56(224)100 L (157)0(})48(225)100(if\(ioptr >= conf.nswppo\))124 L (158)0(break;)48(226)100(goto out;)132 L (159)0(})40(227)100(})116 L (160)0(})32(228 })100 L (161)0(})24(229 out:)100 L (162)0(qunlock\(&p->seglock\);)24(230 poperror\(\);)100 L (163)0(})16(231 qunlock\(&s->lk\);)100 L (164)0(else {)16(232 putseg\(s\);)100 L (165)0(if\(!cpuserver\))24(233 })100 L (166)0(freebroken\(\); /* can use the memory */)32(234)100 L (167)0(else)24(235 static int)100 L (168)0(killbig\(\);)32(236 canflush\(Proc *p, Segment *s\))100 L (169)0(237 {)100 L (170)0(/* Emulate the old system if no swap channel */)24(238 int i;)100 L (171)0(print\("no physical memory\\n"\);)24(239 Proc *ep;)100 L (172)0(tsleep\(&swapalloc.pause, return0, 0, 5000\);)24(240)100 L (173)0(wakeup\(&palloc.r\);)24(241 lock\(s\);)100 L (174)0(})16(242 if\(s->ref == 1\) {)100(/* Easy if we are the only user */)140 L (175 })0(243)100(s->ref++;)116 L (176 goto loop;)0(244)100(unlock\(s\);)116 L (177 })0(245)100(return canpage\(p\);)116 L (178)0(246 })100 L (179 static void)0(247 s->ref++;)100 L (180 pageout\(Proc *p, Segment *s\))0(248 unlock\(s\);)100 L (181 {)0(249)100 L (182 int type, i, size;)0(250 /* Now we must do hardwork to ensure all processes which have tlb)100 L (183 Pte *l;)0(251)100(* entries for this segment will be flushed if we succeed in paging it out)109 L (184 Page **pg, *entry;)0(252)100(*/)109 L (185)0(253 p = proctab\(0\);)100 L (186 if\(!canqlock\(&s->lk\)\) /* We cannot afford to wait, we will surely deadlock */)0(254 ep = &p[conf.nproc];)100 L (187)0(return;)16(255 while\(p < ep\) {)100 L (188)0(256)100(if\(p->state != Dead\) {)116 L (189 if\(s->steal\) {)0(/* Protected by /dev/proc */)32(257)100(for\(i = 0; i < NSEG; i++\))124 L (190)0(qunlock\(&s->lk\);)16(258)100(if\(p->seg[i] == s\))132 L (191)0(return;)16(259)100(if\(!canpage\(p\)\))140 L (192 })0(260)100(return 0;)148 L (193)0(261)100(})116 L (194 if\(!canflush\(p, s\)\) { /* Able to invalidate all tlbs with references */)0(262)100(p++;)116 L (195)0(qunlock\(&s->lk\);)16(263 })100 L (196)0(putseg\(s\);)16(264 return 1;)100 L (197)0(return;)16(265 })100 L (198 })0(266)100 L (199)0(267 static void)100 L (200 if\(waserror\(\)\) {)0(268 pagepte\(int type, Page **pg\))100 L (201)0(qunlock\(&s->lk\);)16(269 {)100 L (202)0(putseg\(s\);)16(270 ulong daddr;)100 L (203)0(return;)16(271 Page *outp;)100 L (204 })0(272)100 L cleartomark showpage saveobj restore %%EndPage: 206 206 %%Page: 207 207 /saveobj save def mark 207 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/swap.c Page 3)l ()l ()l (273 outp = *pg;)0(341)100 L (274 switch\(type\) {)0(342 for\(i = 0; i < ioptr; i++\) {)100 L (275 case SG_TEXT:)0(/* Revert to demand load */)48(343)100(if\(ioptr > conf.nswppo\))116 L (276)0(putpage\(outp\);)16(344)100(panic\("executeio: ioptr %d > %d\\n", ioptr, conf.nswppo\);)124 L (277)0(*pg = 0;)16(345)100(out = iolist[i];)116 L (278)0(break;)16(346)100(k = kmap\(out\);)116 L (279)0(347)100(kaddr = \(char*\)VA\(k\);)116 L (280 case SG_DATA:)0(348)100 L (281 case SG_BSS:)0(349)100(if\(waserror\(\)\))116 L (282 case SG_STACK:)0(350)100(panic\("executeio: page out I/O error"\);)124 L (283 case SG_SHARED:)0(351)100 L (284 case SG_SHDATA:)0(352)100(n = devtab[c->type]->write\(c, kaddr, BY2PG, out->daddr\);)116 L (285 case SG_MAP:)0(353)100(if\(n != BY2PG\))116 L (286)0(/*)16(354)100(nexterror\(\);)124 L (287)0(* get a new swap address and clear any pages)17(355)100 L (288)0(* referring to it from the cache)17(356)100(kunmap\(k\);)116 L (289)0(*/)17(357)100(poperror\(\);)116 L (290)0(daddr = newswap\(\);)16(358)100 L (291)0(if\(daddr == ~0\))16(359)100(/* Free up the page after I/O */)116 L (292)0(break;)24(360)100(lock\(out\);)116 L (293)0(cachedel\(&swapimage, daddr\);)16(361)100(out->ref--;)116 L (294)0(362)100(unlock\(out\);)116 L (295)0(lock\(outp\);)16(363)100(putpage\(out\);)116 L (296)0(364 })100 L (297)0(/* forget anything that it used to cache */)16(365 ioptr = 0;)100 L (298)0(uncachepage\(outp\);)16(366 })100 L (299)0(367)100 L (300)0(/*)16(368 static int)100 L (301)0(* incr the reference count to make sure it sticks around while)17(369 needpages\(void*\))100 L (302)0(* being written)17(370 {)100 L (303)0(*/)17(371 return palloc.freecount < swapalloc.headroom;)100 L (304)0(outp->ref++;)16(372 })100 L (305)0(373)100 L (306)0(/*)16(374 void)100 L (307)0(* enter it into the cache so that a fault happening)17(375 setswapchan\(Chan *c\))100 L (308)0(* during the write will grab the page from the cache)17(376 {)100 L (309)0(* rather than one partially written to the disk)17(377 char dirbuf[DIRLEN];)100 L (310)0(*/)17(378 Dir d;)100 L (311)0(outp->daddr = daddr;)16(379)100 L (312)0(cachepage\(outp, &swapimage\);)16(380 if\(swapimage.c\) {)100 L (313)0(*pg = \(Page*\)\(daddr|PG_ONSWAP\);)16(381)100(if\(swapalloc.free != conf.nswap\){)116 L (314)0(unlock\(outp\);)16(382)100(cclose\(c\);)124 L (315)0(383)100(error\(Einuse\);)124 L (316)0(/* Add page to IO transaction list */)16(384)100(})116 L (317)0(iolist[ioptr++] = outp;)16(385)100(cclose\(swapimage.c\);)116 L (318)0(break;)16(386 })100 L (319 })0(387)100 L (320 })0(388 /*)100 L (321)0(389)100(* if this isn't a file, set the swap space)109 L (322 void)0(390)100(* to be at most the size of the partition)109 L (323 pagersummary\(void\))0(391)100(*/)109 L (324 {)0(392 if\(devtab[c->type]->dc != L'M'\){)100 L (325 print\("%lud/%lud memory %lud/%lud swap %d iolist\\n",)0(393)100(devtab[c->type]->stat\(c, dirbuf\);)116 L (326)0(palloc.user-palloc.freecount,)16(394)100(convM2D\(dirbuf, &d\);)116 L (327)0(palloc.user, conf.nswap-swapalloc.free, conf.nswap,)16(395)100(if\(d.length < conf.nswap*BY2PG\){)116 L (328)0(ioptr\);)16(396)100(conf.nswap = d.length/BY2PG;)124 L (329 })0(397)100(swapalloc.top = &swapalloc.swmap[conf.nswap];)124 L (330)0(398)100(swapalloc.free = conf.nswap;)124 L (331 static void)0(399)100(})116 L (332 executeio\(void\))0(400 })100 L (333 {)0(401)100 L (334 Page *out;)0(402 swapimage.c = c;)100 L (335 int i, n;)0(403 })100 L (336 Chan *c;)0(404)100 L (337 char *kaddr;)0(405 int)100 L (338 KMap *k;)0(406 swapfull\(void\))100 L (339)0(407 {)100 L (340 c = swapimage.c;)0(408 return swapalloc.free < conf.nswap/10;)100 L cleartomark showpage saveobj restore %%EndPage: 207 207 %%Page: 208 208 /saveobj save def mark 208 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/swap.c Page 4)l ()l ()l (409 })l cleartomark showpage saveobj restore %%EndPage: 208 208 %%Page: 209 209 /saveobj save def mark 209 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 1)l ()l ()l (1 #include "u.h")0(69 {)100 L (2 #include "../port/lib.h")0(70)100(Chan *c;)108 L (3 #include "mem.h")0(71)100(Fgrp *f;)108 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(c = 0;)108 L (6 #include "../port/error.h")0(74)100(f = up->fgrp;)108 L (7)0(75)100 L (8 /*)0(76)100(lock\(f\);)108 L (9)0(* The sys*\(\) routines needn't poperror\(\) as they return directly to syscall\(\).)7(77)100(if\(fd<0 || f->nfd<=fd || \(c = f->fd[fd]\)==0\) {)108 L (10 */)0(78)100(unlock\(f\);)116 L (11)0(79)100(error\(Ebadfd\);)116 L (12 int)0(80)100(})108 L (13 growfd\(Fgrp *f, int fd\) /* fd is always >= 0 */)0(81)100(if\(iref\))108 L (14 {)0(82)100(incref\(c\);)116 L (15)0(Chan **newfd, **oldfd;)8(83)100(unlock\(f\);)108 L (16)0(84)100 L (17)0(if\(fd < f->nfd\))8(85)100(if\(chkmnt && \(c->flag&CMSG\)\) {)108 L (18)0(return 0;)16(86)100(if\(iref\))116 L (19)0(if\(fd >= f->nfd+DELTAFD\))8(87)100(cclose\(c\);)124 L (20)0(return -1;)16(/* out of range */)32(88)100(error\(Ebadusefd\);)116 L (21)0(if\(fd % 100 == 0\))8(89)100(})108 L (22)0(pprint\("warning: process exceeds %d file descriptors\\n", fd\);)16(90)100 L (23)0(/*)8(91)100(if\(mode<0 || c->mode==ORDWR\))108 L (24)0(* Unbounded allocation is unwise; besides, there are only 16 bits)9(92)100(return c;)116 L (25)0(* of fid in 9P)9(93)100 L (26)0(*/)9(94)100(if\(\(mode&OTRUNC\) && c->mode==OREAD\) {)108 L (27)0(if\(f->nfd >= 5000\){)8(95)100(if\(iref\))116 L (28)0(Exhausted:)10(96)100(cclose\(c\);)124 L (29)0(exhausted\("file descriptors"\);)16(97)100(error\(Ebadusefd\);)116 L (30)0(return -1;)16(98)100(})108 L (31)0(})8(99)100 L (32)0(newfd = malloc\(\(f->nfd+DELTAFD\)*sizeof\(Chan*\)\);)8(100 if\(\(mode&~OTRUNC\) != c->mode\) {)100 L (33)0(if\(newfd == 0\))8(101)100(if\(iref\))116 L (34)0(goto Exhausted;)16(102)100(cclose\(c\);)124 L (35)0(oldfd = f->fd;)8(103)100(error\(Ebadusefd\);)116 L (36)0(memmove\(newfd, oldfd, f->nfd*sizeof\(Chan*\)\);)8(104 })100 L (37)0(f->fd = newfd;)8(105)100 L (38)0(free\(oldfd\);)8(106 return c;)100 L (39)0(f->nfd += DELTAFD;)8(107 })100 L (40)0(if\(fd > f->maxfd\))8(108)100 L (41)0(f->maxfd = fd;)16(109 int)100 L (42)0(return 1;)8(110 openmode\(ulong o\))100 L (43 })0(111 {)100 L (44)0(112 o &= ~\(OTRUNC|OCEXEC|ORCLOSE\);)100 L (45 int)0(113 if\(o > OEXEC\))100 L (46 newfd\(Chan *c\))0(114)100(error\(Ebadarg\);)116 L (47 {)0(115 if\(o == OEXEC\))100 L (48)0(int fd;)8(116)100(return OREAD;)116 L (49)0(Fgrp *f;)8(117 return o;)100 L (50)0(118 })100 L (51)0(f = up->fgrp;)8(119)100 L (52)0(lock\(f\);)8(120 long)100 L (53)0(for\(fd=0; fdnfd; fd++\))8(121 sysfd2path\(ulong *arg\))100 L (54)0(if\(f->fd[fd] == 0\))16(122 {)100 L (55)0(break;)24(123 Chan *c;)100 L (56)0(if\(fd >= f->nfd && growfd\(f, fd\) < 0\){)8(124)100 L (57)0(unlock\(f\);)16(125 validaddr\(arg[1], arg[2], 1\);)100 L (58)0(return -1;)16(126)100 L (59)0(})8(127 c = fdtochan\(arg[0], -1, 0, 1\);)100 L (60)0(if\(fd > f->maxfd\))8(128)100 L (61)0(f->maxfd = fd;)16(129 if\(c->name == nil\))100 L (62)0(f->fd[fd] = c;)8(130)100(snprint\(\(char*\)arg[1], arg[2], ""\);)116 L (63)0(unlock\(f\);)8(131 else)100 L (64)0(return fd;)8(132)100(snprint\(\(char*\)arg[1], arg[2], "%s", c->name->s\);)116 L (65 })0(133 cclose\(c\);)100 L (66)0(134 return 0;)100 L (67 Chan*)0(135 })100 L (68 fdtochan\(int fd, int mode, int chkmnt, int iref\))0(136)100 L cleartomark showpage saveobj restore %%EndPage: 209 209 %%Page: 210 210 /saveobj save def mark 210 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 2)l ()l ()l (137 long)0(205)100(cclose\(oc\);)124 L (138 syspipe\(ulong *arg\))0(206 }else{)100 L (139 {)0(207)100(if\(waserror\(\)\) {)116 L (140 int fd[2];)0(208)100(cclose\(c\);)124 L (141 Chan *c[2];)0(209)100(nexterror\(\);)124 L (142 Dev *d;)0(210)100(})116 L (143 Fgrp *f = up->fgrp;)0(211)100(fd = newfd\(c\);)116 L (144)0(212)100(if\(fd < 0\))116 L (145 validaddr\(arg[0], 2*BY2WD, 1\);)0(213)100(error\(Enofd\);)124 L (146 evenaddr\(arg[0]\);)0(214)100(poperror\(\);)116 L (147 d = devtab[devno\('|', 0\)];)0(215 })100 L (148 c[0] = namec\("#|", Atodir, 0, 0\);)0(216)100 L (149 c[1] = 0;)0(217 return fd;)100 L (150 fd[0] = -1;)0(218 })100 L (151 fd[1] = -1;)0(219)100 L (152 if\(waserror\(\)\){)0(220 long)100 L (153)0(cclose\(c[0]\);)16(221 sysopen\(ulong *arg\))100 L (154)0(if\(c[1]\))16(222 {)100 L (155)0(cclose\(c[1]\);)24(223 int fd;)100 L (156)0(if\(fd[0] >= 0\))16(224 Chan *c = 0;)100 L (157)0(f->fd[fd[0]]=0;)24(225)100 L (158)0(if\(fd[1] >= 0\))16(226 openmode\(arg[1]\);)100(/* error check only */)132 L (159)0(f->fd[fd[1]]=0;)24(227 if\(waserror\(\)\){)100 L (160)0(nexterror\(\);)16(228)100(if\(c\))116 L (161 })0(229)100(cclose\(c\);)124 L (162 c[1] = cclone\(c[0], 0\);)0(230)100(nexterror\(\);)116 L (163 if\(walk\(&c[0], "data", 1\) < 0\))0(231 })100 L (164)0(error\(Egreg\);)16(232 validaddr\(arg[0], 1, 0\);)100 L (165 if\(walk\(&c[1], "data1", 1\) < 0\))0(233 c = namec\(\(char*\)arg[0], Aopen, arg[1], 0\);)100 L (166)0(error\(Egreg\);)16(234 fd = newfd\(c\);)100 L (167 c[0] = d->open\(c[0], ORDWR\);)0(235 if\(fd < 0\))100 L (168 c[1] = d->open\(c[1], ORDWR\);)0(236)100(error\(Enofd\);)116 L (169 fd[0] = newfd\(c[0]\);)0(237 poperror\(\);)100 L (170 fd[1] = newfd\(c[1]\);)0(238 return fd;)100 L (171 if\(fd[0] < 0 || fd[1] < 0\))0(239 })100 L (172)0(error\(Enofd\);)16(240)100 L (173 \(\(long*\)arg[0]\)[0] = fd[0];)0(241 void)100 L (174 \(\(long*\)arg[0]\)[1] = fd[1];)0(242 fdclose\(int fd, int flag\))100 L (175 poperror\(\);)0(243 {)100 L (176 return 0;)0(244 int i;)100 L (177 })0(245 Chan *c;)100 L (178)0(246 Fgrp *f = up->fgrp;)100 L (179 long)0(247)100 L (180 sysdup\(ulong *arg\))0(248 lock\(f\);)100 L (181 {)0(249 c = f->fd[fd];)100 L (182 int fd;)0(250 if\(c == 0\){)100 L (183 Chan *c, *oc;)0(251)100(/* can happen for users with shared fd tables */)116 L (184 Fgrp *f = up->fgrp;)0(252)100(unlock\(f\);)116 L (185)0(253)100(return;)116 L (186 /*)0(254 })100 L (187)0(* Close after dup'ing, so date > #d/1 works)9(255 if\(flag\){)100 L (188)0(*/)9(256)100(if\(c==0 || !\(c->flag&flag\)\){)116 L (189 c = fdtochan\(arg[0], -1, 0, 1\);)0(257)100(unlock\(f\);)124 L (190 fd = arg[1];)0(258)100(return;)124 L (191 if\(fd != -1\){)0(259)100(})116 L (192)0(lock\(f\);)16(260 })100 L (193)0(if\(fd<0 || growfd\(f, fd\)<0\) {)16(261 f->fd[fd] = 0;)100 L (194)0(unlock\(f\);)24(262 if\(fd == f->maxfd\))100 L (195)0(cclose\(c\);)24(263)100(for\(i=fd; --i>=0 && f->fd[i]==0; \))116 L (196)0(error\(Ebadfd\);)24(264)100(f->maxfd = i;)124 L (197)0(})16(265)100 L (198)0(if\(fd > f->maxfd\))16(266 unlock\(f\);)100 L (199)0(f->maxfd = fd;)24(267 cclose\(c\);)100 L (200)0(268 })100 L (201)0(oc = f->fd[fd];)16(269)100 L (202)0(f->fd[fd] = c;)16(270 long)100 L (203)0(unlock\(f\);)16(271 sysclose\(ulong *arg\))100 L (204)0(if\(oc\))16(272 {)100 L cleartomark showpage saveobj restore %%EndPage: 210 210 %%Page: 211 211 /saveobj save def mark 211 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 3)l ()l ()l (273 fdtochan\(arg[0], -1, 0, 0\);)0(341 validaddr\(arg[1], arg[2], 1\);)100 L (274 fdclose\(arg[0], 0\);)0(342 c = fdtochan\(arg[0], OREAD, 1, 1\);)100 L (275)0(343 if\(waserror\(\)\) {)100 L (276 return 0;)0(344)100(cclose\(c\);)116 L (277 })0(345)100(nexterror\(\);)116 L (278)0(346 })100 L (279 long)0(347)100 L (280 unionread\(Chan *c, void *va, long n\))0(348 n = arg[2];)100 L (281 {)0(349 dir = c->qid.path&CHDIR;)100 L (282 int i;)0(350)100 L (283 long nr;)0(351 if\(dir\) {)100 L (284 Chan *nc;)0(352)100(n -= n%DIRLEN;)116 L (285 Mhead *m;)0(353)100(if\(c->offset%DIRLEN || n==0\))116 L (286 Mount *mount;)0(354)100(error\(Etoosmall\);)124 L (287)0(355 })100 L (288 m = c->mh;)0(356)100 L (289 rlock\(&m->lock\);)0(357 if\(dir && c->mh\))100 L (290 mount = m->mount;)0(358)100(n = unionread\(c, \(void*\)arg[1], n\);)116 L (291 for\(i = 0; mount != nil && i < c->uri; i++\))0(359 else if\(devtab[c->type]->dc != L'M'\))100 L (292)0(mount = mount->next;)16(360)100(n = devtab[c->type]->read\(c, \(void*\)arg[1], n, c->offset\);)116 L (293)0(361 else)100 L (294 while\(mount != nil\) {)0(362)100(n = mntread9p\(c, \(void*\)arg[1], n, c->offset\);)116 L (295)0(if\(waserror\(\)\) {)16(363)100 L (296)0(runlock\(&m->lock\);)24(364 lock\(c\);)100 L (297)0(nexterror\(\);)24(365 c->offset += n;)100 L (298)0(})16(366 unlock\(c\);)100 L (299)0(if\(mount->to == nil\))16(367)100 L (300)0(goto next;)24(368 poperror\(\);)100 L (301)0(nc = cclone\(mount->to, 0\);)16(369 cclose\(c\);)100 L (302)0(poperror\(\);)16(370)100 L (303)0(371 return n;)100 L (304)0(/* Error causes component of union to be skipped */)16(372 })100 L (305)0(if\(waserror\(\)\) {)16(373)100 L (306)0(cclose\(nc\);)24(374 long)100 L (307)0(goto next;)24(375 sysread\(ulong *arg\))100 L (308)0(})16(376 {)100 L (309)0(377 int dir;)100 L (310)0(nc = devtab[nc->type]->open\(nc, OREAD\);)16(378 long n;)100 L (311)0(nc->offset = c->offset;)16(379 Chan *c;)100 L (312)0(nr = devtab[nc->type]->read\(nc, va, n, nc->offset\);)16(380)100 L (313)0(/* devdirread e.g. changes it */)16(381 n = arg[2];)100 L (314)0(c->offset = nc->offset;)16(382 validaddr\(arg[1], n, 1\);)100 L (315)0(poperror\(\);)16(383 c = fdtochan\(arg[0], OREAD, 1, 1\);)100 L (316)0(384)100 L (317)0(cclose\(nc\);)16(385 if\(waserror\(\)\) {)100 L (318)0(if\(nr > 0\) {)16(386)100(cclose\(c\);)116 L (319)0(runlock\(&m->lock\);)24(387)100(nexterror\(\);)116 L (320)0(return nr;)24(388 })100 L (321)0(})16(389)100 L (322)0(/* Advance to next element */)16(390 dir = c->qid.path&CHDIR;)100 L (323 next:)0(391)100 L (324)0(c->uri++;)16(392 if\(dir\) {)100 L (325)0(mount = mount->next;)16(393)100(n -= n%DIRLEN;)116 L (326)0(if\(mount == nil\))16(394)100(if\(c->offset%DIRLEN || n==0\))116 L (327)0(break;)24(395)100(error\(Etoosmall\);)124 L (328)0(c->offset = 0;)16(396 })100 L (329 })0(397)100 L (330 runlock\(&m->lock\);)0(398 if\(dir && c->mh\))100 L (331 return 0;)0(399)100(n = unionread\(c, \(void*\)arg[1], n\);)116 L (332 })0(400 else)100 L (333)0(401)100(n = devtab[c->type]->read\(c, \(void*\)arg[1], n, c->offset\);)116 L (334 long)0(402)100 L (335 sysread9p\(ulong *arg\))0(403 lock\(c\);)100 L (336 {)0(404 c->offset += n;)100 L (337 int dir;)0(405 unlock\(c\);)100 L (338 long n;)0(406)100 L (339 Chan *c;)0(407 poperror\(\);)100 L (340)0(408 cclose\(c\);)100 L cleartomark showpage saveobj restore %%EndPage: 211 211 %%Page: 212 212 /saveobj save def mark 212 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 4)l ()l ()l (409)0(477 poperror\(\);)100 L (410 return n;)0(478 cclose\(c\);)100 L (411 })0(479)100 L (412)0(480 return m;)100 L (413 long)0(481 })100 L (414 syswrite9p\(ulong *arg\))0(482)100 L (415 {)0(483 static void)100 L (416 Chan *c;)0(484 sseek\(ulong *arg\))100 L (417 long n;)0(485 {)100 L (418)0(486 Chan *c;)100 L (419 validaddr\(arg[1], arg[2], 0\);)0(487 char buf[DIRLEN];)100 L (420 c = fdtochan\(arg[0], OWRITE, 1, 1\);)0(488 Dir dir;)100 L (421 if\(waserror\(\)\) {)0(489 vlong off;)100 L (422)0(cclose\(c\);)16(490 union {)100 L (423)0(nexterror\(\);)16(491)100(vlong v;)116 L (424 })0(492)100(ulong u[2];)116 L (425)0(493 } o;)100 L (426 if\(c->qid.path & CHDIR\))0(494)100 L (427)0(error\(Eisdir\);)16(495 c = fdtochan\(arg[1], -1, 1, 1\);)100 L (428)0(496 if\(waserror\(\)\){)100 L (429 if\(devtab[c->type]->dc != L'M'\))0(497)100(cclose\(c\);)116 L (430)0(n = devtab[c->type]->write\(c, \(void*\)arg[1], arg[2], c->offset\);)16(498)100(nexterror\(\);)116 L (431 else)0(499 })100 L (432)0(n = mntwrite9p\(c, \(void*\)arg[1], arg[2], c->offset\);)16(500 if\(c->qid.path & CHDIR\))100 L (433 lock\(c\);)0(501)100(error\(Eisdir\);)116 L (434 c->offset += n;)0(502)100 L (435 unlock\(c\);)0(503 if\(devtab[c->type]->dc == '|'\))100 L (436)0(504)100(error\(Eisstream\);)116 L (437 poperror\(\);)0(505)100 L (438 cclose\(c\);)0(506 off = 0;)100 L (439)0(507 o.u[0] = arg[2];)100 L (440 return n;)0(508 o.u[1] = arg[3];)100 L (441 })0(509 switch\(arg[4]\){)100 L (442)0(510 case 0:)100 L (443 long)0(511)100(off = o.v;)116 L (444 syswrite\(ulong *arg\))0(512)100(c->offset = off;)116 L (445 {)0(513)100(break;)116 L (446 Chan *c;)0(514)100 L (447 long m, n;)0(515 case 1:)100 L (448 uvlong oo;)0(516)100(lock\(c\);)116(/* lock for read/write update */)132 L (449)0(517)100(off = o.v + c->offset;)116 L (450 validaddr\(arg[1], arg[2], 0\);)0(518)100(c->offset = off;)116 L (451 n = arg[2];)0(519)100(unlock\(c\);)116 L (452 c = fdtochan\(arg[0], OWRITE, 1, 1\);)0(520)100(break;)116 L (453 if\(waserror\(\)\) {)0(521)100 L (454)0(cclose\(c\);)16(522 case 2:)100 L (455)0(lock\(c\);)16(523)100(devtab[c->type]->stat\(c, buf\);)116 L (456)0(c->offset -= n;)16(524)100(convM2D\(buf, &dir\);)116 L (457)0(unlock\(c\);)16(525)100(off = dir.length + o.v;)116 L (458)0(nexterror\(\);)16(526)100(c->offset = off;)116 L (459 })0(527)100(break;)116 L (460)0(528 })100 L (461 if\(c->qid.path & CHDIR\))0(529 *\(vlong*\)arg[0] = off;)100 L (462)0(error\(Eisdir\);)16(530 c->uri = 0;)100 L (463)0(531 cclose\(c\);)100 L (464 lock\(c\);)0(532 poperror\(\);)100 L (465 oo = c->offset;)0(533 })100 L (466 c->offset += n;)0(534)100 L (467 unlock\(c\);)0(535 long)100 L (468)0(536 sysseek\(ulong *arg\))100 L (469 m = devtab[c->type]->write\(c, \(void*\)arg[1], n, oo\);)0(537 {)100 L (470)0(538 validaddr\(arg[0], BY2V, 1\);)100 L (471 if\(m < n\){)0(539 sseek\(arg\);)100 L (472)0(lock\(c\);)16(540 return 0;)100 L (473)0(c->offset -= n - m;)16(541 })100 L (474)0(unlock\(c\);)16(542)100 L (475 })0(543 long)100 L (476)0(544 sysoseek\(ulong *arg\))100 L cleartomark showpage saveobj restore %%EndPage: 212 212 %%Page: 213 213 /saveobj save def mark 213 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 5)l ()l ()l (545 {)0(613 bindmount\(ulong *arg, int ismount\))100 L (546 union {)0(614 {)100 L (547)0(vlong v;)16(615 ulong flag;)100 L (548)0(ulong u[2];)16(616 int fd, ret;)100 L (549 } o;)0(617 Chan *c0, *c1, *bc;)100 L (550 ulong a[5];)0(618 struct{)100 L (551)0(619)100(Chan *chan;)116 L (552 o.v = arg[1];)0(620)100(char *spec;)116 L (553 a[0] = \(ulong\)&o.v;)0(621)100(int flags;)116 L (554 a[1] = arg[0];)0(622 }bogus;)100 L (555 a[2] = o.u[0];)0(623)100 L (556 a[3] = o.u[1];)0(624 flag = arg[2];)100 L (557 a[4] = arg[2];)0(625 fd = arg[0];)100 L (558 sseek\(a\);)0(626 if\(flag>MMASK || \(flag&MORDER\)==\(MBEFORE|MAFTER\)\))100 L (559 return o.v;)0(627)100(error\(Ebadarg\);)116 L (560 })0(628)100 L (561)0(629 bogus.flags = flag & MCACHE;)100 L (562 long)0(630)100 L (563 sysfstat\(ulong *arg\))0(631 if\(ismount\){)100 L (564 {)0(632)100(if\(up->pgrp->noattach\))116 L (565 Chan *c;)0(633)100(error\(Enoattach\);)124 L (566)0(634)100 L (567 validaddr\(arg[1], DIRLEN, 1\);)0(635)100(bc = fdtochan\(fd, ORDWR, 0, 1\);)116 L (568 evenaddr\(arg[1]\);)0(636)100(if\(waserror\(\)\) {)116 L (569 c = fdtochan\(arg[0], -1, 0, 1\);)0(637)100(cclose\(bc\);)124 L (570 if\(waserror\(\)\) {)0(638)100(nexterror\(\);)124 L (571)0(cclose\(c\);)16(639)100(})116 L (572)0(nexterror\(\);)16(640)100(bogus.chan = bc;)116 L (573 })0(641)100 L (574 devtab[c->type]->stat\(c, \(char*\)arg[1]\);)0(642)100(validaddr\(arg[3], 1, 0\);)116 L (575 poperror\(\);)0(643)100(if\(vmemchr\(\(char*\)arg[3], '\\0', NAMELEN\) == 0\))116 L (576 cclose\(c\);)0(644)100(error\(Ebadarg\);)124 L (577 return 0;)0(645)100 L (578 })0(646)100(bogus.spec = \(char*\)arg[3];)116 L (579)0(647)100(if\(waserror\(\)\))116 L (580 long)0(648)100(error\(Ebadspec\);)124 L (581 sysstat\(ulong *arg\))0(649)100(nameok\(bogus.spec, 1\);)116 L (582 {)0(650)100(poperror\(\);)116 L (583 Chan *c;)0(651)100 L (584)0(652)100(ret = devno\('M', 0\);)116 L (585 validaddr\(arg[1], DIRLEN, 1\);)0(653)100(c0 = devtab[ret]->attach\(\(char*\)&bogus\);)116 L (586 evenaddr\(arg[1]\);)0(654)100 L (587 validaddr\(arg[0], 1, 0\);)0(655)100(poperror\(\);)116 L (588 c = namec\(\(char*\)arg[0], Aaccess, 0, 0\);)0(656)100(cclose\(bc\);)116 L (589 if\(waserror\(\)\){)0(657 })100 L (590)0(cclose\(c\);)16(658 else {)100 L (591)0(nexterror\(\);)16(659)100(bogus.spec = 0;)116 L (592 })0(660)100(validaddr\(arg[0], 1, 0\);)116 L (593 devtab[c->type]->stat\(c, \(char*\)arg[1]\);)0(661)100(c0 = namec\(\(char*\)arg[0], Aaccess, 0, 0\);)116 L (594 poperror\(\);)0(662 })100 L (595 cclose\(c\);)0(663)100 L (596 return 0;)0(664 if\(waserror\(\)\){)100 L (597 })0(665)100(cclose\(c0\);)116 L (598)0(666)100(nexterror\(\);)116 L (599 long)0(667 })100 L (600 syschdir\(ulong *arg\))0(668)100 L (601 {)0(669 validaddr\(arg[1], 1, 0\);)100 L (602 Chan *c;)0(670 c1 = namec\(\(char*\)arg[1], Amount, 0, 0\);)100 L (603)0(671 if\(waserror\(\)\){)100 L (604 validaddr\(arg[0], 1, 0\);)0(672)100(cclose\(c1\);)116 L (605)0(673)100(nexterror\(\);)116 L (606 c = namec\(\(char*\)arg[0], Atodir, 0, 0\);)0(674 })100 L (607 cclose\(up->dot\);)0(675)100 L (608 up->dot = c;)0(676 ret = cmount\(c0, c1, flag, bogus.spec\);)100 L (609 return 0;)0(677)100 L (610 })0(678 poperror\(\);)100 L (611)0(679 cclose\(c1\);)100 L (612 long)0(680 poperror\(\);)100 L cleartomark showpage saveobj restore %%EndPage: 213 213 %%Page: 214 214 /saveobj save def mark 214 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysfile.c Page 6)l ()l ()l (681 cclose\(c0\);)0(749 if\(fd < 0\))100 L (682 if\(ismount\))0(750)100(error\(Enofd\);)116 L (683)0(fdclose\(fd, 0\);)16(751 poperror\(\);)100 L (684 return ret;)0(752 return fd;)100 L (685 })0(753 })100 L (686)0(754)100 L (687 long)0(755 long)100 L (688 sysbind\(ulong *arg\))0(756 sysremove\(ulong *arg\))100 L (689 {)0(757 {)100 L (690 return bindmount\(arg, 0\);)0(758 Chan *c;)100 L (691 })0(759)100 L (692)0(760 validaddr\(arg[0], 1, 0\);)100 L (693 long)0(761 c = namec\(\(char*\)arg[0], Aaccess, 0, 0\);)100 L (694 sysmount\(ulong *arg\))0(762 if\(waserror\(\)\){)100 L (695 {)0(763)100(c->type = 0; /* see below */)116 L (696 return bindmount\(arg, 1\);)0(764)100(cclose\(c\);)116 L (697 })0(765)100(nexterror\(\);)116 L (698)0(766 })100 L (699 long)0(767 devtab[c->type]->remove\(c\);)100 L (700 sysunmount\(ulong *arg\))0(768 /*)100 L (701 {)0(769)100(* Remove clunks the fid, but we need to recover the Chan)109 L (702 Chan *cmount, *cmounted;)0(770)100(* so fake it up. rootclose\(\) is known to be a nop.)109 L (703)0(771)100(*/)109 L (704 cmounted = 0;)0(772 c->type = 0;)100 L (705)0(773 poperror\(\);)100 L (706 validaddr\(arg[1], 1, 0\);)0(774 cclose\(c\);)100 L (707 cmount = namec\(\(char *\)arg[1], Amount, 0, 0\);)0(775 return 0;)100 L (708)0(776 })100 L (709 if\(arg[0]\) {)0(777)100 L (710)0(if\(waserror\(\)\) {)16(778 long)100 L (711)0(cclose\(cmount\);)24(779 syswstat\(ulong *arg\))100 L (712)0(nexterror\(\);)24(780 {)100 L (713)0(})16(781 Chan *c;)100 L (714)0(validaddr\(arg[0], 1, 0\);)16(782)100 L (715)0(cmounted = namec\(\(char*\)arg[0], Aopen, OREAD, 0\);)16(783 validaddr\(arg[1], DIRLEN, 0\);)100 L (716)0(poperror\(\);)16(784 nameok\(\(char*\)arg[1], 0\);)100 L (717 })0(785 validaddr\(arg[0], 1, 0\);)100 L (718)0(786 c = namec\(\(char*\)arg[0], Aaccess, 0, 0\);)100 L (719 if\(waserror\(\)\) {)0(787 if\(waserror\(\)\){)100 L (720)0(cclose\(cmount\);)16(788)100(cclose\(c\);)116 L (721)0(if\(cmounted\))16(789)100(nexterror\(\);)116 L (722)0(cclose\(cmounted\);)24(790 })100 L (723)0(nexterror\(\);)16(791 devtab[c->type]->wstat\(c, \(char*\)arg[1]\);)100 L (724 })0(792 poperror\(\);)100 L (725)0(793 cclose\(c\);)100 L (726 cunmount\(cmount, cmounted\);)0(794 return 0;)100 L (727 cclose\(cmount\);)0(795 })100 L (728 if\(cmounted\))0(796)100 L (729)0(cclose\(cmounted\);)16(797 long)100 L (730 poperror\(\);)0(798 sysfwstat\(ulong *arg\))100 L (731 return 0;)0(799 {)100 L (732 })0(800 Chan *c;)100 L (733)0(801)100 L (734 long)0(802 validaddr\(arg[1], DIRLEN, 0\);)100 L (735 syscreate\(ulong *arg\))0(803 nameok\(\(char*\)arg[1], 0\);)100 L (736 {)0(804 c = fdtochan\(arg[0], -1, 1, 1\);)100 L (737 int fd;)0(805 if\(waserror\(\)\) {)100 L (738 Chan *c = 0;)0(806)100(cclose\(c\);)116 L (739)0(807)100(nexterror\(\);)116 L (740 openmode\(arg[1]\);)0(/* error check only */)32(808 })100 L (741 if\(waserror\(\)\) {)0(809 devtab[c->type]->wstat\(c, \(char*\)arg[1]\);)100 L (742)0(if\(c\))16(810 poperror\(\);)100 L (743)0(cclose\(c\);)24(811 cclose\(c\);)100 L (744)0(nexterror\(\);)16(812 return 0;)100 L (745 })0(813 })100 L (746 validaddr\(arg[0], 1, 0\);)l (747 c = namec\(\(char*\)arg[0], Acreate, arg[1], arg[2]\);)l (748 fd = newfd\(c\);)l cleartomark showpage saveobj restore %%EndPage: 214 214 %%Page: 215 215 /saveobj save def mark 215 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(up->egrp = smalloc\(sizeof\(Egrp\)\);)124 L (2 #include "../port/lib.h")0(70)100(up->egrp->ref = 1;)124 L (3 #include "mem.h")0(71)100(if\(flag & RFENVG\))124 L (4 #include "dat.h")0(72)100(envcpy\(up->egrp, oeg\);)132 L (5 #include "fns.h")0(73)100(closeegrp\(oeg\);)124 L (6 #include "../port/error.h")0(74)100(})116 L (7)0(75)100(if\(flag & RFNOTEG\))116 L (8 #include )0(76)100(up->noteid = incref\(¬eidalloc\);)124 L (9)0(77)100(return 0;)116 L (10 int)0(shargs\(char*, int, char**\);)16(78)100(})108 L (11)0(79)100 L (12 long)0(80)100(p = newproc\(\);)108 L (13 sysr1\(ulong *arg\))0(81)100 L (14 {)0(82)100(p->fpsave = up->fpsave;)108 L (15)0(print\("[%s %s %lud] r1 = %lud\\n", up->user, up->text, up->pid, arg[0]\);)8(83)100(p->scallnr = up->scallnr;)108 L (16)0(return 0;)8(84)100(p->s = up->s;)108 L (17 })0(85)100(p->nerrlab = 0;)108 L (18)0(86)100(p->slash = up->slash;)108 L (19 long)0(87)100(p->dot = up->dot;)108 L (20 sysrfork\(ulong *arg\))0(88)100(incref\(p->dot\);)108 L (21 {)0(89)100 L (22)0(Proc *p;)8(90)100(memmove\(p->note, up->note, sizeof\(p->note\)\);)108 L (23)0(int n, i;)8(91)100(p->nnote = up->nnote;)108 L (24)0(Fgrp *ofg;)8(92)100(p->notified = 0;)108 L (25)0(Pgrp *opg;)8(93)100(p->lastnote = up->lastnote;)108 L (26)0(Rgrp *org;)8(94)100(p->notify = up->notify;)108 L (27)0(Egrp *oeg;)8(95)100(p->ureg = up->ureg;)108 L (28)0(ulong pid, flag;)8(96)100(p->dbgreg = 0;)108 L (29)0(Mach *wm;)8(97)100 L (30)0(98)100(/* Make a new set of memory segments */)108 L (31)0(flag = arg[0];)8(99)100(n = flag & RFMEM;)108 L (32)0(/* Check flags before we commit */)8(100 qlock\(&p->seglock\);)100 L (33)0(if\(\(flag & \(RFFDG|RFCFDG\)\) == \(RFFDG|RFCFDG\)\))8(101 if\(waserror\(\)\){)100 L (34)0(error\(Ebadarg\);)16(102)100(qunlock\(&p->seglock\);)116 L (35)0(if\(\(flag & \(RFNAMEG|RFCNAMEG\)\) == \(RFNAMEG|RFCNAMEG\)\))8(103)100(nexterror\(\);)116 L (36)0(error\(Ebadarg\);)16(104 })100 L (37)0(if\(\(flag & \(RFENVG|RFCENVG\)\) == \(RFENVG|RFCENVG\)\))8(105 for\(i = 0; i < NSEG; i++\))100 L (38)0(error\(Ebadarg\);)16(106)100(if\(up->seg[i]\))116 L (39)0(107)100(p->seg[i] = dupseg\(up->seg, i, n\);)124 L (40)0(if\(\(flag&RFPROC\) == 0\) {)8(108 qunlock\(&p->seglock\);)100 L (41)0(if\(flag & \(RFMEM|RFNOWAIT\)\))16(109 poperror\(\);)100 L (42)0(error\(Ebadarg\);)24(110)100 L (43)0(if\(flag & \(RFFDG|RFCFDG\)\) {)16(111 /* File descriptors */)100 L (44)0(ofg = up->fgrp;)24(112 if\(flag & \(RFFDG|RFCFDG\)\) {)100 L (45)0(if\(flag & RFFDG\))24(113)100(if\(flag & RFFDG\))116 L (46)0(up->fgrp = dupfgrp\(ofg\);)32(114)100(p->fgrp = dupfgrp\(up->fgrp\);)124 L (47)0(else)24(115)100(else)116 L (48)0(up->fgrp = dupfgrp\(nil\);)32(116)100(p->fgrp = dupfgrp\(nil\);)124 L (49)0(closefgrp\(ofg\);)24(117 })100 L (50)0(})16(118 else {)100 L (51)0(if\(flag & \(RFNAMEG|RFCNAMEG\)\) {)16(119)100(p->fgrp = up->fgrp;)116 L (52)0(opg = up->pgrp;)24(120)100(incref\(p->fgrp\);)116 L (53)0(up->pgrp = newpgrp\(\);)24(121 })100 L (54)0(if\(flag & RFNAMEG\))24(122)100 L (55)0(pgrpcpy\(up->pgrp, opg\);)32(123 /* Process groups */)100 L (56)0(/* inherit noattach */)24(124 if\(flag & \(RFNAMEG|RFCNAMEG\)\) {)100 L (57)0(up->pgrp->noattach = opg->noattach;)24(125)100(p->pgrp = newpgrp\(\);)116 L (58)0(closepgrp\(opg\);)24(126)100(if\(flag & RFNAMEG\))116 L (59)0(})16(127)100(pgrpcpy\(p->pgrp, up->pgrp\);)124 L (60)0(if\(flag & RFNOMNT\))16(128)100(/* inherit noattach */)116 L (61)0(up->pgrp->noattach = 1;)24(129)100(p->pgrp->noattach = up->pgrp->noattach;)116 L (62)0(if\(flag & RFREND\) {)16(130 })100 L (63)0(org = up->rgrp;)24(131 else {)100 L (64)0(up->rgrp = newrgrp\(\);)24(132)100(p->pgrp = up->pgrp;)116 L (65)0(closergrp\(org\);)24(133)100(incref\(p->pgrp\);)116 L (66)0(})16(134 })100 L (67)0(if\(flag & \(RFENVG|RFCENVG\)\) {)16(135 if\(flag & RFNOMNT\))100 L (68)0(oeg = up->egrp;)24(136)100(up->pgrp->noattach = 1;)116 L cleartomark showpage saveobj restore %%EndPage: 215 215 %%Page: 216 216 /saveobj save def mark 216 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 2)l ()l ()l (137)0(205 return \(cp[0]<<24\) | \(cp[1]<<16\) | \(cp[2]<<8\) | cp[3];)100 L (138 if\(flag & RFREND\))0(206 })100 L (139)0(p->rgrp = newrgrp\(\);)16(207)100 L (140 else {)0(208 long)100 L (141)0(incref\(up->rgrp\);)16(209 sysexec\(ulong *arg\))100 L (142)0(p->rgrp = up->rgrp;)16(210 {)100 L (143 })0(211 Segment *s, *ts;)100 L (144)0(212 ulong t, d, b;)100 L (145 /* Environment group */)0(213 int i;)100 L (146 if\(flag & \(RFENVG|RFCENVG\)\) {)0(214 Chan *tc;)100 L (147)0(p->egrp = smalloc\(sizeof\(Egrp\)\);)16(215 char **argv, **argp;)100 L (148)0(p->egrp->ref = 1;)16(216 char *a, *charp, *file;)100 L (149)0(if\(flag & RFENVG\))16(217 char *progarg[sizeof\(Exec\)/2+1], elem[NAMELEN];)100 L (150)0(envcpy\(p->egrp, up->egrp\);)24(218 ulong ssize, spage, nargs, nbytes, n, bssend;)100 L (151 })0(219 int indir;)100 L (152 else {)0(220 Exec exec;)100 L (153)0(p->egrp = up->egrp;)16(221 char line[sizeof\(Exec\)];)100 L (154)0(incref\(p->egrp\);)16(222 Fgrp *f;)100 L (155 })0(223 Image *img;)100 L (156 p->hang = up->hang;)0(224 ulong magic, text, entry, data, bss;)100 L (157 p->procmode = up->procmode;)0(225)100 L (158)0(226 validaddr\(arg[0], 1, 0\);)100 L (159 /* Craft a return frame which will cause the child to pop out of)0(227 file = \(char*\)arg[0];)100 L (160)0(* the scheduler in user mode with the return register zero)9(228 indir = 0;)100 L (161)0(*/)9(229 for\(;;\){)100 L (162 forkchild\(p, up->dbgreg\);)0(230)100(tc = namec\(file, Aopen, OEXEC, 0\);)116 L (163)0(231)100(if\(waserror\(\)\){)116 L (164 p->parent = up;)0(232)100(cclose\(tc\);)124 L (165 p->parentpid = up->pid;)0(233)100(nexterror\(\);)124 L (166 if\(flag&RFNOWAIT\))0(234)100(})116 L (167)0(p->parentpid = 1;)16(235)100(if\(!indir\))116 L (168 else {)0(236)100(strcpy\(elem, up->elem\);)124 L (169)0(lock\(&up->exl\);)16(237)100 L (170)0(up->nchild++;)16(238)100(n = devtab[tc->type]->read\(tc, &exec, sizeof\(Exec\), 0\);)116 L (171)0(unlock\(&up->exl\);)16(239)100(if\(n < 2\))116 L (172 })0(240)100(error\(Ebadexec\);)124 L (173 if\(\(flag&RFNOTEG\) == 0\))0(241)100(magic = l2be\(exec.magic\);)116 L (174)0(p->noteid = up->noteid;)16(242)100(text = l2be\(exec.text\);)116 L (175)0(243)100(entry = l2be\(exec.entry\);)116 L (176 p->fpstate = up->fpstate;)0(244)100(if\(n==sizeof\(Exec\) && \(magic == AOUT_MAGIC\)\){)116 L (177 pid = p->pid;)0(245)100(if\(\(text&KZERO\))124 L (178 memset\(p->time, 0, sizeof\(p->time\)\);)0(246)100(|| entry < UTZERO+sizeof\(Exec\))124 L (179 p->time[TReal] = MACHP\(0\)->ticks;)0(247)100(|| entry >= UTZERO+sizeof\(Exec\)+text\))124 L (180 memmove\(p->text, up->text, NAMELEN\);)0(248)100(error\(Ebadexec\);)132 L (181 memmove\(p->user, up->user, NAMELEN\);)0(249)100(break; /* for binary */)124 L (182 /*)0(250)100(})116 L (183)0(* since the bss/data segments are now shareable,)9(251)100 L (184)0(* any mmu info about this process is now stale)9(252)100(/*)116 L (185)0(* \(i.e. has bad properties\) and has to be discarded.)9(253)100(* Process #! /bin/sh args ...)117 L (186)0(*/)9(254)100(*/)117 L (187 flushmmu\(\);)0(255)100(memmove\(line, &exec, sizeof\(Exec\)\);)116 L (188 p->priority = up->priority;)0(256)100(if\(indir || line[0]!='#' || line[1]!='!'\))116 L (189 p->basepri = up->basepri;)0(257)100(error\(Ebadexec\);)124 L (190 p->mp = up->mp;)0(258)100(n = shargs\(line, n, progarg\);)116 L (191 wm = up->wired;)0(259)100(if\(n == 0\))116 L (192 if\(wm\))0(260)100(error\(Ebadexec\);)124 L (193)0(procwired\(p, wm->machno\);)16(261)100(indir = 1;)116 L (194 ready\(p\);)0(262)100(/*)116 L (195 sched\(\);)0(263)100(* First arg becomes complete file name)117 L (196 return pid;)0(264)100(*/)117 L (197 })0(265)100(progarg[n++] = file;)116 L (198)0(266)100(progarg[n] = 0;)116 L (199 static ulong)0(267)100(validaddr\(arg[1], BY2WD, 1\);)116 L (200 l2be\(long l\))0(268)100(arg[1] += BY2WD;)116 L (201 {)0(269)100(file = progarg[0];)116 L (202 uchar *cp;)0(270)100(progarg[0] = elem;)116 L (203)0(271)100(poperror\(\);)116 L (204 cp = \(uchar*\)&l;)0(272)100(cclose\(tc\);)116 L cleartomark showpage saveobj restore %%EndPage: 216 216 %%Page: 217 217 /saveobj save def mark 217 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 3)l ()l ()l (273 })0(341 for\(i=0; itext, elem, NAMELEN\);)100 L (285)0(* Args: pass 1: count)9(353)100 L (286)0(*/)9(354 /*)100 L (287 nbytes = BY2WD;)0(/* hole for profiling clock at top of stack */)32(355)100(* Committed.)109 L (288 nargs = 0;)0(356)100(* Free old memory.)109 L (289 if\(indir\){)0(357)100(* Special segments are maintained across exec)109 L (290)0(argp = progarg;)16(358)100(*/)109 L (291)0(while\(*argp\){)16(359 for\(i = SSEG; i <= BSEG; i++\) {)100 L (292)0(a = *argp++;)24(360)100(putseg\(up->seg[i]\);)116 L (293)0(nbytes += strlen\(a\) + 1;)24(361)100(/* prevent a second free if we have an error */)116 L (294)0(nargs++;)24(362)100(up->seg[i] = 0;)116 L (295)0(})16(363 })100 L (296 })0(364 for\(i = BSEG+1; i < NSEG; i++\) {)100 L (297 evenaddr\(arg[1]\);)0(365)100(s = up->seg[i];)116 L (298 argp = \(char**\)arg[1];)0(366)100(if\(s != 0 && \(s->type&SG_CEXEC\)\) {)116 L (299 validaddr\(\(ulong\)argp, BY2WD, 0\);)0(367)100(putseg\(s\);)124 L (300 while\(*argp\){)0(368)100(up->seg[i] = 0;)124 L (301)0(a = *argp++;)16(369)100(})116 L (302)0(if\(\(\(ulong\)argp&\(BY2PG-1\)\) < BY2WD\))16(370 })100 L (303)0(validaddr\(\(ulong\)argp, BY2WD, 0\);)24(371)100 L (304)0(validaddr\(\(ulong\)a, 1, 0\);)16(372 /*)100 L (305)0(nbytes += \(vmemchr\(a, 0, 0x7FFFFFFF\) - a\) + 1;)16(373)100(* Close on exec)109 L (306)0(nargs++;)16(374)100(*/)109 L (307 })0(375 f = up->fgrp;)100 L (308 ssize = BY2WD*\(nargs+1\) + \(\(nbytes+\(BY2WD-1\)\) & ~\(BY2WD-1\)\);)0(376 for\(i=0; i<=f->maxfd; i++\))100 L (309)0(377)100(fdclose\(i, CCEXEC\);)116 L (310 /*)0(378)100 L (311)0(* 8-byte align SP for those \(e.g. sparc\) that need it.)9(379 /* Text. Shared. Attaches to cache image if possible */)100 L (312)0(* execregs\(\) will subtract another 4 bytes for argc.)9(380 /* attachimage returns a locked cache image */)100 L (313)0(*/)9(381 img = attachimage\(SG_TEXT|SG_RONLY, tc, UTZERO, \(t-UTZERO\)>>PGSHIFT\);)100 L (314 if\(\(ssize+4\) & 7\))0(382 ts = img->s;)100 L (315)0(ssize += 4;)16(383 up->seg[TSEG] = ts;)100 L (316 spage = \(ssize+\(BY2PG-1\)\) >> PGSHIFT;)0(384 ts->flushme = 1;)100 L (317)0(385 ts->fstart = 0;)100 L (318 /*)0(386 ts->flen = sizeof\(Exec\)+text;)100 L (319)0(* Build the stack segment, putting it in kernel virtual for the moment)9(387 unlock\(img\);)100 L (320)0(*/)9(388)100 L (321 if\(spage > TSTKSIZ\))0(389 /* Data. Shared. */)100 L (322)0(error\(Enovmem\);)16(390 s = newseg\(SG_DATA, t, \(d-t\)>>PGSHIFT\);)100 L (323)0(391 up->seg[DSEG] = s;)100 L (324 qlock\(&up->seglock\);)0(392)100 L (325 if\(waserror\(\)\){)0(393 /* Attached by hand */)100 L (326)0(qunlock\(&up->seglock\);)16(394 incref\(img\);)100 L (327)0(nexterror\(\);)16(395 s->image = img;)100 L (328 })0(396 s->fstart = ts->fstart+ts->flen;)100 L (329 up->seg[ESEG] = newseg\(SG_STACK, TSTKTOP-USTKSIZE, USTKSIZE/BY2PG\);)0(397 s->flen = data;)100 L (330)0(398)100 L (331 /*)0(399 /* BSS. Zero fill on demand */)100 L (332)0(* Args: pass 2: assemble; the pages will be faulted in)9(400 up->seg[BSEG] = newseg\(SG_BSS, d, \(b-d\)>>PGSHIFT\);)100 L (333)0(*/)9(401)100 L (334 argv = \(char**\)\(TSTKTOP - ssize\);)0(402 /*)100 L (335 charp = \(char*\)\(TSTKTOP - nbytes\);)0(403)100(* Move the stack)109 L (336 if\(indir\))0(404)100(*/)109 L (337)0(argp = progarg;)16(405 s = up->seg[ESEG];)100 L (338 else)0(406 up->seg[ESEG] = 0;)100 L (339)0(argp = \(char**\)arg[1];)16(407 up->seg[SSEG] = s;)100 L (340)0(408 qunlock\(&up->seglock\);)100 L cleartomark showpage saveobj restore %%EndPage: 217 217 %%Page: 218 218 /saveobj save def mark 218 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 4)l ()l ()l (409 poperror\(\);)0(477 long)100 L (410 s->base = USTKTOP-USTKSIZE;)0(478 syssleep\(ulong *arg\))100 L (411 s->top = USTKTOP;)0(479 {)100 L (412 relocateseg\(s, USTKTOP-TSTKTOP\);)0(480)100 L (413)0(481 int n;)100 L (414 /*)0(482)100 L (415)0(* '/' processes are higher priority \(hack to make /ip more responsive\).)9(483 n = arg[0];)100 L (416)0(*/)9(484 if\(n <= 0\) {)100 L (417 if\(devtab[tc->type]->dc == L'/'\))0(485)100(up->priority = 0;)116 L (418)0(up->basepri = PriRoot;)16(486)100(sched\(\);)116 L (419 up->priority = up->basepri;)0(487)100(return 0;)116 L (420 poperror\(\);)0(488 })100 L (421 cclose\(tc\);)0(489 if\(n < TK2MS\(1\)\))100 L (422)0(490)100(n = TK2MS\(1\);)116 L (423 /*)0(491 tsleep\(&up->sleep, return0, 0, n\);)100 L (424)0(* At this point, the mmu contains info about the old address)9(492 return 0;)100 L (425)0(* space and needs to be flushed)9(493 })100 L (426)0(*/)9(494)100 L (427 flushmmu\(\);)0(495 long)100 L (428 qlock\(&up->debug\);)0(496 sysalarm\(ulong *arg\))100 L (429 up->nnote = 0;)0(497 {)100 L (430 up->notify = 0;)0(498 return procalarm\(arg[0]\);)100 L (431 up->notified = 0;)0(499 })100 L (432 procsetup\(up\);)0(500)100 L (433 qunlock\(&up->debug\);)0(501 long)100 L (434 if\(up->hang\))0(502 sysexits\(ulong *arg\))100 L (435)0(up->procctl = Proc_stopme;)16(503 {)100 L (436)0(504 char *status;)100 L (437 return execregs\(entry, ssize, nargs\);)0(505 char *inval = "invalid exit string";)100 L (438 })0(506 char buf[ERRLEN];)100 L (439)0(507)100 L (440 int)0(508 status = \(char*\)arg[0];)100 L (441 shargs\(char *s, int n, char **ap\))0(509 if\(status\){)100 L (442 {)0(510)100(if\(waserror\(\)\))116 L (443 int i;)0(511)100(status = inval;)124 L (444)0(512)100(else{)116 L (445 s += 2;)0(513)100(validaddr\(\(ulong\)status, 1, 0\);)124 L (446 n -= 2;)0(/* skip #! */)24(514)100(if\(vmemchr\(status, 0, ERRLEN\) == 0\){)124 L (447 for\(i=0; s[i]!='\\n'; i++\))0(515)100(memmove\(buf, status, ERRLEN\);)132 L (448)0(if\(i == n-1\))16(516)100(buf[ERRLEN-1] = 0;)132 L (449)0(return 0;)24(517)100(status = buf;)132 L (450 s[i] = 0;)0(518)100(})124 L (451 *ap = 0;)0(519)100(})116 L (452 i = 0;)0(520)100(poperror\(\);)116 L (453 for\(;;\) {)0(521)100 L (454)0(while\(*s==' ' || *s=='\\t'\))16(522 })100 L (455)0(s++;)24(523 pexit\(status, 1\);)100 L (456)0(if\(*s == 0\))16(524 return 0;)100(/* not reached */)132 L (457)0(break;)24(525 })100 L (458)0(i++;)16(526)100 L (459)0(*ap++ = s;)16(527 long)100 L (460)0(*ap = 0;)16(528 syswait\(ulong *arg\))100 L (461)0(while\(*s && *s!=' ' && *s!='\\t'\))16(529 {)100 L (462)0(s++;)24(530 if\(arg[0]\){)100 L (463)0(if\(*s == 0\))16(531)100(validaddr\(arg[0], sizeof\(Waitmsg\), 1\);)116 L (464)0(break;)24(532)100(evenaddr\(arg[0]\);)116 L (465)0(else)16(533 })100 L (466)0(*s++ = 0;)24(534 return pwait\(\(Waitmsg*\)arg[0]\);)100 L (467 })0(535 })100 L (468 return i;)0(536)100 L (469 })0(537 long)100 L (470)0(538 sysdeath\(ulong*\))100 L (471 int)0(539 {)100 L (472 return0\(void*\))0(540 pprint\("deprecated system call\\n"\);)100 L (473 {)0(541 pexit\("Suicide", 0\);)100 L (474 return 0;)0(542 return 0;)100(/* not reached */)124 L (475 })0(543 })100 L (476)0(544)100 L cleartomark showpage saveobj restore %%EndPage: 218 218 %%Page: 219 219 /saveobj save def mark 219 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 5)l ()l ()l (545 void)0(613)100 L (546 werrstr\(char *fmt, ...\))0(614 long)100 L (547 {)0(615 syssegattach\(ulong *arg\))100 L (548 va_list va;)0(616 {)100 L (549)0(617 return segattach\(up, arg[0], \(char*\)arg[1], arg[2], arg[3]\);)100 L (550 if\(up == nil\))0(618 })100 L (551)0(return;)16(619)100 L (552)0(620 long)100 L (553 va_start\(va, fmt\);)0(621 syssegdetach\(ulong *arg\))100 L (554 doprint\(up->error, up->error+ERRLEN, fmt, va\);)0(622 {)100 L (555 va_end\(va\);)0(623 int i;)100 L (556 })0(624 ulong addr;)100 L (557)0(625 Segment *s;)100 L (558 long)0(626)100 L (559 syserrstr\(ulong *arg\))0(627 qlock\(&up->seglock\);)100 L (560 {)0(628 if\(waserror\(\)\){)100 L (561 char *e, tmp[ERRLEN];)0(629)100(qunlock\(&up->seglock\);)116 L (562)0(630)100(nexterror\(\);)116 L (563 validaddr\(arg[0], ERRLEN, 1\);)0(631 })100 L (564 e = \(char*\)arg[0];)0(632)100 L (565 memmove\(tmp, e, ERRLEN\);)0(633 s = 0;)100 L (566 memmove\(e, up->error, ERRLEN\);)0(634 addr = arg[0];)100 L (567 memmove\(up->error, tmp, ERRLEN\);)0(635 for\(i = 0; i < NSEG; i++\))100 L (568 return 0;)0(636)100(if\(s = up->seg[i]\) {)116 L (569 })0(637)100(qlock\(&s->lk\);)124 L (570)0(638)100(if\(\(addr >= s->base && addr < s->top\) ||)124 L (571 long)0(639)100(\(s->top == s->base && addr == s->base\)\))127 L (572 sysnotify\(ulong *arg\))0(640)100(goto found;)132 L (573 {)0(641)100(qunlock\(&s->lk\);)124 L (574 if\(arg[0] != 0\))0(642)100(})116 L (575)0(validaddr\(arg[0], sizeof\(ulong\), 0\);)16(643)100 L (576 up->notify = \(int\(*\)\(void*, char*\)\)\(arg[0]\);)0(644 error\(Ebadarg\);)100 L (577 return 0;)0(645)100 L (578 })0(646 found:)100 L (579)0(647 /* Check we are not detaching the current stack segment */)100 L (580 long)0(648 if\(\(ulong\)arg >= s->base && \(ulong\)arg < s->top\) {)100 L (581 sysnoted\(ulong *arg\))0(649)100(qunlock\(&s->lk\);)116 L (582 {)0(650)100(error\(Ebadarg\);)116 L (583 if\(arg[0]!=NRSTR && !up->notified\))0(651 })100 L (584)0(error\(Egreg\);)16(652 up->seg[i] = 0;)100 L (585 return 0;)0(653 qunlock\(&s->lk\);)100 L (586 })0(654 putseg\(s\);)100 L (587)0(655 qunlock\(&up->seglock\);)100 L (588 long)0(656 poperror\(\);)100 L (589 syssegbrk\(ulong *arg\))0(657)100 L (590 {)0(658 /* Ensure we flush any entries from the lost segment */)100 L (591 int i;)0(659 flushmmu\(\);)100 L (592 ulong addr;)0(660 return 0;)100 L (593 Segment *s;)0(661 })100 L (594)0(662)100 L (595 addr = arg[0];)0(663 long)100 L (596 for\(i = 0; i < NSEG; i++\) {)0(664 syssegfree\(ulong *arg\))100 L (597)0(s = up->seg[i];)16(665 {)100 L (598)0(if\(s == 0 || addr < s->base || addr >= s->top\))16(666 Segment *s;)100 L (599)0(continue;)24(667 ulong from, pages;)100 L (600)0(switch\(s->type&SG_TYPE\) {)16(668)100 L (601)0(case SG_TEXT:)16(669 from = PGROUND\(arg[0]\);)100 L (602)0(case SG_DATA:)16(670 s = seg\(up, from, 1\);)100 L (603)0(case SG_STACK:)16(671 if\(s == 0\))100 L (604)0(error\(Ebadarg\);)24(672)100(error\(Ebadarg\);)116 L (605)0(default:)16(673)100 L (606)0(return ibrk\(arg[1], i\);)24(674 pages = \(arg[1]+BY2PG-1\)/BY2PG;)100 L (607)0(})16(675)100 L (608 })0(676 if\(from+pages*BY2PG > s->top\) {)100 L (609)0(677)100(qunlock\(&s->lk\);)116 L (610 error\(Ebadarg\);)0(678)100(error\(Ebadarg\);)116 L (611 return 0;)0(/* not reached */)32(679 })100 L (612 })0(680)100 L cleartomark showpage saveobj restore %%EndPage: 219 219 %%Page: 220 220 /saveobj save def mark 220 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/sysproc.c Page 6)l ()l ()l (681 mfreeseg\(s, from, pages\);)l (682 qunlock\(&s->lk\);)l (683 flushmmu\(\);)l (684)l (685 return 0;)l (686 })l (687)l (688 /* For binary compatibility */)l (689 long)l (690 sysbrk_\(ulong *arg\))l (691 {)l (692 return ibrk\(arg[0], BSEG\);)l (693 })l (694)l (695 long)l (696 sysrendezvous\(ulong *arg\))l (697 {)l (698 ulong tag;)l (699 ulong val;)l (700 Proc *p, **l;)l (701)l (702 tag = arg[0];)l (703 l = &REND\(up->rgrp, tag\);)l (704)l (705 lock\(up->rgrp\);)l (706 for\(p = *l; p; p = p->rendhash\) {)l (707)0(if\(p->rendtag == tag\) {)16 L (708)0(*l = p->rendhash;)24 L (709)0(val = p->rendval;)24 L (710)0(p->rendval = arg[1];)24 L (711)l (712)0(while\(p->mach != 0\))24 L (713)0(;)32 L (714)0(ready\(p\);)24 L (715)0(unlock\(up->rgrp\);)24 L (716)0(return val;)24 L (717)0(})16 L (718)0(l = &p->rendhash;)16 L (719 })l (720)l (721 /* Going to sleep here */)l (722 up->rendtag = tag;)l (723 up->rendval = arg[1];)l (724 up->rendhash = *l;)l (725 *l = up;)l (726 up->state = Rendezvous;)l (727 unlock\(up->rgrp\);)l (728)l (729 sched\(\);)l (730)l (731 return up->rendval;)l (732 })l cleartomark showpage saveobj restore %%EndPage: 220 220 %%Page: 221 221 /saveobj save def mark 221 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/taslock.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(})132 L (2 #include "../port/lib.h")0(70)100(})124 L (3 #include "mem.h")0(71)100(})116 L (4 #include "dat.h")0(72)100(if\(tas\(&l->key\) == 0\){)116 L (5 #include "fns.h")0(73)100(l->pc = pc;)124 L (6 #include "../port/error.h")0(74)100(l->p = up;)124 L (7)0(75)100(l->isilock = 0;)124 L (8 struct {)0(76)100(if\(cansched\){)124 L (9)0(ulong locks;)8(77)100(up->lockwait = 0;)132 L (10)0(ulong glare;)8(78)100(up->priority = oldpri;)132 L (11)0(ulong inglare;)8(79)100(})124 L (12 } lockstats;)0(80)100(return;)124 L (13)0(81)100(})116 L (14 void)0(82)100(})108 L (15 lockloop\(Lock *l, ulong pc\))0(83 })100 L (16 {)0(84)100 L (17)0(Proc *p;)8(85 void)100 L (18)0(86 ilock\(Lock *l\))100 L (19)0(p = l->p;)8(87 {)100 L (20)0(print\("lock loop key 0x%lux pc 0x%lux held by pc 0x%lux proc %lud\\n",)8(88)100(ulong x;)108 L (21)0(l->key, pc, l->pc, p ? p->pid : 0\);)16(89)100(ulong pc, oldpri;)108 L (22)0(dumpaproc\(up\);)8(90)100(int cansched;)108 L (23)0(if\(p != nil\))8(91)100 L (24)0(dumpaproc\(p\);)16(92)100(pc = getcallerpc\(&l\);)108 L (25)0(93)100(lockstats.locks++;)108 L (26)0(if\(up && up->state == Running && islo\(\)\))8(94)100 L (27)0(sched\(\);)16(95)100(x = splhi\(\);)108 L (28 })0(96)100(if\(tas\(&l->key\) == 0\){)108 L (29)0(97)100(l->sr = x;)116 L (30 void)0(98)100(l->pc = pc;)116 L (31 lock\(Lock *l\))0(99)100(l->p = up;)116 L (32 {)0(100)100(l->isilock = 1;)116 L (33)0(int i, cansched;)8(101)100(return;)116 L (34)0(ulong pc, oldpri;)8(102 })100 L (35)0(103)100 L (36)0(pc = getcallerpc\(&l\);)8(104 lockstats.glare++;)100 L (37)0(105 cansched = up != nil && up->state == Running;)100 L (38)0(lockstats.locks++;)8(106 if\(cansched\){)100 L (39)0(if\(tas\(&l->key\) == 0\){)8(107)100(oldpri = up->priority;)116 L (40)0(l->pc = pc;)16(108)100(up->lockwait = 1;)116 L (41)0(l->p = up;)16(109)100(up->priority = PriLock;)116 L (42)0(l->isilock = 0;)16(110 } else)100 L (43)0(return;)16(111)100(oldpri = 0;)116 L (44)0(})8(112 if\(conf.nmach < 2\))100 L (45)0(113)100(panic\("ilock: no way out: pc %uX\\n", pc\);)116 L (46)0(lockstats.glare++;)8(114)100 L (47)0(cansched = up != nil && up->state == Running;)8(115 for\(;;\){)100 L (48)0(if\(cansched\){)8(116)100(lockstats.inglare++;)116 L (49)0(oldpri = up->priority;)16(117)100(splx\(x\);)116 L (50)0(up->lockwait = 1;)16(118)100(while\(l->key\))116 L (51)0(up->priority = PriLock;)16(119)100(;)124 L (52)0(} else)8(120)100(x = splhi\(\);)116 L (53)0(oldpri = 0;)16(121)100(if\(tas\(&l->key\) == 0\){)116 L (54)0(122)100(l->sr = x;)124 L (55)0(for\(;;\){)8(123)100(l->pc = pc;)124 L (56)0(lockstats.inglare++;)16(124)100(l->p = up;)124 L (57)0(i = 0;)16(125)100(l->isilock = 1;)124 L (58)0(while\(l->key\){)16(126)100(if\(cansched\){)124 L (59)0(if\(conf.nmach < 2 && cansched\){)24(127)100(up->lockwait = 0;)132 L (60)0(if\(i++ > 1000\){)32(128)100(up->priority = oldpri;)132 L (61)0(i = 0;)40(129)100(})124 L (62)0(lockloop\(l, pc\);)40(130)100(return;)124 L (63)0(})32(131)100(})116 L (64)0(sched\(\);)32(132 })100 L (65)0(} else {)24(133 })100 L (66)0(if\(i++ > 100000000\){)32(134)100 L (67)0(i = 0;)40(135 int)100 L (68)0(lockloop\(l, pc\);)40(136 canlock\(Lock *l\))100 L cleartomark showpage saveobj restore %%EndPage: 221 221 %%Page: 222 222 /saveobj save def mark 222 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/taslock.c Page 2)l ()l ()l (137 {)l (138 if\(tas\(&l->key\)\))l (139)0(return 0;)16 L (140)l (141 l->pc = getcallerpc\(&l\);)l (142 l->p = up;)l (143 l->isilock = 0;)l (144 return 1;)l (145 })l (146)l (147 void)l (148 unlock\(Lock *l\))l (149 {)l (150)l (151 if\(l->key == 0\))l (152)0(print\("unlock: not locked: pc %luX\\n", getcallerpc\(&l\)\);)16 L (153 if\(l->isilock\))l (154)0(print\("unlock of ilock: pc %lux, held by %lux\\n", getcallerpc\(&l\), l->pc\);)16 L (155 l->pc = 0;)l (156 l->key = 0;)l (157 coherence\(\);)l (158 })l (159)l (160 void)l (161 iunlock\(Lock *l\))l (162 {)l (163 ulong sr;)l (164)l (165 if\(l->key == 0\))l (166)0(print\("iunlock: not locked: pc %luX\\n", getcallerpc\(&l\)\);)16 L (167 if\(!l->isilock\))l (168)0(print\("iunlock of lock: pc %lux, held by %lux\\n", getcallerpc\(&l\), l->pc\);)16 L (169)l (170 sr = l->sr;)l (171 l->pc = 0;)l (172 l->key = 0;)l (173 coherence\(\);)l (174)l (175 m->splpc = getcallerpc\(&l\);)l (176 splxpc\(sr\);)l (177 })l cleartomark showpage saveobj restore %%EndPage: 222 222 %%Page: 223 223 /saveobj save def mark 223 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/tod.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(if\(t >= 0\){)108 L (2 #include "../port/lib.h")0(70)100(tod.off = t;)116 L (3 #include "mem.h")0(71)100(tod.last = fastticks\(nil\);)116 L (4 #include "dat.h")0(72)100(tod.lasttime = 0;)116 L (5 #include "fns.h")0(73)100(tod.delta = 0;)116 L (6 #include "../port/error.h")0(74)100(tod.sstart = tod.send;)116 L (7)0(75)100(} else {)108 L (8 // compute nanosecond epoch time from the fastest ticking clock)0(76)100(if\(n <= 0\))116 L (9 // on the system. converting the time to nanoseconds requires)0(77)100(n = 1;)124 L (10 // the following formula)0(78)100(n *= HZ;)116 L (11 //)0(79)100(if\(delta < 0 && n > -delta\))116 L (12 //)0(t = \(\(\(1000000000<<31\)/f\)*ticks\)>>31)16(80)100(n = -delta;)124 L (13 //)0(81)100(if\(delta > 0 && n > delta\))116 L (14 // where)0(82)100(n = delta;)124 L (15 //)0(83)100(delta = delta/n;)116 L (16 //)0('f')16(is the clock frequency)32(84)100(tod.sstart = MACHP\(0\)->ticks;)116 L (17 //)0('ticks')16(are clock ticks)32(85)100(tod.send = tod.sstart + n;)116 L (18 //)0(86)100(tod.delta = delta;)116 L (19 // to avoid too much calculation in gettod\(\), we calculate)0(87)100(})108 L (20 //)0(88)100(iunlock\(&tod\);)108 L (21 //)0(mult = \(1000000000<<31\)/f)16(89 })100 L (22 //)0(90)100 L (23 // each time f is set. f is normally set by a user level)0(91 //)100 L (24 // program writing to /dev/fastclock.)0(92 // get time of day)100 L (25)0(93 //)100 L (26)0(94 vlong)100 L (27 // frequency of the tod clock)0(95 todget\(vlong *ticksp\))100 L (28 #define TODFREQ 1000000000LL)0(96 {)100 L (29)0(97)100(uvlong x;)108 L (30 struct {)0(98)100(vlong ticks, diff;)108 L (31)0(Lock;)8(99)100(ulong t;)108 L (32)0(vlong multiplier; // t = off + \(multiplier*ticks\)>>31)8(100)100 L (33)0(vlong hz;)8(// frequency of fast clock)32(101 if\(tod.hz == 0\))100 L (34)0(vlong last;)8(// last reading of fast clock)32(102)100(ticks = fastticks\(\(uvlong*\)&tod.hz\);)116 L (35)0(vlong off;)8(// offset from epoch to last)32(103 else)100 L (36)0(vlong lasttime;)8(// last return value from gettod)32(104)100(ticks = fastticks\(nil\);)116 L (37)0(vlong delta;)8(// add 'delta' each slow clock tick from sstart to send)32(105 diff = ticks - tod.last;)100 L (38)0(ulong sstart;)8(// ...)32(106)100 L (39)0(ulong send;)8(// ...)32(107 // convert to epoch)100 L (40 } tod;)0(108 x = \(diff * tod.multiplier\) >> 31;)100 L (41)0(109 x = x + tod.off;)100 L (42 void)0(110)100 L (43 todinit\(void\))0(111 if\(m->machno == 0\){)100 L (44 {)0(112)100(ilock\(&tod\);)116 L (45)0(fastticks\(\(uvlong*\)&tod.hz\);)8(113)100 L (46)0(todsetfreq\(tod.hz\);)8(114)100(// add in correction)116 L (47)0(addclock0link\(todfix\);)8(115)100(if\(tod.sstart != tod.send\){)116 L (48 })0(116)100(t = MACHP\(0\)->ticks;)124 L (49)0(117)100(if\(t >= tod.send\))124 L (50 //)0(118)100(t = tod.send;)132 L (51 // calculate multiplier)0(119)100(tod.off = tod.off + tod.delta*\(t - tod.sstart\);)124 L (52 //)0(120)100(tod.sstart = t;)124 L (53 void)0(121)100(})116 L (54 todsetfreq\(vlong f\))0(122)100 L (55 {)0(123)100(// protect against overflows)116 L (56)0(ilock\(&tod\);)8(124)100(if\(diff > tod.hz\){)116 L (57)0(tod.hz = f;)8(125)100(tod.last = ticks;)124 L (58)0(tod.multiplier = \(TODFREQ<<31\)/f;)8(126)100(tod.off = x;)124 L (59)0(iunlock\(&tod\);)8(127)100(})116 L (60 })0(128)100(iunlock\(&tod\);)116 L (61)0(129 })100 L (62 //)0(130)100 L (63 // Set the time of day struct)0(131 // time can't go backwards)100 L (64 //)0(132 if\(x < tod.lasttime\))100 L (65 void)0(133)100(x = tod.lasttime;)116 L (66 todset\(vlong t, vlong delta, int n\))0(134 else)100 L (67 {)0(135)100(tod.lasttime = x;)116 L (68)0(ilock\(&tod\);)8(136)100 L cleartomark showpage saveobj restore %%EndPage: 223 223 %%Page: 224 224 /saveobj save def mark 224 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/tod.c Page 2)l ()l ()l (137 if\(ticksp != nil\))l (138)0(*ticksp = ticks;)16 L (139)l (140 return x;)l (141 })l (142)l (143 //)l (144 // called every clock tick)l (145 //)l (146 void)l (147 todfix\(void\))l (148 {)l (149 static ulong last;)l (150)l (151 // once a second, make sure we don't overflow)l (152 if\(MACHP\(0\)->ticks - last >= HZ\){)l (153)0(last = MACHP\(0\)->ticks;)16 L (154)0(todget\(nil\);)16 L (155 })l (156 })l (157)l (158 long)l (159 seconds\(void\))l (160 {)l (161 vlong x;)l (162 int i;)l (163)l (164 x = todget\(nil\);)l (165 x = x/TODFREQ;)l (166 i = x;)l (167 return i;)l (168 })l cleartomark showpage saveobj restore %%EndPage: 224 224 %%Page: 225 225 /saveobj save def mark 225 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/xalloc.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(if\(np0 > conf.npage0\))108 L (2 #include "../port/lib.h")0(70)100(np0 = conf.npage0;)116 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72)100(palloc.p0 = conf.base0 + \(conf.npage0 - np0\)*BY2PG;)108 L (5 #include "fns.h")0(73)100(conf.npage0 -= np0;)108 L (6)0(74)100(xhole\(conf.base0, conf.npage0*BY2PG\);)108 L (7 #define datoff)0(\(\(ulong\)\(\(Xhdr*\)0\)->data\))32(75)100(conf.npage0 = conf.base0+\(conf.npage0*BY2PG\);)108 L (8)0(76)100 L (9 enum)0(77)100(palloc.np0 = np0;)108 L (10 {)0(78)100(palloc.np1 = np1;)108 L (11)0(Chunk)8(= 64*1024,)24(79)100(/* Save the bounds of kernel alloc memory for kernel mmu mapping */)108 L (12)0(Nhole)8(= 128,)24(80)100(conf.base0 = \(ulong\)KADDR\(conf.base0\);)108 L (13)0(Magichole)8(= 0x484F4C45,)24(/* HOLE */)56(81)100(conf.base1 = \(ulong\)KADDR\(conf.base1\);)108 L (14 };)0(82)100(conf.npage0 = \(ulong\)KADDR\(conf.npage0\);)108 L (15)0(83)100(conf.npage1 = \(ulong\)KADDR\(conf.npage1\);)108 L (16 typedef struct Hole Hole;)0(84 })100 L (17 typedef struct Xalloc Xalloc;)0(85)100 L (18 typedef struct Xhdr Xhdr;)0(86 void*)100 L (19)0(87 xspanalloc\(ulong size, int align, ulong span\))100 L (20 struct Hole)0(88 {)100 L (21 {)0(89)100(ulong a, v, t;)108 L (22)0(ulong addr;)8(90)100 L (23)0(ulong size;)8(91)100(a = \(ulong\)xalloc\(size+align+span\);)108 L (24)0(ulong top;)8(92)100(if\(a == 0\))108 L (25)0(Hole* link;)8(93)100(panic\("xspanalloc: %d %d %lux\\n", size, align, span\);)116 L (26 };)0(94)100 L (27)0(95)100(if\(span > 2\) {)108 L (28 struct Xhdr)0(96)100(v = \(a + span\) & ~\(span-1\);)116 L (29 {)0(97)100(t = v - a;)116 L (30)0(ulong size;)8(98)100(if\(t > 0\))116 L (31)0(ulong magix;)8(99)100(xhole\(PADDR\(a\), t\);)124 L (32)0(char data[1];)8(100)100(t = a + span - v;)116 L (33 };)0(101)100(if\(t > 0\))116 L (34)0(102)100(xhole\(PADDR\(v+size+align\), t\);)124 L (35 struct Xalloc)0(103 })100 L (36 {)0(104 else)100 L (37)0(Lock;)8(105)100(v = a;)116 L (38)0(Hole hole[Nhole];)8(106)100 L (39)0(Hole* flist;)8(107 if\(align > 1\))100 L (40)0(Hole* table;)8(108)100(v = \(v + align\) & ~\(align-1\);)116 L (41 };)0(109)100 L (42)0(110 return \(void*\)v;)100 L (43 static Xalloc xlists;)0(111 })100 L (44)0(112)100 L (45 void)0(113 void*)100 L (46 xinit\(void\))0(114 xallocz\(ulong size, int zero\))100 L (47 {)0(115 {)100 L (48)0(Hole *h, *eh;)8(116 Xhdr *p;)100 L (49)0(int upages, np0, np1;)8(117 Hole *h, **l;)100 L (50)0(118)100 L (51)0(eh = &xlists.hole[Nhole-1];)8(119 size += BY2V + sizeof\(Xhdr\);)100 L (52)0(for\(h = xlists.hole; h < eh; h++\))8(120 size &= ~\(BY2V-1\);)100 L (53)0(h->link = h+1;)16(121)100 L (54)0(122 ilock\(&xlists\);)100 L (55)0(xlists.flist = xlists.hole;)8(123 l = &xlists.table;)100 L (56)0(124 for\(h = *l; h; h = h->link\) {)100 L (57)0(upages = conf.upages;)8(125)100(if\(h->size >= size\) {)116 L (58)0(np1 = upages;)8(126)100(p = \(Xhdr*\)h->addr;)124 L (59)0(if\(np1 > conf.npage1\))8(127)100(h->addr += size;)124 L (60)0(np1 = conf.npage1;)16(128)100(h->size -= size;)124 L (61)0(129)100(if\(h->size == 0\) {)124 L (62)0(palloc.p1 = conf.base1 + \(conf.npage1 - np1\)*BY2PG;)8(130)100(*l = h->link;)132 L (63)0(conf.npage1 -= np1;)8(131)100(h->link = xlists.flist;)132 L (64)0(xhole\(conf.base1, conf.npage1*BY2PG\);)8(132)100(xlists.flist = h;)132 L (65)0(conf.npage1 = conf.base1+\(conf.npage1*BY2PG\);)8(133)100(})124 L (66)0(upages -= np1;)8(134)100(iunlock\(&xlists\);)124 L (67)0(135)100(p = KADDR\(p\);)124 L (68)0(np0 = upages;)8(136)100(p->magix = Magichole;)124 L cleartomark showpage saveobj restore %%EndPage: 225 225 %%Page: 226 226 /saveobj save def mark 226 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/9/port/xalloc.c Page 2)l ()l ()l (137)0(p->size = size;)24(205)100(iunlock\(&xlists\);)124 L (138)0(if\(zero\))24(206)100(return;)124 L (139)0(memset\(p->data, 0, size\);)32(207)100(})116 L (140)0(return p->data;)24(208)100(if\(h->addr > addr\))116 L (141)0(})16(209)100(break;)124 L (142)0(l = &h->link;)16(210)100(l = &h->link;)116 L (143 })0(211 })100 L (144 iunlock\(&xlists\);)0(212 if\(h && top == h->addr\) {)100 L (145 return nil;)0(213)100(h->addr -= size;)116 L (146 })0(214)100(h->size += size;)116 L (147)0(215)100(iunlock\(&xlists\);)116 L (148 void*)0(216)100(return;)116 L (149 xalloc\(ulong size\))0(217 })100 L (150 {)0(218)100 L (151 return xallocz\(size, 1\);)0(219 if\(xlists.flist == nil\) {)100 L (152 })0(220)100(iunlock\(&xlists\);)116 L (153)0(221)100(print\("xfree: no free holes, leaked %lud bytes\\n", size\);)116 L (154 void)0(222)100(return;)116 L (155 xfree\(void *p\))0(223 })100 L (156 {)0(224)100 L (157 Xhdr *x;)0(225 h = xlists.flist;)100 L (158)0(226 xlists.flist = h->link;)100 L (159 x = \(Xhdr*\)\(\(ulong\)p - datoff\);)0(227 h->addr = addr;)100 L (160 if\(x->magix != Magichole\) {)0(228 h->top = top;)100 L (161)0(xsummary\(\);)16(229 h->size = size;)100 L (162)0(panic\("xfree\(0x%lux\) 0x%lux!=0x%lux", p, Magichole, x->magix\);)16(230 h->link = *l;)100 L (163 })0(231 *l = h;)100 L (164 xhole\(PADDR\(x\), x->size\);)0(232 iunlock\(&xlists\);)100 L (165 })0(233 })100 L (166)0(234)100 L (167 int)0(235 void)100 L (168 xmerge\(void *vp, void *vq\))0(236 xsummary\(void\))100 L (169 {)0(237 {)100 L (170 Xhdr *p, *q;)0(238 int i;)100 L (171)0(239 Hole *h;)100 L (172 p = vp;)0(240)100 L (173 if\(\(uchar*\)vp+p->size == \(uchar*\)vq\) {)0(241 i = 0;)100 L (174)0(q = vq;)16(242 for\(h = xlists.flist; h; h = h->link\))100 L (175)0(p->size += q->size;)16(243)100(i++;)116 L (176)0(return 1;)16(244)100 L (177 })0(245 print\("%d holes free\\n", i\);)100 L (178 return 0;)0(246 i = 0;)100 L (179 })0(247 for\(h = xlists.table; h; h = h->link\) {)100 L (180)0(248)100(print\("%.8lux %.8lux %lud\\n", h->addr, h->top, h->size\);)116 L (181 void)0(249)100(i += h->size;)116 L (182 xhole\(ulong addr, ulong size\))0(250 })100 L (183 {)0(251 print\("%d bytes free\\n", i\);)100 L (184 ulong top;)0(252 })100 L (185 Hole *h, *c, **l;)l (186)l (187 if\(size == 0\))l (188)0(return;)16 L (189)l (190 top = addr + size;)l (191 ilock\(&xlists\);)l (192 l = &xlists.table;)l (193 for\(h = *l; h; h = h->link\) {)l (194)0(if\(h->top == addr\) {)16 L (195)0(h->size += size;)24 L (196)0(h->top = h->addr+h->size;)24 L (197)0(c = h->link;)24 L (198)0(if\(c && h->top == c->addr\) {)24 L (199)0(h->top += c->size;)32 L (200)0(h->size += c->size;)32 L (201)0(h->link = c->link;)32 L (202)0(c->link = xlists.flist;)32 L (203)0(xlists.flist = c;)32 L (204)0(})24 L cleartomark showpage saveobj restore %%EndPage: 226 226 %%Page: 227 227 /saveobj save def mark 227 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/boot.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(print\("gz..."\);)132 L (2 #include "lib.h")0(70)100(break;)132 L (3 #include "mem.h")0(71)100(})124 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73)100(print\("bad kernel format\\n"\);)124 L (6 #include "io.h")0(74)100(b->state = FAILED;)124 L (7)0(75)100(return FAIL;)124 L (8 static int)0(76)100 L (9 addbytes\(char **dbuf, char *edbuf, char **sbuf, char *esbuf\))0(77)100(case READTEXT:)116 L (10 {)0(78)100(ep = &b->exec;)124 L (11)0(int n;)8(79)100(b->state = READDATA;)124 L (12)0(80)100(b->bp = \(char*\)PGROUND\(GLLONG\(ep->entry\)+GLLONG\(ep->text\)\);)124 L (13)0(n = edbuf - *dbuf;)8(81)100(b->wp = b->bp;)124 L (14)0(if\(n <= 0\))8(82)100(b->ep = b->wp + GLLONG\(ep->data\);)124 L (15)0(return 0;)16(83)100(print\("+%ld", GLLONG\(ep->data\)\);)124 L (16)0(if\(n > esbuf - *sbuf\))8(84)100(break;)124 L (17)0(n = esbuf - *sbuf;)16(85)100 L (18)0(if\(n <= 0\))8(86)100(case READDATA:)116 L (19)0(return -1;)16(87)100(ep = &b->exec;)124 L (20)0(88)100(bss = GLLONG\(ep->bss\);)124 L (21)0(memmove\(*dbuf, *sbuf, n\);)8(89)100(print\("+%ld=%ld\\n",)124 L (22)0(*sbuf += n;)8(90)100(bss, GLLONG\(ep->text\)+GLLONG\(ep->data\)+bss\);)132 L (23)0(*dbuf += n;)8(91)100(b->state = TRYBOOT;)124 L (24)0(return edbuf - *dbuf;)8(92)100(return ENOUGH;)124 L (25 })0(93)100 L (26)0(94)100(case TRYBOOT:)116 L (27 int)0(95)100(case READGZIP:)116 L (28 bootpass\(Boot *b, void *vbuf, int nbuf\))0(96)100(return ENOUGH;)124 L (29 {)0(97)100 L (30)0(char *buf, *ebuf;)8(98)100(case READ9LOAD:)116 L (31)0(Exec *ep;)8(99)100(case INIT9LOAD:)116 L (32)0(ulong entry, data, text, bss;)8(100)100(panic\("9load"\);)124 L (33)0(101)100 L (34)0(if\(b->state == FAILED\))8(102)100(default:)116 L (35)0(return FAIL;)16(103)100(panic\("bootstate"\);)124 L (36)0(104)100(})116 L (37)0(if\(nbuf == 0\))8(105 })100 L (38)0(goto Endofinput;)16(106 return MORE;)100 L (39)0(107)100 L (40)0(buf = vbuf;)8(108)100 L (41)0(ebuf = buf+nbuf;)8(109 Endofinput:)100 L (42)0(while\(addbytes\(&b->wp, b->ep, &buf, ebuf\) == 0\) {)8(110 /* end of input */)100 L (43)0(switch\(b->state\) {)16(111 switch\(b->state\) {)100 L (44)0(case INITKERNEL:)16(112 case INITKERNEL:)100 L (45)0(b->state = READEXEC;)24(113 case READEXEC:)100 L (46)0(b->bp = \(char*\)&b->exec;)24(114 case READDATA:)100 L (47)0(b->wp = b->bp;)24(115 case READTEXT:)100 L (48)0(b->ep = b->bp+sizeof\(Exec\);)24(116)100(print\("premature EOF\\n"\);)116 L (49)0(break;)24(117)100(b->state = FAILED;)116 L (50)0(case READEXEC:)16(118)100(return FAIL;)116 L (51)0(ep = &b->exec;)24(119)100 L (52)0(if\(GLLONG\(ep->magic\) == I_MAGIC\) {)24(120 case TRYBOOT:)100 L (53)0(b->state = READTEXT;)32(121)100(entry = GLLONG\(b->exec.entry\);)116 L (54)0(b->bp = \(char*\)PADDR\(GLLONG\(ep->entry\)\);)32(122)100(print\("entry: 0x%lux\\n", entry\);)116 L (55)0(b->wp = b->bp;)32(123)100(warp9\(PADDR\(entry\)\);)116 L (56)0(b->ep = b->wp+GLLONG\(ep->text\);)32(124)100(b->state = FAILED;)116 L (57)0(print\("%ld", GLLONG\(ep->text\)\);)32(125)100(return FAIL;)116 L (58)0(break;)32(126)100 L (59)0(})24(127 case READGZIP:)100 L (60)0(128)100(ep = &b->exec;)116 L (61)0(/* check for gzipped kernel */)24(129)100(if\(b->bp[0] != 0x1F || \(uchar\)b->bp[1] != 0x8B || b->bp[2] != 0x08\))116 L (62)0(if\(b->bp[0] == 0x1F && \(uchar\)b->bp[1] == 0x8B && b->bp[2] == 0x08\) {)24(130)100(print\("lost magic\\n"\);)124 L (63)0(b->state = READGZIP;)32(131)100 L (64)0(b->bp = \(char*\)malloc\(1024*1024\);)32(132)100(print\("%ld => ", b->wp - b->bp\);)116 L (65)0(b->wp = b->bp;)32(133)100(if\(gunzip\(\(uchar*\)ep, sizeof\(*ep\), \(uchar*\)b->bp, b->wp - b->bp\) < sizeof\(*ep\)\) {)116 L (66)0(b->ep = b->wp + 1024*1024;)32(134)100(print\("badly compressed kernel\\n"\);)124 L (67)0(memmove\(b->bp, &b->exec, sizeof\(Exec\)\);)32(135)100(return FAIL;)124 L (68)0(b->wp += sizeof\(Exec\);)32(136)100(})116 L cleartomark showpage saveobj restore %%EndPage: 227 227 %%Page: 228 228 /saveobj save def mark 228 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/boot.c Page 2)l ()l ()l (137)0(entry = GLLONG\(ep->entry\);)16 L (138)0(text = GLLONG\(ep->text\);)16 L (139)0(data = GLLONG\(ep->data\);)16 L (140)0(bss = GLLONG\(ep->bss\);)16 L (141)0(print\("%lud+%lud+%lud=%lud\\n", text, data, bss, text+data+bss\);)16 L (142)l (143)0(if\(gunzip\(\(uchar*\)PADDR\(entry\)-sizeof\(Exec\), sizeof\(Exec\)+text+data,)16 L (144)0(\(uchar*\)b->bp, b->wp-b->bp\) < sizeof\(Exec\)+text+data\) {)21 L (145)0(print\("error uncompressing kernel\\n"\);)24 L (146)0(return FAIL;)24 L (147)0(})16 L (148)l (149)0(/* relocate data to start at page boundary */)16 L (150)0(memmove\(\(void*\)PGROUND\(entry+text\), \(void*\)PADDR\(entry+text\), data\);)16 L (151)l (152)0(print\("entry: %lux\\n", entry\);)16 L (153)0(warp9\(PADDR\(entry\)\);)16 L (154)0(b->state = FAILED;)16 L (155)0(return FAIL;)16 L (156)l (157 case INIT9LOAD:)l (158 case READ9LOAD:)l (159)0(panic\("end 9load"\);)16 L (160)l (161 default:)l (162)0(panic\("bootdone"\);)16 L (163 })l (164 b->state = FAILED;)l (165 return FAIL;)l (166 })l cleartomark showpage saveobj restore %%EndPage: 228 228 %%Page: 229 229 /saveobj save def mark 229 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/clock.c Page 1)l ()l ()l (1 #include "u.h")0(69)100({ 4, 7,)108(22, "DX2WB", }, /* P24D */)124 L (2 #include "lib.h")0(70)100({ 4, 8,)108(22, "DX4", },)124(/* P24C */)148 L (3 #include "mem.h")0(71)100({ 4, 9,)108(22, "DX4WB", }, /* P24CT */)124 L (4 #include "dat.h")0(72)100({ 5, 0,)108(23, "P5", },)124 L (5 #include "fns.h")0(73)100({ 5, 1,)108(23, "P5", },)124 L (6 #include "io.h")0(74)100({ 5, 2,)108(23, "P54C", },)124 L (7 #include "ureg.h")0(75)100({ 5, 3,)108(23, "P24T", },)124 L (8)0(76)100({ 5, 4,)108(23, "P55C MMX", },)124 L (9 /*)0(77)100({ 5, 7,)108(23, "P54C VRT", },)124 L (10 * 8253 timer)0(78)100({ 6, 1,)108(16, "PentiumPro", },/* trial and error */)124 L (11 */)0(79)100({ 6, 3,)108(16, "PentiumII", },)124 L (12 enum)0(80)100({ 6, 5,)108(16, "PentiumII/Xeon", },)124 L (13 {)0(81)100({ 6, 6,)108(16, "Celeron", },)124 L (14)0(T0cntr= 0x40,)8(/* counter ports */)32(82)100({ 6, 7,)108(16, "PentiumIII/Xeon", },)124 L (15)0(T1cntr= 0x41,)8(/* ... */)32(83)100({ 6, 8,)108(16, "PentiumIII/Xeon", },)124 L (16)0(T2cntr= 0x42,)8(/* ... */)32(84)100 L (17)0(Tmode= 0x43,)8(/* mode port */)32(85)100({ 3, -1, 32, "386", },)108(/* family defaults */)148 L (18)0(86)100({ 4, -1, 22, "486", },)108 L (19)0(/* commands */)8(87)100({ 5, -1, 23, "Pentium", },)108 L (20)0(Latch0= 0x00,)8(/* latch counter 0's value */)32(88)100({ 6, -1, 16, "PentiumPro", },)108 L (21)0(Load0= 0x30,)8(/* load counter 0 with 2 bytes */)32(89)100 L (22)0(90)100({ -1, -1, 23, "unknown", }, /* total default */)108 L (23)0(/* modes */)8(91 };)100 L (24)0(Square= 0x36,)8(/* perioic square wave */)32(92)100 L (25)0(93)100 L (26)0(Freq= 1193182,)8(/* Real clock frequency */)32(94 /*)100 L (27 };)0(95 * The AMD processors all implement the CPUID instruction.)100 L (28)0(96 * The later ones also return the processor name via functions)100 L (29 static int cpufreq = 66000000;)0(97 * 0x80000002, 0x80000003 and 0x80000004 in registers AX, BX, CX)100 L (30 static int cpumhz = 66;)0(98 * and DX:)100 L (31 static int loopconst = 100;)0(99 *)100(K5)116("AMD-K5\(tm\) Processor")124 L (32 static int cpuidax, cpuiddx;)0(100 *)100(K6)116("AMD-K6tm w/ multimedia extensions")124 L (33)0(101 *)100(K6 3D "AMD-K6\(tm\) 3D processor")116 L (34 static void)0(102 *)100(K6 3D+ ?)116 L (35 clockintr\(Ureg*, void*\))0(103 */)100 L (36 {)0(104 static X86type x86amd[] =)100 L (37)0(m->ticks++;)8(105 {)100 L (38)0(checkalarms\(\);)8(106 { 5, 0,)100(23, "AMD-K5", }, /* guesswork */)124 L (39 })0(107 { 5, 1,)100(23, "AMD-K5", }, /* guesswork */)124 L (40)0(108 { 5, 2,)100(23, "AMD-K5", }, /* guesswork */)124 L (41 #define STEPPING\(x\))0(\(\(x\)&0xf\))32(109 { 5, 3,)100(23, "AMD-K5", }, /* guesswork */)124 L (42 #define X86MODEL\(x\))0(\(\(\(x\)>>4\)&0xf\))32(110 { 5, 6,)100(11, "AMD-K6", }, /* trial and error */)124 L (43 #define X86FAMILY\(x\))0(\(\(\(x\)>>8\)&0xf\))32(111 { 5, 7,)100(11, "AMD-K6", }, /* trial and error */)124 L (44)0(112 { 5, 8,)100(11, "AMD-K6-2", }, /* trial and error */)124 L (45 enum)0(113 { 5, 9,)100(11, "AMD-K6-III", },/* trial and error */)124 L (46 {)0(114)100 L (47)0(/* flags */)8(115 { 6, 1,)100(11, "AMD-Athlon", },/* trial and error */)124 L (48)0(CpuidFPU)8(= 0x001,)24(/* on-chip floating point unit */)40(116 { 6, 2,)100(11, "AMD-Athlon", },/* trial and error */)124 L (49)0(CpuidMCE)8(= 0x080,)24(/* machine check exception */)40(117)100 L (50)0(CpuidCX8)8(= 0x100,)24(/* CMPXCHG8B instruction */)40(118 { 4, -1, 22, "Am486", }, /* guesswork */)100 L (51 };)0(119 { 5, -1, 23, "AMD-K5/K6", }, /* guesswork */)100 L (52)0(120 { 6, -1, 11, "AMD-Athlon", },/* guesswork */)100 L (53 typedef struct)0(121)100 L (54 {)0(122 { -1, -1, 23, "unknown", }, /* total default */)100 L (55)0(int family;)8(123 };)100 L (56)0(int model;)8(124)100 L (57)0(int aalcycles;)8(125 static X86type *cputype;)100 L (58)0(char *name;)8(126)100 L (59 } X86type;)0(127 /*)100 L (60)0(128 * delay for l milliseconds more or less. delayloop is set by)100 L (61 X86type x86intel[] =)0(129 * clockinit\(\) to match the actual CPU speed.)100 L (62 {)0(130 */)100 L (63)0({ 4, 0,)8(22, "486DX", }, /* known chips */)24(131 void)100 L (64)0({ 4, 1,)8(22, "486DX50", },)24(132 delay\(int l\))100 L (65)0({ 4, 2,)8(22, "486SX", },)24(133 {)100 L (66)0({ 4, 3,)8(22, "486DX2", },)24(134 l *= loopconst;)100 L (67)0({ 4, 4,)8(22, "486SL", },)24(135 if\(l <= 0\))100 L (68)0({ 4, 5,)8(22, "486SX2", },)24(136)100(l = 1;)116 L cleartomark showpage saveobj restore %%EndPage: 229 229 %%Page: 230 230 /saveobj save def mark 230 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/clock.c Page 2)l ()l ()l (137 aamloop\(l\);)0(205)100(* The i8254 \(which this probably is\) has a read-back)109 L (138 })0(206)100(* command which can be used to make sure the counting)109 L (139)0(207)100(* register has been written into the counting element.)109 L (140 void)0(208)100(*/)109 L (141 microdelay\(int l\))0(209 x = \(Freq/HZ\);)100 L (142 {)0(210 for\(loops = 0; loops < 100000 && x >= \(Freq/HZ\); loops++\){)100 L (143 l *= loopconst;)0(211)100(outb\(Tmode, Latch0\);)116 L (144 l /= 1000;)0(212)100(x = inb\(T0cntr\);)116 L (145 if\(l <= 0\))0(213)100(x |= inb\(T0cntr\)<<8;)116 L (146)0(l = 1;)16(214 })100 L (147 aamloop\(l\);)0(215)100 L (148 })0(216 /* find biggest loop that doesn't wrap */)100 L (149)0(217 incr = 16000000/\(t->aalcycles*HZ*2\);)100 L (150 extern void cpuid\(char*, int*, int*\);)0(218 x = 2000;)100 L (151)0(219 for\(loops = incr; loops < 64*1024; loops += incr\) {)100 L (152 X86type*)0(220)100 L (153 cpuidentify\(void\))0(221)100(/*)116 L (154 {)0(222)100(* measure time for the loop)117 L (155 int family, model;)0(223)100(*)117 L (156 X86type *t;)0(224)100(*)117(MOVL loops,CX)140 L (157 char cpuidid[16];)0(225)100(*)117(aaml1:)124(AAM)140 L (158 int cpuidax, cpuiddx;)0(226)100(*)117(LOOP aaml1)140 L (159)0(227)100(*)117 L (160 cpuid\(cpuidid, &cpuidax, &cpuiddx\);)0(228)100(* the time for the loop should be independent of external)117 L (161 if\(strncmp\(cpuidid, "AuthenticAMD", 12\) == 0\))0(229)100(* cache and memory system since it fits in the execution)117 L (162)0(t = x86amd;)16(230)100(* prefetch buffer.)117 L (163 else)0(231)100(*)117 L (164)0(t = x86intel;)16(232)100(*/)117 L (165 family = X86FAMILY\(cpuidax\);)0(233)100(outb\(Tmode, Latch0\);)116 L (166 model = X86MODEL\(cpuidax\);)0(234)100(x = inb\(T0cntr\);)116 L (167 while\(t->name\){)0(235)100(x |= inb\(T0cntr\)<<8;)116 L (168)0(if\(\(t->family == family && t->model == model\))16(236)100(aamloop\(loops\);)116 L (169)0(|| \(t->family == family && t->model == -1\))16(237)100(outb\(Tmode, Latch0\);)116 L (170)0(|| \(t->family == -1\)\))16(238)100(y = inb\(T0cntr\);)116 L (171)0(break;)24(239)100(y |= inb\(T0cntr\)<<8;)116 L (172)0(t++;)16(240)100(x -= y;)116 L (173 })0(241)100 L (174 if\(t->name == nil\))0(242)100(if\(x < 0\))116 L (175)0(panic\("cpuidentify"\);)16(243)100(x += Freq/HZ;)124 L (176)0(244)100 L (177 return t;)0(245)100(if\(x > Freq/\(3*HZ\)\))116 L (178 })0(246)100(break;)124 L (179)0(247 })100 L (180 void)0(248)100 L (181 clockinit\(void\))0(249 /*)100 L (182 {)0(250)100(* counter goes at twice the frequency, once per transition,)109 L (183 int x, y;)0(/* change in counter */)24(251)100(* i.e., twice per square wave)109 L (184 int loops, incr;)0(252)100(*/)109 L (185 X86type *t;)0(253 x >>= 1;)100 L (186)0(254)100 L (187 /*)0(255 /*)100 L (188)0(* set vector for clock interrupts)9(256)100(* figure out clock frequency and a loop multiplier for delay\(\).)109 L (189)0(*/)9(257)100(*/)109 L (190 setvec\(VectorCLOCK, clockintr, 0\);)0(258 cpufreq = loops*\(\(t->aalcycles*Freq\)/x\);)100 L (191)0(259 loopconst = \(cpufreq/1000\)/t->aalcycles;)100(/* AAM+LOOP's for 1 ms */)156 L (192 t = cpuidentify\(\);)0(260)100 L (193)0(261 /*)100 L (194 /*)0(262)100(* add in possible .2% error and convert to MHz)109 L (195)0(* set clock for 1/HZ seconds)9(263)100(*/)109 L (196)0(*/)9(264 cpumhz = \(cpufreq + cpufreq/500\)/1000000;)100 L (197 outb\(Tmode, Load0|Square\);)0(265 //)100(print\("%dMHz %s loop %d\\n", cpumhz, t->name, loopconst\);)116 L (198 outb\(T0cntr, \(Freq/HZ\)\);)0(/* low byte */)40(266 })100 L (199 outb\(T0cntr, \(Freq/HZ\)>>8\); /* high byte */)0(267)100 L (200)l (201 /*)l (202)0(* Introduce a little delay to make sure the count is)9 L (203)0(* latched and the timer is counting down; with a fast)9 L (204)0(* enough processor this may not be the case.)9 L cleartomark showpage saveobj restore %%EndPage: 230 230 %%Page: 231 231 /saveobj save def mark 231 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/conf.c Page 1)l ()l ()l (1 #include "u.h")0(69 void)100 L (2 #include "lib.h")0(70 addconf\(char *fmt, ...\))100 L (3 #include "mem.h")0(71 {)100 L (4 #include "dat.h")0(72)100(donprint\(BOOTARGS+strlen\(BOOTARGS\), BOOTARGS+BOOTARGSLEN, fmt, \(&fmt+1\)\);)108 L (5 #include "fns.h")0(73 })100 L (6 #include "io.h")0(74)100 L (7)0(75 /*)100 L (8 #include "dosfs.h")0(76 * read configuration file)100 L (9)0(77 */)100 L (10 /*)0(78 static char inibuf[BOOTARGSLEN];)100 L (11 * Where configuration info is left for the loaded programme.)0(79 static char id[8] = "ZORT 0\\r\\n";)100 L (12 * This will turn into a structure as more is done by the boot loader)0(80)100 L (13 * \(e.g. why parse the .ini file twice?\).)0(81 int)100 L (14 * There are XXX bytes available at CONFADDR.)0(82 dotini\(Dos *dos\))100 L (15 */)0(83 {)100 L (16 #define BOOTLINELEN)0(64)32(84)100(Dosfile rc;)108 L (17 #define BOOTARGS \(\(char*\)\(CONFADDR+BOOTLINELEN\)\))0(85)100(int i, n;)108 L (18 #define BOOTARGSLEN \(4096-0x200-BOOTLINELEN\))0(86)100(char *cp, *p, *q, *line[MAXCONF];)108 L (19 #define MAXCONF)0(32)32(87)100 L (20)0(88)100(if\(dosstat\(dos, *ini, &rc\) <= 0\))108 L (21 static char *confname[MAXCONF];)0(89)100(return -1;)116 L (22 static char *confval[MAXCONF];)0(90)100 L (23 static int nconf;)0(91)100(cp = inibuf;)108 L (24)0(92)100(*cp = 0;)108 L (25 extern char **ini;)0(93)100(n = dosread\(&rc, cp, BOOTARGSLEN-1\);)108 L (26)0(94)100(if\(n <= 0\))108 L (27 char*)0(95)100(return -1;)116 L (28 getconf\(char *name\))0(96)100 L (29 {)0(97)100(cp[n] = 0;)108 L (30)0(int i, n, nmatch;)8(98)100 L (31)0(char buf[20];)8(99)100(/*)108 L (32)0(100)100(* Keep a pristine copy.)109 L (33)0(nmatch = 0;)8(101)100(* We could change this to pass the parsed strings)109 L (34)0(for\(i = 0; i < nconf; i++\))8(102)100(* to the booted programme instead of the raw)109 L (35)0(if\(cistrcmp\(confname[i], name\) == 0\))16(103)100(* string, then it only gets done once.)109 L (36)0(nmatch++;)24(104)100(*/)109 L (37)0(105 if\(strncmp\(cp, id, sizeof\(id\)\)\){)100 L (38)0(switch\(nmatch\) {)8(106)100(memmove\(BOOTARGS, id, sizeof\(id\)\);)116 L (39)0(default:)8(107)100(if\(n+1+sizeof\(id\) >= BOOTARGSLEN\))116 L (40)0(print\("\\n"\);)16(108)100(n -= sizeof\(id\);)124 L (41)0(nmatch = 0;)16(109)100(memmove\(BOOTARGS+sizeof\(id\), cp, n+1\);)116 L (42)0(for\(i = 0; i < nconf; i++\))16(110 })100 L (43)0(if\(cistrcmp\(confname[i], name\) == 0\))24(111 else)100 L (44)0(print\("%d. %s\\n", ++nmatch, confval[i]\);)32(112)100(memmove\(BOOTARGS, cp, n+1\);)116 L (45)0(print\("%d. none of the above\\n", ++nmatch\);)16(113)100 L (46)0(do {)16(114 /*)100 L (47)0(getstr\(name, buf, sizeof\(buf\), nil, 0\);)24(115)100(* Strip out '\\r', change '\\t' -> ' '.)109 L (48)0(n = atoi\(buf\);)24(116)100(*/)109 L (49)0(} while\(n < 1 || n > nmatch\);)16(117 p = cp;)100 L (50)0(118 for\(q = cp; *q; q++\){)100 L (51)0(for\(i = 0; i < nconf; i++\))16(119)100(if\(*q == '\\r'\))116 L (52)0(if\(cistrcmp\(confname[i], name\) == 0\))24(120)100(continue;)124 L (53)0(if\(--n == 0\))32(121)100(if\(*q == '\\t'\))116 L (54)0(return confval[i];)40(122)100(*q = ' ';)124 L (55)0(break;)16(123)100(*p++ = *q;)116 L (56)0(124 })100 L (57)0(case 1:)8(125 *p = 0;)100 L (58)0(for\(i = 0; i < nconf; i++\))16(126 n = getfields\(cp, line, MAXCONF, '\\n'\);)100 L (59)0(if\(cistrcmp\(confname[i], name\) == 0\))24(127 for\(i = 0; i < n; i++\){)100 L (60)0(return confval[i];)32(128)100(cp = strchr\(line[i], '='\);)116 L (61)0(break;)16(129)100(if\(cp == 0\))116 L (62)0(130)100(continue;)124 L (63)0(case 0:)8(131)100(*cp++ = 0;)116 L (64)0(break;)16(132)100(if\(cp - line[i] >= NAMELEN+1\))116 L (65)0(})8(133)100(*\(line[i]+NAMELEN-1\) = 0;)124 L (66)0(return nil;)8(134)100(confname[nconf] = line[i];)116 L (67 })0(135)100(confval[nconf] = cp;)116 L (68)0(136)100(nconf++;)116 L cleartomark showpage saveobj restore %%EndPage: 231 231 %%Page: 232 232 /saveobj save def mark 232 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/conf.c Page 2)l ()l ()l (137 })0(205)100(r = isa->opt[isa->nopt];)132 L (138 return 0;)0(206)100(while\(*p && *p != ' ' && *p != '\\t'\){)132 L (139 })0(207)100(*r++ = *p++;)140 L (140)0(208)100(if\(r-isa->opt[isa->nopt] >= ISAOPTLEN-1\))140 L (141 static int)0(209)100(break;)148 L (142 parseether\(uchar *to, char *from\))0(210)100(})132 L (143 {)0(211)100(*r = '\\0';)132 L (144 char nip[4];)0(212)100(isa->nopt++;)132 L (145 char *p;)0(213)100(})124 L (146 int i;)0(214)100(while\(*p && *p != ' ' && *p != '\\t'\))124 L (147)0(215)100(p++;)132 L (148 p = from;)0(216)100(})116 L (149 while\(*p == ' '\))0(217)100(return 1;)116 L (150)0(++p;)16(218 })100 L (151 for\(i = 0; i < 6; i++\){)0(219 return 0;)100 L (152)0(if\(*p == 0\))16(220 })100 L (153)0(return -1;)24 L (154)0(nip[0] = *p++;)16 L (155)0(if\(*p == 0\))16 L (156)0(return -1;)24 L (157)0(nip[1] = *p++;)16 L (158)0(nip[2] = 0;)16 L (159)0(to[i] = strtoul\(nip, 0, 16\);)16 L (160)0(if\(*p == ':'\))16 L (161)0(p++;)24 L (162 })l (163 return 0;)l (164 })l (165)l (166 int)l (167 isaconfig\(char *class, int ctlrno, ISAConf *isa\))l (168 {)l (169 char cc[NAMELEN], *p, *q, *r;)l (170 int n;)l (171)l (172 sprint\(cc, "%s%d", class, ctlrno\);)l (173 for\(n = 0; n < nconf; n++\){)l (174)0(if\(cistrncmp\(confname[n], cc, NAMELEN\)\))16 L (175)0(continue;)24 L (176)0(isa->nopt = 0;)16 L (177)0(p = confval[n];)16 L (178)0(while\(*p\){)16 L (179)0(while\(*p == ' ' || *p == '\\t'\))24 L (180)0(p++;)32 L (181)0(if\(*p == '\\0'\))24 L (182)0(break;)32 L (183)0(if\(cistrncmp\(p, "type=", 5\) == 0\){)24 L (184)0(p += 5;)32 L (185)0(for\(q = isa->type; q < &isa->type[NAMELEN-1]; q++\){)32 L (186)0(if\(*p == '\\0' || *p == ' ' || *p == '\\t'\))40 L (187)0(break;)48 L (188)0(*q = *p++;)40 L (189)0(})32 L (190)0(*q = '\\0';)32 L (191)0(})24 L (192)0(else if\(cistrncmp\(p, "port=", 5\) == 0\))24 L (193)0(isa->port = strtoul\(p+5, &p, 0\);)32 L (194)0(else if\(cistrncmp\(p, "irq=", 4\) == 0\))24 L (195)0(isa->irq = strtoul\(p+4, &p, 0\);)32 L (196)0(else if\(cistrncmp\(p, "mem=", 4\) == 0\))24 L (197)0(isa->mem = strtoul\(p+4, &p, 0\);)32 L (198)0(else if\(cistrncmp\(p, "size=", 5\) == 0\))24 L (199)0(isa->size = strtoul\(p+5, &p, 0\);)32 L (200)0(else if\(cistrncmp\(p, "ea=", 3\) == 0\){)24 L (201)0(if\(parseether\(isa->ea, p+3\) == -1\))32 L (202)0(memset\(isa->ea, 0, 6\);)40 L (203)0(})24 L (204)0(else if\(isa->nopt < NISAOPT\){)24 L cleartomark showpage saveobj restore %%EndPage: 232 232 %%Page: 233 233 /saveobj save def mark 233 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/console.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(uartputs\(&consoq, s, n\);)116 L (2 #include "lib.h")0(70 })100 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72 static int)100 L (5 #include "fns.h")0(73 getline\(char *buf, int size, int dotimeout\))100 L (6 #include "io.h")0(74 {)100 L (7)0(75)100(int c, i=0;)108 L (8 static IOQ consiq;)0(76)100(ulong start;)108 L (9 static IOQ consoq;)0(77)100(char echo;)108 L (10)0(78)100 L (11 static int useuart;)0(79)100(for \(;;\) {)108 L (12)0(80)100(start = m->ticks;)116 L (13 int)0(debug = 0;)16(81)100(do{)116 L (14)0(82)100(if\(dotimeout && \(\(m->ticks - start\) > 15*HZ\)\) /* 15 seconds to first char)124 L (15 void)0(83)100(return -2;)132 L (16 consinit\(void\))0(84)100(c = consiq.getc\(&consiq\);)124 L (17 {)0(85)100(}while\(c == -1\);)116 L (18)0(char *p;)8(86)100(if\(c == '\\r'\))116 L (19)0(int baud, port;)8(87)100(c = '\\n';)124(/* turn carriage return into newline */)148 L (20)0(88)100(if\(c == '\\177'\))116 L (21)0(qinit\(&consiq\);)8(89)100(c = '\\010';)124(/* turn delete into backspace */)148 L (22)0(kbdinit\(\);)8(90)100(if\(c == '\\025'\))116 L (23)0(91)100(echo = '\\n';)124(/* echo ^U as a newline */)148 L (24)0(if\(\(p = getconf\("console"\)\) == 0 || cistrcmp\(p, "cga"\) == 0\))8(92)100(else)116 L (25)0(return;)16(93)100(echo = c;)124 L (26)0(94)100(consputs\(&echo, 1\);)116 L (27)0(qinit\(&consoq\);)8(95)100 L (28)0(96)100(if\(c == '\\010'\){)116 L (29)0(port = strtoul\(p, 0, 0\);)8(97)100(if\(i > 0\))124 L (30)0(baud = 0;)8(98)100(i--; /* bs deletes last character */)132 L (31)0(if\(p = getconf\("baud"\)\))8(99)100(continue;)124 L (32)0(baud = strtoul\(p, 0, 0\);)16(100)100(})116 L (33)0(if\(baud == 0\))8(101)100(/* a newline ends a line */)116 L (34)0(baud = 9600;)16(102)100(if \(c == '\\n'\))116 L (35)0(uartspecial\(port, kbdchar, conschar, baud\);)8(103)100(break;)124 L (36)0(useuart = 1;)8(104)100(/* ^U wipes out the line */)116 L (37)0(uartputs\(&consoq, "\\n", 1\);)8(105)100(if \(c =='\\025'\))116 L (38 })0(106)100(return -1;)124 L (39)0(107)100(if\(i == size\))116 L (40 void)0(108)100(return size;)124 L (41 consdrain\(void\))0(109)100(buf[i++] = c;)116 L (42 {)0(110 })100 L (43)0(if\(useuart\))8(111 buf[i] = 0;)100 L (44)0(uartdrain\(\);)16(112 return i;)100 L (45 })0(113 })100 L (46)0(114)100 L (47 void)0(115 int)100 L (48 kbdchar\(int c\))0(116 getstr\(char *prompt, char *buf, int size, char *def, int dotimeout\))100 L (49 {)0(117 {)100 L (50)0(c &= 0x7F;)8(118 int len, isdefault;)100 L (51)0(if\(c == 0x10\))8(119)100 L (52)0(panic\("^p"\);)16(120 buf[0] = 0;)100 L (53)0(if\(c == 0x12\))8(121 isdefault = \(def && *def\);)100 L (54)0(debug = !debug;)16(122 if\(isdefault == 0\))100 L (55)0(consiq.putc\(&consiq, c\);)8(123)100(dotimeout = 0;)116 L (56 })0(124 for \(;;\) {)100 L (57)0(125)100(if\(isdefault\))116 L (58 int)0(126)100(print\("%s[default==%s]: ", prompt, def\);)124 L (59 conschar\(void\))0(127)100(else)116 L (60 {)0(128)100(print\("%s: ", prompt\);)124 L (61)0(return consoq.getc\(&consoq\);)8(129)100(len = getline\(buf, size, dotimeout\);)116 L (62 })0(130)100(switch\(len\){)116 L (63)0(131)100(case -1:)116 L (64 void)0(132)100(/* ^U typed */)124 L (65 consputs\(char* s, int n\))0(133)100(continue;)124 L (66 {)0(134)100(case -2:)116 L (67)0(cgascreenputs\(s, n\);)8(135)100(/* timeout, use default */)124 L (68)0(if\(useuart\))8(136)100(consputs\("\\n", 1\);)124 L cleartomark showpage saveobj restore %%EndPage: 233 233 %%Page: 234 234 /saveobj save def mark 234 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/console.c Page 2)l ()l ()l (137)0(len = 0;)24 L (138)0(break;)24 L (139)0(default:)16 L (140)0(break;)24 L (141)0(})16 L (142)0(if\(len >= size\){)16 L (143)0(print\("line too long\\n"\);)24 L (144)0(continue;)24 L (145)0(})16 L (146)0(break;)16 L (147 })l (148 if\(len == 0 && isdefault\))l (149)0(strcpy\(buf, def\);)16 L (150 return 0;)l (151 })l (152)l (153 int)l (154 sprint\(char *s, char *fmt, ...\))l (155 {)l (156 return donprint\(s, s+PRINTSIZE, fmt, \(&fmt+1\)\) - s;)l (157 })l (158)l (159 int)l (160 snprint\(char *s, int n, char *fmt, ...\))l (161 {)l (162 return donprint\(s, s+n, fmt, \(&fmt+1\)\) - s;)l (163 })l (164)l (165 int)l (166 print\(char *fmt, ...\))l (167 {)l (168 char buf[PRINTSIZE];)l (169 int n;)l (170)l (171 n = donprint\(buf, buf+sizeof\(buf\), fmt, \(&fmt+1\)\) - buf;)l (172 consputs\(buf, n\);)l (173 return n;)l (174 })l (175)l (176 void)l (177 panic\(char *fmt, ...\))l (178 {)l (179 int n;)l (180 char buf[PRINTSIZE];)l (181)l (182 consputs\("panic: ", 7\);)l (183 n = donprint\(buf, buf+sizeof\(buf\), fmt, \(&fmt+1\)\) - buf;)l (184 consputs\(buf, n\);)l (185 consputs\("\\n", 1\);)l (186 for\(;;\) splhi\(\);)l (187 for\(n=0; n<20; n++\))l (188)0(microdelay\(500\);)16 L (189 spllo\(\);)l (190 consdrain\(\);)l (191 i8042reset\(\);)l (192 print\("Takes a licking and keeps on ticking...\\n"\);)l (193 for\(;;\))l (194)0(idle\(\);)16 L (195 })l cleartomark showpage saveobj restore %%EndPage: 234 234 %%Page: 235 235 /saveobj save def mark 235 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dat.h Page 1)l ()l ()l (1 typedef struct List {)0(69)100 L (2)0(void *next;)8(70 typedef struct Exec Exec;)100 L (3 } List;)0(71 struct Exec)100 L (4)0(72 {)100 L (5 typedef struct Alarm {)0(73)100(uchar magic[4];)108(/* magic number */)140 L (6)0(List;)8(74)100(uchar text[4];)108(/* size of text segment */)140 L (7)0(int busy;)8(75)100(uchar data[4];)108(/* size of initialized data */)140 L (8)0(long dt;)8(76)100(uchar bss[4];)108(/* size of uninitialized data */)140 L (9)0(void \(*f\)\(void*\);)8(77)100(uchar syms[4];)108(/* size of symbol table */)140 L (10)0(void *arg;)8(78)100(uchar entry[4];)108(/* entry point */)140 L (11 } Alarm;)0(79)100(uchar spsz[4];)108(/* size of sp/pc offset table */)140 L (12)0(80)100(uchar pcsz[4];)108(/* size of pc/line number table */)140 L (13 typedef struct Block Block;)0(81 };)100 L (14 struct Block {)0(82)100 L (15)0(Block* next;)8(83 /*)100 L (16)0(uchar* rp;)8(/* first unconsumed byte */)40(84 * a parsed .ini line)100 L (17)0(uchar* wp;)8(/* first empty byte */)40(85 */)100 L (18)0(uchar* lim;)8(/* 1 past the end of the buffer */)40(86 #define ISAOPTLEN 16)100 L (19)0(uchar* base;)8(/* start of the buffer */)40(87 #define NISAOPT)100(8)132 L (20)0(ulong flag;)8(88)100 L (21 };)0(89 typedef struct ISAConf {)100 L (22 #define BLEN\(s\) \(\(s\)->wp - \(s\)->rp\))0(90)100(char type[NAMELEN];)108 L (23)0(91)100(ulong port;)108 L (24 typedef struct IOQ IOQ;)0(92)100(ulong irq;)108 L (25 typedef struct IOQ {)0(93)100(ulong mem;)108 L (26)0(uchar buf[4096];)8(94)100(ulong size;)108 L (27)0(uchar *in;)8(95)100(uchar ea[6];)108 L (28)0(uchar *out;)8(96)100 L (29)0(int state;)8(97)100(int nopt;)108 L (30)0(int \(*getc\)\(IOQ*\);)8(98)100(char opt[NISAOPT][ISAOPTLEN];)108 L (31)0(int \(*putc\)\(IOQ*, int\);)8(99 } ISAConf;)100 L (32)0(void *ptr;)8(100)100 L (33 };)0(101 typedef struct Pcidev Pcidev;)100 L (34)0(102 typedef struct PCMmap PCMmap;)100 L (35 enum {)0(103)100 L (36)0(Eaddrlen)8(= 6,)24(104 #define BOOTLINE \(\(char*\)CONFADDR\))100 L (37)0(ETHERMINTU)8(= 60,)24(/* minimum transmit size */)40(105)100 L (38)0(ETHERMAXTU)8(= 1514,)24(/* maximum transmit size */)40(106 enum {)100 L (39)0(ETHERHDRSIZE = 14,)8(/* size of an ethernet header */)40(107 MB =)100(\(1024*1024\),)124 L (40)0(108 };)100 L (41)0(MaxEther)8(= 4,)24(109 #define ROUND\(s, sz\))100(\(\(\(s\)+\(\(sz\)-1\)\)&~\(\(sz\)-1\)\))132 L (42 };)0(110)100 L (43)0(111)100 L (44 typedef struct {)0(112 typedef struct Type Type;)100 L (45)0(uchar d[Eaddrlen];)8(113 typedef struct Medium Medium;)100 L (46)0(uchar s[Eaddrlen];)8(114 typedef struct Boot Boot;)100 L (47)0(uchar type[2];)8(115)100 L (48)0(uchar data[1500];)8(116 enum {)100(/* type */)148 L (49)0(uchar crc[4];)8(117 Tnil)100(= 0x00,)124 L (50 } Etherpkt;)0(118)100 L (51)0(119 Tfloppy)100(= 0x01,)124 L (52 extern uchar broadcast[Eaddrlen];)0(120 Tsd)100(= 0x02,)124 L (53)0(121 Tether)100(= 0x03,)124 L (54 typedef struct Ureg Ureg;)0(122)100 L (55)0(123 Tany)100(= -1,)124 L (56 typedef struct Segdesc {)0(124 };)100 L (57)0(ulong d0;)8(125)100 L (58)0(ulong d1;)8(126 enum {)100(/* name and flag */)148 L (59 } Segdesc;)0(127 Fnone)100(= 0x00,)124 L (60)0(128)100 L (61 typedef struct Mach {)0(129 Ndos)100(= 0x00,)124 L (62)0(ulong ticks;)8(/* of the clock since boot time */)40(130 Fdos)100(= \(1<)0(69 static int c2b[] =)100 L (2)0(70 {)100 L (3 #include "lib.h")0(71)100(128,)108 L (4 #include "mem.h")0(72)100(256,)108 L (5 #include "dat.h")0(73)100(512,)108 L (6 #include "fns.h")0(74)100(1024,)108 L (7 #include "io.h")0(75 };)100 L (8 #include "ureg.h")0(76)100 L (9)0(77 FController)100(fl;)124 L (10 #include "dosfs.h")0(78)100 L (11 #include "devfloppy.h")0(79 #define MOTORBIT\(i\))100(\(1<<\(\(i\)+4\)\))132 L (12)0(80)100 L (13)0(81 /*)100 L (14 /* Intel 82077A \(8272A compatible\) floppy controller */)0(82 * predeclared)100 L (15)0(83 */)100 L (16 /* This module expects the following functions to be defined)0(84 static int)100(cmddone\(void*\);)124 L (17 * elsewhere:)0(85 static void)100(floppyformat\(FDrive*, char*\);)124 L (18 *)0(86 static void)100(floppykproc\(void*\);)124 L (19 * inb\(\))0(87 static void)100(floppypos\(FDrive*,long\);)124 L (20 * outb\(\))0(88 static int)100(floppyrecal\(FDrive*\);)124 L (21 * floppyexec\(\))0(89 static int)100(floppyresult\(void\);)124 L (22 * floppyeject\(\))0(90 static void)100(floppyrevive\(void\);)124 L (23 * floppysetup0\(\))0(91 static long)100(pcfloppyseek\(FDrive*, long\);)124 L (24 * floppysetup1\(\))0(92 static int)100(floppysense\(void\);)124 L (25 * dmainit\(\))0(93 static void)100(floppywait\(void\);)124 L (26 * dmasetup\(\))0(94 static long)100(floppyxfer\(FDrive*, int, void*, long, long\);)124 L (27 * dmaend\(\))0(95)100 L (28 *)0(96 static void)100 L (29 * On DMA systems, floppyexec\(\) should be an empty function;)0(97 fldump\(void\))100 L (30 * on non-DMA systems, dmaend\(\) should be an empty function;)0(98 {)100 L (31 * dmasetup\(\) may enforce maximum transfer sizes.)0(99)100(DPRINT\("sra %ux srb %ux dor %ux msr %ux dir %ux\\n", inb\(Psra\), inb\(Psrb\),)108 L (32 */)0(100)100(inb\(Pdor\), inb\(Pmsr\), inb\(Pdir\)\);)116 L (33)0(101 })100 L (34 enum {)0(102)100 L (35)0(/* file types */)8(103 static void)100 L (36)0(Qdir=)8(0,)24(104 floppyalarm\(Alarm* a\))100 L (37)0(Qdata=)8(\(1<<2\),)24(105 {)100 L (38)0(Qctl=)8(\(2<<2\),)24(106 FDrive *dp;)100 L (39)0(Qmask=)8(\(3<<2\),)24(107)100 L (40)0(108 for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\){)100 L (41)0(DMAchan=)8(2,)24(/* floppy dma channel */)32(109)100(if\(\(fl.motor&MOTORBIT\(dp->dev\)\) && TK2SEC\(m->ticks - dp->lasttouched\) > 5\))116 L (42 };)0(110)100(floppyoff\(dp\);)124 L (43)0(111 })100 L (44 #define DPRINT if\(0\)print)0(112)100 L (45)0(113 alarm\(5*1000, floppyalarm, 0\);)100 L (46 FType floppytype[] =)0(114 cancel\(a\);)100 L (47 {)0(115 })100 L (48 { "3\302\275HD",)0(T1440kb, 512, 18, 2, 1, 80, 0x1B, 0x54, 0, },)25(116)101 L (49 { "3\302\275DD",)0(T1440kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },)25(117 /*)101 L (50 { "3\302\275DD",)0(T720kb, 512, 9, 2, 1, 80, 0x1B, 0x54, 2, },)25(118 * set floppy drive to its default type)101 L (51 { "5\302\274HD",)0(T1200kb, 512, 15, 2, 1, 80, 0x2A, 0x50, 0, },)25(119 */)101 L (52 { "5\302\274DD",)0(T1200kb, 512, 9, 2, 2, 40, 0x2A, 0x50, 1, },)25(120 static void)101 L (53 { "ATT3B1",)0(T1200kb, 512, 8, 2, 2, 48, 0x2A, 0x50, 1, },)24(121 floppysetdef\(FDrive *dp\))100 L (54 { "5\302\274DD",)0(T360kb, 512, 9, 2, 1, 40, 0x2A, 0x50, 2, },)25(122 {)101 L (55 };)0(123 FType *t;)100 L (56)0(124)100 L (57 /*)0(125 for\(t = floppytype; t < &floppytype[nelem\(floppytype\)]; t++\))100 L (58 * bytes per sector encoding for the controller.)0(126)100(if\(dp->dt == t->dt\){)116 L (59 * - index for b2c is is \(bytes per sector/128\).)0(127)100(dp->t = t;)124 L (60 * - index for c2b is code from b2c)0(128)100(break;)124 L (61 */)0(129)100(})116 L (62 static int b2c[] =)0(130 })100 L (63 {)0(131)100 L (64 [1])0(0,)16(132 int)100 L (65 [2])0(1,)16(133 floppyinit\(void\))100 L (66 [4])0(2,)16(134 {)100 L (67 [8])0(3,)16(135 FDrive *dp;)100 L (68 };)0(136 FType *t;)100 L cleartomark showpage saveobj restore %%EndPage: 237 237 %%Page: 238 238 /saveobj save def mark 238 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/devfloppy.c Page 2)l ()l ()l (137 ulong maxtsize;)0(205 {)100 L (138 int mask;)0(206 Dos *dos;)100 L (139)0(207)100 L (140 dmainit\(DMAchan\);)0(208 if\(strncmp\(file, "dos!", 4\) == 0\))100 L (141)0(209)100(file += 4;)116 L (142 floppysetup0\(&fl\);)0(210 else if\(strchr\(file, '!'\) || strcmp\(file, ""\)==0\) {)100 L (143)0(211)100(print\("syntax is fd0!file\\n"\);)116 L (144 /*)0(212)100(return -1;)116 L (145)0(* init dependent parameters)9(213 })100 L (146)0(*/)9(214)100 L (147 maxtsize = 0;)0(215 dos = floppygetdospart\(dev, "dos"\);)100 L (148 for\(t = floppytype; t < &floppytype[nelem\(floppytype\)]; t++\){)0(216 if\(dos == nil\) {)100 L (149)0(t->cap = t->bytes * t->heads * t->sectors * t->tracks;)16(217)100(print\("no such FAT partition fd%d!dos\\n", dev\);)116 L (150)0(t->bcode = b2c[t->bytes/128];)16(218)100(return -1;)116 L (151)0(t->tsize = t->bytes * t->sectors;)16(219 })100 L (152)0(if\(maxtsize < t->tsize\))16(220)100 L (153)0(maxtsize = t->tsize;)24(221 return dosboot\(dos, file, b\);)100 L (154 })0(222 })100 L (155)0(223)100 L (156 fl.selected = fl.d;)0(224 ///*)100 L (157)0(225 // * check if the floppy has been replaced under foot. cause)100 L (158 /*)0(226 // * an error if it has.)100 L (159)0(* stop the motors)9(227 // *)100 L (160)0(*/)9(228 // * a seek and a read clears the condition. this was determined)100 L (161 fl.motor = 0;)0(229 // * experimentally, there has to be a better way.)100 L (162 delay\(10\);)0(230 // *)100 L (163 outb\(Pdor, fl.motor | Fintena | Fena\);)0(231 // * if the read fails, cycle through the possible floppy)100 L (164 delay\(10\);)0(232 // * density till one works or we've cycled through all)100 L (165)0(233 // * possibilities for this drive.)100 L (166 /*)0(234 // */)100 L (167)0(* init drives)9(235 //static int)100 L (168)0(*/)9(236 //changed\(FDrive *dp\))100 L (169 mask = 0;)0(237 //{)100 L (170 for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\){)0(238 //)100(FType *start;)116 L (171)0(dp->dev = dp - fl.d;)16(239 //)100 L (172)0(if\(dp->dt == Tnone\))16(240 //)100(/*)116 L (173)0(continue;)24(241 //)100(* if floppy has changed or first time through)117 L (174)0(mask |= 1<dev;)16(242 //)100(*/)117 L (175)0(floppysetdef\(dp\);)16(243 //)100(if\(\(inb\(Pdir\)&Fchange\) || dp->vers == 0\){)116 L (176)0(dp->cyl = -1;)16(/* because we don't know */)48(244 //)100(DPRINT\("changed\\n"\);)124 L (177)0(//dp->cache = \(uchar*\)xspanalloc\(maxtsize, BY2PG, 64*1024\);)16(245 //)100(fldump\(\);)124 L (178)0(dp->cache = \(uchar*\)ialloc\(maxtsize, BY2PG\);)16(246 //)100(dp->vers++;)124 L (179)0(dp->ccyl = -1;)16(247 //)100(floppysetdef\(dp\);)124 L (180)0(dp->vers = 0;)16(248 //)100(start = dp->t;)124 L (181)0(dp->maxtries = 5;)16(249 //)100(dp->confused = 1;)124(/* make floppyon recal */)148 L (182 })0(250 //)100(floppyon\(dp\);)124 L (183)0(251 //)100(pcfloppyseek\(dp, dp->t->heads*dp->t->tsize\);)124 L (184 /*)0(252 //)100 L (185)0(* first operation will recalibrate)9(253 //)100(while\(floppyxfer\(dp, Fread, dp->cache, 0, dp->t->tsize\) <= 0\){)124 L (186)0(*/)9(254 //)100(while\(++dp->t\){)132 L (187 fl.confused = 1;)0(255 //)100(if\(dp->t == &floppytype[nelem\(floppytype\)]\))140 L (188)0(256 //)100(dp->t = floppytype;)148 L (189 floppysetup1\(&fl\);)0(257 //)100(if\(dp->dt == dp->t->dt\))140 L (190)0(258 //)100(break;)148 L (191 /* to turn the motor off when inactive */)0(259 //)100(})132 L (192 alarm\(5*1000, floppyalarm, 0\);)0(260 //)100(floppyon\(dp\);)132 L (193)0(261 //)100(DPRINT\("changed: trying %s\\n", dp->t->name\);)132 L (194 return mask;)0(262 //)100(fldump\(\);)132 L (195 })0(263 //)100(if\(dp->t == start\){)132 L (196)0(264 //)100(return -1;)140 L (197 void)0(265 //)100(})132 L (198 floppyinitdev\(int i, char *name\))0(266 //)100(})124 L (199 {)0(267 //)100(})116 L (200 sprint\(name, "fd%d", i\);)0(268 //)100 L (201 })0(269 //)100(return 0;)116 L (202)0(270 //})100 L (203 int)0(271)100 L (204 floppyboot\(int dev, char *file, Boot *b\))0(272 static int)100 L cleartomark showpage saveobj restore %%EndPage: 238 238 %%Page: 239 239 /saveobj save def mark 239 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/devfloppy.c Page 3)l ()l ()l (273 readtrack\(FDrive *dp, int cyl, int head\))0(341)100 L (274 {)0(342 /* sometimes we get spurious errors and doing it again works */)100 L (275 int i, nn, sofar;)0(343 if\(dosinit\(&dos\) < 0 && dosinit\(&dos\) < 0\))100 L (276 ulong pos;)0(344)100(return nil;)116 L (277)0(345 return &dos;)100 L (278 nn = dp->t->tsize;)0(346 })100 L (279 if\(dp->ccyl==cyl && dp->chead==head\))0(347)100 L (280)0(return nn;)16(348 static int)100 L (281 pos = \(cyl*dp->t->heads+head\) * nn;)0(349 return0\(void*\))100 L (282 for\(sofar = 0; sofar < nn; sofar += i\){)0(350 {)100 L (283)0(dp->ccyl = -1;)16(351 return 0;)100 L (284)0(i = floppyxfer\(dp, Fread, dp->cache + sofar, pos + sofar, nn - sofar\);)16(352 })100 L (285)0(if\(i <= 0\))16(353)100 L (286)0(return -1;)24(354 static void)100 L (287 })0(355 timedsleep\(int \(*f\)\(void*\), void* arg, int ms\))100 L (288 dp->ccyl = cyl;)0(356 {)100 L (289 dp->chead = head;)0(357 int s;)100 L (290 return nn;)0(358 ulong end;)100 L (291 })0(359)100 L (292)0(360 end = m->ticks + 1 + MS2TK\(ms\);)100 L (293 long)0(361 while\(m->ticks < end && !\(*f\)\(arg\)\){)100 L (294 floppyread\(Dos *dos, void *a, long n\))0(362)100(s = spllo\(\);)116 L (295 {)0(363)100(delay\(10\);)116 L (296 FDrive *dp;)0(364)100(splx\(s\);)116 L (297 long rv, offset;)0(365 })100 L (298 int sec, head, cyl;)0(366 })100 L (299 long len;)0(367)100 L (300 uchar *aa;)0(368 /*)100 L (301)0(369 * start a floppy drive's motor.)100 L (302 aa = a;)0(370 */)100 L (303 dp = &fl.d[dos->dev];)0(371 static void)100 L (304)0(372 floppyon\(FDrive *dp\))100 L (305 offset = dp->offset;)0(373 {)100 L (306 floppyon\(dp\);)0(374 int alreadyon;)100 L (307 //)0(if\(changed\(dp\)\))16(375 int tries;)100 L (308 //)0(return -1;)24(376)100 L (309)0(377 if\(fl.confused\))100 L (310 for\(rv = 0; rv < n; rv += len\){)0(378)100(floppyrevive\(\);)116 L (311)0(/*)16(379)100 L (312)0(* all xfers come out of the track cache)17(380 /* start motor and select drive */)100 L (313)0(*/)17(381 dp->lasttouched = m->ticks;)100 L (314)0(dp->len = n - rv;)16(382 alreadyon = fl.motor & MOTORBIT\(dp->dev\);)100 L (315)0(floppypos\(dp, offset+rv\);)16(383 if\(!alreadyon\){)100 L (316)0(cyl = dp->tcyl;)16(384)100(fl.motor |= MOTORBIT\(dp->dev\);)116 L (317)0(head = dp->thead;)16(385)100(outb\(Pdor, fl.motor | Fintena | Fena | dp->dev\);)116 L (318)0(len = dp->len;)16(386)100(/* wait for drive to spin up */)116 L (319)0(sec = dp->tsec;)16(387)100(timedsleep\(return0, 0, 750\);)116 L (320)0(if\(readtrack\(dp, cyl, head\) < 0\))16(388)100 L (321)0(break;)24(389)100(/* clear any pending interrupts */)116 L (322)0(memmove\(aa+rv, dp->cache + \(sec-1\)*dp->t->bytes, len\);)16(390)100(floppysense\(\);)116 L (323 })0(391 })100 L (324 dp->offset = offset+rv;)0(392)100 L (325)0(393 /* set transfer rate */)100 L (326 return rv;)0(394 if\(fl.rate != dp->t->rate\){)100 L (327 })0(395)100(fl.rate = dp->t->rate;)116 L (328)0(396)100(outb\(Pdsr, fl.rate\);)116 L (329 void*)0(397 })100 L (330 floppygetdospart\(int i, char *name\))0(398)100 L (331 {)0(399 /* get drive to a known cylinder */)100 L (332 static Dos dos;)0(400 if\(dp->confused\))100 L (333)0(401)100(for\(tries = 0; tries < 4; tries++\))116 L (334 if\(strcmp\(name, "dos"\) != 0\))0(402)100(if\(floppyrecal\(dp\) >= 0\))124 L (335)0(return nil;)16(403)100(break;)132 L (336)0(404 dp->lasttouched = m->ticks;)100 L (337 dos.dev = i;)0(405 fl.selected = dp;)100 L (338 dos.read = floppyread;)0(406 })100 L (339 dos.seek = floppyseek;)0(407)100 L (340 dos.start = 0;)0(408 /*)100 L cleartomark showpage saveobj restore %%EndPage: 239 239 %%Page: 240 240 /saveobj save def mark 240 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/devfloppy.c Page 4)l ()l ()l (409 * stop the floppy if it hasn't been used in 5 seconds)0(477)100(microdelay\(1\);)124 L (410 */)0(478)100(})116 L (411 static void)0(479)100(fl.stat[i] = inb\(Pfdata\);)116 L (412 floppyoff\(FDrive *dp\))0(480 })100 L (413 {)0(481 fl.nstat = sizeof\(fl.stat\);)100 L (414 fl.motor &= ~MOTORBIT\(dp->dev\);)0(482 return fl.nstat;)100 L (415 outb\(Pdor, fl.motor | Fintena | Fena | dp->dev\);)0(483 })100 L (416 })0(484)100 L (417)0(485 /*)100 L (418 /*)0(486 * calculate physical address of a logical byte offset into the disk)100 L (419 * send a command to the floppy)0(487 *)100 L (420 */)0(488 * truncate dp->length if it crosses a track boundary)100 L (421 static int)0(489 */)100 L (422 floppycmd\(void\))0(490 static void)100 L (423 {)0(491 floppypos\(FDrive *dp, long off\))100 L (424 int i;)0(492 {)100 L (425 int tries;)0(493 int lsec;)100 L (426)0(494 int ltrack;)100 L (427 fl.nstat = 0;)0(495 int end;)100 L (428 for\(i = 0; i < fl.ncmd; i++\){)0(496)100 L (429)0(for\(tries = 0; ; tries++\){)16(497 lsec = off/dp->t->bytes;)100 L (430)0(if\(\(inb\(Pmsr\)&\(Ffrom|Fready\)\) == Fready\))24(498 ltrack = lsec/dp->t->sectors;)100 L (431)0(break;)32(499 dp->tcyl = ltrack/dp->t->heads;)100 L (432)0(if\(tries > 1000\){)24(500 dp->tsec = \(lsec % dp->t->sectors\) + 1;)100 L (433)0(DPRINT\("cmd %ux can't be sent \(%d\)\\n", fl.cmd[0], i\);)32(501 dp->thead = \(lsec/dp->t->sectors\) % dp->t->heads;)100 L (434)0(fldump\(\);)32(502)100 L (435)0(503 /*)100 L (436)0(/* empty fifo, might have been a bad command */)32(504)100(* can't read across track boundaries.)109 L (437)0(floppyresult\(\);)32(505)100(* if so, decrement the bytes to be read.)109 L (438)0(return -1;)32(506)100(*/)109 L (439)0(})24(507 end = \(ltrack+1\)*dp->t->sectors*dp->t->bytes;)100 L (440)0(microdelay\(1\);)24(508 if\(off+dp->len > end\))100 L (441)0(})16(509)100(dp->len = end - off;)116 L (442)0(outb\(Pfdata, fl.cmd[i]\);)16(510 })100 L (443 })0(511)100 L (444 return 0;)0(512 /*)100 L (445 })0(513 * get the interrupt cause from the floppy.)100 L (446)0(514 */)100 L (447 /*)0(515 static int)100 L (448 * get a command result from the floppy)0(516 floppysense\(void\))100 L (449 *)0(517 {)100 L (450 * when the controller goes ready waiting for a command)0(518 fl.ncmd = 0;)100 L (451 * \(instead of sending results\), we're done)0(519 fl.cmd[fl.ncmd++] = Fsense;)100 L (452 *)0(520 if\(floppycmd\(\) < 0\))100 L (453 */)0(521)100(return -1;)116 L (454 static int)0(522 if\(floppyresult\(\) < 2\){)100 L (455 floppyresult\(void\))0(523)100(DPRINT\("can't read sense response\\n"\);)116 L (456 {)0(524)100(fldump\(\);)116 L (457 int i, s;)0(525)100(fl.confused = 1;)116 L (458 int tries;)0(526)100(return -1;)116 L (459)0(527 })100 L (460 /* get the result of the operation */)0(528 return 0;)100 L (461 for\(i = 0; i < sizeof\(fl.stat\); i++\){)0(529 })100 L (462)0(/* wait for status byte */)16(530)100 L (463)0(for\(tries = 0; ; tries++\){)16(531 static int)100 L (464)0(s = inb\(Pmsr\)&\(Ffrom|Fready\);)24(532 cmddone\(void *a\))100 L (465)0(if\(s == Fready\){)24(533 {)100 L (466)0(fl.nstat = i;)32(534 USED\(a\);)100 L (467)0(return fl.nstat;)32(535 return fl.ncmd == 0;)100 L (468)0(})24(536 })100 L (469)0(if\(s == \(Ffrom|Fready\)\))24(537)100 L (470)0(break;)32(538 /*)100 L (471)0(if\(tries > 1000\){)24(539 * Wait for a floppy interrupt. If none occurs in 5 seconds, we)100 L (472)0(DPRINT\("floppyresult: %d stats\\n", i\);)32(540 * may have missed one. This only happens on some portables which)100 L (473)0(fldump\(\);)32(541 * do power management behind our backs. Call the interrupt)100 L (474)0(fl.confused = 1;)32(542 * routine to try to clear any conditions.)100 L (475)0(return -1;)32(543 */)100 L (476)0(})24(544 static void)100 L cleartomark showpage saveobj restore %%EndPage: 240 240 %%Page: 241 241 /saveobj save def mark 241 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/devfloppy.c Page 5)l ()l ()l (545 floppywait\(void\))0(613)100(outb\(Pdor, Fintena|Fena\);)116 L (546 {)0(614)100(delay\(10\);)116 L (547 timedsleep\(cmddone, 0, 5000\);)0(615)100(spllo\(\);)116 L (548 if\(!cmddone\(0\)\){)0(616)100(fl.motor = 0;)116 L (549)0(floppyintr\(0\);)16(617)100(fl.confused = 0;)116 L (550)0(fl.confused = 1;)16(618)100(floppywait\(\);)116 L (551 })0(619)100 L (552 })0(620)100(/* mark all drives in an unknown state */)116 L (553)0(621)100(for\(dp = fl.d; dp < &fl.d[fl.ndrive]; dp++\))116 L (554 /*)0(622)100(dp->confused = 1;)124 L (555 * we've lost the floppy position, go to cylinder 0.)0(623)100 L (556 */)0(624)100(/* set rate to a known value */)116 L (557 static int)0(625)100(outb\(Pdsr, 0\);)116 L (558 floppyrecal\(FDrive *dp\))0(626)100(fl.rate = 0;)116 L (559 {)0(627)100 L (560 dp->ccyl = -1;)0(628)100(DPRINT\("floppyrevive out\\n"\);)116 L (561 dp->cyl = -1;)0(629)100(fldump\(\);)116 L (562)0(630 })100 L (563 fl.ncmd = 0;)0(631 })100 L (564 fl.cmd[fl.ncmd++] = Frecal;)0(632)100 L (565 fl.cmd[fl.ncmd++] = dp->dev;)0(633 /*)100 L (566 if\(floppycmd\(\) < 0\))0(634 * seek to the target cylinder)100 L (567)0(return -1;)16(635 *)100 L (568 floppywait\(\);)0(636 *)100(interrupt, no results)116 L (569 if\(fl.nstat < 2\){)0(637 */)100 L (570)0(DPRINT\("recalibrate: confused %ux\\n", inb\(Pmsr\)\);)16(638 static long)100 L (571)0(fl.confused = 1;)16(639 pcfloppyseek\(FDrive *dp, long off\))100 L (572)0(return -1;)16(640 {)100 L (573 })0(641 floppypos\(dp, off\);)100 L (574 if\(\(fl.stat[0] & \(Codemask|Seekend\)\) != Seekend\){)0(642 if\(dp->cyl == dp->tcyl\){)100 L (575)0(DPRINT\("recalibrate: failed\\n"\);)16(643)100(dp->offset = off;)116 L (576)0(dp->confused = 1;)16(644)100(return off;)116 L (577)0(return -1;)16(645 })100 L (578 })0(646 dp->cyl = -1;)100 L (579 dp->cyl = fl.stat[1];)0(647)100 L (580 if\(dp->cyl != 0\){)0(648 fl.ncmd = 0;)100 L (581)0(DPRINT\("recalibrate: wrong cylinder %d\\n", dp->cyl\);)16(649 fl.cmd[fl.ncmd++] = Fseek;)100 L (582)0(dp->cyl = -1;)16(650 fl.cmd[fl.ncmd++] = \(dp->thead<<2\) | dp->dev;)100 L (583)0(dp->confused = 1;)16(651 fl.cmd[fl.ncmd++] = dp->tcyl * dp->t->steps;)100 L (584)0(return -1;)16(652 if\(floppycmd\(\) < 0\))100 L (585 })0(653)100(return -1;)116 L (586)0(654 floppywait\(\);)100 L (587 dp->confused = 0;)0(655 if\(fl.nstat < 2\){)100 L (588 return 0;)0(656)100(DPRINT\("seek: confused\\n"\);)116 L (589 })0(657)100(fl.confused = 1;)116 L (590)0(658)100(return -1;)116 L (591 /*)0(659 })100 L (592 * if the controller or a specific drive is in a confused state,)0(660 if\(\(fl.stat[0] & \(Codemask|Seekend\)\) != Seekend\){)100 L (593 * reset it and get back to a kown state)0(661)100(DPRINT\("seek: failed\\n"\);)116 L (594 */)0(662)100(dp->confused = 1;)116 L (595 static void)0(663)100(return -1;)116 L (596 floppyrevive\(void\))0(664 })100 L (597 {)0(665)100 L (598 FDrive *dp;)0(666 dp->cyl = dp->tcyl;)100 L (599)0(667 dp->offset = off;)100 L (600 /*)0(668 DPRINT\("seek to %d succeeded\\n", dp->offset\);)100 L (601)0(* reset the controller if it's confused)9(669)100 L (602)0(*/)9(670 return dp->offset;)100 L (603 if\(fl.confused\){)0(671 })100 L (604)0(DPRINT\("floppyrevive in\\n"\);)16(672)100 L (605)0(fldump\(\);)16(673 /*)100 L (606)0(674 * read or write to floppy. try up to three times.)100 L (607)0(/* reset controller and turn all motors off */)16(675 */)100 L (608)0(splhi\(\);)16(676 static long)100 L (609)0(fl.ncmd = 1;)16(677 floppyxfer\(FDrive *dp, int cmd, void *a, long off, long n\))100 L (610)0(fl.cmd[0] = 0;)16(678 {)100 L (611)0(outb\(Pdor, 0\);)16(679 long offset;)100 L (612)0(delay\(10\);)16(680 int tries;)100 L cleartomark showpage saveobj restore %%EndPage: 241 241 %%Page: 242 242 /saveobj save def mark 242 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/devfloppy.c Page 6)l ()l ()l (681)0(749)100(* check for correct cylinder)117 L (682 if\(off >= dp->t->cap\))0(750)100(*/)117 L (683)0(return 0;)16(751)100(offset = fl.stat[3] * dp->t->heads + fl.stat[4];)116 L (684 if\(off + n > dp->t->cap\))0(752)100(offset = offset*dp->t->sectors + fl.stat[5] - 1;)116 L (685)0(n = dp->t->cap - off;)16(753)100(offset = offset * c2b[fl.stat[6]];)116 L (686)0(754)100(if\(offset != off+dp->len\){)116 L (687 /* retry on error \(until it gets ridiculous\) */)0(755)100(DPRINT\("xfer: ends on wrong cyl\\n"\);)124 L (688 for\(tries = 0; tries < dp->maxtries; tries++\){)0(756)100(dp->confused = 1;)124 L (689)0(757)100(continue;)124 L (690)0(dp->len = n;)16(758)100(})116 L (691)0(if\(pcfloppyseek\(dp, off\) < 0\){)16(759)100 L (692)0(DPRINT\("xfer: seek failed\\n"\);)24(760)100(dp->lasttouched = m->ticks;)116 L (693)0(dp->confused = 1;)24(761)100(dp->maxtries = 20;)116 L (694)0(continue;)24(762)100(return dp->len;)116 L (695)0(})16(763 })100 L (696)0(764)100 L (697)0(/*)16(765 return -1;)100 L (698)0(* set up the dma \(dp->len may be trimmed\))17(766 })100 L (699)0(*/)17(767)100 L (700)0(dp->len = dmasetup\(DMAchan, a, dp->len, cmd==Fread\);)16(768 static void)100 L (701)0(if\(dp->len < 0\){)16(769 floppyintr\(Ureg *ur\))100 L (702 buggery:)0(770 {)100 L (703)0(dmaend\(DMAchan\);)24(771 USED\(ur\);)100 L (704)0(continue;)24(772 switch\(fl.cmd[0]&~Fmulti\){)100 L (705)0(})16(773 case Fread:)100 L (706)0(774 case Fwrite:)100 L (707)0(/*)16(775 case Fformat:)100 L (708)0(* start operation)17(776 case Fdumpreg:)100 L (709)0(*/)17(777)100(floppyresult\(\);)116 L (710)0(fl.ncmd = 0;)16(778)100(break;)116 L (711)0(fl.cmd[fl.ncmd++] = cmd | \(dp->t->heads > 1 ? Fmulti : 0\);)16(779 case Fseek:)100 L (712)0(fl.cmd[fl.ncmd++] = \(dp->thead<<2\) | dp->dev;)16(780 case Frecal:)100 L (713)0(fl.cmd[fl.ncmd++] = dp->tcyl;)16(781 default:)100 L (714)0(fl.cmd[fl.ncmd++] = dp->thead;)16(782)100(floppysense\(\); /* to clear interrupt */)116 L (715)0(fl.cmd[fl.ncmd++] = dp->tsec;)16(783)100(break;)116 L (716)0(fl.cmd[fl.ncmd++] = dp->t->bcode;)16(784 })100 L (717)0(fl.cmd[fl.ncmd++] = dp->t->sectors;)16(785 fl.ncmd = 0;)100 L (718)0(fl.cmd[fl.ncmd++] = dp->t->gpl;)16(786 })100 L (719)0(fl.cmd[fl.ncmd++] = 0xFF;)16 L (720)0(if\(floppycmd\(\) < 0\))16 L (721)0(goto buggery;)24 L (722)l (723)0(/*)16 L (724)0(* give bus to DMA, floppyintr\(\) will read result)17 L (725)0(*/)17 L (726)0(floppywait\(\);)16 L (727)0(dmaend\(DMAchan\);)16 L (728)l (729)0(/*)16 L (730)0(* check for errors)17 L (731)0(*/)17 L (732)0(if\(fl.nstat < 7\){)16 L (733)0(DPRINT\("xfer: confused\\n"\);)24 L (734)0(fl.confused = 1;)24 L (735)0(continue;)24 L (736)0(})16 L (737)0(if\(\(fl.stat[0] & Codemask\)!=0 || fl.stat[1] || fl.stat[2]\){)16 L (738)0(DPRINT\("xfer: failed %lux %lux %lux\\n", fl.stat[0],)24 L (739)0(fl.stat[1], fl.stat[2]\);)32 L (740)0(DPRINT\("offset %lud len %d\\n", off, dp->len\);)24 L (741)0(if\(\(fl.stat[0]&Codemask\)==Cmdexec && fl.stat[1]==Overrun\){)24 L (742)0(DPRINT\("DMA overrun: retry\\n"\);)32 L (743)0(} else)24 L (744)0(dp->confused = 1;)32 L (745)0(continue;)24 L (746)0(})16 L (747)l (748)0(/*)16 L cleartomark showpage saveobj restore %%EndPage: 242 242 %%Page: 243 243 /saveobj save def mark 243 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dosboot.c Page 1)l ()l ()l (1 #include "u.h")0(69)100 L (2 #include "lib.h")0(70)100(/*)108 L (3 #include "mem.h")0(71)100(* make sure the buffer is big enough)109 L (4 #include "dat.h")0(72)100(*/)109 L (5 #include "fns.h")0(73)100(size = dos->clustsize*dos->sectsize;)108 L (6 #include "dosfs.h")0(74)100(if\(p->iobuf==0 || p->size < size\))108 L (7)0(75)100(p->iobuf = ialloc\(size, 0\);)116 L (8 /*)0(76)100(p->size = size;)108 L (9)0(* predeclared)7(77)100 L (10 */)0(78)100(/*)108 L (11 static void)0(bootdump\(Dosboot*\);)24(79)100(* read in the cluster)109 L (12 static void)0(setname\(Dosfile*, char*\);)24(80)100(*/)109 L (13)0(81)100(chat\("getclust addr %d\\n", \(sector+dos->start\)*dos->sectsize\);)108 L (14 /*)0(82)100(if\(\(*dos->seek\)\(dos, \(sector+dos->start\)*dos->sectsize\) < 0\){)108 L (15 * debugging)0(83)100(chat\("can't seek block\\n"\);)116 L (16 */)0(84)100(return 0;)116 L (17 #define chatty 0)0(85)100(})108 L (18 #define chat)0(if\(chatty\)print)24(86)100(if\(\(*dos->read\)\(dos, p->iobuf, size\) != size\){)108 L (19)0(87)100(chat\("can't read block\\n"\);)116 L (20 /*)0(88)100(return 0;)116 L (21 * block io buffers)0(89)100(})108 L (22 */)0(90)100 L (23 enum)0(91)100(p->age = m->ticks;)108 L (24 {)0(92)100(p->dos = dos;)108 L (25)0(Nbio= 16,)8(93)100(p->sector = sector;)108 L (26 };)0(94)100(chat\("getclust %d read\\n", sector\);)108 L (27 typedef struct Clustbuf)0(Clustbuf;)40(95)100(return p;)108 L (28 struct Clustbuf)0(96 })100 L (29 {)0(97)100 L (30)0(int age;)8(98 /*)100 L (31)0(long sector;)8(99 * walk the fat one level \( n is a current cluster number \).)100 L (32)0(uchar *iobuf;)8(100 * return the new cluster number or -1 if no more.)100 L (33)0(Dos *dos;)8(101 */)100 L (34)0(int size;)8(102 static long)100 L (35 };)0(103 fatwalk\(Dos *dos, int n\))100 L (36 Clustbuf bio[Nbio];)0(104 {)100 L (37)0(105 ulong k, sect;)100 L (38 /*)0(106 Clustbuf *p;)100 L (39 * get an io block from an io buffer)0(107 int o;)100 L (40 */)0(108)100 L (41 Clustbuf*)0(109 chat\("fatwalk %d\\n", n\);)100 L (42 getclust\(Dos *dos, long sector\))0(110)100 L (43 {)0(111 if\(n < 2 || n >= dos->fatclusters\))100 L (44)0(Clustbuf *p, *oldest;)8(112)100(return -1;)116 L (45)0(int size;)8(113)100 L (46)0(114 switch\(dos->fatbits\){)100 L (47)0(chat\("getclust @ %d\\n", sector\);)8(115 case 12:)100 L (48)0(116)100(k = \(3*n\)/2; break;)116 L (49)0(/*)8(117 case 16:)100 L (50)0(* if we have it, just return it)9(118)100(k = 2*n; break;)116 L (51)0(*/)9(119 case 32:)100 L (52)0(for\(p = bio; p < &bio[Nbio]; p++\){)8(120)100(k = 4*n; break;)116 L (53)0(if\(sector == p->sector && dos == p->dos\){)16(121 default:)100 L (54)0(p->age = m->ticks;)24(122)100(return -1;)116 L (55)0(chat\("getclust %d in cache\\n", sector\);)24(123 })100 L (56)0(return p;)24(124 if\(k >= dos->fatsize*dos->sectsize\))100 L (57)0(})16(125)100(panic\("getfat"\);)116 L (58)0(})8(126)100 L (59)0(127 sect = \(k/\(dos->sectsize*dos->clustsize\)\)*dos->clustsize + dos->fataddr;)100 L (60)0(/*)8(128 o = k%\(dos->sectsize*dos->clustsize\);)100 L (61)0(* otherwise, reuse the oldest entry)9(129 p = getclust\(dos, sect\);)100 L (62)0(*/)9(130 k = p->iobuf[o++];)100 L (63)0(oldest = bio;)8(131 if\(o >= dos->sectsize*dos->clustsize\){)100 L (64)0(for\(p = &bio[1]; p < &bio[Nbio]; p++\){)8(132)100(p = getclust\(dos, sect+dos->clustsize\);)116 L (65)0(if\(p->age <= oldest->age\))16(133)100(o = 0;)116 L (66)0(oldest = p;)24(134 })100 L (67)0(})8(135 k |= p->iobuf[o++]<<8;)100 L (68)0(p = oldest;)8(136 if\(dos->fatbits == 12\){)100 L cleartomark showpage saveobj restore %%EndPage: 243 243 %%Page: 244 244 /saveobj save def mark 244 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dosboot.c Page 2)l ()l ()l (137)0(if\(n&1\))16(205)100(* clusters start at 2 instead of 0 \(why? - presotto\))109 L (138)0(k >>= 4;)24(206)100(*/)109 L (139)0(else)16(207 l = dos->dataaddr + \(p-2\)*dos->clustsize;)100 L (140)0(k &= 0xfff;)24(208 chat\("fileaddr %d -> %d\\n", ltarget, l\);)100 L (141)0(if\(k >= 0xff8\))16(209 return l;)100 L (142)0(k = -1;)24(210 })100 L (143 })0(211)100 L (144 else if \(dos->fatbits == 32\){)0(212 /*)100 L (145)0(if\(o >= dos->sectsize*dos->clustsize\){)16(213 * read from a dos file)100 L (146)0(p = getclust\(dos, sect+dos->clustsize\);)24(214 */)100 L (147)0(o = 0;)24(215 long)100 L (148)0(})16(216 dosread\(Dosfile *fp, void *a, long n\))100 L (149)0(k |= p->iobuf[o++]<<16;)16(217 {)100 L (150)0(k |= p->iobuf[o]<<24;)16(218 long addr;)100 L (151)0(if \(k >= 0xfffffff8\))16(219 long rv;)100 L (152)0(k = -1;)24(220 int i;)100 L (153 })0(221 int off;)100 L (154 else)0(222 Clustbuf *p;)100 L (155)0(k = k < 0xfff8 ? k : -1;)16(223 uchar *from, *to;)100 L (156 chat\("fatwalk %d -> %d\\n", n, k\);)0(224)100 L (157 return k;)0(225 if\(\(fp->attr & DDIR\) == 0\){)100 L (158 })0(226)100(if\(fp->offset >= fp->length\))116 L (159)0(227)100(return 0;)124 L (160 /*)0(228)100(if\(fp->offset+n > fp->length\))116 L (161 * map a file's logical cluster address to a physical sector address)0(229)100(n = fp->length - fp->offset;)124 L (162 */)0(230 })100 L (163 static long)0(231)100 L (164 fileaddr\(Dosfile *fp, long ltarget\))0(232 to = a;)100 L (165 {)0(233 for\(rv = 0; rv < n; rv+=i\){)100 L (166 Dos *dos = fp->dos;)0(234)100(/*)116 L (167 long l;)0(235)100(* read the cluster)117 L (168 long p;)0(236)100(*/)117 L (169)0(237)100(addr = fileaddr\(fp, fp->offset/fp->dos->clustbytes\);)116 L (170 chat\("fileaddr %8.8s %d\\n", fp->name, ltarget\);)0(238)100(if\(addr < 0\))116 L (171 /*)0(239)100(return -1;)124 L (172)0(* root directory is contiguous and easy \(unless FAT32\))9(240)100(p = getclust\(fp->dos, addr\);)116 L (173)0(*/)9(241)100(if\(p == 0\))116 L (174 if\(fp->pstart == 0 && dos->rootsize != 0\) {)0(242)100(return -1;)124 L (175)0(if\(ltarget*dos->sectsize*dos->clustsize >= dos->rootsize*sizeof\(Dosdir\)\))16(243)100 L (176)0(return -1;)24(244)100(/*)116 L (177)0(l = dos->rootaddr + ltarget*dos->clustsize;)16(245)100(* copy the bytes we need)117 L (178)0(chat\("fileaddr %d -> %d\\n", ltarget, l\);)16(246)100(*/)117 L (179)0(return l;)16(247)100(off = fp->offset % fp->dos->clustbytes;)116 L (180 })0(248)100(from = &p->iobuf[off];)116 L (181)0(249)100(i = n - rv;)116 L (182 /*)0(250)100(if\(i > fp->dos->clustbytes - off\))116 L (183)0(* anything else requires a walk through the fat)9(251)100(i = fp->dos->clustbytes - off;)124 L (184)0(*/)9(252)100(memmove\(to, from, i\);)116 L (185 if\(ltarget >= fp->lcurrent && fp->pcurrent\){)0(253)100(to += i;)116 L (186)0(/* start at the currrent point */)16(254)100(fp->offset += i;)116 L (187)0(l = fp->lcurrent;)16(255 })100 L (188)0(p = fp->pcurrent;)16(256)100 L (189 } else {)0(257 return rv;)100 L (190)0(/* go back to the beginning */)16(258 })100 L (191)0(l = 0;)16(259)100 L (192)0(p = fp->pstart;)16(260 /*)100 L (193 })0(261 * walk a directory returns)100 L (194 while\(l != ltarget\){)0(262 *)100(-1 if something went wrong)116 L (195)0(/* walk the fat */)16(263 *)100(0 if not found)117 L (196)0(p = fatwalk\(dos, p\);)16(264 *)100(1 if found)117 L (197)0(if\(p < 0\))16(265 */)100 L (198)0(return -1;)24(266 int)100 L (199)0(l++;)16(267 doswalk\(Dosfile *file, char *name\))100 L (200 })0(268 {)100 L (201 fp->lcurrent = l;)0(269 Dosdir d;)100 L (202 fp->pcurrent = p;)0(270 long n;)100 L (203)0(271)100 L (204 /*)0(272 if\(\(file->attr & DDIR\) == 0\){)100 L cleartomark showpage saveobj restore %%EndPage: 244 244 %%Page: 245 245 /saveobj save def mark 245 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dosboot.c Page 3)l ()l ()l (273)0(chat\("walking non-directory!\\n"\);)16(341 dos->fatbits = 0;)100 L (274)0(return -1;)16(342 dos->sectsize = GSHORT\(b->sectsize\);)100 L (275 })0(343 dos->clustsize = b->clustsize;)100 L (276)0(344 dos->clustbytes = dos->sectsize*dos->clustsize;)100 L (277 setname\(file, name\);)0(345 dos->nresrv = GSHORT\(b->nresrv\);)100 L (278)0(346 dos->nfats = b->nfats;)100 L (279 file->offset = 0;)0(/* start at the beginning */)32(347 dos->fatsize = GSHORT\(b->fatsize\);)100 L (280 while\(\(n = dosread\(file, &d, sizeof\(d\)\)\) == sizeof\(d\)\){)0(348 dos->rootsize = GSHORT\(b->rootsize\);)100 L (281)0(chat\("comparing to %8.8s.%3.3s\\n", d.name, d.ext\);)16(349 dos->volsize = GSHORT\(b->volsize\);)100 L (282)0(if\(memcmp\(file->name, d.name, sizeof\(d.name\)\) != 0\))16(350 if\(dos->volsize == 0\))100 L (283)0(continue;)24(351)100(dos->volsize = GLONG\(b->bigvolsize\);)116 L (284)0(if\(memcmp\(file->ext, d.ext, sizeof\(d.ext\)\) != 0\))16(352 dos->mediadesc = b->mediadesc;)100 L (285)0(continue;)24(353 if\(dos->fatsize == 0\) {)100 L (286)0(if\(d.attr & DVLABEL\){)16(354)100(chat\("fat32\\n"\);)116 L (287)0(chat\("%8.8s.%3.3s is a LABEL\\n", d.name, d.ext\);)24(355)100(dos->rootsize = 0;)116 L (288)0(continue;)24(356)100(dos->fatsize = GLONG\(b->bigfatsize\);)116 L (289)0(})16(357)100(dos->fatbits = 32;)116 L (290)0(file->attr = d.attr;)16(358 })100 L (291)0(file->pstart = GSHORT\(d.start\);)16(359 dos->fataddr = dos->nresrv;)100 L (292)0(if \(file->dos->fatbits == 32\))16(360 if \(dos->rootsize == 0\) {)100 L (293)0(file->pstart |= GSHORT\(d.highstart\) << 16;)24(361)100(dos->rootaddr = 0;)116 L (294)0(file->length = GLONG\(d.length\);)16(362)100(dos->rootclust = GLONG\(b->rootdirstartclust\);)116 L (295)0(file->pcurrent = 0;)16(363)100(dos->dataaddr = dos->fataddr + dos->nfats*dos->fatsize;)116 L (296)0(file->lcurrent = 0;)16(364 } else {)100 L (297)0(file->offset = 0;)16(365)100(dos->rootaddr = dos->fataddr + dos->nfats*dos->fatsize;)116 L (298)0(return 1;)16(366)100(i = dos->rootsize*sizeof\(Dosdir\) + dos->sectsize - 1;)116 L (299 })0(367)100(i = i/dos->sectsize;)116 L (300 return n >= 0 ? 0 : -1;)0(368)100(dos->dataaddr = dos->rootaddr + i;)116 L (301 })0(369 })100 L (302)0(370 dos->fatclusters = 2+\(dos->volsize - dos->dataaddr\)/dos->clustsize;)100 L (303 /*)0(371 if\(dos->fatbits != 32\) {)100 L (304 * instructions that boot blocks can start with)0(372)100(if\(dos->fatclusters < 4087\))116 L (305 */)0(373)100(dos->fatbits = 12;)124 L (306 #define JMPSHORT)0(0xeb)32(374)100(else)116 L (307 #define JMPNEAR)0(0xe9)32(375)100(dos->fatbits = 16;)124 L (308)0(376 })100 L (309 int)0(377 dos->freeptr = 2;)100 L (310 dosinit\(Dos *dos\))0(378)100 L (311 {)0(379 /*)100 L (312 Clustbuf *p;)0(380)100(* set up the root)109 L (313 Dosboot *b;)0(381)100(*/)109 L (314 int i;)0(382 dos->root.dos = dos;)100 L (315)0(383 dos->root.pstart = dos->rootsize == 0 ? dos->rootclust : 0;)100 L (316 /* defaults till we know better */)0(384 dos->root.pcurrent = dos->root.lcurrent = 0;)100 L (317 dos->sectsize = 512;)0(385 dos->root.offset = 0;)100 L (318 dos->clustsize = 1;)0(386 dos->root.attr = DDIR;)100 L (319)0(387 dos->root.length = dos->rootsize*sizeof\(Dosdir\);)100 L (320 /* get first sector */)0(388)100 L (321 p = getclust\(dos, 0\);)0(389 return 0;)100 L (322 if\(p == 0\){)0(390 })100 L (323)0(chat\("can't read boot block\\n"\);)16(391)100 L (324)0(return -1;)16(392 static void)100 L (325 })0(393 bootdump\(Dosboot *b\))100 L (326)0(394 {)100 L (327 p->dos = 0;)0(395 if\(chatty == 0\))100 L (328 b = \(Dosboot *\)p->iobuf;)0(396)100(return;)116 L (329 if\(b->magic[0] != JMPNEAR && \(b->magic[0] != JMPSHORT || b->magic[2] != 0x90\)\){)0(397 print\("magic: 0x%2.2x 0x%2.2x 0x%2.2x\\n",)100 L (330)0(chat\("no dos file system %x %x %x %x\\n",)16(398)100(b->magic[0], b->magic[1], b->magic[2]\);)116 L (331)0(b->magic[0], b->magic[1], b->magic[2], b->magic[3]\);)24(399 print\("version: \\"%8.8s\\"\\n", b->version\);)100 L (332)0(return -1;)16(400 print\("sectsize: %d\\n", GSHORT\(b->sectsize\)\);)100 L (333 })0(401 print\("allocsize: %d\\n", b->clustsize\);)100 L (334)0(402 print\("nresrv: %d\\n", GSHORT\(b->nresrv\)\);)100 L (335 if\(chatty\))0(403 print\("nfats: %d\\n", b->nfats\);)100 L (336)0(bootdump\(b\);)16(404 print\("rootsize: %d\\n", GSHORT\(b->rootsize\)\);)100 L (337)0(405 print\("volsize: %d\\n", GSHORT\(b->volsize\)\);)100 L (338 /*)0(406 print\("mediadesc: 0x%2.2x\\n", b->mediadesc\);)100 L (339)0(* determine the systems' wondersous properties)9(407 print\("fatsize: %d\\n", GSHORT\(b->fatsize\)\);)100 L (340)0(*/)9(408 print\("trksize: %d\\n", GSHORT\(b->trksize\)\);)100 L cleartomark showpage saveobj restore %%EndPage: 245 245 %%Page: 246 246 /saveobj save def mark 246 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dosboot.c Page 4)l ()l ()l (409 print\("nheads: %d\\n", GSHORT\(b->nheads\)\);)0(477)100(if\(n <= 0\))116 L (410 print\("nhidden: %d\\n", GLONG\(b->nhidden\)\);)0(478)100(break;)124 L (411 print\("bigvolsize: %d\\n", GLONG\(b->bigvolsize\)\);)0(479)100(print\("."\);)116 L (412 /*)0(480 })100 L (413 print\("driveno: %d\\n", b->driveno\);)0(481 return sofar;)100 L (414 print\("reserved0: 0x%2.2x\\n", b->reserved0\);)0(482 })100 L (415 print\("bootsig: 0x%2.2x\\n", b->bootsig\);)0(483)100 L (416 print\("volid: 0x%8.8x\\n", GLONG\(b->volid\)\);)0(484 /*)100 L (417 print\("label: \\"%11.11s\\"\\n", b->label\);)0(485 * boot)100 L (418 */)0(486 */)100 L (419 })0(487 int)100 L (420)0(488 dosboot\(Dos *dos, char *path, Boot *b\))100 L (421 /*)0(489 {)100 L (422 * grab next element from a path, return the pointer to unprocessed portion of)0(490 Dosfile file;)100 L (423 * path.)0(491 long n;)100 L (424 */)0(492 static char buf[8192];)100 L (425 static char *)0(493)100 L (426 nextelem\(char *path, char *elem\))0(494 switch\(dosstat\(dos, path, &file\)\){)100 L (427 {)0(495 case -1:)100 L (428 int i;)0(496)100(print\("error walking to %s\\n", path\);)116 L (429)0(497)100(return -1;)116 L (430 while\(*path == '/'\))0(498 case 0:)100 L (431)0(path++;)16(499)100(print\("%s not found\\n", path\);)116 L (432 if\(*path==0 || *path==' '\))0(500)100(return -1;)116 L (433)0(return 0;)16(501 case 1:)100 L (434 for\(i=0; *path!='\\0' && *path!='/' && *path!=' '; i++\){)0(502)100(print\("found %8.8s.%3.3s attr 0x%ux start 0x%lux len %d\\n", file.name,)116 L (435)0(if\(i==28\){)16(503)100(file.ext, file.attr, file.pstart, file.length\);)124 L (436)0(print\("name component too long\\n"\);)24(504)100(break;)116 L (437)0(return 0;)24(505 })100 L (438)0(})16(506)100 L (439)0(*elem++ = *path++;)16(507 while\(\(n = dosreadseg\(&file, buf, sizeof buf\)\) > 0\) {)100 L (440 })0(508)100(if\(bootpass\(b, buf, n\) != MORE\))116 L (441 *elem = '\\0';)0(509)100(break;)124 L (442 return path;)0(510 })100 L (443 })0(511)100 L (444)0(512 bootpass\(b, nil, 0\); /* tries boot */)100 L (445 int)0(513 return -1;)100 L (446 dosstat\(Dos *dos, char *path, Dosfile *f\))0(514 })100 L (447 {)0(515)100 L (448 char element[NAMELEN];)0(516 /*)100 L (449)0(517 * set up a dos file name)100 L (450 *f = dos->root;)0(518 */)100 L (451 while\(path = nextelem\(path, element\)\){)0(519 static void)100 L (452)0(switch\(doswalk\(f, element\)\){)16(520 setname\(Dosfile *fp, char *from\))100 L (453)0(case -1:)16(521 {)100 L (454)0(return -1;)24(522 char *to;)100 L (455)0(case 0:)16(523)100 L (456)0(return 0;)24(524 to = fp->name;)100 L (457)0(})16(525 for\(; *from && to-fp->name < 8; from++, to++\){)100 L (458 })0(526)100(if\(*from == '.'\){)116 L (459 return 1;)0(527)100(from++;)124 L (460 })0(528)100(break;)124 L (461)0(529)100(})116 L (462 /*)0(530)100(if\(*from >= 'a' && *from <= 'z'\))116 L (463 * read in a segment)0(531)100(*to = *from + 'A' - 'a';)124 L (464 */)0(532)100(else)116 L (465 long)0(533)100(*to = *from;)124 L (466 dosreadseg\(Dosfile *fp, void *va, long len\))0(534 })100 L (467 {)0(535 while\(to - fp->name < 8\))100 L (468 char *a;)0(536)100(*to++ = ' ';)116 L (469 long n, sofar;)0(537)100 L (470)0(538 to = fp->ext;)100 L (471 a = va;)0(539 for\(; *from && to-fp->ext < 3; from++, to++\){)100 L (472 for\(sofar = 0; sofar < len; sofar += n\){)0(540)100(if\(*from >= 'a' && *from <= 'z'\))116 L (473)0(n = 8*1024;)16(541)100(*to = *from + 'A' - 'a';)124 L (474)0(if\(len - sofar < n\))16(542)100(else)116 L (475)0(n = len - sofar;)24(543)100(*to = *from;)124 L (476)0(n = dosread\(fp, a + sofar, n\);)16(544 })100 L cleartomark showpage saveobj restore %%EndPage: 246 246 %%Page: 247 247 /saveobj save def mark 247 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/dosboot.c Page 5)l ()l ()l (545 while\(to-fp->ext < 3\))l (546)0(*to++ = ' ';)16 L (547)l (548 chat\("name is %8.8s %3.3s\\n", fp->name, fp->ext\);)l (549 })l cleartomark showpage saveobj restore %%EndPage: 247 247 %%Page: 248 248 /saveobj save def mark 248 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/ether8003.c Page 1)l ()l ()l (1 #include "u.h")0(69 static void)100 L (2 #include "lib.h")0(70 reset8003\(Ether* ether, uchar ea[Eaddrlen], uchar ic[8]\))100 L (3 #include "mem.h")0(71 {)100 L (4 #include "dat.h")0(72)100(Dp8390 *ctlr;)108 L (5 #include "fns.h")0(73)100(ulong port;)108 L (6 #include "io.h")0(74)100 L (7)0(75)100(ctlr = ether->ctlr;)108 L (8 #include "etherif.h")0(76)100(port = ether->port;)108 L (9 #include "ether8390.h")0(77)100 L (10)0(78)100(/*)108 L (11 /*)0(79)100(* Check for old, dumb 8003E, which doesn't have an interface)109 L (12 * Western Digital/Standard Microsystems Corporation cards \(WD80[01]3\).)0(80)100(* chip. Only Msr exists out of the 1st eight registers, reads)109 L (13 * Also handles 8216 cards \(Elite Ultra\).)0(81)100(* of the others just alias the 2nd eight registers, the LAN)109 L (14 * Configuration code based on that provided by SMC a long time ago.)0(82)100(* address ROM. Can check Icr, Irr and Laar against the ethernet)109 L (15 */)0(83)100(* address read above and if they match it's an 8003E \(or an)109 L (16 enum {)0(/* 83C584 Bus Interface Controller */)48(84)100(* 8003EBT, 8003S, 8003SH or 8003WT, doesn't matter\), in which)109 L (17)0(Msr)8(= 0x00,)24(/* Memory Select Register */)40(85)100(* case the default irq gets used.)109 L (18)0(Icr)8(= 0x01,)24(/* Interface Configuration Register */)40(86)100(*/)109 L (19)0(Iar)8(= 0x02,)24(/* I/O Address Register */)40(87)100(if\(memcmp\(&ea[1], &ic[1], 5\) == 0\){)108 L (20)0(Bio)8(= 0x03,)24(/* BIOS ROM Address Register */)40(88)100(memset\(ic, 0, sizeof\(ic\)\);)116 L (21)0(Ear)8(= 0x03,)24(/* EEROM Address Register \(shared with Bio\) */)40(89)100(ic[Msr] = \(\(\(ulong\)ether->mem\)>>13\) & 0x3F;)116 L (22)0(Irr)8(= 0x04,)24(/* Interrupt Request Register */)40(90)100(})108 L (23)0(Hcr)8(= 0x04,)24(/* 8216 hardware control */)40(91)100(else{)108 L (24)0(Laar)8(= 0x05,)24(/* LA Address Register */)40(92)100(/*)116 L (25)0(Ijr)8(= 0x06,)24(/* Initialisation Jumpers */)40(93)100(* As a final sanity check for the 8013EBT, which doesn't have)117 L (26)0(Gp2)8(= 0x07,)24(/* General Purpose Data Register */)40(94)100(* the 83C584 interface chip, but has 2 real registers, write Gp2)117 L (27)0(Lar)8(= 0x08,)24(/* LAN Address Registers */)40(95)100(* and if it reads back the same, it's not an 8013EBT.)117 L (28)0(Id)8(= 0x0E,)24(/* Card ID byte */)40(96)100(*/)117 L (29)0(Cksum)8(= 0x0F,)24(/* Checksum */)40(97)100(outb\(port+Gp2, 0xAA\);)116 L (30 };)0(98)100(inb\(port+Msr\);)116(/* wiggle bus */)156 L (31)0(99)100(if\(inb\(port+Gp2\) != 0xAA\){)116 L (32 enum {)0(/* Msr */)48(100)100(memset\(ic, 0, sizeof\(ic\)\);)124 L (33)0(Rst)8(= 0x80,)24(/* software reset */)40(101)100(ic[Msr] = \(\(\(ulong\)ether->mem\)>>13\) & 0x3F;)124 L (34)0(Menb)8(= 0x40,)24(/* memory enable */)40(102)100(})116 L (35 };)0(103)100(else)116 L (36)0(104)100(ether->irq = irq8003[\(\(ic[Irr]>>5\) & 0x3\)|\(ic[Icr] & 0x4\)];)124 L (37 enum {)0(/* Icr */)48(105)100 L (38)0(Bit16)8(= 0x01,)24(/* 16-bit bus */)40(106)100(/*)116 L (39)0(Other)8(= 0x02,)24(/* other register access */)40(107)100(* Check if 16-bit card.)117 L (40)0(Ir2)8(= 0x04,)24(/* IR2 */)40(108)100(* If Bit16 is read/write, then it's an 8-bit card.)117 L (41)0(Msz)8(= 0x08,)24(/* SRAM size */)40(109)100(* If Bit16 is set, it's in a 16-bit slot.)117 L (42)0(Rla)8(= 0x10,)24(/* recall LAN address */)40(110)100(*/)117 L (43)0(Rx7)8(= 0x20,)24(/* recall all but I/O and LAN address */)40(111)100(outb\(port+Icr, ic[Icr]^Bit16\);)116 L (44)0(Rio)8(= 0x40,)24(/* recall I/O address from EEROM */)40(112)100(inb\(port+Msr\);)116(/* wiggle bus */)156 L (45)0(Sto)8(= 0x80,)24(/* non-volatile EEROM store */)40(113)100(if\(\(inb\(port+Icr\) & Bit16\) == \(ic[Icr] & Bit16\)\){)116 L (46 };)0(114)100(ctlr->width = 2;)124 L (47)0(115)100(ic[Icr] &= ~Bit16;)124 L (48 enum {)0(/* Laar */)48(116)100(})116 L (49)0(ZeroWS16)8(= 0x20,)24(/* zero wait states for 16-bit ops */)40(117)100(outb\(port+Icr, ic[Icr]\);)116 L (50)0(L16en)8(= 0x40,)24(/* enable 16-bit LAN operation */)40(118)100 L (51)0(M16en)8(= 0x80,)24(/* enable 16-bit memory access */)40(119)100(if\(ctlr->width == 2 && \(inb\(port+Icr\) & Bit16\) == 0\))116 L (52 };)0(120)100(ctlr->width = 1;)124 L (53)0(121 })100 L (54 enum {)0(/* Ijr */)48(122)100 L (55)0(Ienable)8(= 0x01,)24(/* 8216 interrupt enable */)40(123 ether->mem = \(ulong\)KADDR\(\(ic[Msr] & 0x3F\)<<13\);)100 L (56 };)0(124 if\(ctlr->width == 2\))100 L (57)0(125)100(ether->mem |= \(ic[Laar] & 0x1F\)<<19;)116 L (58 /*)0(126 else)100 L (59 * Mapping from configuration bits to interrupt level.)0(127)100(ether->mem |= 0x80000;)116 L (60 */)0(128)100 L (61 static int irq8003[8] = {)0(129 if\(ic[Icr] & \(1<<3\)\))100 L (62)0(9, 3, 5, 7, 10, 11, 15, 4,)8(130)100(ether->size = 32*1024;)116 L (63 };)0(131 if\(ctlr->width == 2\))100 L (64)0(132)100(ether->size <<= 1;)116 L (65 static int irq8216[8] = {)0(133)100 L (66)0(0, 9, 3, 5, 7, 10, 11, 15,)8(134 /*)100 L (67 };)0(135)100(* Enable interface RAM, set interface width.)109 L (68)0(136)100(*/)109 L cleartomark showpage saveobj restore %%EndPage: 248 248 %%Page: 249 249 /saveobj save def mark 249 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/ether8003.c Page 2)l ()l ()l (137 outb\(port+Msr, ic[Msr]|Menb\);)0(205 /*)100 L (138 if\(ctlr->width == 2\))0(206)100(* Look for the interface. Read the LAN address ROM)109 L (139)0(outb\(port+Laar, ic[Laar]|L16en|M16en|ZeroWS16\);)16(207)100(* and validate the checksum - the sum of all 8 bytes)109 L (140 })0(208)100(* should be 0xFF.)109 L (141)0(209)100(* At the same time, get the \(possible\) interface chip)109 L (142 static void)0(210)100(* registers, they'll be used later to check for aliasing.)109 L (143 reset8216\(Ether* ether, uchar[8]\))0(211)100(*/)109 L (144 {)0(212 port = ether->port;)100 L (145 uchar hcr, irq, x;)0(213 sum = 0;)100 L (146 ulong addr, port;)0(214 for\(i = 0; i < sizeof\(ea\); i++\){)100 L (147 Dp8390 *ctlr;)0(215)100(ea[i] = inb\(port+Lar+i\);)116 L (148)0(216)100(sum += ea[i];)116 L (149 ctlr = ether->ctlr;)0(217)100(ic[i] = inb\(port+i\);)116 L (150 port = ether->port;)0(218 })100 L (151)0(219 id = inb\(port+Id\);)100 L (152 ctlr->width = 2;)0(220 sum += id;)100 L (153)0(221 sum += inb\(port+Cksum\);)100 L (154 /*)0(222 if\(sum != 0xFF\))100 L (155)0(* Switch to the alternate register set and retrieve the memory)9(223)100(return -1;)116 L (156)0(* and irq information.)9(224)100 L (157)0(*/)9(225 ether->ctlr = malloc\(sizeof\(Dp8390\)\);)100 L (158 hcr = inb\(port+Hcr\);)0(226 ctlr = ether->ctlr;)100 L (159 outb\(port+Hcr, 0x80|hcr\);)0(227 ctlr->ram = 1;)100 L (160 addr = inb\(port+0x0B\) & 0xFF;)0(228)100 L (161 irq = inb\(port+0x0D\);)0(229 if\(\(id & 0xFE\) == 0x2A\))100 L (162 outb\(port+Hcr, hcr\);)0(230)100(reset8216\(ether, ic\);)116 L (163)0(231 else)100 L (164 ether->mem = \(ulong\)KADDR\(0xC0000+\(\(\(\(addr>>2\) & 0x30\)|\(addr & 0x0F\)\)<<13\)\);)0(232)100(reset8003\(ether, ea, ic\);)116 L (165 ether->size = 8192*\(1<<\(\(addr>>4\) & 0x03\)\);)0(233)100 L (166 ether->irq = irq8216[\(\(irq>>4\) & 0x04\)|\(\(irq>>2\) & 0x03\)];)0(234 /*)100 L (167)0(235)100(* Set the DP8390 ring addresses.)109 L (168 /*)0(236)100(*/)109 L (169)0(* Enable interface RAM, set interface width, and enable interrupts.)9(237 ctlr->port = port+0x10;)100 L (170)0(*/)9(238 ctlr->tstart = 0;)100 L (171 x = inb\(port+Msr\) & ~Rst;)0(239 ctlr->pstart = HOWMANY\(sizeof\(Etherpkt\), Dp8390BufSz\);)100 L (172 outb\(port+Msr, Menb|x\);)0(240 ctlr->pstop = HOWMANY\(ether->size, Dp8390BufSz\);)100 L (173 x = inb\(port+Laar\);)0(241)100 L (174 outb\(port+Laar, M16en|x\);)0(242 /*)100 L (175 outb\(port+Ijr, Ienable\);)0(243)100(* Finally, init the 8390, set the ethernet address)109 L (176 })0(244)100(* and claim the memory used.)109 L (177)0(245)100(*/)109 L (178 /*)0(246 dp8390reset\(ether\);)100 L (179 * Get configuration parameters, enable memory.)0(247 memset\(nullea, 0, Eaddrlen\);)100 L (180 * There are opportunities here for buckets of code, try to resist.)0(248 if\(memcmp\(nullea, ether->ea, Eaddrlen\) == 0\){)100 L (181 */)0(249)100(for\(i = 0; i < sizeof\(ether->ea\); i++\))116 L (182 int)0(250)100(ether->ea[i] = ea[i];)124 L (183 wd8003reset\(Ether* ether\))0(251 })100 L (184 {)0(252 dp8390setea\(ether\);)100 L (185 int i;)0(253)100 L (186 uchar ea[Eaddrlen], ic[8], id, nullea[Eaddrlen], sum;)0(254 if\(umbrwmalloc\(PADDR\(ether->mem\), ether->size, 0\) == 0\))100 L (187 ulong port;)0(255)100(print\("ether8003: warning - 0x%luX unavailable", PADDR\(ether->mem\)\);)116 L (188 Dp8390 *ctlr;)0(256)100 L (189)0(257 return 0;)100 L (190 /*)0(258 })100 L (191)0(* Set up the software configuration.)9 L (192)0(* Use defaults for port, irq, mem and size if not specified.)9 L (193)0(* Defaults are set for the dumb 8003E which can't be)9 L (194)0(* autoconfigured.)9 L (195)0(*/)9 L (196 if\(ether->port == 0\))l (197)0(ether->port = 0x280;)16 L (198 if\(ether->irq == 0\))l (199)0(ether->irq = 3;)16 L (200 if\(ether->mem == 0\))l (201)0(ether->mem = 0xD0000;)16 L (202 if\(ether->size == 0\))l (203)0(ether->size = 8*1024;)16 L (204)l cleartomark showpage saveobj restore %%EndPage: 249 249 %%Page: 250 250 /saveobj save def mark 250 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/fns.h Page 1)l ()l ()l (1 void)0(aamloop\(int\);)16(69 void)100(pcicfgw16\(Pcidev*, int, int\);)116 L (2 void)0(addconf\(char*, ...\);)16(70 void)100(pcicfgw32\(Pcidev*, int, int\);)116 L (3 Alarm* alarm\(int, void \(*\)\(Alarm*\), void*\);)0(71 Pcidev* pcimatch\(Pcidev*, int, int\);)100 L (4 void)0(alarminit\(void\);)16(72 void)100(pcireset\(void\);)116 L (5 Block* allocb\(int\);)0(73 void)100(pcisetbme\(Pcidev*\);)116 L (6 int)0(bootp\(int, char*, Boot*\);)16(74 int)100(pcmcistuple\(int, int, void*, int\);)116 L (7 int)0(bootpass\(Boot*, void*, int\);)16(75 int)100(pcmspecial\(char*, ISAConf*\);)116 L (8 void)0(cancel\(Alarm*\);)16(76 void)100(pcmspecialclose\(int\);)116 L (9 void)0(cgascreenputs\(char*, int\);)16(77 void)100(pcmunmap\(int, PCMmap*\);)116 L (10 int)0(cistrcmp\(char*, char*\);)16(78 void)100(putcr3\(ulong\);)116 L (11 int)0(cistrncmp\(char*, char*, int\);)16(79 void)100(putidt\(Segdesc*, int\);)116 L (12 void)0(checkalarms\(void\);)16(80 void)100(qinit\(IOQ*\);)116 L (13 void)0(clockinit\(void\);)16(81 void)100(sdaddconf\(int\);)116 L (14 int)0(conschar\(void\);)16(82 int)100(sdboot\(int, char*, Boot*\);)116 L (15 void)0(consdrain\(void\);)16(83 void* sdgetdospart\(int, char*\);)100 L (16 void)0(consinit\(void\);)16(84 int)100(sdinit\(void\);)116 L (17 void)0(consputs\(char*, int\);)16(85 void)100(sdinitdev\(int, char*\);)116 L (18 void)0(delay\(int\);)16(86 int)100(sdsetpart\(int, char*\);)116 L (19 uchar* etheraddr\(int\);)0(87 void)100(setvec\(int, void \(*\)\(Ureg*, void*\), void*\);)116 L (20 int)0(etherinit\(void\);)16(88 int)100(splhi\(void\);)116 L (21 void)0(etherinitdev\(int, char*\);)16(89 int)100(spllo\(void\);)116 L (22 int)0(etherrxpkt\(int, Etherpkt*, int\);)16(90 void)100(splx\(int\);)116 L (23 int)0(ethertxpkt\(int, Etherpkt*, int, int\);)16(91 void)100(trapinit\(void\);)116 L (24 #define evenaddr\(x\))0(/* 386 doesn't care */)40(92 void)100(uartdrain\(void\);)116 L (25 int)0(floppyboot\(int, char*, Boot*\);)16(93 void)100(uartspecial\(int, void \(*\)\(int\), int \(*\)\(void\), int\);)116 L (26 int)0(floppyinit\(void\);)16(94 void)100(uartputs\(IOQ*, char*, int\);)116 L (27 void)0(floppyinitdev\(int, char*\);)16(95 ulong umbmalloc\(ulong, int, int\);)100 L (28 void* floppygetdospart\(int, char*\);)0(96 void)100(umbfree\(ulong, int\);)116 L (29 void)0(freeb\(Block*\);)16(97 ulong umbrwmalloc\(ulong, int, int\);)100 L (30 char* getconf\(char*\);)0(98 void)100(warp9\(ulong\);)116 L (31 ulong getcr0\(void\);)0(99 int)100(x86cpuid\(int*, int*\);)116 L (32 ulong getcr2\(void\);)0(100)100 L (33 ulong getcr3\(void\);)0(101 #define malloc\(n\) ialloc\(n, 0\))100 L (34 int)0(getfields\(char*, char**, int, char\);)16(102 #define free\(v\))100 L (35 int)0(getstr\(char*, char*, int, char*, int\);)16(103)100 L (36 int)0(gunzip\(uchar*, int, uchar*, int\);)16(104 #define GSHORT\(p\))100(\(\(\(p\)[1]<<8\)|\(p\)[0]\))132 L (37 void)0(i8042a20\(void\);)16(105 #define GLONG\(p\))100(\(\(GSHORT\(p+2\)<<16\)|GSHORT\(p\)\))132 L (38 void)0(i8042reset\(void\);)16(106 #define GLSHORT\(p\))100(\(\(\(p\)[0]<<8\)|\(p\)[1]\))132 L (39 void* ialloc\(ulong, int\);)0(107 #define GLLONG\(p\))100(\(\(GLSHORT\(p\)<<16\)|GLSHORT\(p+2\)\))132 L (40 void)0(idle\(void\);)16(108)100 L (41 void)0(ilock\(Lock*\);)16(109 #define KADDR\(a\) \(\(void*\)\(\(ulong\)\(a\)|KZERO\)\))100 L (42 int)0(inb\(int\);)16(110 #define PADDR\(a\) \(\(ulong\)\(a\)&~KZERO\))100 L (43 ushort ins\(int\);)0(111)100 L (44 ulong inl\(int\);)0(112 #define HOWMANY\(x, y\) \(\(\(x\)+\(\(y\)-1\)\)/\(y\)\))100 L (45 void)0(insb\(int, void*, int\);)16(113 #define ROUNDUP\(x, y\) \(HOWMANY\(\(x\), \(y\)\)*\(y\)\))100 L (46 void)0(inss\(int, void*, int\);)16(114)100 L (47 void)0(insl\(int, void*, int\);)16(115)100 L (48 void)0(iunlock\(Lock*\);)16(116 #define xalloc\(n\) ialloc\(n, 0\))100 L (49 int)0(isaconfig\(char*, int, ISAConf*\);)16(117 #define xfree\(v\))100 L (50 void)0(kbdinit\(void\);)16(118 #define lock\(l\) if\(l\);else;)100 L (51 void)0(kbdchar\(int\);)16(119 #define unlock\(l\) if\(l\);else;)100 L (52 void)0(machinit\(void\);)16(120)100 L (53 void)0(meminit\(ulong\);)16(121 int)100(dmacount\(int\);)116 L (54 void)0(microdelay\(int\);)16(122 int)100(dmadone\(int\);)116 L (55 void)0(mmuinit\(void\);)16(123 void)100(dmaend\(int\);)116 L (56 #define nelem\(x\))0(\(sizeof\(x\)/sizeof\(x[0]\)\))32(124 void)100(dmainit\(int\);)116 L (57 uchar nvramread\(int\);)0(125 long)100(dmasetup\(int, void*, long, int\);)116 L (58 void)0(outb\(int, int\);)16(126)100 L (59 void)0(outs\(int, ushort\);)16 L (60 void)0(outl\(int, ulong\);)16 L (61 void)0(outsb\(int, void*, int\);)16 L (62 void)0(outss\(int, void*, int\);)16 L (63 void)0(outsl\(int, void*, int\);)16 L (64 void)0(panic\(char*, ...\);)16 L (65 int)0(pcicfgr8\(Pcidev*, int\);)16 L (66 int)0(pcicfgr16\(Pcidev*, int\);)16 L (67 int)0(pcicfgr32\(Pcidev*, int\);)16 L (68 void)0(pcicfgw8\(Pcidev*, int, int\);)16 L cleartomark showpage saveobj restore %%EndPage: 250 250 %%Page: 251 251 /saveobj save def mark 251 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/io.h Page 1)l ()l ()l (1 /*)0(69)100 L (2)0(* programmable interrupt vectors \(for the 8259's\))7(70 #define MKBUS\(t,b,d,f\) \(\(\(t\)<<24\)|\(\(\(b\)&0xFF\)<<16\)|\(\(\(d\)&0x1F\)<<11\)|\(\(\(f\)&0x07\)<<8\)\))100 L (3)0(*/)7(71 #define BUSFNO\(tbdf\))100(\(\(\(tbdf\)>>8\)&0x07\))132 L (4 enum)0(72 #define BUSDNO\(tbdf\))100(\(\(\(tbdf\)>>11\)&0x1F\))132 L (5 {)0(73 #define BUSBNO\(tbdf\))100(\(\(\(tbdf\)>>16\)&0xFF\))132 L (6)0(Bptvec=)8(3,)24(/* breakpoints */)40(74 #define BUSTYPE\(tbdf\) \(\(tbdf\)>>24\))100 L (7)0(Mathemuvec= 7,)8(/* math coprocessor emulation interrupt */)40(75 #define BUSBDF\(tbdf\))100(\(\(tbdf\)&0x00FFFF00\))132 L (8)0(Mathovervec= 9,)8(/* math coprocessor overrun interrupt */)40(76 #define BUSUNKNOWN)100(\(-1\))132 L (9)0(Matherr1vec= 16,)8(/* math coprocessor error interrupt */)40(77)100 L (10)0(Faultvec=)8(14,)24(/* page fault */)40(78 enum {)100 L (11)0(79)100(MaxEISA)108(= 16,)124 L (12 #ifdef notdef)0(80)100(EISAconfig)108(= 0xC80,)124 L (13)0(Int0vec=)8(24,)24(/* first 8259 */)40(81 };)100 L (14)0(Clockvec=)9(Int0vec+0,)24(/* clock interrupts */)40(82)100 L (15)0(Kbdvec=)9(Int0vec+1,)24(/* keyboard interrupts */)40(83 /*)100 L (16)0(Uart1vec=)9(Int0vec+3,)24(/* modem line */)40(84 * PCI support code.)100 L (17)0(Uart0vec=)9(Int0vec+4,)24(/* serial line */)40(85 */)100 L (18)0(PCMCIAvec= Int0vec+5,)9(/* PCMCIA card change */)40(86 enum {)100(/* type 0 and type 1 pre-defined header */)148 L (19)0(Floppyvec= Int0vec+6,)9(/* floppy interrupts */)40(87)100(PciVID)108(= 0x00,)124(/* vendor ID */)140 L (20)0(Parallelvec= Int0vec+7,)9(/* parallel port interrupts */)40(88)100(PciDID)108(= 0x02,)124(/* device ID */)140 L (21)0(Int1vec=)8(Int0vec+8,)24(89)100(PciPCR)108(= 0x04,)124(/* command */)140 L (22)0(Vector9=)9(Int0vec+9,)24(/* unassigned */)40(90)100(PciPSR)108(= 0x06,)124(/* status */)140 L (23)0(Vector10=)9(Int0vec+10, /* unassigned, usually ethernet */)24(91)100(PciRID)108(= 0x08,)124(/* revision ID */)140 L (24)0(Vector11=)9(Int0vec+11, /* unassigned, usually scsi */)24(92)100(PciCCRp)108(= 0x09,)124(/* programming interface class code */)140 L (25)0(Mousevec=)9(Int0vec+12, /* mouse interrupt */)24(93)100(PciCCRu)108(= 0x0A,)124(/* sub-class code */)140 L (26)0(Matherr2vec= Int0vec+13, /* math coprocessor */)9(94)100(PciCCRb)108(= 0x0B,)124(/* base class code */)140 L (27)0(ATAvec0=)9(Int0vec+14, /* ATA controller #1 */)24(95)100(PciCLS)108(= 0x0C,)124(/* cache line size */)140 L (28)0(ATAvec1=)9(Int0vec+15, /* ATA controller #2 */)24(96)100(PciLTR)108(= 0x0D,)124(/* latency timer */)140 L (29 #endif /* notdef */)0(97)100(PciHDT)108(= 0x0E,)124(/* header type */)140 L (30)0(98)100(PciBST)108(= 0x0F,)124(/* BIST */)140 L (31)0(Syscallvec= 64,)8(99)100 L (32)0(100 PciBAR0)100(= 0x10,)124(/* base address */)140 L (33)0(VectorPIC)8(= 24,)24(/* external [A]PIC interrupts */)40(101 PciBAR1)100(= 0x14,)124 L (34)0(VectorCLOCK = VectorPIC+0,)8(102)100 L (35)0(VectorKBD)8(= VectorPIC+1,)24(103 PciINTL)100(= 0x3C,)124(/* interrupt line */)140 L (36)0(VectorUART1 = VectorPIC+3,)8(104 PciINTP)100(= 0x3D,)124(/* interrupt pin */)140 L (37)0(VectorUART0 = VectorPIC+4,)8(105 };)100 L (38)0(VectorPCMCIA = VectorPIC+5,)8(106)100 L (39)0(VectorFLOPPY = VectorPIC+6,)8(107 enum {)100(/* type 0 pre-defined header */)148 L (40)0(VectorLPT)8(= VectorPIC+7,)24(108 PciBAR2)100(= 0x18,)124 L (41)0(VectorIRQ7)8(= VectorPIC+7,)24(109 PciBAR3)100(= 0x1C,)124 L (42)0(VectorAUX)8(= VectorPIC+12, /* PS/2 port */)24(110 PciBAR4)100(= 0x20,)124 L (43)0(VectorIRQ13 = VectorPIC+13, /* coprocessor on x386 */)8(111 PciBAR5)100(= 0x24,)124 L (44)0(VectorATA0)8(= VectorPIC+14,)24(112 PciCIS)100(= 0x28,)124(/* cardbus CIS pointer */)140 L (45)0(VectorATA1)8(= VectorPIC+15,)24(113 PciSVID)100(= 0x2C,)124(/* subsystem vendor ID */)140 L (46)0(MaxVectorPIC = VectorPIC+15,)8(114 PciSID)100(= 0x2E,)124(/* cardbus CIS pointer */)140 L (47 };)0(115 PciEBAR0)100(= 0x30,)124(/* expansion ROM base address */)140 L (48)0(116 PciMGNT)100(= 0x3E,)124(/* burst period length */)140 L (49 enum {)0(117 PciMLT)100(= 0x3F,)124(/* maximum latency between bursts */)140 L (50)0(BusCBUS)8(= 0,)24(/* Corollary CBUS */)40(118 };)100 L (51)0(BusCBUSII,)8(/* Corollary CBUS II */)40(119)100 L (52)0(BusEISA,)8(/* Extended ISA */)40(120 enum {)100(/* type 1 pre-defined header */)148 L (53)0(BusFUTURE,)8(/* IEEE Futurebus */)40(121 PciPBN)100(= 0x18,)124(/* primary bus number */)140 L (54)0(BusINTERN,)8(/* Internal bus */)40(122 PciSBN)100(= 0x19,)124(/* secondary bus number */)140 L (55)0(BusISA,)8(/* Industry Standard Architecture */)40(123 PciUBN)100(= 0x1A,)124(/* subordinate bus number */)140 L (56)0(BusMBI,)8(/* Multibus I */)40(124 PciSLTR)100(= 0x1B,)124(/* secondary latency timer */)140 L (57)0(BusMBII,)8(/* Multibus II */)40(125 PciIBR)100(= 0x1C,)124(/* I/O base */)140 L (58)0(BusMCA,)8(/* Micro Channel Architecture */)40(126 PciILR)100(= 0x1D,)124(/* I/O limit */)140 L (59)0(BusMPI,)8(/* MPI */)40(127 PciSPSR)100(= 0x1E,)124(/* secondary status */)140 L (60)0(BusMPSA,)8(/* MPSA */)40(128 PciMBR)100(= 0x20,)124(/* memory base */)140 L (61)0(BusNUBUS,)8(/* Apple Macintosh NuBus */)40(129 PciMLR)100(= 0x22,)124(/* memory limit */)140 L (62)0(BusPCI,)8(/* Peripheral Component Interconnect */)40(130 PciPMBR)100(= 0x24,)124(/* prefetchable memory base */)140 L (63)0(BusPCMCIA,)8(/* PC Memory Card International Association */)40(131 PciPMLR)100(= 0x26,)124(/* prefetchable memory limit */)140 L (64)0(BusTC,)8(/* DEC TurboChannel */)40(132 PciPUBR)100(= 0x28,)124(/* prefetchable base upper 32 bits */)140 L (65)0(BusVL,)8(/* VESA Local bus */)40(133 PciPULR)100(= 0x2C,)124(/* prefetchable limit upper 32 bits */)140 L (66)0(BusVME,)8(/* VMEbus */)40(134 PciIUBR)100(= 0x30,)124(/* I/O base upper 16 bits */)140 L (67)0(BusXPRESS,)8(/* Express System Bus */)40(135 PciIULR)100(= 0x32,)124(/* I/O limit upper 16 bits */)140 L (68 };)0(136 PciEBAR1)100(= 0x28,)124(/* expansion ROM base address */)140 L cleartomark showpage saveobj restore %%EndPage: 251 251 %%Page: 252 252 /saveobj save def mark 252 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/io.h Page 2)l ()l ()l (137 PciBCR)0(= 0x3E,)24(/* bridge control register */)40 L (138 };)l (139)l (140 typedef struct Pcidev Pcidev;)l (141 typedef struct Pcidev {)l (142 int tbdf;)0(/* type+bus+device+function */)40 L (143 ushort vid;)0(/* vendor ID */)40 L (144 ushort did;)0(/* device ID */)40 L (145)l (146 struct {)l (147)0(ulong bar;)16(/* base address */)40 L (148)0(int size;)16 L (149 } mem[6];)l (150)l (151 uchar intl;)0(/* interrupt line */)40 L (152 uchar ccrp;)l (153 uchar ccru;)l (154 uchar ccrb;)l (155)l (156 Pcidev* list;)l (157 Pcidev* bridge;)0(/* down a bus */)40 L (158 Pcidev* link;)0(/* next device on this bno */)40 L (159 };)l (160)l (161 /*)l (162 * PCMCIA support code.)l (163 */)l (164 /*)l (165 * Map between ISA memory space and PCMCIA card memory space.)l (166 */)l (167 struct PCMmap {)l (168 ulong ca;)0(/* card address */)40 L (169 ulong cea;)0(/* card end address */)40 L (170 ulong isa;)0(/* ISA address */)40 L (171 int len;)0(/* length of the ISA area */)40 L (172 int attr;)0(/* attribute memory */)40 L (173 int ref;)l (174 };)l cleartomark showpage saveobj restore %%EndPage: 252 252 %%Page: 253 253 /saveobj save def mark 253 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/kbd.c Page 1)l ()l ()l (1 #include "u.h")0(69 [0x10] 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I',)100 L (2 #include "lib.h")0(70 [0x18] 'O', 'P', '{', '}', '\\n', Ctrl, 'A', 'S',)100 L (3 #include "mem.h")0(71 [0x20] 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':',)100 L (4 #include "dat.h")0(72 [0x28] '"', '~', Shift, '|', 'Z', 'X', 'C', 'V',)100 L (5 #include "fns.h")0(73 [0x30] 'B', 'N', 'M', '<', '>', '?', Shift, No,)100 L (6 #include "io.h")0(74 [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,)100 L (7)0(75 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,)100 L (8 enum {)0(76 [0x48] No, No, No, No, No, No, No, No,)100 L (9)0(Data=)8(0x60, /* data port */)24(77 [0x50] No, No, No, No, No, No, No, KF|11,)100 L (10)0(78 [0x58] KF|12, No, No, No, No, No, No, No,)100 L (11)0(Status=)8(0x64, /* status port */)24(79 };)100 L (12)0(Inready=)9(0x01, /* input character ready */)24(80)100 L (13)0(Outbusy=)9(0x02, /* output busy */)24(81 uchar kbtabesc1[] =)100 L (14)0(Sysflag=)9(0x04, /* system flag */)24(82 {)100 L (15)0(Cmddata=)9(0x08, /* cmd==0, data==1 */)24(83 [0x00] No, No, No, No, No, No, No, No,)100 L (16)0(Inhibit=)9(0x10, /* keyboard/mouse inhibited */)24(84 [0x08] No, No, No, No, No, No, No, No,)100 L (17)0(Minready=)9(0x20, /* mouse character ready */)24(85 [0x10] No, No, No, No, No, No, No, No,)100 L (18)0(Rtimeout=)9(0x40, /* general timeout */)24(86 [0x18] No, No, No, No, No, Ctrl, No, No,)100 L (19)0(Parity=)9(0x80,)24(87 [0x20] No, No, No, No, No, No, No, No,)100 L (20)0(88 [0x28] No, No, No, No, No, No, No, No,)100 L (21)0(Cmd=)8(0x64, /* command port \(write only\) */)24(89 [0x30] No, No, No, No, No, No, No, Print,)100 L (22)0(90 [0x38] Latin, No, No, No, No, No, No, No,)100 L (23)0(Spec= 0x80,)8(91 [0x40] No, No, No, No, No, No, Break, Home,)100 L (24)0(92 [0x48] Up, Pgup, No, Down, No, Right, No, End,)100 L (25)0(PF= Spec|0x20,)8(/* num pad function key */)32(93 [0x50] Left, Pgdown, Ins, Del, No, No, No, No,)100 L (26)0(View= Spec|0x00,)8(/* view \(shift window up\) */)32(94 [0x58] No, No, No, No, No, No, No, No,)100 L (27)0(KF= Spec|0x40,)8(/* function key */)32(95 };)100 L (28)0(Shift= Spec|0x60,)8(96)100 L (29)0(Break= Spec|0x61,)8(97 struct latin)100 L (30)0(Ctrl= Spec|0x62,)8(98 {)100 L (31)0(Latin= Spec|0x63,)8(99)100(uchar l;)108 L (32)0(Caps= Spec|0x64,)8(100 char c[2];)100 L (33)0(Num= Spec|0x65,)8(101 }latintab[] = {)100 L (34)0(No= Spec|0x7F,)8(/* no mapping */)32(102 L'\302\241', "!!", /* spanish initial ! */)100 L (35)0(103 L'\302\242', "c|", /* cent */)100 L (36)0(Home= KF|13,)8(104 L'\302\242', "c$", /* cent */)100 L (37)0(Up= KF|14,)8(105 L'\302\243', "l$", /* pound sterling */)100 L (38)0(Pgup= KF|15,)8(106 L'\302\244', "g$", /* general currency */)100 L (39)0(Print= KF|16,)8(107 L'\302\245', "y$", /* yen */)100 L (40)0(Left= View,)8(108 L'\302\245', "j$", /* yen */)100 L (41)0(Right= View,)8(109 L'\302\246', "||", /* broken vertical bar */)100 L (42)0(End= '\\r',)8(110 L'\302\247', "SS", /* section symbol */)100 L (43)0(Down= View,)8(111 L'\302\250', "\\"\\"", /* dieresis */)100 L (44)0(Pgdown= View,)8(112 L'\302\251', "cr", /* copyright */)100 L (45)0(Ins= KF|20,)8(113 L'\302\251', "cO", /* copyright */)100 L (46)0(Del= 0x7F,)8(114 L'\302\252', "sa", /* super a, feminine ordinal */)100 L (47 };)0(115 L'\302\253', "<<", /* left angle quotation */)100 L (48)0(116 L'\302\254', "no", /* not sign, hooked overbar */)100 L (49 uchar kbtab[] =)0(117 L'\302\255', "--", /* soft hyphen */)100 L (50 {)0(118 L'\302\256', "rg", /* registered trademark */)100 L (51 [0x00] No, 0x1b, '1', '2', '3', '4', '5', '6',)0(119 L'\302\257', "__", /* macron */)100 L (52 [0x08] '7', '8', '9', '0', '-', '=', '\\b', '\\t',)0(120 L'\302\260', "s0", /* degree \(sup o\) */)100 L (53 [0x10] 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i',)0(121 L'\302\261', "+-", /* plus-minus */)100 L (54 [0x18] 'o', 'p', '[', ']', '\\n', Ctrl, 'a', 's',)0(122 L'\302\262', "s2", /* sup 2 */)100 L (55 [0x20] 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';',)0(123 L'\302\263', "s3", /* sup 3 */)100 L (56 [0x28] '\\'', '`', Shift, '\\\\', 'z', 'x', 'c', 'v',)0(124 L'\302\264', "''", /* grave accent */)100 L (57 [0x30] 'b', 'n', 'm', ',', '.', '/', Shift, No,)0(125 L'\302\265', "mu", /* mu */)100 L (58 [0x38] Latin, ' ', Caps, KF|1, KF|2, KF|3, KF|4, KF|5,)0(126 L'\302\266', "pg", /* paragraph \(pilcrow\) */)100 L (59 [0x40] KF|6, KF|7, KF|8, KF|9, KF|10, Num, KF|12, Home,)0(127 L'\302\267', "..", /* centered . */)100 L (60 [0x48] No, No, No, No, No, No, No, No,)0(128 L'\302\270', ",,", /* cedilla */)100 L (61 [0x50] No, No, No, No, No, No, No, KF|11,)0(129 L'\302\271', "s1", /* sup 1 */)100 L (62 [0x58] KF|12, No, No, No, No, No, No, No,)0(130 L'\302\272', "so", /* sup o */)100 L (63 };)0(131 L'\302\273', ">>", /* right angle quotation */)100 L (64)0(132 L'\302\274', "14", /* 1/4 */)100 L (65 uchar kbtabshift[] =)0(133 L'\302\275', "12", /* 1/2 */)100 L (66 {)0(134 L'\302\276', "34", /* 3/4 */)100 L (67 [0x00] No, 0x1b, '!', '@', '#', '$', '%', '^',)0(135 L'\302\277', "??", /* spanish initial ? */)100 L (68 [0x08] '&', '*', '\(', '\)', '_', '+', '\\b', '\\t',)0(136 L'\303\200', "A`", /* A grave */)100 L cleartomark showpage saveobj restore %%EndPage: 253 253 %%Page: 254 254 /saveobj save def mark 254 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/kbd.c Page 2)l ()l ()l (137 L'\303\201', "A'", /* A acute */)0(205 L'\303\265', "o~", /* o tilde */)101 L (138 L'\303\202', "A^", /* A circumflex */)0(206 L'\303\266', "o\\"", /* o dieresis */)101 L (139 L'\303\203', "A~", /* A tilde */)0(207 L'\303\266', "o:", /* o dieresis */)101 L (140 L'\303\204', "A\\"", /* A dieresis */)0(208 L'\303\266', "oe", /* o dieresis */)101 L (141 L'\303\204', "A:", /* A dieresis */)0(209 L'\303\267', "-:", /* divide sign */)101 L (142 L'\303\205', "Ao", /* A circle */)0(210 L'\303\270', "o/", /* o slash */)101 L (143 L'\303\205', "AO", /* A circle */)0(211 L'\303\271', "u`", /* u grave */)101 L (144 L'\303\206', "Ae", /* AE ligature */)0(212 L'\303\272', "u'", /* u acute */)101 L (145 L'\303\206', "AE", /* AE ligature */)0(213 L'\303\273', "u^", /* u circumflex */)101 L (146 L'\303\207', "C,", /* C cedilla */)0(214 L'\303\274', "u\\"", /* u dieresis */)101 L (147 L'\303\210', "E`", /* E grave */)0(215 L'\303\274', "u:", /* u dieresis */)101 L (148 L'\303\211', "E'", /* E acute */)0(216 L'\303\274', "ue", /* u dieresis */)101 L (149 L'\303\212', "E^", /* E circumflex */)0(217 L'\303\275', "y'", /* y acute */)101 L (150 L'\303\213', "E\\"", /* E dieresis */)0(218 L'\303\276', "th", /* thorn */)101 L (151 L'\303\213', "E:", /* E dieresis */)0(219 L'\303\276', "p|", /* thorn */)101 L (152 L'\303\214', "I`", /* I grave */)0(220 L'\303\277', "y\\"", /* y dieresis */)101 L (153 L'\303\215', "I'", /* I acute */)0(221 L'\303\277', "y:", /* y dieresis */)101 L (154 L'\303\216', "I^", /* I circumflex */)0(222 0,)101(0,)117 L (155 L'\303\217', "I\\"", /* I dieresis */)0(223 };)101 L (156 L'\303\217', "I:", /* I dieresis */)0(224)101 L (157 L'\303\220', "D-", /* Eth */)0(225 enum)101 L (158 L'\303\221', "N~", /* N tilde */)0(226 {)101 L (159 L'\303\222', "O`", /* O grave */)0(227 /* controller command byte */)101 L (160 L'\303\223', "O'", /* O acute */)0(228 Cscs1=)101(\(1<<6\),)125(/* scan code set 1 */)141 L (161 L'\303\224', "O^", /* O circumflex */)0(229 Cmousedis=)101(\(1<<5\),)125(/* mouse disable */)141 L (162 L'\303\225', "O~", /* O tilde */)0(230 Ckbddis=)101(\(1<<4\),)125(/* kbd disable */)141 L (163 L'\303\226', "O\\"", /* O dieresis */)0(231 Csf=)101(\(1<<2\),)125(/* system flag */)141 L (164 L'\303\226', "O:", /* O dieresis */)0(232 Cmouseint=)101(\(1<<1\),)125(/* mouse interrupt enable */)141 L (165 L'\303\226', "OE", /* O dieresis */)0(233 Ckbdint=)101(\(1<<0\),)125(/* kbd interrupt enable */)141 L (166 L'\303\226', "Oe", /* O dieresis */)0(234 };)101 L (167 L'\303\227', "xx", /* times sign */)0(235)101 L (168 L'\303\230', "O/", /* O slash */)0(236 static uchar ccc;)101 L (169 L'\303\231', "U`", /* U grave */)0(237)101 L (170 L'\303\232', "U'", /* U acute */)0(238 int)101 L (171 L'\303\233', "U^", /* U circumflex */)0(239 latin1\(int k1, int k2\))101 L (172 L'\303\234', "U\\"", /* U dieresis */)0(240 {)101 L (173 L'\303\234', "U:", /* U dieresis */)0(241 struct latin *l;)101 L (174 L'\303\234', "UE", /* U dieresis */)0(242)101 L (175 L'\303\234', "Ue", /* U dieresis */)0(243 for\(l=latintab; l->l; l++\))101 L (176 L'\303\235', "Y'", /* Y acute */)0(244)101(if\(k1==l->c[0] && k2==l->c[1]\))117 L (177 L'\303\236', "P|", /* Thorn */)0(245)101(return l->l;)125 L (178 L'\303\236', "Th", /* Thorn */)0(246 return 0;)101 L (179 L'\303\236', "TH", /* Thorn */)0(247 })101 L (180 L'\303\237', "ss", /* sharp s */)0(248)101 L (181 L'\303\240', "a`", /* a grave */)0(249 /*)101 L (182 L'\303\241', "a'", /* a acute */)0(250 * wait for output no longer busy)101 L (183 L'\303\242', "a^", /* a circumflex */)0(251 */)101 L (184 L'\303\243', "a~", /* a tilde */)0(252 static int)101 L (185 L'\303\244', "a\\"", /* a dieresis */)0(253 outready\(void\))101 L (186 L'\303\244', "a:", /* a dieresis */)0(254 {)101 L (187 L'\303\245', "ao", /* a circle */)0(255 int tries;)101 L (188 L'\303\246', "ae", /* ae ligature */)0(256)101 L (189 L'\303\247', "c,", /* c cedilla */)0(257 for\(tries = 0; \(inb\(Status\) & Outbusy\); tries++\){)101 L (190 L'\303\250', "e`", /* e grave */)0(258)101(if\(tries > 500\))117 L (191 L'\303\251', "e'", /* e acute */)0(259)101(return -1;)125 L (192 L'\303\252', "e^", /* e circumflex */)0(260)101(delay\(2\);)117 L (193 L'\303\253', "e\\"", /* e dieresis */)0(261 })101 L (194 L'\303\253', "e:", /* e dieresis */)0(262 return 0;)101 L (195 L'\303\254', "i`", /* i grave */)0(263 })101 L (196 L'\303\255', "i'", /* i acute */)0(264)101 L (197 L'\303\256', "i^", /* i circumflex */)0(265 /*)101 L (198 L'\303\257', "i\\"", /* i dieresis */)0(266 * wait for input)101 L (199 L'\303\257', "i:", /* i dieresis */)0(267 */)101 L (200 L'\303\260', "d-", /* eth */)0(268 static int)101 L (201 L'\303\261', "n~", /* n tilde */)0(269 inready\(void\))101 L (202 L'\303\262', "o`", /* o grave */)0(270 {)101 L (203 L'\303\263', "o'", /* o acute */)0(271 int tries;)101 L (204 L'\303\264', "o^", /* o circumflex */)0(272)101 L cleartomark showpage saveobj restore %%EndPage: 254 254 %%Page: 255 255 /saveobj save def mark 255 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/kbd.c Page 3)l ()l ()l (273 for\(tries = 0; !\(inb\(Status\) & Inready\); tries++\){)0(341 if\(!\(s&Inready\)\))100 L (274)0(if\(tries > 500\))16(342)100(return;)116 L (275)0(return -1;)24(343)100 L (276)0(delay\(2\);)16(344 /*)100 L (277 })0(345)100(* get the character)109 L (278 return 0;)0(346)100(*/)109 L (279 })0(347 c = inb\(Data\);)100 L (280)0(348)100 L (281 /*)0(349 /*)100 L (282 * ask 8042 to enable the use of address bit 20)0(350)100(* if it's the aux port...)109 L (283 */)0(351)100(*/)109 L (284 void)0(352 if\(s & Minready\))100 L (285 i8042a20\(void\))0(353)100(return;)116 L (286 {)0(354)100 L (287 outready\(\);)0(355 /*)100 L (288 outb\(Cmd, 0xD1\);)0(356)100(* e0's is the first of a 2 character sequence)109 L (289 outready\(\);)0(357)100(*/)109 L (290 outb\(Data, 0xDF\);)0(358 if\(c == 0xe0\){)100 L (291 outready\(\);)0(359)100(esc1 = 1;)116 L (292 })0(360)100(return;)116 L (293)0(361 } else if\(c == 0xe1\){)100 L (294 /*)0(362)100(esc2 = 2;)116 L (295 * ask 8042 to reset the machine)0(363)100(return;)116 L (296 */)0(364 })100 L (297 void)0(365)100 L (298 i8042reset\(void\))0(366 keyup = c&0x80;)100 L (299 {)0(367 c &= 0x7f;)100 L (300 int i, x;)0(368 if\(c > sizeof kbtab\){)100 L (301 #ifdef notdef)0(369)100(c |= keyup;)116 L (302 ushort *s = \(ushort*\)\(KZERO|0x472\);)0(370)100(if\(c != 0xFF\) /* these come fairly often: CAPSLOCK U Y */)116 L (303)0(371)100(print\("unknown key %ux\\n", c\);)124 L (304 *s = 0x1234;)0(/* BIOS warm-boot flag */)32(372)100(return;)116 L (305 #endif /* notdef */)0(373 })100 L (306)0(374)100 L (307 outready\(\);)0(375 if\(esc1\){)100 L (308 outb\(Cmd, 0xFE\);)0(/* pulse reset line \(means resend on AT&T machines\) */)32(376)100(c = kbtabesc1[c];)116 L (309 outready\(\);)0(377)100(esc1 = 0;)116 L (310)0(378 } else if\(esc2\){)100 L (311 /*)0(379)100(esc2--;)116 L (312)0(* Pulse it by hand \(old somewhat reliable\))9(380)100(return;)116 L (313)0(*/)9(381 } else if\(shift\))100 L (314 x = 0xDF;)0(382)100(c = kbtabshift[c];)116 L (315 for\(i = 0; i < 5; i++\){)0(383 else)100 L (316)0(x ^= 1;)16(384)100(c = kbtab[c];)116 L (317)0(outready\(\);)16(385)100 L (318)0(outb\(Cmd, 0xD1\);)16(386 if\(caps && c<='z' && c>='a'\))100 L (319)0(outready\(\);)16(387)100(c += 'A' - 'a';)116 L (320)0(outb\(Data, x\); /* toggle reset */)16(388)100 L (321)0(delay\(100\);)16(389 /*)100 L (322 })0(390)100(* keyup only important for shifts)109 L (323 })0(391)100(*/)109 L (324)0(392 if\(keyup\){)100 L (325 /*)0(393)100(switch\(c\){)116 L (326 * keyboard interrupt)0(394)100(case Latin:)116 L (327 */)0(395)100(alt = 0;)124 L (328 static void)0(396)100(break;)124 L (329 kbdintr\(Ureg*, void*\))0(397)100(case Shift:)116 L (330 {)0(398)100(shift = 0;)124 L (331 int s, c;)0(399)100(break;)124 L (332 static int esc1, esc2;)0(400)100(case Ctrl:)116 L (333 static int alt, caps, ctl, num, shift;)0(401)100(ctl = 0;)124 L (334 static int lstate, k1, k2;)0(402)100(break;)124 L (335 int keyup;)0(403)100(})116 L (336)0(404)100(return;)116 L (337 /*)0(405 })100 L (338)0(* get status)9(406)100 L (339)0(*/)9(407 /*)100 L (340 s = inb\(Status\);)0(408)100(* normal character)109 L cleartomark showpage saveobj restore %%EndPage: 255 255 %%Page: 256 256 /saveobj save def mark 256 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/kbd.c Page 4)l ()l ()l (409)0(*/)9(477 ccc &= ~Ckbddis;)100 L (410 if\(!\(c & Spec\)\){)0(478 ccc |= Csf | Ckbdint | Cscs1;)100 L (411)0(if\(ctl\){)16(479 if\(outready\(\) < 0\))100 L (412)0(if\(alt && c == Del\))24(480)100(print\(initfailed\);)116 L (413)0(panic\("Ctrl-Alt-Del"\);)32(481 outb\(Cmd, 0x60\);)100 L (414)0(c &= 0x1f;)24(482 if\(outready\(\) < 0\))100 L (415)0(})16(483)100(print\(initfailed\);)116 L (416)0(switch\(lstate\){)16(484 outb\(Data, ccc\);)100 L (417)0(case 1:)16(485 if\(outready\(\) < 0\))100 L (418)0(k1 = c;)24(486)100(print\(initfailed\);)116 L (419)0(lstate = 2;)24(487)100 L (420)0(return;)24(488 setvec\(VectorKBD, kbdintr, 0\);)100 L (421)0(case 2:)16(489 })100 L (422)0(k2 = c;)24 L (423)0(lstate = 0;)24 L (424)0(c = latin1\(k1, k2\);)24 L (425)0(if\(c == 0\){)24 L (426)0(kbdchar\(k1\);)32 L (427)0(c = k2;)32 L (428)0(})24 L (429)0(/* fall through */)24 L (430)0(default:)16 L (431)0(break;)24 L (432)0(})16 L (433 } else {)l (434)0(switch\(c\){)16 L (435)0(case Caps:)16 L (436)0(caps ^= 1;)24 L (437)0(return;)24 L (438)0(case Num:)16 L (439)0(num ^= 1;)24 L (440)0(return;)24 L (441)0(case Shift:)16 L (442)0(shift = 1;)24 L (443)0(return;)24 L (444)0(case Latin:)16 L (445)0(alt = 1;)24 L (446)0(lstate = 1;)24 L (447)0(return;)24 L (448)0(case Ctrl:)16 L (449)0(ctl = 1;)24 L (450)0(return;)24 L (451)0(})16 L (452 })l (453 kbdchar\(c\);)l (454 })l (455)l (456 static char *initfailed = "kbd init failed\\n";)l (457)l (458 void)l (459 kbdinit\(void\))l (460 {)l (461 int c;)l (462)l (463 /* wait for a quiescent controller */)l (464 while\(\(c = inb\(Status\)\) & \(Outbusy | Inready\)\))l (465)0(if\(c & Inready\))16 L (466)0(inb\(Data\);)24 L (467)l (468 /* get current controller command byte */)l (469 outb\(Cmd, 0x20\);)l (470 if\(inready\(\) < 0\){)l (471)0(print\("kbdinit: can't read ccc\\n"\);)16 L (472)0(ccc = 0;)16 L (473 } else)l (474)0(ccc = inb\(Data\);)16 L (475)l (476 /* enable kbd xfers and interrupts */)l cleartomark showpage saveobj restore %%EndPage: 256 256 %%Page: 257 257 /saveobj save def mark 257 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/lib.h Page 1)l ()l ()l (1 /*)0(69)100 L (2)0(* functions \(possibly\) linked in, complete, from libc.)7(70 #define NCONT 0)100(/* continue after note */)132 L (3)0(*/)7(71 #define NDFLT 1)100(/* terminate after note */)132 L (4)0(72)100 L (5 /*)0(73 typedef struct Qid)100(Qid;)132 L (6)0(* mem routines)7(74 typedef struct Dir)100(Dir;)132 L (7)0(*/)7(75 typedef struct Waitmsg Waitmsg;)100 L (8 extern void* memccpy\(void*, void*, int, long\);)0(76)100 L (9 extern void* memset\(void*, int, long\);)0(77 #define ERRLEN 64)100 L (10 extern int memcmp\(void*, void*, long\);)0(78 #define DIRLEN 116)100 L (11 extern void* memmove\(void*, void*, long\);)0(79 #define NAMELEN 28)100 L (12 extern void* memchr\(void*, int, long\);)0(80)100 L (13)0(81 struct Qid)100 L (14 /*)0(82 {)100 L (15 * string routines)0(83)100(ulong path;)108 L (16 */)0(84)100(ulong vers;)108 L (17 extern char* strcat\(char*, char*\);)0(85 };)100 L (18 extern char* strchr\(char*, char\);)0(86)100 L (19 extern int strcmp\(char*, char*\);)0(87 struct Dir)100 L (20 extern char* strcpy\(char*, char*\);)0(88 {)100 L (21 extern char* strncat\(char*, char*, long\);)0(89)100(char name[NAMELEN];)108 L (22 extern char* strncpy\(char*, char*, long\);)0(90)100(char uid[NAMELEN];)108 L (23 extern int strncmp\(char*, char*, long\);)0(91)100(char gid[NAMELEN];)108 L (24 extern long strlen\(char*\);)0(92)100(Qid qid;)108 L (25 extern char* strrchr\(char*, char\);)0(93)100(ulong mode;)108 L (26)0(94)100(long atime;)108 L (27 /*)0(95)100(long mtime;)108 L (28 * print routines)0(96)100(Length;)108 L (29 *)0(Fconv isn't used but is defined to satisfy prototypes in libg.h)16(97)100(short type;)108 L (30 *)0(that are never called.)16(98)100(short dev;)108 L (31 */)0(99 };)100 L (32 typedef struct Fconv Fconv;)0(100)100 L (33)0(101 struct Waitmsg)100 L (34 extern char* donprint\(char*, char*, char*, void*\);)0(102 {)100 L (35 extern int sprint\(char*, char*, ...\);)0(103 int pid;)100(/* of loved one */)132 L (36 extern int snprint\(char*, int, char*, ...\);)0(104 int status;)100(/* unused; a placeholder */)132 L (37 extern int print\(char*, ...\);)0(105 ulong time[3];)100(/* of loved one */)132 L (38)0(106 char msg[ERRLEN];)100 L (39 #define PRINTSIZE)0(256)32(107 };)100 L (40)l (41 /*)l (42 * one-of-a-kind)l (43 */)l (44 extern int atoi\(char*\);)l (45 extern void longjmp\(jmp_buf, int\);)l (46 extern int setjmp\(jmp_buf\);)l (47 extern long strtol\(char*, char**, int\);)l (48 extern ulong strtoul\(char*, char**, int\);)l (49 extern long end;)l (50)l (51 /*)l (52 * Syscall data structures)l (53 */)l (54)l (55 #define MORDER 0x0003 /* mask for bits defining order of mounting */)l (56 #define MREPL 0x0000 /* mount replaces object */)l (57 #define MBEFORE 0x0001 /* mount goes before others in union directory */)l (58 #define MAFTER 0x0002 /* mount goes after others in union directory */)l (59 #define MCREATE 0x0004 /* permit creation in mounted directory */)l (60 #define MMASK 0x0007 /* all bits on */)l (61)l (62 #define OREAD 0)0(/* open for read */)32 L (63 #define OWRITE 1)0(/* write */)32 L (64 #define ORDWR 2)0(/* read and write */)32 L (65 #define OEXEC 3)0(/* execute, == read but check execute permission */)32 L (66 #define OTRUNC 16)0(/* or'ed in \(except for exec\), truncate file first */)32 L (67 #define OCEXEC 32)0(/* or'ed in, close on exec */)32 L (68 #define ORCLOSE 64)0(/* or'ed in, remove on close */)32 L cleartomark showpage saveobj restore %%EndPage: 257 257 %%Page: 258 258 /saveobj save def mark 258 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/load.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(Nini)108(= 10,)124 L (2 #include "lib.h")0(70 };)100 L (3 #include "mem.h")0(71)100 L (4 #include "dat.h")0(72 enum {)100(/* mode */)148 L (5 #include "fns.h")0(73)100(Mauto)108(= 0x00,)124 L (6 #include "io.h")0(74)100(Mlocal)108(= 0x01,)124 L (7)0(75)100(Manual)108(= 0x02,)124 L (8 #include "dosfs.h")0(76)100(NMode)108(= 0x03,)124 L (9)0(77 };)100 L (10 Type types[] = {)0(78)100 L (11)0({)8(Tfloppy,)16(79 typedef struct Medium Medium;)100 L (12)0(Fini|Fdos,)16(80 struct Medium {)100 L (13)0(floppyinit, floppyinitdev,)16(81)100(Type* type;)108 L (14)0(floppygetdospart, 0, floppyboot,)16(82)100(int flag;)108 L (15)0(},)8(83)100(int dev;)108 L (16)0({)8(Tether,)16(84)100(char name[NAMELEN];)108 L (17)0(Fbootp,)16(85)100 L (18)0(etherinit, etherinitdev,)16(86)100(Dos *inidos;)108 L (19)0(0, 0, bootp,)16(87)100(char *part;)108 L (20)0(},)8(88)100(char *ini;)108 L (21)0({)8(Tsd,)16(89)100 L (22)0(Fini|Fdos,)16(90)100(Medium* next;)108 L (23)0(sdinit, sdinitdev,)16(91 };)100 L (24)0(sdgetdospart, sdaddconf, sdboot,)16(92)100 L (25)0(},)8(93 typedef struct Mode {)100 L (26)0({)8(Tnil,)16(94)100(char* name;)108 L (27)0(0,)16(95)100(int mode;)108 L (28)0(0, 0, 0, 0,)16(96 } Mode;)100 L (29)0({ 0, },)16(97)100 L (30)0(},)8(98 static Medium media[Nmedia];)100 L (31 };)0(99 static Medium *curmedium = media;)100 L (32)0(100)100 L (33 #include "etherif.h")0(101 static Mode modes[NMode+1] = {)100 L (34)0(102 [Mauto])100({ "auto", Mauto, },)124 L (35 extern int ether2114xreset\(Ether*\);)0(103 [Mlocal])100({ "local", Mlocal, },)124 L (36 extern int elnk3reset\(Ether*\);)0(104 [Manual])100({ "manual", Manual, },)124 L (37 extern int i82557reset\(Ether*\);)0(105 };)100 L (38 extern int elnk3reset\(Ether*\);)0(106)100 L (39 extern int ether589reset\(Ether*\);)0(107 static char *inis[] = {)100 L (40 extern int ne2000reset\(Ether*\);)0(108 "plan9/plan9.ini",)100 L (41 extern int wd8003reset\(Ether*\);)0(109 "plan9.ini",)100 L (42 extern int ec2treset\(Ether*\);)0(110 0)100 L (43)0(111 };)100 L (44 struct {)0(112)100 L (45)0(char *type;)8(113 char **ini;)100 L (46)0(int \(*reset\)\(Ether*\);)8(114)100 L (47 } ethercards[] = {)0(115 int scsi0port;)100 L (48)0({ "21140", ether2114xreset, },)8(116)100 L (49)0({ "2114x", ether2114xreset, },)8(117 static Medium*)100 L (50)0({ "i82557", i82557reset, },)8(118 parse\(char *line, char **file\))100 L (51)0({ "elnk3", elnk3reset, },)8(119 {)100 L (52)0({ "3C509", elnk3reset, },)8(120 char *p;)100 L (53)0({ "3C589", ether589reset, },)8(121 Type *tp;)100 L (54)0({ "3C562", ether589reset, },)8(122 Medium *mp;)100 L (55)0({ "589E", ether589reset, },)8(123)100 L (56)0({ "NE2000", ne2000reset, },)8(124 if\(p = strchr\(line, '!'\)\) {)100 L (57)0({ "WD8003", wd8003reset, },)8(125)100(*p++ = 0;)116 L (58)0({ "EC2T", ec2treset, },)8(126)100(*file = p;)116 L (59)0(127 } else)100 L (60)0({ 0, })8(128)100(*file = "";)116 L (61 };)0(129)100 L (62)0(130 for\(tp = types; tp->type != Tnil; tp++\))100 L (63 typedef struct Mode Mode;)0(131)100(for\(mp = tp->media; mp; mp = mp->next\))116 L (64)0(132)100(if\(strcmp\(mp->name, line\) == 0\))124 L (65 enum {)0(133)100(return mp;)132 L (66)0(Maxdev)8(= 7,)24(134 if\(p\))100 L (67)0(Dany)8(= -1,)24(135)100(*--p = '!';)116 L (68)0(Nmedia)8(= 16,)24(136 return nil;)100 L cleartomark showpage saveobj restore %%EndPage: 258 258 %%Page: 259 259 /saveobj save def mark 259 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/load.c Page 2)l ()l ()l (137 })0(205)100(if\(\(tp->mask & \(1<mask &= ~\(1<dev = i;)124 L (145 Boot b;)0(213)100(mp->flag = tp->flag;)124 L (146)0(214)100(mp->type = tp;)124 L (147 memset\(&b, 0, sizeof b\);)0(215)100(\(*tp->initdev\)\(i, mp->name\);)124 L (148 b.state = INITKERNEL;)0(216)100 L (149)0(217)100(if\(mp->flag & Fini\){)124 L (150 if\(didaddconf == 0\) {)0(218)100(mp->flag &= ~Fini;)132 L (151)0(didaddconf = 1;)16(219)100(for\(partp = parts; *partp; partp++\){)132 L (152)0(for\(tp = types; tp->type != Tnil; tp++\))16(220)100(if\(\(dos = \(*tp->getdospart\)\(i, *partp\)\) == nil\))140 L (153)0(if\(tp->addconf\))24(221)100(continue;)148 L (154)0(for\(xmp = tp->media; xmp; xmp = xmp->next\))32(222)100 L (155)0(\(*tp->addconf\)\(xmp->dev\);)40(223)100(for\(ini = inis; *ini; ini++\){)140 L (156 })0(224)100(if\(dosstat\(dos, *ini, &df\) > 0\){)148 L (157)0(225)100(mp->inidos = dos;)156 L (158 sprint\(BOOTLINE, "%s!%s", mp->name, file\);)0(226)100(mp->part = *partp;)156 L (159 return \(*mp->type->boot\)\(mp->dev, file, &b\);)0(227)100(mp->ini = *ini;)156 L (160 })0(228)100(mp->flag |= Fini;)156 L (161)0(229)100(goto Break2;)156 L (162 static Medium*)0(230)100(})148 L (163 allocm\(Type *tp\))0(231)100(})140 L (164 {)0(232)100(})132 L (165 Medium **l;)0(233)100(})124 L (166)0(234)100(Break2:)116 L (167 if\(curmedium >= &media[Nmedia]\))0(235)100(if\(\(flag & mp->flag\) && \(dev == Dany || dev == i\)\))124 L (168)0(return 0;)16(236)100(return mp;)132 L (169)0(237)100(})116 L (170 for\(l = &tp->media; *l; l = &\(*l\)->next\))0(238 })100 L (171)0(;)16(239)100 L (172 *l = curmedium++;)0(240 return 0;)100 L (173 return *l;)0(241 })100 L (174 })0(242)100 L (175)0(243 void)100 L (176 char *parts[] = { "dos", "9fat", 0 };)0(244 main\(void\))100 L (177)0(245 {)100 L (178 Medium*)0(246 Medium *mp;)100 L (179 probe\(int type, int flag, int dev\))0(247 int flag, i, mode, tried;)100 L (180 {)0(248 char def[2*NAMELEN], line[80], *p, *file;)100 L (181 Type *tp;)0(249 Type *tp;)100 L (182 int i;)0(250)100 L (183 Medium *mp;)0(251 i8042a20\(\);)100 L (184 Dosfile df;)0(252 memset\(m, 0, sizeof\(Mach\)\);)100 L (185 Dos *dos;)0(253 trapinit\(\);)100 L (186 char **partp;)0(254 clockinit\(\);)100 L (187)0(255 alarminit\(\);)100 L (188 for\(tp = types; tp->type != Tnil; tp++\){)0(256 spllo\(\);)100 L (189)0(if\(type != Tany && type != tp->type\))16(257)100 L (190)0(continue;)24(258 if\(\(ulong\)&end > \(KZERO|\(640*1024\)\)\))100 L (191)0(259)100(panic\("i'm too big\\n"\);)116 L (192)0(if\(flag != Fnone\){)16(260)100 L (193)0(for\(mp = tp->media; mp; mp = mp->next\){)24(261 for\(tp = types; tp->type != Tnil; tp++\){)100 L (194)0(if\(\(flag & mp->flag\) && \(dev == Dany || dev == mp->dev\)\))32(262)100(if\(tp->type == Tether\))116 L (195)0(return mp;)40(263)100(continue;)124 L (196)0(})24(264)100(if\(\(mp = probe\(tp->type, Fini, Dany\)\) && \(mp->flag & Fini\)\){)116 L (197)0(})16(265 print\("using %s!%s!%s\\n", mp->name, mp->part, mp->ini\);)100 L (198)0(266)100(dotini\(mp->inidos\);)124 L (199)0(if\(\(tp->flag & Fprobe\) == 0\){)16(267)100(break;)124 L (200)0(tp->flag |= Fprobe;)24(268)100(})116 L (201)0(tp->mask = \(*tp->init\)\(\);)24(269 })100 L (202)0(})16(270)100 L (203)0(271 consinit\(\);)100 L (204)0(for\(i = 0; tp->mask; i++\){)16(272)100 L cleartomark showpage saveobj restore %%EndPage: 259 259 %%Page: 260 260 /saveobj save def mark 260 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/load.c Page 3)l ()l ()l (273 /*)0(341)100(*lp++ = 0;)124 L (274)0(* Even after we find the ini file, we keep probing disks,)9(342)100(if\(*lp == 0\))116 L (275)0(* because we have to collect the partition tables and)9(343)100(break;)124 L (276)0(* have boot devices for parse.)9(344)100(fields[i] = lp;)116 L (277)0(*/)9(345)100(while\(*lp && *lp != sep\){)116 L (278 probe\(Tany, Fnone, Dany\);)0(346)100(if\(*lp == '\\\\' && *\(lp+1\) == '\\n'\))124 L (279)0(347)100(*lp++ = ' ';)132 L (280 tried = 0;)0(348)100(lp++;)124 L (281 mode = Mauto;)0(349)100(})116 L (282)0(350 })100 L (283 p = getconf\("bootfile"\);)0(351 return i;)100 L (284)0(352 })100 L (285 if\(p != 0\) {)0(353)100 L (286)0(mode = Manual;)16(354 int)100 L (287)0(for\(i = 0; i < NMode; i++\){)16(355 cistrcmp\(char *a, char *b\))100 L (288)0(if\(strcmp\(p, modes[i].name\) == 0\){)24(356 {)100 L (289)0(mode = modes[i].mode;)32(357 int ac, bc;)100 L (290)0(goto done;)32(358)100 L (291)0(})24(359 for\(;;\){)100 L (292)0(})16(360)100(ac = *a++;)116 L (293)0(if\(\(mp = parse\(p, &file\)\) == nil\) {)16(361)100(bc = *b++;)116 L (294)0(print\("Bad bootfile syntax: %s\\n", p\);)24(362)100 L (295)0(goto done;)24(363)100(if\(ac >= 'A' && ac <= 'Z'\))116 L (296)0(})16(364)100(ac = 'a' + \(ac - 'A'\);)124 L (297)0(tried = boot\(mp, file\);)16(365)100(if\(bc >= 'A' && bc <= 'Z'\))116 L (298 })0(366)100(bc = 'a' + \(bc - 'A'\);)124 L (299 done:)0(367)100(ac -= bc;)116 L (300 if\(tried == 0 && mode != Manual\){)0(368)100(if\(ac\))116 L (301)0(flag = Fany;)16(369)100(return ac;)124 L (302)0(if\(mode == Mlocal\))16(370)100(if\(bc == 0\))116 L (303)0(flag &= ~Fbootp;)24(371)100(break;)124 L (304)0(if\(\(mp = probe\(Tany, flag, Dany\)\) && mp->type->type != Tfloppy\))16(372 })100 L (305)0(boot\(mp, 0\);)24(373 return 0;)100 L (306 })0(374 })100 L (307)0(375)100 L (308 def[0] = 0;)0(376 int)100 L (309 probe\(Tany, Fnone, Dany\);)0(377 cistrncmp\(char *a, char *b, int n\))100 L (310 if\(p = getconf\("bootdef"\)\))0(378 {)100 L (311)0(strcpy\(def, p\);)16(379 unsigned ac, bc;)100 L (312)0(380)100 L (313 flag = 0;)0(381 while\(n > 0\){)100 L (314 for\(tp = types; tp->type != Tnil; tp++\){)0(382)100(ac = *a++;)116 L (315)0(for\(mp = tp->media; mp; mp = mp->next\){)16(383)100(bc = *b++;)116 L (316)0(if\(flag == 0\){)24(384)100(n--;)116 L (317)0(flag = 1;)32(385)100 L (318)0(print\("Boot devices:"\);)32(386)100(if\(ac >= 'A' && ac <= 'Z'\))116 L (319)0(})24(387)100(ac = 'a' + \(ac - 'A'\);)124 L (320)0(print\(" %s", mp->name\);)24(388)100(if\(bc >= 'A' && bc <= 'Z'\))116 L (321)0(})16(389)100(bc = 'a' + \(bc - 'A'\);)124 L (322 })0(390)100 L (323 if\(flag\))0(391)100(ac -= bc;)116 L (324)0(print\("\\n"\);)16(392)100(if\(ac\))116 L (325)0(393)100(return ac;)124 L (326 for\(;;\){)0(394)100(if\(bc == 0\))116 L (327)0(if\(getstr\("boot from", line, sizeof\(line\), def, mode != Manual\) >= 0\))16(395)100(break;)124 L (328)0(if\(mp = parse\(line, &file\)\))24(396 })100 L (329)0(boot\(mp, file\);)32(397)100 L (330)0(def[0] = 0;)16(398 return 0;)100 L (331 })0(399 })100 L (332 })0(400)100 L (333)0(401 void*)100 L (334 int)0(402 ialloc\(ulong n, int align\))100 L (335 getfields\(char *lp, char **fields, int n, char sep\))0(403 {)100 L (336 {)0(404)100 L (337 int i;)0(405 static ulong palloc;)100 L (338)0(406 ulong p;)100 L (339 for\(i = 0; lp && *lp && i < n; i++\){)0(407 int a;)100 L (340)0(while\(*lp == sep\))16(408)100 L cleartomark showpage saveobj restore %%EndPage: 260 260 %%Page: 261 261 /saveobj save def mark 261 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/load.c Page 4)l ()l ()l (409 if\(palloc == 0\))0(477 outb\(Paddr, offset\);)100 L (410)0(palloc = 3*1024*1024;)16(478 return inb\(Pdata\);)100 L (411)0(479 })100 L (412 p = palloc;)0(480)100 L (413 if\(align <= 0\))0(481 void \(*etherdetach\)\(void\);)100 L (414)0(align = 4;)16(482)100 L (415 if\(a = n % align\))0(483 void)100 L (416)0(n += align - a;)16(484 warp9\(ulong entry\))100 L (417 if\(a = p % align\))0(485 {)100 L (418)0(p += align - a;)16(486 if\(etherdetach\))100 L (419)0(487)100(etherdetach\(\);)116 L (420 palloc = p+n;)0(488 consdrain\(\);)100 L (421)0(489 \(*\(void\(*\)\(void\)\)\(PADDR\(entry\)\)\)\(\);)100 L (422 return memset\(\(void*\)\(p|KZERO\), 0, n\);)0(490 })100 L (423 })l (424)l (425 static Block *allocbp;)l (426)l (427 Block*)l (428 allocb\(int size\))l (429 {)l (430 Block *bp, **lbp;)l (431 ulong addr;)l (432)l (433 lbp = &allocbp;)l (434 for\(bp = *lbp; bp; bp = bp->next\){)l (435)0(if\(\(bp->lim - bp->base\) >= size\){)16 L (436)0(*lbp = bp->next;)24 L (437)0(break;)24 L (438)0(})16 L (439)0(lbp = &bp->next;)16 L (440 })l (441 if\(bp == 0\){)l (442)0(bp = ialloc\(sizeof\(Block\)+size+64, 0\);)16 L (443)0(addr = \(ulong\)bp;)16 L (444)0(addr = ROUNDUP\(addr + sizeof\(Block\), 8\);)16 L (445)0(bp->base = \(uchar*\)addr;)16 L (446)0(bp->lim = \(\(uchar*\)bp\) + sizeof\(Block\)+size+64;)16 L (447 })l (448)l (449 if\(bp->flag\))l (450)0(panic\("allocb reuse\\n"\);)16 L (451)l (452 bp->rp = bp->base;)l (453 bp->wp = bp->rp;)l (454 bp->next = 0;)l (455 bp->flag = 1;)l (456)l (457 return bp;)l (458 })l (459)l (460 void)l (461 freeb\(Block* bp\))l (462 {)l (463 bp->next = allocbp;)l (464 allocbp = bp;)l (465)l (466 bp->flag = 0;)l (467 })l (468)l (469 enum {)l (470 Paddr=)0(0x70, /* address port */)24 L (471 Pdata=)0(0x71, /* data port */)24 L (472 };)l (473)l (474 uchar)l (475 nvramread\(int offset\))l (476 {)l cleartomark showpage saveobj restore %%EndPage: 261 261 %%Page: 262 262 /saveobj save def mark 262 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/trap.c Page 1)l ()l ()l (1 #include "u.h")0(69)100(ilt[v].d0 = \(\(ulong\)r\)&0xFFFF|\(KESEL<<16\);)108 L (2 #include "lib.h")0(70)100(ilt[v].d1 = \(\(ulong\)r\)&0xFFFF0000|SEGP|SEGPL\(pri\)|type;)108 L (3 #include "mem.h")0(71 })100 L (4 #include "dat.h")0(72)100 L (5 #include "fns.h")0(73 void)100 L (6 #include "io.h")0(74 setvec\(int v, void \(*r\)\(Ureg*, void*\), void *arg\))100 L (7 #include "ureg.h")0(75 {)100 L (8)0(76)100(Handler *h;)108 L (9 void)0(intr0\(void\), intr1\(void\), intr2\(void\), intr3\(void\);)16(77)100 L (10 void)0(intr4\(void\), intr5\(void\), intr6\(void\), intr7\(void\);)16(78)100(if\(halloc.nextfree >= Maxhandler\))108 L (11 void)0(intr8\(void\), intr9\(void\), intr10\(void\), intr11\(void\);)16(79)100(panic\("out of interrupt handlers"\);)116 L (12 void)0(intr12\(void\), intr13\(void\), intr14\(void\), intr15\(void\);)16(80)100(h = &halloc.h[halloc.nextfree++];)108 L (13 void)0(intr16\(void\);)16(81)100(h->next = halloc.ivec[v];)108 L (14 void)0(intr24\(void\), intr25\(void\), intr26\(void\), intr27\(void\);)16(82)100(h->r = r;)108 L (15 void)0(intr28\(void\), intr29\(void\), intr30\(void\), intr31\(void\);)16(83)100(h->arg = arg;)108 L (16 void)0(intr32\(void\), intr33\(void\), intr34\(void\), intr35\(void\);)16(84)100(halloc.ivec[v] = h;)108 L (17 void)0(intr36\(void\), intr37\(void\), intr38\(void\), intr39\(void\);)16(85)100 L (18 void)0(intr64\(void\);)16(86)100(/*)108 L (19 void)0(intrbad\(void\);)16(87)100(* enable corresponding interrupt in 8259)109 L (20)0(88)100(*/)109 L (21 /*)0(89)100(if\(\(v&~0x7\) == VectorPIC\){)108 L (22 * 8259 interrupt controllers)0(90)100(int0mask &= ~\(1<<\(v&7\)\);)116 L (23 */)0(91)100(outb\(Int0aux, int0mask\);)116 L (24 enum)0(92)100(} else if\(\(v&~0x7\) == VectorPIC+8\){)108 L (25 {)0(93)100(int1mask &= ~\(1<<\(v&7\)\);)116 L (26)0(Int0ctl=)8(0x20,)24(/* control port \(ICW1, OCW2, OCW3\) */)40(94)100(outb\(Int1aux, int1mask\);)116 L (27)0(Int0aux=)8(0x21,)24(/* everything else \(ICW2, ICW3, ICW4, OCW1\) */)40(95)100(})108 L (28)0(Int1ctl=)8(0xA0,)24(/* control port */)40(96 })100 L (29)0(Int1aux=)8(0xA1,)24(/* everything else \(ICW2, ICW3, ICW4, OCW1\) */)40(97)100 L (30)0(98 /*)100 L (31)0(Icw1=)8(0x10,)24(/* select bit in ctl register */)40(99 * set up the interrupt/trap gates)100 L (32)0(Ocw2=)8(0x00,)24(100 */)100 L (33)0(Ocw3=)8(0x08,)24(101 void)100 L (34)0(102 trapinit\(void\))100 L (35)0(EOI=)8(0x20,)24(/* non-specific end of interrupt */)40(103 {)100 L (36 };)0(104 int i;)100 L (37)0(105)100 L (38 int)0(int0mask = 0xff;)16(/* interrupts enabled for first 8259 */)40(106 /*)100 L (39 int)0(int1mask = 0xff;)16(/* interrupts enabled for second 8259 */)40(107)100(* set all interrupts to panics)109 L (40)0(108)100(*/)109 L (41 /*)0(109 for\(i = 0; i < 256; i++\))100 L (42 * trap/interrupt gates)0(110)100(sethvec\(i, intrbad, SEGTG, 0\);)116 L (43 */)0(111)100 L (44 Segdesc ilt[256];)0(112 /*)100 L (45)0(113)100(* 80386 processor \(and coprocessor\) traps)109 L (46 enum)0(114)100(*/)109 L (47 {)0(115 sethvec\(0, intr0, SEGTG, 0\);)100 L (48)0(Maxhandler= 32,)8(/* max number of interrupt handlers */)40(116 sethvec\(1, intr1, SEGTG, 0\);)100 L (49 };)0(117 sethvec\(2, intr2, SEGTG, 0\);)100 L (50)0(118 sethvec\(3, intr3, SEGTG, 0\);)100 L (51 typedef struct Handler Handler;)0(119 sethvec\(4, intr4, SEGTG, 0\);)100 L (52 struct Handler)0(120 sethvec\(5, intr5, SEGTG, 0\);)100 L (53 {)0(121 sethvec\(6, intr6, SEGTG, 0\);)100 L (54)0(void \(*r\)\(Ureg*, void*\);)8(122 sethvec\(7, intr7, SEGTG, 0\);)100 L (55)0(void *arg;)8(123 sethvec\(8, intr8, SEGTG, 0\);)100 L (56)0(Handler *next;)8(124 sethvec\(9, intr9, SEGTG, 0\);)100 L (57 };)0(125 sethvec\(10, intr10, SEGTG, 0\);)100 L (58)0(126 sethvec\(11, intr11, SEGTG, 0\);)100 L (59 struct)0(127 sethvec\(12, intr12, SEGTG, 0\);)100 L (60 {)0(128 sethvec\(13, intr13, SEGTG, 0\);)100 L (61)0(Handler *ivec[256];)8(129 sethvec\(14, intr14, SEGTG, 0\);)100 L (62)0(Handler h[Maxhandler];)8(130 sethvec\(15, intr15, SEGTG, 0\);)100 L (63)0(int nextfree;)8(131 sethvec\(16, intr16, SEGTG, 0\);)100 L (64 } halloc;)0(132)100 L (65)0(133 /*)100 L (66 void)0(134)100(* device interrupts)109 L (67 sethvec\(int v, void \(*r\)\(void\), int type, int pri\))0(135)100(*/)109 L (68 {)0(136 sethvec\(24, intr24, SEGIG, 0\);)100 L cleartomark showpage saveobj restore %%EndPage: 262 262 %%Page: 263 263 /saveobj save def mark 263 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/trap.c Page 2)l ()l ()l (137 sethvec\(25, intr25, SEGIG, 0\);)0(205)100(ur->ax, ur->bx, ur->cx, ur->dx\);)116 L (138 sethvec\(26, intr26, SEGIG, 0\);)0(206 print\(" SI %8.8lux DI %8.8lux BP %8.8lux\\n",)100 L (139 sethvec\(27, intr27, SEGIG, 0\);)0(207)100(ur->si, ur->di, ur->bp\);)116 L (140 sethvec\(28, intr28, SEGIG, 0\);)0(208 print\(" CS %4.4ux DS %4.4ux ES %4.4ux FS %4.4ux GS %4.4ux\\n",)100 L (141 sethvec\(29, intr29, SEGIG, 0\);)0(209)100(ur->cs & 0xFF, ur->ds & 0xFFFF, ur->es & 0xFFFF, ur->fs & 0xFFFF, ur->gs & 0xFFFF\);)116 L (142 sethvec\(30, intr30, SEGIG, 0\);)0(210 print\(" CR0 %8.8lux CR2 %8.8lux CR3 %8.8lux\\n",)100 L (143 sethvec\(31, intr31, SEGIG, 0\);)0(211)100(getcr0\(\), getcr2\(\), getcr3\(\)\);)116 L (144 sethvec\(32, intr32, SEGIG, 0\);)0(212 })100 L (145 sethvec\(33, intr33, SEGIG, 0\);)0(213)100 L (146 sethvec\(34, intr34, SEGIG, 0\);)0(214 /*)100 L (147 sethvec\(35, intr35, SEGIG, 0\);)0(215 * All traps)100 L (148 sethvec\(36, intr36, SEGIG, 0\);)0(216 */)100 L (149 sethvec\(37, intr37, SEGIG, 0\);)0(217 void)100 L (150 sethvec\(38, intr38, SEGIG, 0\);)0(218 trap\(Ureg *ur\))100 L (151 sethvec\(39, intr39, SEGIG, 0\);)0(219 {)100 L (152)0(220 int v;)100 L (153 /*)0(221 int c;)100 L (154)0(* tell the hardware where the table is \(and how long\))9(222 Handler *h;)100 L (155)0(*/)9(223 ushort isr;)100 L (156 putidt\(ilt, sizeof\(ilt\)\);)0(224)100 L (157)0(225 v = ur->trap;)100 L (158 /*)0(226 /*)100 L (159)0(* Set up the first 8259 interrupt processor.)9(227)100(* tell the 8259 that we're done with the)109 L (160)0(* Make 8259 interrupts start at CPU vector VectorPIC.)9(228)100(* highest level interrupt \(interrupts are still)109 L (161)0(* Set the 8259 as master with edge triggered)9(229)100(* off at this point\))109 L (162)0(* input with fully nested interrupts.)9(230)100(*/)109 L (163)0(*/)9(231 c = v&~0x7;)100 L (164 outb\(Int0ctl, Icw1|0x01\);)0(/* ICW1 - edge triggered, master,)40(232 isr = 0;)100 L (165)0(ICW4 will be sent */)43(233 if\(c==VectorPIC || c==VectorPIC+8\){)100 L (166 outb\(Int0aux, VectorPIC\);)0(/* ICW2 - interrupt vector offset */)48(234)100(isr = inb\(Int0ctl\);)116 L (167 outb\(Int0aux, 0x04\);)0(/* ICW3 - have slave on level 2 */)40(235)100(outb\(Int0ctl, EOI\);)116 L (168 outb\(Int0aux, 0x01\);)0(/* ICW4 - 8086 mode, not buffered */)40(236)100(if\(c == VectorPIC+8\){)116 L (169)0(237)100(isr |= inb\(Int1ctl\)<<8;)124 L (170 /*)0(238)100(outb\(Int1ctl, EOI\);)124 L (171)0(* Set up the second 8259 interrupt processor.)9(239)100(})116 L (172)0(* Make 8259 interrupts start at CPU vector VectorPIC+8.)9(240 })100 L (173)0(* Set the 8259 as master with edge triggered)9(241)100 L (174)0(* input with fully nested interrupts.)9(242 if\(v>=256 || \(h = halloc.ivec[v]\) == 0\){)100 L (175)0(*/)9(243)100(if\(v >= VectorPIC && v < VectorPIC+16\){)116 L (176 outb\(Int1ctl, Icw1|0x01\);)0(/* ICW1 - edge triggered, master,)40(244)100(v -= VectorPIC;)124 L (177)0(ICW4 will be sent */)43(245)100(/*)124 L (178 outb\(Int1aux, VectorPIC+8\);)0(/* ICW2 - interrupt vector offset */)48(246)100(* Check for a default IRQ7. This can happen when)125 L (179 outb\(Int1aux, 0x02\);)0(/* ICW3 - I am a slave on level 2 */)40(247)100(* the IRQ input goes away before the acknowledge.)125 L (180 outb\(Int1aux, 0x01\);)0(/* ICW4 - 8086 mode, not buffered */)40(248)100(* In this case, a 'default IRQ7' is generated, but)125 L (181 outb\(Int1aux, int1mask\);)0(249)100(* the corresponding bit in the ISR isn't set.)125 L (182)0(250)100(* In fact, just ignore all such interrupts.)125 L (183 /*)0(251)100(*/)125 L (184)0(* pass #2 8259 interrupts to #1)9(252)100(if\(isr & \(1<pc\);)132 L (186 int0mask &= ~0x04;)0(254)100(return;)124 L (187 outb\(Int0aux, int0mask\);)0(255)100(})116 L (188)0(256)100 L (189 /*)0(257)100(switch\(v\){)116 L (190)0(* Set Ocw3 to return the ISR when ctl read.)9(258)100 L (191)0(*/)9(259)100(case 0x02:)116(/* NMI */)156 L (192 outb\(Int0ctl, Ocw3|0x03\);)0(260)100(print\("NMI: nmisc=0x%2.2ux, nmiertc=0x%2.2ux, nmiesc=0x%2.2ux\\n",)124 L (193 outb\(Int1ctl, Ocw3|0x03\);)0(261)100(inb\(0x61\), inb\(0x70\), inb\(0x461\)\);)132 L (194 })0(262)100(return;)124 L (195)0(263)100 L (196 /*)0(264)100(default:)116 L (197 * dump registers)0(265)100(print\("exception/interrupt %d\\n", v\);)124 L (198 */)0(266)100(dumpregs\(ur\);)124 L (199 static void)0(267)100(//spllo\(\);)124 L (200 dumpregs\(Ureg *ur\))0(268)100(print\("^P to reset\\n"\);)124 L (201 {)0(269)100(for\(;;\);)124 L (202 print\("FLAGS=%lux TRAP=%lux ECODE=%lux PC=%lux\\n",)0(270)100(})116 L (203)0(ur->flags, ur->trap, ur->ecode, ur->pc\);)16(271 })100 L (204 print\(" AX %8.8lux BX %8.8lux CX %8.8lux DX %8.8lux\\n",)0(272)100 L cleartomark showpage saveobj restore %%EndPage: 263 263 %%Page: 264 264 /saveobj save def mark 264 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/trap.c Page 3)l ()l ()l (273 /*)l (274)0(* call the trap routines)9 L (275)0(*/)9 L (276 do {)l (277)0(\(*h->r\)\(ur, h->arg\);)16 L (278)0(h = h->next;)16 L (279 } while\(h\);)l (280 })l cleartomark showpage saveobj restore %%EndPage: 264 264 %%Page: 265 265 /saveobj save def mark 265 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/boot/pc/ureg.h Page 1)l ()l ()l (1 typedef struct Ureg)0(Ureg;)32 L (2)l (3 struct Ureg)l (4 {)l (5)0(ulong di;)8(/* general registers */)32 L (6)0(ulong si;)8(/* ... */)32 L (7)0(ulong bp;)8(/* ... */)32 L (8)0(ulong nsp;)8 L (9)0(ulong bx;)8(/* ... */)32 L (10)0(ulong dx;)8(/* ... */)32 L (11)0(ulong cx;)8(/* ... */)32 L (12)0(ulong ax;)8(/* ... */)32 L (13)0(ulong gs;)8(/* data segments */)32 L (14)0(ulong fs;)8(/* ... */)32 L (15)0(ulong es;)8(/* ... */)32 L (16)0(ulong ds;)8(/* ... */)32 L (17)0(ulong trap;)8(/* trap type */)32 L (18)0(ulong ecode;)8(/* error code \(or zero\) */)32 L (19)0(ulong pc;)8(/* pc */)32 L (20)0(ulong cs;)8(/* old context */)32 L (21)0(ulong flags;)8(/* old flags */)32 L (22)0(union {)8 L (23)0(ulong usp;)16 L (24)0(ulong sp;)16 L (25)0(};)8 L (26)0(ulong ss;)8(/* old stack segment */)32 L (27 };)l cleartomark showpage saveobj restore %%EndPage: 265 265 %%Page: 266 266 /saveobj save def mark 266 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/cleanname.c Page 1)l ()l ()l (1 #include )l (2 #include )l (3)l (4 /*)l (5)0(* In place, rewrite name to compress multiple /, eliminate ., and process ..)7 L (6)0(*/)7 L (7 #define SEP\(x\) \(\(x\)=='/' || \(x\) == 0\))l (8 char*)l (9 cleanname\(char *name\))l (10 {)l (11)0(char *p, *q, *dotdot;)8 L (12)0(int rooted;)8 L (13)l (14)0(rooted = name[0] == '/';)8 L (15)l (16)0(/*)8 L (17)0(* invariants:)9 L (18)0(*)9(p points at beginning of path element we're considering.)16 L (19)0(*)9(q points just past the last path element we wrote \(no slash\).)16 L (20)0(*)9(dotdot points just past the point where .. cannot backtrack)16 L (21)0(*)9(any further \(no slash\).)24 L (22)0(*/)9 L (23)0(p = q = dotdot = name+rooted;)8 L (24)0(while\(*p\) {)8 L (25)0(if\(p[0] == '/'\) /* null element */)16 L (26)0(p++;)24 L (27)0(else if\(p[0] == '.' && SEP\(p[1]\)\))16 L (28)0(p += 1; /* don't count the separator in case it is nul */)24 L (29)0(else if\(p[0] == '.' && p[1] == '.' && SEP\(p[2]\)\) {)16 L (30)0(p += 2;)24 L (31)0(if\(q > dotdot\) {)24(/* can backtrack */)48 L (32)0(while\(--q > dotdot && *q != '/'\))32 L (33)0(;)40 L (34)0(} else if\(!rooted\) { /* /.. is / but ./../ is .. */)24 L (35)0(if\(q != name\))32 L (36)0(*q++ = '/';)40 L (37)0(*q++ = '.';)32 L (38)0(*q++ = '.';)32 L (39)0(dotdot = q;)32 L (40)0(})24 L (41)0(} else {)16(/* real path element */)32 L (42)0(if\(q != name+rooted\))24 L (43)0(*q++ = '/';)32 L (44)0(while\(\(*q = *p\) != '/' && *q != 0\))24 L (45)0(p++, q++;)32 L (46)0(})16 L (47)0(})8 L (48)0(if\(q == name\) /* empty string is really ``.'' */)8 L (49)0(*q++ = '.';)16 L (50)0(*q = '\\0';)8 L (51)0(return name;)8 L (52 })l cleartomark showpage saveobj restore %%EndPage: 266 266 %%Page: 267 267 /saveobj save def mark 267 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 1)l ()l ()l (1 /*)0(69 struct Btail {)100 L (2)0(* This allocator takes blocks from a coarser allocator \(p->alloc\) and)7(70)100(uchar magic0;)108 L (3)0(* uses them as arenas.)7(71)100(uchar datasize[2];)108 L (4)0(*)7(72)100(uchar magic1;)108 L (5)0(* An arena is split into a sequence of blocks of variable size. The)7(73)100(ulong size; /* same as Bhdr->size */)108 L (6)0(* blocks begin with a Bhdr that denotes the length \(including the Bhdr\))7(74 };)100 L (7)0(* of the block. An arena begins with an Arena header block \(Arena,)7(75 #define B2T\(b\) \(\(Btail*\)\(\(uchar*\)\(b\)+\(b\)->size-sizeof\(Btail\)\)\))100 L (8)0(* ARENA_MAGIC\) and ends with a Bhdr block with magic ARENATAIL_MAGIC and)7(76 #define B2PT\(b\) \(\(Btail*\)\(\(uchar*\)\(b\)-sizeof\(Btail\)\)\))100 L (9)0(* size 0. Intermediate blocks are either allocated or free. At the end)7(77 #define T2HDR\(t\) \(\(Bhdr*\)\(\(uchar*\)\(t\)+sizeof\(Btail\)-\(t\)->size\)\))100 L (10 * of each intermediate block is a Btail, which contains information)0(78 struct Free {)100 L (11 * about where the block starts. This is useful for walking backwards.)0(79)100(Bhdr;)124 L (12 *)0(80)100(Free* left;)108 L (13 * Free blocks \(Free*\) have a magic value of FREE_MAGIC in their Bhdr)0(81)100(Free* right;)108 L (14 * headers. They are kept in a binary tree \(p->freeroot\) traversible by)0(82)100(Free* next;)108 L (15 * walking ->left and ->right. Each node of the binary tree is a pointer)0(83)100(Free* prev;)108 L (16 * to a circular doubly-linked list \(next, prev\) of blocks of identical)0(84 };)100 L (17 * size. Blocks are added to this ``tree of lists'' by pooladd\(\), and)0(85 enum {)100 L (18 * removed by pooldel\(\).)0(86)100(FREE_MAGIC = 0xBA5EBA11,)108 L (19 *)0(87 };)100 L (20 * When freed, adjacent blocks are coalesced to create larger blocks when)0(88)100 L (21 * possible.)0(89 /*)100 L (22 *)0(90 * the point of the notused fields is to make 8c differentiate)100 L (23 * Allocated blocks \(Alloc*\) have one of two magic values: KEMPT_MAGIC or)0(91 * between Bhdr and Allocblk, and between Kempt and Unkempt.)100 L (24 * UNKEMPT_MAGIC. When blocks are released from the pool, they have)0(92 */)100 L (25 * magic value UNKEMPT_MAGIC. Once the block has been trimmed by kemb\(\))0(93 struct Alloc {)100 L (26 * and the amount of user-requested data has been recorded in the)0(94)100(Bhdr;)124 L (27 * datasize field of the tail, the magic value is changed to KEMPT_MAGIC.)0(95 };)100 L (28 * All blocks returned to callers should be of type KEMPT_MAGIC, as)0(96 enum {)100 L (29 * should all blocks passed to us by callers. The amount of data the user)0(97)100(KEMPT_MAGIC = 0x0A110C09,)108 L (30 * asked us for can be found by subtracting the short in tail->datasize)0(98)100(UNKEMPT_MAGIC = 0xCAB00D1E+1,)108 L (31 * from header->size. Further, the up to at most four bytes between the)0(99 };)100 L (32 * end of the user-requested data block and the actual Btail structure are)0(100)100 L (33 * marked with a magic value, which is checked to detect user overflow.)0(101 struct Arena {)100 L (34 *)0(102)100(Bhdr;)124 L (35 * The arenas returned by p->alloc are kept in a doubly-linked list)0(103 Arena* aup;)100 L (36 * \(p->arenalist\) running through the arena headers, sorted by descending)0(104 Arena* down;)100 L (37 * base address \(prev, next\). When a new arena is allocated, we attempt)0(105 ulong asize;)100 L (38 * to merge it with its two neighbors via p->merge.)0(106 ulong pad; /* to a multiple of 8 bytes */)100 L (39 */)0(107 };)100 L (40)0(108 enum {)100 L (41 #include )0(109 ARENA_MAGIC = 0xC0A1E5CE+1,)100 L (42 #include )0(110 ARENATAIL_MAGIC = 0xEC5E1A0C+1,)100 L (43 #include )0(111 };)100 L (44)0(112 #define A2TB\(a\) \(\(Bhdr*\)\(\(uchar*\)\(a\)+\(a\)->asize-sizeof\(Bhdr\)\)\))100 L (45 typedef struct Alloc)0(Alloc;)32(113 #define A2B\(a\) B2NB\(a\))100 L (46 typedef struct Arena)0(Arena;)32(114)100 L (47 typedef struct Bhdr)0(Bhdr;)32(115 enum {)100 L (48 typedef struct Btail)0(Btail;)32(116 MINBLOCKSIZE = sizeof\(Free\)+sizeof\(Btail\))100 L (49 typedef struct Free)0(Free;)32(117 };)100 L (50)0(118)100 L (51 struct Bhdr {)0(119 static uchar datamagic[] = { 0xFE, 0xF1, 0xF0, 0xFA };)100 L (52)0(ulong magic;)8(120)100 L (53)0(ulong size;)8(121 #define Poison \(void*\)0xCafeBabe)100 L (54 };)0(122)100 L (55 enum {)0(123 #define _B2D\(a\) \(\(void*\)\(\(uchar*\)a+sizeof\(Bhdr\)\)\))100 L (56)0(NOT_MAGIC = 0xdeadfa11,)8(124 #define _D2B\(v\) \(\(Alloc*\)\(\(uchar*\)v-sizeof\(Bhdr\)\)\))100 L (57 };)0(125)100 L (58 #define B2NB\(b\) \(\(Bhdr*\)\(\(uchar*\)\(b\)+\(b\)->size\)\))0(126 // static void* _B2D\(void*\);)100 L (59)0(127 // static void* _D2B\(void*\);)100 L (60 #define SHORT\(x\) \(\(\(x\)[0] << 8\) | \(x\)[1]\))0(128 static void*)100(B2D\(Pool*, Alloc*\);)124 L (61 #define PSHORT\(p, x\) \\)0(129 static Alloc* D2B\(Pool*, void*\);)100 L (62)0(\(\(\(uchar*\)\(p\)\)[0] = \(\(x\)>>8\)&0xFF, \\)8(130 static Arena* arenamerge\(Pool*, Arena*, Arena*\);)100 L (63)0(\(\(uchar*\)\(p\)\)[1] = \(x\)&0xFF\))8(131 static void)100(blockcheck\(Pool*, Bhdr*\);)132 L (64)0(132 static Alloc* blockmerge\(Pool*, Bhdr*, Bhdr*\);)100 L (65 enum {)0(133 static Alloc* blocksetdsize\(Pool*, Alloc*, ulong\);)100 L (66)0(TAIL_MAGIC0 = 0xBE,)8(134 static Bhdr*)100(blocksetsize\(Bhdr*, ulong\);)124 L (67)0(TAIL_MAGIC1 = 0xEF)8(135 static ulong)100(bsize2asize\(Pool*, ulong\);)124 L (68 };)0(136 static ulong)100(dsize2bsize\(Pool*, ulong\);)124 L cleartomark showpage saveobj restore %%EndPage: 267 267 %%Page: 268 268 /saveobj save def mark 268 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 2)l ()l ()l (137 static ulong)0(getdsize\(Alloc*\);)24(205)100 L (138 static Alloc* kemb\(Pool*, Alloc*, ulong\);)0(206)100(if\(size == \(*t\)->size\))116 L (139 static Free*)0(listadd\(Free*, Free*\);)24(207)100(return t;)124 L (140 static Free*)0(listdelete\(Free*, Free*\);)24(208)100(if\(size < \(*t\)->size\))116 L (141 static void)0(logstack\(Pool*\);)32(209)100(t = &\(*t\)->left;)124 L (142 static Free** ltreewalk\(Free**, ulong\);)0(210)100(else)116 L (143 static void)0(memmark\(void*, int, ulong\);)32(211)100(t = &\(*t\)->right;)124 L (144 static Free*)0(pooladd\(Pool*, Alloc*\);)24(212 })100 L (145 static void*)0(poolallocl\(Pool*, ulong\);)24(213 return nil; /* not reached */)100 L (146 static void)0(poolcheckl\(Pool*\);)32(214 })100 L (147 static void)0(poolcheckarena\(Pool*, Arena*\);)32(215)100 L (148 static int)0(poolcompactl\(Pool*\);)32(216 /* treelookup: find node in tree with size == size */)100 L (149 static Alloc* pooldel\(Pool*, Free*\);)0(217 static Free*)100 L (150 static void)0(pooldumpl\(Pool*\);)32(218 treelookup\(Free *t, ulong size\))100 L (151 static void)0(pooldumparena\(Pool*, Arena*\);)32(219 {)100 L (152 static void)0(poolfreel\(Pool*, void*\);)32(220 return *ltreewalk\(&t, size\);)100 L (153 static void)0(poolnewarena\(Pool*, ulong\);)32(221 })100 L (154 static void*)0(poolreallocl\(Pool*, void*, ulong\);)24(222)100 L (155 static Free*)0(treedelete\(Free*, Free*\);)24(223 /* treeinsert: insert node into tree */)100 L (156 static Free*)0(treeinsert\(Free*, Free*\);)24(224 static Free*)100 L (157 static Free*)0(treelookup\(Free*, ulong\);)24(225 treeinsert\(Free *tree, Free *node\))100 L (158 static Free*)0(treelookupgt\(Free*, ulong\);)24(226 {)100 L (159)0(227 Free **loc, *repl;)100 L (160 /*)0(228)100 L (161 * Debugging)0(229 assert\(node != nil /* treeinsert */\);)100 L (162 *)0(230)100 L (163 * Antagonism causes blocks to always be filled with garbage if their)0(231 loc = ltreewalk\(&tree, node->size\);)100 L (164 * contents are undefined. This tickles both programs and the library.)0(232 if\(*loc == nil\) {)100 L (165 * It's a linear time hit but not so noticeable during nondegenerate use.)0(233)100(node->left = nil;)116 L (166 * It would be worth leaving in except that it negates the benefits of the)0(234)100(node->right = nil;)116 L (167 * kernel's demand-paging. The tail magic and end-of-data magic)0(235 } else {)100(/* replace existing node */)124 L (168 * provide most of the user-visible benefit that antagonism does anyway.)0(236)100(repl = *loc;)116 L (169 *)0(237)100(node->left = repl->left;)116 L (170 * Paranoia causes the library to recheck the entire pool on each lock)0(238)100(node->right = repl->right;)116 L (171 * or unlock. A failed check on unlock means we tripped over ourselves,)0(239 })100 L (172 * while a failed check on lock tends to implicate the user. Paranoia has)0(240 *loc = node;)100 L (173 * the potential to slow things down a fair amount for pools with large)0(241 return tree;)100 L (174 * numbers of allocated blocks. It completely negates all benefits won)0(242 })100 L (175 * by the binary tree. Turning on paranoia in the kernel makes it painfully)0(243)100 L (176 * slow.)0(244 /* treedelete: remove node from tree */)100 L (177 *)0(245 static Free*)100 L (178 * Verbosity induces the dumping of the pool via p->print at each lock operation.)0(246 treedelete\(Free *tree, Free *node\))100 L (179 * By default, only one line is logged for each alloc, free, and realloc.)0(247 {)100 L (180 */)0(248 Free **loc, **lsucc, *succ;)100 L (181)0(249)100 L (182 /* the if\(!x\);else avoids ``dangling else'' problems */)0(250 assert\(node != nil /* treedelete */\);)100 L (183 #define antagonism)0(if\(!\(p->flags & POOL_ANTAGONISM\)\);else)32(251)100 L (184 #define paranoia if\(!\(p->flags & POOL_PARANOIA\)\);else)0(252 loc = ltreewalk\(&tree, node->size\);)100 L (185 #define verbosity if\(!\(p->flags & POOL_VERBOSITY\)\);else)0(253 assert\(*loc == node\);)100 L (186)0(254)100 L (187 #define DPRINT if\(!\(p->flags & POOL_DEBUGGING\)\);else p->print)0(255 if\(node->left == nil\))100 L (188 #define LOG)0(if\(!\(p->flags & POOL_LOGGING\)\);else p->print)32(256)100(*loc = node->right;)116 L (189)0(257 else if\(node->right == nil\))100 L (190 /*)0(258)100(*loc = node->left;)116 L (191 * Tree walking)0(259 else {)100 L (192 */)0(260)100(/* have two children, use inorder successor as replacement */)116 L (193)0(261)100(for\(lsucc = &node->right; \(*lsucc\)->left; lsucc = &\(*lsucc\)->left\))116 L (194 /* ltreewalk: return address of pointer to node of size == size */)0(262)100(;)124 L (195 static Free**)0(263)100(succ = *lsucc;)116 L (196 ltreewalk\(Free **t, ulong size\))0(264)100(*lsucc = succ->right;)116 L (197 {)0(265)100(succ->left = node->left;)116 L (198 assert\(t != nil /* ltreewalk */\);)0(266)100(succ->right = node->right;)116 L (199)0(267)100(*loc = succ;)116 L (200 for\(;;\) {)0(268 })100 L (201)0(if\(*t == nil\))16(269)100 L (202)0(return t;)24(270 node->left = node->right = Poison;)100 L (203)0(271 return tree;)100 L (204)0(assert\(\(*t\)->magic == FREE_MAGIC\);)16(272 })100 L cleartomark showpage saveobj restore %%EndPage: 268 268 %%Page: 269 269 /saveobj save def mark 269 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 3)l ()l ()l (273)0(341)100 L (274 /* treelookupgt: find smallest node in tree with size >= size */)0(342 /* pooladd: add anode to the free pool */)100 L (275 static Free*)0(343 static Free*)100 L (276 treelookupgt\(Free *t, ulong size\))0(344 pooladd\(Pool *p, Alloc *anode\))100 L (277 {)0(345 {)100 L (278 Free *lastgood; /* last node we saw that was big enough */)0(346 Free *lst, *olst;)100 L (279)0(347 Free *node;)100 L (280 lastgood = nil;)0(348 Free **parent;)100 L (281 for\(;;\) {)0(349)100 L (282)0(if\(t == nil\))16(350 antagonism {)100 L (283)0(return lastgood;)24(351)100(memmark\(_B2D\(anode\), 0xF7, anode->size-sizeof\(Bhdr\)-sizeof\(Btail\)\);)116 L (284)0(if\(size == t->size\))16(352 })100 L (285)0(return t;)24(353)100 L (286)0(if\(size < t->size\) {)16(354 node = \(Free*\)anode;)100 L (287)0(lastgood = t;)24(355 node->magic = FREE_MAGIC;)100 L (288)0(t = t->left;)24(356 parent = ltreewalk\(&p->freeroot, node->size\);)100 L (289)0(} else {)16(357 olst = *parent;)100 L (290)0(t = t->right;)24(358 lst = listadd\(olst, node\);)100 L (291)0(})16(359 if\(olst != lst\) /* need to update tree */)100 L (292 })0(360)100(*parent = treeinsert\(*parent, lst\);)116 L (293 return nil; /* not reached */)0(361 p->curfree += node->size;)100 L (294 })0(362 return node;)100 L (295)0(363 })100 L (296 /*)0(364)100 L (297 * List maintenance)0(365 /* pooldel: remove node from the free pool */)100 L (298 */)0(366 static Alloc*)100 L (299)0(367 pooldel\(Pool *p, Free *node\))100 L (300 /* listadd: add a node to a doubled linked list */)0(368 {)100 L (301 static Free*)0(369 Free *lst, *olst;)100 L (302 listadd\(Free *list, Free *node\))0(370 Free **parent;)100 L (303 {)0(371)100 L (304 if\(list == nil\) {)0(372 parent = ltreewalk\(&p->freeroot, node->size\);)100 L (305)0(node->next = node;)16(373 olst = *parent;)100 L (306)0(node->prev = node;)16(374 assert\(olst != nil /* pooldel */\);)100 L (307)0(return node;)16(375)100 L (308 })0(376 lst = listdelete\(olst, node\);)100 L (309)0(377 if\(lst == nil\))100 L (310 node->prev = list->prev;)0(378)100(*parent = treedelete\(*parent, olst\);)116 L (311 node->next = list;)0(379 else if\(lst != olst\))100 L (312)0(380)100(*parent = treeinsert\(*parent, lst\);)116 L (313 node->prev->next = node;)0(381)100 L (314 node->next->prev = node;)0(382 node->left = node->right = Poison;)100 L (315)0(383 p->curfree -= node->size;)100 L (316 return list;)0(384)100 L (317 })0(385 antagonism {)100 L (318)0(386)100(memmark\(_B2D\(node\), 0xF9, node->size-sizeof\(Bhdr\)-sizeof\(Btail\)\);)116 L (319 /* listdelete: remove node from a doubly linked list */)0(387 })100 L (320 static Free*)0(388)100 L (321 listdelete\(Free *list, Free *node\))0(389 node->magic = UNKEMPT_MAGIC;)100 L (322 {)0(390 return \(Alloc*\)node;)100 L (323 if\(node->next == node\) {)0(/* singular list */)40(391 })100 L (324)0(node->prev = node->next = Poison;)16(392)100 L (325)0(return nil;)16(393 /*)100 L (326 })0(394 * Block maintenance)100 L (327)0(395 */)100 L (328 node->next->prev = node->prev;)0(396 /* block allocation */)100 L (329 node->prev->next = node->next;)0(397 static ulong)100 L (330)0(398 dsize2bsize\(Pool *p, ulong sz\))100 L (331 if\(list == node\))0(399 {)100 L (332)0(list = node->next;)16(400 sz += sizeof\(Bhdr\)+sizeof\(Btail\);)100 L (333)0(401 if\(sz < p->minblock\))100 L (334 node->prev = node->next = Poison;)0(402)100(sz = p->minblock;)116 L (335 return list;)0(403 sz = \(sz+p->quantum-1\)&~\(p->quantum-1\);)100 L (336 })0(404 return sz;)100 L (337)0(405 })100 L (338 /*)0(406)100 L (339 * Pool maintenance)0(407 static ulong)100 L (340 */)0(408 bsize2asize\(Pool *p, ulong sz\))100 L cleartomark showpage saveobj restore %%EndPage: 269 269 %%Page: 270 270 /saveobj save def mark 270 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 4)l ()l ()l (409 {)0(477 {)100 L (410 sz += sizeof\(Arena\)+sizeof\(Btail\);)0(478 Btail *t;)100 L (411 if\(sz < p->minarena\))0(479 uchar *q, *eq;)100 L (412)0(sz = p->minarena;)16(480)100 L (413 sz = \(sz+p->quantum\)&~\(p->quantum-1\);)0(481 assert\(b->size >= dsize2bsize\(p, dsize\)\);)100 L (414 return sz;)0(482 assert\(b->size - dsize < 0x10000\);)100 L (415 })0(483)100 L (416)0(484 t = B2T\(b\);)100 L (417 /* blockmerge: merge a and b, known to be adjacent */)0(485 PSHORT\(t->datasize, b->size - dsize\);)100 L (418 /* both are removed from pool if necessary. */)0(486)100 L (419 static Alloc*)0(487 q=\(uchar*\)_B2D\(b\)+dsize;)100 L (420 blockmerge\(Pool *pool, Bhdr *a, Bhdr *b\))0(488 eq = \(uchar*\)t;)100 L (421 {)0(489 if\(eq > q+4\))100 L (422 Btail *t;)0(490)100(eq = q+4;)116 L (423)0(491 for\(; qmagic == FREE_MAGIC\))0(494 return b;)100 L (427)0(pooldel\(pool, \(Free*\)a\);)16(495 })100 L (428 if\(b->magic == FREE_MAGIC\))0(496)100 L (429)0(pooldel\(pool, \(Free*\)b\);)16(497 /* kemb: trim a block down to what is needed to hold dsize bytes of user data */)100 L (430)0(498 static Alloc*)100 L (431 t = B2T\(a\);)0(499 kemb\(Pool *p, Alloc *b, ulong dsize\))100 L (432 t->size = \(ulong\)Poison;)0(500 {)100 L (433 t->magic0 = NOT_MAGIC;)0(501 ulong extra, bsize;)100 L (434 t->magic1 = NOT_MAGIC;)0(502 Alloc *frag;)100 L (435 PSHORT\(t->datasize, NOT_MAGIC\);)0(503)100 L (436)0(504 bsize = dsize2bsize\(p, dsize\);)100 L (437 a->size += b->size;)0(505 extra = b->size - bsize;)100 L (438 t = B2T\(a\);)0(506 if\(b->size - dsize >= 0x10000 ||)100 L (439 t->size = a->size;)0(507)100(\(extra >= bsize>>2 && extra >= MINBLOCKSIZE && extra >= p->minblock\)\) {)110 L (440 PSHORT\(t->datasize, 0xFFFF\);)0(508)100(blocksetsize\(b, bsize\);)116 L (441)0(509)100(frag = \(Alloc*\) B2NB\(b\);)116 L (442 b->size = NOT_MAGIC;)0(510)100 L (443 b->magic = NOT_MAGIC;)0(511)100(antagonism {)116 L (444)0(512)100(memmark\(frag, 0xF1, extra\);)124 L (445 a->magic = UNKEMPT_MAGIC;)0(513)100(})116 L (446 return \(Alloc*\)a;)0(514)100 L (447 })0(515)100(frag->magic = UNKEMPT_MAGIC;)116 L (448)0(516)100(blocksetsize\(frag, extra\);)116 L (449 /* blocksetsize: set the total size of a block, fixing tail pointers */)0(517)100(pooladd\(p, frag\);)116 L (450 static Bhdr*)0(518 })100 L (451 blocksetsize\(Bhdr *b, ulong bsize\))0(519)100 L (452 {)0(520 b->magic = KEMPT_MAGIC;)100 L (453 Btail *t;)0(521 blocksetdsize\(p, b, dsize\);)100 L (454)0(522 return b;)100 L (455 assert\(b->magic != FREE_MAGIC /* blocksetsize */\);)0(523 })100 L (456)0(524)100 L (457 b->size = bsize;)0(525 /*)100 L (458 t = B2T\(b\);)0(526 * Arena maintenance)100 L (459 t->size = b->size;)0(527 */)100 L (460 t->magic0 = TAIL_MAGIC0;)0(528)100 L (461 t->magic1 = TAIL_MAGIC1;)0(529 /* arenasetsize: set arena size, updating tail */)100 L (462 return b;)0(530 static void)100 L (463 })0(531 arenasetsize\(Arena *a, ulong asize\))100 L (464)0(532 {)100 L (465 /* getdsize: return the requested data size for an allocated block */)0(533 Bhdr *atail;)100 L (466 static ulong)0(534)100 L (467 getdsize\(Alloc *b\))0(535 a->asize = asize;)100 L (468 {)0(536 atail = A2TB\(a\);)100 L (469 Btail *t;)0(537 atail->magic = ARENATAIL_MAGIC;)100 L (470 t = B2T\(b\);)0(538 atail->size = 0;)100 L (471 return b->size - SHORT\(t->datasize\);)0(539 })100 L (472 })0(540)100 L (473)0(541 /* poolnewarena: allocate new arena */)100 L (474 /* blocksetdsize: set the user data size of a block */)0(542 static void)100 L (475 static Alloc*)0(543 poolnewarena\(Pool *p, ulong asize\))100 L (476 blocksetdsize\(Pool *p, Alloc *b, ulong dsize\))0(544 {)100 L cleartomark showpage saveobj restore %%EndPage: 270 270 %%Page: 271 271 /saveobj save def mark 271 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 5)l ()l ()l (545 Arena *a;)0(613)100(blockcheck\(p, a\);)116 L (546 Arena *ap, *lastap;)0(614)100(pooladd\(p, a\);)116 L (547 Alloc *b;)0(615 } else {)100 L (548)0(616)100(Alloc *a;)116 L (549 LOG\(p, "newarena %lud\\n", asize\);)0(617)100(ulong dsize;)116 L (550 if\(p->cursize+asize > p->maxsize\) {)0(618)100 L (551)0(if\(poolcompactl\(p\) == 0\))16(619)100(a = \(Alloc*\)b;)116 L (552)0(LOG\(p, "pool too big: %lud+%lud > %lud\\n",)24(620)100(dsize = getdsize\(a\);)116 L (553)0(p->cursize, asize, p->maxsize\);)32(621)100(blocksetsize\(a, nsize\);)116 L (554)0(return;)16(622)100(kemb\(p, a, dsize\);)116 L (555 })0(623 })100 L (556)0(624 })100 L (557 if\(\(a = p->alloc\(asize\)\) == nil\) {)0(625)100 L (558)0(/* assume errstr set by p->alloc */)16(626 /* arenamerge: attempt to coalesce to arenas that might be adjacent */)100 L (559)0(return;)16(627 static Arena*)100 L (560 })0(628 arenamerge\(Pool *p, Arena *bot, Arena *top\))100 L (561)0(629 {)100 L (562 p->cursize += asize;)0(630 Bhdr *bbot, *btop;)100 L (563)0(631 Btail *t;)100 L (564 /* arena hdr */)0(632)100 L (565 a->magic = ARENA_MAGIC;)0(633 blockcheck\(p, bot\);)100 L (566 blocksetsize\(a, sizeof\(Arena\)\);)0(634 blockcheck\(p, top\);)100 L (567 arenasetsize\(a, asize\);)0(635 assert\(bot->aup == top && top > bot\);)100 L (568 blockcheck\(p, a\);)0(636)100 L (569)0(637 if\(p->merge == nil || p->merge\(bot, top\) == 0\))100 L (570 /* create one large block in arena */)0(638)100(return nil;)116 L (571 b = \(Alloc*\)A2B\(a\);)0(639)100 L (572 b->magic = UNKEMPT_MAGIC;)0(640 /* remove top from list */)100 L (573 blocksetsize\(b, \(uchar*\)A2TB\(a\)-\(uchar*\)b\);)0(641 if\(bot->aup = top->aup\) /* assign = */)100 L (574 blockcheck\(p, b\);)0(642)100(bot->aup->down = bot;)116 L (575 pooladd\(p, b\);)0(643 else)100 L (576 blockcheck\(p, b\);)0(644)100(p->arenalist = bot;)116 L (577)0(645)100 L (578 /* sort arena into descending sorted arena list */)0(646 /* save ptrs to last block in bot, first block in top */)100 L (579 for\(lastap=nil, ap=p->arenalist; ap > a; lastap=ap, ap=ap->down\))0(647 t = B2PT\(A2TB\(bot\)\);)100 L (580)0(;)16(648 bbot = T2HDR\(t\);)100 L (581)0(649 btop = A2B\(top\);)100 L (582 if\(a->down = ap\))0(/* assign = */)32(650 blockcheck\(p, bbot\);)100 L (583)0(a->down->aup = a;)16(651 blockcheck\(p, btop\);)100 L (584)0(652)100 L (585 if\(a->aup = lastap\) /* assign = */)0(653 /* grow bottom arena to encompass top */)100 L (586)0(a->aup->down = a;)16(654 arenasetsize\(bot, top->asize + \(\(uchar*\)top - \(uchar*\)bot\)\);)100 L (587 else)0(655)100 L (588)0(p->arenalist = a;)16(656 /* grow bottom block to encompass space between arenas */)100 L (589)0(657 blockgrow\(p, bbot, \(uchar*\)btop-\(uchar*\)bbot\);)100 L (590 /* merge with surrounding arenas if possible */)0(658 blockcheck\(p, bbot\);)100 L (591 /* must do a with up before down with a \(think about it\) */)0(659 return bot;)100 L (592 if\(a->aup\))0(660 })100 L (593)0(arenamerge\(p, a, a->aup\);)16(661)100 L (594 if\(a->down\))0(662 /* dumpblock: print block's vital stats */)100 L (595)0(arenamerge\(p, a->down, a\);)16(663 static void)100 L (596 })0(664 dumpblock\(Pool *p, Bhdr *b\))100 L (597)0(665 {)100 L (598 /* blockresize: grow a block to encompass space past its end, possibly by */)0(666 ulong *dp;)100 L (599 /* trimming it into two different blocks. */)0(667 ulong dsize;)100 L (600 static void)0(668 uchar *cp;)100 L (601 blockgrow\(Pool *p, Bhdr *b, ulong nsize\))0(669)100 L (602 {)0(670 dp = \(ulong*\)b;)100 L (603 if\(b->magic == FREE_MAGIC\) {)0(671 p->print\(p, "pool %s block %p\\nhdr %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux\\n",)100 L (604)0(Alloc *a;)16(672)100(p->name, b, dp[0], dp[1], dp[2], dp[3], dp[4], dp[5], dp[6]\);)116 L (605)0(Bhdr *bnxt;)16(673)100 L (606)0(a = pooldel\(p, \(Free*\)b\);)16(674 if\(b->size >= 1024*1024*1024\) /* tail pointer corrupt; printing tail will fault */)100 L (607)0(blockcheck\(p, a\);)16(675)100(return;)116 L (608)0(blocksetsize\(a, nsize\);)16(676 dp = \(ulong*\)B2T\(b\);)100 L (609)0(blockcheck\(p, a\);)16(677 p->print\(p, "tail %.8lux %.8lux %.8lux %.8lux %.8lux %.8lux\\n",)100 L (610)0(bnxt = B2NB\(a\);)16(678)100(dp[-6], dp[-5], dp[-4], dp[-3], dp[-2], dp[-1]\);)116 L (611)0(if\(bnxt->magic == FREE_MAGIC\))16(679)100 L (612)0(a = blockmerge\(p, a, bnxt\);)24(680 if\(b->magic == KEMPT_MAGIC\){)100 L cleartomark showpage saveobj restore %%EndPage: 271 271 %%Page: 272 272 /saveobj save def mark 272 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 6)l ()l ()l (681)0(dsize = getdsize\(\(Alloc*\)b\);)16(749)100(if\(t->magic0 != TAIL_MAGIC0\){)116 L (682)0(if\(dsize >= b->size\) /* user data size corrupt */)16(750)100(/* if someone wrote exactly one byte over and it was a NUL, we sometimes on)124 L (683)0(return;)24(751)100(if\(\(p->flags & POOL_TOLERANCE\) && bq == eq && t->magic0 == 0\))124 L (684)0(752)100(printblock\(p, b, "mem user overflow \(magic0\)"\);)132 L (685)0(cp = \(uchar*\)_B2D\(b\)+dsize;)16(753)100(else)124 L (686)0(p->print\(p, "user data "\);)16(754)100(panicblock\(p, b, "corrupt tail magic0"\);)132 L (687)0(p->print\(p, "%.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux",)16(755)100(})116 L (688)0(cp[-8], cp[-7], cp[-6], cp[-5], cp[-4], cp[-3], cp[-2], cp[-1]\);)24(756)100 L (689)0(p->print\(p, " | %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux %.2ux\\n",)16(757)100(if\(t->magic1 != TAIL_MAGIC1\))116 L (690)0(cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]\);)24(758)100(panicblock\(p, b, "corrupt tail magic1"\);)124 L (691 })0(759)100(if\(T2HDR\(t\) != b\))116 L (692 })0(760)100(panicblock\(p, b, "corrupt tail ptr"\);)124 L (693)0(761)100 L (694 static void)0(762)100(if\(dsize2bsize\(p, dsize\) > a->size\))116 L (695 printblock\(Pool *p, Bhdr *b, char *msg\))0(763)100(panicblock\(p, b, "too much block data"\);)124 L (696 {)0(764)100 L (697 p->print\(p, "%s\\n", msg\);)0(765)100(if\(eq > bq+4\))116 L (698 dumpblock\(p, b\);)0(766)100(eq = bq+4;)124 L (699 })0(767)100(for\(q=bq; qflags & POOL_TOLERANCE\)\){)132 L (702 panicblock\(Pool *p, Bhdr *b, char *msg\))0(770)100(printblock\(p, b, "mem user overflow"\);)140 L (703 {)0(771)100(continue;)140 L (704 p->print\(p, "%s\\n", msg\);)0(772)100(})132 L (705 dumpblock\(p, b\);)0(773)100(panicblock\(p, b, "mem user overflow"\);)132 L (706 p->panic\(p, "pool panic"\);)0(774)100(})124 L (707 })0(775)100(})116 L (708)0(776)100(break;)116 L (709 /* blockcheck: ensure a block consistent with our expectations */)0(777 })100 L (710 /* should only be called when holding pool lock */)0(778 })100 L (711 static void)0(779)100 L (712 blockcheck\(Pool *p, Bhdr *b\))0(780 /*)100 L (713 {)0(781 * compact an arena by shifting all the free blocks to the end.)100 L (714 Alloc *a;)0(782 * assumes pool lock is held.)100 L (715 Btail *t;)0(783 */)100 L (716 uchar *q, *bq, *eq;)0(784 enum {)100 L (717 ulong dsize;)0(785 FLOATING_MAGIC = 0xCBCBCBCB, /* temporarily neither allocated nor in the free tree */)100 L (718)0(786 };)100 L (719 switch\(b->magic\) {)0(787)100 L (720 default:)0(788 static int)100 L (721)0(panicblock\(p, b, "bad magic"\);)16(789 arenacompact\(Pool *p, Arena *a\))100 L (722 case FREE_MAGIC:)0(790 {)100 L (723 case UNKEMPT_MAGIC:)0(791 Bhdr *b, *wb, *eb, *nxt;)100 L (724)0(t = B2T\(b\);)16(792 int compacted;)100 L (725)0(if\(t->magic0 != TAIL_MAGIC0 || t->magic1 != TAIL_MAGIC1\))16(793)100 L (726)0(panicblock\(p, b, "corrupt tail magic"\);)24(794 if\(p->move == nil\))100 L (727)0(if\(T2HDR\(t\) != b\))16(795)100(p->panic\(p, "don't call me when pool->move is nil\\n"\);)116 L (728)0(panicblock\(p, b, "corrupt tail ptr"\);)24(796)100 L (729)0(break;)16(797 poolcheckarena\(p, a\);)100 L (730 case ARENA_MAGIC:)0(798 eb = A2TB\(a\);)100 L (731)0(b = A2TB\(\(Arena*\)b\);)16(799 compacted = 0;)100 L (732)0(if\(b->magic != ARENATAIL_MAGIC\))16(800 for\(b=wb=A2B\(a\); b && b < eb; b=nxt\) {)100 L (733)0(panicblock\(p, b, "bad arena size"\);)24(801)100(nxt = B2NB\(b\);)116 L (734)0(/* fall through */)16(802)100(switch\(b->magic\) {)116 L (735 case ARENATAIL_MAGIC:)0(803)100(case FREE_MAGIC:)116 L (736)0(if\(b->size != 0\))16(804)100(pooldel\(p, \(Free*\)b\);)124 L (737)0(panicblock\(p, b, "bad arena tail size"\);)24(805)100(b->magic = FLOATING_MAGIC;)124 L (738)0(break;)16(806)100(break;)124 L (739 case KEMPT_MAGIC:)0(807)100(case KEMPT_MAGIC:)116 L (740)0(a = \(Alloc*\)b;)16(808)100(if\(wb != b\) {)124 L (741)0(if\(a->size > 1024*1024*1024\))16(809)100(memmove\(wb, b, b->size\);)132 L (742)0(panicblock\(p, b, "block too big"\);)24(810)100(p->move\(_B2D\(b\), _B2D\(wb\)\);)132 L (743)0(811)100(compacted = 1;)132 L (744)0(t = B2T\(b\);)16(812)100(})124 L (745)0(dsize = getdsize\(a\);)16(813)100(wb = B2NB\(wb\);)124 L (746)0(bq = \(uchar*\)_B2D\(a\)+dsize;)16(814)100(break;)124 L (747)0(eq = \(uchar*\)t;)16(815)100(})116 L (748)0(816 })100 L cleartomark showpage saveobj restore %%EndPage: 272 272 %%Page: 273 273 /saveobj save def mark 273 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 7)l ()l ()l (817)0(885 a = \(Alloc*\)\(\(uchar*\)v-sizeof\(Bhdr\)\);)100 L (818 /*)0(886 return a;)100 L (819)0(* the only free data is now at the end of the arena, pointed)9(887 })100 L (820)0(* at by wb. all we need to do is set its size and get out.)9(888 */)100 L (821)0(*/)9(889)100 L (822 if\(wb < eb\) {)0(890 static Alloc*)100 L (823)0(wb->magic = UNKEMPT_MAGIC;)16(891 D2B\(Pool *p, void *v\))100 L (824)0(blocksetsize\(wb, \(uchar*\)eb-\(uchar*\)wb\);)16(892 {)100 L (825)0(pooladd\(p, \(Alloc*\)wb\);)16(893 Alloc *a;)100 L (826 })0(894 a = _D2B\(v\);)100 L (827)0(895 if\(a->magic != KEMPT_MAGIC\))100 L (828 return compacted;)0(896)100(p->panic\(p, "D2B called on non-block %p", v\);)116 L (829 })0(897 return a;)100 L (830)0(898 })100 L (831 /*)0(899)100 L (832 * compact a pool by compacting each individual arena.)0(900 /* poolallocl: attempt to allocate block to hold dsize user bytes; assumes lock held */)100 L (833 * 'twould be nice to shift blocks from one arena to the)0(901 static void*)100 L (834 * next but it's a pain to code.)0(902 poolallocl\(Pool *p, ulong dsize\))100 L (835 */)0(903 {)100 L (836 static int)0(904 ulong bsize;)100 L (837 poolcompactl\(Pool *pool\))0(905 Free *fb;)100 L (838 {)0(906 Alloc *ab;)100 L (839 Arena *a;)0(907)100 L (840 int compacted;)0(908 if\(dsize < 0 || dsize >= 0x80000000UL\) /* for sanity, overflow */)100 L (841)0(909)100(return nil;)116 L (842 if\(pool->move == nil || pool->lastcompact == pool->nfree\))0(910)100 L (843)0(return 0;)16(911 bsize = dsize2bsize\(p, dsize\);)100 L (844)0(912)100 L (845 pool->lastcompact = pool->nfree;)0(913 fb = treelookupgt\(p->freeroot, bsize\);)100 L (846 compacted = 0;)0(914 if\(fb == nil\) {)100 L (847 for\(a=pool->arenalist; a; a=a->down\))0(915)100(poolnewarena\(p, bsize2asize\(p, bsize\)\);)116 L (848)0(compacted |= arenacompact\(pool, a\);)16(916)100(if\(\(fb = treelookupgt\(p->freeroot, bsize\)\) == nil\) {)116 L (849 return compacted;)0(917)100(/* assume poolnewarena failed and set %r */)124 L (850 })0(918)100(return nil;)124 L (851)0(919)100(})116 L (852 /*)0(920 })100 L (853 static int)0(921)100 L (854 poolcompactl\(Pool*\))0(922 ab = kemb\(p, pooldel\(p, fb\), dsize\);)100 L (855 {)0(923 p->curalloc += ab->size;)100 L (856 return 0;)0(924 return B2D\(p, ab\);)100 L (857 })0(925 })100 L (858 */)0(926)100 L (859)0(927 /* poolreallocl: attempt to grow v to ndsize bytes; assumes lock held */)100 L (860 /*)0(928 static void*)100 L (861 * Actual allocators)0(929 poolreallocl\(Pool *p, void *v, ulong ndsize\))100 L (862 */)0(930 {)100 L (863)0(931 Alloc *a;)100 L (864 /*)0(932 Bhdr *left, *right, *newb;)100 L (865 static void*)0(933 Btail *t;)100 L (866 _B2D\(void *a\))0(934 ulong nbsize;)100 L (867 {)0(935 ulong odsize;)100 L (868 return \(uchar*\)a+sizeof\(Bhdr\);)0(936 ulong obsize;)100 L (869 })0(937 void *nv;)100 L (870 */)0(938)100 L (871)0(939 if\(v == nil\) /* for ANSI */)100 L (872 static void*)0(940)100(return poolallocl\(p, ndsize\);)116 L (873 B2D\(Pool *p, Alloc *a\))0(941 if\(ndsize == 0\) {)100 L (874 {)0(942)100(poolfreel\(p, v\);)116 L (875 if\(a->magic != KEMPT_MAGIC\))0(943)100(return nil;)116 L (876)0(p->panic\(p, "B2D called on unworthy block"\);)16(944 })100 L (877 return _B2D\(a\);)0(945 a = D2B\(p, v\);)100 L (878 })0(946 blockcheck\(p, a\);)100 L (879)0(947 odsize = getdsize\(a\);)100 L (880 /*)0(948 obsize = a->size;)100 L (881 static void*)0(949)100 L (882 _D2B\(void *v\))0(950 /* can reuse the same block? */)100 L (883 {)0(951 nbsize = dsize2bsize\(p, ndsize\);)100 L (884 Alloc *a;)0(952 if\(nbsize <= a->size\) {)100 L cleartomark showpage saveobj restore %%EndPage: 273 273 %%Page: 274 274 /saveobj save def mark 274 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 8)l ()l ()l (953 Returnblock:)0(1021 if\(back->magic == FREE_MAGIC\))100 L (954)0(if\(v != _B2D\(a\)\))16(1022)100(ab = blockmerge\(p, back, ab\);)116 L (955)0(memmove\(_B2D\(a\), v, odsize\);)24(1023)100 L (956)0(a = kemb\(p, a, ndsize\);)16(1024 fwd = B2NB\(ab\);)100 L (957)0(p->curalloc -= obsize;)16(1025 if\(fwd->magic == FREE_MAGIC\))100 L (958)0(p->curalloc += a->size;)16(1026)100(ab = blockmerge\(p, ab, fwd\);)116 L (959)0(v = B2D\(p, a\);)16(1027)100 L (960)0(return v;)16(1028 pooladd\(p, ab\);)100 L (961 })0(1029 })100 L (962)0(1030)100 L (963 /* can merge with surrounding blocks? */)0(1031 void*)100 L (964 right = B2NB\(a\);)0(1032 poolalloc\(Pool *p, ulong n\))100 L (965 if\(right->magic == FREE_MAGIC && a->size+right->size >= nbsize\) {)0(1033 {)100 L (966)0(a = blockmerge\(p, a, right\);)16(1034 void *v;)100 L (967)0(goto Returnblock;)16(1035)100 L (968 })0(1036 p->lock\(p\);)100 L (969)0(1037 paranoia {)100 L (970 t = B2PT\(a\);)0(1038)100(poolcheckl\(p\);)116 L (971 left = T2HDR\(t\);)0(1039 })100 L (972 if\(left->magic == FREE_MAGIC && left->size+a->size >= nbsize\) {)0(1040 verbosity {)100 L (973)0(a = blockmerge\(p, left, a\);)16(1041)100(pooldumpl\(p\);)116 L (974)0(goto Returnblock;)16(1042 })100 L (975 })0(1043 v = poolallocl\(p, n\);)100 L (976)0(1044 paranoia {)100 L (977 if\(left->magic == FREE_MAGIC && right->magic == FREE_MAGIC)0(1045)100(poolcheckl\(p\);)116 L (978 && left->size+a->size+right->size >= nbsize\) {)0(1046 })100 L (979)0(a = blockmerge\(p, blockmerge\(p, left, a\), right\);)16(1047 verbosity {)100 L (980)0(goto Returnblock;)16(1048)100(pooldumpl\(p\);)116 L (981 })0(1049 })100 L (982)0(1050 if\(p->logstack && \(p->flags & POOL_LOGGING\)\) p->logstack\(p\);)100 L (983 if\(\(nv = poolallocl\(p, ndsize\)\) == nil\))0(1051 LOG\(p, "poolalloc %p %lud = %p\\n", p, n, v\);)100 L (984)0(return nil;)16(1052 p->unlock\(p\);)100 L (985)0(1053 return v;)100 L (986 /* maybe the new block is next to us; if so, merge */)0(1054 })100 L (987 left = T2HDR\(B2PT\(a\)\);)0(1055)100 L (988 right = B2NB\(a\);)0(1056 int)100 L (989 newb = D2B\(p, nv\);)0(1057 poolcompact\(Pool *p\))100 L (990 if\(left == newb || right == newb\) {)0(1058 {)100 L (991)0(if\(left == newb || left->magic == FREE_MAGIC\))16(1059 int rv;)100 L (992)0(a = blockmerge\(p, left, a\);)24(1060)100 L (993)0(if\(right == newb || right->magic == FREE_MAGIC\))16(1061 p->lock\(p\);)100 L (994)0(a = blockmerge\(p, a, right\);)24(1062 paranoia {)100 L (995)0(assert\(a->size >= nbsize\);)16(1063)100(poolcheckl\(p\);)116 L (996)0(goto Returnblock;)16(1064 })100 L (997 })0(1065 verbosity {)100 L (998)0(1066)100(pooldumpl\(p\);)116 L (999 /* enough cleverness */)0(1067 })100 L (1000 memmove\(nv, v, odsize\);)0(1068 rv = poolcompactl\(p\);)100 L (1001 poolfreel\(p, v\);)0(1069 paranoia {)100 L (1002 return nv;)0(1070)100(poolcheckl\(p\);)116 L (1003 })0(1071 })100 L (1004)0(1072 verbosity {)100 L (1005 /* poolfree: free block obtained from poolalloc; assumes lock held */)0(1073)100(pooldumpl\(p\);)116 L (1006 static void)0(1074 })100 L (1007 poolfreel\(Pool *p, void *v\))0(1075 LOG\(p, "poolcompact %p\\n", p\);)100 L (1008 {)0(1076 p->unlock\(p\);)100 L (1009 Alloc *ab;)0(1077 return rv;)100 L (1010 Bhdr *back, *fwd;)0(1078 })100 L (1011)0(1079)100 L (1012 if\(v == nil\) /* for ANSI */)0(1080 void*)100 L (1013)0(return;)16(1081 poolrealloc\(Pool *p, void *v, ulong n\))100 L (1014)0(1082 {)100 L (1015 ab = D2B\(p, v\);)0(1083 void *nv;)100 L (1016 blockcheck\(p, ab\);)0(1084)100 L (1017)0(1085 p->lock\(p\);)100 L (1018 p->nfree++;)0(1086 paranoia {)100 L (1019 p->curalloc -= ab->size;)0(1087)100(poolcheckl\(p\);)116 L (1020 back = T2HDR\(B2PT\(ab\)\);)0(1088 })100 L cleartomark showpage saveobj restore %%EndPage: 274 274 %%Page: 275 275 /saveobj save def mark 275 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 9)l ()l ()l (1089 verbosity {)0(1157 if\(p->logstack && \(p->flags & POOL_LOGGING\)\) p->logstack\(p\);)100 L (1090)0(pooldumpl\(p\);)16(1158 LOG\(p, "poolmsize %p %p = %ld\\n", p, v, dsize\);)100 L (1091 })0(1159 p->unlock\(p\);)100 L (1092 nv = poolreallocl\(p, v, n\);)0(1160 return dsize;)100 L (1093 paranoia {)0(1161 })100 L (1094)0(poolcheckl\(p\);)16(1162)100 L (1095 })0(1163 /*)100 L (1096 verbosity {)0(1164 * Debugging)100 L (1097)0(pooldumpl\(p\);)16(1165 */)100 L (1098 })0(1166)100 L (1099 if\(p->logstack && \(p->flags & POOL_LOGGING\)\) p->logstack\(p\);)0(1167 static void)100 L (1100 LOG\(p, "poolrealloc %p %p %ld = %p\\n", p, v, n, nv\);)0(1168 poolcheckarena\(Pool *p, Arena *a\))100 L (1101 p->unlock\(p\);)0(1169 {)100 L (1102 return nv;)0(1170 Bhdr *b;)100 L (1103 })0(1171 Bhdr *atail;)100 L (1104)0(1172)100 L (1105 void)0(1173 atail = A2TB\(a\);)100 L (1106 poolfree\(Pool *p, void *v\))0(1174 for\(b=a; b->magic != ARENATAIL_MAGIC && block\(p\);)0(1176 blockcheck\(p, b\);)100 L (1109 paranoia {)0(1177 if\(b != atail\))100 L (1110)0(poolcheckl\(p\);)16(1178)100(p->panic\(p, "found wrong tail"\);)116 L (1111 })0(1179 })100 L (1112 verbosity {)0(1180)100 L (1113)0(pooldumpl\(p\);)16(1181 static void)100 L (1114 })0(1182 poolcheckl\(Pool *p\))100 L (1115 poolfreel\(p, v\);)0(1183 {)100 L (1116 paranoia {)0(1184 Arena *a;)100 L (1117)0(poolcheckl\(p\);)16(1185)100 L (1118 })0(1186 for\(a=p->arenalist; a; a=a->down\))100 L (1119 verbosity {)0(1187)100(poolcheckarena\(p, a\);)116 L (1120)0(pooldumpl\(p\);)16(1188 })100 L (1121 })0(1189)100 L (1122 if\(p->logstack && \(p->flags & POOL_LOGGING\)\) p->logstack\(p\);)0(1190 void)100 L (1123 LOG\(p, "poolfree %p %p\\n", p, v\);)0(1191 poolcheck\(Pool *p\))100 L (1124 p->unlock\(p\);)0(1192 {)100 L (1125 })0(1193 p->lock\(p\);)100 L (1126)0(1194 poolcheckl\(p\);)100 L (1127 /*)0(1195 p->unlock\(p\);)100 L (1128 * Return the real size of a block, and let the user use it.)0(1196 })100 L (1129 */)0(1197)100 L (1130 ulong)0(1198 void)100 L (1131 poolmsize\(Pool *p, void *v\))0(1199 poolblockcheck\(Pool *p, void *v\))100 L (1132 {)0(1200 {)100 L (1133 Alloc *b;)0(1201 if\(v == nil\))100 L (1134 ulong dsize;)0(1202)100(return;)116 L (1135)0(1203)100 L (1136 p->lock\(p\);)0(1204 p->lock\(p\);)100 L (1137 paranoia {)0(1205 blockcheck\(p, D2B\(p, v\)\);)100 L (1138)0(poolcheckl\(p\);)16(1206 p->unlock\(p\);)100 L (1139 })0(1207 })100 L (1140 verbosity {)0(1208)100 L (1141)0(pooldumpl\(p\);)16(1209 static void)100 L (1142 })0(1210 pooldumpl\(Pool *p\))100 L (1143 if\(v == nil\) /* consistency with other braindead ANSI-ness */)0(1211 {)100 L (1144)0(dsize = 0;)16(1212 Arena *a;)100 L (1145 else {)0(1213)100 L (1146)0(b = D2B\(p, v\);)16(1214 p->print\(p, "pool %p %s\\n", p, p->name\);)100 L (1147)0(dsize = \(b->size&~\(p->quantum-1\)\) - sizeof\(Bhdr\) - sizeof\(Btail\);)16(1215 for\(a=p->arenalist; a; a=a->down\))100 L (1148)0(assert\(dsize >= getdsize\(b\)\);)16(1216)100(pooldumparena\(p, a\);)116 L (1149)0(blocksetdsize\(p, b, dsize\);)16(1217 })100 L (1150 })0(1218)100 L (1151 paranoia {)0(1219 void)100 L (1152)0(poolcheckl\(p\);)16(1220 pooldump\(Pool *p\))100 L (1153 })0(1221 {)100 L (1154 verbosity {)0(1222 p->lock\(p\);)100 L (1155)0(pooldumpl\(p\);)16(1223 pooldumpl\(p\);)100 L (1156 })0(1224 p->unlock\(p\);)100 L cleartomark showpage saveobj restore %%EndPage: 275 275 %%Page: 276 276 /saveobj save def mark 276 pagesetup ()l ()l (Oct 3 19:26 2005 sys/src/libc/port/pool.c Page 10)l ()l ()l (1225 })l (1226)l (1227 static void)l (1228 pooldumparena\(Pool *p, Arena *a\))l (1229 {)l (1230 Bhdr *b;)l (1231)l (1232 for\(b=a; b->magic != ARENATAIL_MAGIC; b=B2NB\(b\)\))l (1233)0(p->print\(p, "\(%p %.8lux %lud\)", b, b->magic, b->size\);)16 L (1234 p->print\(p, "\\n"\);)l (1235 })l (1236)l (1237 /*)l (1238 * mark the memory in such a way that we know who marked it)l (1239 * \(via the signature\) and we know where the marking started.)l (1240 */)l (1241 static void)l (1242 memmark\(void *v, int sig, ulong size\))l (1243 {)l (1244 uchar *p, *ep;)l (1245 ulong *lp, *elp;)l (1246 lp = v;)l (1247 elp = lp+size/4;)l (1248 while\(lp < elp\))l (1249)0(*lp++ = \(sig<<24\) ^ \(long\)v;)16 L (1250 p = \(uchar*\)lp;)l (1251 ep = \(uchar*\)v+size;)l (1252 while\(p