Plan 9 from Bell Labs 1990-12-23
28 files changed, 9216 insertions(+), 1 deletions(-) M gnot/mem.h A ss/boot.c A ss/boot.h A ss/clock.c A ss/crc_16.h A ss/dat.h A ss/devbit.c A ss/devcons.c A ss/devincon.c A ss/devkprof.c A ss/errno.h A ss/faultsparc.c A ss/fcall.h A ss/fns.h A ss/io.h A ss/l.s A ss/lib.h A ss/lock.c A ss/main.c A ss/malloc.h A ss/mem.h A ss/mmu.c A ss/screen.c A ss/stream.h A ss/trap.c A ss/u.h A ss/uart.c A ss/ureg.h
M gnot/mem.h => gnot/mem.h +1 -1
@@ 37,7 37,7 @@ #define CENABLE 0x01 /* * Magic registers * Magic registers (unused in current system) */ #define MACH A5 /* A5 is m-> */
A ss/boot.c => ss/boot.c +211 -0
@@ 0,0 1,211 @@ #include <u.h> #include <libc.h> #include <fcall.h> Fcall hdr; char buf[100]; char bootline[64]; char bootdevice; char bootserver[64]; void error(char*); void sendmsg(int, char*); main(int argc, char *argv[]) { int cfd, fd, n, fu, f, i; char buf[256]; int p[2]; open("#c/cons", OREAD); open("#c/cons", OWRITE); open("#c/cons", OWRITE); fd = open("#e/bootline", OREAD); if(fd >= 0){ read(fd, bootline, sizeof bootline); close(fd); } fd = open("#e/bootdevice", OREAD); if(fd >= 0){ read(fd, &bootdevice, 1); close(fd); } fd = open("#e/bootserver", OREAD); if(fd >= 0){ read(fd, bootserver, 64); close(fd); } else strcpy(bootserver, "nfs"); switch(bootdevice){ case 'A': /* * grab the rs232 line, * make it 9600 baud, * push the async protocol onto it, */ cfd = open("#c/rs232ctl", 2); if(cfd < 0) error("opening #c/rs232ctl"); sendmsg(cfd, "B9600"); sendmsg(cfd, "push async"); break; case 'a': /* * grab the rs232 line, * make it 19200 baud, * push the async protocol onto it, */ cfd = open("#c/rs232ctl", 2); if(cfd < 0) error("opening #c/rs232ctl"); sendmsg(cfd, "B19200"); sendmsg(cfd, "push async"); break; default: /* * grab the incon, */ cfd = open("#i/ctl", 2); if(cfd < 0) error("opening #i/ctl"); break; } /* * push the dk multiplexor onto the communications link, * and use line 1 as the signalling channel. */ sendmsg(cfd, "push dkmux"); sendmsg(cfd, "config 1 16 norestart"); /* * fork a process to hold the device channel open */ switch(fork()){ case -1: break; case 0: for(;;) sleep(60*1000); exit(0); default: close(cfd); break; } /* * open a datakit channel and call ken, leave the * incon ctl channel open */ for(i = 0; ; i++){ fd = open("#k/2/data", 2); if(fd < 0) error("opening #k/2/data"); cfd = open("#k/2/ctl", 2); if(cfd < 0) error("opening #k/2/ctl"); sprint(buf, "connect %s", bootserver); n = strlen(buf); if(write(cfd, buf, n) == n) break; if(i == 5) error("dialing"); print("error dialing, retrying ...\n"); close(fd); close(cfd); } print("connected to %s\n", bootserver); close(cfd); /* * talk to the file server */ print("nop..."); hdr.type = Tnop; hdr.tag = ~0; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n) error("write nop"); n = read(fd, buf, sizeof buf); if(n==2 && buf[0]=='O' && buf[1]=='K') n = read(fd, buf, sizeof buf); if(n <= 0) error("read nop"); if(convM2S(buf, &hdr, n) == 0) { print("n = %d; buf = %.2x %.2x %.2x %.2x\n", n, buf[0], buf[1], buf[2], buf[3]); error("format nop"); } if(hdr.type != Rnop) error("not Rnop"); print("session..."); hdr.type = Tsession; hdr.tag = ~0; n = convS2M(&hdr, buf); if(write(fd, buf, n) != n) error("write session"); n = read(fd, buf, sizeof buf); if(n <= 0) error("read session"); if(convM2S(buf, &hdr, n) == 0) error("format session"); if(hdr.type == Rerror){ print("error %s;", hdr.ename); error(hdr.ename); } if(hdr.type != Rsession) error("not Rsession"); print("post..."); sprint(buf, "#s/%s", "bootes"); f = create(buf, 1, 0666); if(f < 0) error("create"); sprint(buf, "%d", fd); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write"); close(f); sprint(buf, "#s/%s", "bootes"); f = create("#s/boot", 1, 0666); if(f < 0) error("create"); sprint(buf, "%d", fd); if(write(f, buf, strlen(buf)) != strlen(buf)) error("write"); close(f); print("mount..."); if(bind("/", "/", MREPL) < 0) error("bind"); if(mount(fd, "/", MAFTER|MCREATE, "", "") < 0) error("mount"); print("success\n"); if(strchr(bootline, ' ')) execl("/68020/init", "init", "-m", 0); else execl("/68020/init", "init", 0); error("/68020/init"); } void sendmsg(int fd, char *msg) { int n; n = strlen(msg); if(write(fd, msg, n) != n) error(msg); } void error(char *s) { char buf[64]; errstr(buf); fprint(2, "boot: %s: %s\n", s, buf); exits(0); }
A ss/boot.h => ss/boot.h +2662 -0
@@ 0,0 1,2662 @@ ulong bootcode[]={ 0x000000107, 0x000002504, 0x000000464, 0x0000001e4, 0x000000000, 0x000002020, 0x000000000, 0x000000000, 0x04feffff0, 0x02c7c0000, 0x0dffe486f, 0x000142f2f, 0x00014610c, 0x02f006100, 0x006884fef, 0x0001c4e75, 0x04feffee0, 0x042a7486e, 0x081166100, 0x0151e4878, 0x00001486e, 0x0811e6100, 0x015124878, 0x00001486e, 0x081266100, 0x0150642a7, 0x0486e812e, 0x0610014fc, 0x04a806d1e, 0x048780040, 0x0486e860a, 0x02f002f40, 0x001446100, 0x014ec2f2f, 0x001446100, 0x014c04fef, 0x0001042a7, 0x0486e813a, 0x0610014d0, 0x04a806d1e, 0x048780001, 0x0486e8002, 0x02f002f40, 0x0014c6100, 0x014c02f2f, 0x0014c6100, 0x014944fef, 0x0001042a7, 0x0486e8148, 0x0610014a4, 0x04a806d00, 0x005324878, 0x00040486e, 0x084ea2f00, 0x02f400154, 0x061001492, 0x02f2f0154, 0x061001466, 0x0102e8002, 0x049c04fef, 0x000407241, 0x0b2006700, 0x004cc7261, 0x0b2006700, 0x004884878, 0x00002486e, 0x081bd6100, 0x0145e2f40, 0x001244aaf, 0x00124508f, 0x06c0a486e, 0x081c46100, 0x00520588f, 0x0486e81d3, 0x02f2f0120, 0x0610004e2, 0x0486e81de, 0x02f2f0128, 0x0610004d6, 0x061001420, 0x04fef0010, 0x072ffb280, 0x06700043a, 0x04281b280, 0x067000424, 0x02f2f011c, 0x0610013f2, 0x0588f42af, 0x001084878, 0x00002486e, 0x081f46100, 0x013fe4a80, 0x042e72f40, 0x0012244df, 0x06c0a486e, 0x081fe6100, 0x004c0588f, 0x048780002, 0x0486e8210, 0x0610013dc, 0x04a8042e7, 0x02f40012e, 0x044df6c0a, 0x0486e8219, 0x06100049e, 0x0588f486e, 0x084ea486e, 0x0822a486f, 0x000206100, 0x0062a486f, 0x000246100, 0x0136c2f00, 0x02f400138, 0x0486f002c, 0x02f2f0144, 0x0610013ae, 0x0b0af0140, 0x06600036a, 0x0486e84ea, 0x0486e825a, 0x06100052c, 0x02f2f0150, 0x061001362, 0x0486e826b, 0x06100051c, 0x01d7c0032, 0x0858e3d7c, 0x0ffff8592, 0x0486f0044, 0x0486e858e, 0x06100137e, 0x02f002f40, 0x0015c486f, 0x000502f2f, 0x001646100, 0x01360b0af, 0x00164670a, 0x0486e8272, 0x061000416, 0x0588f4878, 0x00100486f, 0x0005c2f2f, 0x001706100, 0x013342400, 0x07002b082, 0x0660a0c2f, 0x0004f0064, 0x0670002ce, 0x04a8242e7, 0x02f420172, 0x044df6e0e, 0x0486e827c, 0x0610003de, 0x0242f0174, 0x0588f2f02, 0x0486e858e, 0x0486f006c, 0x061001ace, 0x04a806638, 0x0102f0073, 0x049c02f00, 0x0102f0076, 0x049c02f00, 0x0102f0079, 0x049c02f00, 0x0102f007c, 0x049c02f00, 0x02f2f018c, 0x0486e8285, 0x061000468, 0x0486e82a8, 0x061000392, 0x04fef001c, 0x00c2e0033, 0x0858e670a, 0x0486e82b3, 0x06100037e, 0x0588f486e, 0x082bc6100, 0x004421d7c, 0x00034858e, 0x03d7cffff, 0x08592486f, 0x00074486e, 0x0858e6100, 0x012a42f00, 0x02f40018c, 0x0486f0080, 0x02f2f0194, 0x061001286, 0x0b0af0194, 0x0670a486e, 0x082c76100, 0x0033c588f, 0x048780100, 0x0486f008c, 0x02f2f01a0, 0x06100125a, 0x02f4001a0, 0x04aaf01a0, 0x06e0a486e, 0x082d56100, 0x00318588f, 0x02f2f01a0, 0x0486e858e, 0x0486f009c, 0x061001a0a, 0x04a80660a, 0x0486e82e2, 0x0610002fa, 0x0588f0c2e, 0x00037858e, 0x06618486e, 0x08594486e, 0x082f16100, 0x003b2486e, 0x085946100, 0x002dc4fef, 0x0000c0c2e, 0x00035858e, 0x0670a486e, 0x082fb6100, 0x002c8588f, 0x0486e8308, 0x06100038c, 0x0486e8316, 0x0486e8310, 0x0486f00ac, 0x06100044c, 0x0487801b6, 0x048780001, 0x0486f00b8, 0x0610011b0, 0x04a8042e7, 0x02f4001c2, 0x044df6c0a, 0x0486e831d, 0x06100028a, 0x0588f2f2f, 0x001cc486e, 0x08324486f, 0x000c46100, 0x00416486f, 0x000c86100, 0x01158588f, 0x02f00486f, 0x000cc2f2f, 0x001d46100, 0x0119c2f00, 0x0486f00d8, 0x06100113e, 0x0588f221f, 0x0b280670a, 0x0486e8327, 0x061000246, 0x0588f2f2f, 0x001d86100, 0x01148486e, 0x08333486e, 0x0832d486f, 0x000e06100, 0x003ca4878, 0x001b64878, 0x00001486e, 0x0833a6100, 0x0112e4a80, 0x042e72f40, 0x001f644df, 0x06c0a486e, 0x083426100, 0x00208588f, 0x02f2f0200, 0x0486e8349, 0x0486f00f8, 0x061000394, 0x0486f00fc, 0x0610010d6, 0x0588f2f00, 0x0486f0100, 0x02f2f0208, 0x06100111a, 0x02f00486f, 0x0010c6100, 0x010bc588f, 0x0221fb280, 0x0670a486e, 0x0834c6100, 0x001c4588f, 0x02f2f020c, 0x0610010c6, 0x0486e8352, 0x061000280, 0x042a7486e, 0x0835d486e, 0x0835b6100, 0x010a44a80, 0x06c0a486e, 0x0835f6100, 0x00198588f, 0x0486e8367, 0x0486e8366, 0x048780006, 0x0486e8364, 0x02f2f023c, 0x0610010a2, 0x04a806c0a, 0x0486e8368, 0x061000172, 0x0588f486e, 0x0836e6100, 0x002364878, 0x00020486e, 0x0860a6100, 0x0100c4a80, 0x0672042a7, 0x0486e8388, 0x0486e8383, 0x0486e8377, 0x061000f56, 0x0486e839c, 0x06100013e, 0x04fef0268, 0x04e7542a7, 0x0486e8397, 0x0486e838b, 0x061000f3a, 0x0598f60e0, 0x00c2f004b, 0x000656600, 0x0fd2c4878, 0x00100486f, 0x000682f2f, 0x0017c6100, 0x0103c2400, 0x04fef000c, 0x06000fd12, 0x07005b0af, 0x00134660a, 0x0486e8235, 0x0610000f2, 0x0588f486e, 0x0823d6100, 0x001b62f2f, 0x001486100, 0x00fec2f2f, 0x001506100, 0x00fe452af, 0x001404fef, 0x000386000, 0x0fbee4879, 0x00000ea60, 0x061000ff8, 0x0588f60f2, 0x06000fbd8, 0x048780002, 0x0486e818b, 0x061000fd8, 0x02f400124, 0x04aaf0124, 0x06c0a486e, 0x081976100, 0x0009c588f, 0x0486e81ab, 0x02f2f0128, 0x0615e486e, 0x081b22f2f, 0x001306154, 0x04fef0018, 0x06000fb62, 0x048780002, 0x0486e815a, 0x061000f9c, 0x02f400124, 0x04aaf0124, 0x06c08486e, 0x081666160, 0x0588f486e, 0x0817a2f2f, 0x001286124, 0x0486e8180, 0x02f2f0130, 0x0611a4fef, 0x000186000, 0x0fb28486e, 0x08156486e, 0x084ea6100, 0x00f0e518f, 0x06000fada, 0x0598f2f2f, 0x0000c6100, 0x00f102f00, 0x02f400008, 0x02f2f0014, 0x02f2f0014, 0x061000f52, 0x0b0af0010, 0x067082f2f, 0x0001c6108, 0x0588f4fef, 0x000144e75, 0x04fefffc0, 0x048576100, 0x00f3a486f, 0x000042f2f, 0x0004c486e, 0x083a84878, 0x000026100, 0x0011a42a7, 0x061744fef, 0x000584e75, 0x0598f4281, 0x07021b081, 0x06f1e4ab6, 0x01d208466, 0x0660e2daf, 0x000081d20, 0x084667001, 0x0588f4e75, 0x052817021, 0x0b0816ee2, 0x04280588f, 0x04e75598f, 0x0206f0008, 0x042827021, 0x0b0826f18, 0x020362d20, 0x08466b088, 0x0660642b6, 0x02d208466, 0x052827021, 0x0b0826ee8, 0x0588f4e75, 0x04aaf0004, 0x0660642a7, 0x0610c588f, 0x0486e844e, 0x06104588f, 0x04e75518f, 0x072204a81, 0x06d222eb6, 0x01d208466, 0x04a976712, 0x02f410004, 0x042b61d20, 0x084664eb7, 0x00151222f, 0x000045381, 0x04a816cde, 0x02f2f000c, 0x061000e40, 0x04fef000c, 0x04e754fef, 0x0eff841ef, 0x0100c5888, 0x02f082f2f, 0x0101041ef, 0x00010d1fc, 0x000001000, 0x02f08486f, 0x000146100, 0x0011a2200, 0x041ef0018, 0x092882f01, 0x0486f001c, 0x048780001, 0x061000e36, 0x0240042e7, 0x02f40001e, 0x044df6c1a, 0x052ae8012, 0x0700ab0ae, 0x080126e0e, 0x048780001, 0x06100ff5a, 0x0242f0020, 0x0588f2002, 0x04fef1024, 0x04e754fef, 0x0eff841ef, 0x010105888, 0x02f082f2f, 0x0101441ef, 0x00010d1fc, 0x000001000, 0x02f08486f, 0x000146100, 0x000b22200, 0x041ef0018, 0x092882f01, 0x0486f001c, 0x02f2f1024, 0x061000dce, 0x0240042e7, 0x02f40001e, 0x044df6c1a, 0x052ae8012, 0x0700ab0ae, 0x080126e0e, 0x048780001, 0x06100fef2, 0x0242f0020, 0x0588f2002, 0x04fef1024, 0x04e75518f, 0x0226f000c, 0x02eae8016, 0x041ef0010, 0x058882f08, 0x02f2f0014, 0x048691000, 0x02f09614e, 0x02d6f0010, 0x0801690af, 0x0001c4fef, 0x000184e75, 0x0142f0007, 0x0c43c007f, 0x0701eb0ae, 0x0801a6e04, 0x070014e75, 0x0202e801a, 0x0120249c1, 0x01d801920, 0x0809652ae, 0x0801a1202, 0x049c11036, 0x019208096, 0x049c02daf, 0x000080d20, 0x0801e4280, 0x04e754fef, 0x0ffe4282f, 0x0002c246f, 0x000282f6e, 0x0800a0004, 0x02eae8006, 0x02d6f0020, 0x0800a202f, 0x000245380, 0x02d408006, 0x0101a49c0, 0x024007025, 0x0b0826768, 0x04a826628, 0x0202e800a, 0x0b0ae8006, 0x0650453ae, 0x0800a4236, 0x00161800a, 0x0202e800a, 0x02d6f0004, 0x0800a2d57, 0x080064fef, 0x0001c4e75, 0x0202e800a, 0x0b0ae8006, 0x0640a1d82, 0x00161800a, 0x052ae800a, 0x052ae8016, 0x0700ab082, 0x0660642ae, 0x0801660a4, 0x07009b082, 0x0669e7007, 0x0d0ae8016, 0x0c0bcffff, 0x0fff82d40, 0x08016608c, 0x0327cfc18, 0x02f7cffff, 0x0fc180014, 0x042af0010, 0x0101a49c0, 0x024002f4a, 0x000284a82, 0x06606538a, 0x06000ff6a, 0x0702eb082, 0x06610b2fc, 0x0fc186604, 0x0327c0000, 0x042af0014, 0x060d67031, 0x0b0826e46, 0x07039b082, 0x06d404283, 0x07030b082, 0x06e067039, 0x0b0826c10, 0x0b2fcfc18, 0x066042243, 0x060bc2f43, 0x0001460b6, 0x020032203, 0x0d281d281, 0x0d081d080, 0x0d08290bc, 0x000000030, 0x02600101a, 0x049c02400, 0x02f4a0028, 0x060c27030, 0x0b0826606, 0x0b2fcfc18, 0x066b4702a, 0x0b082661c, 0x024304990, 0x058842004, 0x0b2fcfc18, 0x066062242, 0x06000ff66, 0x02f420014, 0x06000ff5e, 0x0c4bc0000, 0x0007f2f02, 0x02f2f0014, 0x02f2f001c, 0x02f092f49, 0x000282f04, 0x02f440040, 0x010362920, 0x0809649c0, 0x020760d20, 0x0801e4e90, 0x0282f0040, 0x0246f003c, 0x0226f002c, 0x04a806c0e, 0x0448081af, 0x000244fef, 0x000146000, 0x0ff14d880, 0x020044fef, 0x000146000, 0x0fe84222f, 0x000080c81, 0x0fffffc18, 0x067087002, 0x0c0af0010, 0x066142f2f, 0x0000c2f01, 0x02f2f000c, 0x061000218, 0x04fef000c, 0x04e754481, 0x060e84fef, 0x0ffbc2a2f, 0x00058226f, 0x00048206f, 0x000502e2f, 0x000542c2f, 0x000042817, 0x0367c0000, 0x020052405, 0x0726fb081, 0x06d0001ce, 0x06e0001a6, 0x070082a00, 0x0347c0000, 0x07078c087, 0x07228b081, 0x06d000156, 0x06e00011c, 0x02c117004, 0x02f400014, 0x07020c087, 0x066064a86, 0x06d0000fe, 0x0422f0041, 0x0741c7040, 0x0c0876700, 0x000da2004, 0x04c450801, 0x026017030, 0x0d6807039, 0x0b0836c04, 0x07027d680, 0x022021f83, 0x029200024, 0x07002b082, 0x06f7c7004, 0x0c087671a, 0x00c370030, 0x029200024, 0x067107008, 0x0b0856638, 0x053821fbc, 0x000302920, 0x00024b4fc, 0x00000670a, 0x053821fbc, 0x0002d2920, 0x000242f07, 0x04878fc18, 0x02f2f0054, 0x048772920, 0x000306100, 0x0ff06202f, 0x000244fef, 0x000544e75, 0x07010b085, 0x066ccb6fc, 0x000006716, 0x053821fbc, 0x000582920, 0x000245382, 0x01fbc0030, 0x029200024, 0x060b05382, 0x01fbc0078, 0x029200024, 0x060e87040, 0x0c087673e, 0x020044c45, 0x008012800, 0x0b0fcfc18, 0x06708701e, 0x09088b082, 0x06f127040, 0x0c0876706, 0x04a846f00, 0x0ff5e4a86, 0x06f00ff58, 0x053827040, 0x0c0876600, 0x0ff2a2006, 0x04c450001, 0x026016000, 0x0ff262006, 0x04c450001, 0x02c0060c0, 0x04486347c, 0x000016000, 0x0fefc7230, 0x0b280671e, 0x07248b280, 0x0670c2c11, 0x070042f40, 0x000146000, 0x0fed82811, 0x070042f40, 0x000146000, 0x0fecc2c11, 0x034064286, 0x03c027004, 0x02f400014, 0x06000feba, 0x07208b280, 0x0672a7210, 0x0b2806712, 0x07220b280, 0x066c42c11, 0x070042f40, 0x000146000, 0x0fe9c2c11, 0x034063c02, 0x048c67004, 0x02f400014, 0x06000fe8a, 0x02c117004, 0x02f400014, 0x06000fe7e, 0x07275b280, 0x067107278, 0x0b2806600, 0x0fe547010, 0x02a006000, 0x0fe4c8ebc, 0x000000020, 0x0700a2a00, 0x06000fe3e, 0x07258b280, 0x0670a7264, 0x0b2806600, 0x0fe3060e8, 0x070012640, 0x060d4518f, 0x02f2f000c, 0x0610008fa, 0x0266f0010, 0x0246e8006, 0x0262f0014, 0x0226f0018, 0x0206e800a, 0x022000c83, 0x0fffffc18, 0x067064a83, 0x06c000084, 0x0101b49c0, 0x024006734, 0x0b2fcfc18, 0x06706b2fc, 0x000006fec, 0x0b1ca6406, 0x010c22d48, 0x0800a52ae, 0x08016700a, 0x0b0826642, 0x042ae8016, 0x0b2fcfc18, 0x067ce5389, 0x0101b49c0, 0x0240066cc, 0x00c83ffff, 0x0fc186704, 0x04a836d06, 0x04fef000c, 0x04e752403, 0x04482b282, 0x06cf2b1ca, 0x0640810fc, 0x000202d48, 0x0800a52ae, 0x080165281, 0x060e87009, 0x0b08266bc, 0x07007d0ae, 0x08016c0bc, 0x0fffffff8, 0x02d408016, 0x060aa2001, 0x0b2836c00, 0x0ff78b1ca, 0x0640810fc, 0x000202d48, 0x0800a52ae, 0x080165281, 0x060e4598f, 0x01ebc002a, 0x0202f0018, 0x01f400001, 0x01f7c002a, 0x00002422f, 0x000034878, 0x0fc1842a7, 0x0486f0008, 0x06100ff10, 0x042804fef, 0x000104e75, 0x0598f2037, 0x001610008, 0x01e80422f, 0x000014878, 0x0fc182f2f, 0x00010486f, 0x000086100, 0x0feea7004, 0x04fef0010, 0x04e752f2f, 0x000102f2f, 0x000102f2f, 0x000102f37, 0x001610010, 0x06100fc94, 0x070044fef, 0x000104e75, 0x0202e800a, 0x0b0ae8006, 0x0640c1dbc, 0x000250161, 0x0800a52ae, 0x0800a4280, 0x04e75202f, 0x000147268, 0x0b0816d2a, 0x06e0470f0, 0x04e75726c, 0x0b280670e, 0x07275b280, 0x067044280, 0x04e7570e0, 0x04e757008, 0x0c0af0010, 0x0670470c0, 0x04e7570f8, 0x04e757223, 0x0b2806714, 0x0722bb280, 0x0670a722d, 0x0b28066d6, 0x070fe4e75, 0x070ff4e75, 0x070fc4e75, 0x04fefff74, 0x0f2375400, 0x001610090, 0x0f22f7400, 0x0003442af, 0x00010f22f, 0x0543a0034, 0x0f2930016, 0x0f22f5400, 0x00034f200, 0x0001af22f, 0x074000034, 0x052af0010, 0x042977041, 0x0b0af00a0, 0x06e0a705a, 0x0b0af00a0, 0x06c0004d2, 0x042af0020, 0x0f23c4000, 0x000000000, 0x0f22f543a, 0x00034f281, 0x000e2486f, 0x00020f22f, 0x054000038, 0x0f2277400, 0x0610004b8, 0x0f22f4000, 0x0002cf23c, 0x054233fd3, 0x044135547, 0x05a32f22f, 0x06000002c, 0x0202f002c, 0x0e2802f40, 0x000284480, 0x02f006100, 0x005e0f22f, 0x054230044, 0x0f22f7400, 0x00034202f, 0x0002c90af, 0x000302f00, 0x0610005c6, 0x0f22f5423, 0x00038f200, 0x00100f23c, 0x040000000, 0x00001f200, 0x00838f295, 0x0003053af, 0x00034202f, 0x0003090af, 0x000342f00, 0x06100059a, 0x0f22f5423, 0x0003cf200, 0x00100f23c, 0x040000000, 0x00001f200, 0x00838588f, 0x0f292ffd4, 0x0f23c4000, 0x00000000a, 0x0f2000838, 0x04fef0014, 0x0f2920030, 0x052af0020, 0x0202f001c, 0x090af0020, 0x02f006100, 0x00558f22f, 0x054230028, 0x0f2000100, 0x0f23c4000, 0x00000000a, 0x0f2000838, 0x0588ff295, 0x0ffd40caf, 0x0fffffc18, 0x000986606, 0x070062f40, 0x000987067, 0x0b0af00a0, 0x066084aaf, 0x000986e00, 0x003b4701e, 0x0b0af0098, 0x06c06701e, 0x02f400098, 0x07802d8af, 0x000987066, 0x0b0af00a0, 0x06612202f, 0x00020d880, 0x06e0a7801, 0x0f23c4000, 0x000000000, 0x07020b084, 0x042e72f44, 0x0001644df, 0x06e187065, 0x0b0af00a0, 0x0660670ff, 0x02f400098, 0x070652f40, 0x000a06000, 0x0fe98f22f, 0x054000034, 0x0f22f7400, 0x0002c4aaf, 0x000206c26, 0x070ff90af, 0x000202f00, 0x0610004aa, 0x0282f0018, 0x0f2277400, 0x0f22f5400, 0x00038f21f, 0x05423f22f, 0x074000030, 0x0588f4283, 0x0b6846c6a, 0x0202f0020, 0x090832f43, 0x000184a80, 0x06d0002d0, 0x02f006100, 0x00474f22f, 0x054800030, 0x0f20000a0, 0x0f22f7400, 0x00028f227, 0x074806100, 0x00478262f, 0x00024282f, 0x00020f202, 0x06000f202, 0x04000f22f, 0x054230030, 0x0f22f5480, 0x00038f200, 0x000a8f22f, 0x074800038, 0x07030d082, 0x022031f80, 0x039200071, 0x05283b684, 0x04fef000c, 0x06d967605, 0x074ffd484, 0x04a826d38, 0x0200241f7, 0x029200065, 0x0101049c0, 0x0d0831080, 0x042830c37, 0x000392920, 0x000656f16, 0x0200241f7, 0x029200065, 0x0101049c0, 0x090bc0000, 0x0000a1080, 0x052835382, 0x04a826cc8, 0x07c014a83, 0x0670c1f7c, 0x000310064, 0x052af0020, 0x042864282, 0x04aaf0010, 0x067000200, 0x01fbc002d, 0x02920003c, 0x052824283, 0x07801d8af, 0x000982a2f, 0x000987067, 0x0b0af00a0, 0x0661470fb, 0x0b0af0020, 0x06e0c202f, 0x00020b0af, 0x000986f00, 0x001b27066, 0x0b0af00a0, 0x0661c262f, 0x000204483, 0x06c024283, 0x0b6af0098, 0x06f022604, 0x0202f0020, 0x0d8806c02, 0x042844a83, 0x06f222003, 0x0d084b085, 0x0660a1fbc, 0x0002e2920, 0x0003c5282, 0x01fbc0030, 0x02920003c, 0x052825383, 0x04a836ede, 0x04a846f28, 0x02003d084, 0x0b085660a, 0x01fbc002e, 0x02920003c, 0x052822202, 0x01fb76920, 0x000642920, 0x0003c5282, 0x052865384, 0x04a846ed8, 0x07004c0af, 0x0009c6700, 0x000e62003, 0x0d084b085, 0x0660a1fbc, 0x0002e2920, 0x0003c5282, 0x07065b0af, 0x000a0672a, 0x07067b0af, 0x000a06722, 0x042372920, 0x0003c2f2f, 0x0009c4878, 0x0fc182f2f, 0x0009c486f, 0x000486100, 0x0f87a7008, 0x04fef009c, 0x04e754a97, 0x06700008e, 0x01fbc0045, 0x02920003c, 0x05282262f, 0x000206c70, 0x01fbc002d, 0x02920003c, 0x052824483, 0x07064b083, 0x06e262003, 0x04c7c0801, 0x000000064, 0x0d0bc0000, 0x000302202, 0x01f802920, 0x0003c5282, 0x020034c7c, 0x008010000, 0x000642601, 0x020034c7c, 0x008010000, 0x0000ad0bc, 0x000000030, 0x022021f80, 0x02920003c, 0x052822003, 0x04c7c0801, 0x00000000a, 0x02001d0bc, 0x000000030, 0x01f802920, 0x0003c5282, 0x06000ff5a, 0x01fbc002b, 0x02920003c, 0x052826090, 0x01fbc0065, 0x02920003c, 0x052826000, 0x0ff727067, 0x0b0af00a0, 0x0670a7068, 0x0b0af00a0, 0x06600ff1e, 0x076ffd682, 0x04a836d0a, 0x00c370030, 0x03920003c, 0x067242803, 0x04a846d00, 0x0ff040c37, 0x0002e4920, 0x0003c660e, 0x02403b883, 0x06700fef2, 0x052826000, 0x0feec5384, 0x060de5383, 0x060ca76ff, 0x096af0020, 0x06c024283, 0x02a2f0098, 0x09aaf0020, 0x070682f40, 0x000a06000, 0x0fe367001, 0x0c0af009c, 0x06700fe04, 0x01fbc002b, 0x02920003c, 0x052826000, 0x0fdf6f22f, 0x05400002c, 0x0f23c4023, 0x00000000a, 0x0f22f7400, 0x0002cf227, 0x074006100, 0x001ac262f, 0x00020282f, 0x0001cf202, 0x06000f202, 0x04000f22f, 0x054800034, 0x0f20000a8, 0x0f22f7480, 0x00034598f, 0x06000fd36, 0x053af0098, 0x06000fc48, 0x070012e80, 0x07020d1af, 0x000a06000, 0x0fb24518f, 0x0f22f5500, 0x0000c206f, 0x00014f200, 0x0083af28e, 0x000104290, 0x0f23c4000, 0x000000000, 0x0508f4e75, 0x0f2177500, 0x020177214, 0x0e2a0c0bc, 0x0000007ff, 0x090bc0000, 0x003fe2080, 0x00297800f, 0x0ffff0097, 0x03fe00000, 0x0f2175400, 0x0508f4e75, 0x0518ff22f, 0x05500000c, 0x0242f0014, 0x0f200083a, 0x0f28e000e, 0x0f23c4000, 0x000000000, 0x0508f4e75, 0x0f2177500, 0x020177214, 0x0e2a0c0bc, 0x0000007ff, 0x0d4806e0c, 0x0f23c4000, 0x000000000, 0x0508f4e75, 0x00c820000, 0x007ff6d0c, 0x0f23c4000, 0x000000000, 0x0508f4e75, 0x00297800f, 0x0ffff2002, 0x07214e3a0, 0x08197f217, 0x05400508f, 0x04e754fef, 0x0fff4206f, 0x00018f22f, 0x055000010, 0x0f23c4000, 0x000000001, 0x0f2000838, 0x0f2950018, 0x0f23c4000, 0x000000000, 0x0f2107400, 0x0f2000800, 0x04fef000c, 0x04e75f22f, 0x075000004, 0x0242f0004, 0x07214e2a2, 0x0c4bc0000, 0x007ff94bc, 0x0000003fe, 0x07015b082, 0x06d2c203c, 0x0001fffff, 0x0e4a04680, 0x0c1af0004, 0x042af0008, 0x0f22f5400, 0x00004f210, 0x07400f200, 0x00800f22f, 0x054280004, 0x04fef000c, 0x04e757035, 0x0b0826de0, 0x072ead282, 0x0203c7fff, 0x0ffffe2a0, 0x04680c1af, 0x0000860cc, 0x0f22f4012, 0x000044e75, 0x041ef0004, 0x058882f08, 0x02f2f0008, 0x0610000fa, 0x0508f4e75, 0x0518ff22f, 0x0543a000c, 0x0f2930054, 0x0486f000c, 0x0f22f5400, 0x00010f200, 0x0001af227, 0x074006100, 0x0ff2af200, 0x00100f200, 0x0003af281, 0x00016f22f, 0x054000018, 0x0f23c4022, 0x000000001, 0x0f22f7400, 0x00018f22f, 0x054000018, 0x0f200001a, 0x0f22f7400, 0x00018f22f, 0x054000018, 0x04fef0014, 0x04e75486f, 0x0000cf22f, 0x054000010, 0x0f2277400, 0x06100fedc, 0x060e0f22f, 0x054800004, 0x0f200049a, 0x0f2277480, 0x06100ff7e, 0x0f200001a, 0x0508f4e75, 0x0206f0004, 0x0142f000b, 0x067121218, 0x0670ab202, 0x066f82008, 0x053804e75, 0x042804e75, 0x04a1866fc, 0x020085380, 0x04e75246f, 0x00004226f, 0x0000814d9, 0x066fc202f, 0x000044e75, 0x0226f0004, 0x04a19670c, 0x024494a19, 0x066fc93ca, 0x020094e75, 0x070004e75, 0x070024e40, 0x04e757008, 0x04e404e75, 0x070044e40, 0x04e757016, 0x04e404e75, 0x070074e40, 0x04e757009, 0x04e404e75, 0x0700d4e40, 0x04e75700e, 0x04e404e75, 0x0700f4e40, 0x04e757011, 0x04e404e75, 0x070144e40, 0x04e757001, 0x04e404e75, 0x0598f226f, 0x00008206f, 0x0000c10d1, 0x030290004, 0x010803029, 0x0000448c0, 0x0e0801140, 0x000015488, 0x0101149c0, 0x07232b001, 0x06d0005d4, 0x0724fb001, 0x06e0005cc, 0x030360b20, 0x083724efb, 0x000002008, 0x090af000c, 0x0588f4e75, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x060e03029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054884878, 0x000744869, 0x000062f08, 0x02f48000c, 0x061000ecc, 0x0206f000c, 0x07074d1c0, 0x04fef000c, 0x060ac3029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054884878, 0x000744869, 0x000062f08, 0x02f48000c, 0x061000e98, 0x0206f000c, 0x07074d1c0, 0x04fef000c, 0x06000ff78, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x06000ff60, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x06000ff48, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x06000ff30, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x06000ff18, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x06000ff00, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x02029000a, 0x010802029, 0x0000ae080, 0x011400001, 0x054886000, 0x0fed63029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054882029, 0x000061080, 0x020290006, 0x0e0801140, 0x000012029, 0x000067210, 0x0e2a01140, 0x000022029, 0x000067218, 0x0e2a01140, 0x000034228, 0x000044228, 0x000054228, 0x000064228, 0x000075088, 0x02029000a, 0x010802029, 0x0000ae080, 0x011400001, 0x054885288, 0x02f29000a, 0x02f29000e, 0x02f082f48, 0x0000c6100, 0x00d72206f, 0x0000c2037, 0x001620014, 0x0000ad1c0, 0x04fef000c, 0x06000fe4c, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x02029000a, 0x010802029, 0x0000ae080, 0x011400001, 0x054885288, 0x02f29000a, 0x02f29000e, 0x02f082f48, 0x0000c6100, 0x00d22206f, 0x0000c2037, 0x001620014, 0x0000ad1c0, 0x04fef000c, 0x06000fdfc, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x020290006, 0x010802029, 0x00006e080, 0x011400001, 0x020290006, 0x07210e2a0, 0x011400002, 0x020290006, 0x07218e2a0, 0x011400003, 0x042280004, 0x042280005, 0x042280006, 0x042280007, 0x050882029, 0x0000a1080, 0x02029000a, 0x0e0801140, 0x000015488, 0x06000fd98, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x02029000a, 0x010802029, 0x0000ae088, 0x011400001, 0x02029000a, 0x07210e2a8, 0x011400002, 0x02029000a, 0x07218e2a8, 0x011400003, 0x058882029, 0x0000e1080, 0x02029000e, 0x0e0881140, 0x000012029, 0x0000e7210, 0x0e2a81140, 0x000022029, 0x0000e7218, 0x0e2a81140, 0x000035888, 0x06000fd2c, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x04878001c, 0x04869000a, 0x02f082f48, 0x0000c6100, 0x00c16226f, 0x00014206f, 0x0000c701c, 0x0d1c02029, 0x000061080, 0x020290006, 0x0e0801140, 0x000012029, 0x000067210, 0x0e2a01140, 0x000022029, 0x000067218, 0x0e2a01140, 0x000035888, 0x010e90026, 0x04fef000c, 0x06000fcc4, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x02029000a, 0x010802029, 0x0000ae088, 0x011400001, 0x02029000a, 0x07210e2a8, 0x011400002, 0x02029000a, 0x07218e2a8, 0x011400003, 0x058882029, 0x0000e1080, 0x02029000e, 0x0e0881140, 0x000012029, 0x0000e7210, 0x0e2a81140, 0x000022029, 0x0000e7218, 0x0e2a81140, 0x000035888, 0x06000fc58, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x010e90026, 0x06000fc3c, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x02029000a, 0x010802029, 0x0000ae088, 0x011400001, 0x02029000a, 0x07210e2a8, 0x011400002, 0x02029000a, 0x07218e2a8, 0x011400003, 0x058882029, 0x0000e1080, 0x02029000e, 0x0e0881140, 0x000012029, 0x0000e7210, 0x0e2a81140, 0x000022029, 0x0000e7218, 0x0e2a81140, 0x000035888, 0x06000fbd0, 0x030290002, 0x010803029, 0x0000248c0, 0x0e0801140, 0x000015488, 0x04878001c, 0x04869000a, 0x02f082f48, 0x0000c6100, 0x00aba206f, 0x0000c701c, 0x0d1c04fef, 0x0000c6000, 0x0fb9a3029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054886000, 0x0fb823029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054883029, 0x000061080, 0x030290006, 0x048c0e080, 0x011400001, 0x054886000, 0x0fb563029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054882029, 0x0000a1080, 0x02029000a, 0x0e0881140, 0x000012029, 0x0000a7210, 0x0e2a81140, 0x000022029, 0x0000a7218, 0x0e2a81140, 0x000035888, 0x02029000e, 0x010802029, 0x0000ee088, 0x011400001, 0x02029000e, 0x07210e2a8, 0x011400002, 0x02029000e, 0x07218e2a8, 0x011400003, 0x058886000, 0x0faea3029, 0x000021080, 0x030290002, 0x048c0e080, 0x011400001, 0x054884878, 0x0001c4869, 0x000062f08, 0x02f48000c, 0x0610009d4, 0x0701cd1af, 0x0000c4878, 0x0001c4877, 0x001620018, 0x000222f2f, 0x000146100, 0x009ba701c, 0x0d1af0018, 0x04878001c, 0x048770162, 0x00024003e, 0x02f2f0020, 0x0610009a0, 0x0206f0024, 0x0701cd1c0, 0x04fef0024, 0x06000fa80, 0x06000fa7c, 0x030290008, 0x010803029, 0x0000848c0, 0x0e0801140, 0x000015488, 0x06000fa64, 0x048780040, 0x048690006, 0x02f082f48, 0x0000c6100, 0x00962206f, 0x0000c7040, 0x0d1c04fef, 0x0000c6000, 0x0fa421011, 0x049c02f00, 0x0486e83b6, 0x06100eb7c, 0x042804fef, 0x0000c4e75, 0x06000fa28, 0x06000fa24, 0x06000fa20, 0x06000fa1c, 0x0598f206f, 0x0000c4878, 0x0001c2f2f, 0x0000c2f08, 0x02f48000c, 0x061000914, 0x0701cd1af, 0x0000c4878, 0x0001c4877, 0x001620018, 0x0001c2f2f, 0x000146100, 0x008fa701c, 0x0d1af0018, 0x04878001c, 0x048770162, 0x000240038, 0x02f2f0020, 0x0610008e0, 0x0226f002c, 0x0206f0024, 0x0701cd1c0, 0x020290054, 0x010802029, 0x00054e088, 0x011400001, 0x020290054, 0x07210e2a8, 0x011400002, 0x020290054, 0x07218e2a8, 0x011400003, 0x058882029, 0x000581080, 0x020290058, 0x0e0881140, 0x000012029, 0x000587210, 0x0e2a81140, 0x000022029, 0x000587218, 0x0e2a81140, 0x000035888, 0x02029005c, 0x010802029, 0x0005ce088, 0x011400001, 0x02029005c, 0x07210e2a8, 0x011400002, 0x02029005c, 0x07218e2a8, 0x011400003, 0x058882029, 0x000601080, 0x020290060, 0x0e0801140, 0x000012029, 0x000607210, 0x0e2a01140, 0x000022029, 0x000607218, 0x0e2a01140, 0x000035888, 0x020290064, 0x010802029, 0x00064e080, 0x011400001, 0x020290064, 0x07210e2a0, 0x011400002, 0x020290064, 0x07218e2a0, 0x011400003, 0x058882029, 0x0006c1080, 0x02029006c, 0x0e0801140, 0x000012029, 0x0006c7210, 0x0e2a01140, 0x000022029, 0x0006c7218, 0x0e2a01140, 0x000034228, 0x000044228, 0x000054228, 0x000064228, 0x000075088, 0x030290070, 0x010803029, 0x0007048c0, 0x0e0801140, 0x000015488, 0x030290072, 0x010803029, 0x0007248c0, 0x0e0801140, 0x000015488, 0x0200890af, 0x000304fef, 0x000284e75, 0x0598f226f, 0x0000c206f, 0x000081298, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000045488, 0x0101149c0, 0x07232b001, 0x06d0005ae, 0x0724fb001, 0x06e0005a6, 0x030360b20, 0x083ae4efb, 0x00000202f, 0x00008d0af, 0x00010b088, 0x06608202f, 0x00010588f, 0x04e754280, 0x0588f4e75, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x060d04280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054884878, 0x000742f08, 0x02f480008, 0x048690006, 0x061000700, 0x0206f000c, 0x07074d1c0, 0x04fef000c, 0x0609c4280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054884878, 0x000742f08, 0x02f480008, 0x048690006, 0x0610006cc, 0x0206f000c, 0x07074d1c0, 0x04fef000c, 0x06000ff68, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000ff50, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000ff38, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000ff20, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000ff08, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000fef0, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080812340, 0x0000a5488, 0x06000fec4, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x000065088, 0x042801010, 0x042811228, 0x00001e181, 0x080812340, 0x0000a5488, 0x052882348, 0x0000e2029, 0x0000ad1c0, 0x06000fe60, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080812340, 0x0000a5488, 0x052882348, 0x0000e2029, 0x0000ad1c0, 0x06000fe28, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x000065088, 0x042801010, 0x042811228, 0x00001e181, 0x080812340, 0x0000a5488, 0x06000fdd0, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x0000a5888, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x0000e5888, 0x06000fd60, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x04878001c, 0x02f082f48, 0x000084869, 0x0000a6100, 0x0048e226f, 0x00018206f, 0x0000c701c, 0x0d1c04280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x023400006, 0x058881358, 0x000264fef, 0x0000c6000, 0x0fcf64280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340000a, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340000e, 0x058886000, 0x0fc864280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054881358, 0x000266000, 0x0fc6a4280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340000a, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340000e, 0x058886000, 0x0fbfa4280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400002, 0x054884878, 0x0001c2f08, 0x02f480008, 0x04869000a, 0x061000328, 0x0206f000c, 0x0701cd1c0, 0x04fef000c, 0x06000fbc4, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x06000fbac, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000065488, 0x06000fb80, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x0000a5888, 0x042801010, 0x042811228, 0x00001e181, 0x080814281, 0x012280002, 0x07410e5a1, 0x080814281, 0x012280003, 0x07418e5a1, 0x080812340, 0x0000e5888, 0x06000fb10, 0x042801010, 0x042811228, 0x00001e181, 0x080813340, 0x000025488, 0x04878001c, 0x02f082f48, 0x000084869, 0x000066100, 0x0023e701c, 0x0d1af000c, 0x04878001c, 0x02f2f0010, 0x048770162, 0x000200022, 0x061000224, 0x0701cd1af, 0x000184878, 0x0001c2f2f, 0x0001c4877, 0x00162002c, 0x0003e6100, 0x0020a206f, 0x00024701c, 0x0d1c04fef, 0x000246000, 0x0faa66000, 0x0faa24280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400008, 0x054886000, 0x0fa8a4878, 0x000402f08, 0x02f480008, 0x048690006, 0x0610001cc, 0x0206f000c, 0x07040d1c0, 0x04fef000c, 0x06000fa68, 0x0101149c0, 0x02f00486e, 0x083c46100, 0x0e3e64280, 0x04fef000c, 0x04e756000, 0x0fa4e6000, 0x0fa4a6000, 0x0fa466000, 0x0fa42598f, 0x0206f0008, 0x04878001c, 0x02f082f48, 0x000082f2f, 0x000146100, 0x0017e701c, 0x0d1af000c, 0x04878001c, 0x02f2f0010, 0x048770162, 0x00020001c, 0x061000164, 0x0701cd1af, 0x000184878, 0x0001c2f2f, 0x0001c4877, 0x00162002c, 0x000386100, 0x0014a226f, 0x00030206f, 0x00024701c, 0x0d1c04280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x023400054, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x023400058, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340005c, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x023400060, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x023400064, 0x058884280, 0x010104281, 0x012280001, 0x0e1818081, 0x042811228, 0x000027410, 0x0e5a18081, 0x042811228, 0x000037418, 0x0e5a18081, 0x02340006c, 0x050884280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400070, 0x054884280, 0x010104281, 0x012280001, 0x0e1818081, 0x033400072, 0x054882008, 0x090af002c, 0x04fef0028, 0x04e75518f, 0x0242f0010, 0x0222f000c, 0x0206f0014, 0x0b2826320, 0x02441d5c8, 0x02242d3c8, 0x05388b0fc, 0x000006d0a, 0x015215388, 0x0b0fc0000, 0x06cf62001, 0x0508f4e75, 0x024412242, 0x05388b0fc, 0x000006d0a, 0x014d95388, 0x0b0fc0000, 0x06cf62001, 0x0508f4e75, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000007, 0x000002cf2, 0x000002d7e, 0x000002a1a, 0x000002dd0, 0x000002d20, 0x000002d46, 0x000002d64, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000001, 0x000060000, 0x000000001, 0x000010000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x000030003, 0x000000000, 0x000000000, 0x000000000, 0x000000000, 0x002000000, 0x000000000, 0x000000004, 0x002030303, 0x001000000, 0x001000002, 0x000000005, 0x000010000, 0x002000000, 0x000000000, 0x023632f63, 0x06f6e7300, 0x023632f63, 0x06f6e7300, 0x023632f63, 0x06f6e7300, 0x023652f62, 0x06f6f746c, 0x0696e6500, 0x023652f62, 0x06f6f7464, 0x065766963, 0x065002365, 0x02f626f6f, 0x074736572, 0x076657200, 0x06e667300, 0x023632f72, 0x073323332, 0x063746c00, 0x06f70656e, 0x0696e6720, 0x023632f72, 0x073323332, 0x063746c00, 0x042393630, 0x030007075, 0x073682061, 0x073796e63, 0x00023632f, 0x072733233, 0x03263746c, 0x0006f7065, 0x06e696e67, 0x02023632f, 0x072733233, 0x03263746c, 0x000423139, 0x032303000, 0x070757368, 0x020617379, 0x06e630023, 0x0692f6374, 0x06c006f70, 0x0656e696e, 0x067202369, 0x02f63746c, 0x000707573, 0x06820646b, 0x06d757800, 0x0636f6e66, 0x069672031, 0x020313620, 0x06e6f7265, 0x073746172, 0x07400236b, 0x02f322f64, 0x061746100, 0x06f70656e, 0x0696e6720, 0x0236b2f32, 0x02f646174, 0x06100236b, 0x02f322f63, 0x0746c006f, 0x070656e69, 0x06e672023, 0x06b2f322f, 0x063746c00, 0x0636f6e6e, 0x065637420, 0x025730064, 0x069616c69, 0x06e670065, 0x072726f72, 0x020646961, 0x06c696e67, 0x02c207265, 0x074727969, 0x06e67202e, 0x02e2e0a00, 0x0636f6e6e, 0x065637465, 0x06420746f, 0x02025730a, 0x0006e6f70, 0x02e2e2e00, 0x077726974, 0x065206e6f, 0x070007265, 0x06164206e, 0x06f70006e, 0x0203d2025, 0x0643b2062, 0x07566203d, 0x020252e32, 0x07820252e, 0x032782025, 0x02e327820, 0x0252e3278, 0x00a00666f, 0x0726d6174, 0x0206e6f70, 0x0006e6f74, 0x020526e6f, 0x070007365, 0x07373696f, 0x06e2e2e2e, 0x000777269, 0x074652073, 0x065737369, 0x06f6e0072, 0x065616420, 0x073657373, 0x0696f6e00, 0x0666f726d, 0x061742073, 0x065737369, 0x06f6e0065, 0x072726f72, 0x02025733b, 0x0006e6f74, 0x020527365, 0x07373696f, 0x06e00706f, 0x073742e2e, 0x02e002373, 0x02f257300, 0x0626f6f74, 0x065730063, 0x072656174, 0x065002564, 0x000777269, 0x074650023, 0x0732f2573, 0x000626f6f, 0x074657300, 0x023732f62, 0x06f6f7400, 0x063726561, 0x074650025, 0x064007772, 0x069746500, 0x06d6f756e, 0x0742e2e2e, 0x0002f002f, 0x00062696e, 0x064002f00, 0x000006d6f, 0x0756e7400, 0x073756363, 0x06573730a, 0x0002f3638, 0x03032302f, 0x0696e6974, 0x000696e69, 0x074002d6d, 0x0002f3638, 0x03032302f, 0x0696e6974, 0x000696e69, 0x074002f36, 0x038303230, 0x02f696e69, 0x07400626f, 0x06f743a20, 0x025733a20, 0x025730a00, 0x062616420, 0x074797065, 0x03a202564, 0x00a006261, 0x064207479, 0x070653a20, 0x025640a00, 0x000000000, 0x005e405e0, 0x005dc05d8, 0x005c205a0, 0x005880584, 0x0051a04ae, 0x00482046a, 0x0043403c8, 0x003ac0340, 0x002d8026c, 0x0020801b8, 0x0012e0104, 0x000ec00d4, 0x000bc00a4, 0x0008c0056, 0x00022000c, 0x005be05ba, 0x005b605b2, 0x0059c057a, 0x00562055e, 0x004f40484, 0x004580440, 0x0040a039a, 0x0037e030e, 0x002a40234, 0x001dc01a4, 0x001400114, 0x000fc00e4, 0x000cc00b4, 0x0009c0066, 0x00032001c, 0x06e6f6e2d, 0x07a65726f, 0x020657869, 0x074207374, 0x061747573, 0x000000000, 0x00002988, 0x0, };
A ss/clock.c => ss/clock.c +42 -0
@@ 0,0 1,42 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" void delay(int ms) { ulong t, *p; int i; ms *= 1000; /* experimentally determined */ for(i=0; i<ms; i++) ; } void clock(Ureg *ur) { Proc *p; SYNCREG[1] = 0x5F; /* clear interrupt */ m->ticks++; p = m->proc; if(p){ p->pc = ur->pc; if (p->state==Running) p->time[p->insyscall]++; } checkalarms(); kbdclock(); mouseclock(); if((ur->sr&SPL(7)) == 0 && p && p->state==Running){ sched(); if(u->nnote && (ur->sr&SUPER)==0) notify(ur); } }
A ss/crc_16.h => ss/crc_16.h +35 -0
@@ 0,0 1,35 @@ /* * CRC 0120001 */ 0x0, 0xc0c1, 0xc181, 0x140, 0xc301, 0x3c0, 0x280, 0xc241, 0xc601, 0x6c0, 0x780, 0xc741, 0x500, 0xc5c1, 0xc481, 0x440, 0xcc01, 0xcc0, 0xd80, 0xcd41, 0xf00, 0xcfc1, 0xce81, 0xe40, 0xa00, 0xcac1, 0xcb81, 0xb40, 0xc901, 0x9c0, 0x880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941, 0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01, 0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0, 0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081, 0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240, 0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00, 0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0, 0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981, 0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41, 0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700, 0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0, 0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281, 0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441, 0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01, 0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1, 0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80, 0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541, 0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101, 0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0, 0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481, 0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40, 0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801, 0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1, 0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581, 0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341, 0x4100, 0x81c1, 0x8081, 0x4040
A ss/dat.h => ss/dat.h +613 -0
@@ 0,0 1,613 @@ typedef struct Alarm Alarm; typedef struct Block Block; typedef struct Blist Blist; typedef struct Chan Chan; typedef struct Conf Conf; typedef struct Dev Dev; typedef struct Dirtab Dirtab; typedef struct Env Env; typedef struct Envp Envp; typedef struct Envval Envval; typedef struct FFrame FFrame; typedef struct FPsave FPsave; typedef struct KMap KMap; typedef struct Label Label; typedef struct List List; typedef struct Lock Lock; typedef struct MMU MMU; typedef struct MMUCache MMUCache; typedef struct Mach Mach; typedef struct Mount Mount; typedef struct Mtab Mtab; typedef struct Note Note; typedef struct Orig Orig; typedef struct PTE PTE; typedef struct Page Page; typedef struct Pgrp Pgrp; typedef struct Proc Proc; typedef struct Qinfo Qinfo; typedef struct QLock QLock; typedef struct Queue Queue; typedef struct Ref Ref; typedef struct Rendez Rendez; typedef struct Seg Seg; typedef struct Service Service; typedef struct Stream Stream; typedef struct Ureg Ureg; typedef struct User User; typedef int Devgen(Chan*, Dirtab*, int, int, Dir*); struct List { void *next; }; struct Lock { char key; /* addr of sync bus semaphore */ ulong pc; }; struct Ref { Lock; int ref; }; struct QLock { Proc *head; /* next process waiting for object */ Proc *tail; /* last process waiting for object */ Lock use; /* to use object */ Lock queue; /* to access list */ }; struct Label { ulong sp; ulong pc; ushort sr; }; struct Alarm { List; Lock; int busy; long dt; /* may underflow in clock(); must be signed */ void (*f)(void*); void *arg; }; #define CHDIR 0x80000000L #define CHAPPEND 0x40000000L #define CHEXCL 0x20000000L struct Chan { QLock; /* general access */ Ref; union{ Chan *next; /* allocation */ ulong offset; /* in file */ }; ushort type; ushort dev; ushort mode; /* read/write */ ushort flag; Qid qid; Mount *mnt; /* mount point that derived Chan */ ulong mountid; int fid; /* for devmnt */ union { Stream *stream; /* for stream channels */ void *aux; Qid pgrpid; /* for #p/notepg */ }; Chan *mchan; /* channel to mounted server */ Qid mqid; /* qid of root of mount point */ }; struct FPsave { uchar type; uchar size; short reserved; char junk[212]; /* 68881: sizes 24, 180; 68882: 56, 212 */ char reg[3*4+8*12]; }; struct Conf { int nmach; /* processors */ int nproc; /* processes */ int npgrp; /* process groups */ ulong npage0; /* total physical pages of memory, bank 0 */ ulong npage1; /* total physical pages of memory, bank 1 */ ulong base0; /* base of bank 0 */ ulong base1; /* base of bank 1 */ ulong npage; /* total physical pages of memory */ ulong norig; /* origins */ ulong npte; /* contiguous page table entries */ ulong nmod; /* single (modifying) page table entries */ int nalarm; /* alarms */ int nchan; /* channels */ int nenv; /* distinct environment values */ int nenvchar; /* environment text storage */ int npgenv; /* environment files per process group */ int nmtab; /* mounted-upon channels per process group */ int nmount; /* mounts */ int nmntdev; /* mounted devices (devmnt.c) */ int nmntbuf; /* buffers for devmnt.c messages */ int nmnthdr; /* headers for devmnt.c messages */ int nstream; /* streams */ int nqueue; /* stream queues */ int nblock; /* stream blocks */ int nsrv; /* public servers (devsrv.c) */ int nbitmap; /* bitmap structs (devbit.c) */ int nbitbyte; /* bytes of bitmap data (devbit.c) */ int nfont; /* font structs (devbit.c) */ int nurp; /* max urp conversations */ int nasync; /* number of async protocol modules */ int npipe; /* number of pipes */ int nservice; /* number of services */ int nfsyschan; /* number of filsys open channels */ ulong maxialloc; /* maximum bytes used by ialloc */ int copymode; /* 0 is copy on write, 1 is copy on reference */ }; struct Dev { void (*reset)(void); void (*init)(void); Chan *(*attach)(char*); Chan *(*clone)(Chan*, Chan*); int (*walk)(Chan*, char*); void (*stat)(Chan*, char*); Chan *(*open)(Chan*, int); void (*create)(Chan*, char*, int, ulong); void (*close)(Chan*); long (*read)(Chan*, void*, long); long (*write)(Chan*, void*, long); void (*remove)(Chan*); void (*wstat)(Chan*, char*); }; struct Dirtab { char name[NAMELEN]; Qid qid; long length; long perm; }; struct Env { Lock; Envval *val; char name[NAMELEN]; Env *next; /* in chain of Envs for a pgrp */ int pgref; /* # pgrps pointing here */ }; struct Envp { Env *env; int chref; /* # chans from pgrp pointing here */ }; struct KMap { KMap *next; ulong pa; ulong va; }; #define VA(k) ((k)->va) struct Mach { int machno; /* physical id of processor */ ulong splpc; /* pc of last caller to splhi */ int mmask; /* 1<<m->machno */ ulong ticks; /* of the clock since boot time */ Proc *proc; /* current process on this processor */ Proc *lproc; /* last process on this processor */ Label sched; /* scheduler wakeup */ Lock alarmlock; /* access to alarm list */ void *alarm; /* alarms bound to this clock */ int fpstate; /* state of fp registers on machine */ void (*intr)(ulong, ulong); /* !!Compatability with mips!! */ ulong cause; /* ... */ ulong pc; /* ... */ int stack[1]; }; struct Mount { Ref; /* also used as a lock when playing lists */ short term; /* terminates list */ ulong mountid; Mount *next; Chan *c; /* channel replacing underlying channel */ }; struct Mtab { Chan *c; /* channel mounted upon */ Mount *mnt; /* what's mounted upon it */ }; enum{ NUser, /* note provided externally */ NExit, /* process should exit */ NDebug, /* process should hang */ }; struct Note { char msg[ERRLEN]; int flag; /* whether system posted it */ }; struct Orig { Lock; Orig *next; /* for allocation */ ushort nproc; /* processes using it */ ushort npage; /* sum of refs of pages in it */ ushort flag; ulong va; /* va of 0th pte */ ulong npte; /* #pte's in list */ PTE *pte; Chan *chan; /* channel deriving segment (if open) */ ushort type; /* of channel (which could be non-open) */ Qid qid; Chan *mchan; Qid mqid; ulong minca; /* base of region in chan */ ulong maxca; /* end of region in chan */ }; struct Page { Orig *o; /* origin of segment owning page */ ulong va; /* virtual address */ ulong pa; /* physical address */ ushort ref; Page *next; Page *prev; }; struct Pgrp { Ref; /* also used as a lock when mounting */ Pgrp *next; int index; /* index in pgrp table */ ulong pgrpid; char user[NAMELEN]; int nmtab; /* highest active mount table entry, +1 */ int nenv; /* highest active env table entry, +1 */ Lock debug; /* single access via devproc.c */ Mtab *mtab; Envp *etab; }; struct PTE { Proc *proc; /* process owning this PTE (0 in Orig) */ PTE *nextmod; /* next at this va */ PTE *nextva; /* next in this proc at higher va */ Page *page; }; struct Rendez { Lock; Proc *p; }; struct Seg { Proc *proc; /* process owning this segment */ Orig *o; /* root list of pte's */ ulong minva; /* va of 0th pte (not necessarily Seg->o->va) */ ulong maxva; /* va of last pte */ PTE *mod; /* list of modified pte's */ ulong pad[3]; /**/ }; struct Proc { Label sched; Mach *mach; /* machine running this proc */ char text[NAMELEN]; Proc *rnext; /* next process in run queue */ Proc *qnext; /* next process on queue for a QLock */ QLock *qlock; /* address of qlock being queued for DEBUG */ int state; int spin; /* spinning instead of unscheduled */ Page *upage; /* BUG: should be unlinked from page list */ Seg seg[NSEG]; ulong bssend; /* initial top of bss seg */ ulong pid; int nchild; QLock wait; /* exiting children to be waited for */ ulong waitmsg; Proc *child; Proc *parent; Pgrp *pgrp; ulong parentpid; ulong time[6]; /* User, Sys, Real; child U, S, R */ short exiting; short insyscall; int fpstate; Lock debug; /* to access debugging elements of User */ Rendez *r; /* rendezvous point slept on */ Rendez sleep; /* place for tsleep and syssleep */ int wokeup; /* whether sleep was interrupted */ ulong pc; /* DEBUG only */ int kp; /* true if a kernel process */ int pidonmach[1]; /* !!Compatability with mips!! */ }; struct MMU { ulong va; ulong pa; }; #define NMMU 16 struct MMUCache { ulong next; MMU mmu[NMMU]; }; #define NERR 15 #define NNOTE 5 #define NFD 100 struct User { Proc *p; int nerrlab; Label errlab[NERR]; char error[ERRLEN]; FPsave fpsave; /* address of this is known by vdb */ char elem[NAMELEN]; /* last name element from namec */ Chan *slash; Chan *dot; Chan *fd[NFD]; int maxfd; /* highest fd in use */ /* * Rest of structure controlled by devproc.c and friends. * lock(&p->debug) to modify. */ Note note[NNOTE]; short nnote; short notified; /* sysnoted is due */ int (*notify)(void*, char*); MMUCache mc; void *ureg; }; /* * operations available to a queue */ struct Qinfo { void (*iput)(Queue*, Block*); /* input routine */ void (*oput)(Queue*, Block*); /* output routine */ void (*open)(Queue*, Stream*); void (*close)(Queue*); char *name; void (*reset)(void); /* initialization */ Qinfo *next; }; /* * We reference lance buffers via descriptors kept in host memory */ struct Block { Block *next; uchar *rptr; /* first unconsumed byte */ uchar *wptr; /* first empty byte */ uchar *lim; /* 1 past the end of the buffer */ uchar *base; /* start of the buffer */ uchar flags; uchar type; }; /* flag bits */ #define S_DELIM 0x80 #define S_CLASS 0x07 /* type values */ #define M_DATA 0 #define M_CTL 1 #define M_HANGUP 2 /* * a list of blocks */ struct Blist { Lock; Block *first; /* first data block */ Block *last; /* last data block */ long len; /* length of list in bytes */ int nb; /* number of blocks in list */ }; /* * a queue of blocks */ struct Queue { Blist; int flag; Qinfo *info; /* line discipline definition */ Queue *other; /* opposite direction, same line discipline */ Queue *next; /* next queue in the stream */ void (*put)(Queue*, Block*); QLock rlock; /* mutex for processes sleeping at r */ Rendez r; /* standard place to wait for flow control */ Rendez *rp; /* where flow control wakeups go to */ void *ptr; /* private info for the queue */ }; #define QHUNGUP 0x1 /* flag bit meaning the stream has been hung up */ #define QINUSE 0x2 #define QHIWAT 0x4 /* queue has gone past the high water mark */ #define QDEBUG 0x8 /* * a stream head */ struct Stream { QLock; /* structure lock */ short inuse; /* number of processes in stream */ short opens; /* number of processes with stream open */ ushort hread; /* number of reads after hangup */ ushort type; /* correlation with Chan */ ushort dev; /* ... */ ushort id; /* ... */ QLock rdlock; /* read lock */ Queue *procq; /* write queue at process end */ Queue *devq; /* read queue at device end */ }; #define RD(q) ((q)->other < (q) ? (q->other) : q) #define WR(q) ((q)->other > (q) ? (q->other) : q) #define GLOBAL(a) (((ulong)(a)) & 0x80000000) #define STREAMTYPE(x) ((x)&0x1f) #define STREAMID(x) (((x)&~CHDIR)>>5) #define STREAMQID(i,t) (((i)<<5)|(t)) #define PUTNEXT(q,b) (*(q)->next->put)((q)->next, b) #define BLEN(b) ((b)->wptr - (b)->rptr) #define QFULL(q) ((q)->flag & QHIWAT) #define FLOWCTL(q) { if(QFULL(q->next)) flowctl(q); } /* * stream file qid's & high water mark */ enum { Shighqid = STREAMQID(1,0) - 1, Sdataqid = Shighqid, Sctlqid = Sdataqid-1, Slowqid = Sctlqid, Streamhi= (9*1024), /* byte count high water mark */ Streambhi= 32, /* block count high water mark */ }; #define NSTUB 32 struct Service { Ref; Service *next; QLock alock; int die; Chan *inc; Chan *outc; char name[NAMELEN]; }; #define PRINTSIZE 256 extern register Mach *m; extern register User *u; /* * Process states */ enum { Dead = 0, Moribund, Zombie, Ready, Scheding, Running, Queueing, MMUing, Exiting, Inwait, Wakeme, Broken, }; extern char *statename[]; /* * Chan flags */ #define COPEN 1 /* for i/o */ #define CMOUNT 2 /* is result of a mount/bind */ #define CCREATE 4 /* permits creation if CMOUNT */ #define CCEXEC 8 /* close on exec */ #define CFREE 16 /* not in use */ /* * Proc.time */ enum { TUser, TSys, TReal, TCUser, TCSys, TCReal, }; /* * floating point registers */ enum { FPinit, FPactive, FPdirty, }; /* * Memory management */ #define SSEG 0 #define TSEG 1 #define DSEG 2 #define BSEG 3 #define ESEG 4 /* used by exec to build new stack */ #define OWRPERM 0x01 /* write permission */ #define OPURE 0x02 /* original data mustn't be written */ #define OCACHED 0x04 /* cached; don't discard on exit */ /* * Access types in namec */ enum { Aaccess, /* as in access, stat */ Atodir, /* as in chdir */ Aopen, /* for i/o */ Amount, /* to be mounted upon */ Acreate, /* file is to be created */ }; #define NUMSIZE 12 /* size of formatted number */ #define MACHP(n) (n==0? &mach0 : *(Mach**)0) extern Conf conf; extern ulong initcode[]; extern Dev devtab[]; extern char devchar[]; extern FPsave initfp; extern Mach mach0; extern char user[NAMELEN]; extern char *errstrtab[]; extern void (*kprofp)(ulong); /* * parameters for sysproc.c */ #define AOUT_MAGIC A_MAGIC #define ENTRYOFFSET 0
A ss/devbit.c => ss/devbit.c +1153 -0
@@ 0,0 1,1153 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #include <libg.h> #include <gnot.h> extern GFont *defont; /* * Device (#b/bitblt) is exclusive use on open, so no locks are necessary * for i/o */ /* * Some fields in GBitmaps are overloaded: * ldepth = -1 means free. * base is next pointer when free. * Arena is a word containing N, followed by a pointer to its bitmap, * followed by N blocks. The bitmap pointer is zero if block is free. */ struct { Ref; GBitmap *map; /* arena */ GBitmap *free; /* free list */ ulong *words; /* storage */ ulong nwords; /* total in arena */ ulong *wfree; /* pointer to next free word */ GFont *font; /* arena; looked up linearly BUG */ int lastid; /* last allocated bitmap id */ int lastfid; /* last allocated font id */ int init; /* freshly opened; init message pending */ int rid; /* read bitmap id */ int rminy; /* read miny */ int rmaxy; /* read maxy */ }bit; #define FREE 0x80000000 void bitcompact(void); void bitfree(GBitmap*); extern GBitmap gscreen; struct{ /* * First three fields are known in l.s */ int dx; /* interrupt-time delta */ int dy; int track; /* update cursor on screen */ Mouse; int changed; /* mouse structure changed since last read */ int newbuttons; /* interrupt time access only */ Rendez r; }mouse; Cursor arrow = { {-1, -1}, {0xFF, 0xE0, 0xFF, 0xE0, 0xFF, 0xC0, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0xFF, 0xC0, 0xFF, 0xE0, 0xE7, 0xF0, 0xE3, 0xF8, 0xC1, 0xFC, 0x00, 0xFE, 0x00, 0x7F, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, }, {0x00, 0x00, 0x7F, 0xC0, 0x7F, 0x00, 0x7C, 0x00, 0x7E, 0x00, 0x7F, 0x00, 0x6F, 0x80, 0x67, 0xC0, 0x43, 0xE0, 0x41, 0xF0, 0x00, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1C, 0x00, 0x08, 0x00, 0x00, } }; struct{ Cursor; Lock; int visible; /* on screen */ Rectangle r; /* location */ }cursor; ulong setbits[16]; GBitmap set = { setbits, 0, 1, 0, {0, 0, 16, 16} }; ulong clrbits[16]; GBitmap clr = { clrbits, 0, 1, 0, {0, 0, 16, 16} }; ulong cursorbackbits[16]; GBitmap cursorback = { cursorbackbits, 0, 1, 0, {0, 0, 16, 16} }; void Cursortocursor(Cursor*); void cursoron(int); void cursoroff(int); int mousechanged(void*); enum{ Qdir, Qbitblt, Qmouse, Qscreen, }; Dirtab bitdir[]={ "bitblt", {Qbitblt}, 0, 0600, "mouse", {Qmouse}, 0, 0600, "screen", {Qscreen}, 0, 0400, }; #define NBIT (sizeof bitdir/sizeof(Dirtab)) #define NINFO 257 void bitreset(void) { int i; GBitmap *bp; bit.map = ialloc(conf.nbitmap * sizeof(GBitmap), 0); for(i=0,bp=bit.map; i<conf.nbitmap; i++,bp++){ bp->ldepth = -1; bp->base = (ulong*)(bp+1); } bp--; bp->base = 0; bit.map[0] = gscreen; /* bitmap 0 is screen */ bit.free = bit.map+1; bit.lastid = -1; bit.lastfid = -1; bit.words = ialloc(conf.nbitbyte, 0); bit.nwords = conf.nbitbyte/sizeof(ulong); bit.wfree = bit.words; bit.font = ialloc(conf.nfont * sizeof(GFont), 0); bit.font[0] = *defont; for(i=1; i<conf.nfont; i++) bit.font[i].info = ialloc((NINFO+1)*sizeof(Fontchar), 0); Cursortocursor(&arrow); } void bitinit(void) { lock(&bit); unlock(&bit); if(gscreen.ldepth > 1) panic("bitinit ldepth>1"); cursorback.ldepth = gscreen.ldepth; cursoron(1); } Chan* bitattach(char *spec) { return devattach('b', spec); } Chan* bitclone(Chan *c, Chan *nc) { nc = devclone(c, nc); if(c->qid.path != CHDIR) incref(&bit); } int bitwalk(Chan *c, char *name) { return devwalk(c, name, bitdir, NBIT, devgen); } void bitstat(Chan *c, char *db) { devstat(c, db, bitdir, NBIT, devgen); } Chan * bitopen(Chan *c, int omode) { if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eperm); }else if(c->qid.path == Qbitblt){ lock(&bit); if(bit.ref){ unlock(&bit); error(Einuse); } bit.lastid = -1; bit.lastfid = -1; bit.rid = -1; bit.init = 0; bit.ref = 1; Cursortocursor(&arrow); unlock(&bit); }else incref(&bit); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void bitcreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void bitremove(Chan *c) { error(Eperm); } void bitwstat(Chan *c, char *db) { error(Eperm); } void bitclose(Chan *c) { int i; GBitmap *bp; GFont *fp; if(c->qid.path!=CHDIR && (c->flag&COPEN)){ lock(&bit); if(--bit.ref == 0){ for(i=1,bp=&bit.map[1]; i<conf.nbitmap; i++,bp++) if(bp->ldepth >= 0) bitfree(bp); for(i=1,fp=&bit.font[1]; i<conf.nfont; i++,fp++) fp->bits = 0; } unlock(&bit); } } #define GSHORT(p) (((p)[0]<<0) | ((p)[1]<<8)) #define GLONG(p) ((GSHORT(p)<<0) | (GSHORT(p+2)<<16)) #define PSHORT(p, v) ((p)[0]=(v), (p)[1]=((v)>>8)) #define PLONG(p, v) (PSHORT(p, (v)), PSHORT(p+2, (v)>>16)) /* * These macros turn user-level (high bit at left) into internal (whatever) * bit order. On the gnot they're trivial. */ #define U2K(x) (x) #define K2U(x) (x) long bitread(Chan *c, void *va, long n) { uchar *p, *q; long miny, maxy, t, x, y; ulong l, nw, ws; int off, j; Fontchar *i; GBitmap *src; if(c->qid.path & CHDIR) return devdirread(c, va, n, bitdir, NBIT, devgen); switch(c->qid.path){ case Qmouse: /* * mouse: * 'm' 1 * buttons 1 * point 8 */ if(n < 10) error(Ebadblt); Again: while(mouse.changed == 0) sleep(&mouse.r, mousechanged, 0); lock(&cursor); if(mouse.changed == 0){ unlock(&cursor); goto Again; } p = va; p[0] = 'm'; p[1] = mouse.buttons; PLONG(p+2, mouse.xy.x); PLONG(p+6, mouse.xy.y); mouse.changed = 0; unlock(&cursor); n = 10; break; case Qbitblt: p = va; /* * Fuss about and figure out what to say. */ if(bit.init){ /* * init: * 'I' 1 * ldepth 1 * rectangle 16 * if count great enough, also * font info 3*12 * fontchars 6*(defont->n+1) */ if(n < 18) error(Ebadblt); p[0] = 'I'; p[1] = gscreen.ldepth; PLONG(p+2, gscreen.r.min.x); PLONG(p+6, gscreen.r.min.y); PLONG(p+10, gscreen.r.max.x); PLONG(p+14, gscreen.r.max.y); if(n >= 18+3*12+6*(defont->n+1)){ p += 18; sprint((char*)p, "%11d %11d %11d ", defont->n, defont->height, defont->ascent); p += 3*12; for(i=defont->info,j=0; j<=defont->n; j++,i++,p+=6){ PSHORT(p, i->x); p[2] = i->top; p[3] = i->bottom; p[4] = i->left; p[5] = i->width; } n = 18+3*12+6*(defont->n+1); }else n = 18; bit.init = 0; break; } if(bit.lastid > 0){ /* * allocate: * 'A' 1 * bitmap id 2 */ if(n < 3) error(Ebadblt); p[0] = 'A'; PSHORT(p+1, bit.lastid); bit.lastid = -1; n = 3; break; } if(bit.lastfid > 0){ /* * allocate font: * 'K' 1 * font id 2 */ if(n < 3) error(Ebadblt); p[0] = 'K'; PSHORT(p+1, bit.lastfid); bit.lastfid = -1; n = 3; break; } if(bit.rid >= 0){ /* * read * data bytewidth*(maxy-miny) */ src = &bit.map[bit.rid]; if(src->ldepth<0) error(Ebadbitmap); off = 0; if(bit.rid == 0) off = 1; miny = bit.rminy; maxy = bit.rmaxy; if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) error(Ebadblt); ws = 1<<(3-src->ldepth); /* pixels per byte */ /* set l to number of bytes of incoming data per scan line */ if(src->r.min.x >= 0) l = (src->r.max.x+ws-1)/ws - src->r.min.x/ws; else{ /* make positive before divide */ t = (-src->r.min.x)+ws-1; t = (t/ws)*ws; l = (t+src->r.max.x+ws-1)/ws; } if(n < l*(maxy-miny)) error(Ebadblt); if(off) cursoroff(1); n = 0; p = va; for(y=miny; y<maxy; y++){ q = (uchar*)gaddr(src, Pt(src->r.min.x, y)); q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws; for(x=0; x<l; x++) *p++ = K2U(*q++); n += l; } if(off) cursoron(1); bit.rid = -1; break; } error(Ebadblt); case Qscreen: if(c->offset==0){ if(n < 5*12) error(Eio); sprint(va, "%11d %11d %11d %11d %11d ", gscreen.ldepth, gscreen.r.min.x, gscreen.r.min.y, gscreen.r.max.x, gscreen.r.max.y); n = 5*12; break; } ws = 1<<(3-gscreen.ldepth); /* pixels per byte */ l = (gscreen.r.max.x+ws-1)/ws - gscreen.r.min.x/ws; t = c->offset-5*12; miny = t/l; maxy = (t+n)/l; if(miny >= gscreen.r.max.y) return 0; if(maxy >= gscreen.r.max.y) maxy = gscreen.r.max.y; n = 0; p = va; for(y=miny; y<maxy; y++){ q = (uchar*)gaddr(&gscreen, Pt(0, y)); for(x=0; x<l; x++) *p++ = K2U(*q++); n += l; } break; default: error(Egreg); } return n; } long bitwrite(Chan *c, void *va, long n) { uchar *p, *q; long m, v, miny, maxy, minx, maxx, t, x, y, tw, th; ulong l, nw, ws; int off, isoff, i; Point pt, pt1, pt2; Rectangle rect; Cursor curs; Fontchar *fcp; GBitmap *bp, *src, *dst; GFont *f; if(c->qid.path == CHDIR) error(Eisdir); if(c->qid.path != Qbitblt) error(Egreg); isoff = 0; if(waserror()){ if(isoff) cursoron(1); nexterror(); } p = va; m = n; while(m > 0) switch(*p){ default: pprint("bitblt request 0x%x\n", *p); error(Ebadblt); case 'a': /* * allocate: * 'a' 1 * ldepth 1 * Rectangle 16 * next read returns allocated bitmap id */ if(m < 18) error(Ebadblt); v = *(p+1); if(v!=0 && v!=1) /* BUG */ error(Ebadblt); ws = 1<<(5-v); /* pixels per word */ if(bit.free == 0) error(Enobitmap); rect.min.x = GLONG(p+2); rect.min.y = GLONG(p+6); rect.max.x = GLONG(p+10); rect.max.y = GLONG(p+14); if(rect.min.x >= 0) l = (rect.max.x+ws-1)/ws - rect.min.x/ws; else{ /* make positive before divide */ t = (-rect.min.x)+ws-1; t = (t/ws)*ws; l = (t+rect.max.x+ws-1)/ws; } nw = l*Dy(rect); if(bit.wfree+2+nw > bit.words+bit.nwords){ bitcompact(); if(bit.wfree+2+nw > bit.words+bit.nwords) error(Enobitstore); } bp = bit.free; bit.free = (GBitmap*)(bp->base); *bit.wfree++ = nw; *bit.wfree++ = (ulong)bp; bp->base = bit.wfree; memset(bp->base, 0, nw*sizeof(ulong)); bit.wfree += nw; bp->zero = l*rect.min.y; if(rect.min.x >= 0) bp->zero += rect.min.x/ws; else bp->zero -= (-rect.min.x+ws-1)/ws; bp->zero = -bp->zero; bp->width = l; bp->ldepth = v; bp->r = rect; bp->cache = 0; bit.lastid = bp-bit.map; m -= 18; p += 18; break; case 'b': /* * bitblt * 'b' 1 * dst id 2 * dst Point 8 * src id 2 * src Rectangle 16 * code 2 */ if(m < 31) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth < 0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; pt.x = GLONG(p+3); pt.y = GLONG(p+7); v = GSHORT(p+11); src = &bit.map[v]; if(v<0 || v>=conf.nbitmap || src->ldepth < 0) error(Ebadbitmap); if(v == 0) off = 1; rect.min.x = GLONG(p+13); rect.min.y = GLONG(p+17); rect.max.x = GLONG(p+21); rect.max.y = GLONG(p+25); v = GSHORT(p+29); if(off && !isoff){ cursoroff(1); isoff = 1; } balubitblt(dst, pt, src, rect, v); m -= 31; p += 31; break; case 'c': /* * cursorswitch * 'c' 1 * nothing more: return to arrow; else * Point 8 * clr 32 * set 32 */ if(m == 1){ if(!isoff){ cursoroff(1); isoff = 1; } Cursortocursor(&arrow); m -= 1; p += 1; break; } if(m < 73) error(Ebadblt); curs.offset.x = GLONG(p+1); curs.offset.y = GLONG(p+5); memcpy(curs.clr, p+9, 2*16); memcpy(curs.set, p+41, 2*16); if(!isoff){ cursoroff(1); isoff = 1; } Cursortocursor(&curs); m -= 73; p += 73; break; case 'f': /* * free * 'f' 1 * id 2 */ if(m < 3) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); bitfree(dst); m -= 3; p += 3; break; case 'g': /* * free font (free bitmap separately) * 'g' 1 * id 2 */ if(m < 3) error(Ebadblt); v = GSHORT(p+1); f = &bit.font[v]; if(v<0 || v>=conf.nfont || f->bits==0) error(Ebadfont); f->bits = 0; m -= 3; p += 3; break; case 'i': /* * init * * 'i' 1 */ bit.init = 1; m -= 1; p += 1; break; case 'k': /* * allocate font * 'k' 1 * n 2 * height 1 * ascent 1 * bitmap id 2 * fontchars 6*(n+1) * next read returns allocated font id */ if(m < 7) error(Ebadblt); v = GSHORT(p+1); if(v<0 || v>NINFO || m<7+6*(v+1)) /* BUG */ error(Ebadblt); for(i=1; i<conf.nfont; i++) if(bit.font[i].bits == 0) goto fontfound; error(Enofont); fontfound: f = &bit.font[i]; f->n = v; f->height = p[3]; f->ascent = p[4]; v = GSHORT(p+5); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); m -= 7; p += 7; fcp = f->info; for(i=0; i<=f->n; i++,fcp++){ fcp->x = GSHORT(p); fcp->top = p[2]; fcp->bottom = p[3]; fcp->left = p[4]; fcp->width = p[5]; fcp->top = p[2]; p += 6; m -= 6; } bit.lastfid = f - bit.font; f->bits = dst; break; case 'l': /* * line segment * * 'l' 1 * id 2 * pt1 8 * pt2 8 * value 1 * code 2 */ if(m < 22) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; pt1.x = GLONG(p+3); pt1.y = GLONG(p+7); pt2.x = GLONG(p+11); pt2.y = GLONG(p+15); t = p[19]; v = GSHORT(p+20); if(off && !isoff){ cursoroff(1); isoff = 1; } gsegment(dst, pt1, pt2, t, v); m -= 22; p += 22; break; case 'p': /* * point * * 'p' 1 * id 2 * pt 8 * value 1 * code 2 */ if(m < 14) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; pt1.x = GLONG(p+3); pt1.y = GLONG(p+7); t = p[11]; v = GSHORT(p+12); if(off && !isoff){ cursoroff(1); isoff = 1; } gpoint(dst, pt1, t, v); m -= 14; p += 14; break; case 'r': /* * read * 'r' 1 * src id 2 * miny 4 * maxy 4 */ if(m < 11) error(Ebadblt); v = GSHORT(p+1); src = &bit.map[v]; if(v<0 || v>=conf.nbitmap || src->ldepth<0) error(Ebadbitmap); miny = GLONG(p+3); maxy = GLONG(p+7); if(miny>maxy || miny<src->r.min.y || maxy>src->r.max.y) error(Ebadblt); bit.rid = v; bit.rminy = miny; bit.rmaxy = maxy; p += 11; m -= 11; break; case 's': /* * string * 's' 1 * id 2 * pt 8 * font id 2 * code 2 * string n (null terminated) */ if(m < 16) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; pt.x = GLONG(p+3); pt.y = GLONG(p+7); v = GSHORT(p+11); f = &bit.font[v]; if(v<0 || v>=conf.nfont || f->bits==0 || f->bits->ldepth<0) error(Ebadblt); v = GSHORT(p+13); p += 15; m -= 15; q = memchr(p, 0, m); if(q == 0) error(Ebadblt); if(off && !isoff){ cursoroff(1); isoff = 1; } gstring(dst, pt, f, (char*)p, v); q++; m -= q-p; p = q; break; case 't': /* * texture * 't' 1 * dst id 2 * Rectangle 16 * src id 2 * fcode 2 */ if(m < 23) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; rect.min.x = GLONG(p+3); rect.min.y = GLONG(p+7); rect.max.x = GLONG(p+11); rect.max.y = GLONG(p+15); v = GSHORT(p+19); src = &bit.map[v]; if(v<0 || v>=conf.nbitmap || src->ldepth<0) error(Ebadbitmap); v = GSHORT(p+21); x = src->r.min.x; y = src->r.min.y; tw = src->r.max.x - x; th = src->r.max.y - y; if(x==0 && y==0 && 16%tw == 0 && 16%th == 0){ GTexture t; if(tw==16 && th==16) for(y=0; y<16; y++) t.bits[y] = src->base[y]>>16; else for(y=0; y<16; y++){ l = src->base[y%th] >> (32-tw); for(i=16/tw, ws=l; i > 1; i--) ws = (ws<<tw) | l; t.bits[y] = ws; } if(off && !isoff){ cursoroff(1); isoff = 1; } gtexture(dst, rect, &t, v); }else{ GBitmap d; d = *dst; rect = rcanon(rect); if(rectclip(&d.r, rect)==0) return; /* * Find x, maxx such that * x <= rect.min.x < x+tw, * maxx-tw < rect.max.x <= maxx * and x, maxx are integral multiples of tw * away from src->r.min.x * Similarly for y, maxy */ if(x > rect.min.x) x -= ((x-rect.min.x+tw-1)/tw)*tw; else if(x+tw <= rect.min.x) x += ((rect.min.x-x)/tw)*tw; if(y > rect.min.y) y -= ((y-rect.min.y+th-1)/th)*th; else if(y+tw <= rect.min.y) y += ((rect.min.y-y)/th)*th; maxx = x+tw; if(maxx < rect.max.x) maxx += ((rect.max.x-maxx+tw-1)/tw)*tw; maxy = y+th; if(maxy < rect.max.y) maxy += ((rect.max.y-maxy+th-1)/th)*th; minx = x; if(off && !isoff){ cursoroff(1); isoff = 1; } for( ; y<maxy; y+=th) for(x=minx; x<maxx; x+=tw) gbitblt(&d, Pt(x,y), src, src->r, v); } m -= 23; p += 23; break; case 'w': /* * write * 'w' 1 * dst id 2 * miny 4 * maxy 4 * data bytewidth*(maxy-miny) */ if(m < 11) error(Ebadblt); v = GSHORT(p+1); dst = &bit.map[v]; if(v<0 || v>=conf.nbitmap || dst->ldepth<0) error(Ebadbitmap); off = 0; if(v == 0) off = 1; miny = GLONG(p+3); maxy = GLONG(p+7); if(miny>maxy || miny<dst->r.min.y || maxy>dst->r.max.y) error(Ebadblt); ws = 1<<(3-dst->ldepth); /* pixels per byte */ /* set l to number of bytes of incoming data per scan line */ if(dst->r.min.x >= 0) l = (dst->r.max.x+ws-1)/ws - dst->r.min.x/ws; else{ /* make positive before divide */ t = (-dst->r.min.x)+ws-1; t = (t/ws)*ws; l = (t+dst->r.max.x+ws-1)/ws; } p += 11; m -= 11; if(m < l*(maxy-miny)) error(Ebadblt); if(off && !isoff){ cursoroff(1); isoff = 1; } for(y=miny; y<maxy; y++){ q = (uchar*)gaddr(dst, Pt(dst->r.min.x, y)); q += (dst->r.min.x&((sizeof(ulong))*ws-1))/ws; for(x=0; x<l; x++) *q++ = U2K(*p++); m -= l; } break; case 'x': /* * cursorset * * 'x' 1 * pt 8 */ if(m < 9) error(Ebadblt); pt1.x = GLONG(p+1); pt1.y = GLONG(p+5); mouse.xy = pt1; mouse.track = 1; mouseclock(); m -= 9; p += 9; break; } if(isoff) cursoron(1); return n; } void bitfree(GBitmap *bp) { bp->base[-1] = 0; bp->ldepth = -1; bp->base = (ulong*)bit.free; bit.free = bp; } QLock bitlock; GBitmap * id2bit(int k) { GBitmap *bp; bp = &bit.map[k]; if(k<0 || k>=conf.nbitmap || bp->ldepth < 0) error(Ebadbitmap); return bp; } void bitcompact(void) { ulong *p1, *p2; qlock(&bitlock); p1 = p2 = bit.words; while(p2 < bit.wfree){ if(p2[1] == 0){ p2 += 2 + p2[0]; continue; } if(p1 != p2){ memcpy(p1, p2, (2+p2[0])*sizeof(ulong)); ((GBitmap*)p1[1])->base = p1+2; } p2 += 2 + p1[0]; p1 += 2 + p1[0]; } bit.wfree = p1; qunlock(&bitlock); } void Cursortocursor(Cursor *c) { int i; lock(&cursor); memcpy(&cursor, c, sizeof(Cursor)); for(i=0; i<16; i++){ setbits[i] = (c->set[2*i]<<24) + (c->set[2*i+1]<<16); clrbits[i] = (c->clr[2*i]<<24) + (c->clr[2*i+1]<<16); } unlock(&cursor); } void cursoron(int dolock) { if(dolock) lock(&cursor); if(cursor.visible++ == 0){ cursor.r.min = mouse.xy; cursor.r.max = add(mouse.xy, Pt(16, 16)); cursor.r = raddp(cursor.r, cursor.offset); gbitblt(&cursorback, Pt(0, 0), &gscreen, cursor.r, S); gbitblt(&gscreen, add(mouse.xy, cursor.offset), &clr, Rect(0, 0, 16, 16), D&~S); gbitblt(&gscreen, add(mouse.xy, cursor.offset), &set, Rect(0, 0, 16, 16), S|D); } if(dolock) unlock(&cursor); } void cursoroff(int dolock) { if(dolock) lock(&cursor); if(--cursor.visible == 0) gbitblt(&gscreen, cursor.r.min, &cursorback, Rect(0, 0, 16, 16), S); if(dolock) unlock(&cursor); } void mousebuttons(int b) /* called spl5 */ { /* * It is possible if you click very fast and get bad luck * you could miss a button click (down up). Doesn't seem * likely or important enough to worry about. */ mouse.newbuttons = b; mouse.track = 1; /* aggressive but o.k. */ mouseclock(); } void mouseclock(void) /* called spl6 */ { int x, y; if(mouse.track && canlock(&cursor)){ x = mouse.xy.x + mouse.dx; if(x < gscreen.r.min.x) x = gscreen.r.min.x; if(x >= gscreen.r.max.x) x = gscreen.r.max.x; y = mouse.xy.y + mouse.dy; if(y < gscreen.r.min.y) y = gscreen.r.min.y; if(y >= gscreen.r.max.y) y = gscreen.r.max.y; cursoroff(0); mouse.xy = Pt(x, y); cursoron(0); mouse.dx = 0; mouse.dy = 0; mouse.track = 0; mouse.buttons = mouse.newbuttons; mouse.changed = 1; unlock(&cursor); wakeup(&mouse.r); } } int mousechanged(void *m) { return mouse.changed; }
A ss/devcons.c => ss/devcons.c +1021 -0
@@ 0,0 1,1021 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "errno.h" #include "devtab.h" typedef struct IOQ IOQ; static struct { Lock; int printing; int c; }printq; #define NQ 2048 struct IOQ{ union{ Lock; QLock; }; uchar buf[NQ]; uchar *in; uchar *out; int state; Rendez r; }; IOQ lineq; struct{ IOQ; Lock put; }klogq; struct{ IOQ; /* qlock to getc; interrupt putc's */ int c; int repeat; int count; }kbdq; Ref raw; /* whether kbd i/o is raw (rcons is open) */ /* * rs232 stream module */ typedef struct Rs232 Rs232; typedef struct IOBQ IOBQ; #define NBQ 6 struct IOBQ{ Block *bp[NBQ]; int w; int r; int f; }; #define NEXT(x) ((x+1)%NBQ) struct Rs232{ QLock; QLock outlock; IOQ in; IOBQ out; int kstarted; /* true if kproc started */ Queue *wq; Alarm *a; /* alarm for waking the rs232 kernel process */ int started; int delay; /* time between character input and waking kproc */ Rendez r; }; Rs232 rs232; static void rs232output(Rs232*); static void rs232input(Rs232*); static void rs232timer(Alarm*); static void rs232kproc(void*); static void rs232open(Queue*, Stream*); static void rs232close(Queue*); static void rs232oput(Queue*, Block*); Qinfo rs232info = { nullput, rs232oput, rs232open, rs232close, "rs232" }; void printinit(void) { lock(&printq); /* allocate lock */ unlock(&printq); kbdq.in = kbdq.buf; kbdq.out = kbdq.buf; klogq.in = klogq.buf; klogq.out = klogq.buf; lineq.in = lineq.buf; lineq.out = lineq.buf; rs232.in.in = rs232.in.buf; rs232.in.out = rs232.in.buf; qlock(&kbdq); /* allocate qlock */ qunlock(&kbdq); lock(&lineq); /* allocate lock */ unlock(&lineq); lock(&klogq); /* allocate lock */ unlock(&klogq); lock(&klogq.put); /* allocate lock */ unlock(&klogq.put); screeninit(); } /* * Print a string on the console. */ void putstrn(char *str, long n) { int s; s = splhi(); lock(&printq); printq.printing = 1; while(--n >= 0) screenputc(*str++); printq.printing = 0; unlock(&printq); splx(s); } int cangetc(void *arg) { IOQ *q = (IOQ *)arg; int n = q->in - q->out; if (n < 0) n += sizeof(q->buf); return n; } int canputc(void *arg) { IOQ *q = (IOQ *)arg; return sizeof(q->buf)-cangetc(q)-1; } int isbrkc(void *arg) { IOQ *q = (IOQ *)arg; uchar *p; for(p=q->out; p!=q->in; ){ if(raw.ref) return 1; if(*p==0x04 || *p=='\n') return 1; p++; if(p >= q->buf+sizeof(q->buf)) p = q->buf; } return 0; } int getc(IOQ *q) { int c; if(q->in == q->out) return -1; c = *q->out++; if(q->out == q->buf+sizeof(q->buf)) q->out = q->buf; return c; } int putc(IOQ *q, int c) { uchar *nextin; if(q->in >= &q->buf[sizeof(q->buf)-1]) nextin = q->buf; else nextin = q->in+1; if(nextin == q->out) return -1; *q->in = c; q->in = nextin; return 0; } void putstrk(char *str, long n) { int s; s = splhi(); lock(&klogq.put); while(--n >= 0){ *klogq.in++ = *str++; if(klogq.in == klogq.buf+sizeof(klogq.buf)) klogq.in = klogq.buf; } unlock(&klogq.put); splx(s); wakeup(&klogq.r); } int sprint(char *s, char *fmt, ...) { return doprint(s, s+PRINTSIZE, fmt, (&fmt+1)) - s; } int print(char *fmt, ...) { char buf[PRINTSIZE]; int n; n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; putstrn(buf, n); return n; } int kprint(char *fmt, ...) { char buf[PRINTSIZE]; int n; n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; putstrk(buf, n); return n; } void panic(char *fmt, ...) { char buf[PRINTSIZE]; int n; strcpy(buf, "panic: "); n = doprint(buf+7, buf+sizeof(buf), fmt, (&fmt+1)) - buf; buf[n] = '\n'; putstrn(buf, n+1); exit(); } int pprint(char *fmt, ...) { char buf[2*PRINTSIZE]; Chan *c; int n; c = u->fd[2]; if(c==0 || (c->mode!=OWRITE && c->mode!=ORDWR)) return 0; n = sprint(buf, "%s %d: ", u->p->text, u->p->pid); n = doprint(buf+n, buf+sizeof(buf), fmt, (&fmt+1)) - buf; qlock(c); if(waserror()){ qunlock(c); return 0; } (*devtab[c->type].write)(c, buf, n); c->offset += n; qunlock(c); poperror(); return n; } void prflush(void) { while(printq.printing) delay(100); } void echo(int c) { char ch; static int ctrlt; /* * ^t hack BUG */ if(ctrlt == 2){ ctrlt = 0; switch(c){ case 0x14: break; /* pass it on */ case 'p': DEBUG(); return; case 'q': dumpqueues(); return; case 'm': mntdump(); return; case 'i': incontoggle(); return; } }else if(c == 0x14){ ctrlt++; return; } ctrlt = 0; if(raw.ref) return; if(c == 0x15) putstrn("^U\n", 3); else{ ch = c; putstrn(&ch, 1); } } /* * Put character into read queue at interrupt time. * Always called splhi from proc 0. */ void kbdchar(int c) { if(kbdq.repeat == 1){ kbdq.c = c; kbdq.count = 0; kbdq.repeat = 2; } echo(c); *kbdq.in++ = c; if(kbdq.in == kbdq.buf+sizeof(kbdq.buf)) kbdq.in = kbdq.buf; if(raw.ref || c=='\n' || c==0x04) wakeup(&kbdq.r); } void kbdrepeat(int rep) { if(rep) kbdq.repeat = 1; else kbdq.repeat = 0; } void kbdclock(void) { if(kbdq.repeat==2 && (++kbdq.count&1)) kbdchar(kbdq.c); } int consactive(void) { return printq.printing; } /* * I/O interface */ enum{ Qdir, Qcons, Qcputime, Qnull, Qpgrpid, Qpid, Qppid, Qrcons, Qtime, Quser, Qklog, Qmsec, Qclock, Qrs232ctl = STREAMQID(1, Sctlqid), Qrs232 = STREAMQID(1, Sdataqid), }; Dirtab consdir[]={ "cons", {Qcons}, 0, 0600, "cputime", {Qcputime}, 6*NUMSIZE, 0600, "null", {Qnull}, 0, 0600, "pgrpid", {Qpgrpid}, NUMSIZE, 0600, "pid", {Qpid}, NUMSIZE, 0600, "ppid", {Qppid}, NUMSIZE, 0600, "rcons", {Qrcons}, 0, 0600, "rs232", {Qrs232}, 0, 0600, "rs232ctl", {Qrs232ctl}, 0, 0600, "time", {Qtime}, NUMSIZE, 0600, "user", {Quser}, 0, 0600, "klog", {Qklog}, 0, 0400, "msec", {Qmsec}, NUMSIZE, 0400, "clock", {Qclock}, 2*NUMSIZE, 0400, }; #define NCONS (sizeof consdir/sizeof(Dirtab)) static int consgen(Chan *c, Dirtab *tab, int ntab, int i, Dir *dp) { if(tab==0 || i>=ntab) return -1; tab += i; devdir(c, tab->qid, tab->name, tab->length, tab->perm, dp); return 1; } ulong boottime; /* seconds since epoch at boot */ long seconds(void) { return boottime + TK2SEC(MACHP(0)->ticks); } int readnum(ulong off, char *buf, ulong n, ulong val, int size) { char tmp[64]; Op op = (Op){ tmp, tmp+sizeof(tmp), &val, size-1, 0, FUNSIGN|FLONG }; numbconv(&op, 10); tmp[size-1] = ' '; if(off >= size) return 0; if(off+n > size) n = size-off; memcpy(buf, tmp+off, n); return n; } int readstr(ulong off, char *buf, ulong n, char *str) { int size; size = strlen(str); if(off >= size) return 0; if(off+n > size) n = size-off; memcpy(buf, str+off, n); return n; } void consreset(void) { } void consinit(void) { } Chan* consattach(char *spec) { return devattach('c', spec); } Chan* consclone(Chan *c, Chan *nc) { return devclone(c, nc); } int conswalk(Chan *c, char *name) { return devwalk(c, name, consdir, NCONS, consgen); } void consstat(Chan *c, char *dp) { switch(c->qid.path){ case Qrs232: streamstat(c, dp, "rs232"); break; default: devstat(c, dp, consdir, NCONS, consgen); break; } } Chan* consopen(Chan *c, int omode) { int ch; switch(c->qid.path){ case Quser: if(omode==(OWRITE|OTRUNC)){ /* truncate? */ if(strcmp(u->p->pgrp->user, "bootes") == 0) /* BUG */ u->p->pgrp->user[0] = 0; else error(Eperm); } break; case Qrcons: if(incref(&raw) == 1){ lock(&lineq); while((ch=getc(&kbdq)) != -1){ *lineq.in++ = ch; if(lineq.in == lineq.buf+sizeof(lineq.buf)) lineq.in = lineq.buf; } unlock(&lineq); } break; case Qrs232: case Qrs232ctl: streamopen(c, &rs232info); break; } return devopen(c, omode, consdir, NCONS, consgen); } void conscreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void consclose(Chan *c) { if(c->qid.path==Qrcons && (c->flag&COPEN)) decref(&raw); if(c->stream) streamclose(c); } long consread(Chan *c, void *buf, long n) { int ch, i, j, k; ulong l; uchar *out; char *cbuf = buf; char *user; int userlen; char tmp[6*NUMSIZE]; if(n <= 0) return n; switch(c->qid.path&~CHDIR){ case Qdir: return devdirread(c, buf, n, consdir, NCONS, consgen); case Qrcons: case Qcons: qlock(&kbdq); if(waserror()){ qunlock(&kbdq); nexterror(); } while(!cangetc(&lineq)){ sleep(&kbdq.r, isbrkc, &kbdq); do{ lock(&lineq); ch = getc(&kbdq); if(raw.ref){ unlock(&lineq); goto Default; } switch(ch){ case '\b': if(lineq.in != lineq.out){ if(lineq.in == lineq.buf) lineq.in = lineq.buf+sizeof(lineq.buf); lineq.in--; } break; case 0x15: lineq.in = lineq.out; break; Default: default: *lineq.in++ = ch; if(lineq.in == lineq.buf+sizeof(lineq.buf)) lineq.in = lineq.buf; } unlock(&lineq); }while(raw.ref==0 && ch!='\n' && ch!=0x04); } i = 0; while(n > 0){ ch = getc(&lineq); if(ch==-1 || (raw.ref==0 && ch==0x04)) break; i++; *cbuf++ = ch; --n; } qunlock(&kbdq); return i; case Qrs232: return streamread(c, buf, n); case Qrs232ctl: if(c->offset) return 0; *(char *)buf = duartinputport(); return 1; case Qcputime: k = c->offset; if(k >= sizeof tmp) return 0; if(k+n > sizeof tmp) n = sizeof tmp - k; /* easiest to format in a separate buffer and copy out */ for(i=0; i<6 && NUMSIZE*i<k+n; i++){ l = u->p->time[i]; if(i == TReal) l = MACHP(0)->ticks - l; l = TK2MS(l); readnum(0, tmp+NUMSIZE*i, NUMSIZE, l, NUMSIZE); } memcpy(buf, tmp+k, n); return n; case Qpgrpid: return readnum(c->offset, buf, n, u->p->pgrp->pgrpid, NUMSIZE); case Qpid: return readnum(c->offset, buf, n, u->p->pid, NUMSIZE); case Qppid: return readnum(c->offset, buf, n, u->p->parentpid, NUMSIZE); case Qtime: return readnum(c->offset, buf, n, boottime+TK2SEC(MACHP(0)->ticks), NUMSIZE); case Qmsec: return readnum(c->offset, buf, n, TK2MS(MACHP(0)->ticks), NUMSIZE); case Qclock: k = c->offset; if(k >= 2*NUMSIZE) return 0; if(k+n > 2*NUMSIZE) n = 2*NUMSIZE - k; readnum(0, tmp, NUMSIZE, MACHP(0)->ticks, NUMSIZE); readnum(0, tmp+NUMSIZE, NUMSIZE, HZ, NUMSIZE); memcpy(buf, tmp+k, n); return n; case Quser: return readstr(c->offset, buf, n, u->p->pgrp->user); case Qnull: return 0; case Qklog: qlock(&klogq); if(waserror()){ qunlock(&klogq); nexterror(); } while(!cangetc(&klogq)) sleep(&klogq.r, cangetc, &klogq); for(i=0; i<n; i++){ if((ch=getc(&klogq)) == -1) break; *cbuf++ = ch; } poperror(); qunlock(&klogq); return i; default: panic("consread %lux\n", c->qid); return 0; } } long conswrite(Chan *c, void *va, long n) { char cbuf[64]; char buf[256]; long l, m; char *a = va; switch(c->qid.path){ case Qcons: case Qrcons: /* * Damn. Can't page fault in putstrn, so copy the data locally. */ l = n; while(l > 0){ m = l; if(m > sizeof buf) m = sizeof buf; memcpy(buf, a, m); putstrn(a, m); a += m; l -= m; } break; case Qrs232: case Qrs232ctl: n = streamwrite(c, va, n, 1); break; case Qtime: if(n<=0 || boottime!=0) /* only one write please */ return 0; if(n >= sizeof cbuf) n = sizeof cbuf - 1; memcpy(cbuf, a, n); cbuf[n-1] = 0; boottime = strtoul(a, 0, 0); break; case Quser: if(u->p->pgrp->user[0]) /* trying to overwrite /dev/user */ error(Eperm); if(c->offset >= NAMELEN-1) return 0; if(c->offset+n >= NAMELEN-1) n = NAMELEN-1 - c->offset; memcpy(u->p->pgrp->user+c->offset, a, n); u->p->pgrp->user[c->offset+n] = 0; break; case Qcputime: case Qpgrpid: case Qpid: case Qppid: error(Eperm); case Qnull: break; default: error(Egreg); } return n; } void consremove(Chan *c) { error(Eperm); } void conswstat(Chan *c, char *dp) { error(Eperm); } /* * rs232 stream routines * * A kernel process, rs232kproc, stages blocks to be output and * packages input bytes into stream blocks to send upstream. * The process is awakened whenever the interrupt side is almost * out of bytes to xmit or 1/16 second has elapsed since a byte * was input. */ static int rs232empty(void *a) { Rs232 *r; r = a; return r->out.w == r->out.r; } static void rs232output(Rs232 *r) { int next; Queue *q; Block *bp; long l; qlock(&r->outlock); q = r->wq; /* * free old blocks */ for(next = r->out.f; next != r->out.r; next = NEXT(next)){ freeb(r->out.bp[next]); r->out.bp[next] = 0; } r->out.f = next; /* * stage new blocks * * if we run into a control block, wait till the queue * is empty before doing the control. */ for(next = NEXT(r->out.w); next != r->out.f; next = NEXT(next)){ bp = getq(q); if(bp == 0) break; if(bp->type == M_CTL){ while(!rs232empty(r)) sleep(&r->r, rs232empty, r); l = strtoul((char *)(bp->rptr+1), 0, 0); switch(*bp->rptr){ case 'B': case 'b': duartbaud(l); break; case 'D': case 'd': duartdtr(l); break; case 'K': case 'k': duartbreak(l); break; case 'W': case 'w': if(l>=0 && l<1000) r->delay = l; break; } freeb(bp); break; } r->out.bp[r->out.w] = bp; r->out.w = next; } /* * start output, the spl's sync with interrupt level * this wouldn't work on a multi-processor */ splhi(); if(r->started == 0){ r->started = 1; duartstartrs232o(); } spllo(); qunlock(&r->outlock); } static void rs232input(Rs232 *r) { Queue *q; int c; Block *bp; q = RD(r->wq); bp = 0; while((c = getc(&r->in)) >= 0){ if(bp == 0){ bp = allocb(64); bp->flags |= S_DELIM; } *bp->wptr++ = c; if(bp->wptr == bp->lim){ if(QFULL(q->next)) freeb(bp); else PUTNEXT(q, bp); bp = 0; } } if(bp){ if(QFULL(q->next)) freeb(bp); else PUTNEXT(q, bp); } } static int rs232stuff(void *arg) { Rs232 *r; r = arg; return (r->in.in != r->in.out) || (r->out.r != r->out.w) || (r->out.f != r->out.r); } static void rs232kproc(void *a) { Rs232 *r; r = a; for(;;){ qlock(r); if(r->wq != 0){ rs232output(r); rs232input(r); } qunlock(r); sleep(&r->r, rs232stuff, r); } } static void rs232open(Queue *q, Stream *c) { Rs232 *r; r = &rs232; RD(q)->ptr = r; WR(q)->ptr = r; r->wq = WR(q); if(r->kstarted == 0){ r->in.in = r->in.out = r->in.buf; kproc("rs232", rs232kproc, r); r->kstarted = 1; } } static void rs232close(Queue *q) { Rs232 *r; r = q->ptr; qlock(r); r->wq = 0; qunlock(r); } static void rs232oput(Queue *q, Block *bp) { if(bp->rptr >= bp->wptr) freeb(bp); else putq(q, bp); rs232output(q->ptr); } static void rs232timer(Alarm *a) { Rs232 *r; r = a->arg; cancel(a); r->a = 0; wakeup(&r->r); } /* * called by input interrupt. runs splhi */ void rs232ichar(int c) { Rs232 *r; r = &rs232; if(putc(&r->in, c) < 0) screenputc('^'); /* * pass upstream within 1/16 second */ if(r->a==0){ if(r->delay == 0) wakeup(&r->r); else r->a = alarm(r->delay, rs232timer, r); } } /* * called by output interrupt. runs splhi */ int getrs232o(void) { uchar c; Rs232 *r; Block *bp; r = &rs232; if(r->out.r == r->out.w){ r->started = 0; return -1; } bp = r->out.bp[r->out.r]; c = *bp->rptr++; if(bp->rptr >= bp->wptr){ r->out.r = NEXT(r->out.r); if(r->out.r==r->out.w || NEXT(r->out.r)==r->out.w) wakeup(&r->r); } return c; }
A ss/devincon.c => ss/devincon.c +883 -0
@@ 0,0 1,883 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #include "io.h" #include "ureg.h" typedef struct Incon Incon; typedef struct Device Device; #define NOW (MACHP(0)->ticks*MS2HZ) #define MICROSECOND USED(NOW) #define DPRINT if(0) enum { Minstation= 2, /* lowest station # to poll */ Maxstation= 15, /* highest station # to poll */ Nincon= 1, /* number of incons */ Nin= 32, /* Blocks in the input ring */ Bsize= 128, /* size of an input ring block */ Mfifo= 0xff /* a mask, must be 2^n-1, must be > Nin */ }; /* * incon datakit board */ struct Device { uchar cdata; #define cpolln cdata uchar u0; uchar cstatus; uchar u1; uchar creset; uchar u2; uchar csend; uchar u3; ushort data_cntl; /* data is high byte, cntl is low byte */ uchar status; #define cmd status uchar u5; uchar reset; uchar u6; uchar send; uchar u7; }; #define INCON ((Device *)0x40700000) struct Incon { QLock; QLock xmit; /* transmit lock */ QLock reslock; /* reset lock */ Device *dev; int station; /* station number */ int state; /* chip state */ Rendez r; /* output process */ Rendez kr; /* input kernel process */ ushort chan; /* current input channel */ Queue *rq; /* read queue */ int kstarted; /* true if kernel process started */ /* input blocks */ Block *inb[Nin]; ushort wi; ushort ri; /* statistics */ ulong overflow; /* overflow errors */ ulong pack0; /* channel 0 */ ulong crc; /* crc errors */ ulong in; /* bytes in */ ulong out; /* bytes out */ }; Incon incon[Nincon]; /* * chip state */ enum { Selecting, Selected, Notliving, }; /* * internal chip registers */ #define sel_polln 0 #define sel_station 1 #define sel_poll0 2 #define sel_rcv_cnt 3 #define sel_rcv_tim 4 #define sel_tx_cnt 5 /* * CSR bits */ #define INCON_RUN 0x80 #define INCON_STOP 0x00 #define ENABLE_IRQ 0x40 #define ENABLE_TX_IRQ 0x20 #define INCON_ALIVE 0x80 #define TX_FULL 0x10 #define TX_EMPTY 0x08 #define RCV_EMPTY 0x04 #define OVERFLOW 0x02 #define CRC_ERROR 0x01 /* * polling constants */ #define HT_GNOT 0x30 #define ST_UNIX 0x04 #define NCHAN 16 static void inconkproc(void*); /* * incon stream module definition */ static void inconoput(Queue*, Block*); static void inconstopen(Queue*, Stream*); static void inconstclose(Queue*); Qinfo inconinfo = { nullput, inconoput, inconstopen, inconstclose, "incon" }; int incondebug; /* * set the incon parameters */ void inconset(Incon *ip, int cnt, int del) { Device *dev; if (cnt<1 || cnt>14 || del<1 || del>15) error(Ebadarg); dev = ip->dev; dev->cmd = sel_rcv_cnt | INCON_RUN; MICROSECOND; *(uchar *)&dev->data_cntl = cnt; MICROSECOND; dev->cmd = sel_rcv_tim | INCON_RUN; MICROSECOND; *(uchar *)&dev->data_cntl = del; MICROSECOND; dev->cmd = INCON_RUN | ENABLE_IRQ; } /* * parse a set request */ void inconsetctl(Incon *ip, Block *bp) { char *field[3]; int n; int del; int cnt; del = 15; n = getfields((char *)bp->rptr, field, 3, ' '); switch(n){ default: freeb(bp); error(Ebadarg); case 2: del = strtol(field[1], 0, 0); if(del<0 || del>15){ freeb(bp); error(Ebadarg); } /* fall through */ case 1: cnt = strtol(field[0], 0, 0); if(cnt<0 || cnt>15){ freeb(bp); error(Ebadarg); } } inconset(ip, cnt, del); freeb(bp); } static void nop(void) { } /* * poll for a station number */ void inconpoll(Incon *ip, int station) { ulong timer; Device *dev; dev = ip->dev; /* * get us to a known state */ ip->state = Notliving; dev->cmd = INCON_STOP; /* * try a station number */ dev->cmd = sel_station; *(uchar *)&dev->data_cntl = station; dev->cmd = sel_poll0; *(uchar *)&dev->data_cntl = HT_GNOT; dev->cmd = sel_rcv_cnt; *(uchar *)&dev->data_cntl = 3; dev->cmd = sel_rcv_tim; *(uchar *)&dev->data_cntl = 15; dev->cmd = sel_tx_cnt; *(uchar *)&dev->data_cntl = 1; dev->cmd = sel_polln; *(uchar *)&dev->data_cntl = 0x00; *(uchar *)&dev->data_cntl = ST_UNIX; *(uchar *)&dev->data_cntl = NCHAN; *(uchar *)&dev->data_cntl = 'g'; *(uchar *)&dev->data_cntl = 'n'; *(uchar *)&dev->data_cntl = 'o'; *(uchar *)&dev->data_cntl = 't'; dev->cpolln = 0; /* * poll and wait for ready (or 1/4 second) */ ip->state = Selecting; dev->cmd = INCON_RUN | ENABLE_IRQ; timer = NOW + 250; while (NOW < timer) { nop(); if(dev->status & INCON_ALIVE){ ip->station = station; ip->state = Selected; break; } } } /* * reset the chip and find a new staion number */ void inconrestart(Incon *ip) { Device *dev; int i; if(!canqlock(&ip->reslock)) return; print("inconrestart\n"); /* * poll for incon station numbers */ for(i = Minstation; i <= Maxstation; i++){ inconpoll(ip, i); if(ip->state == Selected) break; } switch(ip->state) { case Selecting: print("incon[%d] not polled\n", ip-incon); break; case Selected: print("incon[%d] station %d\n", ip-incon, ip->station); inconset(ip, 3, 15); break; default: print("incon[%d] bollixed\n", ip-incon); break; } qunlock(&ip->reslock); } /* * reset all incon chips. */ void inconreset(void) { int i; Incon *ip; incon[0].dev = INCON; incon[0].state = Selected; incon[0].ri = incon[0].wi = 0; /* inconset(&incon[0], 3, 15); /**/ for(i=1; i<Nincon; i++){ incon[i].dev = INCON+i; incon[i].state = Notliving; incon[i].dev->cmd = INCON_STOP; incon[i].ri = incon[i].wi = 0; } } void inconinit(void) { } /* * enable the device for interrupts, spec is the device number */ Chan* inconattach(char *spec) { Incon *ip; int i; Chan *c; i = strtoul(spec, 0, 0); if(i >= Nincon) error(Ebadarg); ip = &incon[i]; if(ip->state != Selected) inconrestart(ip); c = devattach('i', spec); c->dev = i; c->qid.path = CHDIR; c->qid.vers = 0; return c; } Chan* inconclone(Chan *c, Chan *nc) { return devclone(c, nc); } int inconwalk(Chan *c, char *name) { return devwalk(c, name, 0, 0, streamgen); } void inconstat(Chan *c, char *dp) { devstat(c, dp, 0, 0, streamgen); } Chan* inconopen(Chan *c, int omode) { if(c->qid.path == CHDIR){ if(omode != OREAD) error(Eperm); }else streamopen(c, &inconinfo); c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void inconcreate(Chan *c, char *name, int omode, ulong perm) { error(Eperm); } void inconclose(Chan *c) { if(c->qid.path != CHDIR) streamclose(c); } long inconread(Chan *c, void *buf, long n) { return streamread(c, buf, n); } long inconwrite(Chan *c, void *buf, long n) { return streamwrite(c, buf, n, 0); } void inconremove(Chan *c) { error(Eperm); } void inconwstat(Chan *c, char *dp) { error(Eperm); } /* * the stream routines */ /* * create the kernel process for input */ static void inconstopen(Queue *q, Stream *s) { Incon *ip; char name[32]; ip = &incon[s->dev]; sprint(name, "incon%d", s->dev); q->ptr = q->other->ptr = ip; ip->rq = q; kproc(name, inconkproc, ip); } /* * kill off the kernel process */ static int kNotliving(void *arg) { Incon *ip; ip = (Incon *)arg; return ip->kstarted == 0; } static void inconstclose(Queue * q) { Incon *ip; ip = (Incon *)q->ptr; qlock(ip); ip->rq = 0; qunlock(ip); wakeup(&ip->kr); sleep(&ip->r, kNotliving, ip); } /* * free all blocks of a message in `q', `bp' is the first block * of the message */ static void freemsg(Queue *q, Block *bp) { for(; bp; bp = getq(q)){ if(bp->flags & S_DELIM){ freeb(bp); return; } freeb(bp); } } /* * output a block * * the first 2 bytes of every message are the channel number, * low order byte first. the third is a possible trailing control * character. */ void inconoput(Queue *q, Block *bp) { Device *dev; Incon *ip; ulong end; int chan; int ctl; int n, size; ip = (Incon *)q->ptr; if(bp->type != M_DATA){ if(streamparse("inconset", bp)) inconsetctl(ip, bp); else freeb(bp); return; } /* * get a whole message before handing bytes to the device */ if(!putq(q, bp)) return; /* * one transmitter at a time */ qlock(&ip->xmit); dev = ip->dev; /* * parse message */ bp = getq(q); if(bp->wptr - bp->rptr < 3){ freemsg(q, bp); qunlock(&ip->xmit); return; } chan = bp->rptr[0] | (bp->rptr[1]<<8); ctl = bp->rptr[2]; bp->rptr += 3; if(chan<=0) print("bad channel %d\n", chan); if(incondebug) print("->(%d)%uo %d\n", chan, ctl, bp->wptr - bp->rptr); /* * make sure there's an incon out there */ if(!(dev->status&INCON_ALIVE) || ip->state==Notliving){ inconrestart(ip); freemsg(q, bp); qunlock(&ip->xmit); return; } /* * send the 8 bit data */ for(;;){ /* * spin till there is room */ for(end = NOW+1000; dev->status & TX_FULL;){ nop(); /* make sure we don't optimize too much */ if(NOW > end){ print("incon output stuck\n"); freemsg(q, bp); qunlock(&ip->xmit); return; } } /* * put in next packet */ n = bp->wptr - bp->rptr; if(n > 16) n = 16; size = n; dev->cdata = chan; while(n--){ *(uchar *)&dev->data_cntl = *bp->rptr++; } /* * get next block */ if(bp->rptr >= bp->wptr){ if(bp->flags & S_DELIM){ freeb(bp); break; } freeb(bp); bp = getq(q); if(bp==0) break; } /* * end packet */ dev->cdata = 0; } /* * send the control byte if there is one */ if(ctl){ if(size >= 16){ dev->cdata = 0; MICROSECOND; for(end = NOW+1000; dev->status & TX_FULL;){ nop(); /* make sure we don't optimize too much */ if(NOW > end){ print("incon output stuck\n"); freemsg(q, bp); qunlock(&ip->xmit); return; } } dev->cdata = chan; MICROSECOND; } if(dev->status & TX_FULL) print("inconfull\n"); dev->cdata = ctl; } MICROSECOND; dev->cdata = 0; qunlock(&ip->xmit); return; } /* * return true if the raw fifo is non-empty */ static int notempty(void *arg) { Incon *ip; ip = (Incon *)arg; return ip->ri!=ip->wi; } /* * Read bytes from the raw input circular buffer. */ static void inconkproc(void *arg) { Incon *ip; Block *bp, *nbp; int i; int locked; ip = (Incon *)arg; ip->kstarted = 1; /* * create a number of blocks for input */ for(i = 0; i < Nin; i++){ bp = ip->inb[i] = allocb(Bsize); bp->wptr += 3; } locked = 0; if(waserror()){ if(locked) qunlock(ip); ip->kstarted = 0; wakeup(&ip->r); return; } for(;;){ /* * sleep if input fifo empty */ sleep(&ip->kr, notempty, ip); /* * die if the device is closed */ USED(locked); qlock(ip); locked = 1; if(ip->rq == 0){ qunlock(ip); ip->kstarted = 0; wakeup(&ip->r); poperror(); return; } /* * send blocks upstream and stage new blocks. if the block is small * (< 64 bytes) copy into a smaller buffer. */ while(ip->ri != ip->wi){ bp = ip->inb[ip->ri]; PUTNEXT(ip->rq, bp); bp = ip->inb[ip->ri] = allocb(Bsize); bp->wptr += 3; ip->ri = (ip->ri+1)%Nin; } USED(locked); qunlock(ip); locked = 0; } } /* * drop a single packet */ static void droppacket(Device *dev) { int i; int c; for(i = 0; i < 17; i++){ c = dev->data_cntl; if(c==0) break; } } /* * flush the input fifo */ static void flushfifo(Device *dev) { while(!(dev->status & RCV_EMPTY)) droppacket(dev); } /* * advance the queue. if we've run out of staged input blocks, * drop the packet and return 0. otherwise return the next input * block to fill. */ static Block * nextin(Incon *ip, unsigned int c) { Block *bp; int next; bp = ip->inb[ip->wi]; bp->base[0] = ip->chan; bp->base[1] = ip->chan>>8; bp->base[2] = c; if(incondebug) print("<-(%d)%uo %d\n", ip->chan, c, bp->wptr-bp->rptr); next = (ip->wi+1)%Nin; if(next == ip->ri){ bp->wptr = bp->base+3; return bp; } ip->wi = next; return ip->inb[ip->wi]; } /* * read the packets from the device into the staged input blocks. * we have to do this at interrupt tevel to turn off the interrupts. */ static void rdpackets(Incon *ip) { Block *bp; unsigned int c; Device *dev; uchar *p; int first = ip->wi; dev = ip->dev; bp = ip->inb[ip->wi]; if(bp==0){ flushfifo(ip->dev); return; } p = bp->wptr; while(!(dev->status & RCV_EMPTY)){ /* * get channel number */ c = (dev->data_cntl)>>8; if(c == 0){ droppacket(dev); continue; } if(ip->chan != c){ if(p - bp->rptr > 3){ bp->wptr = p; bp = nextin(ip, 0); p = bp->wptr; } ip->chan = c; } /* * null byte marks end of packet */ for(;;){ if((c=dev->data_cntl)&1) { /* * data byte, put in local buffer */ *p++ = c>>8; } else if (c>>=8) { /* * control byte ends block */ bp->wptr = p; bp = nextin(ip, c); p = bp->wptr; } else { /* end of packet */ break; } } /* * pass a block on if it doesn't have room for one more * packet. this way we don't have to check per byte. */ if(p + 16 > bp->lim){ bp->wptr = p; bp = nextin(ip, 0); p = bp->wptr; } } bp->wptr = p; if(bp->wptr != bp->base+3) nextin(ip, 0); if(first != ip->wi)/**/ wakeup(&ip->kr); } /* * Receive an incon interrupt. One entry point * for all types of interrupt. Until we figure out * how to use more than one incon, this routine only * is for incon[0]. */ inconintr(Ureg *ur) { uchar status; Incon *ip; ip = &incon[0]; status = ip->dev->status; if(!(status & RCV_EMPTY)) rdpackets(ip); /* check for exceptional conditions */ if(status&(OVERFLOW|CRC_ERROR)){ if(status&OVERFLOW) ip->overflow++; if(status&CRC_ERROR) ip->crc++; } /* see if it died underneath us */ if(!(status&INCON_ALIVE)){ switch(ip->state){ case Selected: ip->dev->cmd = INCON_STOP; print("Incon died\n"); break; case Selecting: print("rejected\n"); break; default: ip->dev->cmd = INCON_STOP; break; } ip->state = Notliving; } } incontoggle() { incondebug ^= 1; }
A ss/devkprof.c => ss/devkprof.c +177 -0
@@ 0,0 1,177 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "errno.h" #include "devtab.h" #define MAXPC (100*1024L) #define RES 8 #define LRES 3 #define NBUF (MAXPC>>LRES) long timerbuf[NBUF]; enum{ Kprofdirqid, Kprofdataqid, Kprofstartqid, Kprofstartclrqid, Kprofstopqid, Nkproftab=Kprofstopqid, Kprofmaxqid, }; Dirtab kproftab[Nkproftab]={ "kpdata", Kprofdataqid, NBUF*sizeof timerbuf[0], 0600, "kpstart", Kprofstartqid, 0, 0600, "kpstartclr", Kprofstartclrqid, 0, 0600, "kpstop", Kprofstopqid, 0, 0600, }; void kproftimer(ulong); void kprofreset(void) { kprofp = kproftimer; } void kprofinit(void) { extern void *etext; if((((unsigned long)&etext)-KTZERO)>MAXPC) print("kernel profiling limited to %lud\n", MAXPC); } Chan * kprofattach(char *spec) { return devattach('t', spec); } Chan * kprofclone(Chan *c, Chan *nc) { return devclone(c, nc); } int kprofwalk(Chan *c, char *name) { return devwalk(c, name, kproftab, (long)Nkproftab, devgen); } void kprofstat(Chan *c, char *db) { devstat(c, db, kproftab, (long)Nkproftab, devgen); } Chan * kprofopen(Chan *c, int omode) { if(c->qid == CHDIR){ if(omode != OREAD) error(0, Eperm); } c->mode = openmode(omode); c->flag |= COPEN; c->offset = 0; return c; } void kprofcreate(Chan *c, char *name, int omode, ulong perm) { error(0, Eperm); } void kprofremove(Chan *c) { error(0, Eperm); } void kprofwstat(Chan *c, char *dp) { error(0, Eperm); } void kprofclose(Chan *c) { } void kprofuserstr(Error *e, char *buf) { consuserstr(e, buf); } void kproferrstr(Error *e, char *buf) { rooterrstr(e, buf); } long kprofread(Chan *c, void *a, long n) { switch((int)(c->qid&~CHDIR)){ case Kprofdirqid: return devdirread(c, a, n, kproftab, Nkproftab, devgen); case Kprofdataqid: if(c->offset >= NBUF*sizeof timerbuf[0]){ n = 0; break; } if(c->offset+n > NBUF*sizeof timerbuf[0]) n = NBUF*sizeof timerbuf[0]-c->offset; memcpy(a, ((char *)timerbuf)+c->offset, n); break; default: n=0; break; } return n; } long kprofwrite(Chan *c, char *a, long n) { switch((int)(c->qid&~CHDIR)){ case Kprofstartclrqid: memset((char *)timerbuf, 0, NBUF*sizeof timerbuf[0]); case Kprofstartqid: duartstarttimer(); break; case Kprofstopqid: duartstoptimer(); break; default: error(0, Ebadusefd); } return n; } void kproftimer(ulong pc) { /* * if the pc is coming out of slplo pr splx, then use * the pc saved when we went splhi. */ if(pc>=(ulong)spllo && pc<=(ulong)spldone) pc = m->splpc; timerbuf[0]++; if(KTZERO<=pc && pc<KTZERO+MAXPC){ pc -= KTZERO; pc >>= LRES; timerbuf[pc]++; } else timerbuf[1]++; }
A ss/errno.h => ss/errno.h +63 -0
@@ 0,0 1,63 @@ enum{ Enevermind, /* never mind */ Enofd, /* no free file descriptors */ Ebadfd, /* fd out of range or not open */ Ebadusefd, /* inappropriate use of fd */ Ebadarg, /* bad arg in system call */ Enonexist, /* file does not exist */ Efilename, /* file name syntax */ Ebadchar, /* bad character in file name */ Ebadsharp, /* unknown device in # filename */ Ebadexec, /* a.out header invalid */ Eioload, /* i/o error in demand load */ Eperm, /* permission denied */ Enotdir, /* not a directory */ Enochild, /* no living children */ Enoseg, /* no free segments */ Ebadmount, /* inconsistent mount */ Enomount, /* mount table full */ Enomntdev, /* no free mount devices */ Eshutdown, /* mounted device shut down */ Einuse, /* device or object already in use */ Eio, /* i/o error */ Eisdir, /* file is a directory */ Ebaddirread, /* directory read not quantized */ Esegaddr, /* illegal segment addresses or size */ Enoenv, /* no free environment resources */ Eprocdied, /* process exited */ Enocreate, /* mounted directory forbids creation */ Enotunion, /* attempt to union with non-mounted directory */ Emount, /* inconsistent mount */ Enosrv, /* no free server slots */ Enoqueue, /* no free stream queues */ Ebadld, /* illegal line discipline */ Enostream, /* no free stream heads */ Etoobig, /* read or write too large */ Etoosmall, /* read or write too small */ Ehungup, /* write to hungup stream */ Ebadnet, /* illegal network address */ Enoifc, /* bad interface or no free interface slots */ Enodev, /* no free devices */ Ebadctl, /* bad process or stream control request */ Enonote, /* note overflow */ Eintr, /* interrupted */ Edestbusy, /* datakit destination busy */ Enetbusy, /* datakit controller busy */ Edestotl, /* datakit destination out to lunch */ Enetotl, /* datakit controller out to lunch */ Erejected, /* datakit destination rejected call */ Ebadblt, /* bad bitblt or bitmap request */ Enobitmap, /* out of bitmap descriptors */ Enobitstore, /* out of bitmap storage */ Ebadbitmap, /* unallocated bitmap */ Ebadfont, /* unallocated font */ Eshortmsg, /* short message */ Ebadmsg, /* format error or mismatch in message */ Ebadcnt, /* read count greater than requested */ Enofont, /* out of font descriptors */ Enovmem, /* virtual memory allocation failed */ Enoasync, /* out of async stream modules */ Enopipe, /* out of pipes */ Enofilsys, /* out of filsys resources */ Egreg, /* ken has implemented datakit */ };
A ss/faultsparc.c => ss/faultsparc.c +98 -0
@@ 0,0 1,98 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "errno.h" #define FORMAT(ur) ((((ur)->vo)>>12)&0xF) #define OFFSET(ur) (((ur)->vo)&0xFFF) struct FFrame { ushort ireg0; /* internal register */ ushort ssw; /* special status word */ ushort ipsc; /* instr. pipe stage c */ ushort ipsb; /* instr. pipe stage b */ ulong addr; /* data cycle fault address */ ushort ireg1; /* internal register */ ushort ireg2; /* internal register */ ulong dob; /* data output buffer */ ushort ireg3[4]; /* more stuff */ ulong baddr; /* stage b address */ ushort ireg4[26]; /* more more stuff */ }; /* * SSW bits */ #define RW 0x0040 /* read/write for data cycle */ #define FC 0x8000 /* fault on stage C of instruction pipe */ #define FB 0x4000 /* fault on stage B of instruction pipe */ #define RC 0x2000 /* rerun flag for stage C of instruction pipe */ #define RB 0x1000 /* rerun flag for stage B of instruction pipe */ #define DF 0x0100 /* fault/rerun flag for data cycle */ #define RM 0x0080 /* read-modify-write on data cycle */ #define READ 0x0040 #define WRITE 0x0000 #define SIZ 0x0030 /* size code for data cycle */ #define FC2 0x0004 /* address space for data cycle */ #define FC1 0x0002 #define FC0 0x0001 void fault68020(Ureg *ur, FFrame *f) { ulong addr, badvaddr; int user, read, insyscall; if(u == 0){ dumpregs(ur); panic("fault u==0 pc=%lux", ur->pc); } insyscall = u->p->insyscall; u->p->insyscall = 1; addr = 0; /* set */ if(f->ssw & DF) addr = f->addr; else if(FORMAT(ur) == 0xA){ if(f->ssw & FC) addr = ur->pc+2; else if(f->ssw & FB) addr = ur->pc+4; else panic("prefetch pagefault"); }else if(FORMAT(ur) == 0xB){ if(f->ssw & FC) addr = f->baddr-2; else if(f->ssw & FB) addr = f->baddr; else panic("prefetch pagefault"); }else panic("prefetch format"); addr &= VAMASK; badvaddr = addr; addr &= ~(BY2PG-1); user = !(ur->sr&SUPER); if(f->ssw & DF) read = (f->ssw&READ) && !(f->ssw&RM); else read = f->ssw&(FB|FC); /* print("fault pc=%lux addr=%lux read %d\n", ur->pc, badvaddr, read); /**/ if(fault(addr, read) < 0){ if(user){ pprint("user %s error addr=0x%lux\n", read? "read" : "write", badvaddr); pprint("status=0x%lux pc=0x%lux sp=0x%lux\n", ur->sr, ur->pc, ur->sp); pexit("Suicide", 0); } u->p->state = MMUing; dumpregs(ur); panic("fault: 0x%lux", badvaddr); exit(); } u->p->insyscall = insyscall; }
A ss/fcall.h => ss/fcall.h +88 -0
@@ 0,0 1,88 @@ typedef struct Fcall Fcall; struct Fcall { char type; short fid; short tag; union { struct { short newfid; /* T-Clone */ short oldtag; /* T-Flush */ Qid qid; /* R-Attach, R-Walk, R-Open, R-Create */ }; struct { char uname[NAMELEN]; /* T-Attach */ char aname[NAMELEN]; /* T-Attach */ char auth[NAMELEN]; /* T-Attach */ }; struct { char ename[ERRLEN]; /* R-Error */ }; struct { long perm; /* T-Create */ char name[NAMELEN]; /* T-Walk, T-Create */ char mode; /* T-Create, T-Open */ }; struct { long offset; /* T-Read, T-Write */ long count; /* T-Read, T-Write, R-Read */ char *data; /* T-Write, R-Read */ }; struct { char stat[DIRLEN]; /* T-Wstat, R-Stat */ }; }; }; #define MAXFDATA 8192 enum { Tnop = 50, Rnop, Tsession = 52, Rsession, /* Terror = 54, illegal */ Rerror = 55, Tflush = 56, Rflush, Tattach = 58, Rattach, Tclone = 60, Rclone, Twalk = 62, Rwalk, Topen = 64, Ropen, Tcreate = 66, Rcreate, Tread = 68, Rread, Twrite = 70, Rwrite, Tclunk = 72, Rclunk, Tremove = 74, Rremove, Tstat = 76, Rstat, Twstat = 78, Rwstat, }; int convM2S(char*, Fcall*, int); int convS2M(Fcall*, char*); int convM2D(char*, Dir*); int convD2M(Dir*, char*); int fcallconv(void *, int, int, int, int); int dirconv(void *, int, int, int, int);
A ss/fns.h => ss/fns.h +204 -0
@@ 0,0 1,204 @@ Alarm *alarm(int, void (*)(Alarm*), void*); void alarminit(void); Block *allocb(ulong); void append(List**, List*); void cancel(Alarm*); int canlock(Lock*); int canqlock(QLock*); void chaninit(void); void chandevreset(void); void chandevinit(void); void checkalarms(void); void clearmmucache(void); void clock(Ureg*); Chan *clone(Chan*, Chan*); void close(Chan*); void closemount(Mount*); void closepgrp(Pgrp*); long clrfpintr(void); int compactpte(Orig*, ulong); void confinit(void); Env *copyenv(Env*, int); Chan *createdir(Chan*); int decref(Ref*); void delay(int); void delete(List**, List*, List*); void delete0(List**, List*); Chan *devattach(int, char*); Chan *devclone(Chan*, Chan*); void devdir(Chan*, Qid, char*, long, long, Dir*); long devdirread(Chan*, char*, long, Dirtab*, int, Devgen*); Devgen devgen; int devno(int, int); Chan *devopen(Chan*, int, Dirtab*, int, Devgen*); void devstat(Chan*, char*, Dirtab*, int, Devgen*); int devwalk(Chan*, char*, Dirtab*, int, Devgen*); Chan *domount(Chan*); void duartbaud(int); void duartbreak(int); void duartdtr(int); int duartinputport(void); void duartstartrs232o(void); void duartstarttimer(void); void duartstoptimer(void); void dumpregs(Ureg*); void dumpstack(void); int eqchan(Chan*, Chan*, long); int eqqid(Qid, Qid); void envpgclose(Env *); void error(int); void errors(char*); void exit(void); int fault(ulong, int); void fault68020(Ureg*, FFrame*); void fdclose(int); Chan *fdtochan(int, int); void filsys(Chan*, char*, long); void filsysinit(void); void firmware(void); void flowctl(Queue*); void flushcpucache(void); void flushmmu(void); void forkmod(Seg*, Seg*, Proc*); int fpcr(int); void fpsave(FPsave*); void fpregsave(char*); void fprestore(FPsave*); void fpregrestore(char*); void freeb(Block*); int freebroken(void); void freenextmod(PTE*); void freepage(Orig*, int); void freepte(Orig*); void freesegs(int); void freealarm(Alarm*); Block *getb(Blist*); int getfields(char*, char**, int, char); Block *getq(Queue*); int getrs232o(void); void gotolabel(Label*); void growpte(Orig*, ulong); void *ialloc(ulong, int); int incref(Ref*); void insert(List**, List*, List*); void invalidateu(void); void isdir(Chan*); void kbdchar(int); void kbdrepeat(int); void kbdclock(void); void kmapinit(void); KMap *kmap(Page*); int kprint(char*, ...); void kproc(char*, void(*)(void*), void*); void kunmap(KMap*); void lock(Lock*); void lockinit(void); Orig *lookorig(ulong, ulong, int, Chan*); void machinit(void); void mapstack(Proc*); void mmuinit(void); int mount(Chan*, Chan*, int); void mousebuttons(int); void mouseclock(void); Chan *namec(char*, int, int, ulong); void nexterror(void); Alarm *newalarm(void); Chan *newchan(void); PTE *newmod(Orig *o); Mount *newmount(void); Orig *neworig(ulong, ulong, int, Chan*); Page *newpage(int, Orig*, ulong); Pgrp *newpgrp(void); Proc *newproc(void); void newqinfo(Qinfo*); char *nextelem(char*, char*); void notify(Ureg*); void nullput(Queue*, Block*); int openmode(ulong); Block *padb(Block*, int); void pageinit(void); void panic(char*, ...); void pexit(char*, int); void pgrpcpy(Pgrp*, Pgrp*); void pgrpinit(void); void pgrpnote(Pgrp*, char*, long, int); Pgrp *pgrptab(int); int postnote(Proc*, int, char*, int); int pprint(char*, ...); void printinit(void); void printslave(void); void procinit0(void); void procrestore(Proc*, uchar*); void procsave(uchar*, int); void procsetup(Proc*); Proc *proctab(int); Queue *pushq(Stream*, Qinfo*); void putbq(Blist*, Block*); void putkmmu(ulong, ulong); void putmmu(ulong, ulong); int putq(Queue*, Block*); void putstr(char*); void putstrn(char*, long); ulong pwait(Waitmsg*); int readnum(ulong, char*, ulong, ulong, int); void ready(Proc*); void reset(void); int return0(void*); void rs232ichar(int); Proc *runproc(void); void qlock(QLock*); void qunlock(QLock*); void restartprint(Alarm*); void restfpregs(FPsave*); void savefpregs(FPsave*); void sched(void); void schedinit(void); void screeninit(void); void screenputc(int); long seconds(void); Seg *seg(Proc*, ulong); int segaddr(Seg*, ulong, ulong); void serviceinit(void); void service(char*, Chan*, Chan*, void (*)(Chan*, char*, long)); int setlabel(Label*); char *skipslash(char*); void sleep(Rendez*, int(*)(void*), void*); int splhi(void); int spllo(void); void splx(int); void spldone(void); Devgen streamgen; int streamclose(Chan*); int streamclose1(Stream*); int streamenter(Stream*); int streamexit(Stream*, int); void streaminit(void); long streamread(Chan*, void*, long); long streamwrite(Chan*, void*, long, int); Stream *streamnew(ushort, ushort, ushort, Qinfo*, int); void streamopen(Chan*, Qinfo*); int streamparse(char*, Block*); void streamstat(Chan*, char*, char*); long stringread(Chan*, void*, long, char*); long syscall(Ureg*); int tas(char*); void touser(void); void tsleep(Rendez*, int (*)(void*), void*, int); void twakeme(Alarm*); long unionread(Chan*, void*, long); void unlock(Lock*); void usepage(Page*, int); void unusepage(Page*, int); void userinit(void); void validaddr(ulong, ulong, int); void *vmemchr(void*, int, int); void wakeme(Alarm*); void wakeup(Rendez*); Chan *walk(Chan*, char*, int); #define waserror() (u->nerrlab++, setlabel(&u->errlab[u->nerrlab-1])) #define poperror() u->nerrlab-- #define evenaddr(x) /* 68020 doesn't care */ #define USED(x) if(x)
A ss/io.h => ss/io.h +6 -0
@@ 0,0 1,6 @@ typedef struct Duart Duart; #define SYNCREG ((char*)0x40400000) #define DISPLAYRAM 0x02000000 #define DUARTREG ((Duart*)0x40100000) #define PORT ((uchar *)0x40300000)
A ss/l.s => ss/l.s +81 -0
@@ 0,0 1,81 @@ #include "mem.h" TEXT start(SB), $-4 /* get virtual, fast */ /* we are executing in segment 0, mapped to pmeg 0. stack is there too */ /* get virtual by mapping segment(KZERO) to pmeg 0. */ MOVW $KZERO, R1 MOVB R0, (R1, 3) /* now mapped correctly. jmpl to where we want to be */ MOVW $setR30(SB), R30 MOVW $startvirt(SB), R1 JMPL (R1) RETURN /* can't get here */ TEXT startvirt(SB), $-4 MOVW $0x4000, R29 MOVW $mach0(SB), R(MACH) JMPL main(SB) UNIMP RETURN TEXT pc(SB), $0 MOVW R15, R1 RETURN TEXT setlabel(SB), $0 MOVW b+0(FP), R2 MOVW R29, (R2) MOVW R15, 4(R2) MOVW $0, R1 RETURN TEXT gotolabel(SB), $0 MOVW r+4(FP), R1 MOVW b+0(FP), R2 MOVW (R2), R29 MOVW 4(R2), R15 MOVW R15, 0(R29) RETURN TEXT crash(SB), $0 MOVW 0(FP), R8 /* context */ MOVW 4(FP), R9 /* segment addr */ MOVW 8(FP), R10 /* segment value */ MOVW $0xFFE80118, R1 JMPL (R1) RETURN TEXT putb2(SB), $0 MOVW 0(FP), R1 MOVW 4(FP), R2 MOVB R2, (R1, 2) RETURN TEXT putw3(SB), $0 MOVW 0(FP), R1 MOVW 4(FP), R2 MOVW R2, (R1, 3) RETURN TEXT putpmeg(SB), $0 MOVW 0(FP), R1 MOVW 4(FP), R2 MOVW R2, (R1, 4) RETURN TEXT putwd(SB), $0 MOVW 0(FP), R1 MOVW 4(FP), R2 MOVW R2, (R1, 0xD) RETURN GLOBL mach0+0(SB), $MACHSIZE
A ss/lib.h => ss/lib.h +112 -0
@@ 0,0 1,112 @@ /* * functions (possibly) linked in, complete, from libc. */ /* * mem routines */ extern void *memccpy(void*, void*, int, long); extern void *memset(void*, int, long); extern int memcmp(void*, void*, long); extern void *memcpy(void*, void*, long); extern void *memchr(void*, int, long); /* * string routines */ extern char *strcat(char*, char*); extern char *strchr(char*, char); extern int strcmp(char*, char*); extern char *strcpy(char*, char*); extern char *strncat(char*, char*, long); extern char *strncpy(char*, char*, long); extern int strncmp(char*, char*, long); extern long strlen(char*); /* * print routines */ #define FUNSIGN 4 #define FSHORT 2 #define FLONG 1 typedef struct Op Op; struct Op { char *p; char *ep; void *argp; int f1; int f2; int f3; }; extern void strconv(char*, Op*, int, int); extern int numbconv(Op*, int); extern char *doprint(char*, char*, char*, void*); extern int fmtinstall(char, int (*)(Op*)); extern int sprint(char*, char*, ...); extern int print(char*, ...); /* * one-of-a-kind */ extern long strtol(char*, char**, int); extern ulong strtoul(char*, char**, int); extern long etext; extern long edata; extern long end; /* * Syscall data structures */ #define MORDER 0x0003 /* mask for bits defining order of mounting */ #define MREPL 0x0000 /* mount replaces object */ #define MBEFORE 0x0001 /* mount goes before others in union directory */ #define MAFTER 0x0002 /* mount goes after others in union directory */ #define MCREATE 0x0004 /* permit creation in mounted directory */ #define MMASK 0x0007 /* all bits on */ #define OREAD 0 /* open for read */ #define OWRITE 1 /* write */ #define ORDWR 2 /* read and write */ #define OEXEC 3 /* execute, == read but check execute permission */ #define OTRUNC 16 /* or'ed in (except for exec), truncate file first */ #define OCEXEC 32 /* or'ed in, close on exec */ #define ORCLOSE 64 /* or'ed in, remove on close */ typedef struct Qid Qid; typedef struct Dir Dir; typedef struct Waitmsg Waitmsg; #define ERRLEN 64 #define DIRLEN 116 #define NAMELEN 28 struct Qid { ulong path; ulong vers; }; struct Dir { char name[NAMELEN]; char uid[NAMELEN]; char gid[NAMELEN]; Qid qid; ulong mode; long atime; long mtime; Length; short type; short dev; }; struct Waitmsg { int pid; /* of loved one */ int status; /* unused; a placeholder */ ulong time[3]; /* of loved one */ char msg[ERRLEN]; };
A ss/lock.c => ss/lock.c +111 -0
@@ 0,0 1,111 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #define PCOFF -1 /* * N.B. Ken's compiler generates a TAS instruction for the sequence: * * if(l->key >= 0){ * l->key |= 0x80; * ... * * DO NOT TAKE THE ADDRESS OF l->key or the TAS will disappear. */ void lock(Lock *l) { Lock *ll = l; /* do NOT take the address of l */ int i; /* * Try the fast grab first */ if(ll->key >= 0){ ll->key |= 0x80; ll->pc = ((ulong*)&l)[PCOFF]; return; } for(i=0; i<10000000; i++) if(ll->key >= 0){ ll->key |= 0x80; ll->pc = ((ulong*)&l)[PCOFF]; return; } ll->key = 0; dumpstack(); panic("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&l)[PCOFF], l->pc); } int canlock(Lock *l) { Lock *ll = l; /* do NOT take the address of l */ if(ll->key >= 0){ ll->key |= 0x80; ll->pc = ((ulong*)&l)[PCOFF]; return 1; } return 0; } void unlock(Lock *l) { l->pc = 0; l->key = 0; } void qlock(QLock *q) { Proc *p; if(canlock(&q->use)) return; lock(&q->queue); if(canlock(&q->use)){ unlock(&q->queue); return; } p = q->tail; if(p == 0) q->head = u->p; else p->qnext = u->p; q->tail = u->p; u->p->qnext = 0; u->p->state = Queueing; u->p->qlock = q; /* DEBUG */ unlock(&q->queue); sched(); } int canqlock(QLock *q) { return canlock(&q->use); } void qunlock(QLock *q) { Proc *p; lock(&q->queue); u->p->qlock = 0; if(q->head){ p = q->head; q->head = p->qnext; if(q->head == 0) q->tail = 0; unlock(&q->queue); ready(p); }else{ unlock(&q->use); unlock(&q->queue); } }
A ss/main.c => ss/main.c +450 -0
@@ 0,0 1,450 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "init.h" #include <libg.h> #include <gnot.h> char user[NAMELEN]; char bootline[64]; char bootserver[64]; char bootdevice[64]; int bank[2]; void unloadboot(void); int Xprint(char *fmt, ...) { char buf[PRINTSIZE]; int n; n = doprint(buf, buf+sizeof(buf), fmt, (&fmt+1)) - buf; sccputs(buf); return n; } void putx(ulong x) { int i; for(i=0; i<8; i++){ sccputc("0123456789ABCDEF"[x>>28]); x <<= 4; } sccputc('\n'); } void main(void) { int a; u = 0; memset(&edata, 0, (char*)&end-(char*)&edata); unloadboot(); machinit(); #ifdef adsf mmuinit(); confinit(); kmapinit(); #endif sccsetup(); Xprint("hello world addr %lux pc %lux\n", &a, pc()); reset(); #ifdef asdf print("bank 0: %dM bank 1: %dM\n", bank[0], bank[1]); flushmmu(); procinit0(); pgrpinit(); chaninit(); alarminit(); chandevreset(); streaminit(); /* serviceinit(); /**/ /* filsysinit(); /**/ pageinit(); kmapinit(); userinit(); schedinit(); #endif } void reset(void) { delay(100); putb2(0x40000000, 4); } void unloadboot(void) { strncpy(user, "rob", sizeof user); memcpy(bootline, "9s", sizeof bootline); memcpy(bootserver, "bootes", sizeof bootserver); memcpy(bootdevice, "parnfucky", sizeof bootserver); } void machinit(void) { int n; n = m->machno; memset(m, 0, sizeof(Mach)); m->machno = n; m->mmask = 1<<m->machno; #ifdef adsf m->fpstate = FPinit; fprestore(&initfp); #endif } void mmuinit(void) { ulong l, d, i; /* * Invalidate user addresses */ for(l=0; l<4*1024*1024; l+=BY2PG) putmmu(l, INVALIDPTE); /* * Four meg of usable memory, with top 256K for screen */ for(i=1,l=KTZERO; i<(4*1024*1024-256*1024)/BY2PG; l+=BY2PG,i++) putkmmu(l, PPN(l)|PTEVALID|PTEKERNEL); /* * Screen at top of memory */ for(i=0,d=DISPLAYRAM; i<256*1024/BY2PG; d+=BY2PG,l+=BY2PG,i++) putkmmu(l, PPN(d)|PTEVALID|PTEKERNEL); } void init0(void) { Chan *c; u->nerrlab = 0; m->proc = u->p; u->p->state = Running; u->p->mach = m; spllo(); chandevinit(); u->slash = (*devtab[0].attach)(0); u->dot = clone(u->slash, 0); if(!waserror()){ c = namec("#e/bootline", Acreate, OWRITE, 0600); (*devtab[c->type].write)(c, bootline, 64); close(c); c = namec("#e/bootserver", Acreate, OWRITE, 0600); (*devtab[c->type].write)(c, bootserver, 64); close(c); c = namec("#e/bootdevice", Acreate, OWRITE, 0600); (*devtab[c->type].write)(c, bootdevice, 2); close(c); } poperror(); touser(); } FPsave initfp; void userinit(void) { Proc *p; Seg *s; User *up; KMap *k; p = newproc(); p->pgrp = newpgrp(); strcpy(p->text, "*init*"); strcpy(p->pgrp->user, user); p->fpstate = FPinit; /* * Kernel Stack */ p->sched.pc = (ulong)init0; p->sched.sp = USERADDR+BY2PG-20; /* BUG */ p->sched.sr = SUPER|SPL(0); p->upage = newpage(0, 0, USERADDR|(p->pid&0xFFFF)); /* * User */ k = kmap(p->upage); up = (User*)VA(k); up->p = p; kunmap(k); /* * User Stack */ s = &p->seg[SSEG]; s->proc = p; s->o = neworig(USTKTOP-BY2PG, 1, OWRPERM, 0); s->minva = USTKTOP-BY2PG; s->maxva = USTKTOP; /* * Text */ s = &p->seg[TSEG]; s->proc = p; s->o = neworig(UTZERO, 1, 0, 0); s->o->pte[0].page = newpage(0, 0, UTZERO); s->o->npage = 1; k = kmap(s->o->pte[0].page); memcpy((ulong*)VA(k), initcode, sizeof initcode); kunmap(k); s->minva = UTZERO; s->maxva = UTZERO+BY2PG; ready(p); } void exit(void) { int i; u = 0; splhi(); print("exiting\n"); for(;;) ; } /* * Insert new into list after where */ void insert(List **head, List *where, List *new) { if(where == 0){ new->next = *head; *head = new; }else{ new->next = where->next; where->next = new; } } /* * Insert new into list at end */ void append(List **head, List *new) { List *where; where = *head; if(where == 0) *head = new; else{ while(where->next) where = where->next; where->next = new; } new->next = 0; } /* * Delete old from list */ void delete0(List **head, List *old) { List *l; l = *head; if(l == old){ *head = old->next; return; } while(l->next != old) l = l->next; l->next = old->next; } /* * Delete old from list. where->next is known to be old. */ void delete(List **head, List *where, List *old) { if(where == 0){ *head = old->next; return; } where->next = old->next; } banksize(int base) { ulong va; if(&end > (int *)((KZERO|1024L*1024L)-BY2PG)) return 0; va = UZERO; /* user page 1 is free to play with */ putmmu(va, PTEVALID|(base+0)*1024L*1024L/BY2PG); *(ulong*)va = 0; /* 0 at 0M */ putmmu(va, PTEVALID|(base+1)*1024L*1024L/BY2PG); *(ulong*)va = 1; /* 1 at 1M */ putmmu(va, PTEVALID|(base+4)*1024L*1024L/BY2PG); *(ulong*)va = 4; /* 4 at 4M */ putmmu(va, PTEVALID|(base+0)*1024L*1024L/BY2PG); if(*(ulong*)va == 0) return 16; putmmu(va, PTEVALID|(base+1)*1024L*1024L/BY2PG); if(*(ulong*)va == 1) return 4; putmmu(va, PTEVALID|(base+0)*1024L*1024L/BY2PG); if(*(ulong*)va == 4) return 1; return 0; } Conf conf; void confinit(void) { int mul; conf.nmach = 1; if(conf.nmach > MAXMACH) panic("confinit"); bank[0] = banksize(0); bank[1] = banksize(16); conf.npage0 = (bank[0]*1024*1024)/BY2PG; conf.base0 = 0; conf.npage1 = (bank[1]*1024*1024)/BY2PG; conf.base1 = 16*1024*1024; conf.npage = conf.npage0+conf.npage1; conf.maxialloc = (4*1024*1024-256*1024-BY2PG); mul = 1 + (conf.npage1>0); conf.nproc = 50*mul; conf.npgrp = 12*mul; conf.npte = 700*mul; conf.nmod = 400*mul; conf.nalarm = 1000; conf.norig = 150*mul; conf.nchan = 200*mul; conf.nenv = 100*mul; conf.nenvchar = 8000*mul; conf.npgenv = 200*mul; conf.nmtab = 50*mul; conf.nmount = 80*mul; conf.nmntdev = 10*mul; conf.nmntbuf = conf.nmntdev+3; conf.nmnthdr = 2*conf.nmntdev; conf.nstream = 40 + 32*mul; conf.nqueue = 5 * conf.nstream; conf.nblock = 24 * conf.nstream; conf.nsrv = 16*mul; /* was 32 */ conf.nbitmap = 300*mul; conf.nbitbyte = 300*1024*mul; if(*(uchar*)MOUSE & (1<<4)) conf.nbitbyte *= 2; /* ldepth 1 */ conf.nfont = 10*mul; conf.nurp = 32; conf.nasync = 1; conf.npipe = conf.nstream/2; conf.nservice = 3*mul; /* was conf.nproc/5 */ conf.nfsyschan = 31 + conf.nchan/20; conf.copymode = 0; /* copy on write */ } /* * set up floating point for a new process */ void procsetup(Proc *p) { #ifdef asdf long fpnull; fpnull = 0; splhi(); m->fpstate = FPinit; p->fpstate = FPinit; fprestore((FPsave*)&fpnull); spllo(); #endif panic("procsetup"); } /* * Save the part of the process state. */ void procsave(uchar *state, int len) { panic("procsave"); #ifdef asdf Balu *balu; if(len < sizeof(Balu)) panic("save state too small"); balu = (Balu *)state; fpsave(&u->fpsave); if(u->fpsave.type){ if(u->fpsave.size > sizeof u->fpsave.junk) panic("fpsize %d max %d\n", u->fpsave.size, sizeof u->fpsave.junk); fpregsave(u->fpsave.reg); u->p->fpstate = FPactive; m->fpstate = FPdirty; } if(BALU->cr0 != 0xFFFFFFFF) /* balu busy */ memcpy(balu, BALU, sizeof(Balu)); else{ balu->cr0 = 0xFFFFFFFF; BALU->cr0 = 0xFFFFFFFF; } #endif } /* * Restore what procsave() saves * * Procsave() makes sure that what state points to is long enough */ void procrestore(Proc *p, uchar *state) { panic("procrestore"); #ifdef asdf Balu *balu; balu = (Balu *)state; if(p->fpstate != m->fpstate){ if(p->fpstate == FPinit){ u->p->fpstate = FPinit; fprestore(&initfp); m->fpstate = FPinit; }else{ fpregrestore(u->fpsave.reg); fprestore(&u->fpsave); m->fpstate = FPdirty; } } if(balu->cr0 != 0xFFFFFFFF) /* balu busy */ memcpy(BALU, balu, sizeof balu); #endif }
A ss/malloc.h => ss/malloc.h +15 -0
@@ 0,0 1,15 @@ struct tbl_entry { struct tbl_entry *next; /* free list */ int *data; /* data */ }; struct table { int size; /* # entries */ struct tbl_entry *entries; /* the entries */ struct tbl_entry *free; /* the free list */ }; void *tbl_alloc(struct table *, int); void tbl_free(struct table *, void *); int tbl_index(struct table *, void *); void *tbl_data(struct table *, int);
A ss/mem.h => ss/mem.h +106 -0
@@ 0,0 1,106 @@ /* * Memory and machine-specific definitions. Used in C and assembler. */ /* * Sizes */ #define BI2BY 8 /* bits per byte */ #define BI2WD 32 /* bits per word */ #define BY2WD 4 /* bytes per word */ #define BY2PG 4096 /* bytes per page */ #define WD2PG (BY2PG/BY2WD) /* words per page */ #define PGSHIFT 12 /* log(BY2PG) */ #define MAXMACH 1 /* max # cpus system can run */ /* * Time */ #define HZ (60) /* clock frequency */ #define MS2HZ (1000/HZ) /* millisec per clock tick */ #define TK2SEC(t) ((t)/HZ) /* ticks to seconds */ #define TK2MS(t) ((((ulong)(t))*1000)/HZ) /* ticks to milliseconds */ #define MS2TK(t) ((((ulong)(t))*HZ)/1000) /* milliseconds to ticks */ /* * SR bits */ #define SUPER 0x2000 #define SPL(n) (n<<8) /* * CACR */ #define CCLEAR 0x08 #define CENABLE 0x01 /* * Magic registers */ #define MACH 28 /* R28 is m-> */ #define USER 27 /* R27 is u-> */ /* * Fundamental addresses */ #define USERADDR 0x80000000 #define UREGADDR (USERADDR+BY2PG-(2+4+2+(8+8+1)*BY2WD)) /* * Devices poked during bootstrap */ #define TACADDR 0x40600000 #define MOUSE 0x40200000 /* * MMU */ #define VAMASK 0x1FFFFFFF /* * MMU entries */ #define PTEVALID (1<<31) #define PTEWRITE (1<<30) #define PTEKERNEL (1<<29) #define PTENOCACHE (1<<28) #define PTEMAINMEM (0<<26) #define PTEIO (1<<26) #define PTEACCESS (1<<25) #define PTEMODIFY (1<<24) #define PTERONLY 0 /* BUG */ #define INVALIDPTE 0 #define PPN(pa) ((pa>>12)&0xFFFF) #define KMAP ((unsigned long *)0xD0000000) #define UMAP ((unsigned long *)0x50000000) /* * Virtual addresses */ #define VTAG(va) ((va>>22)&0x03F) #define VPN(va) ((va>>13)&0x1FF) #define PARAM ((char*)0x40500000) #define TLBFLUSH_ 0x01 /* * Address spaces */ #define UZERO 0x00000000 /* base of user address space */ #define UTZERO (UZERO+BY2PG) /* first address in user text */ #define TSTKTOP 0x10000000 /* end of new stack in sysexec */ #define USTKTOP (TSTKTOP-100*BY2PG) /* byte just beyond user stack */ #define KZERO 0x10000000 /* base of kernel address space */ #define KTZERO (KZERO+4*BY2PG) /* first address in kernel text */ #define USTACKSIZE (4*1024*1024) /* size of user stack */ #define NSEG 5 #define MACHSIZE 4096
A ss/mmu.c => ss/mmu.c +159 -0
@@ 0,0 1,159 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" struct { Lock; int init; KMap *free; KMap arena[4*1024*1024/BY2PG]; /* kernel mmu maps up to 4MB */ }kmapalloc; /* * Called splhi, not in Running state */ void mapstack(Proc *p) { ulong tlbvirt, tlbphys; ulong next; MMU *mm, *mn, *me; if(p->upage->va != (USERADDR|(p->pid&0xFFFF))) panic("mapstack %d 0x%lux 0x%lux", p->pid, p->upage->pa, p->upage->va); tlbvirt = USERADDR; tlbphys = PPN(p->upage->pa) | PTEVALID | PTEKERNEL; putkmmu(tlbvirt, tlbphys); u = (User*)USERADDR; /* * if not a kernel process and this process was not the * last process on this machine, flush & preload mmu */ if(!p->kp && p!=m->lproc){ flushmmu(); /* * preload the MMU with the last (up to) NMMU user entries * previously faulted into it for this process. */ mn = &u->mc.mmu[u->mc.next&(NMMU-1)]; me = &u->mc.mmu[NMMU]; if(u->mc.next >= NMMU){ for(mm = mn; mm < me; mm++) UMAP[mm->va] = mm->pa; } for(mm = u->mc.mmu; mm < mn; mm++) UMAP[mm->va] = mm->pa; m->lproc = p; } } void putkmmu(ulong tlbvirt, ulong tlbphys) { if(!(tlbvirt&KZERO)) panic("putkmmu"); tlbvirt &= ~KZERO; KMAP[(tlbvirt&0x003FE000L)>>2] = tlbphys; } void putmmu(ulong tlbvirt, ulong tlbphys) { if(tlbvirt&KZERO) panic("putmmu"); tlbphys |= VTAG(tlbvirt)<<24; tlbvirt = (tlbvirt&0x003FE000L)>>2; if(u){ MMU *mp; int s; s = splhi(); mp = &(u->mc.mmu[u->mc.next&(NMMU-1)]); mp->pa = tlbphys; mp->va = tlbvirt; u->mc.next++; splx(s); } UMAP[tlbvirt] = tlbphys; } void flushmmu(void) { flushcpucache(); *PARAM &= ~TLBFLUSH_; *PARAM |= TLBFLUSH_; } void clearmmucache(void) { if(u == 0) panic("flushmmucache"); u->mc.next = 0; } void kmapinit(void) { KMap *k; int i, e; if(kmapalloc.init == 0){ k = &kmapalloc.arena[0]; k->va = KZERO|(4*1024*1024-256*1024-BY2PG); k->next = 0; kmapalloc.free = k; kmapalloc.init = 1; return; } e = (4*1024*1024 - 256*1024)/BY2PG; /* screen lives at top 256K */ i = (((ulong)ialloc(0, 0))&~KZERO)/BY2PG; print("%lud free map registers\n", e-i); kmapalloc.free = 0; for(k=&kmapalloc.arena[i]; i<e; i++,k++){ k->va = i*BY2PG|KZERO; kunmap(k); } } KMap* kmap(Page *pg) { KMap *k; lock(&kmapalloc); k = kmapalloc.free; if(k == 0){ dumpstack(); panic("kmap"); } kmapalloc.free = k->next; unlock(&kmapalloc); k->pa = pg->pa; putkmmu(k->va, PPN(k->pa) | PTEVALID | PTEKERNEL); return k; } void kunmap(KMap *k) { k->pa = 0; lock(&kmapalloc); k->next = kmapalloc.free; kmapalloc.free = k; putkmmu(k->va, INVALIDPTE); unlock(&kmapalloc); } void invalidateu(void) { putkmmu(USERADDR, INVALIDPTE); }
A ss/screen.c => ss/screen.c +407 -0
@@ 0,0 1,407 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "io.h" #include "ureg.h" #include "errno.h" #include <libg.h> #include <gnot.h> #define MINX 8 extern GFont defont0; GFont *defont; struct{ Point pos; int bwid; }out; void duartinit(void); int duartacr; int duartimr; void (*kprofp)(ulong); GBitmap gscreen = { (ulong*)((4*1024*1024-256*1024)|KZERO), /* BUG */ 0, 64, 0, 0, 0, 1024, 1024, 0 }; void screeninit(void) { duartinit(); /* * Read HEX switch to set ldepth */ if(*(uchar*)MOUSE & (1<<4)) gscreen.ldepth = 1; defont = &defont0; /* save space; let bitblt do the conversion work */ gbitblt(&gscreen, Pt(0, 0), &gscreen, gscreen.r, 0); out.pos.x = MINX; out.pos.y = 0; out.bwid = defont0.info[' '].width; } void screenputc(int c) { char buf[2]; int nx; if(c == '\n'){ out.pos.x = MINX; out.pos.y += defont0.height; if(out.pos.y > gscreen.r.max.y-defont0.height) out.pos.y = gscreen.r.min.y; gbitblt(&gscreen, Pt(0, out.pos.y), &gscreen, Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height), 0); }else if(c == '\t'){ out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; if(out.pos.x >= gscreen.r.max.x) screenputc('\n'); }else if(c == '\b'){ if(out.pos.x >= out.bwid+MINX){ out.pos.x -= out.bwid; screenputc(' '); out.pos.x -= out.bwid; } }else{ if(out.pos.x >= gscreen.r.max.x-out.bwid) screenputc('\n'); buf[0] = c&0x7F; buf[1] = 0; out.pos = gbitbltstring(&gscreen, out.pos, defont, buf, S); } } /* * Register set for half the duart. There are really two sets. */ struct Duart{ uchar mr1_2; /* Mode Register Channels 1 & 2 */ uchar sr_csr; /* Status Register/Clock Select Register */ uchar cmnd; /* Command Register */ uchar data; /* RX Holding / TX Holding Register */ uchar ipc_acr; /* Input Port Change/Aux. Control Register */ #define ivr ivr /* Interrupt Vector Register */ uchar is_imr; /* Interrupt Status/Interrupt Mask Register */ #define ip_opcr is_imr /* Input Port/Output Port Configuration Register */ uchar ctur; /* Counter/Timer Upper Register */ #define scc_sopbc ctur /* Start Counter Command/Set Output Port Bits Command */ uchar ctlr; /* Counter/Timer Lower Register */ #define scc_ropbc ctlr /* Stop Counter Command/Reset Output Port Bits Command */ }; enum{ CHAR_ERR =0x00, /* MR1x - Mode Register 1 */ PAR_ENB =0x00, EVEN_PAR =0x00, ODD_PAR =0x04, NO_PAR =0x10, CBITS8 =0x03, CBITS7 =0x02, CBITS6 =0x01, CBITS5 =0x00, NORM_OP =0x00, /* MR2x - Mode Register 2 */ TWOSTOPB =0x0F, ONESTOPB =0x07, ENB_RX =0x01, /* CRx - Command Register */ DIS_RX =0x02, ENB_TX =0x04, DIS_TX =0x08, RESET_MR =0x10, RESET_RCV =0x20, RESET_TRANS =0x30, RESET_ERR =0x40, RESET_BCH =0x50, STRT_BRK =0x60, STOP_BRK =0x70, RCV_RDY =0x01, /* SRx - Channel Status Register */ FIFOFULL =0x02, XMT_RDY =0x04, XMT_EMT =0x08, OVR_ERR =0x10, PAR_ERR =0x20, FRM_ERR =0x40, RCVD_BRK =0x80, BD38400 =0xCC|0x0000, BD19200 =0xCC|0x0100, BD9600 =0xBB|0x0000, BD4800 =0x99|0x0000, BD2400 =0x88|0x0000, BD1200 =0x66|0x0000, BD300 =0x44|0x0000, IM_IPC =0x80, /* IMRx/ISRx - Interrupt Mask/Interrupt Status */ IM_DBB =0x40, IM_RRDYB =0x20, IM_XRDYB =0x10, IM_CRDY =0x08, IM_DBA =0x04, IM_RRDYA =0x02, IM_XRDYA =0x01, }; uchar keymap[]={ /*80*/ 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x8e, 0x58, /*90*/ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x58, 0x58, 0x58, 0x58, /*A0*/ 0x58, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xae, 0xaf, /*B0*/ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0x80, 0xb7, 0xb8, 0xb9, 0x00, 0xbb, 0x1e, 0xbd, 0x60, 0x1f, /*C0*/ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0x58, 0xc6, 0x0a, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, /*D0*/ 0x09, 0x08, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x58, /*E0*/ 0x58, 0x58, 0xe2, 0x1b, 0x0d, 0xe5, 0x58, 0x0a, 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, /*F0*/ 0x09, 0x08, 0xb2, 0x1b, 0x0d, 0xf5, 0x81, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0xb2, }; void duartinit(void) { Duart *duart; duart = DUARTREG; /* * Keyboard */ duart[0].cmnd = RESET_RCV|DIS_TX|DIS_RX; duart[0].cmnd = RESET_TRANS; duart[0].cmnd = RESET_ERR; duart[0].cmnd = RESET_MR; duart[0].mr1_2 = CHAR_ERR|PAR_ENB|EVEN_PAR|CBITS8; duart[0].mr1_2 = NORM_OP|ONESTOPB; duart[0].sr_csr = BD4800; /* * RS232 */ duart[1].cmnd = RESET_RCV|DIS_TX|DIS_RX; duart[1].cmnd = RESET_TRANS; duart[1].cmnd = RESET_ERR; duart[1].cmnd = RESET_MR; duart[1].mr1_2 = CHAR_ERR|NO_PAR|CBITS8; duart[1].mr1_2 = NORM_OP|ONESTOPB; duart[1].sr_csr = BD9600; /* * Output port */ duart[0].ipc_acr = duartacr = 0xB7; /* allow change of state interrupt */ duart[1].ip_opcr = 0x00; duart[1].scc_ropbc = 0xFF; /* make sure the port is reset first */ duart[1].scc_sopbc = 0x04; /* dtr = 1, pp = 01 */ duart[0].is_imr = duartimr = IM_IPC|IM_RRDYB|IM_XRDYB|IM_RRDYA|IM_XRDYA; duart[0].cmnd = ENB_TX|ENB_RX; /* enable TX and RX last */ duart[1].cmnd = ENB_TX|ENB_RX; /* * Initialize keyboard */ while (!(duart[0].sr_csr & (XMT_EMT|XMT_RDY))) ; duart[0].data = 0x02; } int duartinputport(void) { Duart *duart = DUARTREG; return duart[1].ip_opcr; } void duartbaud(int b) { int x; Duart *duart = DUARTREG; x = 0; /* set */ switch(b){ case 38400: x = BD38400; break; case 19200: x = BD19200; break; case 9600: x = BD9600; break; case 4800: x = BD4800; break; case 2400: x = BD2400; break; case 1200: x = BD1200; break; case 300: x = BD300; break; default: error(Ebadarg); } if(x & 0x0100) duart[0].ipc_acr = duartacr |= 0x80; else duart[0].ipc_acr = duartacr &= ~0x80; duart[1].sr_csr = x; } void duartdtr(int val) { Duart *duart = DUARTREG; if (val) duart[1].scc_ropbc=0x01; else duart[1].scc_sopbc=0x01; } void duartbreak(int ms) { static QLock brk; Duart *duart = DUARTREG; if (ms<=0 || ms >20000) error(Ebadarg); qlock(&brk); duart[0].is_imr = duartimr &= ~IM_XRDYB; duart[1].cmnd = STRT_BRK|ENB_TX; tsleep(&u->p->sleep, return0, 0, ms); duart[1].cmnd = STOP_BRK|ENB_TX; duart[0].is_imr = duartimr |= IM_XRDYB; qunlock(&brk); } enum{ Kptime=200 }; void duartstarttimer(void) { Duart *duart; char x; duart = DUARTREG; duart[0].ctur = (Kptime)>>8; duart[0].ctlr = (Kptime)&255; duart[0].is_imr = duartimr |= IM_CRDY; x = duart[1].scc_sopbc; } void duartstoptimer(void) { Duart *duart; char x; duart = DUARTREG; x = duart[1].scc_ropbc; duart[0].is_imr = duartimr &= ~IM_CRDY; } void duartrs232intr(void) { int c; Duart *duart; duart = DUARTREG; c = getrs232o(); if(c == -1) duart[1].cmnd = DIS_TX; else duart[1].data = c; } void duartstartrs232o(void) { DUARTREG[1].cmnd = ENB_TX; duartrs232intr(); } void duartintr(Ureg *ur) { int cause, status, c; Duart *duart; duart = DUARTREG; cause = duart->is_imr; /* * I can guess your interrupt. */ /* * Is it 0? */ if(cause & IM_CRDY){ if(kprofp) (*kprofp)(ur->pc); c = duart[1].scc_ropbc; duart[0].ctur = (Kptime)>>8; duart[0].ctlr = (Kptime)&255; c = duart[1].scc_sopbc; return; } /* * Is it 1? */ if(cause & IM_RRDYA){ /* keyboard input */ status = duart->sr_csr; c = duart->data; if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) duart->cmnd = RESET_ERR; if(status & PAR_ERR) /* control word: caps lock (0x4) or repeat (0x10) */ kbdrepeat((c&0x10) == 0); else{ if(c == 0x7F) c = 0xFF; /* VIEW key (bizarre) */ if(c & 0x80) c = keymap[c&0x7F]; kbdchar(c); } } /* * Is it 2? */ if(cause & IM_RRDYB){ /* rs232 input */ status = duart[1].sr_csr; c = duart[1].data; if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) duart[1].cmnd = RESET_ERR; else rs232ichar(c); } /* * Is it 3? */ if(cause & IM_XRDYB) /* rs232 output */ duartrs232intr(); /* * Is it 4? */ if(cause & IM_XRDYA) duart[0].cmnd = DIS_TX; /* * Is it 5? */ if(cause & IM_IPC) mousebuttons((~duart[0].ipc_acr) & 7); }
A ss/stream.h => ss/stream.h +5 -0
A ss/trap.c => ss/trap.c +320 -0
@@ 0,0 1,320 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" #include "ureg.h" #include "io.h" #include "errno.h" void notify(Ureg*); void noted(Ureg**); void rfnote(Ureg**); char *regname[]={ "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7", "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", }; long ticks; char *trapname[]={ "reset isp", "reset ipc", "bus error", "address error", "illegal instruction", "zero divide", "chk, chk2 instruction", "cptrapcc, trapcc, trapv instruction", "privilege violation", "trace", "line 1010 emulator", "line 1111 emulator", "reserved", "coprocessor protocol violation", "format error", "uninitialized interrupt", "unassigned 0x40", "unassigned 0x44", "unassigned 0x48", "unassigned 0x4C", "unassigned 0x50", "unassigned 0x54", "unassigned 0x58", "unassigned 0x5C", "spurious interrupt", "level 1 autovector (tac)", "level 2 autovector (port)", "level 3 autovector (incon)", "level 4 autovector (mouse)", "level 5 autovector (uart)", "level 6 autovector (sync)", "level 7 autovector", }; char* excname(unsigned vo) { static char buf[32]; /* BUG: not reentrant! */ vo &= 0x0FFF; vo >>= 2; if(vo < sizeof trapname/sizeof(char*)) return trapname[vo]; sprint(buf, "offset 0x%ux", vo<<2); return buf; } void trap(Ureg *ur) { int user; char buf[64]; user = !(ur->sr&SUPER); if(u) u->p->pc = ur->pc; /* BUG */ if(user){ sprint(buf, "sys: trap: pc=0x%lux %s", ur->pc, excname(ur->vo)); postnote(u->p, 1, buf, NDebug); }else{ print("kernel trap vo=0x%ux pc=0x%lux\n", ur->vo, ur->pc); dumpregs(ur); exit(); } if(user && u->nnote) notify(ur); } void dumpstack(void) { ulong l, v; extern ulong etext; if(u) for(l=(ulong)&l; l<USERADDR+BY2PG; l+=4){ v = *(ulong*)l; if(KTZERO < v && v < (ulong)&etext) print("%lux=%lux\n", l, v); } } void dumpregs(Ureg *ur) { int i; ulong *l; if(u) print("registers for %s %d\n", u->p->text, u->p->pid); else print("registers for kernel\n"); print("SR=%ux PC=%lux VO=%lux, USP=%lux\n", ur->sr, ur->pc, ur->vo, ur->usp); l = &ur->r0; for(i=0; i<sizeof regname/sizeof(char*); i+=2, l+=2) print("%s\t%.8lux\t%s\t%.8lux\n", regname[i], l[0], regname[i+1], l[1]); dumpstack(); } /* * Call user, if necessary, with note */ void notify(Ureg *ur) { ulong sp; lock(&u->p->debug); if(u->nnote==0){ unlock(&u->p->debug); return; } if(u->note[0].flag!=NUser && (u->notified || u->notify==0)){ if(u->note[0].flag == NDebug) pprint("suicide: %s\n", u->note[0].msg); Die: unlock(&u->p->debug); pexit(u->note[0].msg, u->note[0].flag!=NDebug); } if(!u->notified){ if(!u->notify) goto Die; sp = ur->usp; sp -= sizeof(Ureg); u->ureg = (void*)sp; memcpy((Ureg*)sp, ur, sizeof(Ureg)); sp -= ERRLEN; memcpy((char*)sp, u->note[0].msg, ERRLEN); sp -= 3*BY2WD; *(ulong*)(sp+2*BY2WD) = sp+3*BY2WD; /* arg 2 is string */ *(ulong*)(sp+1*BY2WD) = (ulong)u->ureg; /* arg 1 is ureg* */ *(ulong*)(sp+0*BY2WD) = 0; /* arg 0 is pc */ ur->usp = sp; ur->pc = (ulong)u->notify; u->notified = 1; u->nnote--; memcpy(&u->note[0], &u->note[1], u->nnote*sizeof(Note)); } unlock(&u->p->debug); } /* * Return user to state before notify() */ void noted(Ureg **urp) { lock(&u->p->debug); if(!u->notified){ unlock(&u->p->debug); return; } u->notified = 0; memcpy(*urp, u->ureg, sizeof(Ureg)); unlock(&u->p->debug); splhi(); rfnote(urp); } #undef CHDIR /* BUG */ #include "/sys/src/libc/680209sys/sys.h" typedef long Syscall(ulong*); Syscall sysr1, sysfork, sysexec, sysgetpid, syssleep, sysexits, sysdeath, syswait; Syscall sysopen, sysclose, sysread, syswrite, sysseek, syserrstr, sysaccess, sysstat, sysfstat; Syscall sysdup, syschdir, sysforkpgrp, sysbind, sysmount, syspipe, syscreate; Syscall sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted; Syscall *systab[]={ sysr1, syserrstr, sysbind, syschdir, sysclose, sysdup, sysdeath, sysexec, sysexits, sysfork, sysforkpgrp, sysfstat, sysdeath, sysmount, sysopen, sysread, sysseek, syssleep, sysstat, syswait, syswrite, syspipe, syscreate, sysdeath, sysbrk_, sysremove, syswstat, sysfwstat, sysnotify, sysnoted, sysdeath, /* sysfilsys */ }; long syscall(Ureg *aur) { long ret; ulong sp; ulong r0; Ureg *ur; char *msg; u->p->insyscall = 1; ur = aur; u->p->pc = ur->pc; if(ur->sr & SUPER) panic("recursive system call"); /* * since the system call interface does not * guarantee anything about registers, but the fpcr is more than * just a register... BUG */ splhi(); fpsave(&u->fpsave); if(u->p->fpstate==FPactive || u->fpsave.type){ fprestore(&initfp); u->p->fpstate = FPinit; m->fpstate = FPinit; } spllo(); r0 = ur->r0; sp = ur->usp; u->nerrlab = 0; ret = -1; if(!waserror()){ if(r0 >= sizeof systab/BY2WD){ pprint("bad sys call number %d pc %lux\n", r0, ((Ureg*)UREGADDR)->pc); msg = "sys: bad sys call"; Bad: postnote(u->p, 1, msg, NDebug); error(Ebadarg); } if(sp & (BY2WD-1)){ pprint("odd sp in sys call pc %lux sp %lux\n", ((Ureg*)UREGADDR)->pc, ((Ureg*)UREGADDR)->sp); msg = "sys: odd stack"; goto Bad; } if(sp<(USTKTOP-BY2PG) || sp>(USTKTOP-5*BY2WD)) validaddr(sp, 5*BY2WD, 0); ret = (*systab[r0])((ulong*)(sp+BY2WD)); } u->nerrlab = 0; u->p->insyscall = 0; if(r0 == NOTED) /* ugly hack */ noted(&aur); /* doesn't return */ if(u->nnote){ ur->r0 = ret; notify(ur); } return ret; } #include "errstr.h" void error(int code) { strncpy(u->error, errstrtab[code], NAMELEN); nexterror(); } void errors(char *err) { strncpy(u->error, err, NAMELEN); nexterror(); } void nexterror(void) { gotolabel(&u->errlab[--u->nerrlab]); }
A ss/u.h => ss/u.h +15 -0
@@ 0,0 1,15 @@ typedef unsigned short ushort; typedef unsigned char uchar; typedef unsigned long ulong; typedef long vlong; typedef union Length Length; union Length { char clength[8]; vlong vlength; struct{ long hlength; long length; }; };
A ss/uart.c => ss/uart.c +155 -0
@@ 0,0 1,155 @@ #include "u.h" #include "lib.h" #include "mem.h" #include "dat.h" #include "fns.h" enum { /* wr 0 */ ResExtPend= 2<<3, ResTxPend= 5<<3, ResErr= 6<<3, /* wr 1 */ TxIntEna= 1<<1, RxIntDis= 0<<3, RxIntFirstEna= 1<<3, RxIntAllEna= 2<<3, /* wr 3 */ RxEna= 1, Rx5bits= 0<<6, Rx7bits= 1<<6, Rx6bits= 2<<6, Rx8bits= 3<<6, /* wr 4 */ SyncMode= 0<<2, Rx1stop= 1<<2, Rx1hstop= 2<<2, Rx2stop= 3<<2, X16= 1<<6, /* wr 5 */ TxRTS= 1<<1, TxEna= 1<<3, TxBreak= 1<<4, TxDTR= 1<<7, Tx5bits= 0<<5, Tx7bits= 1<<5, Tx6bits= 2<<5, Tx8bits= 3<<5, /* wr 9 */ IntEna= 1<<3, ResetB= 1<<6, ResetA= 2<<6, HardReset= 3<<6, /* wr 11 */ TRxCOutBR= 2, TxClockBR= 2<<3, RxClockBR= 2<<5, TRxCOI= 1<<2, /* wr 14 */ BREna= 1, BRSource= 2, /* rr 0 */ RxReady= 1, TxReady= 1<<2, RxDCD= 1<<3, RxCTS= 1<<5, RxBreak= 1<<7, /* rr 3 */ ExtPendB= 1, TxPendB= 1<<1, RxPendB= 1<<2, ExtPendA= 1<<3, TxPendA= 1<<4, RxPendA= 1<<5, }; typedef struct SCC SCC; struct SCC { uchar *ptr; /* command/pointer register in Z8530 */ uchar *data; /* data register in Z8530 */ }; SCC scc[2]; #define SCCV (0x0F000000-0x1000) #define SCCP 0xF1000000 #define PRINTING 0x4 #define MASK 0x1 void sccsetup(void) { ulong pte; pte = PTEVALID | PTEWRITE | PTEKERNEL | PTENOCACHE | PTEIO | ((SCCP>>PGSHIFT)&0xFFFF) ; putpmeg(SCCV, pte); scc[0].ptr = (uchar*)(SCCV+0); scc[0].data = (uchar*)(SCCV+2); scc[1].ptr = (uchar*)(SCCV+4); scc[1].data = (uchar*)(SCCV+6); } /* * Access registers using the pointer in register 0. * This is a bit stupid when accessing register 0. */ void sccwrreg(SCC *sp, int addr, int value) { *sp->ptr = addr; } ushort sccrdreg(SCC *sp, int addr) { *sp->ptr = addr; return *sp->ptr; } /* * non-spooling non-interrupting get and put */ int sccgetc(void) { uchar ch; SCC *sp; sp = &scc[1]; while((*sp->ptr&RxReady) == 0) ; return *sp->data; } void sccputc(int ch) { SCC *sp; sp = &scc[1]; while((*sp->ptr&TxReady)==0) ; *sp->data = ch; } void sccputs(char *s) { while(*s) sccputc(*s++); }
A ss/ureg.h => ss/ureg.h +23 -0