~kris/9p

9hist

0345182dca336d00b8de6d82307ac8c4207ecd57 — David du Colombier 36 years ago 70a2980
Plan 9 from Bell Labs 1990-06-01
M gnot/boot.c => gnot/boot.c +15 -0
@@ 31,6 31,21 @@ main(int argc, char *argv[])
	sendmsg(cfd, "config 1 16");

	/*
	 *  fork a process to hold the incon 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 via r70, leave the
	 *  incon ctl channel open
	 */

M gnot/boot.h => gnot/boot.h +464 -432
@@ 1,6 1,6 @@
ulong bootcode[]={
	0x00000107,
	0x0000200e,
	0x0000208e,
	0x000003f4,
	0x00000130,
	0x00000000,


@@ 13,476 13,514 @@ ulong bootcode[]={
	0x00142f2f,
	0x0014610c,
	0x2f006100,
	0x045a4fef,
	0x04904fef,
	0x001c4e75,
	0x4fefffc8,
	0x42a7486e,
	0x81126100,
	0x1fd04878,
	0x204a4878,
	0x0001486e,
	0x811a6100,
	0x1fc44878,
	0x203e4878,
	0x0001486e,
	0x81226100,
	0x1fb84878,
	0x20324878,
	0x0002486e,
	0x812a6100,
	0x1fac2f40,
	0x20262f40,
	0x00544aaf,
	0x00546c0a,
	0x486e8131,
	0x6100038e,
	0x610003c4,
	0x588f486e,
	0x81402f2f,
	0x00586100,
	0x0350486e,
	0x0386486e,
	0x814b2f2f,
	0x00606100,
	0x03444878,
	0x0002486e,
	0x81576100,
	0x1f744a80,
	0x42e72f40,
	0x006a44df,
	0x6c0a486e,
	0x81616100,
	0x0354588f,
	0x037a6100,
	0x1fea4fef,
	0x003072ff,
	0xb2806700,
	0x03664281,
	0xb2806700,
	0x03502f2f,
	0x00346100,
	0x1fb6588f,
	0x48780002,
	0x486e8173,
	0x61001f52,
	0x2f400074,
	0x4aaf0074,
	0x6c0a486e,
	0x817c6100,
	0x0334588f,
	0x486e818d,
	0x2f2f0078,
	0x610002f6,
	0x486e81a2,
	0x610003ee,
	0x2f2f0080,
	0x61001f04,
	0x486e81bd,
	0x610003de,
	0x422e84de,
	0x486f005c,
	0x486e84de,
	0x61000fba,
	0x2f002f40,
	0x008c486f,
	0x00682f2f,
	0x00946100,
	0x1f04b0af,
	0x0094670a,
	0x486e81c4,
	0x610002de,
	0x486e8157,
	0x61001fcc,
	0x4a8042e7,
	0x2f40003a,
	0x44df6c0a,
	0x486e8161,
	0x61000368,
	0x588f4878,
	0x001c486f,
	0x00742f2f,
	0x00a06100,
	0x1ede2f40,
	0x00a04aaf,
	0x00a06e0a,
	0x486e81ce,
	0x610002ba,
	0x588f2f2f,
	0x00a0486e,
	0x0002486e,
	0x81736100,
	0x1faa2f40,
	0x00444aaf,
	0x00446c0a,
	0x486e817c,
	0x61000348,
	0x588f486e,
	0x818d2f2f,
	0x00486100,
	0x030a486e,
	0x81a26100,
	0x04022f2f,
	0x00506100,
	0x1f56486e,
	0x81bd6100,
	0x03f2422e,
	0x84de486f,
	0x00846100,
	0x170a4a80,
	0x6638102f,
	0x008b49c0,
	0x2f00102f,
	0x008e49c0,
	0x2f00102f,
	0x009149c0,
	0x2f00102f,
	0x009449c0,
	0x2f002f2f,
	0x00bc486e,
	0x81d76100,
	0x0348486e,
	0x81fa6100,
	0x02704fef,
	0x001c0c2e,
	0x000184de,
	0x002c486e,
	0x84de6100,
	0x100c2f00,
	0x2f40005c,
	0x486f0038,
	0x2f2f0064,
	0x61001f62,
	0xb0af0064,
	0x670a486e,
	0x82056100,
	0x025c588f,
	0x486e820e,
	0x61000322,
	0x1d7c0002,
	0x84de1d7c,
	0x007684e8,
	0x486f008c,
	0x81c46100,
	0x02f2588f,
	0x4878001c,
	0x486f0044,
	0x2f2f0070,
	0x61001f36,
	0x2f400070,
	0x4aaf0070,
	0x6e0a486e,
	0x81ce6100,
	0x02ce588f,
	0x2f2f0070,
	0x486e84de,
	0x61000ef6,
	0x2f002f40,
	0x00bc486f,
	0x00982f2f,
	0x00c46100,
	0x1e40b0af,
	0x00c4670a,
	0x486e8219,
	0x6100021a,
	0x588f4878,
	0x001c486f,
	0x00a42f2f,
	0x00d06100,
	0x1e1a2f40,
	0x00d04aaf,
	0x00d06e0a,
	0x486e8227,
	0x610001f6,
	0x588f2f2f,
	0x00d0486e,
	0x84de486f,
	0x00b46100,
	0x16464a80,
	0x660a486e,
	0x82346100,
	0x01d8588f,
	0x0c2e0003,
	0x486f0054,
	0x6100175c,
	0x4a806638,
	0x102f005b,
	0x49c02f00,
	0x102f005e,
	0x49c02f00,
	0x102f0061,
	0x49c02f00,
	0x102f0064,
	0x49c02f00,
	0x2f2f008c,
	0x486e81d7,
	0x6100035c,
	0x486e81fa,
	0x61000284,
	0x4fef001c,
	0x0c2e0001,
	0x84de670a,
	0x486e8243,
	0x610001c6,
	0x588f4a6e,
	0x84e2671c,
	0x302e84e2,
	0x48c02f00,
	0x486e8250,
	0x6100027e,
	0x486e825a,
	0x610001a6,
	0x4fef000c,
	0x486e8267,
	0x6100026a,
	0x486e8275,
	0x486e826f,
	0x486f00c4,
	0x6100032a,
	0x486e8205,
	0x61000270,
	0x588f486e,
	0x820e6100,
	0x03361d7c,
	0x000284de,
	0x1d7c0076,
	0x84e8486f,
	0x005c486e,
	0x84de6100,
	0x0f482f00,
	0x2f40008c,
	0x486f0068,
	0x2f2f0094,
	0x61001e9e,
	0xb0af0094,
	0x670a486e,
	0x82196100,
	0x022e588f,
	0x4878001c,
	0x486f0074,
	0x2f2f00a0,
	0x61001e72,
	0x2f4000a0,
	0x4aaf00a0,
	0x6e0a486e,
	0x82276100,
	0x020a588f,
	0x2f2f00a0,
	0x486e84de,
	0x486f0084,
	0x61001698,
	0x4a80660a,
	0x486e8234,
	0x610001ec,
	0x588f0c2e,
	0x000384de,
	0x670a486e,
	0x82436100,
	0x01da588f,
	0x4a6e84e2,
	0x671c302e,
	0x84e248c0,
	0x2f00486e,
	0x82506100,
	0x0292486e,
	0x825a6100,
	0x01ba4fef,
	0x000c486e,
	0x82676100,
	0x027e486e,
	0x8275486e,
	0x826f486f,
	0x00946100,
	0x033e4878,
	0x01b64878,
	0x0001486f,
	0x00a06100,
	0x1dc04a80,
	0x42e72f40,
	0x00c244df,
	0x6c0a486e,
	0x827c6100,
	0x017a588f,
	0x2f2f00cc,
	0x486e8283,
	0x486f00ac,
	0x61000308,
	0x486f00b0,
	0x61000e3c,
	0x588f2f00,
	0x486f00b4,
	0x2f2f00d4,
	0x61001db2,
	0x2f00486f,
	0x00c06100,
	0x0e22588f,
	0x221fb280,
	0x670a486e,
	0x82866100,
	0x0136588f,
	0x2f2f00d8,
	0x61001d58,
	0x486e8292,
	0x486e828c,
	0x486f00c8,
	0x610002bc,
	0x487801b6,
	0x48780001,
	0x486f00d0,
	0x61001d6e,
	0x486e8299,
	0x61001d3e,
	0x4a8042e7,
	0x2f4000f2,
	0x2f4000f6,
	0x44df6c0a,
	0x486e827c,
	0x61000166,
	0x486e82a1,
	0x610000f8,
	0x588f2f2f,
	0x00fc486e,
	0x8283486f,
	0x00dc6100,
	0x02f4486f,
	0x0100486e,
	0x82a8486f,
	0x00e06100,
	0x0dea588f,
	0x0286486f,
	0x00e46100,
	0x0dba588f,
	0x2f00486f,
	0x00e42f2f,
	0x01046100,
	0x1d542f00,
	0x486f00f0,
	0x61000dd0,
	0x00e82f2f,
	0x01086100,
	0x1d302f00,
	0x486f00f4,
	0x61000da0,
	0x588f221f,
	0xb280670a,
	0x486e8286,
	0x61000122,
	0x486e82ab,
	0x610000b4,
	0x588f2f2f,
	0x01086100,
	0x1d06486e,
	0x8292486e,
	0x828c486f,
	0x00f86100,
	0x02a84878,
	0x01b64878,
	0x0001486e,
	0x82996100,
	0x1cec4a80,
	0x42e72f40,
	0x012644df,
	0x6c0a486e,
	0x82a16100,
	0x00e4588f,
	0x2f2f0130,
	0x486e82a8,
	0x486f0110,
	0x61000272,
	0x486f0114,
	0x61000d68,
	0x588f2f00,
	0x486f0118,
	0x2f2f0138,
	0x61001cd2,
	0x2f00486f,
	0x01246100,
	0x0d4e588f,
	0x221fb280,
	0x670a486e,
	0x82ab6100,
	0x00a0588f,
	0x2f2f013c,
	0x61001c84,
	0x486e82b1,
	0x6100015e,
	0x42a7486e,
	0x82bc486e,
	0x82ba6100,
	0x0d364a80,
	0x6c08486e,
	0x82be6174,
	0x010c6100,
	0x1cd6486e,
	0x82b16100,
	0x017242a7,
	0x486e82bc,
	0x486e82ba,
	0x61000d88,
	0x4a806c0a,
	0x486e82be,
	0x61000088,
	0x588f486e,
	0x82c54878,
	0x0006486e,
	0x82c32f2f,
	0x01686100,
	0x1c664a80,
	0x01386100,
	0x1cbc4a80,
	0x6c08486e,
	0x82c66154,
	0x82c66166,
	0x588f486e,
	0x82cc6100,
	0x011c42a7,
	0x012e42a7,
	0x486e82e1,
	0x486e82d5,
	0x61000cc8,
	0x61000d18,
	0x486e82e6,
	0x61364fef,
	0x01884e75,
	0x598f2f2f,
	0x000c6100,
	0x0cc62f00,
	0x2f400008,
	0x2f2f0014,
	0x2f2f0014,
	0x61001c2e,
	0xb0af0010,
	0x67082f2f,
	0x001c6108,
	0x588f4fef,
	0x00144e75,
	0x4fefffc0,
	0x485742a7,
	0x61001bf0,
	0x486f0008,
	0x2f2f0050,
	0x486e82f2,
	0x48780002,
	0x6100011a,
	0x42a76174,
	0x4fef005c,
	0x4e75598f,
	0x42817021,
	0xb0816f1e,
	0x4ab61d20,
	0x83f6660e,
	0x2daf0008,
	0x1d2083f6,
	0x7001588f,
	0x4e755281,
	0x61484fef,
	0x01584e75,
	0x48790000,
	0xea606100,
	0x1c96588f,
	0x60f26000,
	0xfcac598f,
	0x2f2f000c,
	0x61000d04,
	0x2f002f40,
	0x00082f2f,
	0x00142f2f,
	0x00146100,
	0x1c78b0af,
	0x00106708,
	0x2f2f001c,
	0x6108588f,
	0x4fef0014,
	0x4e754fef,
	0xffc04857,
	0x42a76100,
	0x1c2e486f,
	0x00082f2f,
	0x0050486e,
	0x82f24878,
	0x00026100,
	0x011a42a7,
	0x61744fef,
	0x005c4e75,
	0x598f4281,
	0x7021b081,
	0x6ee24280,
	0x6f1e4ab6,
	0x1d2083f6,
	0x660e2daf,
	0x00081d20,
	0x83f67001,
	0x588f4e75,
	0x598f206f,
	0x00084282,
	0x7021b082,
	0x6f182036,
	0x52817021,
	0xb0816ee2,
	0x4280588f,
	0x4e75598f,
	0x206f0008,
	0x42827021,
	0xb0826f18,
	0x20362d20,
	0x83f6b088,
	0x660642b6,
	0x2d2083f6,
	0xb0886606,
	0x42b62d20,
	0x83f65282,
	0x7021b082,
	0x6ee8588f,
	0x4e754aaf,
	0x00046606,
	0x42a7610c,
	0x588f486e,
	0x833e6104,
	0x52827021,
	0xb0826ee8,
	0x588f4e75,
	0x518f7220,
	0x4a816d22,
	0x2eb61d20,
	0x83f64a97,
	0x67122f41,
	0x000442b6,
	0x4aaf0004,
	0x660642a7,
	0x610c588f,
	0x486e833e,
	0x6104588f,
	0x4e75518f,
	0x72204a81,
	0x6d222eb6,
	0x1d2083f6,
	0x4eb70151,
	0x222f0004,
	0x53814a81,
	0x6cde2f2f,
	0x000c6100,
	0x1b204fef,
	0x000c4e75,
	0x4fefeff8,
	0x41ef100c,
	0x58882f08,
	0x2f2f1010,
	0x4a976712,
	0x2f410004,
	0x42b61d20,
	0x83f64eb7,
	0x0151222f,
	0x00045381,
	0x4a816cde,
	0x2f2f000c,
	0x61001b5e,
	0x4fef000c,
	0x4e754fef,
	0xeff841ef,
	0x100c5888,
	0x2f082f2f,
	0x101041ef,
	0x0010d1fc,
	0x00001000,
	0x2f08486f,
	0x00146100,
	0x01402200,
	0x41ef0018,
	0x92882f01,
	0x486f001c,
	0x48780001,
	0x61001b5a,
	0x240042e7,
	0x2f40001e,
	0x44df6c1a,
	0x52ae800e,
	0x700ab0ae,
	0x800e6e0e,
	0x48780001,
	0x6100ff5a,
	0x242f0020,
	0x588f2002,
	0x4fef1024,
	0x4e754fef,
	0xeff841ef,
	0x10105888,
	0x2f082f2f,
	0x101441ef,
	0x0010d1fc,
	0x00001000,
	0x2f08486f,
	0x00146100,
	0x00d82200,
	0x41ef0018,
	0x92882f01,
	0x486f001c,
	0x2f2f1024,
	0x61001af2,
	0x240042e7,
	0x2f40001e,
	0x44df6c1a,
	0x52ae800e,
	0x700ab0ae,
	0x800e6e0e,
	0x48780001,
	0x6100fef2,
	0x242f0020,
	0x588f2002,
	0x4fef1024,
	0x4e75518f,
	0x226f000c,
	0x2eae8012,
	0x41ef0010,
	0xd1fc0000,
	0x10002f08,
	0x486f0014,
	0x61000140,
	0x220041ef,
	0x00189288,
	0x2f01486f,
	0x001c4878,
	0x00016100,
	0x1b102400,
	0x42e72f40,
	0x001e44df,
	0x6c1a52ae,
	0x800e700a,
	0xb0ae800e,
	0x6e0e4878,
	0x00016100,
	0xff5a242f,
	0x0020588f,
	0x20024fef,
	0x10244e75,
	0x4fefeff8,
	0x41ef1010,
	0x58882f08,
	0x2f2f1014,
	0x41ef0010,
	0xd1fc0000,
	0x10002f08,
	0x486f0014,
	0x610000d8,
	0x220041ef,
	0x00189288,
	0x2f01486f,
	0x001c2f2f,
	0x10246100,
	0x1aa82400,
	0x42e72f40,
	0x001e44df,
	0x6c1a52ae,
	0x800e700a,
	0xb0ae800e,
	0x6e0e4878,
	0x00016100,
	0xfef2242f,
	0x0020588f,
	0x20024fef,
	0x10244e75,
	0x518f226f,
	0x000c2eae,
	0x801241ef,
	0x00105888,
	0x2f082f2f,
	0x00144869,
	0x10002f09,
	0x61742d6f,
	0x00108012,
	0x90af001c,
	0x4fef0018,
	0x4e75142f,
	0x0007c43c,
	0x007f1002,
	0x49c04a36,
	0x09208092,
	0x661e701e,
	0xb0ae8016,
	0x6e047001,
	0x4e75202e,
	0x2f2f0014,
	0x48691000,
	0x2f096174,
	0x2d6f0010,
	0x801290af,
	0x001c4fef,
	0x00184e75,
	0x142f0007,
	0xc43c007f,
	0x100249c0,
	0x4a360920,
	0x8092661e,
	0x701eb0ae,
	0x80166e04,
	0x70014e75,
	0x202e8016,
	0x120249c1,
	0x1d801920,
	0x809252ae,
	0x80161202,
	0x49c11d80,
	0x49c11036,
	0x19208092,
	0x52ae8016,
	0x120249c1,
	0x10361920,
	0x809249c0,
	0x2daf0008,
	0x0d20801a,
	0x42804e75,
	0x206f0004,
	0x2f2f000c,
	0x2f2f000c,
	0x48680400,
	0x2f086106,
	0x4fef0010,
	0x4e754fef,
	0xffe4226f,
	0x00282f6e,
	0x80060004,
	0x2eae8002,
	0x2d6f0020,
	0x8006202f,
	0x00245380,
	0x2d408002,
	0x101949c0,
	0x24007025,
	0xb082675a,
	0x4a82661a,
	0x42360161,
	0x8006202e,
	0x80062d6f,
	0x00048006,
	0x2d578002,
	0x4fef001c,
	0x4e75202e,
	0x8006b0ae,
	0x8002640a,
	0x1d820161,
	0x800652ae,
	0x800652ae,
	0x8012700a,
	0xb0826606,
	0x42ae8012,
	0x60b27009,
	0xb08266ac,
	0x7007d0ae,
	0x8012c0bc,
	0xfffffff8,
	0x2d408012,
	0x609a4284,
	0x74ff2a02,
	0x42af0010,
	0x141949c2,
	0x2f490028,
	0x4283702d,
	0xb082660c,
	0x74012602,
	0x141949c2,
	0x2f490028,
	0x7030b082,
	0x6e087039,
	0xb0826c00,
	0x00b64a83,
	0x67024484,
	0x702eb082,
	0x676a4a82,
	0x66065389,
	0x2f490028,
	0x2f2f0010,
	0x49c02daf,
	0x00080d20,
	0x801a4280,
	0x4e75206f,
	0x00042f2f,
	0x000c2f2f,
	0x000c4868,
	0x04002f08,
	0x61064fef,
	0x00104e75,
	0x4fefffe4,
	0x226f0028,
	0x282f002c,
	0x2f6e8006,
	0x00042eae,
	0x80022d6f,
	0x00208006,
	0x202f0024,
	0x53802d40,
	0x80021019,
	0x49c02400,
	0x7025b082,
	0x675a4a82,
	0x661a4236,
	0x01618006,
	0x202e8006,
	0x2d6f0004,
	0x80062d57,
	0x80024fef,
	0x001c4e75,
	0x202e8006,
	0xb0ae8002,
	0x640a1d82,
	0x01618006,
	0x52ae8006,
	0x52ae8012,
	0x700ab082,
	0x660642ae,
	0x801260b2,
	0x7009b082,
	0x66ac7007,
	0xd0ae8012,
	0xc0bcffff,
	0xfff82d40,
	0x8012609a,
	0x428574ff,
	0x260242af,
	0x00101419,
	0x49c22f49,
	0x0028702a,
	0xb0826600,
	0x00e02a30,
	0x49905884,
	0x24041419,
	0x49c22f49,
	0x0028702e,
	0xb082676a,
	0x4a826606,
	0x53892f49,
	0x00282f2f,
	0x00102f03,
	0x2f43001c,
	0x2f052f45,
	0x001c2f04,
	0x2f440024,
	0x2f2f0038,
	0x00242f04,
	0x2f44003c,
	0x727fc282,
	0x10361920,
	0x809249c0,
	0x20760d20,
	0x801a4e90,
	0x2a2f0028,
	0x226f0038,
	0x2a2f0024,
	0x282f0028,
	0x282f003c,
	0x262f0024,
	0x24006c16,
	0x448285af,
	0x00201419,
	0x49c22002,
	0x2f490038,
	0x4fef0010,
	0x60a8202f,
	0x003cd082,
	0x2f40003c,
	0x4fef0010,
	0x6000fef2,
	0x60a2d882,
	0x20044fef,
	0x00106000,
	0xff021019,
	0x49c02400,
	0x2f490028,
	0x702ab082,
	0x66162630,
	0x49905884,
	0x20041019,
	0x49c02400,
	0x2f490028,
	0x6000ff72,
	0x7030b082,
	0x6e00ff6a,
	0x7039b082,
	0x6d00ff62,
	0x4a836c02,
	0x42832003,
	0x2203d281,
	0xd281d081,
	0xd080d082,
	0x90bc0000,
	0x00302600,
	0x101949c0,
	0x24002f49,
	0x00287030,
	0xb0826e86,
	0x7039b082,
	0x6d804a85,
	0x6c024285,
	0x002860c8,
	0x4286702d,
	0xb082660c,
	0x74012c02,
	0x141949c2,
	0x2f490028,
	0x7030b082,
	0x6e067039,
	0xb0826c0c,
	0x4a866700,
	0xff0e4485,
	0x6000ff08,
	0x20052205,
	0xd281d281,
	0xd081d080,


@@ 491,16 529,7 @@ ulong bootcode[]={
	0x2a001019,
	0x49c02400,
	0x2f490028,
	0x60cc2004,
	0x2204d281,
	0xd281d081,
	0xd080d082,
	0x90bc0000,
	0x00302800,
	0x101949c0,
	0x24002f49,
	0x00286000,
	0xff1c4fef,
	0x60c64fef,
	0xffc4282f,
	0x004c226f,
	0x00402a2f,


@@ 1462,7 1491,7 @@ ulong bootcode[]={
	0xfa261011,
	0x49c02f00,
	0x486e830a,
	0x6100ee02,
	0x6100edc4,
	0x42804fef,
	0x000c4e75,
	0x30290004,


@@ 1923,7 1952,7 @@ ulong bootcode[]={
	0xfa981011,
	0x49c02f00,
	0x486e8318,
	0x6100e6ce,
	0x6100e690,
	0x42804fef,
	0x000c4e75,
	0x42801010,


@@ 2052,10 2081,13 @@ ulong bootcode[]={
	0x4e757006,
	0x4e404e75,
	0x70074e40,
	0x4e75700d,
	0x4e757009,
	0x4e404e75,
	0x700d4e40,
	0x4e75700e,
	0x4e404e75,
	0x700e4e40,
	0x4e75700f,
	0x700f4e40,
	0x4e757011,
	0x4e404e75,
	0x70144e40,
	0x4e750000,


@@ 2065,19 2097,19 @@ ulong bootcode[]={
	0x00000000,
	0x00000000,
	0x000d0000,
	0x29f80000,
	0x2a0e0000,
	0x2a340000,
	0x2a520000,
	0x2a560000,
	0x2a660000,
	0x2a840000,
	0x2a9e0000,
	0x2aa20000,
	0x2ac00000,
	0x2ece0000,
	0x2ef40000,
	0x2f1a0000,
	0x2a6c0000,
	0x2a820000,
	0x2aa80000,
	0x2ac60000,
	0x2aca0000,
	0x2ada0000,
	0x2af80000,
	0x2b120000,
	0x2b160000,
	0x2b340000,
	0x2f420000,
	0x2f680000,
	0x2f8e0000,
	0x00000000,
	0x00000000,
	0x00000000,


@@ 2312,6 2344,6 @@ ulong bootcode[]={
	0x0162010a,
	0x00be005a,
	0x001c0000,
	0x0002422,
	0x00024a2,
	0x,
};

M gnot/dat.h => gnot/dat.h +2 -2
@@ 287,8 287,8 @@ struct 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;
	short	pidonmach[MAXMACH];	/* TLB pid on each mmu */
	Page	*upage;			/* BUG: should be unlinked from page list */
	Seg	seg[NSEG];
	ulong	pid;


@@ 320,8 320,8 @@ struct Proc
struct User
{
	Proc	*p;
	Label	errlab[NERR];
	int	nerrlab;
	Label	errlab[NERR];
	Error	error;
	FPsave	fpsave;			/* address of this is known by vdb */
	char	elem[NAMELEN];		/* last name element from namec */

M gnot/devdk.c => gnot/devdk.c +11 -4
@@ 329,6 329,8 @@ dkstopen(Queue *q, Stream *s)
	q->other->ptr = q->ptr = lp = &dp->line[s->id];
	lp->dp = dp;
	lp->rq = q;
	if(lp->state == Lclosed)
		lp->state = Lopened;
}

/*


@@ 417,7 419,11 @@ dkoput(Queue *q, Block *bp)
	bp->rptr[0] = line;
	bp->rptr[1] = line>>8;

	PUTNEXT(dp->wq, bp);
	if(QFULL(dp->wq->next)){
		print("dk wq full\n");
		freeb(bp);
	} else
		PUTNEXT(dp->wq, bp);
}

/*


@@ 666,7 672,6 @@ dkopen(Chan *c, int omode)
					continue;
				}
				c->qid = STREAMQID(lp-dp->line, Sctlqid);
				qunlock(lp);
				break;
			}
		}


@@ 674,6 679,7 @@ dkopen(Chan *c, int omode)
			error(0, Enodev);
		streamopen(c, &dkinfo);
		pushq(c->stream, &urpinfo);
		qunlock(lp);
		break;
	case Dlistenqid:
		/*


@@ 723,7 729,7 @@ dkclose(Chan *c)
{
	Dk *dp;

	/* real closing happens in lancestclose */
	/* real closing happens in dkstclose */
	if(c->stream)
		streamclose(c);



@@ 895,7 901,7 @@ dkcall(int type, Chan *c, char *addr, char *nuser, char *machine)
	/*
	 *  only dial on virgin lines
	 */
	if(lp->state != Lclosed)
	if(lp->state != Lopened)
		error(0, Ebadarg);

	DPRINT("dkcall(line=%d, type=%d, dest=%s)\n", line, type, addr);


@@ 1198,6 1204,7 @@ dklisten(Chan *c)
		DPRINT("dklisten returns %d\n", lineno);
		return lineno;
	}
	panic("dklisten terminates strangely\n");
}

/*

M gnot/devincon.c => gnot/devincon.c +2 -0
@@ 757,6 757,8 @@ rdpackets(Incon *ip)
		}
	}	
	bp->wptr = p;
	if(bp->wptr != bp->base+3)
		nextin(ip, 0);

	if(first != ip->wi)/**/
		wakeup(&ip->kr);

M gnot/devmnt.c => gnot/devmnt.c +266 -87
@@ 9,18 9,27 @@

#include	"fcall.h"

/*
 * Easy version: multiple sessions but no intra-session multiplexing, copy the data
 */

typedef struct Mnt	Mnt;
typedef struct Mnthdr	Mnthdr;
typedef struct MntQ	MntQ;

struct Mnt
{
	Ref;			/* for number of chans, incl. mntpt but not msg */
	QLock;			/* for access */
	ulong	mntid;		/* serial # */
	Chan	*msg;		/* for reading and writing messages */
	Chan	*mntpt;		/* channel in user's name space */
	MntQ	*q;
};

struct MntQ
{
	Ref;
	QLock;			/* for access */
	MntQ	*next;		/* for allocation */
	Chan	*msg;		/* for reading and writing messages */
	Proc	*reader;	/* process reading response */
	Mnthdr	*writer;	/* queue of headers of written messages */
};

#define	BUFSIZE	(MAXFDATA+500) 	/* BUG */


@@ 37,12 46,14 @@ struct
	Mntbuf	*free;
}mntbufalloc;

typedef struct Mnthdr Mnthdr;
struct Mnthdr		/* next only meaningful when buffer isn't being used */
struct Mnthdr
{
	Mnthdr	*next;
	Mnthdr	*next;	/* in free list or writers list */
	Fcall	thdr;
	Fcall	rhdr;
	Rendez	r;
	Proc	*p;
	Mntbuf	*mbr;
};

struct


@@ 54,6 65,13 @@ struct
struct
{
	Lock;
	MntQ	*arena;
	MntQ	*free;
}mntqalloc;

struct
{
	Lock;
	long	id;
}mntid;



@@ 106,7 124,7 @@ loop:
	unlock(&mnthdralloc);
	print("no mnthdrs\n");
	if(u == 0)
		panic("mballoc");
		panic("mhalloc");
	u->p->state = Wakeme;
	alarm(1000, wakeme, u->p);
	sched();


@@ 122,6 140,45 @@ mhfree(Mnthdr *mh)
	unlock(&mnthdralloc);
}

MntQ*
mqalloc(void)
{
	MntQ *q;

	lock(&mntqalloc);
	if(q = mntqalloc.free){		/* assign = */
		mntqalloc.free = q->next;
		unlock(&mntqalloc);
		lock(q);
		q->ref = 1;
		q->writer = 0;
		q->reader = 0;
		unlock(q);
		return q;
	}
	unlock(&mntqalloc);
	panic("no mntqs\n");			/* there MUST be enough */
}

void
mqfree(MntQ *mq)
{
	Chan *msg = 0;

	lock(mq);
	if(--mq->ref == 0){
		msg = mq->msg;
		mq->msg = 0;
		lock(&mntqalloc);
		mq->next = mntqalloc.free;
		mntqalloc.free = mq;
		unlock(&mntqalloc);
	}
	unlock(mq);
	if(msg)		/* after locks are down */
		close(msg);
}

Mnt*
mntdev(int dev, int noerr)
{


@@ 130,7 187,7 @@ mntdev(int dev, int noerr)

	for(m=mnt,i=0; i<conf.nmntdev; i++,m++)		/* use a hash table some day */
		if(m->mntid == dev){
			if(m->msg == 0)
			if(m->q == 0)
				break;
			return m;
		}


@@ 145,6 202,7 @@ mntreset(void)
	int i;
	Mntbuf *mb;
	Mnthdr *mh;
	MntQ *mq;

	mnt = ialloc(conf.nmntdev*sizeof(Mnt), 0);



@@ 159,6 217,13 @@ mntreset(void)
		mh[i].next = &mh[i+1];
	mh[i].next = 0;
	mnthdralloc.free = mh;

	mq = ialloc(conf.nmntdev*sizeof(MntQ), 0);
	for(i=0; i<conf.nmntdev-1; i++)
		mq[i].next = &mq[i+1];
	mq[i].next = 0;
	mntqalloc.arena = mq;
	mntqalloc.free = mq;
}

void


@@ 170,8 235,9 @@ Chan*
mntattach(char *spec)
{
	int i;
	Mnt *m;
	Mnt *m, *mm;
	Mnthdr *mh;
	MntQ *q;
	Chan *c, *cm;
	struct bogus{
		Chan	*chan;


@@ 189,6 255,7 @@ mntattach(char *spec)
		unlock(m);
	}
	error(0, Enomntdev);

    Found:
	m->ref = 1;
	unlock(m);


@@ 199,11 266,31 @@ mntattach(char *spec)
	c->dev = m->mntid;
	m->mntpt = c;
	cm = bogus.chan;
	m->msg = cm;

	/*
	 * Look for queue to same msg channel
	 */
	q = mntqalloc.arena;
	for(i=0; i<conf.nmntdev; i++,q++)
		if(q->msg==cm){
			lock(q);
			if(q->ref && q->msg==cm){
				m->q = q;
				q->ref++;
				unlock(q);
				goto out;
			}
			unlock(q);
		}
	m->q = mqalloc();
	m->q->msg = cm;
	incref(cm);

    out:
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		mqfree(q);
		close(c);
		nexterror();
	}


@@ 213,7 300,7 @@ mntattach(char *spec)
	strcpy(mh->thdr.aname, spec);
	mntxmit(m, mh);
	c->qid = mh->rhdr.qid;
	c->mchan = m->msg;
	c->mchan = m->q->msg;
	c->mqid = c->qid;
	mhfree(mh);
	poperror();


@@ 255,10 342,10 @@ mntclone(Chan *c, Chan *nc)
	nc->mnt = c->mnt;
	nc->mchan = c->mchan;
	nc->mqid = c->qid;
	if(new)
		poperror();
	mhfree(mh);
	poperror();
	if(new)
		poperror();
	incref(m);
	return nc;
}


@@ 364,32 451,46 @@ mntcreate(Chan *c, char *name, int omode, ulong perm)
}

void	 
mntclose(Chan *c)
mntclunk(Chan *c, int t)
{
	Mnt *m;
	Mnthdr *mh;
	MntQ *q;
	int waserr;
int ne = u->nerrlab;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	mh->thdr.type = Tclunk;
	mh->thdr.type = t;
	mh->thdr.fid = c->fid;
	mntxmit(m, mh);
	waserr = 0;
	if(waserror())		/* gotta clean up as if there wasn't */
		waserr = 1;
	else
		mntxmit(m, mh);
	mhfree(mh);
	if(c == m->mntpt)
		m->mntpt = 0;
	if(decref(m) == 0){		/* BUG: need to hang up all pending i/o */
		qlock(m);
		close(m->msg);
		m->msg = 0;
		qunlock(m);
	}
	lock(m);
	if(--m->ref == 0){		/* BUG: need to hang up all pending i/o */
		q = m->q;
		m->q = 0;
		m->mntid = 0;
		unlock(m);		/* mqfree can take time */
		mqfree(q);
	}else
		unlock(m);
	if(waserr)
		nexterror();
	poperror();
}

void
mntclose(Chan *c)
{
	mntclunk(c, Tclunk);
}

long
mntreadwrite(Chan *c, void *vbuf, long n, int type)
{


@@ 458,21 559,7 @@ mntwrite(Chan *c, void *buf, long n)
void	 
mntremove(Chan *c)
{
	Mnt *m;
	Mnthdr *mh;

	m = mntdev(c->dev, 0);
	mh = mhalloc();
	if(waserror()){
		mhfree(mh);
		nexterror();
	}
	decref(m);
	mh->thdr.type = Tremove;
	mh->thdr.fid = c->fid;
	mntxmit(m, mh);
	mhfree(mh);
	poperror();
	mntclunk(c, Tremove);
}

void


@@ 550,11 637,48 @@ mntuserstr(Error *e, char *buf)
}

void
mnterrdequeue(MntQ *q, Mnthdr *mh)		/* queue is unlocked */
{
	Mnthdr *w;

	qlock(q);
	/* take self from queue if necessary */
	if(q->reader == u->p){	/* advance a writer to reader */
		w = q->writer;
		if(w){
			q->reader = w->p;
			q->writer = w->next;
			wakeup(&w->r);
		}else{
			q->reader = 0;
			q->writer = 0;
		}
	}else{
		w = q->writer;
		if(w == mh)
			q->writer = w->next;
		else{
			while(w){
				if(w->next == mh){
					w->next = mh->next;
					break;
				}
				w = w->next;
			}
		}
	}
	qunlock(q);

}
void
mntxmit(Mnt *m, Mnthdr *mh)
{
	ulong n;
	Mntbuf *mbr, *mbw;
	Chan *mntpt, *msg;
	Mnthdr *w, *ow;
	Chan *mntpt;
	MntQ *q;
	int qlocked;

	mbr = mballoc();
	mbw = mballoc();


@@ 564,6 688,7 @@ mntxmit(Mnt *m, Mnthdr *mh)
		nexterror();
	}
	n = convS2M(&mh->thdr, mbw->buf);
#ifdef	bit3
	/*
	 * Bit3 does its own multiplexing.  (Well, the file server does.)
	 * The code is different enough that it's broken out separately here.


@@ 582,8 707,8 @@ mntxmit(Mnt *m, Mnthdr *mh)
		nexterror();
	}
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){
		pprint("short write in mntxmit\n");
		error(0, Egreg);
		print("short write in mntxmit\n");
		error(0, Eshortmsg);
	}

	/*


@@ 594,20 719,20 @@ mntxmit(Mnt *m, Mnthdr *mh)
	poperror();

	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
		pprint("format error in mntxmit\n");
		error(0, Egreg);
		print("format error in mntxmit\n");
		error(0, Ebadmsg);
	}

	/*
	 * Various checks
	 */
	if(mh->rhdr.type != mh->thdr.type+1){
		pprint("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Egreg);
		print("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Ebadmsg);
	}
	if(mh->rhdr.fid != mh->thdr.fid){
		pprint("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Egreg);
		print("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Ebadmsg);
	}
	if(mh->rhdr.err){
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */


@@ 627,46 752,100 @@ mntxmit(Mnt *m, Mnthdr *mh)
	return;

    Normal:
	qlock(m);
	if((msg = m->msg) == 0){
		qunlock(m);
#endif
	q = m->q;
	if(q == 0)
		error(0, Eshutdown);
	}
	qlock(msg);
	incref(q);
	qlock(q);
	qlocked = 1;
	if(waserror()){
		qunlock(m);
		qunlock(msg);
		if(qlocked)
			qunlock(q);
		mqfree(q);
		nexterror();
	}
	if((*devtab[msg->type].write)(msg, mbw->buf, n) != n){
		pprint("short write in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Read response
	 */
	n = (*devtab[msg->type].read)(msg, mbr->buf, BUFSIZE);
	qunlock(m);
	qunlock(msg);
	if((*devtab[q->msg->type].write)(q->msg, mbw->buf, n) != n){
		print("short write in mntxmit\n");
		error(0, Eshortmsg);
	}
	if(q->reader == 0){		/* i will read */
		q->reader = u->p;
    Read:
		qunlock(q);
		qlocked = 0;
		n = (*devtab[q->msg->type].read)(q->msg, mbr->buf, BUFSIZE);
		if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
			print("format error in mntxmit\n");
			mnterrdequeue(q, mh);
			error(0, Ebadmsg);
		}
		/*
		 * Response might not be mine
		 */
		qlock(q);
		qlocked = 1;
		if(mh->rhdr.fid == mh->thdr.fid
		&& mh->rhdr.type == mh->thdr.type+1){	/* it's mine */
			q->reader = 0;
			if(w = q->writer){	/* advance a writer to reader */
				q->reader = w->p;
				q->writer = w->next;
				wakeup(&w->r);
			}
			qunlock(q);
			qlocked = 0;
			goto Respond;
		}
		/*
		 * Hand response to correct recipient
		 */
if(q->writer == 0) print("response with empty queue\n");
		for(ow=0,w=q->writer; w; ow=w,w=w->next)
			if(mh->rhdr.fid == w->thdr.fid
			&& mh->rhdr.type == w->thdr.type+1){
				Mntbuf *t;
				t = mbr;
				mbr = w->mbr;
				w->mbr = t;
				memcpy(&w->rhdr, &mh->rhdr, sizeof mh->rhdr);
				/* take recipient from queue */
				if(ow == 0)
					q->writer = w->next;
				else
					ow->next = w->next;
				wakeup(&w->r);
				goto Read;
			}
		goto Read;
	}else{
		mh->mbr = mbr;
		mh->p = u->p;
		/* put self in queue */
		mh->next = q->writer;
		q->writer = mh;
		qunlock(q);
		qlocked = 0;
		if(waserror()){		/* interrupted sleep */
			print("interrupted i/o\n");
			mnterrdequeue(q, mh);
			nexterror();
		}
		sleep(&mh->r, return0, 0);
		poperror();
		qlock(q);
		qlocked = 1;
		if(q->reader == u->p)	/* i got promoted */
			goto Read;
		mbr = mh->mbr;		/* pick up my buffer */
		qunlock(q);
		qlocked = 0;
		goto Respond;
	}

    Respond:
	mqfree(q);
	poperror();

	if(convM2S(mbr->buf, &mh->rhdr, n) == 0){
		pprint("format error in mntxmit\n");
		error(0, Egreg);
	}

	/*
	 * Various checks
	 */
	if(mh->rhdr.type != mh->thdr.type+1){
		pprint("type mismatch %d %d\n", mh->rhdr.type, mh->thdr.type+1);
		error(0, Egreg);
	}
	if(mh->rhdr.fid != mh->thdr.fid){
		pprint("fid mismatch %d %d type %d\n", mh->rhdr.fid, mh->thdr.fid, mh->rhdr.type);
		error(0, Egreg);
	}
	if(mh->rhdr.err){
		mntpt = m->mntpt;	/* unsafe, but Errors are unsafe anyway */
		if(mntpt)

M gnot/devproc.c => gnot/devproc.c +12 -2
@@ 201,6 201,7 @@ procread(Chan *c, void *va, long n)
	Seg *s;
	Orig *o;
	Page *pg;
	PTE *pte, *opte;
	int i;
	long l;
	long pid;


@@ 237,10 238,19 @@ procread(Chan *c, void *va, long n)
				unlock(o);
				error(0, Egreg);
			}
			pg = o->pte[(c->offset-o->va)>>PGSHIFT].page;
			pte = &o->pte[(c->offset-o->va)>>PGSHIFT];
			if(s->mod){
				opte = pte;
				while(pte = pte->nextmod)	/* assign = */
					if(pte->proc == p)
						break;
				if(pte == 0)
					pte = opte;
			}
			pg = pte->page;
			unlock(o);
			if(pg == 0){
				pprint("nonresident page (complain to rob)\n");
				pprint("nonresident page addr %lux (complain to rob)\n", c->offset);
				memset(a, 0, n);
			}else{
				b = (char*)(pg->pa|KZERO);

M gnot/errno.h => gnot/errno.h +2 -0
@@ 50,5 50,7 @@ enum{
	Enobitmap,	/* out of bitmap descriptors */
	Enobitstore,	/* out of bitmap storage */
	Ebadbitmap,	/* unallocated bitmap */
	Eshortmsg,	/* short message */
	Ebadmsg,	/* format error or mismatch in message */
	Egreg,		/* it's all greg's fault */
};

M gnot/fns.h => gnot/fns.h +1 -0
@@ 109,6 109,7 @@ void	putstrn(char*, long);
ulong	pwait(Waitmsg*);
int	readnum(ulong, char*, ulong, ulong, int);
void	ready(Proc*);
int	return0(void*);
void	rooterrstr(Error*, char*);
void	qlock(QLock*);
void	qunlock(QLock*);

M gnot/lock.c => gnot/lock.c +4 -1
@@ 12,6 12,8 @@
 *  	if(l->key >= 0){
 *		l->key |= 0x80;
 *		...
 *
 *	DO NOT TAKE THE ADDRESS OF l->key or the TAS will disappear.
 */
void
lock(Lock *l)


@@ 31,7 33,7 @@ lock(Lock *l)
			l->key |= 0x80;
			l->pc = ((ulong*)&i)[PCOFF];
			return;
	}
		}
	l->key = 0;
	panic("lock loop %lux pc %lux held by pc %lux\n", l, ((ulong*)&i)[PCOFF], l->pc);
}


@@ 76,6 78,7 @@ qlock(QLock *q)
	q->tail = u->p;
	u->p->qnext = 0;
	u->p->state = Queueing;
	u->p->qlock = q;	/* DEBUG */
	unlock(&q->queue);
	sched();
}

M gnot/main.c => gnot/main.c +6 -6
@@ 237,22 237,22 @@ confinit(void)
	conf.npgrp = 15;
	conf.npage = (4*1024*1024-256*1024)/BY2PG;
	conf.npte = 500;
	conf.nmod = 50;
	conf.nmod = 200;
	conf.nalarm = 1000;
	conf.norig = 50;
	conf.norig = 100;
	conf.nchan = 200;
	conf.nenv = 100;
	conf.nenvchar = 8000;
	conf.npgenv = 200;
	conf.nmtab = 50;
	conf.nmount = 100;
	conf.nmntdev = 10;
	conf.nmntbuf = 20;
	conf.nmnthdr = 20;
	conf.nmntdev = 20;
	conf.nmntbuf = 2*conf.nmntdev;
	conf.nmnthdr = 2*conf.nmntdev;
	conf.nstream = 64;
	conf.nqueue = 5 * conf.nstream;
	conf.nblock = 12 * conf.nstream;
	conf.nsrv = 32;
	conf.nbitmap = 100;
	conf.nbitbyte = 200*1024;
	conf.nbitbyte = 400*1024;
}

M gnot/proc.c => gnot/proc.c +2 -4
@@ 172,7 172,6 @@ loop:
		p->nchild = 0;
		p->child = 0;
		p->exiting = 0;
		memset(p->pidonmach, 0, sizeof p->pidonmach);
		memset(p->seg, 0, sizeof p->seg);
		lock(&pidalloc);
		p->pid = ++pidalloc.pid;


@@ 516,7 515,6 @@ again:
	lock(&p->wait.queue);	/* wait until child is finished */
	c = p->child;
	if(c == 0){
		print("pwait %d\n", p->pid);
		p->state = Inwait;
		unlock(&p->wait.queue);
		sched();


@@ 552,9 550,9 @@ DEBUG()
	for(i=0; i<conf.nproc; i++){
		p = procalloc.arena+i;
		if(p->state != Dead)
			print("%d:%s upc %lux %s ut %ld st %ld\n",
			print("%d:%s upc %lux %s ut %ld st %ld %lux\n",
				p->pid, p->text, p->pc, statename[p->state],
				p->time[0], p->time[1]);
				p->time[0], p->time[1], p->qlock);
	}
}


M gnot/screen.c => gnot/screen.c +21 -5
@@ 11,6 11,8 @@
#define	MINX	8

extern	Font	defont0;
extern	Font	defont1;
Font		*defont;

struct{
	Point	pos;


@@ 33,6 35,14 @@ void
screeninit(void)
{
	duartinit();
	/*
	 * Read HEX switch to set ldepth
	 */
	if(*(uchar*)MOUSE & (1<<4)){
		screen.ldepth = 1;
		defont = &defont1;
	}else
		defont = &defont0;
	bitblt(&screen, Pt(0, 0), &screen, screen.r, 0);
	out.pos.x = MINX;
	out.pos.y = 0;


@@ 68,7 78,7 @@ screenputc(int c)
			screenputc('\n');
		buf[0] = c&0x7F;
		buf[1] = 0;
		out.pos = string(&screen, out.pos, &defont0, buf, S);
		out.pos = string(&screen, out.pos, defont, buf, S);
	}
}



@@ 186,7 196,7 @@ duartinit(void)
	/*
	 * Output port
	 */
	duart[0].ipc_acr = 0xBF;	/* allow change	of state interrupt */
	duart[0].ipc_acr = 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 */


@@ 275,12 285,18 @@ duartintr(Ureg *ur)
	if(cause & IM_RRDYB)		/* pen input */
		c = duart[1].data;
	/*
	 * Is it 4?
	 * Is it 3?
	 */
	if(cause & IM_XRDYB)
	if(cause & IM_XRDYB){
		duart[1].cmnd = DIS_TX;
	}
	/*
	 * Is it 3?
	 * 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);

M gnot/stream.c => gnot/stream.c +17 -3
@@ 58,7 58,7 @@ Bclass bclass[Nclass]={
	{ 0 },
	{ 68 },
	{ 260 },
	{ 1024 },
	{ 4096 },
};

/*


@@ 70,17 70,29 @@ dumpqueues(void)
	Queue *q;
	int count;
	Block *bp;
	Bclass *bcp;

	print("\n");
	for(q = qlist; q < qlist + conf.nqueue; q++, q++){
		if(!(q->flag & QINUSE))
			continue;
		for(count = 0, bp = q->first; bp; bp = bp->next)
			count++;
		print("%s %ux  RD count %d len %d", q->info->name, q, count, q->len);
		print("%s %ux  R c %d l %d f %ux", q->info->name, q, count,
			q->len, q->flag);
		for(count = 0, bp = WR(q)->first; bp; bp = bp->next)
			count++;
		print("  WR count %d len %d\n", count, WR(q)->len);
		print("  W c %d l %d f %ux\n", count, WR(q)->len, WR(q)->flag);
	}
	print("\n");
	for(bcp=bclass; bcp<&bclass[Nclass]; bcp++){
		lock(bcp);
		for(count = 0, bp = bcp->first; bp; count++, bp = bp->next)
			;
		unlock(bcp);
		print("%d blocks of size %d\n", count, bcp->size);
	}
	print("\n");
}

/*


@@ 180,6 192,8 @@ freeb(Block *bp)
	Bclass *bcp;
	int tries;

	if((bp->flags&S_CLASS) >= Nclass)
		panic("freeb class");
	bcp = &bclass[bp->flags & S_CLASS];
	lock(bcp);
	bp->rptr = bp->wptr = 0;

M gnot/sturp.c => gnot/sturp.c +65 -34
@@ 48,7 48,6 @@ struct Urp {
	int	blocks;

	/* output */

	QLock	xmit;		/* output lock, only one process at a time */
	Queue	*wq;		/* output queue */
	int	maxout;		/* maximum outstanding unacked blocks */


@@ 60,6 59,7 @@ struct Urp {
	Block	*xb[8];		/* the xmit window buffer */
	QLock	xl[8];
	ulong	timer;		/* timeout for xmit */
	int	rexmit;

	int	kstarted;
};


@@ 166,15 166,7 @@ isflushed(void *a)
	Urp *up;

	up = (Urp *)a;
	return (up->state&HUNGUP) || (up->unechoed==up->next && up->wq->len==0);
}
static int
isdead(void *a)
{
	Urp *up;

	up = (Urp *)a;
	return up->kstarted == 0;
	return (up->state&HUNGUP) || (up->unechoed==up->nxb && up->wq->len==0);
}
static void
urpclose(Queue *q)


@@ 188,28 180,41 @@ urpclose(Queue *q)
	/*
	 *  wait for all outstanding messages to drain, tell kernel
	 *  process we're closing.
	 *
	 *  if 2 minutes elapse, give it up
	 */
	up->state |= CLOSING;
	sleep(&up->r, isflushed, up);
	tsleep(&up->r, isflushed, up, 2*60*1000);

	/*
	 *  ack all outstanding messages
	 *  kill off the kernel process
	 */
	qlock(&up->xmit);
	up->state |= HUNGUP;
	wakeup(&up->rq->r);

	qlock(&up->xmit);
	/*
	 *  ack all outstanding messages
	 */
	i = up->next - 1;
	if(i < 0)
		i = 7;
	rcvack(up, ECHO+i);
	qunlock(&up->xmit);

	/*
	 *  kill off the kernel process
	 *  free all staged but unsent messages
	 */
	wakeup(&up->rq->r);
	for(i = 0; i < 7; i++)
		if(up->xb[i]){
			freeb(up->xb[i]);
			up->xb[i] = 0;
		}
	qunlock(&up->xmit);

	if(up->kstarted == 0)
	if(up->kstarted == 0){
		DPRINT("urpclose %ux\n", up);
		up->state = 0;
	}
}

/*


@@ 256,9 261,10 @@ urpciput(Queue *q, Block *bp)
	/*
	 *  take care of any data
	 */
	if(BLEN(bp)>0 && !QFULL(q->next))
	if(BLEN(bp)>0  && q->next->len<2*Streamhi && q->next->nb<2*Streambhi){
		bp->flags |= S_DELIM;
		PUTNEXT(q, bp);
	else
	} else
		freeb(bp);

	/*


@@ 370,8 376,8 @@ urpiput(Queue *q, Block *bp)
	 *  queue the block(s)
	 */
	if(BLEN(bp) > 0){
		bp->flags &= ~S_DELIM;
		putq(q, bp);
		q->last->flags &= ~S_DELIM;
		if(q->len > 4*1024){
			flushinput(up);
			return;


@@ 460,6 466,10 @@ urpiput(Queue *q, Block *bp)
			urpstat.rjseq++;
			sendrej(up);
			break;
		} else if(q->next->len > (3*Streamhi)/2
			|| q->next->nb > (3*Streambhi)/2) {
			flushinput(up);
			break;
		}

		/*


@@ 472,7 482,8 @@ urpiput(Queue *q, Block *bp)
				PUTNEXT(q, bp);
		} else {
			bp = allocb(0);
			bp->flags |= S_DELIM;
			if(up->trbuf[0] != BOTM)
				bp->flags |= S_DELIM;
			PUTNEXT(q, bp);
		}
		up->trx = 0;


@@ 547,6 558,7 @@ output(Urp *up)
	ulong now;
	Queue *q;
	int n;
	int i;

	if(!canqlock(&up->xmit))
		return;


@@ 595,8 607,7 @@ output(Urp *up)
	/*
	 *  if a retransmit time has elapsed since a transmit, send an ENQ
	 */
	if(up->unechoed != up->next && NOW > up->timer){
		DPRINT("sENQ\n");
	if(up->unechoed!=up->next && NOW>up->timer){
		up->timer = NOW + MSrexmit;
		up->state &= ~REJECTING;
		sendctl(up, ENQ);


@@ 608,11 619,21 @@ output(Urp *up)
	/*
	 *  if there's a window open, push some blocks out
	 */
	while(WINDOW(up)>0 && up->xb[up->next]!=0 && canqlock(&up->xl[up->next])){
		if(up->xb[up->next])
			sendblock(up, up->next);
		qunlock(&up->xl[up->next]);
	if(up->rexmit){
		up->rexmit = 0;
		up->next = up->unechoed;
	}
	while(WINDOW(up)>0 && up->xb[up->next]!=0){
		i = up->next;
		qlock(&up->xl[i]);
		if(waserror()){
			qunlock(&up->xl[i]);
			nexterror();
		}
		sendblock(up, i);
		qunlock(&up->xl[i]);
		up->next = NEXT(up->next);
		poperror();
	}
	qunlock(&up->xmit);
	poperror();


@@ 733,6 754,7 @@ rcvack(Urp *up, int msg)
{
	int seqno;
	int next;
	int i;

	seqno = msg&Nmask;
	next = NEXT(seqno);


@@ 742,11 764,12 @@ rcvack(Urp *up, int msg)
	 */
	if(IN(seqno, up->unacked, up->next)){
		for(; up->unacked != next; up->unacked = NEXT(up->unacked)){
			qlock(&up->xl[up->unacked]);
			if(up->xb[up->unacked])
				freeb(up->xb[up->unacked]);
			up->xb[up->unacked] = 0;
			qunlock(&up->xl[up->unacked]);
			i = up->unacked;
			qlock(&up->xl[i]);
			if(up->xb[i])
				freeb(up->xb[i]);
			up->xb[i] = 0;
			qunlock(&up->xl[i]);
		}
	}



@@ 774,7 797,7 @@ rcvack(Urp *up, int msg)
		 */
		if(up->unechoed==next && !(up->state & REJECTING)){
			up->state |= REJECTING;
			up->next = next;
			up->rexmit = 1;
		}
		break;
	}


@@ 819,6 842,7 @@ initoutput(Urp *up, int window)
	up->unacked = 1;
	up->next = 1;
	up->nxb = 1;
	up->rexmit = 0;

	/*
	 *  free any outstanding blocks


@@ 874,6 898,7 @@ urpkproc(void *arg)
	up = (Urp *)arg;

	if(waserror()){
		print("urpkproc error %ux\n", up);
		up->state = 0;
		up->kstarted = 0;
		wakeup(&up->r);


@@ 886,10 911,16 @@ urpkproc(void *arg)
			if(up->state & HUNGUP)
				break;
		}
		sendack(up);
		if(up->state == 0){
			DPRINT("urpkproc: %ux->state == 0\n", up);
			break;
		}
		if(!QFULL(up->rq->next))
			sendack(up);
		output(up);
		tsleep(&up->rq->r, todo, up, MSrexmit/2);
	}
	up->state = 0;
	up->kstarted = 0;
	DPRINT("urpkproc %ux\n", up);
}

M port/devbit.c => port/devbit.c +65 -29
@@ 9,7 9,7 @@

#include	"gnot.h"

extern Font	defont0;	/* BUG */
extern Font	*defont;

/*
 * Device (#b/bitblt) is exclusive use on open, so no locks are necessary


@@ 24,7 24,8 @@ extern Font	defont0;	/* BUG */
 * followed by N blocks.  The bitmap pointer is zero if block is free. 
 */

struct{
struct
{
	Ref;
	Bitmap	*map;		/* arena */
	Bitmap	*free;		/* free list */


@@ 53,25 54,27 @@ struct{
	Rendez	r;
}mouse;

Cursor	arrow =
{
	{0, 0},
	{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 =
{
	{{0, 0},
	{0xFFE0, 0xFFE0, 0xFFC0, 0xFF00,
	 0xFF00, 0xFF80, 0xFFC0, 0xFFE0,
	 0xE7F0, 0xE3F8, 0xC1FC, 0x00FE,
	 0x007F, 0x003E, 0x001C, 0x0008,
	},
	{0x0000, 0x7FC0, 0x7F00, 0x7C00,
	 0x7E00, 0x7F00, 0x6F80, 0x67C0,
	 0x43E0, 0x41F0, 0x00F8, 0x007C,
	 0x003E, 0x001C, 0x0008, 0x0000,
	}},
};
}cursor;

ulong setbits[16];
Bitmap	set =


@@ 103,7 106,7 @@ Bitmap cursorback =
	{0, 0, 16, 16}
};

void	cursortobitmap(void);
void	Cursortocursor(Cursor*);
void	cursoron(int);
void	cursoroff(int);
int	mousechanged(void*);


@@ 140,7 143,7 @@ bitreset(void)
	bit.words = ialloc(conf.nbitbyte, 0);
	bit.nwords = conf.nbitbyte/sizeof(ulong);
	bit.wfree = bit.words;
	cursortobitmap();
	Cursortocursor(&arrow);
}

void


@@ 148,6 151,9 @@ bitinit(void)
{
	lock(&bit);
	unlock(&bit);
	if(screen.ldepth > 1)
		panic("bitinit ldepth>1");
	cursorback.ldepth = screen.ldepth;
	cursoron(1);
}



@@ 192,6 198,7 @@ bitopen(Chan *c, int omode)
		bit.lastid = -1;
		bit.init = 1;
		bit.ref = 1;
		Cursortocursor(&arrow);
		unlock(&bit);
	}else
		incref(&bit);


@@ 341,6 348,7 @@ bitwrite(Chan *c, void *va, long n)
	int off;
	Point pt;
	Rectangle rect;
	Cursor curs;
	Bitmap *bp, *src, *dst;

	if(c->qid == CHDIR)


@@ 368,7 376,7 @@ bitwrite(Chan *c, void *va, long n)
			if(m < 18)
				error(0, Ebadblt);
			v = *(p+1);
			if(v != 0)	/* BUG */
			if(v!=0 && v!=1)	/* BUG */
				error(0, Ebadblt);
			ws = 1<<(5-v);	/* pixels per word */
			if(bit.free == 0)


@@ 385,9 393,9 @@ bitwrite(Chan *c, void *va, long n)
				l = (t+rect.max.x+ws-1)/ws;
			}
			nw = l*Dy(rect);
			if(bit.wfree+l+2 > bit.words+bit.nwords){
			if(bit.wfree+2+nw > bit.words+bit.nwords){
				bitcompact();
				if(bit.wfree+l+1 > bit.words+bit.nwords)
				if(bit.wfree+2+nw > bit.words+bit.nwords)
					error(0, Enobitstore);
			}
			bp = bit.free;


@@ 453,6 461,36 @@ bitwrite(Chan *c, void *va, long n)
			p += 31;
			break;

		case 'c':
			/*
			 * cursorswitch
			 *	'c'		1
			 * nothing more: return to arrow; else
			 * 	Point		8
			 *	clr		32
			 *	set		32
			 */
			if(m == 1){
				cursoroff(1);
				Cursortocursor(&arrow);
				cursoron(1);
				m -= 1;
				p += 1;
				break;
			}
			if(m < 73)
				error(0, 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);
			cursoroff(1);
			Cursortocursor(&curs);
			cursoron(1);
			m -= 73;
			p += 73;
			break;

		case 'f':
			/*
			 * free


@@ 502,7 540,7 @@ bitwrite(Chan *c, void *va, long n)
				error(0, Ebadblt);
			if(off)
				cursoroff(1);
			string(dst, pt, &defont0/*BUG*/, (char*)p, v);
			string(dst, pt, defont/*BUG*/, (char*)p, v);
			if(off)
				cursoron(1);
			q++;


@@ 622,7 660,7 @@ biterrstr(Error *e, char *buf)
void
bitfree(Bitmap *bp)
{
	bp->base[1] = 0;
	bp->base[-1] = 0;
	bp->ldepth = -1;
	bp->base = (ulong*)bit.free;
	bit.free = bp;


@@ 633,7 671,6 @@ bitcompact(void)
{
	ulong *p1, *p2;

print("bitcompact\n");
	p1 = p2 = bit.words;
	while(p2 < bit.wfree){
		if(p2[1] == 0){


@@ 648,18 685,18 @@ print("bitcompact\n");
		p1 += 2 + p1[0];
	}
	bit.wfree = p1;
print("bitcompact done\n");
}

void
cursortobitmap(void)
Cursortocursor(Cursor *c)
{
	int i;

	lock(&cursor);
	memcpy(&cursor, c, sizeof(Cursor));
	for(i=0; i<16; i++){
		setbits[i] = cursor.set[i]<<16;
		clrbits[i] = cursor.clr[i]<<16;
		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);
}


@@ 711,7 748,6 @@ void
mouseclock(void)	/* called spl6 */
{
	int x, y;

	if(mouse.track && canlock(&cursor)){
		x = mouse.xy.x + mouse.dx;
		if(x < screen.r.min.x)

M port/sturp.c => port/sturp.c +3 -2
@@ 261,9 261,10 @@ urpciput(Queue *q, Block *bp)
	/*
	 *  take care of any data
	 */
	if(BLEN(bp)>0 && !QFULL(q->next))
	if(BLEN(bp)>0  && q->next->len<2*Streamhi && q->next->nb<2*Streambhi){
		bp->flags |= S_DELIM;
		PUTNEXT(q, bp);
	else
	} else
		freeb(bp);

	/*