From c7d82362a66316c86085abfc4003b6228023eefe Mon Sep 17 00:00:00 2001 From: David du Colombier <0intro@gmail.com> Date: Sun, 23 Dec 1990 00:00:00 +0000 Subject: [PATCH] Plan 9 from Bell Labs 1990-12-23 --- gnot/mem.h | 2 +- ss/boot.c | 211 ++++ ss/boot.h | 2662 +++++++++++++++++++++++++++++++++++++++++++++++ ss/clock.c | 42 + ss/crc_16.h | 35 + ss/dat.h | 613 +++++++++++ ss/devbit.c | 1153 ++++++++++++++++++++ ss/devcons.c | 1021 ++++++++++++++++++ ss/devincon.c | 883 ++++++++++++++++ ss/devkprof.c | 177 ++++ ss/errno.h | 63 ++ ss/faultsparc.c | 98 ++ ss/fcall.h | 88 ++ ss/fns.h | 204 ++++ ss/io.h | 6 + ss/l.s | 81 ++ ss/lib.h | 112 ++ ss/lock.c | 111 ++ ss/main.c | 450 ++++++++ ss/malloc.h | 15 + ss/mem.h | 106 ++ ss/mmu.c | 159 +++ ss/screen.c | 407 ++++++++ ss/stream.h | 5 + ss/trap.c | 320 ++++++ ss/u.h | 15 + ss/uart.c | 155 +++ ss/ureg.h | 23 + 28 files changed, 9216 insertions(+), 1 deletion(-) create mode 100644 ss/boot.c create mode 100644 ss/boot.h create mode 100644 ss/clock.c create mode 100644 ss/crc_16.h create mode 100644 ss/dat.h create mode 100644 ss/devbit.c create mode 100644 ss/devcons.c create mode 100644 ss/devincon.c create mode 100644 ss/devkprof.c create mode 100644 ss/errno.h create mode 100644 ss/faultsparc.c create mode 100644 ss/fcall.h create mode 100644 ss/fns.h create mode 100644 ss/io.h create mode 100644 ss/l.s create mode 100644 ss/lib.h create mode 100644 ss/lock.c create mode 100644 ss/main.c create mode 100644 ss/malloc.h create mode 100644 ss/mem.h create mode 100644 ss/mmu.c create mode 100644 ss/screen.c create mode 100644 ss/stream.h create mode 100644 ss/trap.c create mode 100644 ss/u.h create mode 100644 ss/uart.c create mode 100644 ss/ureg.h diff --git a/gnot/mem.h b/gnot/mem.h index 79a07e02a157d492695d87c8aa7f72bed7840150..0a10891a08d8fbc2c630e8ffa6a7bd905ae0d83f 100644 --- a/gnot/mem.h +++ b/gnot/mem.h @@ -37,7 +37,7 @@ #define CENABLE 0x01 /* - * Magic registers + * Magic registers (unused in current system) */ #define MACH A5 /* A5 is m-> */ diff --git a/ss/boot.c b/ss/boot.c new file mode 100644 index 0000000000000000000000000000000000000000..ab395d7c61aade1efeead7d6dbb74123af67bbfb --- /dev/null +++ b/ss/boot.c @@ -0,0 +1,211 @@ +#include +#include +#include + +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); +} diff --git a/ss/boot.h b/ss/boot.h new file mode 100644 index 0000000000000000000000000000000000000000..454cadf68ff794577ed9778e7e2938250bac4981 --- /dev/null +++ b/ss/boot.h @@ -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, +}; diff --git a/ss/clock.c b/ss/clock.c new file mode 100644 index 0000000000000000000000000000000000000000..2b5e3eb278b648026d1b7e85a0651dc25c00cecd --- /dev/null +++ b/ss/clock.c @@ -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; iticks++; + 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); + } +} diff --git a/ss/crc_16.h b/ss/crc_16.h new file mode 100644 index 0000000000000000000000000000000000000000..9a5ad04f4919762732d82919c54bb5298db8b54b --- /dev/null +++ b/ss/crc_16.h @@ -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 diff --git a/ss/dat.h b/ss/dat.h new file mode 100644 index 0000000000000000000000000000000000000000..35bb71881bf26d4696e57332c25053ce139afb77 --- /dev/null +++ b/ss/dat.h @@ -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<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 diff --git a/ss/devbit.c b/ss/devbit.c new file mode 100644 index 0000000000000000000000000000000000000000..cff8f298615de6a19b7423b00f1d03eb93e4bbf0 --- /dev/null +++ b/ss/devbit.c @@ -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 +#include + +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; ildepth = -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 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]; ildepth >= 0) + bitfree(bp); + for(i=1,fp=&bit.font[1]; ibits = 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 || minyr.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; yr.min.x, y)); + q += (src->r.min.x&((sizeof(ulong))*ws-1))/ws; + for(x=0; xoffset==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; yqid.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; in = 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 || minyr.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<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( ; yr, 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 || minyr.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; yr.min.x, y)); + q += (dst->r.min.x&((sizeof(ulong))*ws-1))/ws; + for(x=0; xbase[-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; +} diff --git a/ss/devcons.c b/ss/devcons.c new file mode 100644 index 0000000000000000000000000000000000000000..f1c25ca95bc8a7d6672e81124147932dcb46ed29 --- /dev/null +++ b/ss/devcons.c @@ -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*ip->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; iqid); + 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; +} diff --git a/ss/devincon.c b/ss/devincon.c new file mode 100644 index 0000000000000000000000000000000000000000..035cbd7059c1705d195dff793672d2a651472b5a --- /dev/null +++ b/ss/devincon.c @@ -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; icmd = 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; +} diff --git a/ss/devkprof.c b/ss/devkprof.c new file mode 100644 index 0000000000000000000000000000000000000000..76ca8bb1156cf87b79a44da4500a75cbab4f20d6 --- /dev/null +++ b/ss/devkprof.c @@ -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>= LRES; + timerbuf[pc]++; + } else + timerbuf[1]++; +} diff --git a/ss/errno.h b/ss/errno.h new file mode 100644 index 0000000000000000000000000000000000000000..d4d38c70c104e656ff543b901ee2290f7508c301 --- /dev/null +++ b/ss/errno.h @@ -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 */ +}; diff --git a/ss/faultsparc.c b/ss/faultsparc.c new file mode 100644 index 0000000000000000000000000000000000000000..c7c2dcbc0e7d677e9a2f84fe8b025f0a8c8543d5 --- /dev/null +++ b/ss/faultsparc.c @@ -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; +} diff --git a/ss/fcall.h b/ss/fcall.h new file mode 100644 index 0000000000000000000000000000000000000000..f81ca5ea8133853dfb67ff92a623e5df4a22eb1d --- /dev/null +++ b/ss/fcall.h @@ -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); diff --git a/ss/fns.h b/ss/fns.h new file mode 100644 index 0000000000000000000000000000000000000000..57b4b008b89f9e7d085e110df2e06c59befd4dec --- /dev/null +++ b/ss/fns.h @@ -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) diff --git a/ss/io.h b/ss/io.h new file mode 100644 index 0000000000000000000000000000000000000000..b7d26941b491ebc66b1ce68ca44d3d87760456f5 --- /dev/null +++ b/ss/io.h @@ -0,0 +1,6 @@ +typedef struct Duart Duart; + +#define SYNCREG ((char*)0x40400000) +#define DISPLAYRAM 0x02000000 +#define DUARTREG ((Duart*)0x40100000) +#define PORT ((uchar *)0x40300000) diff --git a/ss/l.s b/ss/l.s new file mode 100644 index 0000000000000000000000000000000000000000..0cc9279ea79230705ba0867a598f60bbcfeeb485 --- /dev/null +++ b/ss/l.s @@ -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 diff --git a/ss/lib.h b/ss/lib.h new file mode 100644 index 0000000000000000000000000000000000000000..f3bbfe09695202b9371f0acbea8543106a9f2b0b --- /dev/null +++ b/ss/lib.h @@ -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]; +}; diff --git a/ss/lock.c b/ss/lock.c new file mode 100644 index 0000000000000000000000000000000000000000..b1e98cecb094c5b2486a00c20804ea1130060e41 --- /dev/null +++ b/ss/lock.c @@ -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); + } +} diff --git a/ss/main.c b/ss/main.c new file mode 100644 index 0000000000000000000000000000000000000000..ce236fe98d96f780834ae59ff56f77c2e51885e5 --- /dev/null +++ b/ss/main.c @@ -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 +#include + +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<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 +} diff --git a/ss/malloc.h b/ss/malloc.h new file mode 100644 index 0000000000000000000000000000000000000000..82d145d1af301580f5d152abcfb423b117978fea --- /dev/null +++ b/ss/malloc.h @@ -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); diff --git a/ss/mem.h b/ss/mem.h new file mode 100644 index 0000000000000000000000000000000000000000..a08b370307e3e928ea72a2ead5507cea55fb5e5d --- /dev/null +++ b/ss/mem.h @@ -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 diff --git a/ss/mmu.c b/ss/mmu.c new file mode 100644 index 0000000000000000000000000000000000000000..8e113030b7400e12d72d98362022436e037f3a26 --- /dev/null +++ b/ss/mmu.c @@ -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]; iva = 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); +} diff --git a/ss/screen.c b/ss/screen.c new file mode 100644 index 0000000000000000000000000000000000000000..41bd4f00ae98b62b7bd587d6fe928246eb4798d8 --- /dev/null +++ b/ss/screen.c @@ -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 +#include + +#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); +} diff --git a/ss/stream.h b/ss/stream.h new file mode 100644 index 0000000000000000000000000000000000000000..8f9ef67ca3e3146dec79bca8fe4501c52a06e113 --- /dev/null +++ b/ss/stream.h @@ -0,0 +1,5 @@ +extern Qinfo asyncinfo; + +void streaminit0(void){ + newqinfo(&asyncinfo); +} diff --git a/ss/trap.c b/ss/trap.c new file mode 100644 index 0000000000000000000000000000000000000000..6b6fea9099eec085fb440fbee129efabf8aa6318 --- /dev/null +++ b/ss/trap.c @@ -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; lp->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; ip->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]); +} diff --git a/ss/u.h b/ss/u.h new file mode 100644 index 0000000000000000000000000000000000000000..81dfccf482a2af1e3a96426b21223e1c14af86d6 --- /dev/null +++ b/ss/u.h @@ -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; + }; +}; diff --git a/ss/uart.c b/ss/uart.c new file mode 100644 index 0000000000000000000000000000000000000000..33cb8d1071f96dbdd5875635424ea73bd548e4a9 --- /dev/null +++ b/ss/uart.c @@ -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++); +} diff --git a/ss/ureg.h b/ss/ureg.h new file mode 100644 index 0000000000000000000000000000000000000000..e6a9c2271029a74976b9515f582b047e38db5b40 --- /dev/null +++ b/ss/ureg.h @@ -0,0 +1,23 @@ +struct Ureg +{ + ulong r0; + ulong r1; + ulong r2; + ulong r3; + ulong r4; + ulong r5; + ulong r6; + ulong r7; + ulong a0; + ulong a1; + ulong a2; + ulong a3; + ulong a4; + ulong a5; + ulong a6; + ulong sp; + ulong usp; + ushort sr; + ulong pc; + ushort vo; +};