Browse Source

remove /sys/src/9

David du Colombier 9 years ago
parent
commit
bc29ea815a
100 changed files with 0 additions and 34194 deletions
  1. 0 10
      sys/src/9/bcm/arch.c
  2. 0 109
      sys/src/9/bcm/archbcm.c
  3. 0 282
      sys/src/9/bcm/arm.h
  4. 0 36
      sys/src/9/bcm/arm.s
  5. 0 30
      sys/src/9/bcm/boot.rc
  6. 0 212
      sys/src/9/bcm/clock.c
  7. 0 10
      sys/src/9/bcm/coproc.c
  8. 0 295
      sys/src/9/bcm/dat.h
  9. 0 172
      sys/src/9/bcm/devarch.c
  10. 0 10
      sys/src/9/bcm/devether.c
  11. 0 133
      sys/src/9/bcm/devfakertc.c
  12. 0 1499
      sys/src/9/bcm/devusb.c
  13. 0 230
      sys/src/9/bcm/dma.c
  14. 0 519
      sys/src/9/bcm/dwcotg.h
  15. 0 436
      sys/src/9/bcm/emmc.c
  16. 0 10
      sys/src/9/bcm/etherif.h
  17. 0 449
      sys/src/9/bcm/etherusb.c
  18. 0 129
      sys/src/9/bcm/fns.h
  19. 0 515
      sys/src/9/bcm/fpiarm.c
  20. 0 1
      sys/src/9/bcm/init9.s
  21. 0 54
      sys/src/9/bcm/io.h
  22. 0 10
      sys/src/9/bcm/kbd.c
  23. 0 274
      sys/src/9/bcm/l.s
  24. 0 197
      sys/src/9/bcm/lexception.s
  25. 0 1
      sys/src/9/bcm/lproc.s
  26. 0 611
      sys/src/9/bcm/main.c
  27. 0 104
      sys/src/9/bcm/mem.h
  28. 0 132
      sys/src/9/bcm/mkfile
  29. 0 327
      sys/src/9/bcm/mmu.c
  30. 0 10
      sys/src/9/bcm/mouse.c
  31. 0 61
      sys/src/9/bcm/pi
  32. 0 61
      sys/src/9/bcm/picpu
  33. 0 57
      sys/src/9/bcm/pifat
  34. 0 93
      sys/src/9/bcm/rebootcode.s
  35. 0 554
      sys/src/9/bcm/screen.c
  36. 0 44
      sys/src/9/bcm/screen.h
  37. 0 10
      sys/src/9/bcm/softfpu.c
  38. 0 10
      sys/src/9/bcm/syscall.c
  39. 0 586
      sys/src/9/bcm/trap.c
  40. 0 433
      sys/src/9/bcm/uartmini.c
  41. 0 991
      sys/src/9/bcm/usbdwc.c
  42. 0 301
      sys/src/9/bcm/vcore.c
  43. 0 10
      sys/src/9/bcm/vfp3.c
  44. 0 149
      sys/src/9/bcm/words
  45. 0 193
      sys/src/9/boot/aux.c
  46. 0 461
      sys/src/9/boot/boot.c
  47. 0 87
      sys/src/9/boot/boot.h
  48. 0 81
      sys/src/9/boot/bootauth.c
  49. 0 89
      sys/src/9/boot/bootcache.c
  50. 0 218
      sys/src/9/boot/bootip.c
  51. 0 28
      sys/src/9/boot/bootmkfile
  52. 0 135
      sys/src/9/boot/doauthenticate.c
  53. 0 83
      sys/src/9/boot/embed.c
  54. 0 52
      sys/src/9/boot/getpasswd.c
  55. 0 297
      sys/src/9/boot/local.c
  56. 0 101
      sys/src/9/boot/mkboot
  57. 0 61
      sys/src/9/boot/nopsession.c
  58. 0 76
      sys/src/9/boot/paq.c
  59. 0 616
      sys/src/9/boot/parts.c
  60. 0 31
      sys/src/9/boot/printstub.c
  61. 0 59
      sys/src/9/boot/sac.c
  62. 0 159
      sys/src/9/boot/settime.c
  63. 0 46
      sys/src/9/boot/testboot.c
  64. 0 156
      sys/src/9/boot/usb.c
  65. 0 695
      sys/src/9/ip/arp.c
  66. 0 133
      sys/src/9/ip/chandial.c
  67. 0 1466
      sys/src/9/ip/devip.c
  68. 0 161
      sys/src/9/ip/eipconvtest.c
  69. 0 1121
      sys/src/9/ip/esp.c
  70. 0 774
      sys/src/9/ip/ethermedium.c
  71. 0 980
      sys/src/9/ip/gre.c
  72. 0 501
      sys/src/9/ip/icmp.c
  73. 0 891
      sys/src/9/ip/icmp6.c
  74. 0 308
      sys/src/9/ip/igmp.c
  75. 0 37
      sys/src/9/ip/inferno.c
  76. 0 716
      sys/src/9/ip/ip.c
  77. 0 753
      sys/src/9/ip/ip.h
  78. 0 377
      sys/src/9/ip/ipaux.c
  79. 0 1678
      sys/src/9/ip/ipifc.c
  80. 0 849
      sys/src/9/ip/ipmux.c
  81. 0 901
      sys/src/9/ip/iproute.c
  82. 0 630
      sys/src/9/ip/ipv6.c
  83. 0 193
      sys/src/9/ip/ipv6.h
  84. 0 129
      sys/src/9/ip/loopbackmedium.c
  85. 0 162
      sys/src/9/ip/netdevmedium.c
  86. 0 273
      sys/src/9/ip/netlog.c
  87. 0 48
      sys/src/9/ip/nullmedium.c
  88. 0 88
      sys/src/9/ip/pktmedium.c
  89. 0 81
      sys/src/9/ip/ptclbsum.c
  90. 0 1065
      sys/src/9/ip/rudp.c
  91. 0 3449
      sys/src/9/ip/tcp.c
  92. 0 629
      sys/src/9/ip/udp.c
  93. 0 248
      sys/src/9/kw/arch.c
  94. 0 540
      sys/src/9/kw/archkw.c
  95. 0 203
      sys/src/9/kw/arm.h
  96. 0 72
      sys/src/9/kw/arm.s
  97. 0 141
      sys/src/9/kw/cga.c
  98. 0 214
      sys/src/9/kw/clock.c
  99. 0 162
      sys/src/9/kw/coproc.c
  100. 0 330
      sys/src/9/kw/dat.h

+ 0 - 10
sys/src/9/bcm/arch.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../omap/arch.c"

+ 0 - 109
sys/src/9/bcm/archbcm.c

@@ -1,109 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2835 (e.g. raspberry pi) architecture-specific stuff
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "io.h"
-#include "arm.h"
-
-#include "../port/netif.h"
-#include "etherif.h"
-
-#define	POWERREGS	(VIRTIO+0x100000)
-
-enum {
-	Wdogfreq	= 65536,
-	Wdogtime	= 5,	/* seconds, ≤ 15 */
-};
-
-/*
- * Power management / watchdog registers
- */
-enum {
-	Rstc		= 0x1c>>2,
-		Password	= 0x5A<<24,
-		CfgMask		= 0x03<<4,
-		CfgReset	= 0x02<<4,
-	Rsts		= 0x20>>2,
-	Wdog		= 0x24>>2,
-};
-
-void
-archreset(void)
-{
-	fpon();
-}
-
-void
-archreboot(void)
-{
-	u32int *r;
-
-	r = (u32int*)POWERREGS;
-	r[Wdog] = Password | 1;
-	r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
-	coherence();
-	for(;;)
-		;
-}
-
-static void
-wdogfeed(void)
-{
-	u32int *r;
-
-	r = (u32int*)POWERREGS;
-	r[Wdog] = Password | (Wdogtime * Wdogfreq);
-	r[Rstc] = Password | (r[Rstc] & ~CfgMask) | CfgReset;
-}
-
-void
-wdogoff(void)
-{
-	u32int *r;
-
-	r = (u32int*)POWERREGS;
-	r[Rstc] = Password | (r[Rstc] & ~CfgMask);
-}
-	
-void
-cpuidprint(void)
-{
-	print("cpu%d: %dMHz ARM1176JZF-S\n", m->machno, m->cpumhz);
-}
-
-void
-archbcmlink(void)
-{
-	addclock0link(wdogfeed, HZ);
-}
-
-int
-archether(unsigned ctlrno, Ether *ether)
-{
-	switch(ctlrno) {
-	case 0:
-		ether->type = "usb";
-		ether->ctlrno = ctlrno;
-		ether->irq = -1;
-		ether->nopt = 0;
-		ether->mbps = 100;
-		return 1;
-	}
-	return -1;
-}
-

+ 0 - 282
sys/src/9/bcm/arm.h

@@ -1,282 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * arm-specific definitions for armv6
- * these are used in C and assembler
- */
-
-/*
- * Program Status Registers
- */
-#define PsrMusr		0x00000010		/* mode */
-#define PsrMfiq		0x00000011
-#define PsrMirq		0x00000012
-#define PsrMsvc		0x00000013	/* `protected mode for OS' */
-#define PsrMmon		0x00000016	/* `secure monitor' (trustzone hyper) */
-#define PsrMabt		0x00000017
-#define PsrMund		0x0000001B
-#define PsrMsys		0x0000001F	/* `privileged user mode for OS' (trustzone) */
-#define PsrMask		0x0000001F
-
-#define PsrDfiq		0x00000040		/* disable FIQ interrupts */
-#define PsrDirq		0x00000080		/* disable IRQ interrupts */
-
-#define PsrV		0x10000000		/* overflow */
-#define PsrC		0x20000000		/* carry/borrow/extend */
-#define PsrZ		0x40000000		/* zero */
-#define PsrN		0x80000000		/* negative/less than */
-
-/* instruction decoding */
-#define ISCPOP(op)	((op) == 0xE || ((op) & ~1) == 0xC)
-#define ISFPAOP(cp, op)	((cp) == CpOFPA && ISCPOP(op))
-#define ISVFPOP(cp, op)	(((cp) == CpDFP || (cp) == CpFP) && ISCPOP(op))
-
-/*
- * Coprocessors
- */
-#define CpOFPA		1			/* ancient 7500 FPA */
-#define CpFP		10			/* float FP, VFP cfg. */
-#define CpDFP		11			/* double FP */
-#define CpSC		15			/* System Control */
-
-/*
- * Primary (CRn) CpSC registers.
- */
-#define	CpID		0			/* ID and cache type */
-#define	CpCONTROL	1			/* miscellaneous control */
-#define	CpTTB		2			/* Translation Table Base(s) */
-#define	CpDAC		3			/* Domain Access Control */
-#define	CpFSR		5			/* Fault Status */
-#define	CpFAR		6			/* Fault Address */
-#define	CpCACHE		7			/* cache/write buffer control */
-#define	CpTLB		8			/* TLB control */
-#define	CpCLD		9			/* L2 Cache Lockdown, op1==1 */
-#define CpTLD		10			/* TLB Lockdown, with op2 */
-#define CpVECS		12			/* vector bases, op1==0, Crm==0, op2s (cortex) */
-#define	CpPID		13			/* Process ID */
-#define CpSPM		15			/* system performance monitor (arm1176) */
-
-/*
- * CpTTB op1==0, Crm==0 opcode2 values.
- */
-#define CpTTB0		0
-#define CpTTB1		1			/* cortex */
-#define CpTTBctl	2			/* cortex */
-
-/*
- * CpFSR opcode2 values.
- */
-#define	CpFSRdata	0			/* armv6, armv7 */
-#define	CpFSRinst	1			/* armv6, armv7 */
-
-/*
- * CpID Secondary (CRm) registers.
- */
-#define CpIDidct	0
-
-/*
- * CpID op1==0 opcode2 fields.
- * the cortex has more op1 codes for cache size, etc.
- */
-#define CpIDid		0			/* main ID */
-#define CpIDct		1			/* cache type */
-#define CpIDtlb		3			/* tlb type (cortex) */
-#define CpIDmpid	5			/* multiprocessor id (cortex) */
-
-/* CpIDid op1 values */
-#define CpIDcsize	1			/* cache size (cortex) */
-#define CpIDcssel	2			/* cache size select (cortex) */
-
-/*
- * CpCONTROL op2 codes, op1==0, Crm==0.
- */
-#define CpMainctl	0
-#define CpAuxctl	1
-#define CpCPaccess	2
-
-/*
- * CpCONTROL: op1==0, CRm==0, op2==CpMainctl.
- * main control register.
- * cortex/armv7 has more ops and CRm values.
- */
-#define CpCmmu		0x00000001	/* M: MMU enable */
-#define CpCalign	0x00000002	/* A: alignment fault enable */
-#define CpCdcache	0x00000004	/* C: data cache on */
-#define CpCsbo (3<<22|1<<18|1<<16|017<<3)	/* must be 1 (armv7) */
-#define CpCsbz (CpCtre|1<<26|CpCve|1<<15|7<<7)	/* must be 0 (armv7) */
-#define CpCsw		(1<<10)		/* SW: SWP(B) enable (deprecated in v7) */
-#define CpCpredict	0x00000800	/* Z: branch prediction (armv7) */
-#define CpCicache	0x00001000	/* I: instruction cache on */
-#define CpChv		0x00002000	/* V: high vectors */
-#define CpCrr		(1<<14)	/* RR: round robin vs random cache replacement */
-#define CpCha		(1<<17)		/* HA: hw access flag enable */
-#define CpCdz		(1<<19)		/* DZ: divide by zero fault enable */
-#define CpCfi		(1<<21)		/* FI: fast intrs */
-#define CpCve		(1<<24)		/* VE: intr vectors enable */
-#define CpCee		(1<<25)		/* EE: exception endianness */
-#define CpCnmfi		(1<<27)		/* NMFI: non-maskable fast intrs. */
-#define CpCtre		(1<<28)		/* TRE: TEX remap enable */
-#define CpCafe		(1<<29)		/* AFE: access flag (ttb) enable */
-
-/*
- * CpCONTROL: op1==0, CRm==0, op2==CpAuxctl.
- * Auxiliary control register on cortex at least.
- */
-#define CpACcachenopipe		(1<<20)	/* don't pipeline cache maint. */
-#define CpACcp15serial		(1<<18)	/* serialise CP1[45] ops. */
-#define CpACcp15waitidle	(1<<17)	/* CP1[45] wait-on-idle */
-#define CpACcp15pipeflush	(1<<16)	/* CP1[45] flush pipeline */
-#define CpACneonissue1		(1<<12)	/* neon single issue */
-#define CpACldstissue1		(1<<11)	/* force single issue ld, st */
-#define CpACissue1		(1<<10)	/* force single issue */
-#define CpACnobsm		(1<<7)	/* no branch size mispredicts */
-#define CpACibe			(1<<6)	/* cp15 invalidate & btb enable */
-#define CpACl1neon		(1<<5)	/* cache neon (FP) data in L1 cache */
-#define CpACasa			(1<<4)	/* enable speculative accesses */
-#define CpACl1pe		(1<<3)	/* l1 cache parity enable */
-#define CpACl2en		(1<<1)	/* l2 cache enable; default 1 */
-/*
- * CpCONTROL Secondary (CRm) registers and opcode2 fields.
- */
-#define CpCONTROLscr	1
-
-#define CpSCRscr	0
-
-/*
- * CpCACHE Secondary (CRm) registers and opcode2 fields.  op1==0.
- * In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
- */
-#define CpCACHEintr	0			/* interrupt (op2==4) */
-#define CpCACHEisi	1			/* inner-sharable I cache (v7) */
-#define CpCACHEpaddr	4			/* 0: phys. addr (cortex) */
-#define CpCACHEinvi	5			/* instruction, branch table */
-#define CpCACHEinvd	6			/* data or unified */
-#define CpCACHEinvu	7			/* unified (not on cortex) */
-#define CpCACHEva2pa	8			/* va -> pa translation (cortex) */
-#define CpCACHEwb	10			/* writeback */
-#define CpCACHEinvdse	11			/* data or unified by mva */
-#define CpCACHEwbi	14			/* writeback+invalidate */
-
-#define CpCACHEall	0			/* entire (not for invd nor wb(i) on cortex) */
-#define CpCACHEse	1			/* single entry */
-#define CpCACHEsi	2			/* set/index (set/way) */
-#define CpCACHEtest	3			/* test loop */
-#define CpCACHEwait	4			/* wait (prefetch flush on cortex) */
-#define CpCACHEdmbarr	5			/* wb only (cortex) */
-#define CpCACHEflushbtc	6			/* flush branch-target cache (cortex) */
-#define CpCACHEflushbtse 7			/* ⋯ or just one entry in it (cortex) */
-
-/*
- * CpTLB Secondary (CRm) registers and opcode2 fields.
- */
-#define CpTLBinvi	5			/* instruction */
-#define CpTLBinvd	6			/* data */
-#define CpTLBinvu	7			/* unified */
-
-#define CpTLBinv	0			/* invalidate all */
-#define CpTLBinvse	1			/* invalidate single entry */
-#define CpTBLasid	2			/* by ASID (cortex) */
-
-/*
- * CpCLD Secondary (CRm) registers and opcode2 fields for op1==0. (cortex)
- */
-#define CpCLDena	12			/* enables */
-#define CpCLDcyc	13			/* cycle counter */
-#define CpCLDuser	14			/* user enable */
-
-#define CpCLDenapmnc	0
-#define CpCLDenacyc	1
-
-/*
- * CpCLD Secondary (CRm) registers and opcode2 fields for op1==1.
- */
-#define CpCLDl2		0			/* l2 cache */
-
-#define CpCLDl2aux	2			/* auxiliary control */
-
-/*
- * l2 cache aux. control
- */
-#define CpCl2ecc	(1<<28)			/* use ecc, not parity */
-#define CpCl2noldforw	(1<<27)			/* no ld forwarding */
-#define CpCl2nowrcomb	(1<<25)			/* no write combining */
-#define CpCl2nowralldel	(1<<24)			/* no write allocate delay */
-#define CpCl2nowrallcomb (1<<23)		/* no write allocate combine */
-#define CpCl2nowralloc	(1<<22)			/* no write allocate */
-#define CpCl2eccparity	(1<<21)			/* enable ecc or parity */
-#define CpCl2inner	(1<<16)			/* inner cacheability */
-/* other bits are tag ram & data ram latencies */
-
-/*
- * CpTLD Secondary (CRm) registers and opcode2 fields.
- */
-#define CpTLDlock	0			/* TLB lockdown registers */
-#define CpTLDpreload	1			/* TLB preload */
-
-#define CpTLDi		0			/* TLB instr. lockdown reg. */
-#define CpTLDd		1			/* " data " " */
-
-/*
- * CpVECS Secondary (CRm) registers and opcode2 fields.
- */
-#define CpVECSbase	0
-
-#define CpVECSnorm	0			/* (non-)secure base addr */
-#define CpVECSmon	1			/* secure monitor base addr */
-
-/*
- * CpSPM Secondary (CRm) registers and opcode2 fields.
- */
-#define CpSPMperf	12			/* various counters */
-
-#define CpSPMctl	0			/* performance monitor control */
-#define	CpSPMcyc	1			/* cycle counter register */
-
-/*
- * CpCACHERANGE opcode2 fields for MCRR instruction (armv6)
- */
-#define	CpCACHERANGEinvi	5		/* invalidate instruction  */
-#define	CpCACHERANGEinvd	6		/* invalidate data */
-#define CpCACHERANGEdwb		12		/* writeback */
-#define CpCACHERANGEdwbi	14		/* writeback+invalidate */
-
-/*
- * MMU page table entries.
- * Mbz (0x10) bit is implementation-defined and must be 0 on the cortex.
- */
-#define Mbz		(0<<4)
-#define Fault		0x00000000		/* L[12] pte: unmapped */
-
-#define Coarse		(Mbz|1)			/* L1 */
-#define Section		(Mbz|2)			/* L1 1MB */
-#define Fine		(Mbz|3)			/* L1 */
-
-#define Large		0x00000001		/* L2 64KB */
-#define Small		0x00000002		/* L2 4KB */
-#define Tiny		0x00000003		/* L2 1KB: not in v7 */
-#define Buffered	0x00000004		/* L[12]: write-back not -thru */
-#define Cached		0x00000008		/* L[12] */
-#define Dom0		0
-
-#define Noaccess	0			/* AP, DAC */
-#define Krw		1			/* AP */
-/* armv7 deprecates AP[2] == 1 & AP[1:0] == 2 (Uro), prefers 3 (new in v7) */
-#define Uro		2			/* AP */
-#define Urw		3			/* AP */
-#define Client		1			/* DAC */
-#define Manager		3			/* DAC */
-
-#define F(v, o, w)	(((v) & ((1<<(w))-1))<<(o))
-#define AP(n, v)	F((v), ((n)*2)+4, 2)
-#define L1AP(ap)	(AP(3, (ap)))
-#define L2AP(ap) (AP(3, (ap))|AP(2, (ap))|AP(1, (ap))|AP(0, (ap))) /* pre-armv7 */
-#define DAC(n, v)	F((v), (n)*2, 2)
-
-#define HVECTORS	0xffff0000

+ 0 - 36
sys/src/9/bcm/arm.s

@@ -1,36 +0,0 @@
-/*
- * armv6 machine assist, definitions
- *
- * loader uses R11 as scratch.
- */
-
-#include "mem.h"
-#include "arm.h"
-
-#define PADDR(va)	(PHYSDRAM | ((va) & ~KSEGM))
-
-#define L1X(va)		(((((va))>>20) & 0x0fff)<<2)
-
-#define PTEDRAM		(Dom0|L1AP(Krw)|Section|Cached|Buffered)
-
-/*
- * new instructions
- */
-
-#define ISB	\
-	MOVW	$0, R0; \
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEwait
-
-#define DSB \
-	MOVW	$0, R0; \
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
-
-#define	BARRIERS	ISB; DSB
-
-#define MCRR(coproc, op, rd, rn, crm) \
-	WORD $(0xec400000|(rn)<<16|(rd)<<12|(coproc)<<8|(op)<<4|(crm))
-
-#define OKAY \
-	MOVW	$0x7E200028,R2; \
-	MOVW	$0x10000,R3; \
-	MOVW	R3,(R2)

+ 0 - 30
sys/src/9/bcm/boot.rc

@@ -1,30 +0,0 @@
-#!/boot/rc -m /boot/rcmain
-
-/boot/echo -n boot...
-path=(/bin /boot)
-bind '#p' /proc
-bind '#d' /fd
-bind -a '#P' /dev
-bind -a '#t' /dev
-bind -a '#S' /dev
-bind -a '#I' /net
-echo -n rpi >/dev/hostowner
-echo -n fdisk...
-fdisk -p /dev/sdM0/data >/dev/sdM0/ctl
-dossrv -f/dev/sdM0/dos boot
-rootdir=/root/plan9
-rootspec=''
-mount -c /srv/boot /root
-bind -ac $rootdir /
-bind -ac $rootdir/mnt /mnt
-
-bind /$cputype/bin /bin
-bind -a /rc/bin /bin
-
-if (! ~ $#init 0)
-	exec `{echo $init}
-if (~ $service cpu)
-	exec /$cputype/init -c
-if not
-	exec /$cputype/init -t
-exec /boot/rc -m/boot/rcmain -i

+ 0 - 212
sys/src/9/bcm/clock.c

@@ -1,212 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2835 timers
- *	System timers run at 1MHz (timers 1 and 2 are used by GPU)
- *	ARM timer usually runs at 250MHz (may be slower in low power modes)
- *	Cycle counter runs at 700MHz (unless overclocked)
- *    All are free-running up-counters
- *
- * Use system timer 3 (64 bits) for hzclock interrupts and fastticks
- * Use ARM timer (32 bits) for perfticks
- * Use ARM timer to force immediate interrupt
- * Use cycle counter for cycles()
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-enum {
-	SYSTIMERS	= VIRTIO+0x3000,
-	ARMTIMER	= VIRTIO+0xB400,
-
-	SystimerFreq	= 1*Mhz,
-	MaxPeriod	= SystimerFreq / HZ,
-	MinPeriod	= SystimerFreq / (100*HZ),
-};
-
-typedef struct Systimers Systimers;
-typedef struct Armtimer Armtimer;
-
-struct Systimers {
-	u32int	cs;
-	u32int	clo;
-	u32int	chi;
-	u32int	c0;
-	u32int	c1;
-	u32int	c2;
-	u32int	c3;
-};
-
-struct Armtimer {
-	u32int	load;
-	u32int	val;
-	u32int	ctl;
-	u32int	irqack;
-	u32int	irq;
-	u32int	maskedirq;
-	u32int	reload;
-	u32int	predivider;
-	u32int	count;
-};
-
-enum {
-	CntPrescaleShift= 16,	/* freq is sys_clk/(prescale+1) */
-	CntPrescaleMask	= 0xFF,
-	CntEnable	= 1<<9,
-	TmrDbgHalt	= 1<<8,
-	TmrEnable	= 1<<7,
-	TmrIntEnable	= 1<<5,
-	TmrPrescale1	= 0x00<<2,
-	TmrPrescale16	= 0x01<<2,
-	TmrPrescale256	= 0x02<<2,
-	CntWidth16	= 0<<1,
-	CntWidth32	= 1<<1,
-};
-
-static void
-clockintr(Ureg *ureg, void *)
-{
-	Systimers *tn;
-
-	tn = (Systimers*)SYSTIMERS;
-	/* dismiss interrupt */
-	tn->cs = 1<<3;
-	timerintr(ureg, 0);
-}
-
-void
-clockshutdown(void)
-{
-	Armtimer *tm;
-
-	tm = (Armtimer*)ARMTIMER;
-	tm->ctl = 0;
-	wdogoff();
-}
-
-void
-clockinit(void)
-{
-	Systimers *tn;
-	Armtimer *tm;
-	u32int t0, t1, tstart, tend;
-
-	tn = (Systimers*)SYSTIMERS;
-	tm = (Armtimer*)ARMTIMER;
-	tm->load = 0;
-	tm->ctl = TmrPrescale1|CntEnable|CntWidth32;
-
-	tstart = tn->clo;
-	do{
-		t0 = lcycles();
-	}while(tn->clo == tstart);
-	tend = tstart + 10000;
-	do{
-		t1 = lcycles();
-	}while(tn->clo != tend);
-	t1 -= t0;
-	m->cpuhz = 100 * t1;
-	m->cpumhz = (m->cpuhz + Mhz/2 - 1) / Mhz;
-	m->cyclefreq = m->cpuhz;
-
-	tn->c3 = tn->clo - 1;
-	intrenable(IRQtimer3, clockintr, nil, 0, "clock");
-}
-
-void
-timerset(uvlong next)
-{
-	Systimers *tn;
-	vlong now, period;
-
-	tn = (Systimers*)SYSTIMERS;
-	now = fastticks(nil);
-	period = next - fastticks(nil);
-	if(period < MinPeriod)
-		next = now + MinPeriod;
-	else if(period > MaxPeriod)
-		next = now + MaxPeriod;
-	tn->c3 = (ulong)next;
-}
-
-uvlong
-fastticks(uvlong *hz)
-{
-	Systimers *tn;
-	ulong lo, hi;
-
-	tn = (Systimers*)SYSTIMERS;
-	if(hz)
-		*hz = SystimerFreq;
-	do{
-		hi = tn->chi;
-		lo = tn->clo;
-	}while(tn->chi != hi);
-	m->fastclock = (uvlong)hi<<32 | lo;
-	return m->fastclock;
-}
-
-ulong
-perfticks(void)
-{
-	Armtimer *tm;
-
-	tm = (Armtimer*)ARMTIMER;
-	return tm->count;
-}
-
-void
-armtimerset(int n)
-{
-	Armtimer *tm;
-
-	tm = (Armtimer*)ARMTIMER;
-	if(n > 0){
-		tm->ctl |= TmrEnable|TmrIntEnable;
-		tm->load = n;
-	}else{
-		tm->load = 0;
-		tm->ctl &= ~(TmrEnable|TmrIntEnable);
-		tm->irq = 1;
-	}
-}
-
-ulong
-µs(void)
-{
-	if(SystimerFreq != 1*Mhz)
-		return fastticks2us(fastticks(nil));
-	return fastticks(nil);
-}
-
-void
-microdelay(int n)
-{
-	Systimers *tn;
-	u32int now, diff;
-
-	tn = (Systimers*)SYSTIMERS;
-	diff = n + 1;
-	now = tn->clo;
-	while(tn->clo - now < diff)
-		;
-}
-
-void
-delay(int n)
-{
-	while(--n >= 0)
-		microdelay(1000);
-}

+ 0 - 10
sys/src/9/bcm/coproc.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../teg2/coproc.c"

+ 0 - 295
sys/src/9/bcm/dat.h

@@ -1,295 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Time.
- *
- * HZ should divide 1000 evenly, ideally.
- * 100, 125, 200, 250 and 333 are okay.
- */
-#define	HZ		100			/* clock frequency */
-#define	MS2HZ		(1000/HZ)		/* millisec per clock tick */
-#define	TK2SEC(t)	((t)/HZ)		/* ticks to seconds */
-
-enum {
-	Mhz	= 1000 * 1000,
-};
-
-typedef struct Conf	Conf;
-typedef struct Confmem	Confmem;
-typedef struct FPsave	FPsave;
-typedef struct ISAConf	ISAConf;
-typedef struct Label	Label;
-typedef struct Lock	Lock;
-typedef struct Memcache	Memcache;
-typedef struct MMMU	MMMU;
-typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
-typedef struct Page	Page;
-typedef struct PhysUart	PhysUart;
-typedef struct PMMU	PMMU;
-typedef struct Proc	Proc;
-typedef u32int		PTE;
-typedef struct Uart	Uart;
-typedef struct Ureg	Ureg;
-typedef uvlong		Tval;
-
-#pragma incomplete Ureg
-
-#define MAXSYSARG	5	/* for mount(fd, mpt, flag, arg, srv) */
-
-/*
- *  parameters for sysproc.c
- */
-#define AOUT_MAGIC	(E_MAGIC)
-
-struct Lock
-{
-	ulong	key;
-	u32int	sr;
-	uintptr	pc;
-	Proc*	p;
-	Mach*	m;
-	int	isilock;
-};
-
-struct Label
-{
-	uintptr	sp;
-	uintptr	pc;
-};
-
-enum {
-	Maxfpregs	= 32,	/* could be 16 or 32, see Mach.fpnregs */
-	Nfpctlregs	= 16,
-};
-
-/*
- * emulated or vfp3 floating point
- */
-struct FPsave
-{
-	ulong	status;
-	ulong	control;
-	/*
-	 * vfp3 with ieee fp regs; uvlong is sufficient for hardware but
-	 * each must be able to hold an Internal from fpi.h for sw emulation.
-	 */
-	ulong	regs[Maxfpregs][3];
-
-	int	fpstate;
-	uintptr	pc;		/* of failed fp instr. */
-};
-
-/*
- * FPsave.fpstate
- */
-enum
-{
-	FPinit,
-	FPactive,
-	FPinactive,
-	FPemu,
-
-	/* bits or'd with the state */
-	FPillegal= 0x100,
-};
-
-struct Confmem
-{
-	uintptr	base;
-	usize	npage;
-	uintptr	limit;
-	uintptr	kbase;
-	uintptr	klimit;
-};
-
-struct Conf
-{
-	ulong	nmach;		/* processors */
-	ulong	nproc;		/* processes */
-	Confmem	mem[1];		/* physical memory */
-	ulong	npage;		/* total physical pages of memory */
-	usize	upages;		/* user page pool */
-	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
-	ulong	ialloc;		/* max interrupt time allocation in bytes */
-	ulong	pipeqsize;	/* size in bytes of pipe queues */
-	ulong	nimage;		/* number of page cache image headers */
-	ulong	nswap;		/* number of swap pages */
-	int	nswppo;		/* max # of pageouts per segment pass */
-	ulong	hz;		/* processor cycle freq */
-	ulong	mhz;
-	int	monitor;	/* flag */
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
-};
-
-/*
- *  MMU stuff in Mach.
- */
-struct MMMU
-{
-	PTE*	mmul1;		/* l1 for this processor */
-	int	mmul1lo;
-	int	mmul1hi;
-	int	mmupid;
-};
-
-/*
- *  MMU stuff in proc
- */
-#define NCOLOR	1		/* 1 level cache, don't worry about VCE's */
-struct PMMU
-{
-	Page*	mmul2;
-	Page*	mmul2cache;	/* free mmu pages */
-};
-
-#include "../port/portdat.h"
-
-struct Mach
-{
-	int	machno;			/* physical id of processor */
-	uintptr	splpc;			/* pc of last caller to splhi */
-
-	Proc*	proc;			/* current process */
-
-	MMMU;
-	int	flushmmu;		/* flush current proc mmu state */
-
-	ulong	ticks;			/* of the clock since boot time */
-	Label	sched;			/* scheduler wakeup */
-	Lock	alarmlock;		/* access to alarm list */
-	void*	alarm;			/* alarms bound to this clock */
-
-	Proc*	readied;		/* for runproc */
-	ulong	schedticks;		/* next forced context switch */
-
-	int	cputype;
-	ulong	delayloop;
-
-	/* stats */
-	int	tlbfault;
-	int	tlbpurge;
-	int	pfault;
-	int	cs;
-	int	syscall;
-	int	load;
-	int	intr;
-	uvlong	fastclock;		/* last sampled value */
-	ulong	spuriousintr;
-	int	lastintr;
-	int	ilockdepth;
-	Perf	perf;			/* performance counters */
-
-
-	int	cpumhz;
-	uvlong	cpuhz;			/* speed of cpu */
-	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
-
-	/* vfp2 or vfp3 fpu */
-	int	havefp;
-	int	havefpvalid;
-	int	fpon;
-	int	fpconfiged;
-	int	fpnregs;
-	ulong	fpscr;			/* sw copy */
-	int	fppid;			/* pid of last fault */
-	uintptr	fppc;			/* addr of last fault */
-	int	fpcnt;			/* how many consecutive at that addr */
-
-	/* save areas for exceptions, hold R0-R4 */
-	u32int	sfiq[5];
-	u32int	sirq[5];
-	u32int	sund[5];
-	u32int	sabt[5];
-	u32int	smon[5];		/* probably not needed */
-	u32int	ssys[5];
-
-	int	stack[1];
-};
-
-/*
- * Fake kmap.
- */
-typedef void		KMap;
-#define	VA(k)		((uintptr)(k))
-#define	kmap(p)		(KMap*)((p)->pa|kseg0)
-#define	kunmap(k)
-
-struct
-{
-	Lock;
-	int	machs;			/* bitmap of active CPUs */
-	int	exiting;		/* shutdown */
-	int	ispanic;		/* shutdown in response to a panic */
-}active;
-
-extern register Mach* m;			/* R10 */
-extern register Proc* up;			/* R9 */
-extern uintptr kseg0;
-extern Mach* machaddr[MAXMACH];
-extern ulong memsize;
-extern int normalprint;
-
-/*
- *  a parsed plan9.ini line
- */
-#define NISAOPT		8
-
-struct ISAConf {
-	char	*type;
-	ulong	port;
-	int	irq;
-	ulong	dma;
-	ulong	mem;
-	ulong	size;
-	ulong	freq;
-
-	int	nopt;
-	char	*opt[NISAOPT];
-};
-
-#define	MACHP(n)	(machaddr[n])
-
-/*
- * Horrid. But the alternative is 'defined'.
- */
-#ifdef _DBGC_
-#define DBGFLG		(dbgflg[_DBGC_])
-#else
-#define DBGFLG		(0)
-#endif /* _DBGC_ */
-
-int vflag;
-extern char dbgflg[256];
-
-#define dbgprint	print		/* for now */
-
-/*
- *  hardware info about a device
- */
-typedef struct {
-	ulong	port;
-	int	size;
-} Devport;
-
-struct DevConf
-{
-	ulong	intnum;			/* interrupt number */
-	char	*type;			/* card type, malloced */
-	int	nports;			/* Number of ports */
-	Devport	*ports;			/* The ports themselves */
-};
-

+ 0 - 172
sys/src/9/bcm/devarch.c

@@ -1,172 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "io.h"
-
-enum {
-	Qdir = 0,
-	Qbase,
-
-	Qmax = 16,
-};
-
-typedef long Rdwrfn(Chan*, void*, long, vlong);
-
-static Rdwrfn *readfn[Qmax];
-static Rdwrfn *writefn[Qmax];
-
-static Dirtab archdir[Qmax] = {
-	".",		{ Qdir, 0, QTDIR },	0,	0555,
-};
-
-Lock archwlock;	/* the lock is only for changing archdir */
-int narchdir = Qbase;
-
-/*
- * Add a file to the #P listing.  Once added, you can't delete it.
- * You can't add a file with the same name as one already there,
- * and you get a pointer to the Dirtab entry so you can do things
- * like change the Qid version.  Changing the Qid path is disallowed.
- */
-Dirtab*
-addarchfile(char *name, int perm, Rdwrfn *rdfn, Rdwrfn *wrfn)
-{
-	int i;
-	Dirtab d;
-	Dirtab *dp;
-
-	memset(&d, 0, sizeof d);
-	strcpy(d.name, name);
-	d.perm = perm;
-
-	lock(&archwlock);
-	if(narchdir >= Qmax){
-		unlock(&archwlock);
-		return nil;
-	}
-
-	for(i=0; i<narchdir; i++)
-		if(strcmp(archdir[i].name, name) == 0){
-			unlock(&archwlock);
-			return nil;
-		}
-
-	d.qid.path = narchdir;
-	archdir[narchdir] = d;
-	readfn[narchdir] = rdfn;
-	writefn[narchdir] = wrfn;
-	dp = &archdir[narchdir++];
-	unlock(&archwlock);
-
-	return dp;
-}
-
-static Chan*
-archattach(char* spec)
-{
-	return devattach('P', spec);
-}
-
-Walkqid*
-archwalk(Chan* c, Chan *nc, char** name, int nname)
-{
-	return devwalk(c, nc, name, nname, archdir, narchdir, devgen);
-}
-
-static int
-archstat(Chan* c, uchar* dp, int n)
-{
-	return devstat(c, dp, n, archdir, narchdir, devgen);
-}
-
-static Chan*
-archopen(Chan* c, int omode)
-{
-	return devopen(c, omode, archdir, narchdir, devgen);
-}
-
-static void
-archclose(Chan*)
-{
-}
-
-static long
-archread(Chan *c, void *a, long n, vlong offset)
-{
-	Rdwrfn *fn;
-
-	switch((ulong)c->qid.path){
-	case Qdir:
-		return devdirread(c, a, n, archdir, narchdir, devgen);
-
-	default:
-		if(c->qid.path < narchdir && (fn = readfn[c->qid.path]))
-			return fn(c, a, n, offset);
-		error(Eperm);
-		break;
-	}
-
-	return 0;
-}
-
-static long
-archwrite(Chan *c, void *a, long n, vlong offset)
-{
-	Rdwrfn *fn;
-
-	if(c->qid.path < narchdir && (fn = writefn[c->qid.path]))
-		return fn(c, a, n, offset);
-	error(Eperm);
-
-	return 0;
-}
-
-void archinit(void);
-
-Dev archdevtab = {
-	'P',
-	"arch",
-
-	devreset,
-	archinit,
-	devshutdown,
-	archattach,
-	archwalk,
-	archstat,
-	archopen,
-	devcreate,
-	archclose,
-	archread,
-	devbread,
-	archwrite,
-	devbwrite,
-	devremove,
-	devwstat,
-};
-
-static long
-cputyperead(Chan*, void *a, long n, vlong offset)
-{
-	char str[128];
-
-	snprint(str, sizeof str, "ARM11 %d\n", m->cpumhz);
-	return readstr(offset, a, n, str);
-}
-
-void
-archinit(void)
-{
-	addarchfile("cputype", 0444, cputyperead, nil);
-}

+ 0 - 10
sys/src/9/bcm/devether.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../omap/devether.c"

+ 0 - 133
sys/src/9/bcm/devfakertc.c

@@ -1,133 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * raspberry pi doesn't have a realtime clock
- * fake a crude approximation from the kernel build time
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-enum{
-	Qdir = 0,
-	Qrtc,
-};
-
-Dirtab rtcdir[]={
-	".",	{Qdir, 0, QTDIR},	0,	0555,
-	"rtc",		{Qrtc, 0},	0,	0664,
-};
-
-extern ulong kerndate;
-
-static ulong rtcsecs;
-
-static void
-rtctick(void)
-{
-	rtcsecs++;
-}
-
-static void
-rtcinit(void)
-{
-	rtcsecs = kerndate;
-	addclock0link(rtctick, 1000);
-}
-
-static long
-rtcread(Chan *c, void *a, long n, vlong offset)
-{
-	if(c->qid.type & QTDIR)
-		return devdirread(c, a, n, rtcdir, nelem(rtcdir), devgen);
-
-	switch((ulong)c->qid.path){
-	case Qrtc:
-		return readnum((ulong)offset, a, n, rtcsecs, 12);
-	}
-	error(Ebadarg);
-	return 0;
-}
-
-static long
-rtcwrite(Chan*c, void *a, long n, vlong)
-{
-	char b[13];
-	ulong i;
-
-	switch((ulong)c->qid.path){
-	case Qrtc:
-		if(n >= sizeof(b))
-			error(Ebadarg);
-		strncpy(b, (char*)a, n);
-		i = strtol(b, 0, 0);
-		if(i <= 0)
-			error(Ebadarg);
-		rtcsecs = i;
-		return n;
-	}
-	error(Eperm);
-	return 0;
-}
-
-static Chan*
-rtcattach(char* spec)
-{
-	return devattach('r', spec);
-}
-
-static Walkqid*	 
-rtcwalk(Chan* c, Chan *nc, char** name, int nname)
-{
-	return devwalk(c, nc, name, nname, rtcdir, nelem(rtcdir), devgen);
-}
-
-static int	 
-rtcstat(Chan* c, uchar* dp, int n)
-{
-	return devstat(c, dp, n, rtcdir, nelem(rtcdir), devgen);
-}
-
-static Chan*
-rtcopen(Chan* c, int omode)
-{
-	return devopen(c, omode, rtcdir, nelem(rtcdir), devgen);
-}
-
-static void	 
-rtcclose(Chan*)
-{
-}
-
-Dev fakertcdevtab = {
-	'r',
-	"rtc",
-
-	devreset,
-	rtcinit,
-	devshutdown,
-	rtcattach,
-	rtcwalk,
-	rtcstat,
-	rtcopen,
-	devcreate,
-	rtcclose,
-	rtcread,
-	devbread,
-	rtcwrite,
-	devbwrite,
-	devremove,
-	devwstat,
-};
-

+ 0 - 1499
sys/src/9/bcm/devusb.c

@@ -1,1499 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * USB device driver framework.
- *
- * This is in charge of providing access to actual HCIs
- * and providing I/O to the various endpoints of devices.
- * A separate user program (usbd) is in charge of
- * enumerating the bus, setting up endpoints and
- * starting devices (also user programs).
- *
- * The interface provided is a violation of the standard:
- * you're welcome.
- *
- * The interface consists of a root directory with several files
- * plus a directory (epN.M) with two files per endpoint.
- * A device is represented by its first endpoint, which
- * is a control endpoint automatically allocated for each device.
- * Device control endpoints may be used to create new endpoints.
- * Devices corresponding to hubs may also allocate new devices,
- * perhaps also hubs. Initially, a hub device is allocated for
- * each controller present, to represent its root hub. Those can
- * never be removed.
- *
- * All endpoints refer to the first endpoint (epN.0) of the device,
- * which keeps per-device information, and also to the HCI used
- * to reach them. Although all endpoints cache that information.
- *
- * epN.M/data files permit I/O and are considered DMEXCL.
- * epN.M/ctl files provide status info and accept control requests.
- *
- * Endpoints may be given file names to be listed also at #u,
- * for those drivers that have nothing to do after configuring the
- * device and its endpoints.
- *
- * Drivers for different controllers are kept at usb[oue]hci.c
- * It's likely we could factor out much from controllers into
- * a generic controller driver, the problem is that details
- * regarding how to handle toggles, tokens, Tds, etc. will
- * get in the way. Thus, code is probably easier the way it is.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"../port/error.h"
-#include	"../port/usb.h"
-
-typedef struct Hcitype Hcitype;
-
-enum
-{
-	/* Qid numbers */
-	Qdir = 0,		/* #u */
-	Qusbdir,			/* #u/usb */
-	Qctl,			/* #u/usb/ctl - control requests */
-
-	Qep0dir,			/* #u/usb/ep0.0 - endpoint 0 dir */
-	Qep0io,			/* #u/usb/ep0.0/data - endpoint 0 I/O */
-	Qep0ctl,		/* #u/usb/ep0.0/ctl - endpoint 0 ctl. */
-	Qep0dummy,		/* give 4 qids to each endpoint */
-
-	Qepdir = 0,		/* (qid-qep0dir)&3 is one of these */
-	Qepio,			/* to identify which file for the endpoint */
-	Qepctl,
-
-	/* ... */
-
-	/* Usb ctls. */
-	CMdebug = 0,		/* debug on|off */
-	CMdump,			/* dump (data structures for debug) */
-
-	/* Ep. ctls */
-	CMnew = 0,		/* new nb ctl|bulk|intr|iso r|w|rw (endpoint) */
-	CMnewdev,		/* newdev full|low|high portnb (allocate new devices) */
-	CMhub,			/* hub (set the device as a hub) */
-	CMspeed,		/* speed full|low|high|no */
-	CMmaxpkt,		/* maxpkt size */
-	CMntds,			/* ntds nb (max nb. of tds per µframe) */
-	CMclrhalt,		/* clrhalt (halt was cleared on endpoint) */
-	CMpollival,		/* pollival interval (interrupt/iso) */
-	CMhz,			/* hz n (samples/sec; iso) */
-	CMsamplesz,		/* samplesz n (sample size; iso) */
-	CMinfo,			/* info infostr (ke.ep info for humans) */
-	CMdetach,		/* detach (abort I/O forever on this ep). */
-	CMaddress,		/* address (address is assigned) */
-	CMdebugep,		/* debug n (set/clear debug for this ep) */
-	CMname,			/* name str (show up as #u/name as well) */
-	CMtmout,		/* timeout n (activate timeouts for ep) */
-	CMpreset,		/* reset the port */
-
-	/* Hub feature selectors */
-	Rportenable	= 1,
-	Rportreset	= 4,
-
-};
-
-struct Hcitype
-{
-	char*	type;
-	int	(*reset)(Hci*);
-};
-
-#define QID(q)	((int)(q).path)
-
-static Cmdtab usbctls[] =
-{
-	{CMdebug,	"debug",	2},
-	{CMdump,	"dump",		1},
-};
-
-static Cmdtab epctls[] =
-{
-	{CMnew,		"new",		4},
-	{CMnewdev,	"newdev",	3},
-	{CMhub,		"hub",		1},
-	{CMspeed,	"speed",	2},
-	{CMmaxpkt,	"maxpkt",	2},
-	{CMntds,	"ntds",		2},
-	{CMpollival,	"pollival",	2},
-	{CMsamplesz,	"samplesz",	2},
-	{CMhz,		"hz",		2},
-	{CMinfo,	"info",		0},
-	{CMdetach,	"detach",	1},
-	{CMaddress,	"address",	1},
-	{CMdebugep,	"debug",	2},
-	{CMclrhalt,	"clrhalt",	1},
-	{CMname,	"name",		2},
-	{CMtmout,	"timeout",	2},
-	{CMpreset,	"reset",	1},
-};
-
-static Dirtab usbdir[] =
-{
-	"ctl",		{Qctl},		0,	0666,
-};
-
-char *usbmodename[] =
-{
-	[OREAD]	"r",
-	[OWRITE]	"w",
-	[ORDWR]	"rw",
-};
-
-static char *ttname[] =
-{
-	[Tnone]	"none",
-	[Tctl]	"control",
-	[Tiso]	"iso",
-	[Tintr]	"interrupt",
-	[Tbulk]	"bulk",
-};
-
-static char *spname[] =
-{
-	[Fullspeed]	"full",
-	[Lowspeed]	"low",
-	[Highspeed]	"high",
-	[Nospeed]	"no",
-};
-
-static int	debug;
-static Hcitype	hcitypes[Nhcis];
-static Hci*	hcis[Nhcis];
-static QLock	epslck;		/* add, del, lookup endpoints */
-static Ep*	eps[Neps];	/* all endpoints known */
-static int	epmax;		/* 1 + last endpoint index used  */
-static int	usbidgen;	/* device address generator */
-
-/*
- * Is there something like this in a library? should it be?
- */
-char*
-seprintdata(char *s, char *se, uchar *d, int n)
-{
-	int i, l;
-
-	s = seprint(s, se, " %#p[%d]: ", d, n);
-	l = n;
-	if(l > 10)
-		l = 10;
-	for(i=0; i<l; i++)
-		s = seprint(s, se, " %2.2ux", d[i]);
-	if(l < n)
-		s = seprint(s, se, "...");
-	return s;
-}
-
-static int
-name2speed(char *name)
-{
-	int i;
-
-	for(i = 0; i < nelem(spname); i++)
-		if(strcmp(name, spname[i]) == 0)
-			return i;
-	return Nospeed;
-}
-
-static int
-name2ttype(char *name)
-{
-	int i;
-
-	for(i = 0; i < nelem(ttname); i++)
-		if(strcmp(name, ttname[i]) == 0)
-			return i;
-	/* may be a std. USB ep. type */
-	i = strtol(name, nil, 0);
-	switch(i+1){
-	case Tctl:
-	case Tiso:
-	case Tbulk:
-	case Tintr:
-		return i+1;
-	default:
-		return Tnone;
-	}
-}
-
-static int
-name2mode(char *mode)
-{
-	int i;
-
-	for(i = 0; i < nelem(usbmodename); i++)
-		if(strcmp(mode, usbmodename[i]) == 0)
-			return i;
-	return -1;
-}
-
-static int
-qid2epidx(int q)
-{
-	q = (q-Qep0dir)/4;
-	if(q < 0 || q >= epmax || eps[q] == nil)
-		return -1;
-	return q;
-}
-
-static int
-isqtype(int q, int type)
-{
-	if(q < Qep0dir)
-		return 0;
-	q -= Qep0dir;
-	return (q & 3) == type;
-}
-
-void
-addhcitype(char* t, int (*r)(Hci*))
-{
-	static int ntype;
-
-	if(ntype == Nhcis)
-		panic("too many USB host interface types");
-	hcitypes[ntype].type = t;
-	hcitypes[ntype].reset = r;
-	ntype++;
-}
-
-static char*
-seprintep(char *s, char *se, Ep *ep, int all)
-{
-	static char* dsnames[] = { "config", "enabled", "detached", "reset" };
-	Udev *d;
-	int i;
-	int di;
-
-	d = ep->dev;
-
-	qlock(ep);
-	if(waserror()){
-		qunlock(ep);
-		nexterror();
-	}
-	di = ep->dev->nb;
-	if(all)
-		s = seprint(s, se, "dev %d ep %d ", di, ep->nb);
-	s = seprint(s, se, "%s", dsnames[ep->dev->state]);
-	s = seprint(s, se, " %s", ttname[ep->ttype]);
-	assert(ep->mode == OREAD || ep->mode == OWRITE || ep->mode == ORDWR);
-	s = seprint(s, se, " %s", usbmodename[ep->mode]);
-	s = seprint(s, se, " speed %s", spname[d->speed]);
-	s = seprint(s, se, " maxpkt %ld", ep->maxpkt);
-	s = seprint(s, se, " pollival %ld", ep->pollival);
-	s = seprint(s, se, " samplesz %ld", ep->samplesz);
-	s = seprint(s, se, " hz %ld", ep->hz);
-	s = seprint(s, se, " hub %d", ep->dev->hub);
-	s = seprint(s, se, " port %d", ep->dev->port);
-	if(ep->inuse)
-		s = seprint(s, se, " busy");
-	else
-		s = seprint(s, se, " idle");
-	if(all){
-		s = seprint(s, se, " load %uld", ep->load);
-		s = seprint(s, se, " ref %ld addr %#p", ep->ref, ep);
-		s = seprint(s, se, " idx %d", ep->idx);
-		if(ep->name != nil)
-			s = seprint(s, se, " name '%s'", ep->name);
-		if(ep->tmout != 0)
-			s = seprint(s, se, " tmout");
-		if(ep == ep->ep0){
-			s = seprint(s, se, " ctlrno %#x", ep->hp->ctlrno);
-			s = seprint(s, se, " eps:");
-			for(i = 0; i < nelem(d->eps); i++)
-				if(d->eps[i] != nil)
-					s = seprint(s, se, " ep%d.%d", di, i);
-		}
-	}
-	if(ep->info != nil)
-		s = seprint(s, se, "\n%s %s\n", ep->info, ep->hp->type);
-	else
-		s = seprint(s, se, "\n");
-	qunlock(ep);
-	poperror();
-	return s;
-}
-
-static Ep*
-epalloc(Hci *hp)
-{
-	Ep *ep;
-	int i;
-
-	ep = smalloc(sizeof(Ep));
-	ep->ref = 1;
-	qlock(&epslck);
-	for(i = 0; i < Neps; i++)
-		if(eps[i] == nil)
-			break;
-	if(i == Neps){
-		qunlock(&epslck);
-		free(ep);
-		print("usb: bug: too few endpoints.\n");
-		return nil;
-	}
-	ep->idx = i;
-	if(epmax <= i)
-		epmax = i+1;
-	eps[i] = ep;
-	ep->hp = hp;
-	ep->maxpkt = 8;
-	ep->ntds = 1;
-	ep->samplesz = ep->pollival = ep->hz = 0; /* make them void */
-	qunlock(&epslck);
-	return ep;
-}
-
-static Ep*
-getep(int i)
-{
-	Ep *ep;
-
-	if(i < 0 || i >= epmax || eps[i] == nil)
-		return nil;
-	qlock(&epslck);
-	ep = eps[i];
-	if(ep != nil)
-		incref(ep);
-	qunlock(&epslck);
-	return ep;
-}
-
-static void
-putep(Ep *ep)
-{
-	Udev *d;
-
-	if(ep != nil && decref(ep) == 0){
-		d = ep->dev;
-		deprint("usb: ep%d.%d %#p released\n", d->nb, ep->nb, ep);
-		qlock(&epslck);
-		eps[ep->idx] = nil;
-		if(ep->idx == epmax-1)
-			epmax--;
-		if(ep == ep->ep0 && ep->dev != nil && ep->dev->nb == usbidgen)
-			usbidgen--;
-		qunlock(&epslck);
-		if(d != nil){
-			qlock(ep->ep0);
-			d->eps[ep->nb] = nil;
-			qunlock(ep->ep0);
-		}
-		if(ep->ep0 != ep){
-			putep(ep->ep0);
-			ep->ep0 = nil;
-		}
-		free(ep->info);
-		free(ep->name);
-		free(ep);
-	}
-}
-
-static void
-dumpeps(void)
-{
-	int i;
-	static char buf[512];
-	char *s;
-	char *e;
-	Ep *ep;
-
-	print("usb dump eps: epmax %d Neps %d (ref=1+ for dump):\n", epmax, Neps);
-	for(i = 0; i < epmax; i++){
-		s = buf;
-		e = buf+sizeof(buf);
-		ep = getep(i);
-		if(ep != nil){
-			if(waserror()){
-				putep(ep);
-				nexterror();
-			}
-			s = seprint(s, e, "ep%d.%d ", ep->dev->nb, ep->nb);
-			seprintep(s, e, ep, 1);
-			print("%s", buf);
-			ep->hp->seprintep(buf, e, ep);
-			print("%s", buf);
-			poperror();
-			putep(ep);
-		}
-	}
-	print("usb dump hcis:\n");
-	for(i = 0; i < Nhcis; i++)
-		if(hcis[i] != nil)
-			hcis[i]->dump(hcis[i]);
-}
-
-static int
-newusbid(Hci *)
-{
-	int id;
-
-	qlock(&epslck);
-	id = ++usbidgen;
-	if(id >= 0x7F)
-		print("#u: too many device addresses; reuse them more\n");
-	qunlock(&epslck);
-	return id;
-}
-
-/*
- * Create endpoint 0 for a new device
- */
-static Ep*
-newdev(Hci *hp, int ishub, int isroot)
-{
-	Ep *ep;
-	Udev *d;
-
-	ep = epalloc(hp);
-	d = ep->dev = smalloc(sizeof(Udev));
-	d->nb = newusbid(hp);
-	d->eps[0] = ep;
-	ep->nb = 0;
-	ep->toggle[0] = ep->toggle[1] = 0;
-	d->ishub = ishub;
-	d->isroot = isroot;
-	if(hp->highspeed != 0)
-		d->speed = Highspeed;
-	else
-		d->speed = Fullspeed;
-	d->state = Dconfig;		/* address not yet set */
-	ep->dev = d;
-	ep->ep0 = ep;			/* no ref counted here */
-	ep->ttype = Tctl;
-	ep->tmout = Xfertmout;
-	ep->mode = ORDWR;
-	dprint("newdev %#p ep%d.%d %#p\n", d, d->nb, ep->nb, ep);
-	return ep;
-}
-
-/*
- * Create a new endpoint for the device
- * accessed via the given endpoint 0.
- */
-static Ep*
-newdevep(Ep *ep, int i, int tt, int mode)
-{
-	Ep *nep;
-	Udev *d;
-
-	d = ep->dev;
-	if(d->eps[i] != nil)
-		error("endpoint already in use");
-	nep = epalloc(ep->hp);
-	incref(ep);
-	d->eps[i] = nep;
-	nep->nb = i;
-	nep->toggle[0] = nep->toggle[1] = 0;
-	nep->ep0 = ep;
-	nep->dev = ep->dev;
-	nep->mode = mode;
-	nep->ttype = tt;
-	nep->debug = ep->debug;
-	/* set defaults */
-	switch(tt){
-	case Tctl:
-		nep->tmout = Xfertmout;
-		break;
-	case Tintr:
-		nep->pollival = 10;
-		break;
-	case Tiso:
-		nep->tmout = Xfertmout;
-		nep->pollival = 10;
-		nep->samplesz = 4;
-		nep->hz = 44100;
-		break;
-	}
-	deprint("newdevep ep%d.%d %#p\n", d->nb, nep->nb, nep);
-	return ep;
-}
-
-static int
-epdataperm(int mode)
-{
-
-	switch(mode){
-	case OREAD:
-		return 0440|DMEXCL;
-		break;
-	case OWRITE:
-		return 0220|DMEXCL;
-		break;
-	default:
-		return 0660|DMEXCL;
-	}
-}
-
-static int
-usbgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp)
-{
-	Qid q;
-	Dirtab *dir;
-	int perm;
-	char *se;
-	Ep *ep;
-	int nb;
-	int mode;
-
-	if(0)ddprint("usbgen q %#x s %d...", QID(c->qid), s);
-	if(s == DEVDOTDOT){
-		if(QID(c->qid) <= Qusbdir){
-			mkqid(&q, Qdir, 0, QTDIR);
-			devdir(c, q, "#u", 0, eve, 0555, dp);
-		}else{
-			mkqid(&q, Qusbdir, 0, QTDIR);
-			devdir(c, q, "usb", 0, eve, 0555, dp);
-		}
-		if(0)ddprint("ok\n");
-		return 1;
-	}
-
-	switch(QID(c->qid)){
-	case Qdir:				/* list #u */
-		if(s == 0){
-			mkqid(&q, Qusbdir, 0, QTDIR);
-			devdir(c, q, "usb", 0, eve, 0555, dp);
-			if(0)ddprint("ok\n");
-			return 1;
-		}
-		s--;
-		if(s < 0 || s >= epmax)
-			goto Fail;
-		ep = getep(s);
-		if(ep == nil || ep->name == nil){
-			if(ep != nil)
-				putep(ep);
-			if(0)ddprint("skip\n");
-			return 0;
-		}
-		if(waserror()){
-			putep(ep);
-			nexterror();
-		}
-		mkqid(&q, Qep0io+s*4, 0, QTFILE);
-		devdir(c, q, ep->name, 0, eve, epdataperm(ep->mode), dp);
-		putep(ep);
-		poperror();
-		if(0)ddprint("ok\n");
-		return 1;
-
-	case Qusbdir:				/* list #u/usb */
-	Usbdir:
-		if(s < nelem(usbdir)){
-			dir = &usbdir[s];
-			mkqid(&q, dir->qid.path, 0, QTFILE);
-			devdir(c, q, dir->name, dir->length, eve, dir->perm, dp);
-			if(0)ddprint("ok\n");
-			return 1;
-		}
-		s -= nelem(usbdir);
-		if(s < 0 || s >= epmax)
-			goto Fail;
-		ep = getep(s);
-		if(ep == nil){
-			if(0)ddprint("skip\n");
-			return 0;
-		}
-		if(waserror()){
-			putep(ep);
-			nexterror();
-		}
-		se = up->genbuf+sizeof(up->genbuf);
-		seprint(up->genbuf, se, "ep%d.%d", ep->dev->nb, ep->nb);
-		mkqid(&q, Qep0dir+4*s, 0, QTDIR);
-		putep(ep);
-		poperror();
-		devdir(c, q, up->genbuf, 0, eve, 0755, dp);
-		if(0)ddprint("ok\n");
-		return 1;
-
-	case Qctl:
-		s = 0;
-		goto Usbdir;
-
-	default:				/* list #u/usb/epN.M */
-		nb = qid2epidx(QID(c->qid));
-		ep = getep(nb);
-		if(ep == nil)
-			goto Fail;
-		mode = ep->mode;
-		putep(ep);
-		if(isqtype(QID(c->qid), Qepdir)){
-		Epdir:
-			switch(s){
-			case 0:
-				mkqid(&q, Qep0io+nb*4, 0, QTFILE);
-				perm = epdataperm(mode);
-				devdir(c, q, "data", 0, eve, perm, dp);
-				break;
-			case 1:
-				mkqid(&q, Qep0ctl+nb*4, 0, QTFILE);
-				devdir(c, q, "ctl", 0, eve, 0664, dp);
-				break;
-			default:
-				goto Fail;
-			}
-		}else if(isqtype(QID(c->qid), Qepctl)){
-			s = 1;
-			goto Epdir;
-		}else{
-			s = 0;
-			goto Epdir;
-		}
-		if(0)ddprint("ok\n");
-		return 1;
-	}
-Fail:
-	if(0)ddprint("fail\n");
-	return -1;
-}
-
-static Hci*
-hciprobe(int cardno, int ctlrno)
-{
-	Hci *hp;
-	char *type;
-	char name[64];
-	static int epnb = 1;	/* guess the endpoint nb. for the controller */
-
-	ddprint("hciprobe %d %d\n", cardno, ctlrno);
-	hp = smalloc(sizeof(Hci));
-	hp->ctlrno = ctlrno;
-
-	if(cardno < 0)
-		for(cardno = 0; cardno < Nhcis; cardno++){
-			if(hcitypes[cardno].type == nil)
-				break;
-			type = hp->type;
-			if(type==nil || *type==0)
-				type = "uhci";
-			if(cistrcmp(hcitypes[cardno].type, type) == 0)
-				break;
-		}
-
-	if(cardno >= Nhcis || hcitypes[cardno].type == nil){
-		free(hp);
-		return nil;
-	}
-	dprint("%s...", hcitypes[cardno].type);
-	if(hcitypes[cardno].reset(hp) < 0){
-		free(hp);
-		return nil;
-	}
-
-	snprint(name, sizeof(name), "usb%s", hcitypes[cardno].type);
-	intrenable(hp->irq, hp->interrupt, hp, UNKNOWN, name);
-
-	print("#u/usb/ep%d.0: %s: port %#luX irq %d\n",
-		epnb, hcitypes[cardno].type, hp->port, hp->irq);
-	epnb++;
-
-	return hp;
-}
-
-static void
-usbreset(void)
-{
-	int cardno, ctlrno;
-	Hci *hp;
-
-	dprint("usbreset\n");
-
-	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++)
-		if((hp = hciprobe(-1, ctlrno)) != nil)
-			hcis[ctlrno] = hp;
-	cardno = ctlrno = 0;
-	while(cardno < Nhcis && ctlrno < Nhcis && hcitypes[cardno].type != nil)
-		if(hcis[ctlrno] != nil)
-			ctlrno++;
-		else{
-			hp = hciprobe(cardno, ctlrno);
-			if(hp == nil)
-				cardno++;
-			hcis[ctlrno++] = hp;
-		}
-	if(hcis[Nhcis-1] != nil)
-		print("usbreset: bug: Nhcis too small\n");
-}
-
-static void
-usbinit(void)
-{
-	Hci *hp;
-	int ctlrno;
-	Ep *d;
-	char info[40];
-
-	dprint("usbinit\n");
-	for(ctlrno = 0; ctlrno < Nhcis; ctlrno++){
-		hp = hcis[ctlrno];
-		if(hp != nil){
-			if(hp->init != nil)
-				hp->init(hp);
-			d = newdev(hp, 1, 1);		/* new root hub */
-			d->dev->state = Denabled;	/* although addr == 0 */
-			d->maxpkt = 64;
-			snprint(info, sizeof(info), "ports %d", hp->nports);
-			kstrdup(&d->info, info);
-		}
-	}
-}
-
-static Chan*
-usbattach(char *spec)
-{
-	return devattach(L'u', spec);
-}
-
-static Walkqid*
-usbwalk(Chan *c, Chan *nc, char **name, int nname)
-{
-	return devwalk(c, nc, name, nname, nil, 0, usbgen);
-}
-
-static int
-usbstat(Chan *c, uchar *db, int n)
-{
-	return devstat(c, db, n, nil, 0, usbgen);
-}
-
-/*
- * µs for the given transfer, for bandwidth allocation.
- * This is a very rough worst case for what 5.11.3
- * of the usb 2.0 spec says.
- * Also, we are using maxpkt and not actual transfer sizes.
- * Only when we are sure we
- * are not exceeding b/w might we consider adjusting it.
- */
-static ulong
-usbload(int speed, int maxpkt)
-{
-	enum{ Hostns = 1000, Hubns = 333 };
-	ulong l;
-	ulong bs;
-
-	l = 0;
-	bs = 10UL * maxpkt;
-	switch(speed){
-	case Highspeed:
-		l = 55*8*2 + 2 * (3 + bs) + Hostns;
-		break;
-	case Fullspeed:
-		l = 9107 + 84 * (4 + bs) + Hostns;
-		break;
-	case Lowspeed:
-		l = 64107 + 2 * Hubns + 667 * (3 + bs) + Hostns;
-		break;
-	default:
-		print("usbload: bad speed %d\n", speed);
-		/* let it run */
-	}
-	return l / 1000UL;	/* in µs */
-}
-
-static Chan*
-usbopen(Chan *c, int omode)
-{
-	int q;
-	Ep *ep;
-	int mode;
-
-	mode = openmode(omode);
-	q = QID(c->qid);
-
-	if(q >= Qep0dir && qid2epidx(q) < 0)
-		error(Eio);
-	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
-		return devopen(c, omode, nil, 0, usbgen);
-
-	ep = getep(qid2epidx(q));
-	if(ep == nil)
-		error(Eio);
-	deprint("usbopen q %#x fid %d omode %d\n", q, c->fid, mode);
-	if(waserror()){
-		putep(ep);
-		nexterror();
-	}
-	qlock(ep);
-	if(ep->inuse){
-		qunlock(ep);
-		error(Einuse);
-	}
-	ep->inuse = 1;
-	qunlock(ep);
-	if(waserror()){
-		ep->inuse = 0;
-		nexterror();
-	}
-	if(mode != OREAD && ep->mode == OREAD)
-		error(Eperm);
-	if(mode != OWRITE && ep->mode == OWRITE)
-		error(Eperm);
-	if(ep->ttype == Tnone)
-		error(Enotconf);
-	ep->clrhalt = 0;
-	ep->rhrepl = -1;
-	if(ep->load == 0)
-		ep->load = usbload(ep->dev->speed, ep->maxpkt);
-	ep->hp->epopen(ep);
-
-	poperror();	/* ep->inuse */
-	poperror();	/* don't putep(): ref kept for fid using the ep. */
-
-	c->mode = mode;
-	c->flag |= COPEN;
-	c->offset = 0;
-	c->aux = nil;	/* paranoia */
-	return c;
-}
-
-static void
-epclose(Ep *ep)
-{
-	qlock(ep);
-	if(waserror()){
-		qunlock(ep);
-		nexterror();
-	}
-	if(ep->inuse){
-		ep->hp->epclose(ep);
-		ep->inuse = 0;
-	}
-	qunlock(ep);
-	poperror();
-}
-
-static void
-usbclose(Chan *c)
-{
-	int q;
-	Ep *ep;
-
-	q = QID(c->qid);
-	if(q < Qep0dir || isqtype(q, Qepctl) || isqtype(q, Qepdir))
-		return;
-
-	ep = getep(qid2epidx(q));
-	if(ep == nil)
-		return;
-	deprint("usbclose q %#x fid %d ref %ld\n", q, c->fid, ep->ref);
-	if(waserror()){
-		putep(ep);
-		nexterror();
-	}
-	if(c->flag & COPEN){
-		free(c->aux);
-		c->aux = nil;
-		epclose(ep);
-		putep(ep);	/* release ref kept since usbopen */
-		c->flag &= ~COPEN;
-	}
-	poperror();
-	putep(ep);
-}
-
-static long
-ctlread(Chan *c, void *a, long n, vlong offset)
-{
-	int q;
-	char *s;
-	char *us;
-	char *se;
-	Ep *ep;
-	int i;
-
-	q = QID(c->qid);
-	us = s = smalloc(READSTR);
-	se = s + READSTR;
-	if(waserror()){
-		free(us);
-		nexterror();
-	}
-	if(q == Qctl)
-		for(i = 0; i < epmax; i++){
-			ep = getep(i);
-			if(ep != nil){
-				if(waserror()){
-					putep(ep);
-					nexterror();
-				}
-				s = seprint(s, se, "ep%d.%d ", ep->dev->nb, ep->nb);
-				s = seprintep(s, se, ep, 0);
-				poperror();
-			}
-			putep(ep);
-		}
-	else{
-		ep = getep(qid2epidx(q));
-		if(ep == nil)
-			error(Eio);
-		if(waserror()){
-			putep(ep);
-			nexterror();
-		}
-		if(c->aux != nil){
-			/* After a new endpoint request we read
-			 * the new endpoint name back.
-			 */
-			strecpy(s, se, c->aux);
-			free(c->aux);
-			c->aux = nil;
-		}else
-			seprintep(s, se, ep, 0);
-		poperror();
-		putep(ep);
-	}
-	n = readstr(offset, a, n, us);
-	poperror();
-	free(us);
-	return n;
-}
-
-/*
- * Fake root hub emulation.
- */
-static long
-rhubread(Ep *ep, void *a, long n)
-{
-	char *b;
-
-	if(ep->dev->isroot == 0 || ep->nb != 0 || n < 2)
-		return -1;
-	if(ep->rhrepl < 0)
-		return -1;
-
-	b = a;
-	memset(b, 0, n);
-	PUT2(b, ep->rhrepl);
-	ep->rhrepl = -1;
-	return n;
-}
-
-static long
-rhubwrite(Ep *ep, void *a, long n)
-{
-	uchar *s;
-	int cmd;
-	int feature;
-	int port;
-	Hci *hp;
-
-	if(ep->dev == nil || ep->dev->isroot == 0 || ep->nb != 0)
-		return -1;
-	if(n != Rsetuplen)
-		error("root hub is a toy hub");
-	ep->rhrepl = -1;
-	s = a;
-	if(s[Rtype] != (Rh2d|Rclass|Rother) && s[Rtype] != (Rd2h|Rclass|Rother))
-		error("root hub is a toy hub");
-	hp = ep->hp;
-	cmd = s[Rreq];
-	feature = GET2(s+Rvalue);
-	port = GET2(s+Rindex);
-	if(port < 1 || port > hp->nports)
-		error("bad hub port number");
-	switch(feature){
-	case Rportenable:
-		ep->rhrepl = hp->portenable(hp, port, cmd == Rsetfeature);
-		break;
-	case Rportreset:
-		ep->rhrepl = hp->portreset(hp, port, cmd == Rsetfeature);
-		break;
-	case Rgetstatus:
-		ep->rhrepl = hp->portstatus(hp, port);
-		break;
-	default:
-		ep->rhrepl = 0;
-	}
-	return n;
-}
-
-static long
-usbread(Chan *c, void *a, long n, vlong offset)
-{
-	int q;
-	Ep *ep;
-	int nr;
-
-	q = QID(c->qid);
-
-	if(c->qid.type == QTDIR)
-		return devdirread(c, a, n, nil, 0, usbgen);
-
-	if(q == Qctl || isqtype(q, Qepctl))
-		return ctlread(c, a, n, offset);
-
-	ep = getep(qid2epidx(q));
-	if(ep == nil)
-		error(Eio);
-	if(waserror()){
-		putep(ep);
-		nexterror();
-	}
-	if(ep->dev->state == Ddetach)
-		error(Edetach);
-	if(ep->mode == OWRITE || ep->inuse == 0)
-		error(Ebadusefd);
-	switch(ep->ttype){
-	case Tnone:
-		error("endpoint not configured");
-	case Tctl:
-		nr = rhubread(ep, a, n);
-		if(nr >= 0){
-			n = nr;
-			break;
-		}
-		/* else fall */
-	default:
-		ddeprint("\nusbread q %#x fid %d cnt %ld off %lld\n",q,c->fid,n,offset);
-		n = ep->hp->epread(ep, a, n);
-		break;
-	}
-	poperror();
-	putep(ep);
-	return n;
-}
-
-static long
-pow2(int n)
-{
-	return 1 << n;
-}
-
-static void
-setmaxpkt(Ep *ep, char* s)
-{
-	long spp;	/* samples per packet */
-
-	if(ep->dev->speed == Highspeed)
-		spp = (ep->hz * ep->pollival * ep->ntds + 7999) / 8000;
-	else
-		spp = (ep->hz * ep->pollival + 999) / 1000;
-	ep->maxpkt = spp * ep->samplesz;
-	deprint("usb: %s: setmaxpkt: hz %ld poll %ld"
-		" ntds %d %s speed -> spp %ld maxpkt %ld\n", s,
-		ep->hz, ep->pollival, ep->ntds, spname[ep->dev->speed],
-		spp, ep->maxpkt);
-	if(ep->maxpkt > 1024){
-		print("usb: %s: maxpkt %ld > 1024. truncating\n", s, ep->maxpkt);
-		ep->maxpkt = 1024;
-	}
-}
-
-/*
- * Many endpoint ctls. simply update the portable representation
- * of the endpoint. The actual controller driver will look
- * at them to setup the endpoints as dictated.
- */
-static long
-epctl(Ep *ep, Chan *c, void *a, long n)
-{
-	int i, l, mode, nb, tt;
-	char *b, *s;
-	Cmdbuf *cb;
-	Cmdtab *ct;
-	Ep *nep;
-	Udev *d;
-	static char *Info = "info ";
-
-	d = ep->dev;
-
-	cb = parsecmd(a, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-	ct = lookupcmd(cb, epctls, nelem(epctls));
-	if(ct == nil)
-		error(Ebadctl);
-	i = ct->index;
-	if(i == CMnew || i == CMspeed || i == CMhub || i == CMpreset)
-		if(ep != ep->ep0)
-			error("allowed only on a setup endpoint");
-	if(i != CMclrhalt && i != CMdetach && i != CMdebugep && i != CMname)
-		if(ep != ep->ep0 && ep->inuse != 0)
-			error("must configure before using");
-	switch(i){
-	case CMnew:
-		deprint("usb epctl %s\n", cb->f[0]);
-		nb = strtol(cb->f[1], nil, 0);
-		if(nb < 0 || nb >= Ndeveps)
-			error("bad endpoint number");
-		tt = name2ttype(cb->f[2]);
-		if(tt == Tnone)
-			error("unknown endpoint type");
-		mode = name2mode(cb->f[3]);
-		if(mode < 0)
-			error("unknown i/o mode");
-		newdevep(ep, nb, tt, mode);
-		break;
-	case CMnewdev:
-		deprint("usb epctl %s\n", cb->f[0]);
-		if(ep != ep->ep0 || d->ishub == 0)
-			error("not a hub setup endpoint");
-		l = name2speed(cb->f[1]);
-		if(l == Nospeed)
-			error("speed must be full|low|high");
-		nep = newdev(ep->hp, 0, 0);
-		nep->dev->speed = l;
-		if(nep->dev->speed  != Lowspeed)
-			nep->maxpkt = 64;	/* assume full speed */
-		nep->dev->hub = d->nb;
-		nep->dev->port = atoi(cb->f[2]);
-		/* next read request will read
-		 * the name for the new endpoint
-		 */
-		l = sizeof(up->genbuf);
-		snprint(up->genbuf, l, "ep%d.%d", nep->dev->nb, nep->nb);
-		kstrdup(&c->aux, up->genbuf);
-		break;
-	case CMhub:
-		deprint("usb epctl %s\n", cb->f[0]);
-		d->ishub = 1;
-		break;
-	case CMspeed:
-		l = name2speed(cb->f[1]);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(l == Nospeed)
-			error("speed must be full|low|high");
-		qlock(ep->ep0);
-		d->speed = l;
-		qunlock(ep->ep0);
-		break;
-	case CMmaxpkt:
-		l = strtoul(cb->f[1], nil, 0);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(l < 1 || l > 1024)
-			error("maxpkt not in [1:1024]");
-		qlock(ep);
-		ep->maxpkt = l;
-		qunlock(ep);
-		break;
-	case CMntds:
-		l = strtoul(cb->f[1], nil, 0);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(l < 1 || l > 3)
-			error("ntds not in [1:3]");
-		qlock(ep);
-		ep->ntds = l;
-		qunlock(ep);
-		break;
-	case CMpollival:
-		if(ep->ttype != Tintr && ep->ttype != Tiso)
-			error("not an intr or iso endpoint");
-		l = strtoul(cb->f[1], nil, 0);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(ep->ttype == Tiso ||
-		   (ep->ttype == Tintr && ep->dev->speed == Highspeed)){
-			if(l < 1 || l > 16)
-				error("pollival power not in [1:16]");
-			l = pow2(l-1);
-		}else
-			if(l < 1 || l > 255)
-				error("pollival not in [1:255]");
-		qlock(ep);
-		ep->pollival = l;
-		if(ep->ttype == Tiso)
-			setmaxpkt(ep, "pollival");
-		qunlock(ep);
-		break;
-	case CMsamplesz:
-		if(ep->ttype != Tiso)
-			error("not an iso endpoint");
-		l = strtoul(cb->f[1], nil, 0);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(l <= 0 || l > 8)
-			error("samplesz not in [1:8]");
-		qlock(ep);
-		ep->samplesz = l;
-		setmaxpkt(ep, "samplesz");
-		qunlock(ep);
-		break;
-	case CMhz:
-		if(ep->ttype != Tiso)
-			error("not an iso endpoint");
-		l = strtoul(cb->f[1], nil, 0);
-		deprint("usb epctl %s %d\n", cb->f[0], l);
-		if(l <= 0 || l > 100000)
-			error("hz not in [1:100000]");
-		qlock(ep);
-		ep->hz = l;
-		setmaxpkt(ep, "hz");
-		qunlock(ep);
-		break;
-	case CMclrhalt:
-		qlock(ep);
-		deprint("usb epctl %s\n", cb->f[0]);
-		ep->clrhalt = 1;
-		qunlock(ep);
-		break;
-	case CMinfo:
-		deprint("usb epctl %s\n", cb->f[0]);
-		l = strlen(Info);
-		s = a;
-		if(n < l+2 || strncmp(Info, s, l) != 0)
-			error(Ebadctl);
-		if(n > 1024)
-			n = 1024;
-		b = smalloc(n);
-		memmove(b, s+l, n-l);
-		b[n-l] = 0;
-		if(b[n-l-1] == '\n')
-			b[n-l-1] = 0;
-		qlock(ep);
-		free(ep->info);
-		ep->info = b;
-		qunlock(ep);
-		break;
-	case CMaddress:
-		deprint("usb epctl %s\n", cb->f[0]);
-		ep->dev->state = Denabled;
-		break;
-	case CMdetach:
-		if(ep->dev->isroot != 0)
-			error("can't detach a root hub");
-		deprint("usb epctl %s ep%d.%d\n",
-			cb->f[0], ep->dev->nb, ep->nb);
-		ep->dev->state = Ddetach;
-		/* Release file system ref. for its endpoints */
-		for(i = 0; i < nelem(ep->dev->eps); i++)
-			putep(ep->dev->eps[i]);
-		break;
-	case CMdebugep:
-		if(strcmp(cb->f[1], "on") == 0)
-			ep->debug = 1;
-		else if(strcmp(cb->f[1], "off") == 0)
-			ep->debug = 0;
-		else
-			ep->debug = strtoul(cb->f[1], nil, 0);
-		print("usb: ep%d.%d debug %d\n",
-			ep->dev->nb, ep->nb, ep->debug);
-		break;
-	case CMname:
-		deprint("usb epctl %s %s\n", cb->f[0], cb->f[1]);
-		validname(cb->f[1], 0);
-		kstrdup(&ep->name, cb->f[1]);
-		break;
-	case CMtmout:
-		deprint("usb epctl %s\n", cb->f[0]);
-		if(ep->ttype == Tiso || ep->ttype == Tctl)
-			error("ctl ignored for this endpoint type");
-		ep->tmout = strtoul(cb->f[1], nil, 0);
-		if(ep->tmout != 0 && ep->tmout < Xfertmout)
-			ep->tmout = Xfertmout;
-		break;
-	case CMpreset:
-		deprint("usb epctl %s\n", cb->f[0]);
-		if(ep->ttype != Tctl)
-			error("not a control endpoint");
-		if(ep->dev->state != Denabled)
-			error("forbidden on devices not enabled");
-		ep->dev->state = Dreset;
-		break;
-	default:
-		panic("usb: unknown epctl %d", ct->index);
-	}
-	free(cb);
-	poperror();
-	return n;
-}
-
-static long
-usbctl(void *a, long n)
-{
-	Cmdtab *ct;
-	Cmdbuf *cb;
-	Ep *ep;
-	int i;
-
-	cb = parsecmd(a, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-	ct = lookupcmd(cb, usbctls, nelem(usbctls));
-	dprint("usb ctl %s\n", cb->f[0]);
-	switch(ct->index){
-	case CMdebug:
-		if(strcmp(cb->f[1], "on") == 0)
-			debug = 1;
-		else if(strcmp(cb->f[1], "off") == 0)
-			debug = 0;
-		else
-			debug = strtol(cb->f[1], nil, 0);
-		print("usb: debug %d\n", debug);
-		for(i = 0; i < epmax; i++)
-			if((ep = getep(i)) != nil){
-				ep->hp->debug(ep->hp, debug);
-				putep(ep);
-			}
-		break;
-	case CMdump:
-		dumpeps();
-		break;
-	}
-	free(cb);
-	poperror();
-	return n;
-}
-
-static long
-ctlwrite(Chan *c, void *a, long n)
-{
-	int q;
-	Ep *ep;
-
-	q = QID(c->qid);
-	if(q == Qctl)
-		return usbctl(a, n);
-
-	ep = getep(qid2epidx(q));
-	if(ep == nil)
-		error(Eio);
-	if(waserror()){
-		putep(ep);
-		nexterror();
-	}
-	if(ep->dev->state == Ddetach)
-		error(Edetach);
-	if(isqtype(q, Qepctl) && c->aux != nil){
-		/* Be sure we don't keep a cloned ep name */
-		free(c->aux);
-		c->aux = nil;
-		error("read, not write, expected");
-	}
-	n = epctl(ep, c, a, n);
-	putep(ep);
-	poperror();
-	return n;
-}
-
-static long
-usbwrite(Chan *c, void *a, long n, vlong off)
-{
-	int nr, q;
-	Ep *ep;
-
-	if(c->qid.type == QTDIR)
-		error(Eisdir);
-
-	q = QID(c->qid);
-
-	if(q == Qctl || isqtype(q, Qepctl))
-		return ctlwrite(c, a, n);
-
-	ep = getep(qid2epidx(q));
-	if(ep == nil)
-		error(Eio);
-	if(waserror()){
-		putep(ep);
-		nexterror();
-	}
-	if(ep->dev->state == Ddetach)
-		error(Edetach);
-	if(ep->mode == OREAD || ep->inuse == 0)
-		error(Ebadusefd);
-
-	switch(ep->ttype){
-	case Tnone:
-		error("endpoint not configured");
-	case Tctl:
-		nr = rhubwrite(ep, a, n);
-		if(nr >= 0){
-			n = nr;
-			break;
-		}
-		/* else fall */
-	default:
-		ddeprint("\nusbwrite q %#x fid %d cnt %ld off %lld\n",q, c->fid, n, off);
-		ep->hp->epwrite(ep, a, n);
-	}
-	putep(ep);
-	poperror();
-	return n;
-}
-
-Block*
-usbbread(Chan *c, long n, ulong offset)
-{
-	Block *bp;
-
-	bp = allocb(n);
-	if(bp == 0)
-		error(Enomem);
-	if(waserror()) {
-		freeb(bp);
-		nexterror();
-	}
-	bp->wp += usbread(c, bp->wp, n, offset);
-	poperror();
-	return bp;
-}
-
-long
-usbbwrite(Chan *c, Block *bp, ulong offset)
-{
-	long n;
-
-	if(waserror()) {
-		freeb(bp);
-		nexterror();
-	}
-	n = usbwrite(c, bp->rp, BLEN(bp), offset);
-	poperror();
-	freeb(bp);
-
-	return n;
-}
-
-void
-usbshutdown(void)
-{
-	Hci *hp;
-	int i;
-
-	for(i = 0; i < Nhcis; i++){
-		hp = hcis[i];
-		if(hp == nil)
-			continue;
-		if(hp->shutdown == nil)
-			print("#u: no shutdown function for %s\n", hp->type);
-		else
-			hp->shutdown(hp);
-	}
-}
-
-Dev usbdevtab = {
-	L'u',
-	"usb",
-
-	usbreset,
-	usbinit,
-	usbshutdown,
-	usbattach,
-	usbwalk,
-	usbstat,
-	usbopen,
-	devcreate,
-	usbclose,
-	usbread,
-	usbbread,
-	usbwrite,
-	usbbwrite,
-	devremove,
-	devwstat,
-};

+ 0 - 230
sys/src/9/bcm/dma.c

@@ -1,230 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2835 dma controller
- *
- * simplest to use only channels 0-6
- *	channels 7-14 have reduced functionality
- *	channel 15 is at a weird address
- *	channels 0 and 15 have an "external 128 bit 8 word read FIFO"
- *	  for memory to memory transfers
- *
- * Experiments show that only channels 2-5,11-12 work with mmc
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define DMAREGS	(VIRTIO+0x7000)
-
-#define DBG	if(Dbg)
-
-enum {
-	Nchan		= 7,		/* number of dma channels */
-	Regsize		= 0x100,	/* size of regs for each chan */
-	Cbalign		= 32,		/* control block byte alignment */
-	Dbg		= 0,
-	
-	/* registers for each dma controller */
-	Cs		= 0x00>>2,
-	Conblkad	= 0x04>>2,
-	Ti		= 0x08>>2,
-	Sourcead	= 0x0c>>2,
-	Destad		= 0x10>>2,
-	Txfrlen		= 0x14>>2,
-	Stride		= 0x18>>2,
-	Nextconbk	= 0x1c>>2,
-	Debug		= 0x20>>2,
-
-	/* collective registers */
-	Intstatus	= 0xfe0>>2,
-	Enable		= 0xff0>>2,
-
-	/* Cs */
-	Reset		= 1<<31,
-	Abort		= 1<<30,
-	Error		= 1<<8,
-	Waitwrite	= 1<<6,
-	Waitdreq	= 1<<5,
-	Paused		= 1<<4,
-	Dreq		= 1<<3,
-	Int		= 1<<2,
-	End		= 1<<1,
-	Active		= 1<<0,
-
-	/* Ti */
-	Permapshift= 16,
-	Srcignore	= 1<<11,
-	Srcdreq		= 1<<10,
-	Srcwidth128	= 1<<9,
-	Srcinc		= 1<<8,
-	Destignore	= 1<<7,
-	Destdreq	= 1<<6,
-	Destwidth128	= 1<<5,
-	Destinc		= 1<<4,
-	Waitresp	= 1<<3,
-	Tdmode		= 1<<1,
-	Inten		= 1<<0,
-
-	/* Debug */
-	Lite		= 1<<28,
-	Clrerrors	= 7<<0,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Cb Cb;
-
-struct Ctlr {
-	u32int	*regs;
-	Cb	*cb;
-	Rendez	r;
-	int	dmadone;
-};
-
-struct Cb {
-	u32int	ti;
-	u32int	sourcead;
-	u32int	destad;
-	u32int	txfrlen;
-	u32int	stride;
-	u32int	nextconbk;
-	u32int	reserved[2];
-};
-
-static Ctlr dma[Nchan];
-static u32int *dmaregs = (u32int*)DMAREGS;
-
-static void
-dump(char *msg, uchar *p, int n)
-{
-	print("%s", msg);
-	while(n-- > 0)
-		print(" %2.2x", *p++);
-	print("\n");
-}
-
-static void
-dumpdregs(char *msg, u32int *r)
-{
-	int i;
-
-	print("%s: %#p =", msg, r);
-	for(i = 0; i < 9; i++)
-		print(" %8.8uX", r[i]);
-	print("\n");
-}
-
-static int
-dmadone(void *a)
-{
-	return ((Ctlr*)a)->dmadone;
-}
-
-static void
-dmainterrupt(Ureg*, void *a)
-{
-	Ctlr *ctlr;
-
-	ctlr = a;
-	ctlr->regs[Cs] = Int;
-	ctlr->dmadone = 1;
-	wakeup(&ctlr->r);
-}
-
-void
-dmastart(int chan, int dev, int dir, void *src, void *dst, int len)
-{
-	Ctlr *ctlr;
-	Cb *cb;
-	int ti;
-
-	ctlr = &dma[chan];
-	if(ctlr->regs == nil){
-		ctlr->regs = (u32int*)(DMAREGS + chan*Regsize);
-		ctlr->cb = xspanalloc(sizeof(Cb), Cbalign, 0);
-		assert(ctlr->cb != nil);
-		dmaregs[Enable] |= 1<<chan;
-		ctlr->regs[Cs] = Reset;
-		while(ctlr->regs[Cs] & Reset)
-			;
-		intrenable(IRQDMA(chan), dmainterrupt, ctlr, 0, "dma");
-	}
-	cb = ctlr->cb;
-	ti = 0;
-	switch(dir){
-	case DmaD2M:
-		cachedwbinvse(dst, len);
-		ti = Srcdreq | Destinc;
-		cb->sourcead = DMAIO(src);
-		cb->destad = DMAADDR(dst);
-		break;
-	case DmaM2D:
-		cachedwbse(src, len);
-		ti = Destdreq | Srcinc;
-		cb->sourcead = DMAADDR(src);
-		cb->destad = DMAIO(dst);
-		break;
-	case DmaM2M:
-		cachedwbse(src, len);
-		cachedwbinvse(dst, len);
-		ti = Srcinc | Destinc;
-		cb->sourcead = DMAADDR(src);
-		cb->destad = DMAADDR(dst);
-		break;
-	}
-	cb->ti = ti | dev<<Permapshift | Inten;
-	cb->txfrlen = len;
-	cb->stride = 0;
-	cb->nextconbk = 0;
-	cachedwbse(cb, sizeof(Cb));
-	ctlr->regs[Cs] = 0;
-	microdelay(1);
-	ctlr->regs[Conblkad] = DMAADDR(cb);
-	DBG print("dma start: %ux %ux %ux %ux %ux %ux\n",
-		cb->ti, cb->sourcead, cb->destad, cb->txfrlen,
-		cb->stride, cb->nextconbk);
-	DBG print("intstatus %ux\n", dmaregs[Intstatus]);
-	dmaregs[Intstatus] = 0;
-	ctlr->regs[Cs] = Int;
-	microdelay(1);
-	coherence();
-	DBG dumpdregs("before Active", ctlr->regs);
-	ctlr->regs[Cs] = Active;
-	DBG dumpdregs("after Active", ctlr->regs);
-}
-
-int
-dmawait(int chan)
-{
-	Ctlr *ctlr;
-	u32int *r;
-	int s;
-
-	ctlr = &dma[chan];
-	tsleep(&ctlr->r, dmadone, ctlr, 3000);
-	ctlr->dmadone = 0;
-	r = ctlr->regs;
-	DBG dumpdregs("after sleep", r);
-	s = r[Cs];
-	if((s & (Active|End|Error)) != End){
-		print("dma chan %d %s Cs %ux Debug %ux\n", chan,
-			(s&End)? "error" : "timeout", s, r[Debug]);
-		r[Cs] = Reset;
-		r[Debug] = Clrerrors;
-		return -1;
-	}
-	r[Cs] = Int|End;
-	return 0;
-}

+ 0 - 519
sys/src/9/bcm/dwcotg.h

@@ -1,519 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * USB host driver for BCM2835
- *	Synopsis DesignWare Core USB 2.0 OTG controller
- *
- * Device register definitions
- */
-
-typedef unsigned int Reg;
-typedef struct Dwcregs Dwcregs;
-typedef struct Hostchan Hostchan;
-
-enum {
-	Maxchans	= 16,	/* actual number of channels in ghwcfg2 */
-};
-
-struct Dwcregs {
-	/* Core global registers 0x000-0x140 */
-	Reg	gotgctl;	/* OTG Control and Status */
-	Reg	gotgint;	/* OTG Interrupt */
-	Reg	gahbcfg;	/* Core AHB Configuration */
-	Reg	gusbcfg;	/* Core USB Configuration */
-	Reg	grstctl;	/* Core Reset */
-	Reg	gintsts;	/* Core Interrupt */
-	Reg	gintmsk;	/* Core Interrupt Mask */
-	Reg	grxstsr;	/* Receive Status Queue Read (RO) */
-	Reg	grxstsp;	/* Receive Status Queue Read & POP (RO) */
-	Reg	grxfsiz;	/* Receive FIFO Size */
-	Reg	gnptxfsiz;	/* Non Periodic Transmit FIFO Size */
-	Reg	gnptxsts;	/* Non Periodic Transmit FIFO/Queue Status (RO) */
-	Reg	gi2cctl;	/* I2C Access */
-	Reg	gpvndctl;	/* PHY Vendor Control */
-	Reg	ggpio;		/* General Purpose Input/Output */
-	Reg	guid;		/* User ID */
-	Reg	gsnpsid;	/* Synopsys ID (RO) */
-	Reg	ghwcfg1;	/* User HW Config1 (RO) (DEVICE) */
-	Reg	ghwcfg2;	/* User HW Config2 (RO) */
-	Reg	ghwcfg3;	/* User HW Config3 (RO) */
-	Reg	ghwcfg4;	/* User HW Config4 (RO)*/
-	Reg	glpmcfg;	/* Core LPM Configuration */
-	Reg	gpwrdn;		/* Global PowerDn */
-	Reg	gdfifocfg;	/* Global DFIFO SW Config (DEVICE?) */
-	Reg	adpctl;		/* ADP Control */
-	Reg	reserved0[39];
-	Reg	hptxfsiz;	/* Host Periodic Transmit FIFO Size */
-	Reg	dtxfsiz[15];	/* Device Periodic Transmit FIFOs (DEVICE) */
-	char	pad0[0x400-0x140];
-
-	/* Host global registers 0x400-0x420 */
-	Reg	hcfg;		/* Configuration */
-	Reg	hfir;		/* Frame Interval */
-	Reg	hfnum;		/* Frame Number / Frame Remaining (RO) */
-	Reg	reserved1;
-	Reg	hptxsts;	/* Periodic Transmit FIFO / Queue Status */
-	Reg	haint;		/* All Channels Interrupt */
-	Reg	haintmsk;	/* All Channels Interrupt Mask */
-	Reg	hflbaddr;	/* Frame List Base Address */
-	char	pad1[0x440-0x420];
-
-	/* Host port register 0x440 */
-	Reg	hport0;		/* Host Port 0 Control and Status */
-	char	pad2[0x500-0x444];
-
-	/* Host channel specific registers 0x500-0x700 */
-	struct	Hostchan {
-		Reg	hcchar;	/* Characteristic */
-		Reg	hcsplt;	/* Split Control */
-		Reg	hcint;	/* Interrupt */
-		Reg	hcintmsk; /* Interrupt Mask */
-		Reg	hctsiz;	/* Transfer Size */
-		Reg	hcdma;	/* DMA Address */
-		Reg	reserved;
-		Reg	hcdmab;	/* DMA Buffer Address */
-	} hchan[Maxchans];
-	char	pad3[0xE00-0x700];
-
-	/* Power & clock gating control register 0xE00 */
-	Reg	pcgcctl;
-};
-
-enum {
-	/* gotgctl */
-	Sesreqscs	= 1<<0,
-	Sesreq		= 1<<1,
-	Vbvalidoven	= 1<<2,
-	Vbvalidovval	= 1<<3,
-	Avalidoven	= 1<<4,
-	Avalidovval	= 1<<5,
-	Bvalidoven	= 1<<6,
-	Bvalidovval	= 1<<7,
-	Hstnegscs	= 1<<8,
-	Hnpreq		= 1<<9,
-	Hstsethnpen	= 1<<10,
-	Devhnpen	= 1<<11,
-	Conidsts	= 1<<16,
-	Dbnctime	= 1<<17,
-	Asesvld		= 1<<18,
-	Bsesvld		= 1<<19,
-	Otgver		= 1<<20,
-	Multvalidbc	= 0x1F<<22,
-	Chirpen		= 1<<27,
-
-	/* gotgint */
-	Sesenddet	= 1<<2,
-	Sesreqsucstschng= 1<<8,
-	Hstnegsucstschng= 1<<9,
-	Hstnegdet	= 1<<17,
-	Adevtoutchng	= 1<<18,
-	Debdone		= 1<<19,
-	Mvic		= 1<<20,
-
-	/* gahbcfg */
-	Glblintrmsk	= 1<<0,
-	/* bits 1:4 redefined for BCM2835 */
-	Axiburstlen	= 0x3<<1,
-		BURST1		= 3<<1,
-		BURST2		= 2<<1,
-		BURST3		= 1<<1,
-		BURST4		= 0<<1,
-	Axiwaitwrites	= 1<<4,
-	Dmaenable	= 1<<5,
-	Nptxfemplvl	= 1<<7,
-		NPTX_HALFEMPTY	= 0<<7,
-		NPTX_EMPTY	= 1<<7,
-	Ptxfemplvl	= 1<<8,
-		PTX_HALFEMPTY	= 0<<8,
-		PTX_EMPTY	= 1<<8,
-	Remmemsupp	= 1<<21,
-	Notialldmawrit	= 1<<22,
-	Ahbsingle	= 1<<23,
-
-	/* gusbcfg */
-	Toutcal		= 0x7<<0,
-	Phyif		= 1<<3,
-	Ulpi_utmi_sel	= 1<<4,
-	Fsintf		= 1<<5,
-		FsUnidir	= 0<<5,
-		FsBidir		= 1<<5,
-	Physel		= 1<<6,
-		PhyHighspeed	= 0<<6,
-		PhyFullspeed	= 1<<6,
-	Ddrsel		= 1<<7,
-	Srpcap		= 1<<8,
-	Hnpcap		= 1<<9,
-	Usbtrdtim	= 0xf<<10,
-		OUsbtrdtim		= 10,
-	Phylpwrclksel	= 1<<15,
-	Otgutmifssel	= 1<<16,
-	Ulpi_fsls	= 1<<17,
-	Ulpi_auto_res	= 1<<18,
-	Ulpi_clk_sus_m	= 1<<19,
-	Ulpi_ext_vbus_drv= 1<<20,
-	Ulpi_int_vbus_indicator= 1<<21,
-	Term_sel_dl_pulse= 1<<22,
-	Indicator_complement= 1<<23,
-	Indicator_pass_through= 1<<24,
-	Ulpi_int_prot_dis= 1<<25,
-	Ic_usb_cap	= 1<<26,
-	Ic_traffic_pull_remove= 1<<27,
-	Tx_end_delay	= 1<<28,
-	Force_host_mode	= 1<<29,
-	Force_dev_mode	= 1<<30,
-
-	/* grstctl */
-	Csftrst		= 1<<0,
-	Hsftrst		= 1<<1,
-	Hstfrm		= 1<<2,
-	Intknqflsh	= 1<<3,
-	Rxfflsh		= 1<<4,
-	Txfflsh		= 1<<5,
-	Txfnum		= 0x1f<<6,
-		TXF_ALL		= 0x10<<6,
-	Dmareq		= 1<<30,
-	Ahbidle		= 1<<31,
-
-	/* gintsts, gintmsk */
-	Curmode		= 1<<0,
-		HOSTMODE	= 1<<0,
-		DEVMODE		= 0<<0,
-	Modemismatch	= 1<<1,
-	Otgintr		= 1<<2,
-	Sofintr		= 1<<3,
-	Rxstsqlvl	= 1<<4,
-	Nptxfempty	= 1<<5,
-	Ginnakeff	= 1<<6,
-	Goutnakeff	= 1<<7,
-	Ulpickint	= 1<<8,
-	I2cintr		= 1<<9,
-	Erlysuspend	= 1<<10,
-	Usbsuspend	= 1<<11,
-	Usbreset	= 1<<12,
-	Enumdone	= 1<<13,
-	Isooutdrop	= 1<<14,
-	Eopframe	= 1<<15,
-	Restoredone	= 1<<16,
-	Epmismatch	= 1<<17,
-	Inepintr	= 1<<18,
-	Outepintr	= 1<<19,
-	Incomplisoin	= 1<<20,
-	Incomplisoout	= 1<<21,
-	Fetsusp		= 1<<22,
-	Resetdet	= 1<<23,
-	Portintr	= 1<<24,
-	Hcintr		= 1<<25,
-	Ptxfempty	= 1<<26,
-	Lpmtranrcvd	= 1<<27,
-	Conidstschng	= 1<<28,
-	Disconnect	= 1<<29,
-	Sessreqintr	= 1<<30,
-	Wkupintr	= 1<<31,
-
-	/* grxsts[rp] */
-	Chnum		= 0xf<<0,
-	Bcnt		= 0x7ff<<4,
-	Dpid		= 0x3<<15,
-	Pktsts		= 0xf<<17,
-		PKTSTS_IN		= 2<<17,
-		PKTSTS_IN_XFER_COMP	= 3<<17,
-		PKTSTS_DATA_TOGGLE_ERR	= 5<<17,
-		PKTSTS_CH_HALTED	= 7<<17,
-
-	/* hptxfsiz, gnptxfsiz */
-	Startaddr	= 0xffff<<0,
-	Depth		= 0xffff<<16,
-		ODepth		= 16,
-
-	/* gnptxsts */
-	Nptxfspcavail	= 0xffff<<0,
-	Nptxqspcavail	= 0xff<<16,
-	Nptxqtop_terminate= 1<<24,
-	Nptxqtop_token	= 0x3<<25,
-	Nptxqtop_chnep	= 0xf<<27,
-
-	/* gpvndctl */
-	Regdata		= 0xff<<0,
-	Vctrl		= 0xff<<8,
-	Regaddr16_21	= 0x3f<<16,
-	Regwr		= 1<<22,
-	Newregreq	= 1<<25,
-	Vstsbsy		= 1<<26,
-	Vstsdone	= 1<<27,
-	Disulpidrvr	= 1<<31,
-
-	/* ggpio */
-	Gpi		= 0xffff<<0,
-	Gpo		= 0xffff<<16,
-
-	/* ghwcfg2 */
-	Op_mode		= 0x7<<0,
-		HNP_SRP_CAPABLE_OTG	= 0<<0,
-		SRP_ONLY_CAPABLE_OTG	= 1<<0,
-		NO_HNP_SRP_CAPABLE	= 2<<0,
-		SRP_CAPABLE_DEVICE	= 3<<0,
-		NO_SRP_CAPABLE_DEVICE	= 4<<0,
-		SRP_CAPABLE_HOST	= 5<<0,
-		NO_SRP_CAPABLE_HOST	= 6<<0,
-	Architecture	= 0x3<<3,
-		SLAVE_ONLY		= 0<<3,
-		EXT_DMA			= 1<<3,
-		INT_DMA			= 2<<3,
-	Point2point	= 1<<5,
-	Hs_phy_type	= 0x3<<6,
-		PHY_NOT_SUPPORTED	= 0<<6,
-		PHY_UTMI		= 1<<6,
-		PHY_ULPI		= 2<<6,
-		PHY_UTMI_ULPI		= 3<<6,
-	Fs_phy_type	= 0x3<<8,
-	Num_dev_ep	= 0xf<<10,
-	Num_host_chan	= 0xf<<14,
-		ONum_host_chan		= 14,
-	Perio_ep_supported= 1<<18,
-	Dynamic_fifo	= 1<<19,
-	Nonperio_tx_q_depth= 0x3<<22,
-	Host_perio_tx_q_depth= 0x3<<24,
-	Dev_token_q_depth= 0x1f<<26,
-	Otg_enable_ic_usb= 1<<31,
-
-	/* ghwcfg3 */
-	Xfer_size_cntr_width	= 0xf<<0,
-	Packet_size_cntr_width	= 0x7<<4,
-	Otg_func		= 1<<7,
-	I2c			= 1<<8,
-	Vendor_ctrl_if		= 1<<9,
-	Optional_features	= 1<<10,
-	Synch_reset_type	= 1<<11,
-	Adp_supp		= 1<<12,
-	Otg_enable_hsic		= 1<<13,
-	Bc_support		= 1<<14,
-	Otg_lpm_en		= 1<<15,
-	Dfifo_depth		= 0xffff<<16,
-		ODfifo_depth		= 16,
-
-	/* ghwcfg4 */
-	Num_dev_perio_in_ep	= 0xf<<0,
-	Power_optimiz		= 1<<4,
-	Min_ahb_freq		= 1<<5,
-	Hiber			= 1<<6,
-	Xhiber			= 1<<7,
-	Utmi_phy_data_width	= 0x3<<14,
-	Num_dev_mode_ctrl_ep	= 0xf<<16,
-	Iddig_filt_en		= 1<<20,
-	Vbus_valid_filt_en	= 1<<21,
-	A_valid_filt_en		= 1<<22,
-	B_valid_filt_en		= 1<<23,
-	Session_end_filt_en	= 1<<24,
-	Ded_fifo_en		= 1<<25,
-	Num_in_eps		= 0xf<<26,
-	Desc_dma		= 1<<30,
-	Desc_dma_dyn		= 1<<31,
-
-	/* glpmcfg */
-	Lpm_cap_en	= 1<<0,
-	Appl_resp	= 1<<1,
-	Hird		= 0xf<<2,
-	Rem_wkup_en	= 1<<6,
-	En_utmi_sleep	= 1<<7,
-	Hird_thres	= 0x1f<<8,
-	Lpm_resp	= 0x3<<13,
-	Prt_sleep_sts	= 1<<15,
-	Sleep_state_resumeok= 1<<16,
-	Lpm_chan_index	= 0xf<<17,
-	Retry_count	= 0x7<<21,
-	Send_lpm	= 1<<24,
-	Retry_count_sts	= 0x7<<25,
-	Hsic_connect	= 1<<30,
-	Inv_sel_hsic	= 1<<31,
-
-	/* gpwrdn */
-	Pmuintsel	= 1<<0,
-	Pmuactv		= 1<<1,
-	Restore		= 1<<2,
-	Pwrdnclmp	= 1<<3,
-	Pwrdnrstn	= 1<<4,
-	Pwrdnswtch	= 1<<5,
-	Dis_vbus	= 1<<6,
-	Lnstschng	= 1<<7,
-	Lnstchng_msk	= 1<<8,
-	Rst_det		= 1<<9,
-	Rst_det_msk	= 1<<10,
-	Disconn_det	= 1<<11,
-	Disconn_det_msk	= 1<<12,
-	Connect_det	= 1<<13,
-	Connect_det_msk	= 1<<14,
-	Srp_det		= 1<<15,
-	Srp_det_msk	= 1<<16,
-	Sts_chngint	= 1<<17,
-	Sts_chngint_msk	= 1<<18,
-	Linestate	= 0x3<<19,
-	Idsts		= 1<<21,
-	Bsessvld	= 1<<22,
-	Adp_int		= 1<<23,
-	Mult_val_id_bc	= 0x1f<<24,
-
-	/* gdfifocfg */
-	Gdfifocfg	= 0xffff<<0,
-	Epinfobase	= 0xffff<<16,
-
-	/* adpctl */
-	Prb_dschg	= 0x3<<0,
-	Prb_delta	= 0x3<<2,
-	Prb_per		= 0x3<<4,
-	Rtim		= 0x7ff<<6,
-	Enaprb		= 1<<17,
-	Enasns		= 1<<18,
-	Adpres		= 1<<19,
-	Adpen		= 1<<20,
-	Adp_prb_int	= 1<<21,
-	Adp_sns_int	= 1<<22,
-	Adp_tmout_int	= 1<<23,
-	Adp_prb_int_msk	= 1<<24,
-	Adp_sns_int_msk	= 1<<25,
-	Adp_tmout_int_msk= 1<<26,
-	Ar		= 0x3<<27,
-
-	/* hcfg */
-	Fslspclksel	= 0x3<<0,
-		HCFG_30_60_MHZ	= 0<<0,
-		HCFG_48_MHZ	= 1<<0,
-		HCFG_6_MHZ	= 2<<0,
-	Fslssupp	= 1<<2,
-	Ena32khzs	= 1<<7,
-	Resvalid	= 0xff<<8,
-	Descdma		= 1<<23,
-	Frlisten	= 0x3<<24,
-	Modechtimen	= 1<<31,
-
-	/* hfir */
-	Frint		= 0xffff<<0,
-	Hfirrldctrl	= 1<<16,
-
-	/* hfnum */
-	Frnum		= 0xffff<<0,
-		MAX_FRNUM 	= 0x3FFF<<0,
-	Frrem		= 0xffff<<16,
-
-	/* hptxsts */
-	Ptxfspcavail	= 0xffff<<0,
-	Ptxqspcavail	= 0xff<<16,
-	Ptxqtop_terminate= 1<<24,
-	Ptxqtop_token	= 0x3<<25,
-	Ptxqtop_chnum	= 0xf<<27,
-	Ptxqtop_odd	= 1<<31,
-
-	/* haint, haintmsk */
-#define CHANINT(n)	(1<<(n))
-
-	/* hport0 */
-	Prtconnsts	= 1<<0,		/* connect status (RO) */
-	Prtconndet	= 1<<1,		/* connect detected R/W1C) */
-	Prtena		= 1<<2,		/* enable (R/W1C) */
-	Prtenchng	= 1<<3,		/* enable/disable change (R/W1C) */
-	Prtovrcurract	= 1<<4,		/* overcurrent active (RO) */
-	Prtovrcurrchng	= 1<<5,		/* overcurrent change (R/W1C) */
-	Prtres		= 1<<6,		/* resume */
-	Prtsusp		= 1<<7,		/* suspend */
-	Prtrst		= 1<<8,		/* reset */
-	Prtlnsts	= 0x3<<10,	/* line state {D+,D-} (RO) */
-	Prtpwr		= 1<<12,	/* power on */
-	Prttstctl	= 0xf<<13,	/* test */
-	Prtspd		= 0x3<<17,	/* speed (RO) */
-		HIGHSPEED	= 0<<17,
-		FULLSPEED	= 1<<17,
-		LOWSPEED	= 2<<17,
-
-	/* hcchar */
-	Mps		= 0x7ff<<0,	/* endpoint maximum packet size */
-	Epnum		= 0xf<<11,	/* endpoint number */
-		OEpnum		= 11,
-	Epdir		= 1<<15,	/* endpoint direction */
-		Epout		= 0<<15,
-		Epin		= 1<<15,
-	Lspddev		= 1<<17,	/* device is lowspeed */
-	Eptype		= 0x3<<18,	/* endpoint type */
-		Epctl		= 0<<18,
-		Episo		= 1<<18,
-		Epbulk		= 2<<18,
-		Epintr		= 3<<18,
-	Multicnt	= 0x3<<20,	/* transactions per μframe */
-					/* or retries per periodic split */
-		OMulticnt	= 20,
-	Devaddr		= 0x7f<<22,	/* device address */
-		ODevaddr	= 22,
-	Oddfrm		= 1<<29,	/* xfer in odd frame (iso/interrupt) */
-	Chdis		= 1<<30,	/* channel disable (write 1 only) */
-	Chen		= 1<<31,	/* channel enable (write 1 only) */
-
-	/* hcsplt */
-	Prtaddr		= 0x7f<<0,	/* port address of recipient */
-					/* transaction translator */
-	Hubaddr		= 0x7f<<7,	/* dev address of transaction */
-					/* translator's hub */
-		OHubaddr	= 7,
-	Xactpos		= 0x3<<14,	/* payload's position within transaction */
-		POS_MID		= 0<<14,		
-		POS_END		= 1<<14,
-		POS_BEGIN	= 2<<14,
-		POS_ALL		= 3<<14, /* all of data (<= 188 bytes) */
-	Compsplt	= 1<<16,	/* do complete split */
-	Spltena		= 1<<31,	/* channel enabled to do splits */
-
-	/* hcint, hcintmsk */
-	Xfercomp	= 1<<0,		/* transfer completed without error */
-	Chhltd		= 1<<1,		/* channel halted */
-	Ahberr		= 1<<2,		/* AHB dma error */
-	Stall		= 1<<3,
-	Nak		= 1<<4,
-	Ack		= 1<<5,
-	Nyet		= 1<<6,
-	Xacterr		= 1<<7,	/* transaction error (crc, t/o, bit stuff, eop) */
-	Bblerr		= 1<<8,
-	Frmovrun	= 1<<9,
-	Datatglerr	= 1<<10,
-	Bna		= 1<<11,
-	Xcs_xact	= 1<<12,
-	Frm_list_roll	= 1<<13,
-
-	/* hctsiz */
-	Xfersize	= 0x7ffff<<0,	/* expected total bytes */
-	Pktcnt		= 0x3ff<<19,	/* expected number of packets */
-		OPktcnt		= 19,
-	Pid		= 0x3<<29,	/* packet id for initial transaction */
-		DATA0		= 0<<29,
-		DATA1		= 2<<29,	/* sic */
-		DATA2		= 1<<29,	/* sic */
-		MDATA		= 3<<29,	/* (non-ctl ep) */
-		SETUP		= 3<<29,	/* (ctl ep) */
-	Dopng		= 1<<31,	/* do PING protocol */
-
-	/* pcgcctl */
-	Stoppclk		= 1<<0,
-	Gatehclk		= 1<<1,
-	Pwrclmp			= 1<<2,
-	Rstpdwnmodule		= 1<<3,
-	Enbl_sleep_gating	= 1<<5,
-	Phy_in_sleep		= 1<<6,
-	Deep_sleep		= 1<<7,
-	Resetaftsusp		= 1<<8,
-	Restoremode		= 1<<9,
-	Enbl_extnd_hiber	= 1<<10,
-	Extnd_hiber_pwrclmp	= 1<<11,
-	Extnd_hiber_switch	= 1<<12,
-	Ess_reg_restored	= 1<<13,
-	Prt_clk_sel		= 0x3<<14,
-	Port_power		= 1<<16,
-	Max_xcvrselect		= 0x3<<17,
-	Max_termsel		= 1<<19,
-	Mac_dev_addr		= 0x7f<<20,
-	P2hd_dev_enum_spd	= 0x3<<27,
-	P2hd_prt_spd		= 0x3<<29,
-	If_dev_mode		= 1<<31,
-};

+ 0 - 436
sys/src/9/bcm/emmc.c

@@ -1,436 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2835 external mass media controller (mmc / sd host interface)
- *
- * Copyright © 2012 Richard Miller <r.miller@acm.org>
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/sd.h"
-
-#define EMMCREGS	(VIRTIO+0x300000)
-
-enum {
-	Extfreq		= 100*Mhz,	/* guess external clock frequency if */
-					/* not available from vcore */
-	Initfreq	= 400000,	/* initialisation frequency for MMC */
-	SDfreq		= 25*Mhz,	/* standard SD frequency */
-	DTO		= 14,		/* data timeout exponent (guesswork) */
-
-	MMCSelect	= 7,		/* mmc/sd card select command */
-	Setbuswidth	= 6,		/* mmc/sd set bus width command */
-};
-
-enum {
-	/* Controller registers */
-	Arg2			= 0x00>>2,
-	Blksizecnt		= 0x04>>2,
-	Arg1			= 0x08>>2,
-	Cmdtm			= 0x0c>>2,
-	Resp0			= 0x10>>2,
-	Resp1			= 0x14>>2,
-	Resp2			= 0x18>>2,
-	Resp3			= 0x1c>>2,
-	Data			= 0x20>>2,
-	Status			= 0x24>>2,
-	Control0		= 0x28>>2,
-	Control1		= 0x2c>>2,
-	Interrupt		= 0x30>>2,
-	Irptmask		= 0x34>>2,
-	Irpten			= 0x38>>2,
-	Control2		= 0x3c>>2,
-	Forceirpt		= 0x50>>2,
-	Boottimeout		= 0x70>>2,
-	Dbgsel			= 0x74>>2,
-	Exrdfifocfg		= 0x80>>2,
-	Exrdfifoen		= 0x84>>2,
-	Tunestep		= 0x88>>2,
-	Tunestepsstd		= 0x8c>>2,
-	Tunestepsddr		= 0x90>>2,
-	Spiintspt		= 0xf0>>2,
-	Slotisrver		= 0xfc>>2,
-
-	/* Control0 */
-	Dwidth4			= 1<<1,
-	Dwidth1			= 0<<1,
-
-	/* Control1 */
-	Srstdata		= 1<<26,	/* reset data circuit */
-	Srstcmd			= 1<<25,	/* reset command circuit */
-	Srsthc			= 1<<24,	/* reset complete host controller */
-	Datatoshift		= 16,		/* data timeout unit exponent */
-	Datatomask		= 0xF0000,
-	Clkfreq8shift		= 8,		/* SD clock base divider LSBs */
-	Clkfreq8mask		= 0xFF00,
-	Clkfreqms2shift		= 6,		/* SD clock base divider MSBs */
-	Clkfreqms2mask		= 0xC0,
-	Clkgendiv		= 0<<5,		/* SD clock divided */
-	Clkgenprog		= 1<<5,		/* SD clock programmable */
-	Clken			= 1<<2,		/* SD clock enable */
-	Clkstable		= 1<<1,	
-	Clkintlen		= 1<<0,		/* enable internal EMMC clocks */
-
-	/* Cmdtm */
-	Indexshift		= 24,
-	Suspend			= 1<<22,
-	Resume			= 2<<22,
-	Abort			= 3<<22,
-	Isdata			= 1<<21,
-	Ixchken			= 1<<20,
-	Crcchken		= 1<<19,
-	Respmask		= 3<<16,
-	Respnone		= 0<<16,
-	Resp136			= 1<<16,
-	Resp48			= 2<<16,
-	Resp48busy		= 3<<16,
-	Multiblock		= 1<<5,
-	Host2card		= 0<<4,
-	Card2host		= 1<<4,
-	Autocmd12		= 1<<2,
-	Autocmd23		= 2<<2,
-	Blkcnten		= 1<<1,
-
-	/* Interrupt */
-	Acmderr		= 1<<24,
-	Denderr		= 1<<22,
-	Dcrcerr		= 1<<21,
-	Dtoerr		= 1<<20,
-	Cbaderr		= 1<<19,
-	Cenderr		= 1<<18,
-	Ccrcerr		= 1<<17,
-	Ctoerr		= 1<<16,
-	Err		= 1<<15,
-	Cardintr	= 1<<8,		/* not in Broadcom datasheet */
-	Cardinsert	= 1<<6,		/* not in Broadcom datasheet */
-	Readrdy		= 1<<5,
-	Writerdy	= 1<<4,
-	Datadone	= 1<<1,
-	Cmddone		= 1<<0,
-
-	/* Status */
-	Bufread		= 1<<11,	/* not in Broadcom datasheet */
-	Bufwrite	= 1<<10,	/* not in Broadcom datasheet */
-	Readtrans	= 1<<9,
-	Writetrans	= 1<<8,
-	Datactive	= 1<<2,
-	Datinhibit	= 1<<1,
-	Cmdinhibit	= 1<<0,
-};
-
-int cmdinfo[64] = {
-[0]  Ixchken,
-[2]  Resp136,
-[3]  Resp48 | Ixchken | Crcchken,
-[6]  Resp48 | Ixchken | Crcchken,
-[7]  Resp48busy | Ixchken | Crcchken,
-[8]  Resp48 | Ixchken | Crcchken,
-[9]  Resp136,
-[12] Resp48busy | Ixchken | Crcchken,
-[13] Resp48 | Ixchken | Crcchken,
-[16] Resp48,
-[17] Resp48 | Isdata | Card2host | Ixchken | Crcchken,
-[18] Resp48 | Isdata | Card2host | Multiblock | Blkcnten | Ixchken | Crcchken,
-[24] Resp48 | Isdata | Host2card | Ixchken | Crcchken,
-[25] Resp48 | Isdata | Host2card | Multiblock | Blkcnten | Ixchken | Crcchken,
-[41] Resp48,
-[55] Resp48 | Ixchken | Crcchken,
-};
-
-typedef struct Ctlr Ctlr;
-
-struct Ctlr {
-	Rendez	r;
-	int	datadone;
-	int	fastclock;
-	ulong	extclk;
-};
-
-static Ctlr emmc;
-
-static void mmcinterrupt(Ureg*, void*);
-
-static void
-WR(int reg, u32int val)
-{
-	u32int *r = (u32int*)EMMCREGS;
-
-	if(0)print("WR %2.2ux %ux\n", reg<<2, val);
-	microdelay(emmc.fastclock? 2 : 20);
-	r[reg] = val;
-}
-
-static uint
-clkdiv(uint d)
-{
-	uint v;
-
-	assert(d < 1<<10);
-	v = (d << Clkfreq8shift) & Clkfreq8mask;
-	v |= ((d >> 8) << Clkfreqms2shift) & Clkfreqms2mask;
-	return v;
-}
-
-static int
-datadone(void*)
-{
-	return emmc.datadone;
-}
-
-static int
-emmcinit(void)
-{
-	u32int *r;
-	ulong clk;
-	char *s;
-
-	clk = getclkrate(ClkEmmc);
-	s = "";
-	if(clk == 0){
-		s = "Assuming ";
-		clk = Extfreq;
-	}
-	emmc.extclk = clk;
-	print("%seMMC external clock %lud Mhz\n", s, clk/1000000);
-	r = (u32int*)EMMCREGS;
-	if(0)print("emmc control %8.8ux %8.8ux %8.8ux\n",
-		r[Control0], r[Control1], r[Control2]);
-	WR(Control1, Srsthc);
-	delay(10);
-	while(r[Control1] & Srsthc)
-		;
-	return 0;
-}
-
-static int
-emmcinquiry(char *inquiry, int inqlen)
-{
-	u32int *r;
-	uint ver;
-
-	r = (u32int*)EMMCREGS;
-	ver = r[Slotisrver] >> 16;
-	return snprint(inquiry, inqlen,
-		"Arasan eMMC SD Host Controller %2.2x Version %2.2x",
-		ver&0xFF, ver>>8);
-}
-
-static void
-emmcenable(void)
-{
-	u32int *r;
-	int i;
-
-	r = (u32int*)EMMCREGS;
-	WR(Control1, clkdiv(emmc.extclk/Initfreq - 1) |
-		DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
-	for(i = 0; i < 1000; i++){
-		delay(1);
-		if(r[Control1] & Clkstable)
-			break;
-	}
-	if(i == 1000)
-		print("SD clock won't initialise!\n");
-	WR(Irptmask, ~(Dtoerr|Cardintr));
-	intrenable(IRQmmc, mmcinterrupt, nil, 0, "mmc");
-}
-
-static int
-emmccmd(u32int cmd, u32int arg, u32int *resp)
-{
-	u32int *r;
-	u32int c;
-	int i;
-	ulong now;
-
-	r = (u32int*)EMMCREGS;
-	assert(cmd < nelem(cmdinfo) && cmdinfo[cmd] != 0);
-	c = (cmd << Indexshift) | cmdinfo[cmd];
-	if(r[Status] & Cmdinhibit){
-		print("emmccmd: need to reset Cmdinhibit intr %ux stat %ux\n",
-			r[Interrupt], r[Status]);
-		WR(Control1, r[Control1] | Srstcmd);
-		while(r[Control1] & Srstcmd)
-			;
-		while(r[Status] & Cmdinhibit)
-			;
-	}
-	if((r[Status] & Datinhibit) &&
-	   ((c & Isdata) || (c & Respmask) == Resp48busy)){
-		print("emmccmd: need to reset Datinhibit intr %ux stat %ux\n",
-			r[Interrupt], r[Status]);
-		WR(Control1, r[Control1] | Srstdata);
-		while(r[Control1] & Srstdata)
-			;
-		while(r[Status] & Datinhibit)
-			;
-	}
-	WR(Arg1, arg);
-	if((i = r[Interrupt]) != 0){
-		if(i != Cardinsert)
-			print("emmc: before command, intr was %ux\n", i);
-		WR(Interrupt, i);
-	}
-	WR(Cmdtm, c);
-	now = m->ticks;
-	while(((i=r[Interrupt])&(Cmddone|Err)) == 0)
-		if(m->ticks-now > HZ)
-			break;
-	if((i&(Cmddone|Err)) != Cmddone){
-		if((i&~Err) != Ctoerr)
-			print("emmc: cmd %ux error intr %ux stat %ux\n", c, i, r[Status]);
-		WR(Interrupt, i);
-		if(r[Status]&Cmdinhibit){
-			WR(Control1, r[Control1]|Srstcmd);
-			while(r[Control1]&Srstcmd)
-				;
-		}
-		error(Eio);
-	}
-	WR(Interrupt, i & ~(Datadone|Readrdy|Writerdy));
-	switch(c & Respmask){
-	case Resp136:
-		resp[0] = r[Resp0]<<8;
-		resp[1] = r[Resp0]>>24 | r[Resp1]<<8;
-		resp[2] = r[Resp1]>>24 | r[Resp2]<<8;
-		resp[3] = r[Resp2]>>24 | r[Resp3]<<8;
-		break;
-	case Resp48:
-	case Resp48busy:
-		resp[0] = r[Resp0];
-		break;
-	case Respnone:
-		resp[0] = 0;
-		break;
-	}
-	if((c & Respmask) == Resp48busy){
-		WR(Irpten, Datadone|Err);
-		tsleep(&emmc.r, datadone, 0, 3000);
-		i = emmc.datadone;
-		emmc.datadone = 0;
-		WR(Irpten, 0);
-		if((i & Datadone) == 0)
-			print("emmcio: no Datadone after CMD%d\n", cmd);
-		if(i & Err)
-			print("emmcio: CMD%d error interrupt %ux\n",
-				cmd, r[Interrupt]);
-		WR(Interrupt, i);
-	}
-	/*
-	 * Once card is selected, use faster clock
-	 */
-	if(cmd == MMCSelect){
-		delay(10);
-		WR(Control1, clkdiv(emmc.extclk/SDfreq - 1) |
-			DTO<<Datatoshift | Clkgendiv | Clken | Clkintlen);
-		for(i = 0; i < 1000; i++){
-			delay(1);
-			if(r[Control1] & Clkstable)
-				break;
-		}
-		delay(10);
-		emmc.fastclock = 1;
-	}
-	/*
-	 * If card bus width changes, change host bus width
-	 */
-	if(cmd == Setbuswidth){
-		switch(arg){
-		case 0:
-			WR(Control0, r[Control0] & ~Dwidth4);
-			break;
-		case 2:
-			WR(Control0, r[Control0] | Dwidth4);
-			break;
-		}
-	}
-	return 0;
-}
-
-void
-emmciosetup(int write, void *buf, int bsize, int bcount)
-{
-	USED(write);
-	USED(buf);
-	WR(Blksizecnt, bcount<<16 | bsize);
-}
-
-static void
-emmcio(int write, uchar *buf, int len)
-{
-	u32int *r;
-	int i;
-
-	r = (u32int*)EMMCREGS;
-	assert((len&3) == 0);
-	okay(1);
-	if(waserror()){
-		okay(0);
-		nexterror();
-	}
-	if(write)
-		dmastart(DmaChanEmmc, DmaDevEmmc, DmaM2D,
-			buf, &r[Data], len);
-	else
-		dmastart(DmaChanEmmc, DmaDevEmmc, DmaD2M,
-			&r[Data], buf, len);
-	if(dmawait(DmaChanEmmc) < 0)
-		error(Eio);
-	WR(Irpten, Datadone|Err);
-	tsleep(&emmc.r, datadone, 0, 3000);
-	i = emmc.datadone;
-	emmc.datadone = 0;
-	WR(Irpten, 0);
-	if((i & Datadone) == 0){
-		print("emmcio: %d timeout intr %ux stat %ux\n",
-			write, i, r[Status]);
-		WR(Interrupt, i);
-		error(Eio);
-	}
-	if(i & Err){
-		print("emmcio: %d error intr %ux stat %ux\n",
-			write, r[Interrupt], r[Status]);
-		WR(Interrupt, i);
-		error(Eio);
-	}
-	if(i)
-		WR(Interrupt, i);
-	poperror();
-	okay(0);
-}
-
-static void
-mmcinterrupt(Ureg*, void*)
-{	
-	u32int *r;
-	int i;
-
-	r = (u32int*)EMMCREGS;
-	i = r[Interrupt];
-	r[Interrupt] = i & (Datadone|Err);
-	emmc.datadone = i;
-	wakeup(&emmc.r);
-}
-
-SDio sdio = {
-	"emmc",
-	emmcinit,
-	emmcenable,
-	emmcinquiry,
-	emmccmd,
-	emmciosetup,
-	emmcio,
-};

+ 0 - 10
sys/src/9/bcm/etherif.h

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../omap/etherif.h"

+ 0 - 449
sys/src/9/bcm/etherusb.c

@@ -1,449 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Kernel proxy for usb ethernet device
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "../port/error.h"
-#include "../port/netif.h"
-
-#include "etherif.h"
-#include "../ip/ip.h"
-
-#define	GET4(p)		((p)[3]<<24 | (p)[2]<<16 | (p)[1]<<8  | (p)[0])
-#define	PUT4(p, v)	((p)[0] = (v), (p)[1] = (v)>>8, \
-			 (p)[2] = (v)>>16, (p)[3] = (v)>>24)
-#define	dprint	if(debug) print
-#define ddump	if(0) dump
-
-static int debug = 0;
-
-enum {
-	Bind	= 0,
-	Unbind,
-
-	SmscRxerror	= 0x8000,
-	SmscTxfirst	= 0x2000,
-	SmscTxlast	= 0x1000,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Udev Udev;
-
-typedef int (Unpackfn)(Ether*, Block*);
-typedef void (Transmitfn)(Ctlr*, Block*);
-
-struct Ctlr {
-	Ether*	edev;
-	Udev*	udev;
-	Chan*	inchan;
-	Chan*	outchan;
-	char*	buf;
-	int	bufsize;
-	int	maxpkt;
-	uint	rxbuf;
-	uint	rxpkt;
-	uint	txbuf;
-	uint	txpkt;
-	QLock;
-};
-
-struct Udev {
-	char	*name;
-	Unpackfn *unpack;
-	Transmitfn *transmit;
-};
-	
-static Cmdtab cmds[] = {
-	{ Bind,		"bind",		7, },
-	{ Unbind,	"unbind",	0, },
-};
-
-static Unpackfn unpackcdc, unpackasix, unpacksmsc;
-static Transmitfn transmitcdc, transmitasix, transmitsmsc;
-
-static Udev udevtab[] = {
-	{ "cdc",	unpackcdc,	transmitcdc, },
-	{ "asix",	unpackasix,	transmitasix, },
-	{ "smsc",	unpacksmsc,	transmitsmsc, },
-	{ nil },
-};
-
-static void
-dump(int c, Block *b)
-{
-	int s, i;
-
-	s = splhi();
-	print("%c%ld:", c, BLEN(b));
-	for(i = 0; i < 32; i++)
-		print(" %2.2ux", b->rp[i]);
-	print("\n");
-	splx(s);
-}
-
-static int
-unpack(Ether *edev, Block *b, int m)
-{
-	Block *nb;
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ddump('?', b);
-	if(m == BLEN(b)){
-		etheriq(edev, b, 1);
-		ctlr->rxpkt++;
-		return 1;
-	}
-	nb = iallocb(m);
-	if(nb != nil){
-		memmove(nb->wp, b->rp, m);
-		nb->wp += m;
-		etheriq(edev, nb, 1);
-		ctlr->rxpkt++;
-	}else
-		edev->soverflows++;
-	b->rp += m;
-	return 0;
-}
-
-static int
-unpackcdc(Ether *edev, Block *b)
-{
-	int m;
-
-	m = BLEN(b);
-	if(m < 6)
-		return -1;
-	return unpack(edev, b, m);
-}
-
-static int
-unpackasix(Ether *edev, Block *b)
-{
-	ulong hd;
-	int m;
-	uchar *wp;
-
-	if(BLEN(b) < 4)
-		return -1;
-	hd = GET4(b->rp);
-	b->rp += 4;
-	m = hd & 0xFFFF;
-	hd >>= 16;
-	if(m != (~hd & 0xFFFF))
-		return -1;
-	m = ROUND(m, 2);
-	if(m < 6 || m > BLEN(b))
-		return -1;
-	if((wp = b->rp + m) != b->wp && b->wp - wp < 4)
-		b->wp = wp;
-	return unpack(edev, b, m);
-}
-
-static int
-unpacksmsc(Ether *edev, Block *b)
-{
-	ulong hd;
-	int m;
-	
-	ddump('@', b);
-	if(BLEN(b) < 4)
-		return -1;
-	hd = GET4(b->rp);
-	b->rp += 4;
-	m = hd >> 16;
-	if(m < 6 || m > BLEN(b))
-		return -1;
-	if(BLEN(b) - m < 4)
-		b->wp = b->rp + m;
-	if(hd & SmscRxerror){
-		edev->frames++;
-		b->rp += m;
-		if(BLEN(b) == 0){
-			freeb(b);
-			return 1;
-		}
-	}else if(unpack(edev, b, m) == 1)
-		return 1;
-	if((m &= 3) != 0)
-		b->rp += 4 - m;
-	return 0;
-}
-
-static void
-transmit(Ctlr *ctlr, Block *b)
-{
-	Chan *c;
-
-	ddump('!', b);
-	c = ctlr->outchan;
-	devtab[c->type]->bwrite(c, b, 0);
-}
-
-static void
-transmitcdc(Ctlr *ctlr, Block *b)
-{
-	transmit(ctlr, b);
-}
-
-static void
-transmitasix(Ctlr *ctlr, Block *b)
-{
-	int n;
-
-	n = BLEN(b) & 0xFFFF;
-	n |= ~n << 16;
-	padblock(b, 4);
-	PUT4(b->rp, n);
-	if(BLEN(b) % ctlr->maxpkt == 0){
-		padblock(b, -4);
-		PUT4(b->wp, 0xFFFF0000);
-		b->wp += 4;
-	}
-	transmit(ctlr, b);
-}
-
-static void
-transmitsmsc(Ctlr *ctlr, Block *b)
-{
-	int n;
-
-	n = BLEN(b) & 0x7FF;
-	padblock(b, 8);
-	PUT4(b->rp, n | SmscTxfirst | SmscTxlast);
-	PUT4(b->rp+4, n);
-	transmit(ctlr, b);
-}
-
-static void
-etherusbproc(void *a)
-{
-	Ether *edev;
-	Ctlr *ctlr;
-	Chan *c;
-	Block *b;
-
-	edev = a;
-	ctlr = edev->ctlr;
-	c = ctlr->inchan;
-	b = nil;
-	if(waserror()){
-		print("etherusbproc: error exit %s\n", up->errstr);
-		pexit(up->errstr, 1);
-		return;
-	}
-	for(;;){
-		if(b == nil){
-			b = devtab[c->type]->bread(c, ctlr->bufsize, 0);
-			ctlr->rxbuf++;
-		}
-		switch(ctlr->udev->unpack(edev, b)){
-		case -1:
-			edev->buffs++;
-			freeb(b);
-			/* fall through */
-		case 1:
-			b = nil;
-			break;
-		}
-	}
-}
-
-/*
- * bind type indev outdev mac bufsize maxpkt
- */
-static void
-bind(Ctlr *ctlr, Udev *udev, Cmdbuf *cb)
-{
-	Chan *inchan, *outchan;
-	char *buf;
-	uint bufsize, maxpkt;
-
-	qlock(ctlr);
-	inchan = outchan = nil;
-	buf = nil;
-	if(waserror()){
-		free(buf);
-		if(inchan)
-			cclose(inchan);
-		if(outchan)
-			cclose(outchan);
-		qunlock(ctlr);
-		nexterror();
-	}
-	if(ctlr->buf != nil)
-		cmderror(cb, "already bound to a device");
-	maxpkt = strtol(cb->f[6], 0, 0);
-	if(maxpkt < 8 || maxpkt > 512)
-		cmderror(cb, "bad maxpkt");
-	bufsize = strtol(cb->f[5], 0, 0);
-	if(bufsize < maxpkt || bufsize > 32*1024)
-		cmderror(cb, "bad bufsize");
-	buf = smalloc(bufsize);
-	inchan = namec(cb->f[2], Aopen, OREAD, 0);
-	outchan = namec(cb->f[3], Aopen, OWRITE, 0);
-	assert(inchan != nil && outchan != nil);
-	if(parsemac(ctlr->edev->ea, cb->f[4], Eaddrlen) != Eaddrlen)
-		cmderror(cb, "bad etheraddr");
-	memmove(ctlr->edev->addr, ctlr->edev->ea, Eaddrlen);
-	print("\netherusb %s: %E\n", udev->name, ctlr->edev->addr);
-	ctlr->buf = buf;
-	ctlr->inchan = inchan;
-	ctlr->outchan = outchan;
-	ctlr->bufsize = bufsize;
-	ctlr->maxpkt = maxpkt;
-	ctlr->udev = udev;
-	kproc("etherusb", etherusbproc, ctlr->edev);
-	poperror();
-	qunlock(ctlr);
-}
-
-static void
-unbind(Ctlr *ctlr)
-{
-	qlock(ctlr);
-	if(ctlr->buf != nil){
-		free(ctlr->buf);
-		ctlr->buf = nil;
-		if(ctlr->inchan)
-			cclose(ctlr->inchan);
-		if(ctlr->outchan)
-			cclose(ctlr->outchan);
-		ctlr->inchan = ctlr->outchan = nil;
-	}
-	qunlock(ctlr);
-}
-
-static long
-etherusbifstat(Ether* edev, void* a, long n, ulong offset)
-{
-	Ctlr *ctlr;
-	char *p;
-	int l;
-
-	ctlr = edev->ctlr;
-	p = malloc(READSTR);
-	l = 0;
-
-	l += snprint(p+l, READSTR-l, "rxbuf: %ud\n", ctlr->rxbuf);
-	l += snprint(p+l, READSTR-l, "rxpkt: %ud\n", ctlr->rxpkt);
-	l += snprint(p+l, READSTR-l, "txbuf: %ud\n", ctlr->txbuf);
-	l += snprint(p+l, READSTR-l, "txpkt: %ud\n", ctlr->txpkt);
-	USED(l);
-
-	n = readstr(offset, a, n, p);
-	free(p);
-	return n;
-}
-
-static void
-etherusbtransmit(Ether *edev)
-{
-	Ctlr *ctlr;
-	Block *b;
-	
-	ctlr = edev->ctlr;
-	while((b = qget(edev->oq)) != nil){
-		ctlr->txpkt++;
-		if(ctlr->buf == nil)
-			freeb(b);
-		else{
-			ctlr->udev->transmit(ctlr, b);
-			ctlr->txbuf++;
-		}
-	}
-}
-
-static long
-etherusbctl(Ether* edev, void* buf, long n)
-{
-	Ctlr *ctlr;
-	Cmdbuf *cb;
-	Cmdtab *ct;
-	Udev *udev;
-
-	if((ctlr = edev->ctlr) == nil)
-		error(Enonexist);
-
-	cb = parsecmd(buf, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-	ct = lookupcmd(cb, cmds, nelem(cmds));
-	switch(ct->index){
-	case Bind:
-		for(udev = udevtab; udev->name; udev++)
-			if(strcmp(cb->f[1], udev->name) == 0)
-				break;
-		if(udev->name == nil)
-			cmderror(cb, "unknown etherusb type");
-		bind(ctlr, udev, cb);
-		break;
-	case Unbind:
-		unbind(ctlr);
-		break;
-	default:
-		cmderror(cb, "unknown etherusb control message");
-	}
-	poperror();
-	free(cb);
-	return n;
-}
-
-static void
-etherusbattach(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = edev->ctlr;
-	ctlr->edev = edev;
-}
-
-static int
-etherusbpnp(Ether* edev)
-{
-	Ctlr *ctlr;
-
-	ctlr = malloc(sizeof(Ctlr));
-	edev->ctlr = ctlr;
-	edev->irq = -1;
-	edev->mbps = 100;	/* TODO: get this from usbether */
-
-	/*
-	 * Linkage to the generic ethernet driver.
-	 */
-	edev->attach = etherusbattach;
-	edev->transmit = etherusbtransmit;
-	edev->interrupt = nil;
-	edev->ifstat = etherusbifstat;
-	edev->ctl = etherusbctl;
-
-	edev->arg = edev;
-	/* TODO: promiscuous, multicast (for ipv6), shutdown (for reboot) */
-//	edev->promiscuous = etherusbpromiscuous;
-//	edev->shutdown = etherusbshutdown;
-//	edev->multicast = etherusbmulticast;
-
-	return 0;
-}
-
-void
-etherusblink(void)
-{
-	addethercard("usb", etherusbpnp);
-}

+ 0 - 129
sys/src/9/bcm/fns.h

@@ -1,129 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../port/portfns.h"
-
-Dirtab*	addarchfile(char*, int, long(*)(Chan*, void*, long, vlong), 
-	long(*)(Chan*, void*, long, vlong));
-extern void archreboot(void);
-extern void archreset(void);
-extern void armtimerset(int);
-extern void cachedwbinv(void);
-extern void cachedwbse(void*, int);
-extern void cachedwbinvse(void*, int);
-extern void cacheiinv(void);
-extern void cacheuwbinv(void);
-extern uintptr cankaddr(uintptr pa);
-extern int cas32(void*, u32int, u32int);
-extern void checkmmu(uintptr, uintptr);
-extern void clockinit(void);
-extern void clockshutdown(void);
-extern int cmpswap(long*, long, long);
-extern void coherence(void);
-extern ulong cprd(int cp, int op1, int crn, int crm, int op2);
-extern ulong cprdsc(int op1, int crn, int crm, int op2);
-extern void cpuidprint(void);
-extern void cpwr(int cp, int op1, int crn, int crm, int op2, ulong val);
-extern void cpwrsc(int op1, int crn, int crm, int op2, ulong val);
-#define cycles(ip) *(ip) = lcycles()
-extern void dmastart(int, int, int, void*, void*, int);
-extern int dmawait(int);
-extern int fbblank(int);
-extern void* fbinit(int, int*, int*, int*);
-extern u32int farget(void);
-extern void fpon(void);
-extern ulong fprd(int fpreg);
-extern void fprestreg(int fpreg, uvlong val);
-extern void fpsave(FPsave *);
-extern ulong fpsavereg(int fpreg, uvlong *fpp);
-extern void fpwr(int fpreg, ulong val);
-extern u32int fsrget(void);
-extern ulong getclkrate(int);
-extern char* getconf(char*);
-extern char *getethermac(void);
-extern uint getfirmware(void);
-extern int getpower(int);
-extern void getramsize(Confmem*);
-extern u32int ifsrget(void);
-extern void irqenable(int, void (*)(Ureg*, void*), void*);
-#define intrenable(i, f, a, b, n) irqenable((i), (f), (a))
-extern void intrsoff(void);
-extern int isaconfig(char*, int, ISAConf*);
-extern void links(void);
-extern void mmuinit(void);
-extern void mmuinit1(void);
-extern void mmuinvalidate(void);
-extern void mmuinvalidateaddr(u32int);
-extern uintptr mmukmap(uintptr, uintptr, usize);
-extern void okay(int);
-extern void procrestore(Proc *);
-extern void procsave(Proc*);
-extern void procsetup(Proc*);
-extern void screeninit(void);
-#define sdfree(p) free(p)
-#define sdmalloc(n)	mallocalign(n, CACHELINESZ, 0, 0)
-extern void setpower(int, int);
-extern void setr13(int, u32int*);
-extern int splfhi(void);
-extern int splflo(void);
-extern void swcursorinit(void);
-extern void syscallfmt(int syscallno, ulong pc, va_list list);
-extern void sysretfmt(int syscallno, va_list list, long ret, uvlong start, uvlong stop);
-extern int tas(void *);
-extern void touser(uintptr);
-extern void trapinit(void);
-extern void uartconsinit(void);
-extern int userureg(Ureg*);
-extern void vectors(void);
-extern void vtable(void);
-extern void wdogoff(void);
-
-/*
- * floating point emulation
- */
-extern int fpiarm(Ureg*);
-extern int fpudevprocio(Proc*, void*, long, uintptr, int);
-extern void fpuinit(void);
-extern void fpunoted(void);
-extern void fpunotify(Ureg*);
-extern void fpuprocrestore(Proc*);
-extern void fpuprocsave(Proc*);
-extern void fpusysprocsetup(Proc*);
-extern void fpusysrfork(Ureg*);
-extern void fpusysrforkchild(Proc*, Ureg*, Proc*);
-extern int fpuemu(Ureg*);
-/*
- * Things called from port.
- */
-extern void delay(int);				/* only scheddump() */
-extern int islo(void);
-extern void microdelay(int);			/* only edf.c */
-extern void idlehands(void);
-extern void setkernur(Ureg*, Proc*);		/* only devproc.c */
-extern void* sysexecregs(uintptr, ulong, int);
-extern void sysprocsetup(Proc*);
-extern void validalign(uintptr, unsigned);
-
-extern void kexit(Ureg*);
-
-#define	getpgcolor(a)	0
-#define	kmapinval()
-#define countpagerefs(a, b)
-
-#define PTR2UINT(p)	((uintptr)(p))
-#define UINT2PTR(i)	((void*)(i))
-
-#define	waserror()	(up->nerrlab++, setlabel(&up->errlab[up->nerrlab-1]))
-
-#define KADDR(pa)	UINT2PTR(KZERO    | ((uintptr)(pa) & ~KSEGM))
-#define PADDR(va)	PTR2UINT(PHYSDRAM | ((uintptr)(va) & ~KSEGM))
-#define DMAADDR(va)	PTR2UINT(BUSDRAM  | ((uintptr)(va) & ~KSEGM))
-#define DMAIO(va)	PTR2UINT(BUSIO    | ((uintptr)(va) & ~VIRTIO))
-
-#define MASK(v)	((1UL << (v)) - 1)	/* mask `v' bits wide */

+ 0 - 515
sys/src/9/bcm/fpiarm.c

@@ -1,515 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * this doesn't attempt to implement ARM floating-point properties
- * that aren't visible in the Inferno environment.
- * all arithmetic is done in double precision.
- * the FP trap status isn't updated.
- */
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-
-#include	"ureg.h"
-
-#include	"arm.h"
-#include	"../port/fpi.h"
-
-#define ARM7500			/* emulate old pre-VFP opcodes */
-
-/* undef this if correct kernel r13 isn't in Ureg;
- * check calculation in fpiarm below
- */
-
-#define	REG(ur, x) (*(long*)(((char*)(ur))+roff[(x)]))
-#ifdef ARM7500
-#define	FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&7])
-#else
-#define	FR(ufp, x) (*(Internal*)(ufp)->regs[(x)&(Nfpregs - 1)])
-#endif
-
-typedef struct FP2 FP2;
-typedef struct FP1 FP1;
-
-struct FP2 {
-	char*	name;
-	void	(*f)(Internal, Internal, Internal*);
-};
-
-struct FP1 {
-	char*	name;
-	void	(*f)(Internal*, Internal*);
-};
-
-enum {
-	N = 1<<31,
-	Z = 1<<30,
-	C = 1<<29,
-	V = 1<<28,
-	REGPC = 15,
-};
-
-enum {
-	fpemudebug = 0,
-};
-
-#undef OFR
-#define	OFR(X)	((ulong)&((Ureg*)0)->X)
-
-static	int	roff[] = {
-	OFR(r0), OFR(r1), OFR(r2), OFR(r3),
-	OFR(r4), OFR(r5), OFR(r6), OFR(r7),
-	OFR(r8), OFR(r9), OFR(r10), OFR(r11),
-	OFR(r12), OFR(r13), OFR(r14), OFR(pc),
-};
-
-static Internal fpconst[8] = {		/* indexed by op&7 (ARM 7500 FPA) */
-	/* s, e, l, h */
-	{0, 0x1, 0x00000000, 0x00000000}, /* 0.0 */
-	{0, 0x3FF, 0x00000000, 0x08000000},	/* 1.0 */
-	{0, 0x400, 0x00000000, 0x08000000},	/* 2.0 */
-	{0, 0x400, 0x00000000, 0x0C000000},	/* 3.0 */
-	{0, 0x401, 0x00000000, 0x08000000},	/* 4.0 */
-	{0, 0x401, 0x00000000, 0x0A000000},	/* 5.0 */
-	{0, 0x3FE, 0x00000000, 0x08000000},	/* 0.5 */
-	{0, 0x402, 0x00000000, 0x0A000000},	/* 10.0 */
-};
-
-/*
- * arm binary operations
- */
-
-static void
-fadd(Internal m, Internal n, Internal *d)
-{
-	(m.s == n.s? fpiadd: fpisub)(&m, &n, d);
-}
-
-static void
-fsub(Internal m, Internal n, Internal *d)
-{
-	m.s ^= 1;
-	(m.s == n.s? fpiadd: fpisub)(&m, &n, d);
-}
-
-static void
-fsubr(Internal m, Internal n, Internal *d)
-{
-	n.s ^= 1;
-	(n.s == m.s? fpiadd: fpisub)(&n, &m, d);
-}
-
-static void
-fmul(Internal m, Internal n, Internal *d)
-{
-	fpimul(&m, &n, d);
-}
-
-static void
-fdiv(Internal m, Internal n, Internal *d)
-{
-	fpidiv(&m, &n, d);
-}
-
-static void
-fdivr(Internal m, Internal n, Internal *d)
-{
-	fpidiv(&n, &m, d);
-}
-
-/*
- * arm unary operations
- */
-
-static void
-fmov(Internal *m, Internal *d)
-{
-	*d = *m;
-}
-
-static void
-fmovn(Internal *m, Internal *d)
-{
-	*d = *m;
-	d->s ^= 1;
-}
-
-static void
-fabsf(Internal *m, Internal *d)
-{
-	*d = *m;
-	d->s = 0;
-}
-
-static void
-frnd(Internal *m, Internal *d)
-{
-	short e;
-
-	(m->s? fsub: fadd)(fpconst[6], *m, d);
-	if(IsWeird(d))
-		return;
-	fpiround(d);
-	e = (d->e - ExpBias) + 1;
-	if(e <= 0)
-		SetZero(d);
-	else if(e > FractBits){
-		if(e < 2*FractBits)
-			d->l &= ~((1<<(2*FractBits - e))-1);
-	}else{
-		d->l = 0;
-		if(e < FractBits)
-			d->h &= ~((1<<(FractBits-e))-1);
-	}
-}
-
-/*
- * ARM 7500 FPA opcodes
- */
-
-static	FP1	optab1[16] = {	/* Fd := OP Fm */
-[0]	{"MOVF",	fmov},
-[1]	{"NEGF",	fmovn},
-[2]	{"ABSF",	fabsf},
-[3]	{"RNDF",	frnd},
-[4]	{"SQTF",	/*fsqt*/0},
-/* LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN all `deprecated' */
-/* URD and NRM aren't implemented */
-};
-
-static	FP2	optab2[16] = {	/* Fd := Fn OP Fm */
-[0]	{"ADDF",	fadd},
-[1]	{"MULF",	fmul},
-[2]	{"SUBF",	fsub},
-[3]	{"RSUBF",	fsubr},
-[4]	{"DIVF",	fdiv},
-[5]	{"RDIVF",	fdivr},
-/* POW, RPW deprecated */
-[8]	{"REMF",	/*frem*/0},
-[9]	{"FMF",	fmul},	/* fast multiply */
-[10]	{"FDV",	fdiv},	/* fast divide */
-[11]	{"FRD",	fdivr},	/* fast reverse divide */
-/* POL deprecated */
-};
-
-static ulong
-fcmp(Internal *n, Internal *m)
-{
-	int i;
-	Internal rm, rn;
-
-	if(IsWeird(m) || IsWeird(n)){
-		/* BUG: should trap if not masked */
-		return V|C;
-	}
-	rn = *n;
-	rm = *m;
-	fpiround(&rn);
-	fpiround(&rm);
-	i = fpicmp(&rn, &rm);
-	if(i > 0)
-		return C;
-	else if(i == 0)
-		return C|Z;
-	else
-		return N;
-}
-
-static void
-fld(void (*f)(Internal*, void*), int d, ulong ea, int n, FPsave *ufp)
-{
-	void *mem;
-
-	mem = (void*)ea;
-	(*f)(&FR(ufp, d), mem);
-	if(fpemudebug)
-		print("MOV%c #%lux, F%d\n", n==8? 'D': 'F', ea, d);
-}
-
-static void
-fst(void (*f)(void*, Internal*), ulong ea, int s, int n, FPsave *ufp)
-{
-	Internal tmp;
-	void *mem;
-
-	mem = (void*)ea;
-	tmp = FR(ufp, s);
-	if(fpemudebug)
-		print("MOV%c	F%d,#%lux\n", n==8? 'D': 'F', s, ea);
-	(*f)(mem, &tmp);
-}
-
-static int
-condok(int cc, int c)
-{
-	switch(c){
-	case 0:	/* Z set */
-		return cc&Z;
-	case 1:	/* Z clear */
-		return (cc&Z) == 0;
-	case 2:	/* C set */
-		return cc&C;
-	case 3:	/* C clear */
-		return (cc&C) == 0;
-	case 4:	/* N set */
-		return cc&N;
-	case 5:	/* N clear */
-		return (cc&N) == 0;
-	case 6:	/* V set */
-		return cc&V;
-	case 7:	/* V clear */
-		return (cc&V) == 0;
-	case 8:	/* C set and Z clear */
-		return cc&C && (cc&Z) == 0;
-	case 9:	/* C clear or Z set */
-		return (cc&C) == 0 || cc&Z;
-	case 10:	/* N set and V set, or N clear and V clear */
-		return (~cc&(N|V))==0 || (cc&(N|V)) == 0;
-	case 11:	/* N set and V clear, or N clear and V set */
-		return (cc&(N|V))==N || (cc&(N|V))==V;
-	case 12:	/* Z clear, and either N set and V set or N clear and V clear */
-		return (cc&Z) == 0 && ((~cc&(N|V))==0 || (cc&(N|V))==0);
-	case 13:	/* Z set, or N set and V clear or N clear and V set */
-		return (cc&Z) || (cc&(N|V))==N || (cc&(N|V))==V;
-	case 14:	/* always */
-		return 1;
-	case 15:	/* never (reserved) */
-		return 0;
-	}
-	return 0;	/* not reached */
-}
-
-static void
-unimp(ulong pc, ulong op)
-{
-	char buf[60];
-
-	snprint(buf, sizeof(buf), "sys: fp: pc=%lux unimp fp 0x%.8lux", pc, op);
-	if(fpemudebug)
-		print("FPE: %s\n", buf);
-	error(buf);
-	/* no return */
-}
-
-static void
-fpemu(ulong pc, ulong op, Ureg *ur, FPsave *ufp)
-{
-	int rn, rd, tag, o;
-	long off;
-	ulong ea;
-	Internal tmp, *fm, *fn;
-
-	/* note: would update fault status here if we noted numeric exceptions */
-
-	/*
-	 * LDF, STF; 10.1.1
-	 */
-	if(((op>>25)&7) == 6){
-		if(op & (1<<22))
-			unimp(pc, op);	/* packed or extended */
-		rn = (op>>16)&0xF;
-		off = (op&0xFF)<<2;
-		if((op & (1<<23)) == 0)
-			off = -off;
-		ea = REG(ur, rn);
-		if(rn == REGPC)
-			ea += 8;
-		if(op & (1<<24))
-			ea += off;
-		rd = (op>>12)&7;
-		if(op & (1<<20)){
-			if(op & (1<<15))
-				fld(fpid2i, rd, ea, 8, ufp);
-			else
-				fld(fpis2i, rd, ea, 4, ufp);
-		}else{
-			if(op & (1<<15))
-				fst(fpii2d, ea, rd, 8, ufp);
-			else
-				fst(fpii2s, ea, rd, 4, ufp);
-		}
-		if((op & (1<<24)) == 0)
-			ea += off;
-		if(op & (1<<21))
-			REG(ur, rn) = ea;
-		return;
-	}
-
-	/*
-	 * CPRT/transfer, 10.3
-	 */
-	if(op & (1<<4)){
-		rd = (op>>12) & 0xF;
-
-		/*
-		 * compare, 10.3.1
-		 */
-		if(rd == 15 && op & (1<<20)){
-			rn = (op>>16)&7;
-			fn = &FR(ufp, rn);
-			if(op & (1<<3)){
-				fm = &fpconst[op&7];
-				if(fpemudebug)
-					tag = 'C';
-			}else{
-				fm = &FR(ufp, op&7);
-				if(fpemudebug)
-					tag = 'F';
-			}
-			switch((op>>21)&7){
-			default:
-				unimp(pc, op);
-			case 4:	/* CMF: Fn :: Fm */
-			case 6:	/* CMFE: Fn :: Fm (with exception) */
-				ur->psr &= ~(N|C|Z|V);
-				ur->psr |= fcmp(fn, fm);
-				break;
-			case 5:	/* CNF: Fn :: -Fm */
-			case 7:	/* CNFE: Fn :: -Fm (with exception) */
-				tmp = *fm;
-				tmp.s ^= 1;
-				ur->psr &= ~(N|C|Z|V);
-				ur->psr |= fcmp(fn, &tmp);
-				break;
-			}
-			if(fpemudebug)
-				print("CMPF	%c%d,F%ld =%#lux\n",
-					tag, rn, op&7, ur->psr>>28);
-			return;
-		}
-
-		/*
-		 * other transfer, 10.3
-		 */
-		switch((op>>20)&0xF){
-		default:
-			unimp(pc, op);
-		case 0:	/* FLT */
-			rn = (op>>16) & 7;
-			fpiw2i(&FR(ufp, rn), &REG(ur, rd));
-			if(fpemudebug)
-				print("MOVW[FD]	R%d, F%d\n", rd, rn);
-			break;
-		case 1:	/* FIX */
-			if(op & (1<<3))
-				unimp(pc, op);
-			rn = op & 7;
-			tmp = FR(ufp, rn);
-			fpii2w(&REG(ur, rd), &tmp);
-			if(fpemudebug)
-				print("MOV[FD]W	F%d, R%d =%ld\n", rn, rd, REG(ur, rd));
-			break;
-		case 2:	/* FPSR := Rd */
-			ufp->status = REG(ur, rd);
-			if(fpemudebug)
-				print("MOVW	R%d, FPSR\n", rd);
-			break;
-		case 3:	/* Rd := FPSR */
-			REG(ur, rd) = ufp->status;
-			if(fpemudebug)
-				print("MOVW	FPSR, R%d\n", rd);
-			break;
-		case 4:	/* FPCR := Rd */
-			ufp->control = REG(ur, rd);
-			if(fpemudebug)
-				print("MOVW	R%d, FPCR\n", rd);
-			break;
-		case 5:	/* Rd := FPCR */
-			REG(ur, rd) = ufp->control;
-			if(fpemudebug)
-				print("MOVW	FPCR, R%d\n", rd);
-			break;
-		}
-		return;
-	}
-
-	/*
-	 * arithmetic
-	 */
-
-	if(op & (1<<3)){	/* constant */
-		fm = &fpconst[op&7];
-		if(fpemudebug)
-			tag = 'C';
-	}else{
-		fm = &FR(ufp, op&7);
-		if(fpemudebug)
-			tag = 'F';
-	}
-	rd = (op>>12)&7;
-	o = (op>>20)&0xF;
-	if(op & (1<<15)){	/* monadic */
-		FP1 *fp;
-		fp = &optab1[o];
-		if(fp->f == nil)
-			unimp(pc, op);
-		if(fpemudebug)
-			print("%s	%c%ld,F%d\n", fp->name, tag, op&7, rd);
-		(*fp->f)(fm, &FR(ufp, rd));
-	} else {
-		FP2 *fp;
-		fp = &optab2[o];
-		if(fp->f == nil)
-			unimp(pc, op);
-		rn = (op>>16)&7;
-		if(fpemudebug)
-			print("%s	%c%ld,F%d,F%d\n", fp->name, tag, op&7, rn, rd);
-		(*fp->f)(*fm, FR(ufp, rn), &FR(ufp, rd));
-	}
-}
-
-/*
- * returns the number of FP instructions emulated
- */
-int
-fpiarm(Ureg *ur)
-{
-	ulong op, o, cp;
-	FPsave *ufp;
-	int n;
-
-	if(up == nil)
-		panic("fpiarm not in a process");
-	ufp = &up->fpsave;
-	/*
-	 * because all the emulated fp state is in the proc structure,
-	 * it need not be saved/restored
-	 */
-	switch(up->fpstate){
-	case FPactive:
-	case FPinactive:
-		error("illegal instruction: emulated fpu opcode in VFP mode");
-	case FPinit:
-		assert(sizeof(Internal) <= sizeof(ufp->regs[0]));
-		up->fpstate = FPemu;
-		ufp->control = 0;
-		ufp->status = (0x01<<28)|(1<<12); /* sw emulation, alt. C flag */
-		for(n = 0; n < 8; n++)
-			FR(ufp, n) = fpconst[0];
-	}
-	for(n=0; ;n++){
-		validaddr(ur->pc, 4, 0);
-		op = *(ulong*)(ur->pc);
-		if(fpemudebug)
-			print("%#lux: %#8.8lux ", ur->pc, op);
-		o = (op>>24) & 0xF;
-		cp = (op>>8) & 0xF;
-		if(!ISFPAOP(cp, o))
-			break;
-		if(condok(ur->psr, op>>28))
-			fpemu(ur->pc, op, ur, ufp);
-		ur->pc += 4;		/* pretend cpu executed the instr */
-	}
-	if(fpemudebug)
-		print("\n");
-	return n;
-}

+ 0 - 1
sys/src/9/bcm/init9.s

@@ -1 +0,0 @@
-#include "../omap/init9.s"

+ 0 - 54
sys/src/9/bcm/io.h

@@ -1,54 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-enum {
-	IRQtimer0	= 0,
-	IRQtimer1	= 1,
-	IRQtimer2	= 2,
-	IRQtimer3	= 3,
-	IRQclock	= IRQtimer3,
-	IRQusb		= 9,
-	IRQdma0		= 16,
-#define IRQDMA(chan)	(IRQdma0+(chan))
-	IRQaux		= 29,
-	IRQmmc		= 62,
-
-	IRQbasic	= 64,
-	IRQtimerArm	= IRQbasic + 0,
-
-	IRQfiq		= IRQusb,	/* only one source can be FIQ */
-
-	DmaD2M		= 0,		/* device to memory */
-	DmaM2D		= 1,		/* memory to device */
-	DmaM2M		= 2,		/* memory to memory */
-
-	DmaChanEmmc	= 4,		/* can only use 2-5, maybe 0 */
-	DmaDevEmmc	= 11,
-
-	PowerSd		= 0,
-	PowerUart0,
-	PowerUart1,
-	PowerUsb,
-	PowerI2c0,
-	PowerI2c1,
-	PowerI2c2,
-	PowerSpi,
-	PowerCcp2tx,
-
-	ClkEmmc		= 1,
-	ClkUart,
-	ClkArm,
-	ClkCore,
-	ClkV3d,
-	ClkH264,
-	ClkIsp,
-	ClkSdram,
-	ClkPixel,
-	ClkPwm,
-};

+ 0 - 10
sys/src/9/bcm/kbd.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../omap/kbd.c"

+ 0 - 274
sys/src/9/bcm/l.s

@@ -1,274 +0,0 @@
-/*
- * Broadcom bcm2835 SoC, as used in Raspberry Pi
- * arm1176jzf-s processor (armv6)
- */
-
-#include "arm.s"
-
-TEXT _start(SB), 1, $-4
-	/*
-	 * load physical base for SB addressing while mmu is off
-	 * keep a handy zero in R0 until first function call
-	 */
-	MOVW	$setR12(SB), R12
-	SUB	$KZERO, R12
-	ADD	$PHYSDRAM, R12
-	MOVW	$0, R0
-
-	/*
-	 * SVC mode, interrupts disabled
-	 */
-	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
-	MOVW	R1, CPSR
-
-	/*
-	 * disable the mmu and L1 caches
-	 * invalidate caches and tlb
-	 */
-	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-	BIC	$(CpCdcache|CpCicache|CpCpredict|CpCmmu), R1
-	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvu), CpCACHEall
-	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
-	ISB
-
-	/*
-	 * clear mach and page tables
-	 */
-	MOVW	$PADDR(MACHADDR), R1
-	MOVW	$PADDR(KTZERO), R2
-_ramZ:
-	MOVW	R0, (R1)
-	ADD	$4, R1
-	CMP	R1, R2
-	BNE	_ramZ
-
-	/*
-	 * start stack at top of mach (physical addr)
-	 * set up page tables for kernel
-	 */
-	MOVW	$PADDR(MACHADDR+MACHSIZE-4), R13
-	BL	,mmuinit(SB)
-
-	/*
-	 * set up domain access control and page table base
-	 */
-	MOVW	$Client, R1
-	MCR	CpSC, 0, R1, C(CpDAC), C(0)
-	MOVW	$PADDR(L1), R1
-	MCR	CpSC, 0, R1, C(CpTTB), C(0)
-
-	/*
-	 * enable caches, mmu, and high vectors
-	 */
-	MRC	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
-	ORR	$(CpChv|CpCdcache|CpCicache|CpCmmu), R0
-	MCR	CpSC, 0, R0, C(CpCONTROL), C(0), CpMainctl
-	ISB
-
-	/*
-	 * switch SB, SP, and PC into KZERO space
-	 */
-	MOVW	$setR12(SB), R12
-	MOVW	$(MACHADDR+MACHSIZE-4), R13
-	MOVW	$_startpg(SB), R15
-
-TEXT _startpg(SB), 1, $-4
-
-	/*
-	 * enable cycle counter
-	 */
-	MOVW	$1, R1
-	MCR	CpSC, 0, R1, C(CpSPM), C(CpSPMperf), CpSPMctl
-
-	/*
-	 * call main and loop forever if it returns
-	 */
-	BL	,main(SB)
-	B	,0(PC)
-
-	BL	_div(SB)		/* hack to load _div, etc. */
-
-TEXT fsrget(SB), 1, $-4				/* data fault status */
-	MRC	CpSC, 0, R0, C(CpFSR), C(0), CpFSRdata
-	RET
-
-TEXT ifsrget(SB), 1, $-4			/* instruction fault status */
-	MRC	CpSC, 0, R0, C(CpFSR), C(0), CpFSRinst
-	RET
-
-TEXT farget(SB), 1, $-4				/* fault address */
-	MRC	CpSC, 0, R0, C(CpFAR), C(0x0)
-	RET
-
-TEXT lcycles(SB), 1, $-4
-	MRC	CpSC, 0, R0, C(CpSPM), C(CpSPMperf), CpSPMcyc
-	RET
-
-TEXT splhi(SB), 1, $-4
-	MOVW	$(MACHADDR+4), R2		/* save caller pc in Mach */
-	MOVW	R14, 0(R2)
-
-	MOVW	CPSR, R0			/* turn off irqs (but not fiqs) */
-	ORR	$(PsrDirq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT splfhi(SB), 1, $-4
-	MOVW	$(MACHADDR+4), R2		/* save caller pc in Mach */
-	MOVW	R14, 0(R2)
-
-	MOVW	CPSR, R0			/* turn off irqs and fiqs */
-	ORR	$(PsrDirq|PsrDfiq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT splflo(SB), 1, $-4
-	MOVW	CPSR, R0			/* turn on fiqs */
-	BIC	$(PsrDfiq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT spllo(SB), 1, $-4
-	MOVW	CPSR, R0			/* turn on irqs and fiqs */
-	BIC	$(PsrDirq|PsrDfiq), R0, R1
-	MOVW	R1, CPSR
-	RET
-
-TEXT splx(SB), 1, $-4
-	MOVW	$(MACHADDR+0x04), R2		/* save caller pc in Mach */
-	MOVW	R14, 0(R2)
-
-	MOVW	R0, R1				/* reset interrupt level */
-	MOVW	CPSR, R0
-	MOVW	R1, CPSR
-	RET
-
-TEXT spldone(SB), 1, $0				/* end marker for devkprof.c */
-	RET
-
-TEXT islo(SB), 1, $-4
-	MOVW	CPSR, R0
-	AND	$(PsrDirq), R0
-	EOR	$(PsrDirq), R0
-	RET
-
-TEXT	tas(SB), $-4
-TEXT	_tas(SB), $-4
-	MOVW	R0,R1
-	MOVW	$1,R0
-	SWPW	R0,(R1)			/* fix: deprecated in armv6 */
-	RET
-
-TEXT setlabel(SB), 1, $-4
-	MOVW	R13, 0(R0)		/* sp */
-	MOVW	R14, 4(R0)		/* pc */
-	MOVW	$0, R0
-	RET
-
-TEXT gotolabel(SB), 1, $-4
-	MOVW	0(R0), R13		/* sp */
-	MOVW	4(R0), R14		/* pc */
-	MOVW	$1, R0
-	RET
-
-TEXT getcallerpc(SB), 1, $-4
-	MOVW	0(R13), R0
-	RET
-
-TEXT idlehands(SB), $-4
-	BARRIERS
-	MOVW	CPSR, R3
-	BIC	$(PsrDirq|PsrDfiq), R3, R1		/* spllo */
-	MOVW	R1, CPSR
-
-	MOVW	$0, R0				/* wait for interrupt */
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEintr), CpCACHEwait
-	ISB
-
-	MOVW	R3, CPSR			/* splx */
-	RET
-
-
-TEXT coherence(SB), $-4
-	BARRIERS
-	RET
-
-/*
- * invalidate tlb
- */
-TEXT mmuinvalidate(SB), 1, $-4
-	MOVW	$0, R0
-	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
-	BARRIERS
-	RET
-
-/*
- * mmuinvalidateaddr(va)
- *   invalidate tlb entry for virtual page address va, ASID 0
- */
-TEXT mmuinvalidateaddr(SB), 1, $-4
-	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinvse
-	BARRIERS
-	RET
-
-/*
- * drain write buffer
- * writeback and invalidate data cache
- */
-TEXT cachedwbinv(SB), 1, $-4
-	DSB
-	MOVW	$0, R0
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall
-	RET
-
-/*
- * cachedwbinvse(va, n)
- *   drain write buffer
- *   writeback and invalidate data cache range [va, va+n)
- */
-TEXT cachedwbinvse(SB), 1, $-4
-	MOVW	R0, R1		/* DSB clears R0 */
-	DSB
-	MOVW	n+4(FP), R2
-	ADD	R1, R2
-	SUB	$1, R2
-	BIC	$(CACHELINESZ-1), R1
-	BIC	$(CACHELINESZ-1), R2
-	MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwbi)
-	RET
-
-/*
- * cachedwbse(va, n)
- *   drain write buffer
- *   writeback data cache range [va, va+n)
- */
-TEXT cachedwbse(SB), 1, $-4
-	MOVW	R0, R1		/* DSB clears R0 */
-	DSB
-	MOVW	n+4(FP), R2
-	ADD	R1, R2
-	BIC	$(CACHELINESZ-1), R1
-	BIC	$(CACHELINESZ-1), R2
-	MCRR(CpSC, 0, 2, 1, CpCACHERANGEdwb)
-	RET
-
-/*
- * drain write buffer and prefetch buffer
- * writeback and invalidate data cache
- * invalidate instruction cache
- */
-TEXT cacheuwbinv(SB), 1, $-4
-	BARRIERS
-	MOVW	$0, R0
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
-	RET
-
-/*
- * invalidate instruction cache
- */
-TEXT cacheiinv(SB), 1, $-4
-	MOVW	$0, R0
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
-	RET

+ 0 - 197
sys/src/9/bcm/lexception.s

@@ -1,197 +0,0 @@
-/*
- * arm exception handlers
- */
-#include "arm.s"
-
-/*
- *  exception vectors, copied by trapinit() to somewhere useful
- */
-TEXT vectors(SB), 1, $-4
-	MOVW	0x18(R15), R15		/* reset */
-	MOVW	0x18(R15), R15		/* undefined instr. */
-	MOVW	0x18(R15), R15		/* SWI & SMC */
-	MOVW	0x18(R15), R15		/* prefetch abort */
-	MOVW	0x18(R15), R15		/* data abort */
-	MOVW	0x18(R15), R15		/* reserved */
-	MOVW	0x18(R15), R15		/* IRQ */
-	MOVW	0x18(R15), R15		/* FIQ */
-
-TEXT vtable(SB), 1, $-4
-	WORD	$_vsvc(SB)		/* reset, in svc mode already */
-	WORD	$_vund(SB)		/* undefined, switch to svc mode */
-	WORD	$_vsvc(SB)		/* swi, in svc mode already */
-	WORD	$_vpabt(SB)		/* prefetch abort, switch to svc mode */
-	WORD	$_vdabt(SB)		/* data abort, switch to svc mode */
-	WORD	$_vsvc(SB)		/* reserved */
-	WORD	$_virq(SB)		/* IRQ, switch to svc mode */
-	WORD	$_vfiq(SB)		/* FIQ, switch to svc mode */
-
-TEXT _vsvc(SB), 1, $-4			/* SWI */
-	MOVW.W	R14, -4(R13)		/* ureg->pc = interrupted PC */
-	MOVW	SPSR, R14		/* ureg->psr = SPSR */
-	MOVW.W	R14, -4(R13)		/* ... */
-	MOVW	$PsrMsvc, R14		/* ureg->type = PsrMsvc */
-	MOVW.W	R14, -4(R13)		/* ... */
-
-	/* avoid the ambiguity described in notes/movm.w. */
-	MOVM.DB.S [R0-R14], (R13)	/* save user level registers */
-	SUB	$(15*4), R13		/* r13 now points to ureg */
-
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-
-//	MOVW	$(KSEG0+16*KiB-MACHSIZE), R10	/* m */
-	MOVW	$(MACHADDR), R10	/* m */
-	MOVW	8(R10), R9		/* up */
-
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$8, R13			/* space for argument+link */
-
-	BL	syscall(SB)
-
-	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vund(SB), 1, $-4			/* undefined */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMund, R0
-	B	_vswitch
-
-TEXT _vpabt(SB), 1, $-4			/* prefetch abort */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMabt, R0		/* r0 = type */
-	B	_vswitch
-
-TEXT _vdabt(SB), 1, $-4			/* data abort */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$(PsrMabt+1), R0	/* r0 = type */
-	B	_vswitch
-
-TEXT _virq(SB), 1, $-4			/* IRQ */
-	MOVM.IA	[R0-R4], (R13)		/* free some working space */
-	MOVW	$PsrMirq, R0		/* r0 = type */
-	B	_vswitch
-
-	/*
-	 *  come here with type in R0 and R13 pointing above saved [r0-r4].
-	 *  we'll switch to SVC mode and then call trap.
-	 */
-_vswitch:
-	MOVW	SPSR, R1		/* save SPSR for ureg */
-	MOVW	R14, R2			/* save interrupted pc for ureg */
-	MOVW	R13, R3			/* save pointer to where the original [R0-R4] are */
-
-	/*
-	 * switch processor to svc mode.  this switches the banked registers
-	 * (r13 [sp] and r14 [link]) to those of svc mode.
-	 */
-	MOVW	CPSR, R14
-	BIC	$PsrMask, R14
-	ORR	$(PsrDirq|PsrMsvc), R14
-	MOVW	R14, CPSR		/* switch! */
-
-	AND.S	$0xf, R1, R4		/* interrupted code kernel or user? */
-	BEQ	_userexcep
-
-	/* here for trap from SVC mode */
-	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
-	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
-
-	/*
-	 * avoid the ambiguity described in notes/movm.w.
-	 * In order to get a predictable value in R13 after the stores,
-	 * separate the store-multiple from the stack-pointer adjustment.
-	 * We'll assume that the old value of R13 should be stored on the stack.
-	 */
-	/* save kernel level registers, at end r13 points to ureg */
-	MOVM.DB	[R0-R14], (R13)
-	SUB	$(15*4), R13		/* SP now points to saved R0 */
-
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$(4*2), R13		/* space for argument+link (for debugger) */
-	MOVW	$0xdeaddead, R11	/* marker */
-
-	BL	trap(SB)
-
-	ADD	$(4*2+4*15), R13	/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-
-	MOVM.DB (R13), [R0-R14]		/* restore registers */
-
-	ADD	$(4*2), R13		/* pop past ureg->{type+psr} to pc */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-	/* here for trap from USER mode */
-_userexcep:
-	MOVM.DB.W [R0-R2], (R13)	/* set ureg->{type, psr, pc}; r13 points to ureg->type  */
-	MOVM.IA	  (R3), [R0-R4]		/* restore [R0-R4] from previous mode's stack */
-
-	/* avoid the ambiguity described in notes/movm.w. */
-	MOVM.DB.S [R0-R14], (R13)	/* save kernel level registers */
-	SUB	$(15*4), R13		/* r13 now points to ureg */
-
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-
-//	MOVW	$(KSEG0+16*KiB-MACHSIZE), R10	/* m */
-	MOVW	$(MACHADDR), R10	/* m */
-	MOVW	8(R10), R9		/* up */
-
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$(4*2), R13		/* space for argument+link (for debugger) */
-
-	BL	trap(SB)
-
-	ADD	$(4*2+4*15), R13	/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$(4*2), R13		/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-TEXT _vfiq(SB), 1, $-4			/* FIQ */
-	MOVW	$PsrMfiq, R8		/* trap type */
-	MOVW	SPSR, R9		/* interrupted psr */
-	MOVW	R14, R10		/* interrupted pc */
-	MOVM.DB.W [R8-R10], (R13)	/* save in ureg */
-	MOVM.DB.W.S [R0-R14], (R13)	/* save interrupted regs */
-	MOVW	$setR12(SB), R12	/* Make sure we've got the kernel's SB loaded */
-	MOVW	$(MACHADDR), R10	/* m */
-	MOVW	8(R10), R9		/* up */
-	MOVW	R13, R0			/* first arg is pointer to ureg */
-	SUB	$(4*2), R13		/* space for argument+link (for debugger) */
-
-	BL	fiq(SB)
-
-	ADD	$(8+4*15), R13		/* make r13 point to ureg->type */
-	MOVW	8(R13), R14		/* restore link */
-	MOVW	4(R13), R0		/* restore SPSR */
-	MOVW	R0, SPSR		/* ... */
-	MOVM.DB.S (R13), [R0-R14]	/* restore registers */
-	ADD	$8, R13			/* pop past ureg->{type+psr} */
-	RFE				/* MOVM.IA.S.W (R13), [R15] */
-
-/*
- *  set the stack value for the mode passed in R0
- */
-TEXT setr13(SB), 1, $-4
-	MOVW	4(FP), R1
-
-	MOVW	CPSR, R2
-	BIC	$PsrMask, R2, R3
-	ORR	R0, R3
-	MOVW	R3, CPSR		/* switch to new mode */
-
-	MOVW	R13, R0			/* return old sp */
-	MOVW	R1, R13			/* install new one */
-
-	MOVW	R2, CPSR		/* switch back to old mode */
-	RET

+ 0 - 1
sys/src/9/bcm/lproc.s

@@ -1 +0,0 @@
-#include "../omap/lproc.s"

+ 0 - 611
sys/src/9/bcm/main.c

@@ -1,611 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "tos.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-#include "init.h"
-#include <pool.h>
-
-#include "reboot.h"
-
-enum {
-	/* space for syscall args, return PC, top-of-stack struct */
-	Ustkheadroom	= sizeof(Sargs) + sizeof(uintptr) + sizeof(Tos),
-};
-
-/* Firmware compatibility */
-#define	Minfirmrev	326770
-#define	Minfirmdate	"19 Aug 2013"
-
-/*
- * Where configuration info is left for the loaded programme.
- */
-#define BOOTARGS	((char*)CONFADDR)
-#define	BOOTARGSLEN	(MACHADDR-CONFADDR)
-#define	MAXCONF		64
-#define MAXCONFLINE	160
-
-uintptr kseg0 = KZERO;
-Mach*	machaddr[MAXMACH];
-Conf	conf;
-ulong	memsize = 128*1024*1024;
-
-/*
- * Option arguments from the command line.
- * oargv[0] is the boot file.
- */
-static int oargc;
-static char* oargv[20];
-static char oargb[128];
-static int oargblen;
-
-static uintptr sp;		/* XXX - must go - user stack of init proc */
-
-/* store plan9.ini contents here at least until we stash them in #ec */
-static char confname[MAXCONF][KNAMELEN];
-static char confval[MAXCONF][MAXCONFLINE];
-static int nconf;
-
-typedef struct Atag Atag;
-struct Atag {
-	u32int	size;	/* size of atag in words, including this header */
-	u32int	tag;	/* atag type */
-	union {
-		u32int	data[1];	/* actually [size-2] */
-		/* AtagMem */
-		struct {
-			u32int	size;
-			u32int	base;
-		} mem;
-		/* AtagCmdLine */
-		char	cmdline[1];	/* actually [4*(size-2)] */
-	};
-};
-
-enum {
-	AtagNone	= 0x00000000,
-	AtagCore	= 0x54410001,
-	AtagMem		= 0x54410002,
-	AtagCmdline	= 0x54410009,
-};
-
-static int
-findconf(char *name)
-{
-	int i;
-
-	for(i = 0; i < nconf; i++)
-		if(cistrcmp(confname[i], name) == 0)
-			return i;
-	return -1;
-}
-
-char*
-getconf(char *name)
-{
-	int i;
-
-	i = findconf(name);
-	if(i >= 0)
-		return confval[i];
-	return nil;
-}
-
-void
-addconf(char *name, char *val)
-{
-	int i;
-
-	i = findconf(name);
-	if(i < 0){
-		if(val == nil || nconf >= MAXCONF)
-			return;
-		i = nconf++;
-		strecpy(confname[i], confname[i]+sizeof(confname[i]), name);
-	}
-	strecpy(confval[i], confval[i]+sizeof(confval[i]), val);
-}
-
-static void
-writeconf(void)
-{
-	char *p, *q;
-	int n;
-
-	p = getconfenv();
-
-	if(waserror()) {
-		free(p);
-		nexterror();
-	}
-
-	/* convert to name=value\n format */
-	for(q=p; *q; q++) {
-		q += strlen(q);
-		*q = '=';
-		q += strlen(q);
-		*q = '\n';
-	}
-	n = q - p + 1;
-	if(n >= BOOTARGSLEN)
-		error("kernel configuration too large");
-	memmove(BOOTARGS, p, n);
-	memset(BOOTARGS + n, '\n', BOOTARGSLEN - n);
-	poperror();
-	free(p);
-}
-
-static void
-plan9iniinit(char *s, int cmdline)
-{
-	char *toks[MAXCONF];
-	int i, c, n;
-	char *v;
-
-	if((c = *s) < ' ' || c >= 0x80)
-		return;
-	if(cmdline)
-		n = tokenize(s, toks, MAXCONF);
-	else
-		n = getfields(s, toks, MAXCONF, 1, "\n");
-	for(i = 0; i < n; i++){
-		if(toks[i][0] == '#')
-			continue;
-		v = strchr(toks[i], '=');
-		if(v == nil)
-			continue;
-		*v++ = '\0';
-		addconf(toks[i], v);
-	}
-}
-
-static void
-ataginit(Atag *a)
-{
-	int n;
-
-	if(a->tag != AtagCore){
-		plan9iniinit((char*)a, 0);
-		return;
-	}
-	while(a->tag != AtagNone){
-		switch(a->tag){
-		case AtagMem:
-			/* use only first bank */
-			if(conf.mem[0].limit == 0 && a->mem.size != 0){
-				memsize = a->mem.size;
-				conf.mem[0].base = a->mem.base;
-				conf.mem[0].limit = a->mem.base + memsize;
-			}
-			break;
-		case AtagCmdline:
-			n = (a->size * sizeof(u32int)) - offsetof(Atag, cmdline[0]);
-			if(a->cmdline + n < BOOTARGS + BOOTARGSLEN)
-				a->cmdline[n] = 0;
-			else
-				BOOTARGS[BOOTARGSLEN-1] = 0;
-			plan9iniinit(a->cmdline, 1);
-			break;
-		}
-		a = (Atag*)((u32int*)a + a->size);
-	}
-}
-
-void
-machinit(void)
-{
-	m->machno = 0;
-	machaddr[m->machno] = m;
-
-	m->ticks = 1;
-	m->perf.period = 1;
-
-	conf.nmach = 1;
-
-	active.machs = 1;
-	active.exiting = 0;
-
-	up = nil;
-}
-
-static void
-optionsinit(char* s)
-{
-	strecpy(oargb, oargb+sizeof(oargb), s);
-
-	oargblen = strlen(oargb);
-	oargc = tokenize(oargb, oargv, nelem(oargv)-1);
-	oargv[oargc] = nil;
-}
-
-void
-main(void)
-{
-	extern char edata[], end[];
-	uint rev;
-
-	okay(1);
-	m = (Mach*)MACHADDR;
-	memset(edata, 0, end - edata);	/* clear bss */
-	machinit();
-	mmuinit1();
-
-	optionsinit("/boot/boot boot");
-	quotefmtinstall();
-	
-	ataginit((Atag*)BOOTARGS);
-	confinit();		/* figures out amount of memory */
-	xinit();
-	uartconsinit();
-	screeninit();
-
-	print("\nPlan 9 from Bell Labs\n");
-	rev = getfirmware();
-	print("firmware: rev %d\n", rev);
-	if(rev < Minfirmrev){
-		print("Sorry, firmware (start*.elf) must be at least rev %d"
-		      " or newer than %s\n", Minfirmrev, Minfirmdate);
-		for(;;)
-			;
-	}
-	trapinit();
-	clockinit();
-	printinit();
-	timersinit();
-	if(conf.monitor)
-		swcursorinit();
-	cpuidprint();
-	archreset();
-
-	procinit0();
-	initseg();
-	links();
-	chandevreset();			/* most devices are discovered here */
-	pageinit();
-	swapinit();
-	userinit();
-	schedinit();
-	assert(0);			/* shouldn't have returned */
-}
-
-/*
- *  starting place for first process
- */
-void
-init0(void)
-{
-	int i;
-	char buf[2*KNAMELEN];
-
-	up->nerrlab = 0;
-	coherence();
-	spllo();
-
-	/*
-	 * These are o.k. because rootinit is null.
-	 * Then early kproc's will have a root and dot.
-	 */
-	up->slash = namec("#/", Atodir, 0, 0);
-	pathclose(up->slash->path);
-	up->slash->path = newpath("/");
-	up->dot = cclone(up->slash);
-
-	chandevinit();
-
-	if(!waserror()){
-		snprint(buf, sizeof(buf), "%s %s", "ARM", conffile);
-		ksetenv("terminal", buf, 0);
-		ksetenv("cputype", "arm", 0);
-		if(cpuserver)
-			ksetenv("service", "cpu", 0);
-		else
-			ksetenv("service", "terminal", 0);
-		snprint(buf, sizeof(buf), "-a %s", getethermac());
-		ksetenv("etherargs", buf, 0);
-
-		/* convert plan9.ini variables to #e and #ec */
-		for(i = 0; i < nconf; i++) {
-			ksetenv(confname[i], confval[i], 0);
-			ksetenv(confname[i], confval[i], 1);
-		}
-		poperror();
-	}
-	kproc("alarm", alarmkproc, 0);
-	touser(sp);
-	assert(0);			/* shouldn't have returned */
-}
-
-static void
-bootargs(uintptr base)
-{
-	int i;
-	ulong ssize;
-	char **av, *p;
-
-	/*
-	 * Push the boot args onto the stack.
-	 * The initial value of the user stack must be such
-	 * that the total used is larger than the maximum size
-	 * of the argument list checked in syscall.
-	 */
-	i = oargblen+1;
-	p = UINT2PTR(STACKALIGN(base + BY2PG - Ustkheadroom - i));
-	memmove(p, oargb, i);
-
-	/*
-	 * Now push the argv pointers.
-	 * The code jumped to by touser in lproc.s expects arguments
-	 *	main(char* argv0, ...)
-	 * and calls
-	 * 	startboot("/boot/boot", &argv0)
-	 * not the usual (int argc, char* argv[])
-	 */
-	av = (char**)(p - (oargc+1)*sizeof(char*));
-	ssize = base + BY2PG - PTR2UINT(av);
-	for(i = 0; i < oargc; i++)
-		*av++ = (oargv[i] - oargb) + (p - base) + (USTKTOP - BY2PG);
-	*av = nil;
-	sp = USTKTOP - ssize;
-}
-
-/*
- *  create the first process
- */
-void
-userinit(void)
-{
-	Proc *p;
-	Segment *s;
-	KMap *k;
-	Page *pg;
-
-	/* no processes yet */
-	up = nil;
-
-	p = newproc();
-	p->pgrp = newpgrp();
-	p->egrp = smalloc(sizeof(Egrp));
-	p->egrp->ref = 1;
-	p->fgrp = dupfgrp(nil);
-	p->rgrp = newrgrp();
-	p->procmode = 0640;
-
-	kstrdup(&eve, "");
-	kstrdup(&p->text, "*init*");
-	kstrdup(&p->user, eve);
-
-	/*
-	 * Kernel Stack
-	 */
-	p->sched.pc = PTR2UINT(init0);
-	p->sched.sp = PTR2UINT(p->kstack+KSTACK-sizeof(up->s.args)-sizeof(uintptr));
-	p->sched.sp = STACKALIGN(p->sched.sp);
-
-	/*
-	 * User Stack
-	 *
-	 * Technically, newpage can't be called here because it
-	 * should only be called when in a user context as it may
-	 * try to sleep if there are no pages available, but that
-	 * shouldn't be the case here.
-	 */
-	s = newseg(SG_STACK, USTKTOP-USTKSIZE, USTKSIZE/BY2PG);
-	s->flushme++;
-	p->seg[SSEG] = s;
-	pg = newpage(1, 0, USTKTOP-BY2PG);
-	segpage(s, pg);
-	k = kmap(pg);
-	bootargs(VA(k));
-	kunmap(k);
-
-	/*
-	 * Text
-	 */
-	s = newseg(SG_TEXT, UTZERO, 1);
-	p->seg[TSEG] = s;
-	pg = newpage(1, 0, UTZERO);
-	memset(pg->cachectl, PG_TXTFLUSH, sizeof(pg->cachectl));
-	segpage(s, pg);
-	k = kmap(s->map[0]->pages[0]);
-	memmove(UINT2PTR(VA(k)), initcode, sizeof initcode);
-	kunmap(k);
-
-	ready(p);
-}
-
-void
-confinit(void)
-{
-	int i;
-	ulong kpages;
-	uintptr pa;
-	char *p;
-
-	if(0 && (p = getconf("service")) != nil){
-		if(strcmp(p, "cpu") == 0)
-			cpuserver = 1;
-		else if(strcmp(p,"terminal") == 0)
-			cpuserver = 0;
-	}
-	if((p = getconf("*maxmem")) != nil){
-		memsize = strtoul(p, 0, 0) - PHYSDRAM;
-		if (memsize < 16*MB)		/* sanity */
-			memsize = 16*MB;
-	}
-
-	getramsize(&conf.mem[0]);
-	if(conf.mem[0].limit == 0){
-		conf.mem[0].base = PHYSDRAM;
-		conf.mem[0].limit = PHYSDRAM + memsize;
-	}else if(p != nil)
-		conf.mem[0].limit = conf.mem[0].base + memsize;
-
-	conf.npage = 0;
-	pa = PADDR(PGROUND(PTR2UINT(end)));
-
-	/*
-	 *  we assume that the kernel is at the beginning of one of the
-	 *  contiguous chunks of memory and fits therein.
-	 */
-	for(i=0; i<nelem(conf.mem); i++){
-		/* take kernel out of allocatable space */
-		if(pa > conf.mem[i].base && pa < conf.mem[i].limit)
-			conf.mem[i].base = pa;
-
-		conf.mem[i].npage = (conf.mem[i].limit - conf.mem[i].base)/BY2PG;
-		conf.npage += conf.mem[i].npage;
-	}
-
-	conf.upages = (conf.npage*80)/100;
-	conf.ialloc = ((conf.npage-conf.upages)/2)*BY2PG;
-
-	/* only one processor */
-	conf.nmach = 1;
-
-	/* set up other configuration parameters */
-	conf.nproc = 100 + ((conf.npage*BY2PG)/MB)*5;
-	if(cpuserver)
-		conf.nproc *= 3;
-	if(conf.nproc > 2000)
-		conf.nproc = 2000;
-	conf.nswap = conf.npage*3;
-	conf.nswppo = 4096;
-	conf.nimage = 200;
-
-	conf.copymode = 0;		/* copy on write */
-
-	/*
-	 * Guess how much is taken by the large permanent
-	 * datastructures. Mntcache and Mntrpc are not accounted for
-	 * (probably ~300KB).
-	 */
-	kpages = conf.npage - conf.upages;
-	kpages *= BY2PG;
-	kpages -= conf.upages*sizeof(Page)
-		+ conf.nproc*sizeof(Proc)
-		+ conf.nimage*sizeof(Image)
-		+ conf.nswap
-		+ conf.nswppo*sizeof(Page);
-	mainmem->maxsize = kpages;
-	if(!cpuserver)
-		/*
-		 * give terminals lots of image memory, too; the dynamic
-		 * allocation will balance the load properly, hopefully.
-		 * be careful with 32-bit overflow.
-		 */
-		imagmem->maxsize = kpages;
-
-}
-
-static void
-shutdown(int ispanic)
-{
-	int ms, once;
-
-	lock(&active);
-	if(ispanic)
-		active.ispanic = ispanic;
-	else if(m->machno == 0 && (active.machs & (1<<m->machno)) == 0)
-		active.ispanic = 0;
-	once = active.machs & (1<<m->machno);
-	active.machs &= ~(1<<m->machno);
-	active.exiting = 1;
-	unlock(&active);
-
-	if(once)
-		iprint("cpu%d: exiting\n", m->machno);
-	spllo();
-	for(ms = 5*1000; ms > 0; ms -= TK2MS(2)){
-		delay(TK2MS(2));
-		if(active.machs == 0 && consactive() == 0)
-			break;
-	}
-	delay(1000);
-}
-
-/*
- *  exit kernel either on a panic or user request
- */
-void
-exit(int code)
-{
-	shutdown(code);
-	splfhi();
-	archreboot();
-}
-
-/*
- * stub for ../omap/devether.c
- */
-int
-isaconfig(char *class, int ctlrno, ISAConf *isa)
-{
-	USED(ctlrno);
-	USED(isa);
-	return strcmp(class, "ether") == 0;
-}
-
-/*
- * the new kernel is already loaded at address `code'
- * of size `size' and entry point `entry'.
- */
-void
-reboot(void *entry, void *code, ulong size)
-{
-	void (*f)(ulong, ulong, ulong);
-
-	print("starting reboot...");
-	writeconf();
-	shutdown(0);
-
-	/*
-	 * should be the only processor running now
-	 */
-
-	print("reboot entry %#lux code %#lux size %ld\n",
-		PADDR(entry), PADDR(code), size);
-	delay(100);
-
-	/* turn off buffered serial console */
-	serialoq = nil;
-	kprintoq = nil;
-	screenputs = nil;
-
-	/* shutdown devices */
-	chandevshutdown();
-
-	/* stop the clock (and watchdog if any) */
-	clockshutdown();
-
-	splfhi();
-	intrsoff();
-
-	/* setup reboot trampoline function */
-	f = (void*)REBOOTADDR;
-	memmove(f, rebootcode, sizeof(rebootcode));
-	cacheuwbinv();
-
-	/* off we go - never to return */
-	(*f)(PADDR(entry), PADDR(code), size);
-
-	iprint("loaded kernel returned!\n");
-	delay(1000);
-	archreboot();
-}
-
-int
-cmpswap(long *addr, long old, long new)
-{
-	return cas32(addr, old, new);
-}

+ 0 - 104
sys/src/9/bcm/mem.h

@@ -1,104 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Memory and machine-specific definitions.  Used in C and assembler.
- */
-#define KiB		1024u			/* Kibi 0x0000000000000400 */
-#define MiB		1048576u		/* Mebi 0x0000000000100000 */
-#define GiB		1073741824u		/* Gibi 000000000040000000 */
-
-/*
- * Sizes
- */
-#define	BY2PG		(4*KiB)			/* bytes per page */
-#define	PGSHIFT		12			/* log(BY2PG) */
-
-#define	MAXMACH		1			/* max # cpus system can run */
-#define	MACHSIZE	BY2PG
-
-#define KSTKSIZE	(8*KiB)
-#define STACKALIGN(sp)	((sp) & ~3)		/* bug: assure with alloc */
-
-/*
- * Address spaces.
- * KTZERO is used by kprof and dumpstack (if any).
- *
- * KZERO is mapped to physical 0 (start of ram).
- *
- * vectors are at 0, plan9.ini is at KZERO+256 and is limited to 16K by
- * devenv.
- */
-
-#define	KSEG0		0x80000000		/* kernel segment */
-/* mask to check segment; good for 512MB dram */
-#define	KSEGM		0xE0000000
-#define	KZERO		KSEG0			/* kernel address space */
-#define CONFADDR	(KZERO+0x100)		/* unparsed plan9.ini */
-#define	MACHADDR	(KZERO+0x2000)		/* Mach structure */
-#define	L2		(KZERO+0x3000)		/* L2 ptes for vectors etc */
-#define	VCBUFFER	(KZERO+0x3400)		/* videocore mailbox buffer */
-#define	FIQSTKTOP	(KZERO+0x4000)		/* FIQ stack */
-#define	L1		(KZERO+0x4000)		/* tt ptes: 16KiB aligned */
-#define	KTZERO		(KZERO+0x8000)		/* kernel text start */
-#define VIRTIO		0x7E000000		/* i/o registers */
-#define	FRAMEBUFFER	0xA0000000		/* video framebuffer */
-
-#define	UZERO		0			/* user segment */
-#define	UTZERO		(UZERO+BY2PG)		/* user text start */
-#define UTROUND(t)	ROUNDUP((t), BY2PG)
-#define	USTKTOP		0x20000000		/* user segment end +1 */
-#define	USTKSIZE	(8*1024*1024)		/* user stack size */
-#define	TSTKTOP		(USTKTOP-USTKSIZE)	/* sysexec temporary stack */
-#define	TSTKSIZ	 	256
-
-/* address at which to copy and execute rebootcode */
-#define	REBOOTADDR	(KZERO+0x3400)
-
-/*
- * Legacy...
- */
-#define BLOCKALIGN	32			/* only used in allocb.c */
-#define KSTACK		KSTKSIZE
-
-/*
- * Sizes
- */
-#define BI2BY		8			/* bits per byte */
-#define BY2SE		4
-#define BY2WD		4
-#define BY2V		8			/* only used in xalloc.c */
-
-#define CACHELINESZ	32
-#define	PTEMAPMEM	(1024*1024)
-#define	PTEPERTAB	(PTEMAPMEM/BY2PG)
-#define	SEGMAPSIZE	1984
-#define	SSEGMAPSIZE	16
-#define	PPN(x)		((x)&~(BY2PG-1))
-
-/*
- * With a little work these move to port.
- */
-#define	PTEVALID	(1<<0)
-#define	PTERONLY	0
-#define	PTEWRITE	(1<<1)
-#define	PTEUNCACHED	(1<<2)
-#define PTEKERNEL	(1<<3)
-
-/*
- * Physical machine information from here on.
- *	PHYS addresses as seen from the arm cpu.
- *	BUS  addresses as seen from the videocore gpu.
- */
-#define	PHYSDRAM	0
-#define BUSDRAM		0x40000000
-#define	DRAMSIZE	(512*MiB)
-#define	PHYSIO		0x20000000
-#define	BUSIO		0x7E000000
-#define	IOSIZE		(16*MiB)

+ 0 - 132
sys/src/9/bcm/mkfile

@@ -1,132 +0,0 @@
-CONF=pi
-CONFLIST=pi picpu pifat
-EXTRACOPIES=
-
-loadaddr=0x80008000
-
-objtype=arm
-</$objtype/mkfile
-p=9
-
-DEVS=`{rc ../port/mkdevlist $CONF}
-
-PORT=\
-	alarm.$O\
-	alloc.$O\
-	allocb.$O\
-	auth.$O\
-	cache.$O\
-	chan.$O\
-	dev.$O\
-	edf.$O\
-	fault.$O\
-	mul64fract.$O\
-	page.$O\
-	parse.$O\
-	pgrp.$O\
-	portclock.$O\
-	print.$O\
-	proc.$O\
-	qio.$O\
-	qlock.$O\
-	rdb.$O\
-	rebootcmd.$O\
-	segment.$O\
-	swap.$O\
-	syscallfmt.$O\
-	sysfile.$O\
-	sysproc.$O\
-	taslock.$O\
-	tod.$O\
-	xalloc.$O\
-
-OBJ=\
-	l.$O\
-	lexception.$O\
-	lproc.$O\
-	arch.$O\
-	clock.$O\
-	fpi.$O\
-	fpiarm.$O\
-	fpimem.$O\
-	main.$O\
-	mmu.$O\
-	random.$O\
-	syscall.$O\
-	trap.$O\
-	$CONF.root.$O\
-	$CONF.rootc.$O\
-	$DEVS\
-	$PORT\
-
-# HFILES=
-
-LIB=\
-	/$objtype/lib/libmemlayer.a\
-	/$objtype/lib/libmemdraw.a\
-	/$objtype/lib/libdraw.a\
-	/$objtype/lib/libip.a\
-	/$objtype/lib/libsec.a\
-	/$objtype/lib/libmp.a\
-	/$objtype/lib/libc.a\
-
-9:V: $p$CONF s$p$CONF
-
-$p$CONF:DQ:	$CONF.c $OBJ $LIB mkfile
-	$CC $CFLAGS '-DKERNDATE='`{date -n} $CONF.c
-	echo '# linking raw kernel'	# H6: no headers, data segment aligned
-	$LD -l -o $target -H6 -R4096 -T$loadaddr $OBJ $CONF.$O $LIB
-
-s$p$CONF:DQ:	$CONF.$O $OBJ $LIB
-	echo '# linking kernel with symbols'
-	$LD -l -o $target -R4096 -T$loadaddr $OBJ $CONF.$O $LIB
-	size $target
-
-$p$CONF.gz:D:	$p$CONF
-	gzip -9 <$p$CONF >$target
-
-$OBJ: $HFILES
-
-install:V: /$objtype/$p$CONF
-
-/$objtype/$p$CONF:D: $p$CONF s$p$CONF
-	cp -x $p$CONF s$p$CONF /$objtype/ &
-	for(i in $EXTRACOPIES)
-		{ 9fs $i && cp $p$CONF s$p$CONF /n/$i/$objtype && echo -n $i... & }
-	wait
-	echo
-	touch $target
-
-<../boot/bootmkfile
-<../port/portmkfile
-<|../port/mkbootrules $CONF
-
-arch.$O clock.$O fpiarm.$O main.$O mmu.$O screen.$O syscall.$O trap.$O: \
-	/$objtype/include/ureg.h
-
-archbcm.$O devether.$0: etherif.h ../port/netif.h
-archbcm.$O: ../port/flashif.h
-fpi.$O fpiarm.$O fpimem.$O: ../port/fpi.h
-l.$O lexception.$O lproc.$O mmu.$O: arm.s mem.h
-main.$O: errstr.h init.h reboot.h
-devmouse.$O mouse.$O screen.$O: screen.h
-devusb.$O: ../port/usb.h
-usbehci.$O usbohci.$O usbuhci.$O: ../port/usb.h usbehci.h uncached.h
-
-init.h:D:	../port/initcode.c init9.s
-	$CC ../port/initcode.c
-	$AS init9.s
-	$LD -l -R1 -s -o init.out init9.$O initcode.$O /$objtype/lib/libc.a
-	{echo 'uchar initcode[]={'
-	 xd -1x <init.out |
-		sed -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
-	 echo '};'} > init.h
-
-reboot.h:D:	rebootcode.s arm.s arm.h mem.h
-	$AS rebootcode.s
-	# -lc is only for memmove.  -T arg is PADDR(REBOOTADDR)
-	$LD -l -s -T0x3400 -R4 -o reboot.out rebootcode.$O -lc
-	{echo 'uchar rebootcode[]={'
-	 xd -1x reboot.out |
-		sed -e '1,2d' -e 's/^[0-9a-f]+ //' -e 's/ ([0-9a-f][0-9a-f])/0x\1,/g'
-	 echo '};'} > reboot.h

+ 0 - 327
sys/src/9/bcm/mmu.c

@@ -1,327 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-#include "arm.h"
-
-#define L1X(va)		FEXT((va), 20, 12)
-#define L2X(va)		FEXT((va), 12, 8)
-
-enum {
-	L1lo		= UZERO/MiB,		/* L1X(UZERO)? */
-	L1hi		= (USTKTOP+MiB-1)/MiB,	/* L1X(USTKTOP+MiB-1)? */
-};
-
-void
-mmuinit(void)
-{
-	PTE *l1, *l2;
-	uintptr pa, va;
-
-	l1 = (PTE*)PADDR(L1);
-	l2 = (PTE*)PADDR(L2);
-
-	/*
-	 * map all of ram at KZERO
-	 */
-	va = KZERO;
-	for(pa = PHYSDRAM; pa < PHYSDRAM+DRAMSIZE; pa += MiB){
-		l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section|Cached|Buffered;
-		va += MiB;
-	}
-
-	/*
-	 * identity map first MB of ram so mmu can be enabled
-	 */
-	l1[L1X(PHYSDRAM)] = PHYSDRAM|Dom0|L1AP(Krw)|Section|Cached|Buffered;
-
-	/*
-	 * map i/o registers 
-	 */
-	va = VIRTIO;
-	for(pa = PHYSIO; pa < PHYSIO+IOSIZE; pa += MiB){
-		l1[L1X(va)] = pa|Dom0|L1AP(Krw)|Section;
-		va += MiB;
-	}
-
-	/*
-	 * double map exception vectors at top of virtual memory
-	 */
-	va = HVECTORS;
-	l1[L1X(va)] = (uintptr)l2|Dom0|Coarse;
-	l2[L2X(va)] = PHYSDRAM|L2AP(Krw)|Small;
-}
-
-void
-mmuinit1(void)
-{
-	PTE *l1;
-
-	l1 = (PTE*)L1;
-	m->mmul1 = l1;
-
-	/*
-	 * undo identity map of first MB of ram
-	 */
-	l1[L1X(PHYSDRAM)] = 0;
-	cachedwbse(&l1[L1X(PHYSDRAM)], sizeof(PTE));
-	mmuinvalidate();
-}
-
-static void
-mmul2empty(Proc* proc, int clear)
-{
-	PTE *l1;
-	Page **l2, *page;
-
-	l1 = m->mmul1;
-	l2 = &proc->mmul2;
-	for(page = *l2; page != nil; page = page->next){
-		if(clear)
-			memset(UINT2PTR(page->va), 0, BY2PG);
-		l1[page->daddr] = Fault;
-		l2 = &page->next;
-	}
-	*l2 = proc->mmul2cache;
-	proc->mmul2cache = proc->mmul2;
-	proc->mmul2 = nil;
-}
-
-static void
-mmul1empty(void)
-{
-#ifdef notdef
-/* there's a bug in here */
-	PTE *l1;
-
-	/* clean out any user mappings still in l1 */
-	if(m->mmul1lo > L1lo){
-		if(m->mmul1lo == 1)
-			m->mmul1[L1lo] = Fault;
-		else
-			memset(&m->mmul1[L1lo], 0, m->mmul1lo*sizeof(PTE));
-		m->mmul1lo = L1lo;
-	}
-	if(m->mmul1hi < L1hi){
-		l1 = &m->mmul1[m->mmul1hi];
-		if((L1hi - m->mmul1hi) == 1)
-			*l1 = Fault;
-		else
-			memset(l1, 0, (L1hi - m->mmul1hi)*sizeof(PTE));
-		m->mmul1hi = L1hi;
-	}
-#else
-	memset(&m->mmul1[L1lo], 0, (L1hi - L1lo)*sizeof(PTE));
-#endif /* notdef */
-}
-
-void
-mmuswitch(Proc* proc)
-{
-	int x;
-	PTE *l1;
-	Page *page;
-
-	/* do kprocs get here and if so, do they need to? */
-	if(m->mmupid == proc->pid && !proc->newtlb)
-		return;
-	m->mmupid = proc->pid;
-
-	/* write back dirty and invalidate l1 caches */
-	cacheuwbinv();
-
-	if(proc->newtlb){
-		mmul2empty(proc, 1);
-		proc->newtlb = 0;
-	}
-
-	mmul1empty();
-
-	/* move in new map */
-	l1 = m->mmul1;
-	for(page = proc->mmul2; page != nil; page = page->next){
-		x = page->daddr;
-		l1[x] = PPN(page->pa)|Dom0|Coarse;
-		/* know here that L1lo < x < L1hi */
-		if(x+1 - m->mmul1lo < m->mmul1hi - x)
-			m->mmul1lo = x+1;
-		else
-			m->mmul1hi = x;
-	}
-
-	/* make sure map is in memory */
-	/* could be smarter about how much? */
-	cachedwbse(&l1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
-
-	/* lose any possible stale tlb entries */
-	mmuinvalidate();
-}
-
-void
-flushmmu(void)
-{
-	int s;
-
-	s = splhi();
-	up->newtlb = 1;
-	mmuswitch(up);
-	splx(s);
-}
-
-void
-mmurelease(Proc* proc)
-{
-	Page *page, *next;
-
-	/* write back dirty and invalidate l1 caches */
-	cacheuwbinv();
-
-	mmul2empty(proc, 0);
-	for(page = proc->mmul2cache; page != nil; page = next){
-		next = page->next;
-		if(--page->ref)
-			panic("mmurelease: page->ref %d", page->ref);
-		pagechainhead(page);
-	}
-	if(proc->mmul2cache && palloc.r.p)
-		wakeup(&palloc.r);
-	proc->mmul2cache = nil;
-
-	mmul1empty();
-
-	/* make sure map is in memory */
-	/* could be smarter about how much? */
-	cachedwbse(&m->mmul1[L1X(UZERO)], (L1hi - L1lo)*sizeof(PTE));
-
-	/* lose any possible stale tlb entries */
-	mmuinvalidate();
-}
-
-void
-putmmu(uintptr va, uintptr pa, Page* page)
-{
-	int x;
-	Page *pg;
-	PTE *l1, *pte;
-
-	x = L1X(va);
-	l1 = &m->mmul1[x];
-	if(*l1 == Fault){
-		/* wasteful - l2 pages only have 256 entries - fix */
-		if(up->mmul2cache == nil){
-			/* auxpg since we don't need much? memset if so */
-			pg = newpage(1, 0, 0);
-			pg->va = VA(kmap(pg));
-		}
-		else{
-			pg = up->mmul2cache;
-			up->mmul2cache = pg->next;
-			memset(UINT2PTR(pg->va), 0, BY2PG);
-		}
-		pg->daddr = x;
-		pg->next = up->mmul2;
-		up->mmul2 = pg;
-
-		/* force l2 page to memory */
-		cachedwbse((void *)pg->va, BY2PG);
-
-		*l1 = PPN(pg->pa)|Dom0|Coarse;
-		cachedwbse(l1, sizeof *l1);
-
-		if(x >= m->mmul1lo && x < m->mmul1hi){
-			if(x+1 - m->mmul1lo < m->mmul1hi - x)
-				m->mmul1lo = x+1;
-			else
-				m->mmul1hi = x;
-		}
-	}
-	pte = UINT2PTR(KADDR(PPN(*l1)));
-
-	/* protection bits are
-	 *	PTERONLY|PTEVALID;
-	 *	PTEWRITE|PTEVALID;
-	 *	PTEWRITE|PTEUNCACHED|PTEVALID;
-	 */
-	x = Small;
-	if(!(pa & PTEUNCACHED))
-		x |= Cached|Buffered;
-	if(pa & PTEWRITE)
-		x |= L2AP(Urw);
-	else
-		x |= L2AP(Uro);
-	pte[L2X(va)] = PPN(pa)|x;
-	cachedwbse(&pte[L2X(va)], sizeof pte[0]);
-
-	/* clear out the current entry */
-	mmuinvalidateaddr(PPN(va));
-
-	/*  write back dirty entries - we need this because the pio() in
-	 *  fault.c is writing via a different virt addr and won't clean
-	 *  its changes out of the dcache.  Page coloring doesn't work
-	 *  on this mmu because the virtual cache is set associative
-	 *  rather than direct mapped.
-	 */
-	cachedwbinv();
-	if(page->cachectl[0] == PG_TXTFLUSH){
-		/* pio() sets PG_TXTFLUSH whenever a text pg has been written */
-		cacheiinv();
-		page->cachectl[0] = PG_NOFLUSH;
-	}
-	checkmmu(va, PPN(pa));
-}
-
-/*
- * Return the number of bytes that can be accessed via KADDR(pa).
- * If pa is not a valid argument to KADDR, return 0.
- */
-uintptr
-cankaddr(uintptr pa)
-{
-	if(pa < PHYSDRAM + memsize)		/* assumes PHYSDRAM is 0 */
-		return PHYSDRAM + memsize - pa;
-	return 0;
-}
-
-uintptr
-mmukmap(uintptr va, uintptr pa, usize size)
-{
-	int o;
-	usize n;
-	PTE *pte, *pte0;
-
-	assert((va & (MiB-1)) == 0);
-	o = pa & (MiB-1);
-	pa -= o;
-	size += o;
-	pte = pte0 = &m->mmul1[L1X(va)];
-	for(n = 0; n < size; n += MiB)
-		if(*pte++ != Fault)
-			return 0;
-	pte = pte0;
-	for(n = 0; n < size; n += MiB){
-		*pte++ = (pa+n)|Dom0|L1AP(Krw)|Section;
-		mmuinvalidateaddr(va+n);
-	}
-	cachedwbse(pte0, pte - pte0);
-	return va + o;
-}
-
-
-void
-checkmmu(uintptr va, uintptr pa)
-{
-	USED(va);
-	USED(pa);
-}
-

+ 0 - 10
sys/src/9/bcm/mouse.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../omap/mouse.c"

+ 0 - 61
sys/src/9/bcm/pi

@@ -1,61 +0,0 @@
-dev
-	root
-	cons
-	env
-	pipe
-	proc
-	mnt
-	srv
-	dup
-	arch
-	ssl
-	tls
-	cap
-	fs
-	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
-	draw	screen
-	mouse	mouse
-	kbmap
-	kbin	kbd latin1
-	uart
-
-	fakertc
-	sd
-	usb
-	ether	netif
-
-link
-	archbcm
-	loopbackmedium
-	ethermedium
-	usbdwc
-	etherusb
-
-ip
-	tcp
-	udp
-	ipifc
-	icmp
-	icmp6
-	ipmux
-
-misc
-	uartmini
-	sdmmc	emmc
-	dma
-	vcore
-	vfp3	coproc
-
-port
-	int cpuserver = 0;
-
-boot boot #S/sdM0/
-	local
-	tcp
-
-bootdir
-	boot$CONF.out	boot
-	/arm/bin/ip/ipconfig
-	/arm/bin/auth/factotum
-	/arm/bin/fossil/fossil
-	/arm/bin/usb/usbd

+ 0 - 61
sys/src/9/bcm/picpu

@@ -1,61 +0,0 @@
-dev
-	root
-	cons
-	env
-	pipe
-	proc
-	mnt
-	srv
-	dup
-	arch
-	ssl
-	tls
-	cap
-	fs
-	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
-	draw	screen
-	mouse	mouse
-	kbmap
-	kbin	kbd latin1
-	uart
-
-	fakertc
-	sd
-	usb
-	ether	netif
-
-link
-	archbcm
-	loopbackmedium
-	ethermedium
-	usbdwc
-	etherusb
-
-ip
-	tcp
-	udp
-	ipifc
-	icmp
-	icmp6
-	ipmux
-
-misc
-	uartmini
-	sdmmc	emmc
-	dma
-	vcore
-	vfp3	coproc
-
-port
-	int cpuserver = 1;
-
-boot cpu boot #S/sdM0/
-	local
-	tcp
-
-bootdir
-	boot$CONF.out	boot
-	/arm/bin/ip/ipconfig
-	/arm/bin/auth/factotum
-	/arm/bin/fossil/fossil
-	/arm/bin/usb/usbd

+ 0 - 57
sys/src/9/bcm/pifat

@@ -1,57 +0,0 @@
-dev
-	root
-	cons
-	env
-	pipe
-	proc
-	mnt
-	srv
-	dup
-	arch
-	ip		arp chandial ip ipv6 ipaux iproute netlog nullmedium pktmedium ptclbsum inferno
-	draw	screen vcore
-	mouse	mouse
-	kbin	kbd latin1
-	uart
-
-	fakertc
-	sd
-	usb
-
-link
-	archbcm
-	loopbackmedium
-	ethermedium
-	usbdwc
-
-ip
-	tcp
-	udp
-	ipifc
-	icmp
-	icmp6
-	ipmux
-
-misc
-	uartmini
-	sdmmc	emmc
-	dma
-	vfp3	coproc
-
-port
-	int cpuserver = 0;
-
-bootdir
-	boot.rc			boot
-	/arm/bin/rc
-	/rc/lib/rcmain
-	/arm/bin/mount
-	/arm/bin/bind
-	/arm/bin/echo
-	/arm/bin/disk/fdisk
-	/arm/bin/dossrv
-	/arm/bin/ls
-	/arm/bin/cat
-	/arm/bin/usb/usbd
-
-

+ 0 - 93
sys/src/9/bcm/rebootcode.s

@@ -1,93 +0,0 @@
-/*
- * armv6 reboot code
- */
-#include "arm.s"
-
-/*
- * Turn off MMU, then copy the new kernel to its correct location
- * in physical memory.  Then jump to the start of the kernel.
- */
-
-/* main(PADDR(entry), PADDR(code), size); */
-TEXT	main(SB), 1, $-4
-	MOVW	$setR12(SB), R12
-
-	/* copy in arguments before stack gets unmapped */
-	MOVW	R0, R8			/* entry point */
-	MOVW	p2+4(FP), R9		/* source */
-	MOVW	n+8(FP), R10		/* byte count */
-
-	/* SVC mode, interrupts disabled */
-	MOVW	$(PsrDirq|PsrDfiq|PsrMsvc), R1
-	MOVW	R1, CPSR
-
-	/* prepare to turn off mmu  */
-	BL	cachesoff(SB)
-
-	/* turn off mmu */
-	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-	BIC	$CpCmmu, R1
-	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-
-	/* set up a tiny stack for local vars and memmove args */
-	MOVW	R8, SP			/* stack top just before kernel dest */
-	SUB	$20, SP			/* allocate stack frame */
-
-	/* copy the kernel to final destination */
-	MOVW	R8, 16(SP)		/* save dest (entry point) */
-	MOVW	R8, R0			/* first arg is dest */
-	MOVW	R9, 8(SP)		/* push src */
-	MOVW	R10, 12(SP)		/* push size */
-	BL	memmove(SB)
-	MOVW	16(SP), R8		/* restore entry point */
-
-	/* jump to kernel physical entry point */
-	B	(R8)
-	B	0(PC)
-
-/*
- * turn the caches off, double map PHYSDRAM & KZERO, invalidate TLBs, revert
- * to tiny addresses.  upon return, it will be safe to turn off the mmu.
- * clobbers R0-R2, and returns with SP invalid.
- */
-TEXT cachesoff(SB), 1, $-4
-
-	/* write back and invalidate caches */
-	BARRIERS
-	MOVW	$0, R0
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwbi), CpCACHEall
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEall
-
-	/* turn caches off */
-	MRC	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-	BIC	$(CpCdcache|CpCicache|CpCpredict), R1
-	MCR	CpSC, 0, R1, C(CpCONTROL), C(0), CpMainctl
-
-	/* invalidate stale TLBs before changing them */
-	BARRIERS
-	MOVW	$KZERO, R0			/* some valid virtual address */
-	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
-	BARRIERS
-
-	/* from here on, R0 is base of physical memory */
-	MOVW	$PHYSDRAM, R0
-
-	/* redo double map of first MiB PHYSDRAM = KZERO */
-	MOVW	$(L1+L1X(PHYSDRAM)), R2		/* address of PHYSDRAM's PTE */
-	MOVW	$PTEDRAM, R1			/* PTE bits */
-	ORR	R0, R1				/* dram base */
-	MOVW	R1, (R2)
-
-	/* invalidate stale TLBs again */
-	BARRIERS
-	MCR	CpSC, 0, R0, C(CpTLB), C(CpTLBinvu), CpTLBinv
-	BARRIERS
-
-	/* relocate SB and return address to PHYSDRAM addressing */
-	MOVW	$KSEGM, R1		/* clear segment bits */
-	BIC	R1, R12			/* adjust SB */
-	ORR	R0, R12
-	BIC	R1, R14			/* adjust return address */
-	ORR	R0, R14
-
-	RET

+ 0 - 554
sys/src/9/bcm/screen.c

@@ -1,554 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2385 framebuffer
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-#define	Image	IMAGE
-#include <draw.h>
-#include <memdraw.h>
-#include <cursor.h>
-#include "screen.h"
-
-enum {
-	Tabstop		= 4,
-	Scroll		= 8,
-	Wid		= 1024,
-	Ht		= 768,
-	Depth		= 16,
-};
-
-Cursor	arrow = {
-	{ -1, -1 },
-	{ 0xFF, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0C,
-	  0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,
-	  0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8C, 0x04,
-	  0x92, 0x08, 0x91, 0x10, 0xA0, 0xA0, 0xC0, 0x40,
-	},
-	{ 0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFC, 0x7F, 0xF0,
-	  0x7F, 0xE0, 0x7F, 0xE0, 0x7F, 0xF0, 0x7F, 0xF8,
-	  0x7F, 0xFC, 0x7F, 0xFE, 0x7F, 0xFC, 0x73, 0xF8,
-	  0x61, 0xF0, 0x60, 0xE0, 0x40, 0x40, 0x00, 0x00,
-	},
-};
-
-Memimage *gscreen;
-
-static Memdata xgdata;
-
-static Memimage xgscreen =
-{
-	{ 0, 0, Wid, Ht },	/* r */
-	{ 0, 0, Wid, Ht },	/* clipr */
-	Depth,			/* depth */
-	3,			/* nchan */
-	RGB16,			/* chan */
-	nil,			/* cmap */
-	&xgdata,		/* data */
-	0,			/* zero */
-	0, 			/* width in words of a single scan line */
-	0,			/* layer */
-	0,			/* flags */
-};
-
-static Memimage *conscol;
-static Memimage *back;
-static Memsubfont *memdefont;
-
-static Lock screenlock;
-
-static Point	curpos;
-static int	h, w;
-static Rectangle window;
-
-static void myscreenputs(char *s, int n);
-static void screenputc(char *buf);
-static void screenwin(void);
-
-/*
- * Software cursor. 
- */
-static int	swvisible;	/* is the cursor visible? */
-static int	swenabled;	/* is the cursor supposed to be on the screen? */
-static Memimage *swback;	/* screen under cursor */
-static Memimage *swimg;		/* cursor image */
-static Memimage *swmask;	/* cursor mask */
-static Memimage *swimg1;
-static Memimage *swmask1;
-
-static Point	swoffset;
-static Rectangle swrect;	/* screen rectangle in swback */
-static Point	swpt;		/* desired cursor location */
-static Point	swvispt;	/* actual cursor location */
-static int	swvers;		/* incremented each time cursor image changes */
-static int	swvisvers;	/* the version on the screen */
-
-/*
- * called with drawlock locked for us, most of the time.
- * kernel prints at inopportune times might mean we don't
- * hold the lock, but memimagedraw is now reentrant so
- * that should be okay: worst case we get cursor droppings.
- */
-static void
-swcursorhide(void)
-{
-	if(swvisible == 0)
-		return;
-	if(swback == nil)
-		return;
-	swvisible = 0;
-	memimagedraw(gscreen, swrect, swback, ZP, memopaque, ZP, S);
-	flushmemscreen(swrect);
-}
-
-static void
-swcursoravoid(Rectangle r)
-{
-	if(swvisible && rectXrect(r, swrect))
-		swcursorhide();
-}
-
-static void
-swcursordraw(void)
-{
-	int dounlock;
-
-	if(swvisible)
-		return;
-	if(swenabled == 0)
-		return;
-	if(swback == nil || swimg1 == nil || swmask1 == nil)
-		return;
-	dounlock = canqlock(&drawlock);
-	swvispt = swpt;
-	swvisvers = swvers;
-	swrect = rectaddpt(Rect(0,0,16,16), swvispt);
-	memimagedraw(swback, swback->r, gscreen, swpt, memopaque, ZP, S);
-	memimagedraw(gscreen, swrect, swimg1, ZP, swmask1, ZP, SoverD);
-	flushmemscreen(swrect);
-	swvisible = 1;
-	if(dounlock)
-		qunlock(&drawlock);
-}
-
-int
-cursoron(int dolock)
-{
-	int retry;
-
-	if (dolock)
-		lock(&cursor);
-	if (canqlock(&drawlock)) {
-		retry = 0;
-		swcursorhide();
-		swcursordraw();
-		qunlock(&drawlock);
-	} else
-		retry = 1;
-	if (dolock)
-		unlock(&cursor);
-	return retry;
-}
-
-void
-cursoroff(int dolock)
-{
-	if (dolock)
-		lock(&cursor);
-	swcursorhide();
-	if (dolock)
-		unlock(&cursor);
-}
-
-static void
-swload(Cursor *curs)
-{
-	uchar *ip, *mp;
-	int i, j, set, clr;
-
-	if(!swimg || !swmask || !swimg1 || !swmask1)
-		return;
-	/*
-	 * Build cursor image and mask.
-	 * Image is just the usual cursor image
-	 * but mask is a transparent alpha mask.
-	 * 
-	 * The 16x16x8 memimages do not have
-	 * padding at the end of their scan lines.
-	 */
-	ip = byteaddr(swimg, ZP);
-	mp = byteaddr(swmask, ZP);
-	for(i=0; i<32; i++){
-		set = curs->set[i];
-		clr = curs->clr[i];
-		for(j=0x80; j; j>>=1){
-			*ip++ = set&j ? 0x00 : 0xFF;
-			*mp++ = (clr|set)&j ? 0xFF : 0x00;
-		}
-	}
-	swoffset = curs->offset;
-	swvers++;
-	memimagedraw(swimg1,  swimg1->r,  swimg,  ZP, memopaque, ZP, S);
-	memimagedraw(swmask1, swmask1->r, swmask, ZP, memopaque, ZP, S);
-}
-
-/* called from devmouse */
-void
-setcursor(Cursor* curs)
-{
-	cursoroff(0);
-	swload(curs);
-	cursoron(0);
-}
-
-static int
-swmove(Point p)
-{
-	swpt = addpt(p, swoffset);
-	return 0;
-}
-
-static void
-swcursorclock(void)
-{
-	int x;
-
-	if(!swenabled)
-		return;
-	swmove(mousexy());
-	if(swvisible && eqpt(swpt, swvispt) && swvers==swvisvers)
-		return;
-
-	x = splhi();
-	if(swenabled)
-	if(!swvisible || !eqpt(swpt, swvispt) || swvers!=swvisvers)
-	if(canqlock(&drawlock)){
-		swcursorhide();
-		swcursordraw();
-		qunlock(&drawlock);
-	}
-	splx(x);
-}
-
-void
-swcursorinit(void)
-{
-	static int init;
-
-	if(!init){
-		init = 1;
-		addclock0link(swcursorclock, 10);
-		swenabled = 1;
-	}
-	if(swback){
-		freememimage(swback);
-		freememimage(swmask);
-		freememimage(swmask1);
-		freememimage(swimg);
-		freememimage(swimg1);
-	}
-
-	swback  = allocmemimage(Rect(0,0,32,32), gscreen->chan);
-	swmask  = allocmemimage(Rect(0,0,16,16), GREY8);
-	swmask1 = allocmemimage(Rect(0,0,16,16), GREY1);
-	swimg   = allocmemimage(Rect(0,0,16,16), GREY8);
-	swimg1  = allocmemimage(Rect(0,0,16,16), GREY1);
-	if(swback==nil || swmask==nil || swmask1==nil || swimg==nil || swimg1 == nil){
-		print("software cursor: allocmemimage fails\n");
-		return;
-	}
-
-	memfillcolor(swmask, DOpaque);
-	memfillcolor(swmask1, DOpaque);
-	memfillcolor(swimg, DBlack);
-	memfillcolor(swimg1, DBlack);
-}
-
-int
-hwdraw(Memdrawparam *par)
-{
-	Memimage *dst, *src, *mask;
-
-	if((dst=par->dst) == nil || dst->data == nil)
-		return 0;
-	if((src=par->src) == nil || src->data == nil)
-		return 0;
-	if((mask=par->mask) == nil || mask->data == nil)
-		return 0;
-
-	if(dst->data->bdata == xgdata.bdata)
-		swcursoravoid(par->r);
-	if(src->data->bdata == xgdata.bdata)
-		swcursoravoid(par->sr);
-	if(mask->data->bdata == xgdata.bdata)
-		swcursoravoid(par->mr);
-
-	return 0;
-}
-
-static int
-screensize(void)
-{
-	char *p;
-	char *f[3];
-	int width, height, depth;
-
-	p = getconf("vgasize");
-	if(p == nil || getfields(p, f, nelem(f), 0, "x") != nelem(f) ||
-	    (width = atoi(f[0])) < 16 ||
-	    (height = atoi(f[1])) <= 0 ||
-	    (depth = atoi(f[2])) <= 0)
-		return -1;
-	xgscreen.r.max = Pt(width, height);
-	xgscreen.depth = depth;
-	return 0;
-}
-
-void
-screeninit(void)
-{
-	uchar *fb;
-	int set;
-	ulong chan;
-
-	set = screensize() == 0;
-	fb = fbinit(set, &xgscreen.r.max.x, &xgscreen.r.max.y, &xgscreen.depth);
-	if(fb == nil){
-		print("can't initialise %dx%dx%d framebuffer \n",
-			xgscreen.r.max.x, xgscreen.r.max.y, xgscreen.depth);
-		return;
-	}
-	xgscreen.clipr = xgscreen.r;
-	switch(xgscreen.depth){
-	default:
-		print("unsupported screen depth %d\n", xgscreen.depth);
-		xgscreen.depth = 16;
-		/* fall through */
-	case 16:
-		chan = RGB16;
-		break;
-	case 24:
-		chan = BGR24;
-		break;
-	case 32:
-		chan = ARGB32;
-		break;
-	}
-	memsetchan(&xgscreen, chan);
-	conf.monitor = 1;
-	xgdata.bdata = fb;
-	xgdata.ref = 1;
-	gscreen = &xgscreen;
-	gscreen->width = wordsperline(gscreen->r, gscreen->depth);
-
-	memimageinit();
-	memdefont = getmemdefont();
-	screenwin();
-	screenputs = myscreenputs;
-}
-
-void
-flushmemscreen(Rectangle)
-{
-}
-
-uchar*
-attachscreen(Rectangle *r, ulong *chan, int* d, int *width, int *softscreen)
-{
-	*r = gscreen->r;
-	*d = gscreen->depth;
-	*chan = gscreen->chan;
-	*width = gscreen->width;
-	*softscreen = 0;
-
-	return gscreen->data->bdata;
-}
-
-void
-getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb)
-{
-	USED(p, pr, pg, pb);
-}
-
-int
-setcolor(ulong p, ulong r, ulong g, ulong b)
-{
-	USED(p, r, g, b);
-	return 0;
-}
-
-void
-blankscreen(int blank)
-{
-	fbblank(blank);
-}
-
-static void
-myscreenputs(char *s, int n)
-{
-	int i;
-	Rune r;
-	char buf[4];
-
-	if(!islo()) {
-		/* don't deadlock trying to print in interrupt */
-		if(!canlock(&screenlock))
-			return;	
-	}
-	else
-		lock(&screenlock);
-
-	while(n > 0){
-		i = chartorune(&r, s);
-		if(i == 0){
-			s++;
-			--n;
-			continue;
-		}
-		memmove(buf, s, i);
-		buf[i] = 0;
-		n -= i;
-		s += i;
-		screenputc(buf);
-	}
-	unlock(&screenlock);
-}
-
-static void
-screenwin(void)
-{
-	char *greet;
-	Memimage *orange;
-	Point p, q;
-	Rectangle r;
-
-	back = memwhite;
-	conscol = memblack;
-
-	orange = allocmemimage(Rect(0, 0, 1, 1), RGB16);
-	orange->flags |= Frepl;
-	orange->clipr = gscreen->r;
-	orange->data->bdata[0] = 0x40;		/* magic: colour? */
-	orange->data->bdata[1] = 0xfd;		/* magic: colour? */
-
-	w = memdefont->info[' '].width;
-	h = memdefont->height;
-
-	r = insetrect(gscreen->r, 4);
-
-	memimagedraw(gscreen, r, memblack, ZP, memopaque, ZP, S);
-	window = insetrect(r, 4);
-	memimagedraw(gscreen, window, memwhite, ZP, memopaque, ZP, S);
-
-	memimagedraw(gscreen, Rect(window.min.x, window.min.y,
-		window.max.x, window.min.y + h + 5 + 6), orange, ZP, nil, ZP, S);
-	freememimage(orange);
-	window = insetrect(window, 5);
-
-	greet = " Plan 9 Console ";
-	p = addpt(window.min, Pt(10, 0));
-	q = memsubfontwidth(memdefont, greet);
-	memimagestring(gscreen, p, conscol, ZP, memdefont, greet);
-	flushmemscreen(r);
-	window.min.y += h + 6;
-	curpos = window.min;
-	window.max.y = window.min.y + ((window.max.y - window.min.y) / h) * h;
-}
-
-static void
-scroll(void)
-{
-	int o;
-	Point p;
-	Rectangle r;
-
-	o = Scroll*h;
-	r = Rpt(window.min, Pt(window.max.x, window.max.y-o));
-	p = Pt(window.min.x, window.min.y+o);
-	memimagedraw(gscreen, r, gscreen, p, nil, p, S);
-	flushmemscreen(r);
-	r = Rpt(Pt(window.min.x, window.max.y-o), window.max);
-	memimagedraw(gscreen, r, back, ZP, nil, ZP, S);
-	flushmemscreen(r);
-
-	curpos.y -= o;
-}
-
-static void
-screenputc(char *buf)
-{
-	int w;
-	uint pos;
-	Point p;
-	Rectangle r;
-	static int *xp;
-	static int xbuf[256];
-
-	if (xp < xbuf || xp >= &xbuf[sizeof(xbuf)])
-		xp = xbuf;
-
-	switch (buf[0]) {
-	case '\n':
-		if (curpos.y + h >= window.max.y)
-			scroll();
-		curpos.y += h;
-		screenputc("\r");
-		break;
-	case '\r':
-		xp = xbuf;
-		curpos.x = window.min.x;
-		break;
-	case '\t':
-		p = memsubfontwidth(memdefont, " ");
-		w = p.x;
-		if (curpos.x >= window.max.x - Tabstop * w)
-			screenputc("\n");
-
-		pos = (curpos.x - window.min.x) / w;
-		pos = Tabstop - pos % Tabstop;
-		*xp++ = curpos.x;
-		r = Rect(curpos.x, curpos.y, curpos.x + pos * w, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
-		flushmemscreen(r);
-		curpos.x += pos * w;
-		break;
-	case '\b':
-		if (xp <= xbuf)
-			break;
-		xp--;
-		r = Rect(*xp, curpos.y, curpos.x, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
-		flushmemscreen(r);
-		curpos.x = *xp;
-		break;
-	case '\0':
-		break;
-	default:
-		p = memsubfontwidth(memdefont, buf);
-		w = p.x;
-
-		if (curpos.x >= window.max.x - w)
-			screenputc("\n");
-
-		*xp++ = curpos.x;
-		r = Rect(curpos.x, curpos.y, curpos.x + w, curpos.y + h);
-		memimagedraw(gscreen, r, back, back->r.min, nil, back->r.min, S);
-		memimagestring(gscreen, curpos, conscol, ZP, memdefont, buf);
-		flushmemscreen(r);
-		curpos.x += w;
-		break;
-	}
-}

+ 0 - 44
sys/src/9/bcm/screen.h

@@ -1,44 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-typedef struct Cursor Cursor;
-typedef struct Cursorinfo Cursorinfo;
-struct Cursorinfo {
-	Cursor;
-	Lock;
-};
-
-/* devmouse.c */
-extern void mousetrack(int, int, int, int);
-extern Point mousexy(void);
-
-extern void mouseaccelerate(int);
-extern int m3mouseputc(Queue*, int);
-extern int m5mouseputc(Queue*, int);
-extern int mouseputc(Queue*, int);
-
-extern Cursorinfo cursor;
-extern Cursor arrow;
-
-/* mouse.c */
-extern void mousectl(Cmdbuf*);
-extern void mouseresize(void);
-
-/* screen.c */
-extern void	blankscreen(int);
-extern void	flushmemscreen(Rectangle);
-extern uchar*	attachscreen(Rectangle*, ulong*, int*, int*, int*);
-extern int	cursoron(int);
-extern void	cursoroff(int);
-extern void	setcursor(Cursor*);
-
-/* devdraw.c */
-extern QLock	drawlock;
-
-#define ishwimage(i)	1		/* for ../port/devdraw.c */

+ 0 - 10
sys/src/9/bcm/softfpu.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../teg2/softfpu.c"

+ 0 - 10
sys/src/9/bcm/syscall.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../kw/syscall.c"

+ 0 - 586
sys/src/9/bcm/trap.c

@@ -1,586 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * traps, exceptions, interrupts, system calls.
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-#include "ureg.h"
-#include "../port/error.h"
-
-#include "arm.h"
-
-#define INTREGS		(VIRTIO+0xB200)
-
-typedef struct Intregs Intregs;
-typedef struct Vctl Vctl;
-
-enum {
-	Debug = 0,
-
-	Nvec = 8,		/* # of vectors at start of lexception.s */
-	Fiqenable = 1<<7,
-};
-
-/*
- *   Layout at virtual address KZERO (double mapped at HVECTORS).
- */
-typedef struct Vpage0 {
-	void	(*vectors[Nvec])(void);
-	u32int	vtable[Nvec];
-} Vpage0;
-
-/*
- * interrupt control registers
- */
-struct Intregs {
-	u32int	ARMpending;
-	u32int	GPUpending[2];
-	u32int	FIQctl;
-	u32int	GPUenable[2];
-	u32int	ARMenable;
-	u32int	GPUdisable[2];
-	u32int	ARMdisable;
-};
-
-struct Vctl {
-	Vctl	*next;
-	int	irq;
-	u32int	*reg;
-	u32int	mask;
-	void	(*f)(Ureg*, void*);
-	void	*a;
-};
-
-static Vctl *vctl, *vfiq;
-
-static char *trapnames[PsrMask+1] = {
-	[ PsrMusr ] "user mode",
-	[ PsrMfiq ] "fiq interrupt",
-	[ PsrMirq ] "irq interrupt",
-	[ PsrMsvc ] "svc/swi exception",
-	[ PsrMabt ] "prefetch abort/data abort",
-	[ PsrMabt+1 ] "data abort",
-	[ PsrMund ] "undefined instruction",
-	[ PsrMsys ] "sys trap",
-};
-
-extern int notify(Ureg*);
-
-/*
- *  set up for exceptions
- */
-void
-trapinit(void)
-{
-	Vpage0 *vpage0;
-
-	/* disable everything */
-	intrsoff();
-
-	/* set up the exception vectors */
-	vpage0 = (Vpage0*)HVECTORS;
-	memmove(vpage0->vectors, vectors, sizeof(vpage0->vectors));
-	memmove(vpage0->vtable, vtable, sizeof(vpage0->vtable));
-	cacheuwbinv();
-
-	/* set up the stacks for the interrupt modes */
-	setr13(PsrMfiq, (u32int*)(FIQSTKTOP));
-	setr13(PsrMirq, m->sirq);
-	setr13(PsrMabt, m->sabt);
-	setr13(PsrMund, m->sund);
-	setr13(PsrMsys, m->ssys);
-
-	coherence();
-}
-
-void
-intrsoff(void)
-{
-	Intregs *ip;
-	int disable;
-
-	ip = (Intregs*)INTREGS;
-	disable = ~0;
-	ip->GPUdisable[0] = disable;
-	ip->GPUdisable[1] = disable;
-	ip->ARMdisable = disable;
-	ip->FIQctl = 0;
-}
-
-/*
- *  called by trap to handle irq interrupts.
- *  returns true iff a clock interrupt, thus maybe reschedule.
- */
-static int
-irq(Ureg* ureg)
-{
-	Vctl *v;
-	int clockintr;
-
-	clockintr = 0;
-	for(v = vctl; v; v = v->next)
-		if(*v->reg & v->mask){
-			coherence();
-			v->f(ureg, v->a);
-			coherence();
-			if(v->irq == IRQclock)
-				clockintr = 1;
-		}
-	return clockintr;
-}
-
-/*
- * called direct from lexception.s to handle fiq interrupt.
- */
-void
-fiq(Ureg *ureg)
-{
-	Vctl *v;
-
-	v = vfiq;
-	if(v == nil)
-		panic("unexpected item in bagging area");
-	m->intr++;
-	ureg->pc -= 4;
-	coherence();
-	v->f(ureg, v->a);
-	coherence();
-}
-
-void
-irqenable(int irq, void (*f)(Ureg*, void*), void* a)
-{
-	Vctl *v;
-	Intregs *ip;
-	u32int *enable;
-
-	ip = (Intregs*)INTREGS;
-	v = (Vctl*)malloc(sizeof(Vctl));
-	if(v == nil)
-		panic("irqenable: no mem");
-	v->irq = irq;
-	if(irq >= IRQbasic){
-		enable = &ip->ARMenable;
-		v->reg = &ip->ARMpending;
-		v->mask = 1 << (irq - IRQbasic);
-	}else{
-		enable = &ip->GPUenable[irq/32];
-		v->reg = &ip->GPUpending[irq/32];
-		v->mask = 1 << (irq % 32);
-	}
-	v->f = f;
-	v->a = a;
-	if(irq == IRQfiq){
-		assert((ip->FIQctl & Fiqenable) == 0);
-		assert((*enable & v->mask) == 0);
-		vfiq = v;
-		ip->FIQctl = Fiqenable | irq;
-	}else{
-		v->next = vctl;
-		vctl = v;
-		*enable = v->mask;
-	}
-}
-
-static char *
-trapname(int psr)
-{
-	char *s;
-
-	s = trapnames[psr & PsrMask];
-	if(s == nil)
-		s = "unknown trap number in psr";
-	return s;
-}
-
-/* this is quite helpful during mmu and cache debugging */
-static void
-ckfaultstuck(uintptr va)
-{
-	static int cnt, lastpid;
-	static uintptr lastva;
-
-	if (va == lastva && up->pid == lastpid) {
-		++cnt;
-		if (cnt >= 2)
-			/* fault() isn't fixing the underlying cause */
-			panic("fault: %d consecutive faults for va %#p",
-				cnt+1, va);
-	} else {
-		cnt = 0;
-		lastva = va;
-		lastpid = up->pid;
-	}
-}
-
-/*
- *  called by trap to handle access faults
- */
-static void
-faultarm(Ureg *ureg, uintptr va, int user, int read)
-{
-	int n, insyscall;
-	char buf[ERRMAX];
-
-	if(up == nil) {
-		dumpregs(ureg);
-		panic("fault: nil up in faultarm, accessing %#p", va);
-	}
-	insyscall = up->insyscall;
-	up->insyscall = 1;
-	if (Debug)
-		ckfaultstuck(va);
-
-	n = fault(va, read);
-	if(n < 0){
-		if(!user){
-			dumpregs(ureg);
-			panic("fault: kernel accessing %#p", va);
-		}
-		/* don't dump registers; programs suicide all the time */
-		snprint(buf, sizeof buf, "sys: trap: fault %s va=%#p",
-			read? "read": "write", va);
-		postnote(up, 1, buf, NDebug);
-	}
-	up->insyscall = insyscall;
-}
-
-/*
- *  returns 1 if the instruction writes memory, 0 otherwise
- */
-int
-writetomem(ulong inst)
-{
-	/* swap always write memory */
-	if((inst & 0x0FC00000) == 0x01000000)
-		return 1;
-
-	/* loads and stores are distinguished by bit 20 */
-	if(inst & (1<<20))
-		return 0;
-
-	return 1;
-}
-
-/*
- *  here on all exceptions other than syscall (SWI) and fiq
- */
-void
-trap(Ureg *ureg)
-{
-	int clockintr, user, x, rv, rem;
-	ulong inst, fsr;
-	uintptr va;
-	char buf[ERRMAX];
-
-	assert(!islo());
-	if(up != nil)
-		rem = ((char*)ureg)-up->kstack;
-	else
-		rem = ((char*)ureg)-((char*)m+sizeof(Mach));
-	if(rem < 256) {
-		iprint("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux\n",
-			rem, up, ureg, ureg->pc);
-		delay(1000);
-		dumpstack();
-		panic("trap: %d stack bytes left, up %#p ureg %#p at pc %#lux",
-			rem, up, ureg, ureg->pc);
-	}
-
-	user = (ureg->psr & PsrMask) == PsrMusr;
-	if(user){
-		up->dbgreg = ureg;
-		cycles(&up->kentry);
-	}
-
-	/*
-	 * All interrupts/exceptions should be resumed at ureg->pc-4,
-	 * except for Data Abort which resumes at ureg->pc-8.
-	 */
-	if(ureg->type == (PsrMabt+1))
-		ureg->pc -= 8;
-	else
-		ureg->pc -= 4;
-
-	clockintr = 0;		/* if set, may call sched() before return */
-	switch(ureg->type){
-	default:
-		panic("unknown trap; type %#lux, psr mode %#lux", ureg->type,
-			ureg->psr & PsrMask);
-		break;
-	case PsrMirq:
-		clockintr = irq(ureg);
-		m->intr++;
-		break;
-	case PsrMabt:			/* prefetch fault */
-		x = ifsrget();
-		fsr = (x>>7) & 0x8 | x & 0x7;
-		switch(fsr){
-		case 0x02:		/* instruction debug event (BKPT) */
-			if(user){
-				snprint(buf, sizeof buf, "sys: breakpoint");
-				postnote(up, 1, buf, NDebug);
-			}else{
-				iprint("kernel bkpt: pc %#lux inst %#ux\n",
-					ureg->pc, *(u32int*)ureg->pc);
-				panic("kernel bkpt");
-			}
-			break;
-		default:
-			faultarm(ureg, ureg->pc, user, 1);
-			break;
-		}
-		break;
-	case PsrMabt+1:			/* data fault */
-		va = farget();
-		inst = *(ulong*)(ureg->pc);
-		/* bits 12 and 10 have to be concatenated with status */
-		x = fsrget();
-		fsr = (x>>7) & 0x20 | (x>>6) & 0x10 | x & 0xf;
-		switch(fsr){
-		default:
-		case 0xa:		/* ? was under external abort */
-			panic("unknown data fault, 6b fsr %#lux", fsr);
-			break;
-		case 0x0:
-			panic("vector exception at %#lux", ureg->pc);
-			break;
-		case 0x1:		/* alignment fault */
-		case 0x3:		/* access flag fault (section) */
-			if(user){
-				snprint(buf, sizeof buf,
-					"sys: alignment: pc %#lux va %#p\n",
-					ureg->pc, va);
-				postnote(up, 1, buf, NDebug);
-			} else
-				panic("kernel alignment: pc %#lux va %#p", ureg->pc, va);
-			break;
-		case 0x2:
-			panic("terminal exception at %#lux", ureg->pc);
-			break;
-		case 0x4:		/* icache maint fault */
-		case 0x6:		/* access flag fault (page) */
-		case 0x8:		/* precise external abort, non-xlat'n */
-		case 0x28:
-		case 0xc:		/* l1 translation, precise ext. abort */
-		case 0x2c:
-		case 0xe:		/* l2 translation, precise ext. abort */
-		case 0x2e:
-		case 0x16:		/* imprecise ext. abort, non-xlt'n */
-		case 0x36:
-			panic("external abort %#lux pc %#lux addr %#p",
-				fsr, ureg->pc, va);
-			break;
-		case 0x1c:		/* l1 translation, precise parity err */
-		case 0x1e:		/* l2 translation, precise parity err */
-		case 0x18:		/* imprecise parity or ecc err */
-			panic("translation parity error %#lux pc %#lux addr %#p",
-				fsr, ureg->pc, va);
-			break;
-		case 0x5:		/* translation fault, no section entry */
-		case 0x7:		/* translation fault, no page entry */
-			faultarm(ureg, va, user, !writetomem(inst));
-			break;
-		case 0x9:
-		case 0xb:
-			/* domain fault, accessing something we shouldn't */
-			if(user){
-				snprint(buf, sizeof buf,
-					"sys: access violation: pc %#lux va %#p\n",
-					ureg->pc, va);
-				postnote(up, 1, buf, NDebug);
-			} else
-				panic("kernel access violation: pc %#lux va %#p",
-					ureg->pc, va);
-			break;
-		case 0xd:
-		case 0xf:
-			/* permission error, copy on write or real permission error */
-			faultarm(ureg, va, user, !writetomem(inst));
-			break;
-		}
-		break;
-	case PsrMund:			/* undefined instruction */
-		if(user){
-			if(seg(up, ureg->pc, 0) != nil &&
-			   *(u32int*)ureg->pc == 0xD1200070)
-				postnote(up, 1, "sys: breakpoint", NDebug);
-			else{
-				/* look for floating point instructions to interpret */
-				rv = fpuemu(ureg);
-				if(rv == 0){
-					snprint(buf, sizeof buf,
-						"undefined instruction: pc %#lux\n",
-						ureg->pc);
-					postnote(up, 1, buf, NDebug);
-				}
-			}
-		}else{
-			if (ureg->pc & 3) {
-				iprint("rounding fault pc %#lux down to word\n",
-					ureg->pc);
-				ureg->pc &= ~3;
-			}
-			iprint("undefined instruction: pc %#lux inst %#ux\n",
-				ureg->pc, *(u32int*)ureg->pc);
-			panic("undefined instruction");
-		}
-		break;
-	}
-	splhi();
-
-	/* delaysched set because we held a lock or because our quantum ended */
-	if(up && up->delaysched && clockintr){
-		sched();		/* can cause more traps */
-		splhi();
-	}
-
-	if(user){
-		if(up->procctl || up->nnote)
-			notify(ureg);
-		kexit(ureg);
-	}
-}
-
-int
-isvalidaddr(void *v)
-{
-	return (uintptr)v >= KZERO;
-}
-
-static void
-dumplongs(char *msg, ulong *v, int n)
-{
-	int i, l;
-
-	l = 0;
-	iprint("%s at %.8p: ", msg, v);
-	for(i=0; i<n; i++){
-		if(l >= 4){
-			iprint("\n    %.8p: ", v);
-			l = 0;
-		}
-		if(isvalidaddr(v)){
-			iprint(" %.8lux", *v++);
-			l++;
-		}else{
-			iprint(" invalid");
-			break;
-		}
-	}
-	iprint("\n");
-}
-
-static void
-dumpstackwithureg(Ureg *ureg)
-{
-	uintptr l, i, v, estack;
-	u32int *p;
-	char *s;
-
-	if((s = getconf("*nodumpstack")) != nil && strcmp(s, "0") != 0){
-		iprint("dumpstack disabled\n");
-		return;
-	}
-	iprint("ktrace /kernel/path %#.8lux %#.8lux %#.8lux # pc, sp, link\n",
-		ureg->pc, ureg->sp, ureg->r14);
-	delay(2000);
-	i = 0;
-	if(up != nil && (uintptr)&l <= (uintptr)up->kstack+KSTACK)
-		estack = (uintptr)up->kstack+KSTACK;
-	else if((uintptr)&l >= (uintptr)m->stack
-	     && (uintptr)&l <= (uintptr)m+MACHSIZE)
-		estack = (uintptr)m+MACHSIZE;
-	else{
-		if(up != nil)
-			iprint("&up->kstack %#p &l %#p\n", up->kstack, &l);
-		else
-			iprint("&m %#p &l %#p\n", m, &l);
-		return;
-	}
-	for(l = (uintptr)&l; l < estack; l += sizeof(uintptr)){
-		v = *(uintptr*)l;
-		if(KTZERO < v && v < (uintptr)etext && !(v & 3)){
-			v -= sizeof(u32int);		/* back up an instr */
-			p = (u32int*)v;
-			if((*p & 0x0f000000) == 0x0b000000){	/* BL instr? */
-				iprint("%#8.8lux=%#8.8lux ", l, v);
-				i++;
-			}
-		}
-		if(i == 4){
-			i = 0;
-			iprint("\n");
-		}
-	}
-	if(i)
-		iprint("\n");
-}
-
-/*
- * Fill in enough of Ureg to get a stack trace, and call a function.
- * Used by debugging interface rdb.
- */
-void
-callwithureg(void (*fn)(Ureg*))
-{
-	Ureg ureg;
-
-	ureg.pc = getcallerpc(&fn);
-	ureg.sp = PTR2UINT(&fn);
-	fn(&ureg);
-}
-
-void
-dumpstack(void)
-{
-	callwithureg(dumpstackwithureg);
-}
-
-void
-dumpregs(Ureg* ureg)
-{
-	int s;
-
-	if (ureg == nil) {
-		iprint("trap: no user process\n");
-		return;
-	}
-	s = splhi();
-	iprint("trap: %s", trapname(ureg->type));
-	if(ureg != nil && (ureg->psr & PsrMask) != PsrMsvc)
-		iprint(" in %s", trapname(ureg->psr));
-	iprint("\n");
-	iprint("psr %8.8lux type %2.2lux pc %8.8lux link %8.8lux\n",
-		ureg->psr, ureg->type, ureg->pc, ureg->link);
-	iprint("R14 %8.8lux R13 %8.8lux R12 %8.8lux R11 %8.8lux R10 %8.8lux\n",
-		ureg->r14, ureg->r13, ureg->r12, ureg->r11, ureg->r10);
-	iprint("R9  %8.8lux R8  %8.8lux R7  %8.8lux R6  %8.8lux R5  %8.8lux\n",
-		ureg->r9, ureg->r8, ureg->r7, ureg->r6, ureg->r5);
-	iprint("R4  %8.8lux R3  %8.8lux R2  %8.8lux R1  %8.8lux R0  %8.8lux\n",
-		ureg->r4, ureg->r3, ureg->r2, ureg->r1, ureg->r0);
-	iprint("stack is at %#p\n", ureg);
-	iprint("pc %#lux link %#lux\n", ureg->pc, ureg->link);
-
-	if(up)
-		iprint("user stack: %#p-%#p\n", up->kstack, up->kstack+KSTACK-4);
-	else
-		iprint("kernel stack: %8.8lux-%8.8lux\n",
-			(ulong)(m+1), (ulong)m+BY2PG-4);
-	dumplongs("stack", (ulong *)(ureg + 1), 16);
-	delay(2000);
-	dumpstack();
-	splx(s);
-}

+ 0 - 433
sys/src/9/bcm/uartmini.c

@@ -1,433 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * bcm2835 mini uart (UART1)
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "../port/error.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#define GPIOREGS	(VIRTIO+0x200000)
-#define AUXREGS		(VIRTIO+0x215000)
-#define	OkLed		16
-#define	TxPin		14
-#define	RxPin		15
-
-/* GPIO regs */
-enum {
-	Fsel0	= 0x00>>2,
-		FuncMask= 0x7,
-		Input	= 0x0,
-		Output	= 0x1,
-		Alt0	= 0x4,
-		Alt1	= 0x5,
-		Alt2	= 0x6,
-		Alt3	= 0x7,
-		Alt4	= 0x3,
-		Alt5	= 0x2,
-	Set0	= 0x1c>>2,
-	Clr0	= 0x28>>2,
-	Lev0	= 0x34>>2,
-	PUD	= 0x94>>2,
-		Off	= 0x0,
-		Pulldown= 0x1,
-		Pullup	= 0x2,
-	PUDclk0	= 0x98>>2,
-	PUDclk1	= 0x9c>>2,
-};
-
-/* AUX regs */
-enum {
-	Irq	= 0x00>>2,
-		UartIrq	= 1<<0,
-	Enables	= 0x04>>2,
-		UartEn	= 1<<0,
-	MuIo	= 0x40>>2,
-	MuIer	= 0x44>>2,
-		RxIen	= 1<<0,
-		TxIen	= 1<<1,
-	MuIir	= 0x48>>2,
-	MuLcr	= 0x4c>>2,
-		Bitsmask= 3<<0,
-		Bits7	= 2<<0,
-		Bits8	= 3<<0,
-	MuMcr	= 0x50>>2,
-		RtsN	= 1<<1,
-	MuLsr	= 0x54>>2,
-		TxDone	= 1<<6,
-		TxRdy	= 1<<5,
-		RxRdy	= 1<<0,
-	MuCntl	= 0x60>>2,
-		CtsFlow	= 1<<3,
-		TxEn	= 1<<1,
-		RxEn	= 1<<0,
-	MuBaud	= 0x68>>2,
-};
-
-extern PhysUart miniphysuart;
-
-static Uart miniuart = {
-	.regs	= (u32int*)AUXREGS,
-	.name	= "uart0",
-	.freq	= 250000000,
-	.phys	= &miniphysuart,
-};
-
-void
-gpiosel(uint pin, int func)
-{	
-	u32int *gp, *fsel;
-	int off;
-
-	gp = (u32int*)GPIOREGS;
-	fsel = &gp[Fsel0 + pin/10];
-	off = (pin % 10) * 3;
-	*fsel = (*fsel & ~(FuncMask<<off)) | func<<off;
-}
-
-void
-gpiopulloff(uint pin)
-{
-	u32int *gp, *reg;
-	u32int mask;
-
-	gp = (u32int*)GPIOREGS;
-	reg = &gp[PUDclk0 + pin/32];
-	mask = 1 << (pin % 32);
-	gp[PUD] = Off;
-	microdelay(1);
-	*reg = mask;
-	microdelay(1);
-	*reg = 0;
-}
-
-void
-gpioout(uint pin, int set)
-{
-	u32int *gp;
-	int v;
-
-	gp = (u32int*)GPIOREGS;
-	v = set? Set0 : Clr0;
-	gp[v + pin/32] = 1 << (pin % 32);
-}
-
-int
-gpioin(uint pin)
-{
-	u32int *gp;
-
-	gp = (u32int*)GPIOREGS;
-	return (gp[Lev0 + pin/32] & (1 << (pin % 32))) != 0;
-}
-
-static void
-interrupt(Ureg*, void *arg)
-{
-	Uart *uart;
-	u32int *ap;
-
-	uart = arg;
-	ap = (u32int*)uart->regs;
-
-	coherence();
-	if(0 && (ap[Irq] & UartIrq) == 0)
-		return;
-	if(ap[MuLsr] & TxRdy)
-		uartkick(uart);
-	if(ap[MuLsr] & RxRdy){
-		if(uart->console){
-			if(uart->opens == 1)
-				uart->putc = kbdcr2nl;
-			else
-				uart->putc = nil;
-		}
-		do{
-			uartrecv(uart, ap[MuIo] & 0xFF);
-		}while(ap[MuLsr] & RxRdy);
-	}
-	coherence();
-}
-
-static Uart*
-pnp(void)
-{
-	Uart *uart;
-
-	uart = &miniuart;
-	if(uart->console == 0)
-		kbdq = qopen(8*1024, 0, nil, nil);
-	return uart;
-}
-
-static void
-enable(Uart *uart, int ie)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	delay(10);
-	gpiosel(TxPin, Alt5);
-	gpiosel(RxPin, Alt5);
-	gpiopulloff(TxPin);
-	gpiopulloff(RxPin);
-	ap[Enables] |= UartEn;
-	ap[MuIir] = 6;
-	ap[MuLcr] = Bits8;
-	ap[MuCntl] = TxEn|RxEn;
-	ap[MuBaud] = 250000000/(115200*8) - 1;
-	if(ie){
-		intrenable(IRQaux, interrupt, uart, 0, "uart");
-		ap[MuIer] = RxIen|TxIen;
-	}else
-		ap[MuIer] = 0;
-}
-
-static void
-disable(Uart *uart)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	ap[MuCntl] = 0;
-	ap[MuIer] = 0;
-}
-
-static void
-kick(Uart *uart)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	if(uart->blocked)
-		return;
-	coherence();
-	while(ap[MuLsr] & TxRdy){
-		if(uart->op >= uart->oe && uartstageoutput(uart) == 0)
-			break;
-		ap[MuIo] = *(uart->op++);
-	}
-	if(ap[MuLsr] & TxDone)
-		ap[MuIer] &= ~TxIen;
-	else
-		ap[MuIer] |= TxIen;
-	coherence();
-}
-
-/* TODO */
-static void
-dobreak(Uart *uart, int ms)
-{
-	USED(uart, ms);
-}
-
-static int
-baud(Uart *uart, int n)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	if(uart->freq == 0 || n <= 0)
-		return -1;
-	ap[MuBaud] = (uart->freq + 4*n - 1) / (8 * n) - 1;
-	uart->baud = n;
-	return 0;
-}
-
-static int
-bits(Uart *uart, int n)
-{
-	u32int *ap;
-	int set;
-
-	ap = (u32int*)uart->regs;
-	switch(n){
-	case 7:
-		set = Bits7;
-		break;
-	case 8:
-		set = Bits8;
-		break;
-	default:
-		return -1;
-	}
-	ap[MuLcr] = (ap[MuLcr] & ~Bitsmask) | set;
-	uart->bits = n;
-	return 0;
-}
-
-static int
-stop(Uart *uart, int n)
-{
-	if(n != 1)
-		return -1;
-	uart->stop = n;
-	return 0;
-}
-
-static int
-parity(Uart *uart, int n)
-{
-	if(n != 'n')
-		return -1;
-	uart->parity = n;
-	return 0;
-}
-
-/*
- * cts/rts flow control
- *   need to bring signals to gpio pins before enabling this
- */
-
-static void
-modemctl(Uart *uart, int on)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	if(on)
-		ap[MuCntl] |= CtsFlow;
-	else
-		ap[MuCntl] &= ~CtsFlow;
-	uart->modem = on;
-}
-
-static void
-rts(Uart *uart, int on)
-{
-	u32int *ap;
-
-	ap = (u32int*)uart->regs;
-	if(on)
-		ap[MuMcr] &= ~RtsN;
-	else
-		ap[MuMcr] |= RtsN;
-}
-
-static long
-status(Uart *uart, void *buf, long n, long offset)
-{
-	char *p;
-
-	p = malloc(READSTR);
-	if(p == nil)
-		error(Enomem);
-	snprint(p, READSTR,
-		"b%d\n"
-		"dev(%d) type(%d) framing(%d) overruns(%d) "
-		"berr(%d) serr(%d)\n",
-
-		uart->baud,
-		uart->dev,
-		uart->type,
-		uart->ferr,
-		uart->oerr,
-		uart->berr,
-		uart->serr
-	);
-	n = readstr(offset, buf, n, p);
-	free(p);
-
-	return n;
-}
-
-static void
-donothing(Uart*, int)
-{
-}
-
-void
-putc(Uart*, int c)
-{
-	u32int *ap;
-
-	ap = (u32int*)AUXREGS;
-	while((ap[MuLsr] & TxRdy) == 0)
-		;
-	ap[MuIo] = c;
-	while((ap[MuLsr] & TxRdy) == 0)
-		;
-}
-
-int
-getc(Uart*)
-{
-	u32int *ap;
-
-	ap = (u32int*)AUXREGS;
-	while((ap[MuLsr] & RxRdy) == 0)
-		;
-	return ap[MuIo] & 0xFF;
-}
-
-void
-uartconsinit(void)
-{
-	Uart *uart;
-	int n;
-	char *p, *cmd;
-
-	if((p = getconf("console")) == nil)
-		return;
-	n = strtoul(p, &cmd, 0);
-	if(p == cmd)
-		return;
-	switch(n){
-	default:
-		return;
-	case 0:
-		uart = &miniuart;
-		break;
-	}
-
-	if(!uart->enabled)
-		(*uart->phys->enable)(uart, 0);
-	uartctl(uart, "b9600 l8 pn s1");
-	if(*cmd != '\0')
-		uartctl(uart, cmd);
-
-	consuart = uart;
-	uart->console = 1;
-}
-
-PhysUart miniphysuart = {
-	.name		= "miniuart",
-	.pnp		= pnp,
-	.enable		= enable,
-	.disable	= disable,
-	.kick		= kick,
-	.dobreak	= dobreak,
-	.baud		= baud,
-	.bits		= bits,
-	.stop		= stop,
-	.parity		= parity,
-	.modemctl	= donothing,
-	.rts		= rts,
-	.dtr		= donothing,
-	.status		= status,
-	.fifo		= donothing,
-	.getc		= getc,
-	.putc		= putc,
-};
-
-void
-okay(int on)
-{
-	static int first;
-
-	if(!first++)
-		gpiosel(OkLed, Output);
-	gpioout(OkLed, !on);
-}

+ 0 - 991
sys/src/9/bcm/usbdwc.c

@@ -1,991 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * USB host driver for BCM2835
- *	Synopsis DesignWare Core USB 2.0 OTG controller
- *
- * Copyright © 2012 Richard Miller <r.miller@acm.org>
- *
- * This is work in progress:
- * - no isochronous pipes
- * - no bandwidth budgeting
- * - frame scheduling is crude
- * - error handling is overly optimistic
- * It should be just about adequate for a Plan 9 terminal with
- * keyboard, mouse, ethernet adapter, and an external flash drive.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"io.h"
-#include	"../port/error.h"
-#include	"../port/usb.h"
-
-#include "dwcotg.h"
-
-enum
-{
-	USBREGS		= VIRTIO + 0x980000,
-	Enabledelay	= 50,
-	Resetdelay	= 10,
-	ResetdelayHS	= 50,
-
-	Read		= 0,
-	Write		= 1,
-};
-
-typedef struct Ctlr Ctlr;
-typedef struct Epio Epio;
-
-struct Ctlr {
-	Dwcregs	*regs;		/* controller registers */
-	int	nchan;		/* number of host channels */
-	ulong	chanbusy;	/* bitmap of in-use channels */
-	QLock	chanlock;	/* serialise access to chanbusy */
-	QLock	split;		/* serialise split transactions */
-	int	splitretry;	/* count retries of Nyet */
-	int	sofchan;	/* bitmap of channels waiting for sof */
-	int	wakechan;	/* bitmap of channels to wakeup after fiq */
-	int	debugchan;	/* bitmap of channels for interrupt debug */
-	Rendez	*chanintr;	/* sleep till interrupt on channel N */
-};
-
-struct Epio {
-	QLock;
-	Block	*cb;
-	ulong	lastpoll;
-};
-
-static Ctlr dwc;
-static int debug;
-
-static char Ebadlen[] = "bad usb request length";
-
-static void clog(Ep *ep, Hostchan *hc);
-static void logdump(Ep *ep);
-
-static Hostchan*
-chanalloc(Ep *ep)
-{
-	Ctlr *ctlr;
-	int bitmap, i;
-
-	ctlr = ep->hp->aux;
-	qlock(&ctlr->chanlock);
-	bitmap = ctlr->chanbusy;
-	for(i = 0; i < ctlr->nchan; i++)
-		if((bitmap & (1<<i)) == 0){
-			ctlr->chanbusy = bitmap | 1<<i;
-			qunlock(&ctlr->chanlock);
-			return &ctlr->regs->hchan[i];
-		}
-	qunlock(&ctlr->chanlock);
-	panic("miller is a lazy git");
-	return nil;
-}
-
-static void
-chanrelease(Ep *ep, Hostchan *chan)
-{
-	Ctlr *ctlr;
-	int i;
-
-	ctlr = ep->hp->aux;
-	i = chan - ctlr->regs->hchan;
-	qlock(&ctlr->chanlock);
-	ctlr->chanbusy &= ~(1<<i);
-	qunlock(&ctlr->chanlock);
-}
-
-static void
-chansetup(Hostchan *hc, Ep *ep)
-{
-	int hcc;
-	Ctlr *ctlr = ep->hp->aux;
-
-	if(ep->debug)
-		ctlr->debugchan |= 1 << (hc - ctlr->regs->hchan);
-	else
-		ctlr->debugchan &= ~(1 << (hc - ctlr->regs->hchan));
-	switch(ep->dev->state){
-	case Dconfig:
-	case Dreset:
-		hcc = 0;
-		break;
-	default:
-		hcc = ep->dev->nb<<ODevaddr;
-		break;
-	}
-	hcc |= ep->maxpkt | 1<<OMulticnt | ep->nb<<OEpnum;
-	switch(ep->ttype){
-	case Tctl:
-		hcc |= Epctl;
-		break;
-	case Tiso:
-		hcc |= Episo;
-		break;
-	case Tbulk:
-		hcc |= Epbulk;
-		break;
-	case Tintr:
-		hcc |= Epintr;
-		break;
-	}
-	switch(ep->dev->speed){
-	case Lowspeed:
-		hcc |= Lspddev;
-		/* fall through */
-	case Fullspeed:
-		if(ep->dev->hub > 1){
-			hc->hcsplt = Spltena | POS_ALL | ep->dev->hub<<OHubaddr |
-				ep->dev->port;
-			break;
-		}
-		/* fall through */
-	default:
-		hc->hcsplt = 0;
-		break;
-	}
-	hc->hcchar = hcc;
-	hc->hcint = ~0;
-}
-
-static int
-sofdone(void *a)
-{
-	Dwcregs *r;
-
-	r = a;
-	return r->gintsts & Sofintr;
-}
-
-static void
-sofwait(Ctlr *ctlr, int n)
-{
-	Dwcregs *r;
-	int x;
-
-	r = ctlr->regs;
-	do{
-		r->gintsts = Sofintr;
-		x = splfhi();
-		ctlr->sofchan |= 1<<n;
-		r->gintmsk |= Sofintr;
-		sleep(&ctlr->chanintr[n], sofdone, r);
-		splx(x);
-	}while((r->hfnum & 7) == 6);
-}
-
-static int
-chandone(void *a)
-{
-	Hostchan *hc;
-
-	hc = a;
-	if(hc->hcint == (Chhltd|Ack))
-		return 0;
-	return (hc->hcint & hc->hcintmsk) != 0;
-}
-
-static int
-chanwait(Ep *ep, Ctlr *ctlr, Hostchan *hc, int mask)
-{
-	int intr, n, x, ointr;
-	ulong start, now;
-	Dwcregs *r;
-
-	r = ctlr->regs;
-	n = hc - r->hchan;
-	for(;;){
-restart:
-		x = splfhi();
-		r->haintmsk |= 1<<n;
-		hc->hcintmsk = mask;
-		sleep(&ctlr->chanintr[n], chandone, hc);
-		hc->hcintmsk = 0;
-		splx(x);
-		intr = hc->hcint;
-		if(intr & Chhltd)
-			return intr;
-		start = fastticks(0);
-		ointr = intr;
-		now = start;
-		do{
-			intr = hc->hcint;
-			if(intr & Chhltd){
-				if((ointr != Ack && ointr != (Ack|Xfercomp)) ||
-				   intr != (Ack|Chhltd|Xfercomp) ||
-				   (now - start) > 60)
-					dprint("await %x after %ld %x -> %x\n",
-						mask, now - start, ointr, intr);
-				return intr;
-			}
-			if((intr & mask) == 0){
-				dprint("ep%d.%d await %x intr %x -> %x\n",
-					ep->dev->nb, ep->nb, mask, ointr, intr);
-				goto restart;
-			}
-			now = fastticks(0);
-		}while(now - start < 100);
-		dprint("ep%d.%d halting channel %8.8ux hcchar %8.8ux "
-			"grxstsr %8.8ux gnptxsts %8.8ux hptxsts %8.8ux\n",
-			ep->dev->nb, ep->nb, intr, hc->hcchar, r->grxstsr,
-			r->gnptxsts, r->hptxsts);
-		mask = Chhltd;
-		hc->hcchar |= Chdis;
-		start = m->ticks;
-		while(hc->hcchar & Chen){
-			if(m->ticks - start >= 100){
-				print("ep%d.%d channel won't halt hcchar %8.8ux\n",
-					ep->dev->nb, ep->nb, hc->hcchar);
-				break;
-			}
-		}
-		logdump(ep);
-	}
-}
-
-static int
-chanintr(Ctlr *ctlr, int n)
-{
-	Hostchan *hc;
-	int i;
-
-	hc = &ctlr->regs->hchan[n];
-	if(ctlr->debugchan & (1<<n))
-		clog(nil, hc);
-	if((hc->hcsplt & Spltena) == 0)
-		return 0;
-	i = hc->hcint;
-	if(i == (Chhltd|Ack)){
-		hc->hcsplt |= Compsplt;
-		ctlr->splitretry = 0;
-	}else if(i == (Chhltd|Nyet)){
-		if(++ctlr->splitretry >= 3)
-			return 0;
-	}else
-		return 0;
-	if(hc->hcchar & Chen){
-		iprint("hcchar %8.8ux hcint %8.8ux", hc->hcchar, hc->hcint);
-		hc->hcchar |= Chen | Chdis;
-		while(hc->hcchar&Chen)
-			;
-		iprint(" %8.8ux\n", hc->hcint);
-	}
-	hc->hcint = i;
-	if(ctlr->regs->hfnum & 1)
-		hc->hcchar &= ~Oddfrm;
-	else
-		hc->hcchar |= Oddfrm;
-	hc->hcchar = (hc->hcchar &~ Chdis) | Chen;
-	return 1;
-}
-
-static Reg chanlog[32][5];
-static int nchanlog;
-
-static void
-logstart(Ep *ep)
-{
-	if(ep->debug)
-		nchanlog = 0;
-}
-
-static void
-clog(Ep *ep, Hostchan *hc)
-{
-	Reg *p;
-
-	if(ep != nil && !ep->debug)
-		return;
-	if(nchanlog == 32)
-		nchanlog--;
-	p = chanlog[nchanlog];
-	p[0] = dwc.regs->hfnum;
-	p[1] = hc->hcchar;
-	p[2] = hc->hcint;
-	p[3] = hc->hctsiz;
-	p[4] = hc->hcdma;
-	nchanlog++;
-}
-
-static void
-logdump(Ep *ep)
-{
-	Reg *p;
-	int i;
-
-	if(!ep->debug)
-		return;
-	p = chanlog[0];
-	for(i = 0; i < nchanlog; i++){
-		print("%5.5d.%5.5d %8.8ux %8.8ux %8.8ux %8.8ux\n",
-			p[0]&0xFFFF, p[0]>>16, p[1], p[2], p[3], p[4]);
-		p += 5;
-	}
-	nchanlog = 0;
-}
-
-static int
-chanio(Ep *ep, Hostchan *hc, int dir, int pid, void *a, int len)
-{
-	Ctlr *ctlr;
-	int nleft, n, nt, i, maxpkt, npkt;
-	uint hcdma, hctsiz;
-
-	ctlr = ep->hp->aux;
-	maxpkt = ep->maxpkt;
-	npkt = HOWMANY(len, ep->maxpkt);
-	if(npkt == 0)
-		npkt = 1;
-
-	hc->hcchar = (hc->hcchar & ~Epdir) | dir;
-	if(dir == Epin)
-		n = ROUND(len, ep->maxpkt);
-	else
-		n = len;
-	hc->hctsiz = n | npkt<<OPktcnt | pid;
-	hc->hcdma  = PADDR(a);
-
-	nleft = len;
-	logstart(ep);
-	for(;;){
-		hcdma = hc->hcdma;
-		hctsiz = hc->hctsiz;
-		hc->hctsiz = hctsiz & ~Dopng;
-		if(hc->hcchar&Chen){
-			dprint("ep%d.%d before chanio hcchar=%8.8ux\n",
-				ep->dev->nb, ep->nb, hc->hcchar);
-			hc->hcchar |= Chen | Chdis;
-			while(hc->hcchar&Chen)
-				;
-			hc->hcint = Chhltd;
-		}
-		if((i = hc->hcint) != 0){
-			dprint("ep%d.%d before chanio hcint=%8.8ux\n",
-				ep->dev->nb, ep->nb, i);
-			hc->hcint = i;
-		}
-		if(hc->hcsplt & Spltena){
-			qlock(&ctlr->split);
-			sofwait(ctlr, hc - ctlr->regs->hchan);
-			if((dwc.regs->hfnum & 1) == 0)
-				hc->hcchar &= ~Oddfrm;
-			else
-				hc->hcchar |= Oddfrm;
-		}
-		hc->hcchar = (hc->hcchar &~ Chdis) | Chen;
-		clog(ep, hc);
-		if(ep->ttype == Tbulk && dir == Epin)
-			i = chanwait(ep, ctlr, hc, /* Ack| */ Chhltd);
-		else if(ep->ttype == Tintr && (hc->hcsplt & Spltena))
-			i = chanwait(ep, ctlr, hc, Chhltd);
-		else
-			i = chanwait(ep, ctlr, hc, Chhltd|Nak);
-		clog(ep, hc);
-		hc->hcint = i;
-
-		if(hc->hcsplt & Spltena){
-			hc->hcsplt &= ~Compsplt;
-			qunlock(&ctlr->split);
-		}
-
-		if((i & Xfercomp) == 0 && i != (Chhltd|Ack) && i != Chhltd){
-			if(i & Stall)
-				error(Estalled);
-			if(i & (Nyet|Frmovrun))
-				continue;
-			if(i & Nak){
-				if(ep->ttype == Tintr)
-					tsleep(&up->sleep, return0, 0, ep->pollival);
-				else
-					tsleep(&up->sleep, return0, 0, 1);
-				continue;
-			}
-			logdump(ep);
-			print("usbotg: ep%d.%d error intr %8.8ux\n",
-				ep->dev->nb, ep->nb, i);
-			if(i & ~(Chhltd|Ack))
-				error(Eio);
-			if(hc->hcdma != hcdma)
-				print("usbotg: weird hcdma %x->%x intr %x->%x\n",
-					hcdma, hc->hcdma, i, hc->hcint);
-		}
-		n = hc->hcdma - hcdma;
-		if(n == 0){
-			if((hc->hctsiz & Pktcnt) != (hctsiz & Pktcnt))
-				break;
-			else
-				continue;
-		}
-		if(dir == Epin && ep->ttype == Tbulk && n == nleft){
-			nt = (hctsiz & Xfersize) - (hc->hctsiz & Xfersize);
-			if(nt != n){
-				if(n == ROUND(nt, 4))
-					n = nt;
-				else
-					print("usbotg: intr %8.8ux "
-						"dma %8.8ux-%8.8ux "
-						"hctsiz %8.8ux-%8.ux\n",
-						i, hcdma, hc->hcdma, hctsiz,
-						hc->hctsiz);
-			}
-		}
-		if(n > nleft){
-			if(n != ROUND(nleft, 4))
-				dprint("too much: wanted %d got %d\n",
-					len, len - nleft + n);
-			n = nleft;
-		}
-		nleft -= n;
-		if(nleft == 0 || (n % maxpkt) != 0)
-			break;
-		if((i & Xfercomp) && ep->ttype != Tctl)
-			break;
-		if(dir == Epout)
-			dprint("too little: nleft %d hcdma %x->%x hctsiz %x->%x intr %x\n",
-				nleft, hcdma, hc->hcdma, hctsiz, hc->hctsiz, i);
-	}
-	logdump(ep);
-	return len - nleft;
-}
-
-static long
-multitrans(Ep *ep, Hostchan *hc, int rw, void *a, long n)
-{
-	long sofar, m;
-
-	sofar = 0;
-	do{
-		m = n - sofar;
-		if(m > ep->maxpkt)
-			m = ep->maxpkt;
-		m = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw],
-			(char*)a + sofar, m);
-		ep->toggle[rw] = hc->hctsiz & Pid;
-		sofar += m;
-	}while(sofar < n && m == ep->maxpkt);
-	return sofar;
-}
-
-static long
-eptrans(Ep *ep, int rw, void *a, long n)
-{
-	Hostchan *hc;
-
-	if(ep->clrhalt){
-		ep->clrhalt = 0;
-		if(ep->mode != OREAD)
-			ep->toggle[Write] = DATA0;
-		if(ep->mode != OWRITE)
-			ep->toggle[Read] = DATA0;
-	}
-	hc = chanalloc(ep);
-	if(waserror()){
-		ep->toggle[rw] = hc->hctsiz & Pid;
-		chanrelease(ep, hc);
-		if(strcmp(up->errstr, Estalled) == 0)
-			return 0;
-		nexterror();
-	}
-	chansetup(hc, ep);
-	if(rw == Read && ep->ttype == Tbulk)
-		n = multitrans(ep, hc, rw, a, n);
-	else{
-		n = chanio(ep, hc, rw == Read? Epin : Epout, ep->toggle[rw],
-			a, n);
-		ep->toggle[rw] = hc->hctsiz & Pid;
-	}
-	chanrelease(ep, hc);
-	poperror();
-	return n;
-}
-
-static long
-ctltrans(Ep *ep, uchar *req, long n)
-{
-	Hostchan *hc;
-	Epio *epio;
-	Block *b;
-	uchar *data;
-	int datalen;
-
-	epio = ep->aux;
-	if(epio->cb != nil){
-		freeb(epio->cb);
-		epio->cb = nil;
-	}
-	if(n < Rsetuplen)
-		error(Ebadlen);
-	if(req[Rtype] & Rd2h){
-		datalen = GET2(req+Rcount);
-		if(datalen <= 0 || datalen > Maxctllen)
-			error(Ebadlen);
-		/* XXX cache madness */
-		epio->cb = b = allocb(ROUND(datalen, ep->maxpkt) + CACHELINESZ);
-		b->wp = (uchar*)ROUND((uintptr)b->wp, CACHELINESZ);
-		memset(b->wp, 0x55, b->lim - b->wp);
-		cachedwbinvse(b->wp, b->lim - b->wp);
-		data = b->wp;
-	}else{
-		b = nil;
-		datalen = n - Rsetuplen;
-		data = req + Rsetuplen;
-	}
-	hc = chanalloc(ep);
-	if(waserror()){
-		chanrelease(ep, hc);
-		if(strcmp(up->errstr, Estalled) == 0)
-			return 0;
-		nexterror();
-	}
-	chansetup(hc, ep);
-	chanio(ep, hc, Epout, SETUP, req, Rsetuplen);
-	if(req[Rtype] & Rd2h){
-		if(ep->dev->hub <= 1){
-			ep->toggle[Read] = DATA1;
-			b->wp += multitrans(ep, hc, Read, data, datalen);
-		}else
-			b->wp += chanio(ep, hc, Epin, DATA1, data, datalen);
-		chanio(ep, hc, Epout, DATA1, nil, 0);
-		n = Rsetuplen;
-	}else{
-		if(datalen > 0)
-			chanio(ep, hc, Epout, DATA1, data, datalen);
-		chanio(ep, hc, Epin, DATA1, nil, 0);
-		n = Rsetuplen + datalen;
-	}
-	chanrelease(ep, hc);
-	poperror();
-	return n;
-}
-
-static long
-ctldata(Ep *ep, void *a, long n)
-{
-	Epio *epio;
-	Block *b;
-
-	epio = ep->aux;
-	b = epio->cb;
-	if(b == nil)
-		return 0;
-	if(n > BLEN(b))
-		n = BLEN(b);
-	memmove(a, b->rp, n);
-	b->rp += n;
-	if(BLEN(b) == 0){
-		freeb(b);
-		epio->cb = nil;
-	}
-	return n;
-}
-
-static void
-greset(Dwcregs *r, int bits)
-{
-	r->grstctl |= bits;
-	while(r->grstctl & bits)
-		;
-	microdelay(10);
-}
-
-static void
-init(Hci *hp)
-{
-	Ctlr *ctlr;
-	Dwcregs *r;
-	uint n, rx, tx, ptx;
-
-	ctlr = hp->aux;
-	r = ctlr->regs;
-
-	ctlr->nchan = 1 + ((r->ghwcfg2 & Num_host_chan) >> ONum_host_chan);
-	ctlr->chanintr = malloc(ctlr->nchan * sizeof(Rendez));
-
-	r->gahbcfg = 0;
-	setpower(PowerUsb, 1);
-
-	while((r->grstctl&Ahbidle) == 0)
-		;
-	greset(r, Csftrst);
-
-	r->gusbcfg |= Force_host_mode;
-	tsleep(&up->sleep, return0, 0, 25);
-	r->gahbcfg |= Dmaenable;
-
-	n = (r->ghwcfg3 & Dfifo_depth) >> ODfifo_depth;
-	rx = 0x306;
-	tx = 0x100;
-	ptx = 0x200;
-	r->grxfsiz = rx;
-	r->gnptxfsiz = rx | tx<<ODepth;
-	tsleep(&up->sleep, return0, 0, 1);
-	r->hptxfsiz = (rx + tx) | ptx << ODepth;
-	greset(r, Rxfflsh);
-	r->grstctl = TXF_ALL;
-	greset(r, Txfflsh);
-	dprint("usbotg: FIFO depth %d sizes rx/nptx/ptx %8.8ux %8.8ux %8.8ux\n",
-		n, r->grxfsiz, r->gnptxfsiz, r->hptxfsiz);
-
-	r->hport0 = Prtpwr|Prtconndet|Prtenchng|Prtovrcurrchng;
-	r->gintsts = ~0;
-	r->gintmsk = Hcintr;
-	r->gahbcfg |= Glblintrmsk;
-}
-
-static void
-dump(Hci*)
-{
-}
-
-static void
-fiqintr(Ureg*, void *a)
-{
-	Hci *hp;
-	Ctlr *ctlr;
-	Dwcregs *r;
-	uint intr, haint, wakechan;
-	int i;
-
-	hp = a;
-	ctlr = hp->aux;
-	r = ctlr->regs;
-	wakechan = 0;
-	intr = r->gintsts;
-	if(intr & Hcintr){
-		haint = r->haint & r->haintmsk;
-		for(i = 0; haint; i++){
-			if(haint & 1){
-				if(chanintr(ctlr, i) == 0){
-					r->haintmsk &= ~(1<<i);
-					wakechan |= 1<<i;
-				}
-			}
-			haint >>= 1;
-		}
-	}
-	if(intr & Sofintr){
-		r->gintsts = Sofintr;
-		if((r->hfnum&7) != 6){
-			r->gintmsk &= ~Sofintr;
-			wakechan |= ctlr->sofchan;
-			ctlr->sofchan = 0;
-		}
-	}
-	if(wakechan){
-		ctlr->wakechan |= wakechan;
-		armtimerset(1);
-	}
-}
-
-static void
-irqintr(Ureg*, void *a)
-{
-	Ctlr *ctlr;
-	uint wakechan;
-	int i, x;
-
-	ctlr = a;
-	x = splfhi();
-	armtimerset(0);
-	wakechan = ctlr->wakechan;
-	ctlr->wakechan = 0;
-	splx(x);
-	for(i = 0; wakechan; i++){
-		if(wakechan & 1)
-			wakeup(&ctlr->chanintr[i]);
-		wakechan >>= 1;
-	}
-}
-
-static void
-epopen(Ep *ep)
-{
-	ddprint("usbotg: epopen ep%d.%d ttype %d\n",
-		ep->dev->nb, ep->nb, ep->ttype);
-	switch(ep->ttype){
-	case Tnone:
-		error(Enotconf);
-	case Tintr:
-		assert(ep->pollival > 0);
-		/* fall through */
-	case Tbulk:
-		if(ep->toggle[Read] == 0)
-			ep->toggle[Read] = DATA0;
-		if(ep->toggle[Write] == 0)
-			ep->toggle[Write] = DATA0;
-		break;
-	}
-	ep->aux = malloc(sizeof(Epio));
-	if(ep->aux == nil)
-		error(Enomem);
-}
-
-static void
-epclose(Ep *ep)
-{
-	ddprint("usbotg: epclose ep%d.%d ttype %d\n",
-		ep->dev->nb, ep->nb, ep->ttype);
-	switch(ep->ttype){
-	case Tctl:
-		freeb(((Epio*)ep->aux)->cb);
-		/* fall through */
-	default:
-		free(ep->aux);
-		break;
-	}
-}
-
-static long
-epread(Ep *ep, void *a, long n)
-{
-	Epio *epio;
-	Block *b;
-	uchar *p;
-	ulong elapsed;
-	long nr;
-
-	ddprint("epread ep%d.%d %ld\n", ep->dev->nb, ep->nb, n);
-	epio = ep->aux;
-	b = nil;
-	qlock(epio);
-	if(waserror()){
-		qunlock(epio);
-		if(b)
-			freeb(b);
-		nexterror();
-	}
-	switch(ep->ttype){
-	default:
-		error(Egreg);
-	case Tctl:
-		nr = ctldata(ep, a, n);
-		qunlock(epio);
-		poperror();
-		return nr;
-	case Tintr:
-		elapsed = TK2MS(m->ticks) - epio->lastpoll;
-		if(elapsed < ep->pollival)
-			tsleep(&up->sleep, return0, 0, ep->pollival - elapsed);
-		/* fall through */
-	case Tbulk:
-		/* XXX cache madness */
-		b = allocb(ROUND(n, ep->maxpkt) + CACHELINESZ);
-		p = (uchar*)ROUND((uintptr)b->base, CACHELINESZ);
-		cachedwbinvse(p, n);
-		nr = eptrans(ep, Read, p, n);
-		epio->lastpoll = TK2MS(m->ticks);
-		memmove(a, p, nr);
-		qunlock(epio);
-		freeb(b);
-		poperror();
-		return nr;
-	}
-}
-
-static long
-epwrite(Ep *ep, void *a, long n)
-{
-	Epio *epio;
-	Block *b;
-	uchar *p;
-	ulong elapsed;
-
-	ddprint("epwrite ep%d.%d %ld\n", ep->dev->nb, ep->nb, n);
-	epio = ep->aux;
-	b = nil;
-	qlock(epio);
-	if(waserror()){
-		qunlock(epio);
-		if(b)
-			freeb(b);
-		nexterror();
-	}
-	switch(ep->ttype){
-	default:
-		error(Egreg);
-	case Tintr:
-		elapsed = TK2MS(m->ticks) - epio->lastpoll;
-		if(elapsed < ep->pollival)
-			tsleep(&up->sleep, return0, 0, ep->pollival - elapsed);
-		/* fall through */
-	case Tctl:
-	case Tbulk:
-		/* XXX cache madness */
-		b = allocb(n + CACHELINESZ);
-		p = (uchar*)ROUND((uintptr)b->base, CACHELINESZ);
-		memmove(p, a, n);
-		cachedwbse(p, n);
-		if(ep->ttype == Tctl)
-			n = ctltrans(ep, p, n);
-		else{
-			n = eptrans(ep, Write, p, n);
-			epio->lastpoll = TK2MS(m->ticks);
-		}
-		qunlock(epio);
-		freeb(b);
-		poperror();
-		return n;
-	}
-}
-
-static char*
-seprintep(char *s, char*, Ep*)
-{
-	return s;
-}
-	
-static int
-portenable(Hci *hp, int port, int on)
-{
-	Ctlr *ctlr;
-	Dwcregs *r;
-
-	assert(port == 1);
-	ctlr = hp->aux;
-	r = ctlr->regs;
-	dprint("usbotg enable=%d; sts %#x\n", on, r->hport0);
-	if(!on)
-		r->hport0 = Prtpwr | Prtena;
-	tsleep(&up->sleep, return0, 0, Enabledelay);
-	dprint("usbotg enable=%d; sts %#x\n", on, r->hport0);
-	return 0;
-}
-
-static int
-portreset(Hci *hp, int port, int on)
-{
-	Ctlr *ctlr;
-	Dwcregs *r;
-	int b, s;
-
-	assert(port == 1);
-	ctlr = hp->aux;
-	r = ctlr->regs;
-	dprint("usbotg reset=%d; sts %#x\n", on, r->hport0);
-	if(!on)
-		return 0;
-	r->hport0 = Prtpwr | Prtrst;
-	tsleep(&up->sleep, return0, 0, ResetdelayHS);
-	r->hport0 = Prtpwr;
-	tsleep(&up->sleep, return0, 0, Enabledelay);
-	s = r->hport0;
-	b = s & (Prtconndet|Prtenchng|Prtovrcurrchng);
-	if(b != 0)
-		r->hport0 = Prtpwr | b;
-	dprint("usbotg reset=%d; sts %#x\n", on, s);
-	if((s & Prtena) == 0)
-		print("usbotg: host port not enabled after reset");
-	return 0;
-}
-
-static int
-portstatus(Hci *hp, int port)
-{
-	Ctlr *ctlr;
-	Dwcregs *r;
-	int b, s;
-
-	assert(port == 1);
-	ctlr = hp->aux;
-	r = ctlr->regs;
-	s = r->hport0;
-	b = s & (Prtconndet|Prtenchng|Prtovrcurrchng);
-	if(b != 0)
-		r->hport0 = Prtpwr | b;
-	b = 0;
-	if(s & Prtconnsts)
-		b |= HPpresent;
-	if(s & Prtconndet)
-		b |= HPstatuschg;
-	if(s & Prtena)
-		b |= HPenable;
-	if(s & Prtenchng)
-		b |= HPchange;
-	if(s & Prtovrcurract)
-		 b |= HPovercurrent;
-	if(s & Prtsusp)
-		b |= HPsuspend;
-	if(s & Prtrst)
-		b |= HPreset;
-	if(s & Prtpwr)
-		b |= HPpower;
-	switch(s & Prtspd){
-	case HIGHSPEED:
-		b |= HPhigh;
-		break;
-	case LOWSPEED:
-		b |= HPslow;
-		break;
-	}
-	return b;
-}
-
-static void
-shutdown(Hci*)
-{
-}
-
-static void
-setdebug(Hci*, int d)
-{
-	debug = d;
-}
-
-static int
-reset(Hci *hp)
-{
-	Ctlr *ctlr;
-	uint id;
-
-	ctlr = &dwc;
-	if(ctlr->regs != nil)
-		return -1;
-	ctlr->regs = (Dwcregs*)USBREGS;
-	id = ctlr->regs->gsnpsid;
-	if((id>>16) != ('O'<<8 | 'T'))
-		return -1;
-	dprint("usbotg: rev %d.%3.3x\n", (id>>12)&0xF, id&0xFFF);
-
-	intrenable(IRQtimerArm, irqintr, ctlr, 0, "dwc");
-
-	hp->aux = ctlr;
-	hp->port = 0;
-	hp->irq = IRQusb;
-	hp->tbdf = 0;
-	hp->nports = 1;
-	hp->highspeed = 1;
-
-	hp->init = init;
-	hp->dump = dump;
-	hp->interrupt = fiqintr;
-	hp->epopen = epopen;
-	hp->epclose = epclose;
-	hp->epread = epread;
-	hp->epwrite = epwrite;
-	hp->seprintep = seprintep;
-	hp->portenable = portenable;
-	hp->portreset = portreset;
-	hp->portstatus = portstatus;
-	hp->shutdown = shutdown;
-	hp->debug = setdebug;
-	hp->type = "dwcotg";
-	return 0;
-}
-
-void
-usbdwclink(void)
-{
-	addhcitype("dwcotg", reset);
-}

+ 0 - 301
sys/src/9/bcm/vcore.c

@@ -1,301 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-
-/*
- * Mailbox interface with videocore gpu
- */
-
-#define	MAILBOX		(VIRTIO+0xB880)
-
-typedef struct Prophdr Prophdr;
-typedef struct Fbinfo Fbinfo;
-
-enum {
-	Read		= 0x00>>2,
-	Write		= 0x00>>2,
-	Peek		= 0x10>>2,
-	Sender		= 0x14>>2,
-	Status		= 0x18>>2,
-		Full		= 1<<31,
-		Empty		= 1<<30,
-	Config		= 0x1C>>2,
-	NRegs		= 0x20>>2,
-
-	ChanMask	= 0xF,
-	ChanProps	= 8,
-	ChanFb		= 1,
-
-	Req			= 0x0,
-	RspOk		= 0x80000000,
-	TagResp		= 1<<31,
-
-	TagGetfwrev	= 0x00000001,
-	TagGetmac	= 0x00010003,
-	TagGetram	= 0x00010005,
-	TagGetpower	= 0x00020001,
-	TagSetpower	= 0x00028001,
-		Powerwait	= 1<<1,
-	TagGetclkspd= 0x00030002,
-	TagFballoc	= 0x00040001,
-	TagFbfree	= 0x00048001,
-	TagFbblank	= 0x00040002,
-	TagGetres	= 0x00040003,
-	TagSetres	= 0x00048003,
-	TagGetvres	= 0x00040004,
-	TagSetvres	= 0x00048004,
-	TagGetdepth	= 0x00040005,
-	TagSetdepth	= 0x00048005,
-	TagGetrgb	= 0x00044006,
-	TagSetrgb	= 0x00048006,
-};
-
-struct Fbinfo {
-	u32int	xres;
-	u32int	yres;
-	u32int	xresvirtual;
-	u32int	yresvirtual;
-	u32int	pitch;			/* returned by gpu */
-	u32int	bpp;
-	u32int	xoffset;
-	u32int	yoffset;
-	u32int	base;			/* returned by gpu */
-	u32int	screensize;		/* returned by gpu */
-};
-
-
-struct Prophdr {
-	u32int	len;
-	u32int	req;
-	u32int	tag;
-	u32int	tagbuflen;
-	u32int	taglen;
-	u32int	data[1];
-};
-
-static void
-vcwrite(uint chan, int val)
-{
-	u32int *r;
-
-	r = (u32int*)MAILBOX + NRegs;
-	val &= ~ChanMask;
-	while(r[Status]&Full)
-		;
-	coherence();
-	r[Write] = val | chan;
-}
-
-static int
-vcread(uint chan)
-{
-	u32int *r;
-	int x;
-
-	r = (u32int*)MAILBOX;
-	do{
-		while(r[Status]&Empty)
-			;
-		coherence();
-		x = r[Read];
-	}while((x&ChanMask) != chan);
-	return x & ~ChanMask;
-}
-
-/*
- * Property interface
- */
-
-static int
-vcreq(int tag, void *buf, int vallen, int rsplen)
-{
-	uintptr r;
-	int n;
-	Prophdr *prop;
-	static uintptr base = BUSDRAM;
-
-	if(rsplen < vallen)
-		rsplen = vallen;
-	rsplen = (rsplen+3) & ~3;
-	prop = (Prophdr*)(VCBUFFER);
-	n = sizeof(Prophdr) + rsplen + 8;
-	memset(prop, 0, n);
-	prop->len = n;
-	prop->req = Req;
-	prop->tag = tag;
-	prop->tagbuflen = rsplen;
-	prop->taglen = vallen;
-	if(vallen > 0)
-		memmove(prop->data, buf, vallen);
-	cachedwbinvse(prop, prop->len);
-	for(;;){
-		vcwrite(ChanProps, PADDR(prop) + base);
-		r = vcread(ChanProps);
-		if(r == PADDR(prop) + base)
-			break;
-		if(base == 0)
-			return -1;
-		base = 0;
-	}
-	if(prop->req == RspOk &&
-	   prop->tag == tag &&
-	   (prop->taglen&TagResp)) {
-		if((n = prop->taglen & ~TagResp) < rsplen)
-			rsplen = n;
-		memmove(buf, prop->data, rsplen);
-	}else
-		rsplen = -1;
-
-	return rsplen;
-}
-
-/*
- * Framebuffer
- */
-
-static int
-fbdefault(int *width, int *height, int *depth)
-{
-	u32int buf[3];
-
-	if(vcreq(TagGetres, &buf[0], 0, 2*4) != 2*4 ||
-	   vcreq(TagGetdepth, &buf[2], 0, 4) != 4)
-		return -1;
-	*width = buf[0];
-	*height = buf[1];
-	*depth = buf[2];
-	return 0;
-}
-
-void*
-fbinit(int set, int *width, int *height, int *depth)
-{
-	Fbinfo *fi;
-	uintptr va;
-
-	if(!set)
-		fbdefault(width, height, depth);
-	/* Screen width must be a multiple of 16 */
-	*width &= ~0xF;
-	fi = (Fbinfo*)(VCBUFFER);
-	memset(fi, 0, sizeof(*fi));
-	fi->xres = fi->xresvirtual = *width;
-	fi->yres = fi->yresvirtual = *height;
-	fi->bpp = *depth;
-	cachedwbinvse(fi, sizeof(*fi));
-	vcwrite(ChanFb, DMAADDR(fi));
-	if(vcread(ChanFb) != 0)
-		return 0;
-	va = mmukmap(FRAMEBUFFER, PADDR(fi->base), fi->screensize);
-	if(va)
-		memset((char*)va, 0x7F, fi->screensize);
-	return (void*)va;
-}
-
-int
-fbblank(int blank)
-{
-	u32int buf[1];
-
-	buf[0] = blank;
-	if(vcreq(TagFbblank, buf, sizeof buf, sizeof buf) != sizeof buf)
-		return -1;
-	return buf[0] & 1;
-}
-
-/*
- * Power management
- */
-void
-setpower(int dev, int on)
-{
-	u32int buf[2];
-
-	buf[0] = dev;
-	buf[1] = Powerwait | (on? 1 : 0);
-	vcreq(TagSetpower, buf, sizeof buf, sizeof buf);
-}
-
-int
-getpower(int dev)
-{
-	u32int buf[2];
-
-	buf[0] = dev;
-	buf[1] = 0;
-	if(vcreq(TagGetpower, buf, sizeof buf[0], sizeof buf) != sizeof buf)
-		return -1;
-	return buf[0] & 1;
-}
-
-/*
- * Get ethernet address (as hex string)
- *	 [not reentrant]
- */
-char *
-getethermac(void)
-{
-	uchar ea[8];
-	char *p;
-	int i;
-	static char buf[16];
-
-	memset(ea, 0, sizeof ea);
-	vcreq(TagGetmac, ea, 0, sizeof ea);
-	p = buf;
-	for(i = 0; i < 6; i++)
-		p += sprint(p, "%.2x", ea[i]);
-	return buf;
-}
-
-/*
- * Get firmware revision
- */
-uint
-getfirmware(void)
-{
-	u32int buf[1];
-
-	if(vcreq(TagGetfwrev, buf, 0, sizeof buf) != sizeof buf)
-		return 0;
-	return buf[0];
-}
-
-/*
- * Get ARM ram
- */
-void
-getramsize(Confmem *mem)
-{
-	u32int buf[2];
-
-	if(vcreq(TagGetram, buf, 0, sizeof buf) != sizeof buf)
-		return;
-	mem->base = buf[0];
-	mem->limit = buf[1];
-}
-
-/*
- * Get clock rate
- */
-ulong
-getclkrate(int clkid)
-{
-	u32int buf[2];
-
-	buf[0] = clkid;
-	if(vcreq(TagGetclkspd, buf, sizeof(buf[0]), sizeof(buf)) != sizeof buf)
-		return 0;
-	return buf[1];
-}

+ 0 - 10
sys/src/9/bcm/vfp3.c

@@ -1,10 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "../teg2/vfp3.c"

+ 0 - 149
sys/src/9/bcm/words

@@ -1,149 +0,0 @@
-raspberry pi
-
-broadcom 2835 SoC (based on 2708)
-arm1176jzf-s (v6 arch) 700MHz cpu, apparently dual-issue, with vfp2
-videocore 4 gpu
-
-l1 I & D VIPT caches
-	16K each: 4-way, 128 sets, 32-byte lines
-	l1 D is write-through, l1 I is write-back
-unified l2 PIPT cache 128K: 4-way?, 1024? sets, 32-byte lines, mostly for gpu
-(by default CPU doesn't see it)
-
-we arrange that device register accesses are uncached and unbuffered
-(strongly ordered, in armv6/v7 terminology).
-
-256MB or 512MB of dram at physical address 0, shared with gpu
-non-16550 uart for console
-	uart serial voltages are TTL (3.3v, not rs232 which is nominally 12v);
-	could use usb serial (ick).
-there's no real ethernet controller, so we have to use usb ether,
-and the usb controller is nastier than usual.
-
-There's a serial port (115200b/s) on P1 connector pins (GND,TXD,RXD) =
-(6,8,10).  These are 3v TTL signals: use a level-shifter to convert to
-RS232, or a USB-to-TTL-serial adapter.  Add the line "console=0
-b115200" to the /cfg/pxe file on the server, or the parameter
-"console='0 b115200'" to cmdline.txt on the SD card.
-
-9pi is a Plan 9 terminal, which can boot with local fossil root on the
-sd card (/dev/sdM0), or with root from a Plan 9 file server via tcp.
-
-9picpu is a Plan 9 cpu server, which could be used in a headless
-configuration without screen, keyboard or mouse.
-
-9pifat is a minimal configuration which boots a shell script boot.rc
-with root in /plan9 on the dos partition, maybe useful for embedded
-applications where a full Plan 9 system is not needed.
-
-Network booting with u-boot:
-start with a normal rpi u-boot sd (e.g. raspberry-pi-uboot-20120707).
-update the start.elf with a version from a newer rpi distro (see below).
-mk installall
-add new system to ndb
-see booting(8)
-
-Booting from sd card:
-- start with a normal rpi distro sd (e.g. 2012-08-16-wheezy-raspbian)
-  [NB: versions of start.elf earlier than this may not be compatible]
-- copy 9pi to sd's root directory
-- add or change "kernel=" line in config.txt to "kernel=9pi"
-- plan9.ini is built from the "kernel arguments" in cmdline.txt - each
-  var=value entry becomes one plan9.ini line, so entries with spaces will
-  need single quotes.
-
-
-	physical mem map
-
-hex addr size	what
-----
-0	 256MB	sdram, cached (newer models have 512MB)
-00000000 64	exception vectors
-00000100 7936	boot ATAGs (inc. cmdline.txt)
-00002000 4K	Mach
-00003000 1K	L2 page table for exception vectors
-00003400 1K	videocore mailbox buffer
-00003800 2K	FIQ stack
-00004000 16K	L1 page table for kernel
-00008000 -	default kernel load address
-01000000 16K	u-boot env
-20000000 16M	peripherals
-20003000	system timer(s)
-20007000	dma
-2000B000	arm control: intr, timers 0 & 1, semas, doorbells, mboxes
-20100000	power, reset, watchdog
-20200000	gpio
-20201000	uart0
-20202000	mmc
-20215040	uart1 (mini uart)
-20300000	eMMC
-20600000	smi
-20980000	otg usb
-
-40000000	l2 cache only
-7e00b000	arm control
-7e2000c0	jtag
-7e201000?	pl011 usrt
-7e215000	aux: uart1, spi[12]
-
-80000000
-
-c0000000	bypass caches
-
-	virtual mem map (from cpu address map & mmu mappings)
-
-hex addr size	what
-----
-0	 512MB	user process address space
-7e000000 16M	i/o registers
-80000000 <=224M	kzero, kernel ram (reserve some for GPU)
-ffff0000 4K	exception vectors
-
-Linux params at *R2 (default 0x100) are a sequence of ATAGs
-  struct atag {
-	u32int size;		/* size of ATAG in words, including header */
-	u32int tag;		/* ATAG_CORE is first, ATAG_NONE is last */
-	u32int data[size-2];
-  };
-00000000	ATAG_NONE
-54410001	ATAG_CORE
-54410002	ATAG_MEM
-54410009	ATAG_CMDLINE
-
-uart dmas	15, 14
-
-intrs (96)
-irq1
-0	timer0
-1	timer1
-2	timer2
-3	timer3
-8	isp
-9	usb
-16	dma0
-17	dma1
-⋯
-28	dma12
-29	aux: uart1
-30	arm
-31	vpu dma
-
-irq2
-35	sdc
-36	dsio
-40	hdmi0
-41	hdmi1
-48	smi
-56	sdio
-57	uart1 aka "vc uart"
-
-irq0
-64	timer
-65	mbox
-66	doorbell0
-67	doorbell1
-75	usb
-77	dma2
-78	dma3
-82	sdio
-83	uart0

+ 0 - 193
sys/src/9/boot/aux.c

@@ -1,193 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-/*
-int
-plumb(char *dir, char *dest, int *efd, char *here)
-{
-	char buf[128];
-	char name[128];
-	int n;
-
-	sprint(name, "%s/clone", dir);
-	efd[0] = open(name, ORDWR);
-	if(efd[0] < 0)
-		return -1;
-	n = read(efd[0], buf, sizeof(buf)-1);
-	if(n < 0){
-		close(efd[0]);
-		return -1;
-	}
-	buf[n] = 0;
-	sprint(name, "%s/%s/data", dir, buf);
-	if(here){
-		sprint(buf, "announce %s", here);
-		if(sendmsg(efd[0], buf) < 0){
-			close(efd[0]);
-			return -1;
-		}
-	}
-	sprint(buf, "connect %s", dest);
-	if(sendmsg(efd[0], buf) < 0){
-		close(efd[0]);
-		return -1;
-	}
-	efd[1] = open(name, ORDWR);
-	if(efd[1] < 0){
-		close(efd[0]);
-		return -1;
-	}
-	return efd[1];
-}
-
-int
-sendmsg(int fd, char *msg)
-{
-	int n;
-
-	n = strlen(msg);
-	if(write(fd, msg, n) != n)
-		return -1;
-	return 0;
-}
- */
-
-void
-warning(char *s)
-{
-	char buf[ERRMAX];
-
-	buf[0] = '\0';
-	errstr(buf, sizeof buf);
-	fprint(2, "boot: %s: %s\n", s, buf);
-}
-
-void
-fatal(char *s)
-{
-	char *msg;
-	char buf[ERRMAX];
-
-	buf[0] = '\0';
-	errstr(buf, sizeof buf);
-	msg = smprint("%s: %s", s, buf);
-	fprint(2, "boot: %s\n", msg);
-	exits(msg);			/* this will trigger a panic */
-}
-
-int
-readfile(char *name, char *buf, int len)
-{
-	int f, n;
-
-	buf[0] = 0;
-	f = open(name, OREAD);
-	if(f < 0)
-		return -1;
-	n = read(f, buf, len-1);
-	if(n >= 0)
-		buf[n] = 0;
-	close(f);
-	return 0;
-}
-
-int
-writefile(char *name, char *buf, int len)
-{
-	int f, n;
-
-	f = open(name, OWRITE);
-	if(f < 0)
-		return -1;
-	n = write(f, buf, len);
-	close(f);
-	return (n != len) ? -1 : 0;
-}
-
-void
-setenv(char *name, char *val)
-{
-	int f;
-	char ename[64];
-
-	snprint(ename, sizeof ename, "#e/%s", name);
-	f = create(ename, 1, 0666);
-	if(f < 0){
-		fprint(2, "create %s: %r\n", ename);
-		return;
-	}
-	write(f, val, strlen(val));
-	close(f);
-}
-
-void
-srvcreate(char *name, int fd)
-{
-	char *srvname;
-	int f;
-	char buf[64];
-
-	srvname = strrchr(name, '/');
-	if(srvname)
-		srvname++;
-	else
-		srvname = name;
-
-	snprint(buf, sizeof buf, "#s/%s", srvname);
-	f = create(buf, 1, 0666);
-	if(f < 0)
-		fatal(buf);
-	sprint(buf, "%d", fd);
-	if(write(f, buf, strlen(buf)) != strlen(buf))
-		fatal("write");
-	close(f);
-}
-
-void
-catchint(void *a, char *note)
-{
-	USED(a);
-	if(strcmp(note, "alarm") == 0)
-		noted(NCONT);
-	noted(NDFLT);
-}
-
-int
-outin(char *prompt, char *def, int len)
-{
-	int n;
-	char buf[256];
-
-	if(len >= sizeof buf)
-		len = sizeof(buf)-1;
-
-	if(cpuflag){
-		notify(catchint);
-		alarm(15*1000);
-	}
-	print("%s[%s]: ", prompt, *def ? def : "no default");
-	memset(buf, 0, sizeof buf);
-	n = read(0, buf, len);
-	if(cpuflag){
-		alarm(0);
-		notify(0);
-	}
-
-	if(n < 0)
-		return 1;
-	if(n > 1){
-		buf[n-1] = 0;
-		strcpy(def, buf);
-	}
-	return n;
-}

+ 0 - 461
sys/src/9/boot/boot.c

@@ -1,461 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "../boot/boot.h"
-
-#define PARTSRV "partfs.sdXX"
-
-enum {
-	Dontpost,
-	Post,
-};
-
-char	cputype[64];
-char	sys[2*64];
-char 	reply[256];
-int	printcol;
-int	mflag;
-int	fflag;
-int	kflag;
-int	debugboot;
-int	nousbboot;
-
-char	*bargv[Nbarg];
-int	bargc;
-
-static void	swapproc(void);
-static Method	*rootserver(char*);
-static void	kbmap(void);
-
-/*
- * we should inherit the standard fds all referring to /dev/cons,
- * but we're being paranoid.
- */
-static void
-opencons(void)
-{
-	close(0);
-	close(1);
-	close(2);
-	bind("#c", "/dev", MBEFORE);
-	open("/dev/cons", OREAD);
-	open("/dev/cons", OWRITE);
-	open("/dev/cons", OWRITE);
-}
-
-/*
- * init will reinitialize its namespace.
- * #ec gets us plan9.ini settings (*var variables).
- */
-static void
-bindenvsrv(void)
-{
-	bind("#ec", "/env", MREPL);
-	bind("#e", "/env", MBEFORE|MCREATE);
-	bind("#s", "/srv/", MREPL|MCREATE);
-}
-
-static void
-debuginit(int argc, char **argv)
-{
-	int fd;
-
-	if(getenv("debugboot"))
-		debugboot = 1;
-	if(getenv("nousbboot"))
-		nousbboot = 1;
-#ifdef DEBUG
-	print("argc=%d\n", argc);
-	for(fd = 0; fd < argc; fd++)
-		print("%#p %s ", argv[fd], argv[fd]);
-	print("\n");
-#endif	/* DEBUG */
-	SET(fd);
-	USED(argc, argv, fd);
-}
-
-/*
- * read disk partition tables here so that readnvram via factotum
- * can see them.  ideally we would have this information in
- * environment variables before attaching #S, which would then
- * parse them and create partitions.
- */
-static void
-partinit(void)
-{
-	char *rdparts;
-
-	rdparts = getenv("readparts");
-	if(rdparts)
-		readparts();
-	free(rdparts);
-}
-
-/*
- *  pick a method and initialize it
- */
-static Method *
-pickmethod(int argc, char **argv)
-{
-	Method *mp;
-
-	if(method[0].name == nil)
-		fatal("no boot methods");
-	mp = rootserver(argc ? *argv : 0);
-	(*mp->config)(mp);
-	return mp;
-}
-
-/*
- *  authentication agent
- *  sets hostowner, creating an auth discontinuity
- */
-static void
-doauth(int cpuflag)
-{
-	dprint("auth...");
-	authentication(cpuflag);
-}
-
-/*
- *  connect to the root file system
- */
-static int
-connectroot(Method *mp, int islocal, int ishybrid)
-{
-	int fd, n;
-	char buf[32];
-
-	fd = (*mp->connect)();
-	if(fd < 0)
-		fatal("can't connect to file server");
-	if(getenv("srvold9p"))
-		fd = old9p(fd);
-	if(!islocal && !ishybrid){
-		if(cfs)
-			fd = (*cfs)(fd);
-	}
-	print("version...");
-	buf[0] = '\0';
-	n = fversion(fd, 0, buf, sizeof buf);
-	if(n < 0)
-		fatal("can't init 9P");
-	srvcreate("boot", fd);
-	return fd;
-}
-
-/*
- *  create the name space, mount the root fs
- */
-static int
-nsinit(int fd, char **rspp)
-{
-	int afd;
-	char *rp, *rsp;
-	AuthInfo *ai;
-	static char rootbuf[64];
-
-	if(bind("/", "/", MREPL) < 0)
-		fatal("bind /");
-	rp = getenv("rootspec");
-	if(rp == nil)
-		rp = "";
-	
-	afd = fauth(fd, rp);
-	if(afd >= 0){
-		ai = auth_proxy(afd, auth_getkey, "proto=p9any role=client");
-		if(ai == nil)
-			print("authentication failed (%r), trying mount anyways\n");
-	}
-	if(mount(fd, afd, "/root", MREPL|MCREATE, rp) < 0)
-		fatal("mount /");
-	rsp = rp;
-	rp = getenv("rootdir");
-	if(rp == nil)
-		rp = rootdir;
-	if(bind(rp, "/", MAFTER|MCREATE) < 0){
-		if(strncmp(rp, "/root", 5) == 0){
-			fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
-			fatal("second bind /");
-		}
-		snprint(rootbuf, sizeof rootbuf, "/root/%s", rp);
-		rp = rootbuf;
-		if(bind(rp, "/", MAFTER|MCREATE) < 0){
-			fprint(2, "boot: couldn't bind $rootdir=%s to root: %r\n", rp);
-			if(strcmp(rootbuf, "/root//plan9") != 0)
-				fatal("second bind /");
-			/* undo installer's work */
-			fprint(2, "**** warning: remove rootdir=/plan9 "
-				"entry from plan9.ini\n");
-			rp = "/root";
-			if(bind(rp, "/", MAFTER|MCREATE) < 0)
-				fatal("second bind /");
-		}
-	}
-	setenv("rootdir", rp);
-	*rspp = rsp;
-	return afd;
-}
-
-static void
-execinit(void)
-{
-	int iargc;
-	char *cmd, cmdbuf[64], *iargv[16];
-
-	/* exec init */
-	cmd = getenv("init");
-	if(cmd == nil){
-		sprint(cmdbuf, "/%s/init -%s%s", cputype,
-			cpuflag ? "c" : "t", mflag ? "m" : "");
-		cmd = cmdbuf;
-	}
-	iargc = tokenize(cmd, iargv, nelem(iargv)-1);
-	cmd = iargv[0];
-
-	/* make iargv[0] basename(iargv[0]) */
-	if(iargv[0] = strrchr(iargv[0], '/'))
-		iargv[0]++;
-	else
-		iargv[0] = cmd;
-
-	iargv[iargc] = nil;
-
-	chmod("/srv/" PARTSRV, 0600);
-	exec(cmd, iargv);
-	fatal(cmd);
-}
-
-void
-boot(int argc, char *argv[])
-{
-	int fd, afd, islocal, ishybrid;
-	char *rsp;
-	Method *mp;
-
-	fmtinstall('r', errfmt);
-	opencons();
-	bindenvsrv();
-	debuginit(argc, argv);
-
-	ARGBEGIN{
-	case 'k':
-		kflag = 1;
-		break;
-	case 'm':
-		mflag = 1;
-		break;
-	case 'f':
-		fflag = 1;
-		break;
-	}ARGEND
-
-	readfile("#e/cputype", cputype, sizeof(cputype));
-
-	/*
-	 *  set up usb keyboard & mouse, if any.
-	 *  starts partfs on first disk, if any, to permit nvram on usb.
-	 */
-	if (!nousbboot)
-		usbinit(Dontpost);
-
-	dprint("pickmethod...");
-	mp = pickmethod(argc, argv);
-	islocal = strcmp(mp->name, "local") == 0;
-	ishybrid = strcmp(mp->name, "hybrid") == 0;
-
-	kbmap();			/*  load keymap if it's there. */
-
-	/* don't trigger aoe until the network has been configured */
-	dprint("bind #æ...");
-	bind("#æ", "/dev", MAFTER);	/* nvram could be here */
-	dprint("bind #S...");
-	bind("#S", "/dev", MAFTER);	/* nvram could be here */
-	dprint("partinit...");
-	partinit();
-
-	doauth(cpuflag);	/* authentication usually changes hostowner */
-	rfork(RFNAMEG);		/* leave existing subprocs in own namespace */
-	if (!nousbboot)
-		usbinit(Post);	/* restart partfs under the new hostowner id */
-	fd = connectroot(mp, islocal, ishybrid);
-	afd = nsinit(fd, &rsp);
-	close(fd);
-
-	settime(islocal, afd, rsp);
-	if(afd > 0)
-		close(afd);
-	swapproc();
-	execinit();
-	exits("failed to exec init");
-}
-
-static Method*
-findmethod(char *a)
-{
-	Method *mp;
-	int i, j;
-	char *cp;
-
-	if((i = strlen(a)) == 0)
-		return nil;
-	cp = strchr(a, '!');
-	if(cp)
-		i = cp - a;
-	for(mp = method; mp->name; mp++){
-		j = strlen(mp->name);
-		if(j > i)
-			j = i;
-		if(strncmp(a, mp->name, j) == 0)
-			break;
-	}
-	if(mp->name)
-		return mp;
-	return nil;
-}
-
-/*
- *  ask user from whence cometh the root file system
- */
-static Method*
-rootserver(char *arg)
-{
-	char prompt[256];
-	Method *mp;
-	char *cp;
-	int n;
-
-	/* look for required reply */
-	dprint("read #e/nobootprompt...");
-	readfile("#e/nobootprompt", reply, sizeof(reply));
-	if(reply[0]){
-		mp = findmethod(reply);
-		if(mp)
-			goto HaveMethod;
-		print("boot method %s not found\n", reply);
-		reply[0] = 0;
-	}
-
-	/* make list of methods */
-	mp = method;
-	n = sprint(prompt, "root is from (%s", mp->name);
-	for(mp++; mp->name; mp++)
-		n += sprint(prompt+n, ", %s", mp->name);
-	sprint(prompt+n, ")");
-
-	/* create default reply */
-	dprint("read #e/bootargs...");
-	readfile("#e/bootargs", reply, sizeof(reply));
-	if(reply[0] == 0 && arg != 0)
-		strcpy(reply, arg);
-	if(reply[0]){
-		mp = findmethod(reply);
-		if(mp == 0)
-			reply[0] = 0;
-	}
-	if(reply[0] == 0)
-		strcpy(reply, method->name);
-
-	/* parse replies */
-	do{
-		dprint("outin...");
-		outin(prompt, reply, sizeof(reply));
-		mp = findmethod(reply);
-	}while(mp == nil);
-
-HaveMethod:
-	bargc = tokenize(reply, bargv, Nbarg-2);
-	bargv[bargc] = nil;
-	cp = strchr(reply, '!');
-	if(cp)
-		strcpy(sys, cp+1);
-	dprint("pickmethod done\n");
-	return mp;
-}
-
-static void
-swapproc(void)
-{
-	int fd;
-
-	fd = open("#c/swap", OWRITE);
-	if(fd < 0){
-		warning("opening #c/swap");
-		return;
-	}
-	if(write(fd, "start", 5) <= 0)
-		warning("starting swap kproc");
-	close(fd);
-}
-
-int
-old9p(int fd)
-{
-	int p[2];
-
-	if(pipe(p) < 0)
-		fatal("pipe");
-
-	print("srvold9p...");
-	switch(fork()) {
-	case -1:
-		fatal("rfork srvold9p");
-	case 0:
-		dup(fd, 1);
-		close(fd);
-		dup(p[0], 0);
-		close(p[0]);
-		close(p[1]);
-		execl("/srvold9p", "srvold9p", "-s", 0);
-		fatal("exec srvold9p");
-	default:
-		close(fd);
-		close(p[0]);
-	}
-	return p[1];
-}
-
-static void
-kbmap(void)
-{
-	char *f;
-	int n, in, out;
-	char buf[1024];
-
-	f = getenv("kbmap");
-	if(f == nil)
-		return;
-	if(bind("#κ", "/dev", MAFTER) < 0){
-		warning("can't bind #κ");
-		return;
-	}
-
-	in = open(f, OREAD);
-	if(in < 0){
-		warning("can't open kbd map");
-		return;
-	}
-	out = open("/dev/kbmap", OWRITE);
-	if(out < 0) {
-		warning("can't open /dev/kbmap");
-		close(in);
-		return;
-	}
-	while((n = read(in, buf, sizeof(buf))) > 0)
-		if(write(out, buf, n) != n){
-			warning("write to /dev/kbmap failed");
-			break;
-		}
-	close(in);
-	close(out);
-}

+ 0 - 87
sys/src/9/boot/boot.h

@@ -1,87 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-typedef struct Method	Method;
-struct Method
-{
-	char	*name;
-	void	(*config)(Method*);
-	int	(*connect)(void);
-	char	*arg;
-};
-enum
-{
-	Statsz=	256,
-	Nbarg=	16,
-};
-
-#define dprint(...) if(debugboot) fprint(2, __VA_ARGS__); else USED(debugboot)
-
-extern char*	bootdisk;		/* defined in ../$arch/boot$CONF.c */
-extern char*	rootdir;
-extern int	(*cfs)(int);
-extern int	cpuflag;
-extern char	cputype[];
-extern int	debugboot;
-extern int	fflag;
-extern int	kflag;
-extern Method	method[];		/* defined in ../$arch/boot$CONF.c */
-extern void	(*pword)(int, Method*);
-extern char	sys[];
-extern uchar	hostkey[];
-extern uchar	statbuf[Statsz];
-extern int	bargc;
-extern char	*bargv[Nbarg];
-extern int	pcload;
-
-/* libc equivalent */
-extern void	authentication(int);
-extern int	cache(int);
-extern char*	checkkey(Method*, char*, char*);
-extern int	chmod(char *file, int mode);
-extern void	fatal(char*);
-extern void	getpasswd(char*, int);
-extern void	key(int, Method*);
-extern int	mountusbparts(void);
-extern int	outin(char*, char*, int);
-extern int	plumb(char*, char*, int*, char*);
-extern int	readfile(char*, char*, int);
-extern int	readparts(void);
-extern long	readn(int, void*, long);
-extern void	run(char *file, ...);
-extern void	runv(char **argv);
-extern int	sendmsg(int, char*);
-extern void	setenv(char*, char*);
-extern void	settime(int, int, char*);
-extern void	srvcreate(char*, int);
-extern void	usbinit(int post);
-extern void	warning(char*);
-extern int	writefile(char*, char*, int);
-extern void	boot(int, char **);
-extern void	doauthenticate(int, Method*);
-extern int		old9p(int);
-extern int	parsefields(char*, char**, int, char*);
-
-/* methods */
-extern void	configtcp(Method*);
-extern int	connecttcp(void);
-
-extern void	configlocal(Method*);
-extern int	connectlocal(void);
-
-extern void	configpaq(Method*);
-extern int	connectpaq(void);
-
-extern void	configembed(Method*);
-extern int	connectembed(void);
-
-extern void	configip(int, char**, int);
-
-/* hack for passing authentication address */
-extern char	*authaddr;

+ 0 - 81
sys/src/9/boot/bootauth.c

@@ -1,81 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "../boot/boot.h"
-
-char	*authaddr;
-static void glenda(void);
-
-void
-authentication(int cpuflag)
-{
-	char *s;
-	char *argv[16], **av;
-	int ac;
-
-	if(access("/boot/factotum", AEXEC) < 0){
-		glenda();
-		return;
-	}
-
-	/* start agent */
-	ac = 0;
-	av = argv;
-	av[ac++] = "factotum";
-	if(getenv("debugfactotum"))
-		av[ac++] = "-p";
-	s = getenv("factotumopts");
-	if(s != nil && *s != '\0')
-		av[ac++] = s;
-//	av[ac++] = "-d";		/* debug traces */
-//	av[ac++] = "-D";		/* 9p messages */
-	if(cpuflag)
-		av[ac++] = "-S";
-	else
-		av[ac++] = "-u";
-	av[ac++] = "-sfactotum";
-	if(authaddr != nil){
-		av[ac++] = "-a";
-		av[ac++] = authaddr;
-	}
-	av[ac] = 0;
-	switch(fork()){
-	case -1:
-		fatal("starting factotum");
-	case 0:
-		exec("/boot/factotum", av);
-		fatal("execing /boot/factotum");
-	}
-
-	/* wait for agent to really be there */
-	while(access("/mnt/factotum", 0) < 0)
-		sleep(250);
-}
-
-static void
-glenda(void)
-{
-	int fd;
-	char *s;
-
-	s = getenv("user");
-	if(s == nil)
-		s = "glenda";
-
-	fd = open("#c/hostowner", OWRITE);
-	if(fd >= 0){
-		if(write(fd, s, strlen(s)) != strlen(s))
-			fprint(2, "setting #c/hostowner to %s: %r\n", s);
-		close(fd);
-	}
-}

+ 0 - 89
sys/src/9/boot/bootcache.c

@@ -1,89 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-uchar statbuf[Statsz];
-
-int
-cache(int fd)
-{
-	int argc, i, p[2];
-	char *argv[5], bd[32], buf[256], partition[64], *pp;
-
-	if(stat("/boot/cfs", statbuf, sizeof statbuf) < 0)
-		return fd;
-
-	*partition = 0;
-
-	bind("#S", "/dev", MAFTER);
-	readfile("#e/cfs", buf, sizeof(buf));
-	if(*buf){
-		argc = tokenize(buf, argv, 4);
-		for(i = 0; i < argc; i++){
-			if(strcmp(argv[i], "off") == 0)
-				return fd;
-			else if(stat(argv[i], statbuf, sizeof statbuf) >= 0){
-				strncpy(partition, argv[i], sizeof(partition)-1);
-				partition[sizeof(partition)-1] = 0;
-			}
-		}
-	}
-
-	if(*partition == 0){
-		readfile("#e/bootdisk", bd, sizeof(bd));
-		if(*bd){
-			if(pp = strchr(bd, ':'))
-				*pp = 0;
-			/* damned artificial intelligence */
-			i = strlen(bd);
-			if(strcmp("disk", &bd[i-4]) == 0)
-				bd[i-4] = 0;
-			else if(strcmp("fs", &bd[i-2]) == 0)
-				bd[i-2] = 0;
-			else if(strcmp("fossil", &bd[i-6]) == 0)
-				bd[i-6] = 0;
-			sprint(partition, "%scache", bd);
-			if(stat(partition, statbuf, sizeof statbuf) < 0)
-				*bd = 0;
-		}
-		if(*bd == 0){
-			sprint(partition, "%scache", bootdisk);
-			if(stat(partition, statbuf, sizeof statbuf) < 0)
-				return fd;
-		}
-	}
-
-	print("cfs...");
-	if(pipe(p)<0)
-		fatal("pipe");
-	switch(fork()){
-	case -1:
-		fatal("fork");
-	case 0:
-		close(p[1]);
-		dup(fd, 0);
-		close(fd);
-		dup(p[0], 1);
-		close(p[0]);
-		if(fflag)
-			execl("/boot/cfs", "bootcfs", "-rs", "-f", partition, 0);
-		else
-			execl("/boot/cfs", "bootcfs", "-s", "-f", partition, 0);
-		break;
-	default:
-		close(p[0]);
-		close(fd);
-		fd = p[1];
-		break;
-	}
-	return fd;
-}

+ 0 - 218
sys/src/9/boot/bootip.c

@@ -1,218 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <ip.h>
-
-#include "boot.h"
-
-static	uchar	fsip[IPaddrlen];
-static	uchar	auip[IPaddrlen];
-static	char	mpoint[32];
-
-static int isvalidip(uchar*);
-static void getndbvar(char *name, uchar *var, char *prompt);
-
-void
-configip(int bargc, char **bargv, int needfs)
-{
-	Waitmsg *w;
-	int argc, pid;
-	char **arg, **argv, *p;
-
-	fmtinstall('I', eipfmt);
-	fmtinstall('M', eipfmt);
-	fmtinstall('E', eipfmt);
-
-	arg = malloc((bargc+1) * sizeof(char*));
-	if(arg == nil)
-		fatal("malloc");
-	memmove(arg, bargv, bargc * sizeof(char*));
-	arg[bargc] = 0;
-
-	argc = bargc;
-	argv = arg;
-	strcpy(mpoint, "/net");
-	ARGBEGIN {
-	case 'x':
-		p = ARGF();
-		if(p != nil)
-			snprint(mpoint, sizeof(mpoint), "/net%s", p);
-		break;
-	case 'g':
-	case 'b':
-	case 'h':
-	case 'm':
-		p = ARGF();
-		USED(p);
-		break;
-	} ARGEND;
-
-	/* bind in an ip interface or two */
-	dprint("bind #I...");
-	if(bind("#I", mpoint, MAFTER) < 0)
-		fatal("bind #I");
-	dprint("bind #l0...");
-	if(access("#l0", 0) == 0 && bind("#l0", mpoint, MAFTER) < 0)
-		warning("bind #l0");
-	dprint("bind #l1...");
-	if(access("#l1", 0) == 0 && bind("#l1", mpoint, MAFTER) < 0)
-		warning("bind #l1");
-	dprint("bind #l2...");
-	if(access("#l2", 0) == 0 && bind("#l2", mpoint, MAFTER) < 0)
-		warning("bind #l2");
-	dprint("bind #l3...");
-	if(access("#l3", 0) == 0 && bind("#l3", mpoint, MAFTER) < 0)
-		warning("bind #l3");
-	werrstr("");
-
-	/* let ipconfig configure the first ip interface */
-	switch(pid = fork()){
-	case -1:
-		fatal("fork configuring ip: %r");
-	case 0:
-		dprint("starting ipconfig...");
-		exec("/boot/ipconfig", arg);
-		fatal("execing /boot/ipconfig: %r");
-	default:
-		break;
-	}
-
-	/* wait for ipconfig to finish */
-	dprint("waiting for dhcp...");
-	for(;;){
-		w = wait();
-		if(w != nil && w->pid == pid){
-			if(w->msg[0] != 0)
-				fatal(w->msg);
-			free(w);
-			break;
-		} else if(w == nil)
-			fatal("configuring ip");
-		free(w);
-	}
-	dprint("\n");
-
-	if(needfs) {  /* if we didn't get a file and auth server, query user */
-		getndbvar("fs", fsip, "filesystem IP address");
-		getndbvar("auth", auip, "authentication server IP address");
-	}
-}
-
-static void
-setauthaddr(char *proto, int port)
-{
-	char buf[128];
-
-	snprint(buf, sizeof buf, "%s!%I!%d", proto, auip, port);
-	authaddr = strdup(buf);
-}
-
-void
-configtcp(Method*)
-{
-	dprint("configip...");
-	configip(bargc, bargv, 1);
-	dprint("setauthaddr...");
-	setauthaddr("tcp", 567);
-}
-
-int
-connecttcp(void)
-{
-	int fd;
-	char buf[64];
-
-	snprint(buf, sizeof buf, "tcp!%I!564", fsip);
-	dprint("dial %s...", buf);
-	fd = dial(buf, 0, 0, 0);
-	if (fd < 0)
-		werrstr("dial %s: %r", buf);
-	return fd;
-}
-
-static int
-isvalidip(uchar *ip)
-{
-	if(ipcmp(ip, IPnoaddr) == 0)
-		return 0;
-	if(ipcmp(ip, v4prefix) == 0)
-		return 0;
-	return 1;
-}
-
-static void
-netenv(char *attr, uchar *ip)
-{
-	int fd, n;
-	char buf[128];
-
-	ipmove(ip, IPnoaddr);
-	snprint(buf, sizeof(buf), "#e/%s", attr);
-	fd = open(buf, OREAD);
-	if(fd < 0)
-		return;
-
-	n = read(fd, buf, sizeof(buf)-1);
-	close(fd);
-	if(n <= 0)
-		return;
-	buf[n] = 0;
-	if (parseip(ip, buf) == -1)
-		fprint(2, "netenv: can't parse ip %s\n", buf);
-}
-
-static void
-netndb(char *attr, uchar *ip)
-{
-	int fd, n, c;
-	char buf[1024];
-	char *p;
-
-	ipmove(ip, IPnoaddr);
-	snprint(buf, sizeof(buf), "%s/ndb", mpoint);
-	fd = open(buf, OREAD);
-	if(fd < 0)
-		return;
-	n = read(fd, buf, sizeof(buf)-1);
-	close(fd);
-	if(n <= 0)
-		return;
-	buf[n] = 0;
-	n = strlen(attr);
-	for(p = buf; ; p++){
-		p = strstr(p, attr);
-		if(p == nil)
-			break;
-		c = *(p-1);
-		if(*(p + n) == '=' && (p == buf || c == '\n' || c == ' ' || c == '\t')){
-			p += n+1;
-			if (parseip(ip, p) == -1)
-				fprint(2, "netndb: can't parse ip %s\n", p);
-			return;
-		}
-	}
-}
-
-static void
-getndbvar(char *name, uchar *var, char *prompt)
-{
-	char buf[64];
-
-	netndb(name, var);
-	if(!isvalidip(var))
-		netenv(name, var);
-	while(!isvalidip(var)){
-		buf[0] = 0;
-		outin(prompt, buf, sizeof buf);
-		if (parseip(var, buf) == -1)
-			fprint(2, "configip: can't parse %s ip %s\n", name, buf);
-	}
-}

+ 0 - 28
sys/src/9/boot/bootmkfile

@@ -1,28 +0,0 @@
-BOOTDIR=../boot
-BOOTLIB=$BOOTDIR/libboot.a$O
-
-BOOTFILES=\
-	bootauth.$O\
-	aux.$O\
-	boot.$O\
-	bootcache.$O\
-	bootip.$O\
-	local.$O\
-	embed.$O\
-	settime.$O\
-	paq.$O\
-	parts.$O\
-	printstub.$O\
-	usb.$O\
-
-$BOOTLIB(%.$O):N:	%.$O
-
-$BOOTLIB:	${BOOTFILES:%=$BOOTLIB(%)}
-	names=`{membername $newprereq}
-	ar vu $BOOTLIB $names
-	rm $names
-
-$BOOTFILES:	$BOOTDIR/boot.h
-
-%.$O:	$BOOTDIR/%.c
-	$CC -I$BOOTDIR $CFLAGS $BOOTDIR/$stem.c

+ 0 - 135
sys/src/9/boot/doauthenticate.c

@@ -1,135 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include "../boot/boot.h"
-
-static char *pbmsg = "AS protocol botch";
-static char *ccmsg = "can't connect to AS";
-
-long
-readn(int fd, void *buf, long len)
-{
-	int m, n;
-	char *p;
-
-	p = buf;
-	for(n = 0; n < len; n += m){
-		m = read(fd, p+n, len-n);
-		if(m <= 0)
-			return -1;
-	}
-	return n;
-}
-
-static char*
-fromauth(Method *mp, char *trbuf, char *tbuf)
-{
-	int afd;
-	char t;
-	char *msg;
-	static char error[2*ERRMAX];
-
-	if(mp->auth == 0)
-		fatal("no method for accessing auth server");
-	afd = (*mp->auth)();
-	if(afd < 0) {
-		sprint(error, "%s: %r", ccmsg);
-		return error;
-	}
-
-	if(write(afd, trbuf, TICKREQLEN) < 0 || read(afd, &t, 1) != 1){
-		close(afd);
-		sprint(error, "%s: %r", pbmsg);
-		return error;
-	}
-	switch(t){
-	case AuthOK:
-		msg = 0;
-		if(readn(afd, tbuf, 2*TICKETLEN) < 0) {
-			sprint(error, "%s: %r", pbmsg);
-			msg = error;
-		}
-		break;
-	case AuthErr:
-		if(readn(afd, error, ERRMAX) < 0) {
-			sprint(error, "%s: %r", pbmsg);
-			msg = error;
-		}
-		else {
-			error[ERRMAX-1] = 0;
-			msg = error;
-		}
-		break;
-	default:
-		msg = pbmsg;
-		break;
-	}
-
-	close(afd);
-	return msg;
-}
-
-void
-doauthenticate(int fd, Method *mp)
-{
-	char *msg;
-	char trbuf[TICKREQLEN];
-	char tbuf[2*TICKETLEN];
-
-	print("session...");
-	if(fsession(fd, trbuf, sizeof trbuf) < 0)
-		fatal("session command failed");
-
-	/* no authentication required? */
-	memset(tbuf, 0, 2*TICKETLEN);
-	if(trbuf[0] == 0)
-		return;
-
-	/* try getting to an auth server */
-	print("getting ticket...");
-	msg = fromauth(mp, trbuf, tbuf);
-	print("authenticating...");
-	if(msg == 0)
-		if(fauth(fd, tbuf) >= 0)
-			return;
-
-	/* didn't work, go for the security hole */
-	fprint(2, "no authentication server (%s), using your key as server key\n", msg);
-}
-
-char*
-checkkey(Method *mp, char *name, char *key)
-{
-	char *msg;
-	Ticketreq tr;
-	Ticket t;
-	char trbuf[TICKREQLEN];
-	char tbuf[TICKETLEN];
-
-	memset(&tr, 0, sizeof tr);
-	tr.type = AuthTreq;
-	strcpy(tr.authid, name);
-	strcpy(tr.hostid, name);
-	strcpy(tr.uid, name);
-	convTR2M(&tr, trbuf);
-	msg = fromauth(mp, trbuf, tbuf);
-	if(msg == ccmsg){
-		fprint(2, "boot: can't contact auth server, passwd unchecked\n");
-		return 0;
-	}
-	if(msg)
-		return msg;
-	convM2T(tbuf, &t, key);
-	if(t.num == AuthTc && strcmp(name, t.cuid)==0)
-		return 0;
-	return "no match";
-}

+ 0 - 83
sys/src/9/boot/embed.c

@@ -1,83 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-static char *paqfile;
-
-void
-configembed(Method *m)
-{
-	if(*sys == '/' || *sys == '#'){
-		/*
-		 *  if the user specifies the disk in the boot cmd or
-		 * 'root is from' prompt, use it
-		 */
-		paqfile = sys;
-	} else if(m->arg){
-		/*
-		 *  a default is supplied when the kernel is made
-		 */
-		paqfile = m->arg;
-	}
-}
-
-int
-connectembed(void)
-{
-	int i, p[2];
-	Dir *dir;
-	char **arg, **argp;
-
-	dir = dirstat("/boot/paqfs");
-	if(dir == nil)
-		return -1;
-	free(dir);
-
-	dir = dirstat(paqfile);
-	if(dir == nil || dir->mode & DMDIR)
-		return -1;
-	free(dir);
-
-	print("paqfs...");
-	if(bind("#c", "/dev", MREPL) < 0)
-		fatal("bind #c");
-	if(bind("#p", "/proc", MREPL) < 0)
-		fatal("bind #p");
-	if(pipe(p)<0)
-		fatal("pipe");
-	switch(fork()){
-	case -1:
-		fatal("fork");
-	case 0:
-		arg = malloc((bargc+5)*sizeof(char*));
-		argp = arg;
-		*argp++ = "/boot/paqfs";
-		*argp++ = "-iv";
-		*argp++ = paqfile;
-		for(i=1; i<bargc; i++)
-			*argp++ = bargv[i];
-		*argp = 0;
-
-		dup(p[0], 0);
-		dup(p[1], 1);
-		close(p[0]);
-		close(p[1]);
-		exec("/boot/paqfs", arg);
-		fatal("can't exec paqfs");
-	default:
-		break;
-	}
-	waitpid();
-
-	close(p[1]);
-	return p[0];
-}

+ 0 - 52
sys/src/9/boot/getpasswd.c

@@ -1,52 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-void
-getpasswd(char *p, int len)
-{
-	char c;
-	int i, n, fd;
-
-	fd = open("#c/consctl", OWRITE);
-	if(fd < 0)
-		fatal("can't open consctl; please reboot");
-	write(fd, "rawon", 5);
- Prompt:		
-	print("password: ");
-	n = 0;
-	for(;;){
-		do{
-			i = read(0, &c, 1);
-			if(i < 0)
-				fatal("can't read cons; please reboot");
-		}while(i == 0);
-		switch(c){
-		case '\n':
-			p[n] = '\0';
-			close(fd);
-			print("\n");
-			return;
-		case '\b':
-			if(n > 0)
-				n--;
-			break;
-		case 'u' - 'a' + 1:		/* cntrl-u */
-			print("\n");
-			goto Prompt;
-		default:
-			if(n < len - 1)
-				p[n++] = c;
-			break;
-		}
-	}
-}

+ 0 - 297
sys/src/9/boot/local.c

@@ -1,297 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-static char diskname[64];
-static char *disk;
-static char **args;
-
-void
-configlocal(Method *mp)
-{
-	char *p, *inibootdisk;
-	int n;
-
-	inibootdisk = getenv("bootdisk");
-	if(*sys == '/' || *sys == '#'){
-		/*
-		 *  if the user specifies the disk in the boot cmd or
-		 * 'root is from' prompt, use it
-		 */
-		disk = sys;
-	} else if(strncmp(argv0, "dksc(0,", 7) == 0){
-		/*
-		 *  on many mips arg0 of the boot command specifies the
-		 *  scsi logical unit number
-		 */
-		p = strchr(argv0, ',');
-		n = strtoul(p+1, 0, 10);
-		sprint(diskname, "#w%d/sd%dfs", n, n);
-		disk = diskname;
-	} else if(mp->arg){
-		/*
-		 *  a default is optionally supplied when the kernel is made
-		 */
-		disk = mp->arg;
-	} else if(inibootdisk != nil && *inibootdisk)
-		/* plan9.ini overrides default from config file */
-		disk = inibootdisk;
-	else if(bootdisk != nil && *bootdisk){
-		/*
-		 *  an environment variable from a pc's plan9.ini or
-		 *  from the mips nvram or generated by the kernel
-		 *  is the last resort.
-		 */
-		disk = bootdisk;
-	}
-
-	/* if we've decided on one, pass it on to all programs */
-	if(disk) {
-		bootdisk = disk;
-		setenv("bootdisk", bootdisk);
-	}
-}
-
-int
-connectlocalkfs(void)
-{
-	int i, pid, fd, p[2];
-	char partition[64];
-	char *dev;
-	char **arg, **argp;
-	Dir *d;
-
-	if(stat("/boot/kfs", statbuf, sizeof statbuf) < 0)
-		return -1;
-
-	dev = disk ? disk : bootdisk;
-	snprint(partition, sizeof partition, "%sfs", dev);
-	fd = open(partition, OREAD);
-	if(fd < 0){
-		strcpy(partition, dev);
-		fd = open(partition, OREAD);
-		if(fd < 0)
-			return -1;
-	}
-	/*
-	 * can't do this check -- might be some other server posing as kfs.
-	 *
-	memset(buf, 0, sizeof buf);
-	pread(fd, buf, 512, 0);
-	close(fd);
-	if(memcmp(buf+256, "kfs wren device\n", 16) != 0){
-		if(strstr(partition, "/fs"))
-			print("no kfs file system found on %s\n", partition);
-		return -1;
-	}
-	 *
-	 */
-	d = dirfstat(fd);
-	close(fd);
-	if(d == nil)
-		return -1;
-	if(d->mode&DMDIR){
-		free(d);
-		return -1;
-	}
-	free(d);
-
-	print("kfs...");
-	if(pipe(p)<0)
-		fatal("pipe");
-	switch(pid = fork()){
-	case -1:
-		fatal("fork");
-	case 0:
-		arg = malloc((bargc+5)*sizeof(char*));
-		argp = arg;
-		*argp++ = "kfs";
-		*argp++ = "-f";
-		*argp++ = partition;
-		*argp++ = "-s";
-		for(i=1; i<bargc; i++)
-			*argp++ = bargv[i];
-		*argp = 0;
-
-		dup(p[0], 0);
-		dup(p[1], 1);
-		close(p[0]);
-		close(p[1]);
-		exec("/boot/kfs", arg);
-		fatal("can't exec kfs");
-	default:
-		break;
-	}
-	for(;;){
-		if((i = waitpid()) == -1)
-			fatal("waitpid for kfs failed");
-		if(i == pid)
-			break;
-	}
-
-	close(p[1]);
-	return p[0];
-}
-
-void
-runv(char **argv)
-{
-	int i, pid;
-
-	switch(pid = fork()){
-	case -1:
-		fatal("fork");
-	case 0:
-		exec(argv[0], argv);
-		fatal(smprint("can't exec %s: %r", argv[0]));
-	default:
-		while ((i = waitpid()) != pid && i != -1)
-			;
-		if(i == -1)
-			fatal(smprint("wait failed running %s", argv[0]));
-	}
-}
-
-void
-run(char *file, ...)
-{
-	runv(&file);
-}
-
-static int
-print1(int fd, char *s)
-{
-	return write(fd, s, strlen(s));
-}
-
-void
-configloopback(void)
-{
-	int fd;
-
-	if((fd = open("/net/ipifc/clone", ORDWR)) < 0){
-		bind("#I", "/net", MAFTER);
-		if((fd = open("/net/ipifc/clone", ORDWR)) < 0)
-			fatal("open /net/ipifc/clone for loopback");
-	}
-	if(print1(fd, "bind loopback /dev/null") < 0
-	|| print1(fd, "add 127.0.0.1 255.255.255.255") < 0)
-		fatal("write /net/ipifc/clone for loopback");
-}
-
-int
-connectlocalfossil(void)
-{
-	int fd;
-	char *venti, *f[32], *p;
-	int nf;
-	char partition[128], buf[512];
-	char *dev;
-
-	if(stat("/boot/fossil", statbuf, sizeof statbuf) < 0)
-		return -1;
-
-	/* look for fossil partition */
-	dev = disk ? disk : bootdisk;
-	snprint(partition, sizeof partition, "%sfossil", dev);
-	fd = open(partition, OREAD);
-	if(fd < 0){
-		strcpy(partition, dev);
-		fd = open(partition, OREAD);
-		if(fd < 0)
-			return -1;
-	}
-	memset(buf, 0, sizeof buf);
-	pread(fd, buf, 512, 127*1024);
-	close(fd);
-	if(memcmp(buf, "fossil config\n", 14) != 0){
-		if(strstr(partition, "/fossil"))
-			print("no fossil config found on %s\n", partition);
-		return -1;
-	}
-
-	settime(1, -1, nil);
-
-	/* make venti available.  give it 20% of free memory. */
-	if((venti = getenv("venti")) && (nf = tokenize(venti, f, nelem(f)))){
-		if((fd = open(f[0], OREAD)) >= 0){
-			print("venti...");
-			memset(buf, 0, sizeof buf);
-			pread(fd, buf, 512, 248*1024);
-			close(fd);
-			if(memcmp(buf, "venti config\n", 13) != 0){
-				print("no venti config found on %s\n", f[0]);
-				return -1;
-			}
-			if(stat("/boot/venti", statbuf, sizeof statbuf) < 0){
-				print("/boot/venti does not exist\n");
-				return -1;
-			}
-			switch(nf){
-			case 1:
-				f[1] = "tcp!127.1!17034";
-			case 2:
-				f[2] = "tcp!127.1!8000";
-			}
-			configloopback();
-			run("/boot/venti", "-m", "20", "-c", f[0],
-				"-a", f[1], "-h", f[2], nil);
-			/*
-			 * If the announce address is tcp!*!foo, then set
-			 * $venti to tcp!127.1!foo instead, which is actually dialable.
-			 */
-			if((p = strstr(f[1], "!*!")) != 0){
-				*p = 0;
-				snprint(buf, sizeof buf, "%s!127.1!%s", f[1], p+3);
-				f[1] = buf;
-			}
-			setenv("venti", f[1]);
-		}else{
-			/* set up the network so we can talk to the venti server */
-			/* this is such a crock. */
-			configip(nf, f, 0);
-			setenv("venti", f[0]);
-		}
-	}
-
-	/* start fossil.  give it 20% of free memory. */
-	print("fossil(%s)...", partition);
-	run("/boot/fossil", "-m", "20", "-f", partition,
-		"-c", "srv -A fboot", "-c", "srv -p fscons", nil);
-	fd = open("#s/fboot", ORDWR);
-	if(fd < 0){
-		warning("open #s/fboot");
-		return -1;
-	}
-	remove("#s/fboot");  /* we'll repost fd as #s/boot after fversion(fd) */
-	return fd;
-}
-
-int
-connectlocal(void)
-{
-	int fd;
-
-	if(bind("#c", "/dev", MREPL) < 0)
-		fatal("bind #c");
-	if(bind("#p", "/proc", MREPL) < 0)
-		fatal("bind #p");
-	bind("#S", "/dev", MAFTER);
-	bind("#k", "/dev", MAFTER);
-	bind("#u", "/dev", MAFTER);
-	bind("#æ", "/dev", MAFTER);
-	mountusbparts();	/* make partfs partitions visible again */
-
-	if((fd = connectlocalfossil()) < 0)
-		fd = connectlocalkfs();
-	return fd;
-}

+ 0 - 101
sys/src/9/boot/mkboot

@@ -1,101 +0,0 @@
-#!/bin/rc
-#
-#  this file configures a boot program (/boot) for a kernel.
-#
-if(! ~ $#* 1){
-	echo usage: mkboot file >[1=2]
-	exit 1
-}
-
-cat <<'---'
-#include <u.h>
-#include <libc.h>
-#include "../boot/boot.h"
-
-Method	method[]={
----
-
-#
-#  configure all remote methods, i.e. all methods in the 'boot' section
-#
-#  EXAMPLE
-#	boot
-#		incon
-#		9600
-#		19200
-#
-../port/mkextract boot 0 $* | awk '{
-	printf "	{ \""  "" $1 "\", "\
-	"config" $1 ", "\
-	"connect" $1 ", "
-	print fieldn(2) " },"
-	}
-
-	func fieldn(n,	s,i)
-	{
-		s = $0
-		while (n > 1) {
-			sub(/^[ \t]*/, "", s)
-			if (substr(s, 1, 1) == "\"") {
-				sub(/^"[^\"]*"/, "", s)
-			} else {
-				sub(/^[^ \t]*/, "", s)
-			}
-			n--
-		}
-		sub(/^[ \t]*/, "", s)
-		if (substr(s, 1, 1) == "\"") {
-			i = index(substr(s, 2), "\"")
-			if (i > 0)
-				return substr(s, 1, i+1)
-			else
-				return s
-		} else {
-			sub(/[ \t].*/, "", s)
-			return s
-		}
-	}'
-
-cat <<'---'
-	{ 0 },
-};
----
-
-awk '
-	BEGIN	{ cpuflag = 0; bootprog = "boot"; bootdisk = "#S/sdC0/"; rootdir = "/root"; }
-	$0 ~ "^boot" && $2=="cpu"\
-		{ cpuflag = 1
-		  if(NF == 4 && $3 == "boot")
-			bootdisk = $4
-		}
-	$0 ~ "^boot" && $2=="rootdir" && NF==3\
-		{ rootdir = $3 }
-	$0 ~ "^boot" && ($2=="bboot" || $2=="romboot" || $2=="dosboot")\
-		{ cpuflag = 1;  bootprog = $2; }
-	$0 ~ "^boot" && $2=="boot" && NF==3\
-		{ bootdisk = $3 }
-	END 	{ print "int cpuflag = " cpuflag ";"
-		  print "char* rootdir = \"" rootdir "\";"
-		  print "char* bootdisk = \"" bootdisk "\";"
-		  print "extern void " bootprog "(int, char**);"
-		  print "void"
-		  print "main(int argc, char **argv)"
-		  print "{"
-		  print "\t" bootprog "(argc, argv);"
-		  print "}"
-		}
-' $1
-
-#
-#  configure in a cache file system if a 
-# /386/bin/root appears in the bootdir section.
-#
-../port/mkextract bootdir 0 $* | awk '
-	BEGIN			{ cfs = 0 }
-	$1 ~ "bin/cfs$"	{ cfs = 1 }
-	END			{ if(cfs)
-					print "int (*cfs)(int) = cache;"
-				  else
-					print "int (*cfs)(int) = 0;"
-				}
-	'

+ 0 - 61
sys/src/9/boot/nopsession.c

@@ -1,61 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "../boot/boot.h"
-
-static Fcall	hdr;
-
-static void
-rpc(int fd, int type)
-{
-	int n, l;
-	char buf[128], *p;
-
-	hdr.type = type;
-	hdr.tag = NOTAG;
-	n = convS2M(&hdr, buf);
-	if(write(fd, buf, n) != n)
-		fatal("write rpc");
-
-	print("...");
-	p = buf;
-	l = 0;
-	while(l < 3) {
-		n = read(fd, p, 3);
-		if(n <= 0)
-			fatal("read rpc");
-		if(n == 2 && l == 0 && buf[0] == 'O' && buf[1] == 'K')
-			continue;
-		p += n;
-		l += n;
-	}
-	if(convM2S(buf, &hdr, n) == 0){
-		print("%ux %ux %ux\n", buf[0], buf[1], buf[2]);
-		fatal("rpc format");
-	}
-	if(hdr.tag != NOTAG)
-		fatal("rpc tag not NOTAG");
-	if(hdr.type == Rerror){
-		print("error %s;", hdr.ename);
-		fatal("remote error");
-	}
-	if(hdr.type != type+1)
-		fatal("not reply");
-}
-
-void
-nop(int fd)
-{
-	print("nop");
-	rpc(fd, Tnop);
-}

+ 0 - 76
sys/src/9/boot/paq.c

@@ -1,76 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-char *fparts[] =
-{
-	"add bootldr	0x0000000 0x0040000",
-	"add params	0x0040000 0x0080000",
-	"add kernel	0x0080000 0x0140000",
-	"add user	0x0140000 0x0200000",
-	"add ramdisk	0x0200000 0x0600000",
-};
-
-void
-configpaq(Method*)
-{
-	int fd;
-	int i;
-
-	if(bind("#F", "/dev", MAFTER) < 0)
-		fatal("bind #c");
-	if(bind("#p", "/proc", MREPL) < 0)
-		fatal("bind #p");
-	fd = open("/dev/flash/flashctl", OWRITE);
-	if(fd < 0)
-		fatal("opening flashctl");
-	for(i = 0; i < nelem(fparts); i++)
-		if(fprint(fd, fparts[i]) < 0)
-			fatal(fparts[i]);
-	close(fd);
-}
-
-int
-connectpaq(void)
-{
-	int  p[2];
-	char **arg, **argp;
-
-	print("paq...");
-	if(pipe(p)<0)
-		fatal("pipe");
-	switch(fork()){
-	case -1:
-		fatal("fork");
-	case 0:
-		arg = malloc(10*sizeof(char*));
-		argp = arg;
-		*argp++ = "paqfs";
-		*argp++ = "-v";
-		*argp++ = "-i";
-		*argp++ = "/dev/flash/ramdisk";
-		*argp = 0;
-
-		dup(p[0], 0);
-		dup(p[1], 1);
-		close(p[0]);
-		close(p[1]);
-		exec("/boot/paqfs", arg);
-		fatal("can't exec paqfs");
-	default:
-		break;
-	}
-	waitpid();
-
-	close(p[1]);
-	return p[0];
-}

+ 0 - 616
sys/src/9/boot/parts.c

@@ -1,616 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * read disk partition tables, intended for early use on systems
- * that don't use 9load.  borrowed from 9load.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include <bio.h>
-#include "../boot/boot.h"
-
-typedef struct Fs Fs;
-#include "/sys/src/boot/pc/dosfs.h"
-
-#define	GSHORT(p)	(((p)[1]<<8)|(p)[0])
-#define	GLONG(p)	((GSHORT((p)+2)<<16)|GSHORT(p))
-
-#define trace 0
-
-enum {
-	parttrace = 0,
-
-	Npart = 64,
-	SDnpart = Npart,
-
-	Maxsec = 2048,
-	Cdsec = 2048,
-	Normsec = 512,			/* disks */
-
-	NAMELEN = 256,			/* hack */
-};
-
-typedef struct SDpart SDpart;
-typedef struct SDunit SDunit;
-
-typedef struct SDpart {
-	uvlong	start;
-	uvlong	end;
-	char	name[NAMELEN];
-	int	valid;
-} SDpart;
-
-typedef struct SDunit {
-	int	ctl;			/* fds */
-	int	data;
-
-	char	name[NAMELEN];
-
-	uvlong	sectors;
-	ulong	secsize;
-	SDpart*	part;
-	int	npart;			/* of valid partitions */
-} SDunit;
-
-static uchar *mbrbuf, *partbuf;
-
-static void
-sdaddpart(SDunit* unit, char* name, uvlong start, uvlong end)
-{
-	SDpart *pp;
-	int i, partno;
-
-	if(parttrace)
-		print("add %d %s %s %lld %lld\n", unit->npart, unit->name, name, start, end);
-	/*
-	 * Check name not already used
-	 * and look for a free slot.
-	 */
-	if(unit->part != nil){
-		partno = -1;
-		for(i = 0; i < SDnpart; i++){
-			pp = &unit->part[i];
-			if(!pp->valid){
-				if(partno == -1)
-					partno = i;
-				break;
-			}
-			if(strcmp(name, pp->name) == 0){
-				if(pp->start == start && pp->end == end){
-					if(parttrace)
-						print("already present\n");
-					return;
-				}
-			}
-		}
-	}else{
-		if((unit->part = malloc(sizeof(SDpart)*SDnpart)) == nil){
-			if(parttrace)
-				print("malloc failed\n");
-			return;
-		}
-		partno = 0;
-	}
-
-	/*
-	 * Check there is a free slot and size and extent are valid.
-	 */
-	if(partno == -1 || start > end || end > unit->sectors){
-		print("cannot add %s!%s [%llud,%llud) to disk [0,%llud): %s\n",
-			unit->name, name, start, end, unit->sectors, 
-			partno==-1 ? "no free partitions" : "partition boundaries out of range");
-		return;
-	}
-	pp = &unit->part[partno];
-	pp->start = start;
-	pp->end = end;
-	strncpy(pp->name, name, NAMELEN);
-	pp->valid = 1;
-	unit->npart++;
-
-	/* update devsd's in-memory partition table */
-	if (fprint(unit->ctl, "part %s %lld %lld\n", name, start, end) < 0)
-		fprint(2, "can't update %s's devsd partition table for %s: %r\n",
-			unit->name, name);
-	dprint("part %s %lld %lld\n", name, start, end);
-}
-
-static long
-sdread(SDunit *unit, SDpart *pp, void* va, long len, vlong off)
-{
-	long l, secsize;
-	uvlong bno, nb;
-
-	/*
-	 * Check the request is within partition bounds.
-	 */
-	secsize = unit->secsize;
-	if (secsize == 0)
-		sysfatal("sdread: zero sector size");
-	bno = off/secsize + pp->start;
-	nb = (off+len+secsize-1)/secsize + pp->start - bno;
-	if(bno+nb > pp->end)
-		nb = pp->end - bno;
-	if(bno >= pp->end || nb == 0)
-		return 0;
-
-	seek(unit->data, bno * secsize, 0);
-	assert(va);				/* "sdread" */
-	l = read(unit->data, va, len);
-	if (l < 0)
-		return 0;
-	return l;
-}
-
-static int
-sdreadblk(SDunit *unit, SDpart *part, void *a, vlong off, int mbr)
-{
-	uchar *b;
-
-	assert(a);			/* sdreadblk */
-	if(sdread(unit, part, a, unit->secsize, off) != unit->secsize){
-		if(trace)
-			print("%s: read %lud at %lld failed\n", unit->name,
-				unit->secsize, (vlong)part->start*unit->secsize+off);
-		return -1;
-	}
-	b = a;
-	if(mbr && (b[0x1FE] != 0x55 || b[0x1FF] != 0xAA)){
-		if(trace)
-			print("%s: bad magic %.2ux %.2ux at %lld\n",
-				unit->name, b[0x1FE], b[0x1FF],
-				(vlong)part->start*unit->secsize+off);
-		return -1;
-	}
-	return 0;
-}
-
-/*
- *  read partition table.  The partition table is just ascii strings.
- */
-#define MAGIC "plan9 partitions"
-static void
-oldp9part(SDunit *unit)
-{
-	SDpart *pp;
-	char *field[3], *line[Npart+1];
-	ulong n;
-	uvlong start, end;
-	int i;
-
-	/*
-	 *  We have some partitions already.
-	 */
-	pp = &unit->part[unit->npart];
-
-	/*
-	 * We prefer partition tables on the second to last sector,
-	 * but some old disks use the last sector instead.
-	 */
-	strcpy(pp->name, "partition");
-	pp->start = unit->sectors - 2;
-	pp->end = unit->sectors - 1;
-
-	dprint("oldp9part %s\n", unit->name);
-	if(sdreadblk(unit, pp, partbuf, 0, 0) < 0)
-		return;
-
-	if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0) {
-		/* not found on 2nd last sector; look on last sector */
-		pp->start++;
-		pp->end++;
-		if(sdreadblk(unit, pp, partbuf, 0, 0) < 0)
-			return;
-		if(strncmp((char*)partbuf, MAGIC, sizeof(MAGIC)-1) != 0)
-			return;
-		print("%s: using old plan9 partition table on last sector\n", unit->name);
-	}else
-		print("%s: using old plan9 partition table on 2nd-to-last sector\n", unit->name);
-
-	/* we found a partition table, so add a partition partition */
-	unit->npart++;
-	partbuf[unit->secsize-1] = '\0';
-
-	/*
-	 * parse partition table
-	 */
-	n = gettokens((char*)partbuf, line, Npart+1, "\n");
-	if(n && strncmp(line[0], MAGIC, sizeof(MAGIC)-1) == 0){
-		for(i = 1; i < n && unit->npart < SDnpart; i++){
-			if(gettokens(line[i], field, 3, " ") != 3)
-				break;
-			start = strtoull(field[1], 0, 0);
-			end = strtoull(field[2], 0, 0);
-			if(start >= end || end > unit->sectors)
-				break;
-			sdaddpart(unit, field[0], start, end);
-		}
-	}	
-}
-
-static SDpart*
-sdfindpart(SDunit *unit, char *name)
-{
-	int i;
-
-	if(parttrace)
-		print("findpart %d %s %s: ", unit->npart, unit->name, name);
-	for(i=0; i<unit->npart; i++) {
-		if(parttrace)
-			print("%s...", unit->part[i].name);
-		if(strcmp(unit->part[i].name, name) == 0){
-			if(parttrace)
-				print("\n");
-			return &unit->part[i];
-		}
-	}
-	if(parttrace)
-		print("not found\n");
-	return nil;
-}
-
-/*
- * look for a plan 9 partition table on drive `unit' in the second
- * sector (sector 1) of partition `name'.
- * if found, add the partitions defined in the table.
- */
-static void
-p9part(SDunit *unit, char *name)
-{
-	SDpart *p;
-	char *field[4], *line[Npart+1];
-	uvlong start, end;
-	int i, n;
-
-	dprint("p9part %s %s\n", unit->name, name);
-	p = sdfindpart(unit, name);
-	if(p == nil)
-		return;
-
-	if(sdreadblk(unit, p, partbuf, unit->secsize, 0) < 0)
-		return;
-	partbuf[unit->secsize-1] = '\0';
-
-	if(strncmp((char*)partbuf, "part ", 5) != 0)
-		return;
-
-	n = gettokens((char*)partbuf, line, Npart+1, "\n");
-	if(n == 0)
-		return;
-	for(i = 0; i < n && unit->npart < SDnpart; i++){
-		if(strncmp(line[i], "part ", 5) != 0)
-			break;
-		if(gettokens(line[i], field, 4, " ") != 4)
-			break;
-		start = strtoull(field[2], 0, 0);
-		end   = strtoull(field[3], 0, 0);
-		if(start >= end || end > unit->sectors)
-			break;
-		sdaddpart(unit, field[1], p->start+start, p->start+end);
-	}
-}
-
-static int
-isdos(int t)
-{
-	return t==FAT12 || t==FAT16 || t==FATHUGE || t==FAT32 || t==FAT32X;
-}
-
-static int
-isextend(int t)
-{
-	return t==EXTEND || t==EXTHUGE || t==LEXTEND;
-}
-
-/* 
- * Fetch the first dos and all plan9 partitions out of the MBR partition table.
- * We return -1 if we did not find a plan9 partition.
- */
-static int
-mbrpart(SDunit *unit)
-{
-	Dospart *dp;
-	uvlong taboffset, start, end;
-	uvlong firstxpart, nxtxpart;
-	int havedos, i, nplan9;
-	char name[10];
-
-	taboffset = 0;
-	dp = (Dospart*)&mbrbuf[0x1BE];
-	{
-		/* get the MBR (allowing for DMDDO) */
-		if(sdreadblk(unit, &unit->part[0], mbrbuf,
-		    (vlong)taboffset * unit->secsize, 1) < 0)
-			return -1;
-		for(i=0; i<4; i++)
-			if(dp[i].type == DMDDO) {
-				if(trace)
-					print("DMDDO partition found\n");
-				taboffset = 63;
-				if(sdreadblk(unit, &unit->part[0], mbrbuf,
-				    (vlong)taboffset * unit->secsize, 1) < 0)
-					return -1;
-				i = -1;	/* start over */
-			}
-	}
-
-	/*
-	 * Read the partitions, first from the MBR and then
-	 * from successive extended partition tables.
-	 */
-	nplan9 = 0;
-	havedos = 0;
-	firstxpart = 0;
-	for(;;) {
-		if(sdreadblk(unit, &unit->part[0], mbrbuf,
-		    (vlong)taboffset * unit->secsize, 1) < 0)
-			return -1;
-		if(trace) {
-			if(firstxpart)
-				print("%s ext %llud ", unit->name, taboffset);
-			else
-				print("%s mbr ", unit->name);
-		}
-		nxtxpart = 0;
-		for(i=0; i<4; i++) {
-			if(trace)
-				print("dp %d...", dp[i].type);
-			start = taboffset+GLONG(dp[i].start);
-			end = start+GLONG(dp[i].len);
-
-			if(dp[i].type == PLAN9) {
-				if(nplan9 == 0)
-					strcpy(name, "plan9");
-				else
-					sprint(name, "plan9.%d", nplan9);
-				sdaddpart(unit, name, start, end);
-				p9part(unit, name);
-				nplan9++;
-			}
-
-			/*
-			 * We used to take the active partition (and then the first
-			 * when none are active).  We have to take the first here,
-			 * so that the partition we call ``dos'' agrees with the
-			 * partition disk/fdisk calls ``dos''. 
-			 */
-			if(havedos==0 && isdos(dp[i].type)){
-				havedos = 1;
-				sdaddpart(unit, "dos", start, end);
-			}
-
-			/* nxtxpart is relative to firstxpart (or 0), not taboffset */
-			if(isextend(dp[i].type)){
-				nxtxpart = start-taboffset+firstxpart;
-				if(trace)
-					print("link %llud...", nxtxpart);
-			}
-		}
-		if(trace)
-			print("\n");
-
-		if(!nxtxpart)
-			break;
-		if(!firstxpart)
-			firstxpart = nxtxpart;
-		taboffset = nxtxpart;
-	}	
-	return nplan9 ? 0 : -1;
-}
-
-/*
- * To facilitate booting from CDs, we create a partition for
- * the boot floppy image embedded in a bootable CD.
- */
-static int
-part9660(SDunit *unit)
-{
-	uchar buf[Maxsec];
-	ulong a, n;
-	uchar *p;
-
-	if(unit->secsize != Cdsec)
-		return -1;
-
-	if(sdread(unit, &unit->part[0], buf, Cdsec, 17*Cdsec) < 0)
-		return -1;
-
-	if(buf[0] || strcmp((char*)buf+1, "CD001\x01EL TORITO SPECIFICATION") != 0)
-		return -1;
-
-	
-	p = buf+0x47;
-	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
-	if(sdread(unit, &unit->part[0], buf, Cdsec, a*Cdsec) < 0)
-		return -1;
-
-	if(memcmp(buf, "\x01\x00\x00\x00", 4) != 0
-	|| memcmp(buf+30, "\x55\xAA", 2) != 0
-	|| buf[0x20] != 0x88)
-		return -1;
-
-	p = buf+0x28;
-	a = p[0] | (p[1]<<8) | (p[2]<<16) | (p[3]<<24);
-
-	switch(buf[0x21]){
-	case 0x01:
-		n = 1200*1024;
-		break;
-	case 0x02:
-		n = 1440*1024;
-		break;
-	case 0x03:
-		n = 2880*1024;
-		break;
-	default:
-		return -1;
-	}
-	n /= Cdsec;
-
-	print("found partition %s!cdboot; %lud+%lud\n", unit->name, a, n);
-	sdaddpart(unit, "cdboot", a, a+n);
-	return 0;
-}
-
-enum {
-	NEW = 1<<0,
-	OLD = 1<<1
-};
-
-/*
- * read unit->data to look for partition tables.
- * if found, stash partitions in environment and write them to ctl too.
- */
-static void
-partition(SDunit *unit)
-{
-	int type;
-	char *p;
-
-	if(unit->part == 0)
-		return;
-
-	if(part9660(unit) == 0)
-		return;
-
-	p = getenv("partition");
-	if(p != nil && strncmp(p, "new", 3) == 0)
-		type = NEW;
-	else if(p != nil && strncmp(p, "old", 3) == 0)
-		type = OLD;
-	else
-		type = NEW|OLD;
-
-	if(mbrbuf == nil) {
-		mbrbuf = malloc(Maxsec);
-		partbuf = malloc(Maxsec);
-		if(mbrbuf==nil || partbuf==nil) {
-			free(mbrbuf);
-			free(partbuf);
-			partbuf = mbrbuf = nil;
-			return;
-		}
-	}
-
-	/*
-	 * there might be no mbr (e.g. on a very large device), so look for
-	 * a bare plan 9 partition table if mbrpart fails.
-	 */
-	if((type & NEW) && mbrpart(unit) >= 0){
-		/* nothing to do */
-	}
-	else if (type & NEW)
-		p9part(unit, "data");
-	else if(type & OLD)
-		oldp9part(unit);
-}
-
-static void
-rdgeom(SDunit *unit)
-{
-	char *line;
-	char *flds[5];
-	Biobuf bb;
-	Biobuf *bp;
-	static char geom[] = "geometry ";
-
-	bp = &bb;
-	seek(unit->ctl, 0, 0);
-	Binit(bp, unit->ctl, OREAD);
-	while((line = Brdline(bp, '\n')) != nil){
-		line[Blinelen(bp) - 1] = '\0';
-		if (strncmp(line, geom, sizeof geom - 1) == 0)
-			break;
-	}
-	if (line != nil && tokenize(line, flds, nelem(flds)) >= 3) {
-		unit->sectors = atoll(flds[1]);
-		unit->secsize = atoll(flds[2]);
-	}
-	Bterm(bp);
-	seek(unit->ctl, 0, 0);
-}
-
-static void
-setpartitions(char *name, int ctl, int data)
-{
-	SDunit sdunit;
-	SDunit *unit;
-	SDpart *part0;
-
-	unit = &sdunit;
-	memset(unit, 0, sizeof *unit);
-	unit->ctl = ctl;
-	unit->data = data;
-
-	unit->secsize = Normsec;	/* default: won't work for CDs */
-	unit->sectors = ~0ull;
-	rdgeom(unit);
-	strncpy(unit->name, name, sizeof unit->name);
-	unit->part = mallocz(sizeof(SDpart) * SDnpart, 1);
-
-	part0 = &unit->part[0];
-	part0->end = unit->sectors - 1;
-	strcpy(part0->name, "data");
-	part0->valid = 1;
-	unit->npart++;
-
-	mbrbuf = malloc(Maxsec);
-	partbuf = malloc(Maxsec);
-	partition(unit);
-	free(unit->part);
-}
-
-/*
- * read disk partition tables so that readnvram via factotum
- * can see them.
- */
-int
-readparts(void)
-{
-	int i, n, ctl, data, fd;
-	char *name, *ctlname, *dataname;
-	Dir *dir;
-
-	fd = open("/dev", OREAD);
-	if(fd < 0)
-		return -1;
-	n = dirreadall(fd, &dir);
-	close(fd);
-
-	for(i = 0; i < n; i++) {
-		name = dir[i].name;
-		if (strncmp(name, "sd", 2) != 0)
-			continue;
-
-		ctlname  = smprint("/dev/%s/ctl", name);
-		dataname = smprint("/dev/%s/data", name);
-		if (ctlname == nil || dataname == nil) {
-			free(ctlname);
-			free(dataname);
-			continue;
-		}
-
-		ctl  = open(ctlname, ORDWR);
-		data = open(dataname, OREAD);
-		free(ctlname);
-		free(dataname);
-
-		if (ctl >= 0 && data >= 0)
-			setpartitions(dataname, ctl, data);
-		close(ctl);
-		close(data);
-	}
-	free(dir);
-	return 0;
-}

+ 0 - 31
sys/src/9/boot/printstub.c

@@ -1,31 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-
-static Lock fmtl;
-
-void
-_fmtlock(void)
-{
-	lock(&fmtl);
-}
-
-void
-_fmtunlock(void)
-{
-	unlock(&fmtl);
-}
-
-int
-_efgfmt(Fmt*)
-{
-	return -1;
-}

+ 0 - 59
sys/src/9/boot/sac.c

@@ -1,59 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <../boot/boot.h>
-
-/*
- * HACK - take over from boot since file system is not
- * available on a pipe
- */
-
-void
-configsac(Method *mp)
-{
-	int fd;
-	char cmd[64];
-
-	USED(mp);
-
-	/*
-	 *  create the name space, mount the root fs
-	 */
-	if(bind("/", "/", MREPL) < 0)
-		fatal("bind /");
-	if(bind("#C", "/", MAFTER) < 0)
-		fatal("bind /");
-
-	/* fixed sysname - enables correct namespace file */
-	fd = open("#c/sysname", OWRITE);
-	if(fd < 0)
-		fatal("open sysname");
-	write(fd, "brick", 5);
-	close(fd);
-
-	fd = open("#c/hostowner", OWRITE);
-	if(fd < 0)
-		fatal("open sysname");
-	write(fd, "brick", 5);
-	close(fd);
-
-	sprint(cmd, "/%s/init", cputype);
-	print("starting %s\n", cmd);
-	execl(cmd, "init", "-c", 0);
-	fatal(cmd);
-}
-
-int
-connectsac(void)
-{
-	/* does not get here */
-	return -1;
-}

+ 0 - 159
sys/src/9/boot/settime.c

@@ -1,159 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "../boot/boot.h"
-
-static long lusertime(char*);
-
-char *timeserver = "#s/boot";
-
-void
-settime(int islocal, int afd, char *rp)
-{
-	int n, f;
-	Dir dir[2];
-	char timebuf[64];
-	static int timeset;
-
-	if(timeset)
-		return;
-	print("time...");
-	if(islocal){
-		/*
-		 *  set the time from the real time clock
-		 */
-		f = open("#r/rtc", ORDWR);
-		if(f >= 0){
-			if((n = read(f, timebuf, sizeof(timebuf)-1)) > 0){
-				timebuf[n] = '\0';
-				timeset = 1;
-			}
-			close(f);
-		}else do{
-			strcpy(timebuf, "yymmddhhmm[ss]");
-			outin("\ndate/time ", timebuf, sizeof(timebuf));
-		}while((timeset=lusertime(timebuf)) <= 0);
-	}
-	if(timeset == 0){
-		/*
-		 *  set the time from the access time of the root
-		 */
-		f = open(timeserver, ORDWR);
-		if(f < 0)
-			return;
-		if(mount(f, afd, "/tmp", MREPL, rp) < 0){
-			warning("settime mount");
-			close(f);
-			return;
-		}
-		close(f);
-		if(stat("/tmp", statbuf, sizeof statbuf) < 0)
-			fatal("stat");
-		convM2D(statbuf, sizeof statbuf, &dir[0], (char*)&dir[1]);
-		sprint(timebuf, "%ld", dir[0].atime);
-		unmount(0, "/tmp");
-	}
-
-	f = open("#c/time", OWRITE);
-	if(write(f, timebuf, strlen(timebuf)) < 0)
-		warning("can't set #c/time");
-	close(f);
-	print("\n");
-}
-
-#define SEC2MIN 60L
-#define SEC2HOUR (60L*SEC2MIN)
-#define SEC2DAY (24L*SEC2HOUR)
-
-int
-g2(char **pp)
-{
-	int v;
-
-	v = 10*((*pp)[0]-'0') + (*pp)[1]-'0';
-	*pp += 2;
-	return v;
-}
-
-/*
- *  days per month plus days/year
- */
-static	int	dmsize[] =
-{
-	365, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-static	int	ldmsize[] =
-{
-	366, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-/*
- *  return the days/month for the given year
- */
-static int *
-yrsize(int y)
-{
-
-	if((y%4) == 0 && ((y%100) != 0 || (y%400) == 0))
-		return ldmsize;
-	else
-		return dmsize;
-}
-
-/*
- *  compute seconds since Jan 1 1970
- */
-static long
-lusertime(char *argbuf)
-{
-	char *buf;
-	ulong secs;
-	int i, y, m;
-	int *d2m;
-
-	buf = argbuf;
-	i = strlen(buf);
-	if(i != 10 && i != 12)
-		return -1;
-	secs = 0;
-	y = g2(&buf);
-	m = g2(&buf);
-	if(y < 70)
-		y += 2000;
-	else
-		y += 1900;
-
-	/*
-	 *  seconds per year
-	 */
-	for(i = 1970; i < y; i++){
-		d2m = yrsize(i);
-		secs += d2m[0] * SEC2DAY;
-	}
-
-	/*
-	 *  seconds per month
-	 */
-	d2m = yrsize(y);
-	for(i = 1; i < m; i++)
-		secs += d2m[i] * SEC2DAY;
-
-	secs += (g2(&buf)-1) * SEC2DAY;
-	secs += g2(&buf) * SEC2HOUR;
-	secs += g2(&buf) * SEC2MIN;
-	if(*buf)
-		secs += g2(&buf);
-
-	sprint(argbuf, "%ld", secs);
-	return secs;
-}

+ 0 - 46
sys/src/9/boot/testboot.c

@@ -1,46 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-
-void
-usage(void)
-{
-	fprint(2, "usage: testboot cmd args...\n");
-	exits("usage");
-}
-
-void
-main(int argc, char **argv)
-{
-	int p[2];
-
-	if(argc == 1)
-		usage();
-
-	pipe(p);
-	switch(rfork(RFPROC|RFFDG|RFNAMEG)){
-	case -1:
-		sysfatal("fork: %r");
-
-	case 0:
-		dup(p[0], 0);
-		dup(p[1], 1);
-		exec(argv[1], argv+1);
-		sysfatal("exec: %r");
-
-	default:
-		if(amount(p[0], "/n/kremvax", MREPL, "") < 0)
-			sysfatal("amount: %r");
-		break;
-	}
-	exits(nil);
-}

+ 0 - 156
sys/src/9/boot/usb.c

@@ -1,156 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/* usb support */
-
-#include <u.h>
-#include <libc.h>
-#include <auth.h>
-#include <fcall.h>
-#include "../boot/boot.h"
-
-#define PARTSRV "partfs.sdXX"
-
-enum {
-	Dontpost,
-	Post,
-};
-
-static char usbdisk0[] = "/dev/sdU0.0";
-static char sdxxctl[]  = "/dev/sdXX/ctl";
-
-/*
- * run argv[0] (short name is name) and wait awhile for file to appear.
- * file must be generated by running argv[0]; if it already exists, we're done.
- */
-static int
-start(char *name, char **argv, char *file)
-{
-	int cnt;
-
-	if(access(file, AEXIST) >= 0)
-		return 0;
-	if(access(argv[0], AEXIST) < 0) {
-		fprint(2, "no %s...", argv[0]);
-		return -1;
-	}
-
-	dprint("%s...", name);
-	runv(argv);
-	for(cnt = 10; cnt > 0 && access(file, AEXIST) < 0; cnt--)
-		sleep(100);
-	if (cnt <= 0) {
-		dprint("no %s...", file);
-		return -1;
-	}
-	return 0;
-}
-
-int
-chmod(char *file, int mode)
-{
-	Dir *dir;
-
-	dir = dirstat(file);
-	if (dir == nil) {
-		dprint("can't stat %s: %r\n", file);
-		return -1;
-	}
-	dir->mode &= ~0777;
-	dir->mode |= mode & 0777;
-	dirwstat("/srv/" PARTSRV, dir);
-	free(dir);
-	return 0;
-}
-
-/* start partfs on first usb disk, if any.  optionally post partfs in /srv. */
-static int
-startpartfs(int post)
-{
-	int r, i;
-	char *parts;
-	char *partfsv[32];
-
-	if(access(usbdisk0, AEXIST) < 0)
-		return -1;	/* can't run partfs until usbd is mounted */
-
-	if (post)
-		remove("/srv/" PARTSRV);
-
-	i = 0;
-	partfsv[i++] = "/boot/partfs";
-	/*
-	 * hack for booting from usb: if /env/sdB0part (from 9load) exists,
-	 * pass it to partfs for sdXX.
-	 */
-	parts = getenv("sdB0part");
-	if (parts != nil) {
-		partfsv[i++] = "-p";
-		partfsv[i++] = parts;
-	}
-	if (post) {
-		partfsv[i++] = "-s";
-		partfsv[i++] = PARTSRV;
-	}
-	partfsv[i++] = usbdisk0;
-	partfsv[i] = nil;
-	r = start("partfs", partfsv, sdxxctl);
-
-	if (post)
-		chmod("/srv/" PARTSRV, 0666);
-	return r;
-}
-
-static int
-mountusb(void)
-{
-	int fd;
-
-	dprint("mount usbd...");
-	fd = open("/srv/usb", ORDWR);
-	if(fd < 0)
-		warning("can't open /srv/usb");
-	else if(mount(fd, -1, "/dev", MBEFORE, "") < 0) {
-		warning("mount -a /srv/usb /dev");
-		close(fd);
-	} else
-		return 0;		/* mount closed fd */
-	return -1;
-}
-
-int
-mountusbparts(void)
-{
-	mountusb();
-	return startpartfs(Post);
-}
-
-/*
- *  start usbd, which mounts itself on /dev.
- *  start partfs on first disk, if any, to permit nvram on usb.
- */
-void
-usbinit(int post)
-{
-	int cnt;
-	static char *usbdv[] = { "/boot/usbd", nil };
-
-	if(access("#u/usb/ctl", AEXIST) < 0 || bind("#u", "/dev", MAFTER) < 0)
-		return;
-	dprint("usbinit...");
-	start("usbd", usbdv, "/srv/usb");
-
-	/* allow a little time for usbd's device discovery */
-	for(cnt = 20; cnt > 0 && access(usbdisk0, AEXIST) < 0; cnt--)
-		sleep(100);
-	if(cnt > 0)
-		startpartfs(post);
-	else
-		dprint("no usb disk...");
-}

+ 0 - 695
sys/src/9/ip/arp.c

@@ -1,695 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-#include "ipv6.h"
-
-/*
- *  address resolution tables
- */
-
-enum
-{
-	NHASH		= (1<<6),
-	NCACHE		= 256,
-
-	AOK		= 1,
-	AWAIT		= 2,
-};
-
-char *arpstate[] =
-{
-	"UNUSED",
-	"OK",
-	"WAIT",
-};
-
-/*
- *  one per Fs
- */
-struct Arp
-{
-	QLock;
-	Fs	*f;
-	Arpent	*hash[NHASH];
-	Arpent	cache[NCACHE];
-	Arpent	*rxmt;
-	Proc	*rxmitp;	/* neib sol re-transmit proc */
-	Rendez	rxmtq;
-	Block 	*dropf, *dropl;
-};
-
-char *Ebadarp = "bad arp";
-
-#define haship(s) ((s)[IPaddrlen-1]%NHASH)
-
-extern int 	ReTransTimer = RETRANS_TIMER;
-
-static void 	rxmitproc(void *v);
-
-void
-arpinit(Fs *f)
-{
-	f->arp = smalloc(sizeof(Arp));
-	f->arp->f = f;
-	f->arp->rxmt = nil;
-	f->arp->dropf = f->arp->dropl = nil;
-	kproc("rxmitproc", rxmitproc, f->arp);
-}
-
-/*
- *  create a new arp entry for an ip address.
- */
-static Arpent*
-newarp6(Arp *arp, uchar *ip, Ipifc *ifc, int addrxt)
-{
-	uint t;
-	Block *next, *xp;
-	Arpent *a, *e, *f, **l;
-	Medium *m = ifc->m;
-	int empty;
-
-	/* find oldest entry */
-	e = &arp->cache[NCACHE];
-	a = arp->cache;
-	t = a->utime;
-	for(f = a; f < e; f++){
-		if(f->utime < t){
-			t = f->utime;
-			a = f;
-		}
-	}
-
-	/* dump waiting packets */
-	xp = a->hold;
-	a->hold = nil;
-
-	if(isv4(a->ip)){
-		while(xp){
-			next = xp->list;
-			freeblist(xp);
-			xp = next;
-		}
-	}
-	else { /* queue icmp unreachable for rxmitproc later on, w/o arp lock */
-		if(xp){
-			if(arp->dropl == nil)
-				arp->dropf = xp;
-			else
-				arp->dropl->list = xp;
-
-			for(next = xp->list; next; next = next->list)
-				xp = next;
-			arp->dropl = xp;
-			wakeup(&arp->rxmtq);
-		}
-	}
-
-	/* take out of current chain */
-	l = &arp->hash[haship(a->ip)];
-	for(f = *l; f; f = f->hash){
-		if(f == a){
-			*l = a->hash;
-			break;
-		}
-		l = &f->hash;
-	}
-
-	/* insert into new chain */
-	l = &arp->hash[haship(ip)];
-	a->hash = *l;
-	*l = a;
-
-	memmove(a->ip, ip, sizeof(a->ip));
-	a->utime = NOW;
-	a->ctime = 0;
-	a->type = m;
-
-	a->rtime = NOW + ReTransTimer;
-	a->rxtsrem = MAX_MULTICAST_SOLICIT;
-	a->ifc = ifc;
-	a->ifcid = ifc->ifcid;
-
-	/* put to the end of re-transmit chain; addrxt is 0 when isv4(a->ip) */
-	if(!ipismulticast(a->ip) && addrxt){
-		l = &arp->rxmt;
-		empty = (*l==nil);
-
-		for(f = *l; f; f = f->nextrxt){
-			if(f == a){
-				*l = a->nextrxt;
-				break;
-			}
-			l = &f->nextrxt;
-		}
-		for(f = *l; f; f = f->nextrxt){
-			l = &f->nextrxt;
-		}
-		*l = a;
-		if(empty)
-			wakeup(&arp->rxmtq);
-	}
-
-	a->nextrxt = nil;
-
-	return a;
-}
-
-/* called with arp qlocked */
-
-void
-cleanarpent(Arp *arp, Arpent *a)
-{
-	Arpent *f, **l;
-
-	a->utime = 0;
-	a->ctime = 0;
-	a->type = 0;
-	a->state = 0;
-
-	/* take out of current chain */
-	l = &arp->hash[haship(a->ip)];
-	for(f = *l; f; f = f->hash){
-		if(f == a){
-			*l = a->hash;
-			break;
-		}
-		l = &f->hash;
-	}
-
-	/* take out of re-transmit chain */
-	l = &arp->rxmt;
-	for(f = *l; f; f = f->nextrxt){
-		if(f == a){
-			*l = a->nextrxt;
-			break;
-		}
-		l = &f->nextrxt;
-	}
-	a->nextrxt = nil;
-	a->hash = nil;
-	a->hold = nil;
-	a->last = nil;
-	a->ifc = nil;
-}
-
-/*
- *  fill in the media address if we have it.  Otherwise return an
- *  Arpent that represents the state of the address resolution FSM
- *  for ip.  Add the packet to be sent onto the list of packets
- *  waiting for ip->mac to be resolved.
- */
-Arpent*
-arpget(Arp *arp, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *mac)
-{
-	int hash;
-	Arpent *a;
-	Medium *type = ifc->m;
-	uchar v6ip[IPaddrlen];
-
-	if(version == V4){
-		v4tov6(v6ip, ip);
-		ip = v6ip;
-	}
-
-	qlock(arp);
-	hash = haship(ip);
-	for(a = arp->hash[hash]; a; a = a->hash){
-		if(memcmp(ip, a->ip, sizeof(a->ip)) == 0)
-		if(type == a->type)
-			break;
-	}
-
-	if(a == nil){
-		a = newarp6(arp, ip, ifc, (version != V4));
-		a->state = AWAIT;
-	}
-	a->utime = NOW;
-	if(a->state == AWAIT){
-		if(bp != nil){
-			if(a->hold)
-				a->last->list = bp;
-			else
-				a->hold = bp;
-			a->last = bp;
-			bp->list = nil;
-		}
-		return a;		/* return with arp qlocked */
-	}
-
-	memmove(mac, a->mac, a->type->maclen);
-
-	/* remove old entries */
-	if(NOW - a->ctime > 15*60*1000)
-		cleanarpent(arp, a);
-
-	qunlock(arp);
-	return nil;
-}
-
-/*
- * called with arp locked
- */
-void
-arprelease(Arp *arp, Arpent*)
-{
-	qunlock(arp);
-}
-
-/*
- * Copy out the mac address from the Arpent.  Return the
- * block waiting to get sent to this mac address.
- *
- * called with arp locked
- */
-Block*
-arpresolve(Arp *arp, Arpent *a, Medium *type, uchar *mac)
-{
-	Block *bp;
-	Arpent *f, **l;
-
-	if(!isv4(a->ip)){
-		l = &arp->rxmt;
-		for(f = *l; f; f = f->nextrxt){
-			if(f == a){
-				*l = a->nextrxt;
-				break;
-			}
-			l = &f->nextrxt;
-		}
-	}
-
-	memmove(a->mac, mac, type->maclen);
-	a->type = type;
-	a->state = AOK;
-	a->utime = NOW;
-	bp = a->hold;
-	a->hold = nil;
-	qunlock(arp);
-
-	return bp;
-}
-
-void
-arpenter(Fs *fs, int version, uchar *ip, uchar *mac, int n, int refresh)
-{
-	Arp *arp;
-	Route *r;
-	Arpent *a, *f, **l;
-	Ipifc *ifc;
-	Medium *type;
-	Block *bp, *next;
-	uchar v6ip[IPaddrlen];
-
-	arp = fs->arp;
-
-	if(n != 6){
-//		print("arp: len = %d\n", n);
-		return;
-	}
-
-	switch(version){
-	case V4:
-		r = v4lookup(fs, ip, nil);
-		v4tov6(v6ip, ip);
-		ip = v6ip;
-		break;
-	case V6:
-		r = v6lookup(fs, ip, nil);
-		break;
-	default:
-		panic("arpenter: version %d", version);
-		return;	/* to supress warnings */
-	}
-
-	if(r == nil){
-//		print("arp: no route for entry\n");
-		return;
-	}
-
-	ifc = r->ifc;
-	type = ifc->m;
-
-	qlock(arp);
-	for(a = arp->hash[haship(ip)]; a; a = a->hash){
-		if(a->type != type || (a->state != AWAIT && a->state != AOK))
-			continue;
-
-		if(ipcmp(a->ip, ip) == 0){
-			a->state = AOK;
-			memmove(a->mac, mac, type->maclen);
-
-			if(version == V6){
-				/* take out of re-transmit chain */
-				l = &arp->rxmt;
-				for(f = *l; f; f = f->nextrxt){
-					if(f == a){
-						*l = a->nextrxt;
-						break;
-					}
-					l = &f->nextrxt;
-				}
-			}
-
-			a->ifc = ifc;
-			a->ifcid = ifc->ifcid;
-			bp = a->hold;
-			a->hold = nil;
-			if(version == V4)
-				ip += IPv4off;
-			a->utime = NOW;
-			a->ctime = a->utime;
-			qunlock(arp);
-
-			while(bp){
-				next = bp->list;
-				if(ifc != nil){
-					if(waserror()){
-						runlock(ifc);
-						nexterror();
-					}
-					rlock(ifc);
-					if(ifc->m != nil)
-						ifc->m->bwrite(ifc, bp, version, ip);
-					else
-						freeb(bp);
-					runlock(ifc);
-					poperror();
-				} else
-					freeb(bp);
-				bp = next;
-			}
-			return;
-		}
-	}
-
-	if(refresh == 0){
-		a = newarp6(arp, ip, ifc, 0);
-		a->state = AOK;
-		a->type = type;
-		a->ctime = NOW;
-		memmove(a->mac, mac, type->maclen);
-	}
-
-	qunlock(arp);
-}
-
-int
-arpwrite(Fs *fs, char *s, int len)
-{
-	int n;
-	Route *r;
-	Arp *arp;
-	Block *bp;
-	Arpent *a, *fl, **l;
-	Medium *m;
-	char *f[4], buf[256];
-	uchar ip[IPaddrlen], mac[MAClen];
-
-	arp = fs->arp;
-
-	if(len == 0)
-		error(Ebadarp);
-	if(len >= sizeof(buf))
-		len = sizeof(buf)-1;
-	strncpy(buf, s, len);
-	buf[len] = 0;
-	if(len > 0 && buf[len-1] == '\n')
-		buf[len-1] = 0;
-
-	n = getfields(buf, f, 4, 1, " ");
-	if(strcmp(f[0], "flush") == 0){
-		qlock(arp);
-		for(a = arp->cache; a < &arp->cache[NCACHE]; a++){
-			memset(a->ip, 0, sizeof(a->ip));
-			memset(a->mac, 0, sizeof(a->mac));
-			a->hash = nil;
-			a->state = 0;
-			a->utime = 0;
-			while(a->hold != nil){
-				bp = a->hold->list;
-				freeblist(a->hold);
-				a->hold = bp;
-			}
-		}
-		memset(arp->hash, 0, sizeof(arp->hash));
-		/* clear all pkts on these lists (rxmt, dropf/l) */
-		arp->rxmt = nil;
-		arp->dropf = nil;
-		arp->dropl = nil;
-		qunlock(arp);
-	} else if(strcmp(f[0], "add") == 0){
-		switch(n){
-		default:
-			error(Ebadarg);
-		case 3:
-			if (parseip(ip, f[1]) == -1)
-				error(Ebadip);
-			if(isv4(ip))
-				r = v4lookup(fs, ip+IPv4off, nil);
-			else
-				r = v6lookup(fs, ip, nil);
-			if(r == nil)
-				error("Destination unreachable");
-			m = r->ifc->m;
-			n = parsemac(mac, f[2], m->maclen);
-			break;
-		case 4:
-			m = ipfindmedium(f[1]);
-			if(m == nil)
-				error(Ebadarp);
-			if (parseip(ip, f[2]) == -1)
-				error(Ebadip);
-			n = parsemac(mac, f[3], m->maclen);
-			break;
-		}
-
-		if(m->ares == nil)
-			error(Ebadarp);
-
-		m->ares(fs, V6, ip, mac, n, 0);
-	} else if(strcmp(f[0], "del") == 0){
-		if(n != 2)
-			error(Ebadarg);
-
-		if (parseip(ip, f[1]) == -1)
-			error(Ebadip);
-		qlock(arp);
-
-		l = &arp->hash[haship(ip)];
-		for(a = *l; a; a = a->hash){
-			if(memcmp(ip, a->ip, sizeof(a->ip)) == 0){
-				*l = a->hash;
-				break;
-			}
-			l = &a->hash;
-		}
-
-		if(a){
-			/* take out of re-transmit chain */
-			l = &arp->rxmt;
-			for(fl = *l; fl; fl = fl->nextrxt){
-				if(fl == a){
-					*l = a->nextrxt;
-					break;
-				}
-				l = &fl->nextrxt;
-			}
-
-			a->nextrxt = nil;
-			a->hash = nil;
-			a->hold = nil;
-			a->last = nil;
-			a->ifc = nil;
-			memset(a->ip, 0, sizeof(a->ip));
-			memset(a->mac, 0, sizeof(a->mac));
-		}
-		qunlock(arp);
-	} else
-		error(Ebadarp);
-
-	return len;
-}
-
-enum
-{
-	Alinelen=	90,
-};
-
-char *aformat = "%-6.6s %-8.8s %-40.40I %-32.32s\n";
-
-static void
-convmac(char *p, char *ep, uchar *mac, int n)
-{
-	while(n-- > 0)
-		p = seprint(p, ep, "%2.2ux", *mac++);
-}
-
-int
-arpread(Arp *arp, char *p, ulong offset, int len)
-{
-	Arpent *a;
-	int n;
-	char mac[2*MAClen+1];
-
-	if(offset % Alinelen)
-		return 0;
-
-	offset = offset/Alinelen;
-	len = len/Alinelen;
-
-	n = 0;
-	for(a = arp->cache; len > 0 && a < &arp->cache[NCACHE]; a++){
-		if(a->state == 0)
-			continue;
-		if(offset > 0){
-			offset--;
-			continue;
-		}
-		len--;
-		qlock(arp);
-		convmac(mac, &mac[sizeof mac], a->mac, a->type->maclen);
-		n += snprint(p+n, Alinelen+1, aformat, a->type->name,
-			arpstate[a->state], a->ip, mac);	/* +1 for NUL */
-		qunlock(arp);
-	}
-
-	return n;
-}
-
-extern int
-rxmitsols(Arp *arp)
-{
-	uint sflag;
-	Block *next, *xp;
-	Arpent *a, *b, **l;
-	Fs *f;
-	uchar ipsrc[IPaddrlen];
-	Ipifc *ifc = nil;
-	long nrxt;
-
-	qlock(arp);
-	f = arp->f;
-
-	a = arp->rxmt;
-	if(a==nil){
-		nrxt = 0;
-		goto dodrops; 		/* return nrxt; */
-	}
-	nrxt = a->rtime - NOW;
-	if(nrxt > 3*ReTransTimer/4)
-		goto dodrops; 		/* return nrxt; */
-
-	for(; a; a = a->nextrxt){
-		ifc = a->ifc;
-		assert(ifc != nil);
-		if((a->rxtsrem <= 0) || !(canrlock(ifc)) || (a->ifcid != ifc->ifcid)){
-			xp = a->hold;
-			a->hold = nil;
-
-			if(xp){
-				if(arp->dropl == nil)
-					arp->dropf = xp;
-				else
-					arp->dropl->list = xp;
-			}
-
-			cleanarpent(arp, a);
-		}
-		else
-			break;
-	}
-	if(a == nil)
-		goto dodrops;
-
-
-	qunlock(arp);	/* for icmpns */
-	if((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC)
-		icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
-
-	runlock(ifc);
-	qlock(arp);
-
-	/* put to the end of re-transmit chain */
-	l = &arp->rxmt;
-	for(b = *l; b; b = b->nextrxt){
-		if(b == a){
-			*l = a->nextrxt;
-			break;
-		}
-		l = &b->nextrxt;
-	}
-	for(b = *l; b; b = b->nextrxt){
-		l = &b->nextrxt;
-	}
-	*l = a;
-	a->rxtsrem--;
-	a->nextrxt = nil;
-	a->rtime = NOW + ReTransTimer;
-
-	a = arp->rxmt;
-	if(a==nil)
-		nrxt = 0;
-	else
-		nrxt = a->rtime - NOW;
-
-dodrops:
-	xp = arp->dropf;
-	arp->dropf = nil;
-	arp->dropl = nil;
-	qunlock(arp);
-
-	for(; xp; xp = next){
-		next = xp->list;
-		icmphostunr(f, ifc, xp, Icmp6_adr_unreach, 1);
-	}
-
-	return nrxt;
-
-}
-
-static int
-rxready(void *v)
-{
-	Arp *arp = (Arp *) v;
-	int x;
-
-	x = ((arp->rxmt != nil) || (arp->dropf != nil));
-
-	return x;
-}
-
-static void
-rxmitproc(void *v)
-{
-	Arp *arp = v;
-	long wakeupat;
-
-	arp->rxmitp = up;
-	//print("arp rxmitproc started\n");
-	if(waserror()){
-		arp->rxmitp = 0;
-		pexit("hangup", 1);
-	}
-	for(;;){
-		wakeupat = rxmitsols(arp);
-		if(wakeupat == 0)
-			sleep(&arp->rxmtq, rxready, v);
-		else if(wakeupat > ReTransTimer/4)
-			tsleep(&arp->rxmtq, return0, 0, wakeupat);
-	}
-}
-

+ 0 - 133
sys/src/9/ip/chandial.c

@@ -1,133 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"../ip/ip.h"
-
-typedef struct DS DS;
-static Chan*	call(char*, char*, DS*);
-static void	_dial_string_parse(char*, DS*);
-
-enum
-{
-	Maxstring=	128,
-};
-
-struct DS
-{
-	char	buf[Maxstring];			/* dist string */
-	char	*netdir;
-	char	*proto;
-	char	*rem;
-	char	*local;				/* other args */
-	char	*dir;
-	Chan	**ctlp;
-};
-
-/*
- *  the dialstring is of the form '[/net/]proto!dest'
- */
-Chan*
-chandial(char *dest, char *local, char *dir, Chan **ctlp)
-{
-	DS ds;
-	char clone[Maxpath];
-
-	ds.local = local;
-	ds.dir = dir;
-	ds.ctlp = ctlp;
-
-	_dial_string_parse(dest, &ds);
-	if(ds.netdir == 0)
-		ds.netdir = "/net";
-
-	/* no connection server, don't translate */
-	snprint(clone, sizeof(clone), "%s/%s/clone", ds.netdir, ds.proto);
-	return call(clone, ds.rem, &ds);
-}
-
-static Chan*
-call(char *clone, char *dest, DS *ds)
-{
-	int n;
-	Chan *dchan, *cchan;
-	char name[Maxpath], data[Maxpath], *p;
-
-	cchan = namec(clone, Aopen, ORDWR, 0);
-
-	/* get directory name */
-	if(waserror()){
-		cclose(cchan);
-		nexterror();
-	}
-	n = devtab[cchan->type]->read(cchan, name, sizeof(name)-1, 0);
-	name[n] = 0;
-	for(p = name; *p == ' '; p++)
-		;
-	snprint(name, sizeof name, "%lud", strtoul(p, 0, 0));
-	p = strrchr(clone, '/');
-	*p = 0;
-	if(ds->dir)
-		snprint(ds->dir, Maxpath, "%s/%s", clone, name);
-	snprint(data, sizeof(data), "%s/%s/data", clone, name);
-
-	/* connect */
-	if(ds->local)
-		snprint(name, sizeof(name), "connect %s %s", dest, ds->local);
-	else
-		snprint(name, sizeof(name), "connect %s", dest);
-	devtab[cchan->type]->write(cchan, name, strlen(name), 0);
-
-	/* open data connection */
-	dchan = namec(data, Aopen, ORDWR, 0);
-	if(ds->ctlp)
-		*ds->ctlp = cchan;
-	else
-		cclose(cchan);
-	poperror();
-	return dchan;
-
-}
-
-/*
- *  parse a dial string
- */
-static void
-_dial_string_parse(char *str, DS *ds)
-{
-	char *p, *p2;
-
-	strncpy(ds->buf, str, Maxstring);
-	ds->buf[Maxstring-1] = 0;
-
-	p = strchr(ds->buf, '!');
-	if(p == 0) {
-		ds->netdir = 0;
-		ds->proto = "net";
-		ds->rem = ds->buf;
-	} else {
-		if(*ds->buf != '/' && *ds->buf != '#'){
-			ds->netdir = 0;
-			ds->proto = ds->buf;
-		} else {
-			for(p2 = p; *p2 != '/'; p2--)
-				;
-			*p2++ = 0;
-			ds->netdir = ds->buf;
-			ds->proto = p2;
-		}
-		*p = 0;
-		ds->rem = p + 1;
-	}
-}

+ 0 - 1466
sys/src/9/ip/devip.c

@@ -1,1466 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"../ip/ip.h"
-
-enum
-{
-	Qtopdir=	1,		/* top level directory */
-	Qtopbase,
-	Qarp=		Qtopbase,
-	Qbootp,
-	Qndb,
-	Qiproute,
-	Qipselftab,
-	Qlog,
-
-	Qprotodir,			/* directory for a protocol */
-	Qprotobase,
-	Qclone=		Qprotobase,
-	Qstats,
-
-	Qconvdir,			/* directory for a conversation */
-	Qconvbase,
-	Qctl=		Qconvbase,
-	Qdata,
-	Qerr,
-	Qlisten,
-	Qlocal,
-	Qremote,
-	Qstatus,
-	Qsnoop,
-
-	Logtype=	5,
-	Masktype=	(1<<Logtype)-1,
-	Logconv=	12,
-	Maskconv=	(1<<Logconv)-1,
-	Shiftconv=	Logtype,
-	Logproto=	8,
-	Maskproto=	(1<<Logproto)-1,
-	Shiftproto=	Logtype + Logconv,
-
-	Nfs=		128,
-};
-#define TYPE(x) 	( ((ulong)(x).path) & Masktype )
-#define CONV(x) 	( (((ulong)(x).path) >> Shiftconv) & Maskconv )
-#define PROTO(x) 	( (((ulong)(x).path) >> Shiftproto) & Maskproto )
-#define QID(p, c, y) 	( ((p)<<(Shiftproto)) | ((c)<<Shiftconv) | (y) )
-
-static char network[] = "network";
-
-QLock	fslock;
-Fs	*ipfs[Nfs];	/* attached fs's */
-Queue	*qlog;
-
-extern	void nullmediumlink(void);
-extern	void pktmediumlink(void);
-	long ndbwrite(Fs *f, char *a, ulong off, int n);
-
-static int
-ip3gen(Chan *c, int i, Dir *dp)
-{
-	Qid q;
-	Conv *cv;
-	char *p;
-
-	cv = ipfs[c->dev]->p[PROTO(c->qid)]->conv[CONV(c->qid)];
-	if(cv->owner == nil)
-		kstrdup(&cv->owner, eve);
-	mkqid(&q, QID(PROTO(c->qid), CONV(c->qid), i), 0, QTFILE);
-
-	switch(i) {
-	default:
-		return -1;
-	case Qctl:
-		devdir(c, q, "ctl", 0, cv->owner, cv->perm, dp);
-		return 1;
-	case Qdata:
-		devdir(c, q, "data", qlen(cv->rq), cv->owner, cv->perm, dp);
-		return 1;
-	case Qerr:
-		devdir(c, q, "err", qlen(cv->eq), cv->owner, cv->perm, dp);
-		return 1;
-	case Qlisten:
-		devdir(c, q, "listen", 0, cv->owner, cv->perm, dp);
-		return 1;
-	case Qlocal:
-		p = "local";
-		break;
-	case Qremote:
-		p = "remote";
-		break;
-	case Qsnoop:
-		if(strcmp(cv->p->name, "ipifc") != 0)
-			return -1;
-		devdir(c, q, "snoop", qlen(cv->sq), cv->owner, 0400, dp);
-		return 1;
-	case Qstatus:
-		p = "status";
-		break;
-	}
-	devdir(c, q, p, 0, cv->owner, 0444, dp);
-	return 1;
-}
-
-static int
-ip2gen(Chan *c, int i, Dir *dp)
-{
-	Qid q;
-
-	switch(i) {
-	case Qclone:
-		mkqid(&q, QID(PROTO(c->qid), 0, Qclone), 0, QTFILE);
-		devdir(c, q, "clone", 0, network, 0666, dp);
-		return 1;
-	case Qstats:
-		mkqid(&q, QID(PROTO(c->qid), 0, Qstats), 0, QTFILE);
-		devdir(c, q, "stats", 0, network, 0444, dp);
-		return 1;
-	}
-	return -1;
-}
-
-static int
-ip1gen(Chan *c, int i, Dir *dp)
-{
-	Qid q;
-	char *p;
-	int prot;
-	int len = 0;
-	Fs *f;
-	extern ulong	kerndate;
-
-	f = ipfs[c->dev];
-
-	prot = 0666;
-	mkqid(&q, QID(0, 0, i), 0, QTFILE);
-	switch(i) {
-	default:
-		return -1;
-	case Qarp:
-		p = "arp";
-		prot = 0664;
-		break;
-	case Qbootp:
-		p = "bootp";
-		break;
-	case Qndb:
-		p = "ndb";
-		len = strlen(f->ndb);
-		q.vers = f->ndbvers;
-		break;
-	case Qiproute:
-		p = "iproute";
-		prot = 0664;
-		break;
-	case Qipselftab:
-		p = "ipselftab";
-		prot = 0444;
-		break;
-	case Qlog:
-		p = "log";
-		break;
-	}
-	devdir(c, q, p, len, network, prot, dp);
-	if(i == Qndb && f->ndbmtime > kerndate)
-		dp->mtime = f->ndbmtime;
-	return 1;
-}
-
-static int
-ipgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
-{
-	Qid q;
-	Conv *cv;
-	Fs *f;
-
-	f = ipfs[c->dev];
-
-	switch(TYPE(c->qid)) {
-	case Qtopdir:
-		if(s == DEVDOTDOT){
-			mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
-			snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
-			devdir(c, q, up->genbuf, 0, network, 0555, dp);
-			return 1;
-		}
-		if(s < f->np) {
-			if(f->p[s]->connect == nil)
-				return 0;	/* protocol with no user interface */
-			mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
-			devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
-			return 1;
-		}
-		s -= f->np;
-		return ip1gen(c, s+Qtopbase, dp);
-	case Qarp:
-	case Qbootp:
-	case Qndb:
-	case Qlog:
-	case Qiproute:
-	case Qipselftab:
-		return ip1gen(c, TYPE(c->qid), dp);
-	case Qprotodir:
-		if(s == DEVDOTDOT){
-			mkqid(&q, QID(0, 0, Qtopdir), 0, QTDIR);
-			snprint(up->genbuf, sizeof up->genbuf, "#I%lud", c->dev);
-			devdir(c, q, up->genbuf, 0, network, 0555, dp);
-			return 1;
-		}
-		if(s < f->p[PROTO(c->qid)]->ac) {
-			cv = f->p[PROTO(c->qid)]->conv[s];
-			snprint(up->genbuf, sizeof up->genbuf, "%d", s);
-			mkqid(&q, QID(PROTO(c->qid), s, Qconvdir), 0, QTDIR);
-			devdir(c, q, up->genbuf, 0, cv->owner, 0555, dp);
-			return 1;
-		}
-		s -= f->p[PROTO(c->qid)]->ac;
-		return ip2gen(c, s+Qprotobase, dp);
-	case Qclone:
-	case Qstats:
-		return ip2gen(c, TYPE(c->qid), dp);
-	case Qconvdir:
-		if(s == DEVDOTDOT){
-			s = PROTO(c->qid);
-			mkqid(&q, QID(s, 0, Qprotodir), 0, QTDIR);
-			devdir(c, q, f->p[s]->name, 0, network, 0555, dp);
-			return 1;
-		}
-		return ip3gen(c, s+Qconvbase, dp);
-	case Qctl:
-	case Qdata:
-	case Qerr:
-	case Qlisten:
-	case Qlocal:
-	case Qremote:
-	case Qstatus:
-	case Qsnoop:
-		return ip3gen(c, TYPE(c->qid), dp);
-	}
-	return -1;
-}
-
-static void
-ipreset(void)
-{
-	nullmediumlink();
-	pktmediumlink();
-
-	fmtinstall('i', eipfmt);
-	fmtinstall('I', eipfmt);
-	fmtinstall('E', eipfmt);
-	fmtinstall('V', eipfmt);
-	fmtinstall('M', eipfmt);
-}
-
-static Fs*
-ipgetfs(int dev)
-{
-	extern void (*ipprotoinit[])(Fs*);
-	Fs *f;
-	int i;
-
-	if(dev >= Nfs)
-		return nil;
-
-	qlock(&fslock);
-	if(ipfs[dev] == nil){
-		f = smalloc(sizeof(Fs));
-		ip_init(f);
-		arpinit(f);
-		netloginit(f);
-		for(i = 0; ipprotoinit[i]; i++)
-			ipprotoinit[i](f);
-		f->dev = dev;
-		ipfs[dev] = f;
-	}
-	qunlock(&fslock);
-
-	return ipfs[dev];
-}
-
-IPaux*
-newipaux(char *owner, char *tag)
-{
-	IPaux *a;
-	int n;
-
-	a = smalloc(sizeof(*a));
-	kstrdup(&a->owner, owner);
-	memset(a->tag, ' ', sizeof(a->tag));
-	n = strlen(tag);
-	if(n > sizeof(a->tag))
-		n = sizeof(a->tag);
-	memmove(a->tag, tag, n);
-	return a;
-}
-
-#define ATTACHER(c) (((IPaux*)((c)->aux))->owner)
-
-static Chan*
-ipattach(char* spec)
-{
-	Chan *c;
-	int dev;
-
-	dev = atoi(spec);
-	if(dev >= Nfs)
-		error("bad specification");
-
-	ipgetfs(dev);
-	c = devattach('I', spec);
-	mkqid(&c->qid, QID(0, 0, Qtopdir), 0, QTDIR);
-	c->dev = dev;
-
-	c->aux = newipaux(commonuser(), "none");
-
-	return c;
-}
-
-static Walkqid*
-ipwalk(Chan* c, Chan *nc, char **name, int nname)
-{
-	IPaux *a = c->aux;
-	Walkqid* w;
-
-	w = devwalk(c, nc, name, nname, nil, 0, ipgen);
-	if(w != nil && w->clone != nil)
-		w->clone->aux = newipaux(a->owner, a->tag);
-	return w;
-}
-
-
-static int
-ipstat(Chan* c, uchar* db, int n)
-{
-	return devstat(c, db, n, nil, 0, ipgen);
-}
-
-static int
-incoming(void* arg)
-{
-	Conv *conv;
-
-	conv = arg;
-	return conv->incall != nil;
-}
-
-static int m2p[] = {
-	[OREAD]		4,
-	[OWRITE]	2,
-	[ORDWR]		6
-};
-
-static Chan*
-ipopen(Chan* c, int omode)
-{
-	Conv *cv, *nc;
-	Proto *p;
-	int perm;
-	Fs *f;
-
-	perm = m2p[omode&3];
-
-	f = ipfs[c->dev];
-
-	switch(TYPE(c->qid)) {
-	default:
-		break;
-	case Qndb:
-		if(omode & (OWRITE|OTRUNC) && !iseve())
-			error(Eperm);
-		if((omode & (OWRITE|OTRUNC)) == (OWRITE|OTRUNC))
-			f->ndb[0] = 0;
-		break;
-	case Qlog:
-		netlogopen(f);
-		break;
-	case Qiproute:
-	case Qarp:
-		if(omode != OREAD && !iseve())
-			error(Eperm);
-		break;
-	case Qtopdir:
-	case Qprotodir:
-	case Qconvdir:
-	case Qstatus:
-	case Qremote:
-	case Qlocal:
-	case Qstats:
-	case Qbootp:
-	case Qipselftab:
-		if(omode != OREAD)
-			error(Eperm);
-		break;
-	case Qsnoop:
-		if(omode != OREAD)
-			error(Eperm);
-		p = f->p[PROTO(c->qid)];
-		cv = p->conv[CONV(c->qid)];
-		if(strcmp(ATTACHER(c), cv->owner) != 0 && !iseve())
-			error(Eperm);
-		incref(&cv->snoopers);
-		break;
-	case Qclone:
-		p = f->p[PROTO(c->qid)];
-		qlock(p);
-		if(waserror()){
-			qunlock(p);
-			nexterror();
-		}
-		cv = Fsprotoclone(p, ATTACHER(c));
-		qunlock(p);
-		poperror();
-		if(cv == nil) {
-			error(Enodev);
-			break;
-		}
-		mkqid(&c->qid, QID(p->x, cv->x, Qctl), 0, QTFILE);
-		break;
-	case Qdata:
-	case Qctl:
-	case Qerr:
-		p = f->p[PROTO(c->qid)];
-		qlock(p);
-		cv = p->conv[CONV(c->qid)];
-		qlock(cv);
-		if(waserror()) {
-			qunlock(cv);
-			qunlock(p);
-			nexterror();
-		}
-		if((perm & (cv->perm>>6)) != perm) {
-			if(strcmp(ATTACHER(c), cv->owner) != 0)
-				error(Eperm);
-		 	if((perm & cv->perm) != perm)
-				error(Eperm);
-
-		}
-		cv->inuse++;
-		if(cv->inuse == 1){
-			kstrdup(&cv->owner, ATTACHER(c));
-			cv->perm = 0660;
-		}
-		qunlock(cv);
-		qunlock(p);
-		poperror();
-		break;
-	case Qlisten:
-		cv = f->p[PROTO(c->qid)]->conv[CONV(c->qid)];
-		if((perm & (cv->perm>>6)) != perm) {
-			if(strcmp(ATTACHER(c), cv->owner) != 0)
-				error(Eperm);
-		 	if((perm & cv->perm) != perm)
-				error(Eperm);
-
-		}
-
-		if(cv->state != Announced)
-			error("not announced");
-
-		if(waserror()){
-			closeconv(cv);
-			nexterror();
-		}
-		qlock(cv);
-		cv->inuse++;
-		qunlock(cv);
-
-		nc = nil;
-		while(nc == nil) {
-			/* give up if we got a hangup */
-			if(qisclosed(cv->rq))
-				error("listen hungup");
-
-			qlock(&cv->listenq);
-			if(waserror()) {
-				qunlock(&cv->listenq);
-				nexterror();
-			}
-
-			/* wait for a connect */
-			sleep(&cv->listenr, incoming, cv);
-
-			qlock(cv);
-			nc = cv->incall;
-			if(nc != nil){
-				cv->incall = nc->next;
-				mkqid(&c->qid, QID(PROTO(c->qid), nc->x, Qctl), 0, QTFILE);
-				kstrdup(&cv->owner, ATTACHER(c));
-			}
-			qunlock(cv);
-
-			qunlock(&cv->listenq);
-			poperror();
-		}
-		closeconv(cv);
-		poperror();
-		break;
-	}
-	c->mode = openmode(omode);
-	c->flag |= COPEN;
-	c->offset = 0;
-	return c;
-}
-
-static void
-ipcreate(Chan*, char*, int, ulong)
-{
-	error(Eperm);
-}
-
-static void
-ipremove(Chan*)
-{
-	error(Eperm);
-}
-
-static int
-ipwstat(Chan *c, uchar *dp, int n)
-{
-	Dir d;
-	Conv *cv;
-	Fs *f;
-	Proto *p;
-
-	f = ipfs[c->dev];
-	switch(TYPE(c->qid)) {
-	default:
-		error(Eperm);
-		break;
-	case Qctl:
-	case Qdata:
-		break;
-	}
-
-	n = convM2D(dp, n, &d, nil);
-	if(n > 0){
-		p = f->p[PROTO(c->qid)];
-		cv = p->conv[CONV(c->qid)];
-		if(!iseve() && strcmp(ATTACHER(c), cv->owner) != 0)
-			error(Eperm);
-		if(d.uid[0])
-			kstrdup(&cv->owner, d.uid);
-		cv->perm = d.mode & 0777;
-	}
-	return n;
-}
-
-void
-closeconv(Conv *cv)
-{
-	Conv *nc;
-	Ipmulti *mp;
-
-	qlock(cv);
-
-	if(--cv->inuse > 0) {
-		qunlock(cv);
-		return;
-	}
-
-	/* close all incoming calls since no listen will ever happen */
-	for(nc = cv->incall; nc; nc = cv->incall){
-		cv->incall = nc->next;
-		closeconv(nc);
-	}
-	cv->incall = nil;
-
-	kstrdup(&cv->owner, network);
-	cv->perm = 0660;
-
-	while((mp = cv->multi) != nil)
-		ipifcremmulti(cv, mp->ma, mp->ia);
-
-	cv->r = nil;
-	cv->rgen = 0;
-	cv->p->close(cv);
-	cv->state = Idle;
-	qunlock(cv);
-}
-
-static void
-ipclose(Chan* c)
-{
-	Fs *f;
-
-	f = ipfs[c->dev];
-	switch(TYPE(c->qid)) {
-	default:
-		break;
-	case Qlog:
-		if(c->flag & COPEN)
-			netlogclose(f);
-		break;
-	case Qdata:
-	case Qctl:
-	case Qerr:
-		if(c->flag & COPEN)
-			closeconv(f->p[PROTO(c->qid)]->conv[CONV(c->qid)]);
-		break;
-	case Qsnoop:
-		if(c->flag & COPEN)
-			decref(&f->p[PROTO(c->qid)]->conv[CONV(c->qid)]->snoopers);
-		break;
-	}
-	free(((IPaux*)c->aux)->owner);
-	free(c->aux);
-}
-
-enum
-{
-	Statelen=	32*1024,
-};
-
-static long
-ipread(Chan *ch, void *a, long n, vlong off)
-{
-	Conv *c;
-	Proto *x;
-	char *buf, *p;
-	long rv;
-	Fs *f;
-	ulong offset = off;
-
-	f = ipfs[ch->dev];
-
-	p = a;
-	switch(TYPE(ch->qid)) {
-	default:
-		error(Eperm);
-	case Qtopdir:
-	case Qprotodir:
-	case Qconvdir:
-		return devdirread(ch, a, n, 0, 0, ipgen);
-	case Qarp:
-		return arpread(f->arp, a, offset, n);
- 	case Qbootp:
- 		return bootpread(a, offset, n);
- 	case Qndb:
-		return readstr(offset, a, n, f->ndb);
-	case Qiproute:
-		return routeread(f, a, offset, n);
-	case Qipselftab:
-		return ipselftabread(f, a, offset, n);
-	case Qlog:
-		return netlogread(f, a, offset, n);
-	case Qctl:
-		buf = smalloc(16);
-		snprint(buf, 16, "%lud", CONV(ch->qid));
-		rv = readstr(offset, p, n, buf);
-		free(buf);
-		return rv;
-	case Qremote:
-		buf = smalloc(Statelen);
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-		if(x->remote == nil) {
-			snprint(buf, Statelen, "%I!%d\n", c->raddr, c->rport);
-		} else {
-			(*x->remote)(c, buf, Statelen-2);
-		}
-		rv = readstr(offset, p, n, buf);
-		free(buf);
-		return rv;
-	case Qlocal:
-		buf = smalloc(Statelen);
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-		if(x->local == nil) {
-			snprint(buf, Statelen, "%I!%d\n", c->laddr, c->lport);
-		} else {
-			(*x->local)(c, buf, Statelen-2);
-		}
-		rv = readstr(offset, p, n, buf);
-		free(buf);
-		return rv;
-	case Qstatus:
-		buf = smalloc(Statelen);
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-		(*x->state)(c, buf, Statelen-2);
-		rv = readstr(offset, p, n, buf);
-		free(buf);
-		return rv;
-	case Qdata:
-		c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
-		return qread(c->rq, a, n);
-	case Qerr:
-		c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
-		return qread(c->eq, a, n);
-	case Qsnoop:
-		c = f->p[PROTO(ch->qid)]->conv[CONV(ch->qid)];
-		return qread(c->sq, a, n);
-	case Qstats:
-		x = f->p[PROTO(ch->qid)];
-		if(x->stats == nil)
-			error("stats not implemented");
-		buf = smalloc(Statelen);
-		(*x->stats)(x, buf, Statelen);
-		rv = readstr(offset, p, n, buf);
-		free(buf);
-		return rv;
-	}
-}
-
-static Block*
-ipbread(Chan* ch, long n, ulong offset)
-{
-	Conv *c;
-	Proto *x;
-	Fs *f;
-
-	switch(TYPE(ch->qid)){
-	case Qdata:
-		f = ipfs[ch->dev];
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-		return qbread(c->rq, n);
-	default:
-		return devbread(ch, n, offset);
-	}
-}
-
-/*
- *  set local address to be that of the ifc closest to remote address
- */
-static void
-setladdr(Conv* c)
-{
-	findlocalip(c->p->f, c->laddr, c->raddr);
-}
-
-/*
- *  set a local port making sure the quad of raddr,rport,laddr,lport is unique
- */
-char*
-setluniqueport(Conv* c, int lport)
-{
-	Proto *p;
-	Conv *xp;
-	int x;
-
-	p = c->p;
-
-	qlock(p);
-	for(x = 0; x < p->nc; x++){
-		xp = p->conv[x];
-		if(xp == nil)
-			break;
-		if(xp == c)
-			continue;
-		if((xp->state == Connected || xp->state == Announced)
-		&& xp->lport == lport
-		&& xp->rport == c->rport
-		&& ipcmp(xp->raddr, c->raddr) == 0
-		&& ipcmp(xp->laddr, c->laddr) == 0){
-			qunlock(p);
-			return "address in use";
-		}
-	}
-	c->lport = lport;
-	qunlock(p);
-	return nil;
-}
-
-/*
- * is lport in use by anyone?
- */
-static int
-lportinuse(Proto *p, ushort lport)
-{
-	int x;
-
-	for(x = 0; x < p->nc && p->conv[x]; x++)
-		if(p->conv[x]->lport == lport)
-			return 1;
-	return 0;
-}
-
-/*
- *  pick a local port and set it
- */
-char *
-setlport(Conv* c)
-{
-	Proto *p;
-	int i, port;
-
-	p = c->p;
-	qlock(p);
-	if(c->restricted){
-		/* Restricted ports cycle between 600 and 1024. */
-		for(i=0; i<1024-600; i++){
-			if(p->nextrport >= 1024 || p->nextrport < 600)
-				p->nextrport = 600;
-			port = p->nextrport++;
-			if(!lportinuse(p, port))
-				goto chosen;
-		}
-	}else{
-		/*
-		 * Unrestricted ports are chosen randomly
-		 * between 2^15 and 2^16.  There are at most
-		 * 4*Nchan = 4096 ports in use at any given time,
-		 * so even in the worst case, a random probe has a
-		 * 1 - 4096/2^15 = 87% chance of success.
-		 * If 64 successive probes fail, there is a bug somewhere
-		 * (or a once in 10^58 event has happened, but that's
-		 * less likely than a venti collision).
-		 */
-		for(i=0; i<64; i++){
-			port = (1<<15) + nrand(1<<15);
-			if(!lportinuse(p, port))
-				goto chosen;
-		}
-	}
-	qunlock(p);
-	/*
-	 * debugging: let's see if we ever get this.
-	 * if we do (and we're a cpu server), we might as well restart
-	 * since we're now unable to service new connections.
-	 */
-	panic("setlport: out of ports");
-	return "no ports available";
-
-chosen:
-	c->lport = port;
-	qunlock(p);
-	return nil;
-}
-
-/*
- *  set a local address and port from a string of the form
- *	[address!]port[!r]
- */
-char*
-setladdrport(Conv* c, char* str, int announcing)
-{
-	char *p;
-	char *rv;
-	ushort lport;
-	uchar addr[IPaddrlen];
-
-	/*
-	 *  ignore restricted part if it exists.  it's
-	 *  meaningless on local ports.
-	 */
-	p = strchr(str, '!');
-	if(p != nil){
-		*p++ = 0;
-		if(strcmp(p, "r") == 0)
-			p = nil;
-	}
-
-	c->lport = 0;
-	if(p == nil){
-		if(announcing)
-			ipmove(c->laddr, IPnoaddr);
-		else
-			setladdr(c);
-		p = str;
-	} else {
-		if(strcmp(str, "*") == 0)
-			ipmove(c->laddr, IPnoaddr);
-		else {
-			if(parseip(addr, str) == -1)
-				return Ebadip;
-			if(ipforme(c->p->f, addr))
-				ipmove(c->laddr, addr);
-			else
-				return "not a local IP address";
-		}
-	}
-
-	/* one process can get all connections */
-	if(announcing && strcmp(p, "*") == 0){
-		if(!iseve())
-			error(Eperm);
-		return setluniqueport(c, 0);
-	}
-
-	lport = atoi(p);
-	if(lport <= 0)
-		rv = setlport(c);
-	else
-		rv = setluniqueport(c, lport);
-	return rv;
-}
-
-static char*
-setraddrport(Conv* c, char* str)
-{
-	char *p;
-
-	p = strchr(str, '!');
-	if(p == nil)
-		return "malformed address";
-	*p++ = 0;
-	if (parseip(c->raddr, str) == -1)
-		return Ebadip;
-	c->rport = atoi(p);
-	p = strchr(p, '!');
-	if(p){
-		if(strstr(p, "!r") != nil)
-			c->restricted = 1;
-	}
-	return nil;
-}
-
-/*
- *  called by protocol connect routine to set addresses
- */
-char*
-Fsstdconnect(Conv *c, char *argv[], int argc)
-{
-	char *p;
-
-	switch(argc) {
-	default:
-		return "bad args to connect";
-	case 2:
-		p = setraddrport(c, argv[1]);
-		if(p != nil)
-			return p;
-		setladdr(c);
-		p = setlport(c);
-		if (p != nil)
-			return p;
-		break;
-	case 3:
-		p = setraddrport(c, argv[1]);
-		if(p != nil)
-			return p;
-		p = setladdrport(c, argv[2], 0);
-		if(p != nil)
-			return p;
-	}
-
-	if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
-		memcmp(c->laddr, v4prefix, IPv4off) == 0)
-		|| ipcmp(c->raddr, IPnoaddr) == 0)
-		c->ipversion = V4;
-	else
-		c->ipversion = V6;
-
-	return nil;
-}
-/*
- *  initiate connection and sleep till its set up
- */
-static int
-connected(void* a)
-{
-	return ((Conv*)a)->state == Connected;
-}
-static void
-connectctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
-{
-	char *p;
-
-	if(c->state != 0)
-		error(Econinuse);
-	c->state = Connecting;
-	c->cerr[0] = '\0';
-	if(x->connect == nil)
-		error("connect not supported");
-	p = x->connect(c, cb->f, cb->nf);
-	if(p != nil)
-		error(p);
-
-	qunlock(c);
-	if(waserror()){
-		qlock(c);
-		nexterror();
-	}
-	sleep(&c->cr, connected, c);
-	qlock(c);
-	poperror();
-
-	if(c->cerr[0] != '\0')
-		error(c->cerr);
-}
-
-/*
- *  called by protocol announce routine to set addresses
- */
-char*
-Fsstdannounce(Conv* c, char* argv[], int argc)
-{
-	memset(c->raddr, 0, sizeof(c->raddr));
-	c->rport = 0;
-	switch(argc){
-	default:
-		break;
-	case 2:
-		return setladdrport(c, argv[1], 1);
-	}
-	return "bad args to announce";
-}
-
-/*
- *  initiate announcement and sleep till its set up
- */
-static int
-announced(void* a)
-{
-	return ((Conv*)a)->state == Announced;
-}
-static void
-announcectlmsg(Proto *x, Conv *c, Cmdbuf *cb)
-{
-	char *p;
-
-	if(c->state != 0)
-		error(Econinuse);
-	c->state = Announcing;
-	c->cerr[0] = '\0';
-	if(x->announce == nil)
-		error("announce not supported");
-	p = x->announce(c, cb->f, cb->nf);
-	if(p != nil)
-		error(p);
-
-	qunlock(c);
-	if(waserror()){
-		qlock(c);
-		nexterror();
-	}
-	sleep(&c->cr, announced, c);
-	qlock(c);
-	poperror();
-
-	if(c->cerr[0] != '\0')
-		error(c->cerr);
-}
-
-/*
- *  called by protocol bind routine to set addresses
- */
-char*
-Fsstdbind(Conv* c, char* argv[], int argc)
-{
-	switch(argc){
-	default:
-		break;
-	case 2:
-		return setladdrport(c, argv[1], 0);
-	}
-	return "bad args to bind";
-}
-
-static void
-bindctlmsg(Proto *x, Conv *c, Cmdbuf *cb)
-{
-	char *p;
-
-	if(x->bind == nil)
-		p = Fsstdbind(c, cb->f, cb->nf);
-	else
-		p = x->bind(c, cb->f, cb->nf);
-	if(p != nil)
-		error(p);
-}
-
-static void
-tosctlmsg(Conv *c, Cmdbuf *cb)
-{
-	if(cb->nf < 2)
-		c->tos = 0;
-	else
-		c->tos = atoi(cb->f[1]);
-}
-
-static void
-ttlctlmsg(Conv *c, Cmdbuf *cb)
-{
-	if(cb->nf < 2)
-		c->ttl = MAXTTL;
-	else
-		c->ttl = atoi(cb->f[1]);
-}
-
-static long
-ipwrite(Chan* ch, void *v, long n, vlong off)
-{
-	Conv *c;
-	Proto *x;
-	char *p;
-	Cmdbuf *cb;
-	uchar ia[IPaddrlen], ma[IPaddrlen];
-	Fs *f;
-	char *a;
-	ulong offset = off;
-
-	a = v;
-	f = ipfs[ch->dev];
-
-	switch(TYPE(ch->qid)){
-	default:
-		error(Eperm);
-	case Qdata:
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-
-		if(c->wq == nil)
-			error(Eperm);
-
-		qwrite(c->wq, a, n);
-		break;
-	case Qarp:
-		return arpwrite(f, a, n);
-	case Qiproute:
-		return routewrite(f, ch, a, n);
-	case Qlog:
-		netlogctl(f, a, n);
-		return n;
-	case Qndb:
-		return ndbwrite(f, a, offset, n);
-		break;
-	case Qctl:
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-		cb = parsecmd(a, n);
-
-		qlock(c);
-		if(waserror()) {
-			qunlock(c);
-			free(cb);
-			nexterror();
-		}
-		if(cb->nf < 1)
-			error("short control request");
-		if(strcmp(cb->f[0], "connect") == 0)
-			connectctlmsg(x, c, cb);
-		else if(strcmp(cb->f[0], "announce") == 0)
-			announcectlmsg(x, c, cb);
-		else if(strcmp(cb->f[0], "bind") == 0)
-			bindctlmsg(x, c, cb);
-		else if(strcmp(cb->f[0], "ttl") == 0)
-			ttlctlmsg(c, cb);
-		else if(strcmp(cb->f[0], "tos") == 0)
-			tosctlmsg(c, cb);
-		else if(strcmp(cb->f[0], "ignoreadvice") == 0)
-			c->ignoreadvice = 1;
-		else if(strcmp(cb->f[0], "addmulti") == 0){
-			if(cb->nf < 2)
-				error("addmulti needs interface address");
-			if(cb->nf == 2){
-				if(!ipismulticast(c->raddr))
-					error("addmulti for a non multicast address");
-				if (parseip(ia, cb->f[1]) == -1)
-					error(Ebadip);
-				ipifcaddmulti(c, c->raddr, ia);
-			} else {
-				if (parseip(ia, cb->f[1]) == -1 ||
-				    parseip(ma, cb->f[2]) == -1)
-					error(Ebadip);
-				if(!ipismulticast(ma))
-					error("addmulti for a non multicast address");
-				ipifcaddmulti(c, ma, ia);
-			}
-		} else if(strcmp(cb->f[0], "remmulti") == 0){
-			if(cb->nf < 2)
-				error("remmulti needs interface address");
-			if(!ipismulticast(c->raddr))
-				error("remmulti for a non multicast address");
-			if (parseip(ia, cb->f[1]) == -1)
-				error(Ebadip);
-			ipifcremmulti(c, c->raddr, ia);
-		} else if(strcmp(cb->f[0], "maxfragsize") == 0){
-			if(cb->nf < 2)
-				error("maxfragsize needs size");
-
-			c->maxfragsize = (int)strtol(cb->f[1], nil, 0);
-
-		} else if(x->ctl != nil) {
-			p = x->ctl(c, cb->f, cb->nf);
-			if(p != nil)
-				error(p);
-		} else
-			error("unknown control request");
-		qunlock(c);
-		free(cb);
-		poperror();
-	}
-	return n;
-}
-
-static long
-ipbwrite(Chan* ch, Block* bp, ulong offset)
-{
-	Conv *c;
-	Proto *x;
-	Fs *f;
-	int n;
-
-	switch(TYPE(ch->qid)){
-	case Qdata:
-		f = ipfs[ch->dev];
-		x = f->p[PROTO(ch->qid)];
-		c = x->conv[CONV(ch->qid)];
-
-		if(c->wq == nil)
-			error(Eperm);
-
-		if(bp->next)
-			bp = concatblock(bp);
-		n = BLEN(bp);
-		qbwrite(c->wq, bp);
-		return n;
-	default:
-		return devbwrite(ch, bp, offset);
-	}
-}
-
-Dev ipdevtab = {
-	'I',
-	"ip",
-
-	ipreset,
-	devinit,
-	devshutdown,
-	ipattach,
-	ipwalk,
-	ipstat,
-	ipopen,
-	ipcreate,
-	ipclose,
-	ipread,
-	ipbread,
-	ipwrite,
-	ipbwrite,
-	ipremove,
-	ipwstat,
-};
-
-int
-Fsproto(Fs *f, Proto *p)
-{
-	if(f->np >= Maxproto)
-		return -1;
-
-	p->f = f;
-
-	if(p->ipproto > 0){
-		if(f->t2p[p->ipproto] != nil)
-			return -1;
-		f->t2p[p->ipproto] = p;
-	}
-
-	p->qid.type = QTDIR;
-	p->qid.path = QID(f->np, 0, Qprotodir);
-	p->conv = malloc(sizeof(Conv*)*(p->nc+1));
-	if(p->conv == nil)
-		panic("Fsproto");
-
-	p->x = f->np;
-	p->nextrport = 600;
-	f->p[f->np++] = p;
-
-	return 0;
-}
-
-/*
- *  return true if this protocol is
- *  built in
- */
-int
-Fsbuiltinproto(Fs* f, uchar proto)
-{
-	return f->t2p[proto] != nil;
-}
-
-/*
- *  called with protocol locked
- */
-Conv*
-Fsprotoclone(Proto *p, char *user)
-{
-	Conv *c, **pp, **ep;
-
-retry:
-	c = nil;
-	ep = &p->conv[p->nc];
-	for(pp = p->conv; pp < ep; pp++) {
-		c = *pp;
-		if(c == nil){
-			c = malloc(sizeof(Conv));
-			if(c == nil)
-				error(Enomem);
-			qlock(c);
-			c->p = p;
-			c->x = pp - p->conv;
-			if(p->ptclsize != 0){
-				c->ptcl = malloc(p->ptclsize);
-				if(c->ptcl == nil) {
-					free(c);
-					error(Enomem);
-				}
-			}
-			*pp = c;
-			p->ac++;
-			c->eq = qopen(1024, Qmsg, 0, 0);
-			(*p->create)(c);
-			break;
-		}
-		if(canqlock(c)){
-			/*
-			 *  make sure both processes and protocol
-			 *  are done with this Conv
-			 */
-			if(c->inuse == 0 && (p->inuse == nil || (*p->inuse)(c) == 0))
-				break;
-
-			qunlock(c);
-		}
-	}
-	if(pp >= ep) {
-		if(p->gc)
-			print("Fsprotoclone: garbage collecting Convs\n");
-		if(p->gc != nil && (*p->gc)(p))
-			goto retry;
-		/* debugging: do we ever get here? */
-		if (cpuserver)
-			panic("Fsprotoclone: all conversations in use");
-		return nil;
-	}
-
-	c->inuse = 1;
-	kstrdup(&c->owner, user);
-	c->perm = 0660;
-	c->state = Idle;
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->r = nil;
-	c->rgen = 0;
-	c->lport = 0;
-	c->rport = 0;
-	c->restricted = 0;
-	c->maxfragsize = 0;
-	c->ttl = MAXTTL;
-	qreopen(c->rq);
-	qreopen(c->wq);
-	qreopen(c->eq);
-
-	qunlock(c);
-	return c;
-}
-
-int
-Fsconnected(Conv* c, char* msg)
-{
-	if(msg != nil && *msg != '\0')
-		strncpy(c->cerr, msg, ERRMAX-1);
-
-	switch(c->state){
-
-	case Announcing:
-		c->state = Announced;
-		break;
-
-	case Connecting:
-		c->state = Connected;
-		break;
-	}
-
-	wakeup(&c->cr);
-	return 0;
-}
-
-Proto*
-Fsrcvpcol(Fs* f, uchar proto)
-{
-	if(f->ipmux)
-		return f->ipmux;
-	else
-		return f->t2p[proto];
-}
-
-Proto*
-Fsrcvpcolx(Fs *f, uchar proto)
-{
-	return f->t2p[proto];
-}
-
-/*
- *  called with protocol locked
- */
-Conv*
-Fsnewcall(Conv *c, uchar *raddr, ushort rport, uchar *laddr, ushort lport, uchar version)
-{
-	Conv *nc;
-	Conv **l;
-	int i;
-
-	qlock(c);
-	i = 0;
-	for(l = &c->incall; *l; l = &(*l)->next)
-		i++;
-	if(i >= Maxincall) {
-		static int beenhere;
-
-		qunlock(c);
-		if (!beenhere) {
-			beenhere = 1;
-			print("Fsnewcall: incall queue full (%d) on port %d\n",
-				i, c->lport);
-		}
-		return nil;
-	}
-
-	/* find a free conversation */
-	nc = Fsprotoclone(c->p, network);
-	if(nc == nil) {
-		qunlock(c);
-		return nil;
-	}
-	ipmove(nc->raddr, raddr);
-	nc->rport = rport;
-	ipmove(nc->laddr, laddr);
-	nc->lport = lport;
-	nc->next = nil;
-	*l = nc;
-	nc->state = Connected;
-	nc->ipversion = version;
-
-	qunlock(c);
-
-	wakeup(&c->listenr);
-
-	return nc;
-}
-
-long
-ndbwrite(Fs *f, char *a, ulong off, int n)
-{
-	if(off > strlen(f->ndb))
-		error(Eio);
-	if(off+n >= sizeof(f->ndb))
-		error(Eio);
-	memmove(f->ndb+off, a, n);
-	f->ndb[off+n] = 0;
-	f->ndbvers++;
-	f->ndbmtime = seconds();
-	return n;
-}
-
-ulong
-scalednconv(void)
-{
-	if(cpuserver && conf.npage*BY2PG >= 128*MB)
-		return Nchans*4;
-	return Nchans;
-}

+ 0 - 161
sys/src/9/ip/eipconvtest.c

@@ -1,161 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include <u.h>
-#include <libc.h>
-
-enum
-{
-	Isprefix= 16,
-};
-
-uchar prefixvals[256] =
-{
-[0x00] 0 | Isprefix,
-[0x80] 1 | Isprefix,
-[0xC0] 2 | Isprefix,
-[0xE0] 3 | Isprefix,
-[0xF0] 4 | Isprefix,
-[0xF8] 5 | Isprefix,
-[0xFC] 6 | Isprefix,
-[0xFE] 7 | Isprefix,
-[0xFF] 8 | Isprefix,
-};
-
-uchar v4prefix[16] = {
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0xff, 0xff,
-	0, 0, 0, 0
-};
-
-void
-hnputl(void *p, ulong v)
-{
-	uchar *a;
-
-	a = p;
-	a[0] = v>>24;
-	a[1] = v>>16;
-	a[2] = v>>8;
-	a[3] = v;
-}
-
-int
-eipconv(va_list *arg, Fconv *f)
-{
-	char buf[8*5];
-	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
-	static char *ifmt = "%d.%d.%d.%d";
-	uchar *p, ip[16];
-	ulong *lp;
-	ushort s;
-	int i, j, n, eln, eli;
-
-	switch(f->chr) {
-	case 'E':		/* Ethernet address */
-		p = va_arg(*arg, uchar*);
-		sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
-		break;
-	case 'I':		/* Ip address */
-		p = va_arg(*arg, uchar*);
-common:
-		if(memcmp(p, v4prefix, 12) == 0)
-			sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
-		else {
-			/* find longest elision */
-			eln = eli = -1;
-			for(i = 0; i < 16; i += 2){
-				for(j = i; j < 16; j += 2)
-					if(p[j] != 0 || p[j+1] != 0)
-						break;
-				if(j > i && j - i > eln){
-					eli = i;
-					eln = j - i;
-				}
-			}
-
-			/* print with possible elision */
-			n = 0;
-			for(i = 0; i < 16; i += 2){
-				if(i == eli){
-					n += sprint(buf+n, "::");
-					i += eln;
-					if(i >= 16)
-						break;
-				} else if(i != 0)
-					n += sprint(buf+n, ":");
-				s = (p[i]<<8) + p[i+1];
-				n += sprint(buf+n, "%ux", s);
-			}
-		}
-		break;
-	case 'i':		/* v6 address as 4 longs */
-		lp = va_arg(*arg, ulong*);
-		for(i = 0; i < 4; i++)
-			hnputl(ip+4*i, *lp++);
-		p = ip;
-		goto common;
-	case 'V':		/* v4 ip address */
-		p = va_arg(*arg, uchar*);
-		sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
-		break;
-	case 'M':		/* ip mask */
-		p = va_arg(*arg, uchar*);
-
-		/* look for a prefix mask */
-		for(i = 0; i < 16; i++)
-			if(p[i] != 0xff)
-				break;
-		if(i < 16){
-			if((prefixvals[p[i]] & Isprefix) == 0)
-				goto common;
-			for(j = i+1; j < 16; j++)
-				if(p[j] != 0)
-					goto common;
-			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
-		} else
-			n = 8*16;
-
-		/* got one, use /xx format */
-		sprint(buf, "/%d", n);
-		break;
-	default:
-		strcpy(buf, "(eipconv)");
-	}
-	strconv(buf, f);
-	return sizeof(uchar*);
-}
-
-uchar testvec[11][16] =
-{
- { 0,0,0,0, 0,0,0,0, 0,0,0xff,0xff, 1,3,4,5, },
- { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
- { 0xff,0xff,0x80,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
- { 0xff,0xff,0xff,0xc0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
- { 0xff,0xff,0xff,0xff, 0xe0,0,0,0, 0,0,0,0, 0,0,0,0, },
- { 0xff,0xff,0xff,0xff, 0xff,0xf0,0,0, 0,0,0,0, 0,0,0,0, },
- { 0xff,0xff,0xff,0xff, 0xff,0xff,0xf8,0, 0,0,0,0, 0,0,0,0, },
- { 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, 0xff,0xff,0xff,0xff, },
- { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, },
- { 0,0,0,0, 0,0x11,0,0, 0,0,0,0, 0,0,0,0, },
- { 0,0,0,0x11, 0,0,0,0, 0,0,0,0, 0,0,0,0x12, },
-};
-
-void
-main(void)
-{
-	int i;
-
-	fmtinstall('I', eipconv);
-	fmtinstall('M', eipconv);
-	for(i = 0; i < 11; i++)
-		print("%I\n%M\n", testvec[i], testvec[i]);
-	exits(0);
-}

+ 0 - 1121
sys/src/9/ip/esp.c

@@ -1,1121 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Encapsulating Security Payload for IPsec for IPv4, rfc1827.
- * extended to IPv6.
- * rfc2104 defines hmac computation.
- *	currently only implements tunnel mode.
- * TODO: verify aes algorithms;
- *	transport mode (host-to-host)
- */
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-#include	"ipv6.h"
-#include	"libsec.h"
-
-#define BITS2BYTES(bi) (((bi) + BI2BY - 1) / BI2BY)
-#define BYTES2BITS(by)  ((by) * BI2BY)
-
-typedef struct Algorithm Algorithm;
-typedef struct Esp4hdr Esp4hdr;
-typedef struct Esp6hdr Esp6hdr;
-typedef struct Espcb Espcb;
-typedef struct Esphdr Esphdr;
-typedef struct Esppriv Esppriv;
-typedef struct Esptail Esptail;
-typedef struct Userhdr Userhdr;
-
-enum {
-	Encrypt,
-	Decrypt,
-
-	IP_ESPPROTO	= 50,	/* IP v4 and v6 protocol number */
-	Esp4hdrlen	= IP4HDR + 8,
-	Esp6hdrlen	= IP6HDR + 8,
-
-	Esptaillen	= 2,	/* does not include pad or auth data */
-	Userhdrlen	= 4,	/* user-visible header size - if enabled */
-
-	Desblk	 = BITS2BYTES(64),
-	Des3keysz = BITS2BYTES(192),
-
-	Aesblk	 = BITS2BYTES(128),
-	Aeskeysz = BITS2BYTES(128),
-};
-
-struct Esphdr
-{
-	uchar	espspi[4];	/* Security parameter index */
-	uchar	espseq[4];	/* Sequence number */
-	uchar	payload[];
-};
-
-/*
- * tunnel-mode (network-to-network, etc.) layout is:
- * new IP hdrs | ESP hdr |
- *	 enc { orig IP hdrs | TCP/UDP hdr | user data | ESP trailer } | ESP ICV
- *
- * transport-mode (host-to-host) layout would be:
- *	orig IP hdrs | ESP hdr |
- *			enc { TCP/UDP hdr | user data | ESP trailer } | ESP ICV
- */
-struct Esp4hdr
-{
-	/* ipv4 header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	Unused;
-	uchar	espproto;	/* Protocol */
-	uchar	espplen[2];	/* Header plus data length */
-	uchar	espsrc[4];	/* Ip source */
-	uchar	espdst[4];	/* Ip destination */
-
-	Esphdr;
-};
-
-/* tunnel-mode layout */
-struct Esp6hdr
-{
-	IPV6HDR;
-	Esphdr;
-};
-
-struct Esptail
-{
-	uchar	pad;
-	uchar	nexthdr;
-};
-
-/* IP-version-dependent data */
-typedef struct Versdep Versdep;
-struct Versdep
-{
-	ulong	version;
-	ulong	iphdrlen;
-	ulong	hdrlen;		/* iphdrlen + esp hdr len */
-	ulong	spi;
-	uchar	laddr[IPaddrlen];
-	uchar	raddr[IPaddrlen];
-};
-
-/* header as seen by the user */
-struct Userhdr
-{
-	uchar	nexthdr;	/* next protocol */
-	uchar	unused[3];
-};
-
-struct Esppriv
-{
-	uvlong	in;
-	ulong	inerrors;
-};
-
-/*
- *  protocol specific part of Conv
- */
-struct Espcb
-{
-	int	incoming;
-	int	header;		/* user-level header */
-	ulong	spi;
-	ulong	seq;		/* last seq sent */
-	ulong	window;		/* for replay attacks */
-
-	char	*espalg;
-	void	*espstate;	/* other state for esp */
-	int	espivlen;	/* in bytes */
-	int	espblklen;
-	int	(*cipher)(Espcb*, uchar *buf, int len);
-
-	char	*ahalg;
-	void	*ahstate;	/* other state for esp */
-	int	ahlen;		/* auth data length in bytes */
-	int	ahblklen;
-	int	(*auth)(Espcb*, uchar *buf, int len, uchar *hash);
-	DigestState *ds;
-};
-
-struct Algorithm
-{
-	char 	*name;
-	int	keylen;		/* in bits */
-	void	(*init)(Espcb*, char* name, uchar *key, unsigned keylen);
-};
-
-static	Conv* convlookup(Proto *esp, ulong spi);
-static	char *setalg(Espcb *ecb, char **f, int n, Algorithm *alg);
-static	void espkick(void *x);
-
-static	void nullespinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void des3espinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void aescbcespinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void aesctrespinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void desespinit(Espcb *ecb, char *name, uchar *k, unsigned n);
-
-static	void nullahinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void shaahinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void aesahinit(Espcb*, char*, uchar *key, unsigned keylen);
-static	void md5ahinit(Espcb*, char*, uchar *key, unsigned keylen);
-
-static Algorithm espalg[] =
-{
-	"null",		0,	nullespinit,
-	"des3_cbc",	192,	des3espinit,	/* new rfc2451, des-ede3 */
-	"aes_128_cbc",	128,	aescbcespinit,	/* new rfc3602 */
-	"aes_ctr",	128,	aesctrespinit,	/* new rfc3686 */
-	"des_56_cbc",	64,	desespinit,	/* rfc2405, deprecated */
-	/* rc4 was never required, was used in original bandt */
-//	"rc4_128",	128,	rc4espinit,
-	nil,		0,	nil,
-};
-
-static Algorithm ahalg[] =
-{
-	"null",		0,	nullahinit,
-	"hmac_sha1_96",	128,	shaahinit,	/* rfc2404 */
-	"aes_xcbc_mac_96", 128,	aesahinit,	/* new rfc3566 */
-	"hmac_md5_96",	128,	md5ahinit,	/* rfc2403 */
-	nil,		0,	nil,
-};
-
-static char*
-espconnect(Conv *c, char **argv, int argc)
-{
-	char *p, *pp, *e = nil;
-	ulong spi;
-	Espcb *ecb = (Espcb*)c->ptcl;
-
-	switch(argc) {
-	default:
-		e = "bad args to connect";
-		break;
-	case 2:
-		p = strchr(argv[1], '!');
-		if(p == nil){
-			e = "malformed address";
-			break;
-		}
-		*p++ = 0;
-		if (parseip(c->raddr, argv[1]) == -1) {
-			e = Ebadip;
-			break;
-		}
-		findlocalip(c->p->f, c->laddr, c->raddr);
-		ecb->incoming = 0;
-		ecb->seq = 0;
-		if(strcmp(p, "*") == 0) {
-			qlock(c->p);
-			for(;;) {
-				spi = nrand(1<<16) + 256;
-				if(convlookup(c->p, spi) == nil)
-					break;
-			}
-			qunlock(c->p);
-			ecb->spi = spi;
-			ecb->incoming = 1;
-			qhangup(c->wq, nil);
-		} else {
-			spi = strtoul(p, &pp, 10);
-			if(pp == p) {
-				e = "malformed address";
-				break;
-			}
-			ecb->spi = spi;
-			qhangup(c->rq, nil);
-		}
-		nullespinit(ecb, "null", nil, 0);
-		nullahinit(ecb, "null", nil, 0);
-	}
-	Fsconnected(c, e);
-
-	return e;
-}
-
-
-static int
-espstate(Conv *c, char *state, int n)
-{
-	return snprint(state, n, "%s", c->inuse?"Open\n":"Closed\n");
-}
-
-static void
-espcreate(Conv *c)
-{
-	c->rq = qopen(64*1024, Qmsg, 0, 0);
-	c->wq = qopen(64*1024, Qkick, espkick, c);
-}
-
-static void
-espclose(Conv *c)
-{
-	Espcb *ecb;
-
-	qclose(c->rq);
-	qclose(c->wq);
-	qclose(c->eq);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-
-	ecb = (Espcb*)c->ptcl;
-	free(ecb->espstate);
-	free(ecb->ahstate);
-	memset(ecb, 0, sizeof(Espcb));
-}
-
-static int
-convipvers(Conv *c)
-{
-	if((memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
-	    memcmp(c->laddr, v4prefix, IPv4off) == 0) ||
-	    ipcmp(c->raddr, IPnoaddr) == 0)
-		return V4;
-	else
-		return V6;
-}
-
-static int
-pktipvers(Fs *f, Block **bpp)
-{
-	if (*bpp == nil || BLEN(*bpp) == 0) {
-		/* get enough to identify the IP version */
-		*bpp = pullupblock(*bpp, IP4HDR);
-		if(*bpp == nil) {
-			netlog(f, Logesp, "esp: short packet\n");
-			return 0;
-		}
-	}
-	return (((Esp4hdr*)(*bpp)->rp)->vihl & 0xf0) == IP_VER4? V4: V6;
-}
-
-static void
-getverslens(int version, Versdep *vp)
-{
-	vp->version = version;
-	switch(vp->version) {
-	case V4:
-		vp->iphdrlen = IP4HDR;
-		vp->hdrlen   = Esp4hdrlen;
-		break;
-	case V6:
-		vp->iphdrlen = IP6HDR;
-		vp->hdrlen   = Esp6hdrlen;
-		break;
-	default:
-		panic("esp: getverslens version %d wrong", version);
-	}
-}
-
-static void
-getpktspiaddrs(uchar *pkt, Versdep *vp)
-{
-	Esp4hdr *eh4;
-	Esp6hdr *eh6;
-
-	switch(vp->version) {
-	case V4:
-		eh4 = (Esp4hdr*)pkt;
-		v4tov6(vp->raddr, eh4->espsrc);
-		v4tov6(vp->laddr, eh4->espdst);
-		vp->spi = nhgetl(eh4->espspi);
-		break;
-	case V6:
-		eh6 = (Esp6hdr*)pkt;
-		ipmove(vp->raddr, eh6->src);
-		ipmove(vp->laddr, eh6->dst);
-		vp->spi = nhgetl(eh6->espspi);
-		break;
-	default:
-		panic("esp: getpktspiaddrs vp->version %ld wrong", vp->version);
-	}
-}
-
-/*
- * encapsulate next IP packet on x's write queue in IP/ESP packet
- * and initiate output of the result.
- */
-static void
-espkick(void *x)
-{
-	int nexthdr, payload, pad, align;
-	uchar *auth;
-	Block *bp;
-	Conv *c = x;
-	Esp4hdr *eh4;
-	Esp6hdr *eh6;
-	Espcb *ecb;
-	Esptail *et;
-	Userhdr *uh;
-	Versdep vers;
-
-	getverslens(convipvers(c), &vers);
-	bp = qget(c->wq);
-	if(bp == nil)
-		return;
-
-	qlock(c);
-	ecb = c->ptcl;
-
-	if(ecb->header) {
-		/* make sure the message has a User header */
-		bp = pullupblock(bp, Userhdrlen);
-		if(bp == nil) {
-			qunlock(c);
-			return;
-		}
-		uh = (Userhdr*)bp->rp;
-		nexthdr = uh->nexthdr;
-		bp->rp += Userhdrlen;
-	} else {
-		nexthdr = 0;	/* what should this be? */
-	}
-
-	payload = BLEN(bp) + ecb->espivlen;
-
-	/* Make space to fit ip header */
-	bp = padblock(bp, vers.hdrlen + ecb->espivlen);
-	getpktspiaddrs(bp->rp, &vers);
-
-	align = 4;
-	if(ecb->espblklen > align)
-		align = ecb->espblklen;
-	if(align % ecb->ahblklen != 0)
-		panic("espkick: ahblklen is important after all");
-	pad = (align-1) - (payload + Esptaillen-1)%align;
-
-	/*
-	 * Make space for tail
-	 * this is done by calling padblock with a negative size
-	 * Padblock does not change bp->wp!
-	 */
-	bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen));
-	bp->wp += pad+Esptaillen+ecb->ahlen;
-
-	et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad);
-
-	/* fill in tail */
-	et->pad = pad;
-	et->nexthdr = nexthdr;
-
-	/* encrypt the payload */
-	ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen);
-	auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen;
-
-	/* fill in head; construct a new IP header and an ESP header */
-	if (vers.version == V4) {
-		eh4 = (Esp4hdr *)bp->rp;
-		eh4->vihl = IP_VER4;
-		v6tov4(eh4->espsrc, c->laddr);
-		v6tov4(eh4->espdst, c->raddr);
-		eh4->espproto = IP_ESPPROTO;
-		eh4->frag[0] = 0;
-		eh4->frag[1] = 0;
-
-		hnputl(eh4->espspi, ecb->spi);
-		hnputl(eh4->espseq, ++ecb->seq);
-	} else {
-		eh6 = (Esp6hdr *)bp->rp;
-		eh6->vcf[0] = IP_VER6;
-		ipmove(eh6->src, c->laddr);
-		ipmove(eh6->dst, c->raddr);
-		eh6->proto = IP_ESPPROTO;
-
-		hnputl(eh6->espspi, ecb->spi);
-		hnputl(eh6->espseq, ++ecb->seq);
-	}
-
-	/* compute secure hash */
-	ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) +
-		payload + pad + Esptaillen, auth);
-
-	qunlock(c);
-	/* print("esp: pass down: %uld\n", BLEN(bp)); */
-	if (vers.version == V4)
-		ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
-	else
-		ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
-}
-
-/*
- * decapsulate IP packet from IP/ESP packet in bp and
- * pass the result up the spi's Conv's read queue.
- */
-void
-espiput(Proto *esp, Ipifc*, Block *bp)
-{
-	int payload, nexthdr;
-	uchar *auth, *espspi;
-	Conv *c;
-	Espcb *ecb;
-	Esptail *et;
-	Fs *f;
-	Userhdr *uh;
-	Versdep vers;
-
-	f = esp->f;
-
-	getverslens(pktipvers(f, &bp), &vers);
-
-	bp = pullupblock(bp, vers.hdrlen + Esptaillen);
-	if(bp == nil) {
-		netlog(f, Logesp, "esp: short packet\n");
-		return;
-	}
-	getpktspiaddrs(bp->rp, &vers);
-
-	qlock(esp);
-	/* Look for a conversation structure for this port */
-	c = convlookup(esp, vers.spi);
-	if(c == nil) {
-		qunlock(esp);
-		netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr,
-			vers.laddr, vers.spi);
-		icmpnoconv(f, bp);
-		freeblist(bp);
-		return;
-	}
-
-	qlock(c);
-	qunlock(esp);
-
-	ecb = c->ptcl;
-	/* too hard to do decryption/authentication on block lists */
-	if(bp->next)
-		bp = concatblock(bp);
-
-	if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) {
-		qunlock(c);
-		netlog(f, Logesp, "esp: short block %I -> %I!%lud\n", vers.raddr,
-			vers.laddr, vers.spi);
-		freeb(bp);
-		return;
-	}
-
-	auth = bp->wp - ecb->ahlen;
-	espspi = vers.version == V4?	((Esp4hdr*)bp->rp)->espspi:
-					((Esp6hdr*)bp->rp)->espspi;
-
-	/* compute secure hash and authenticate */
-	if(!ecb->auth(ecb, espspi, auth - espspi, auth)) {
-		qunlock(c);
-print("esp: bad auth %I -> %I!%ld\n", vers.raddr, vers.laddr, vers.spi);
-		netlog(f, Logesp, "esp: bad auth %I -> %I!%lud\n", vers.raddr,
-			vers.laddr, vers.spi);
-		freeb(bp);
-		return;
-	}
-
-	payload = BLEN(bp) - vers.hdrlen - ecb->ahlen;
-	if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) {
-		qunlock(c);
-		netlog(f, Logesp, "esp: bad length %I -> %I!%lud payload=%d BLEN=%lud\n",
-			vers.raddr, vers.laddr, vers.spi, payload, BLEN(bp));
-		freeb(bp);
-		return;
-	}
-
-	/* decrypt payload */
-	if(!ecb->cipher(ecb, bp->rp + vers.hdrlen, payload)) {
-		qunlock(c);
-print("esp: cipher failed %I -> %I!%ld: %s\n", vers.raddr, vers.laddr, vers.spi, up->errstr);
-		netlog(f, Logesp, "esp: cipher failed %I -> %I!%lud: %s\n",
-			vers.raddr, vers.laddr, vers.spi, up->errstr);
-		freeb(bp);
-		return;
-	}
-
-	payload -= Esptaillen;
-	et = (Esptail*)(bp->rp + vers.hdrlen + payload);
-	payload -= et->pad + ecb->espivlen;
-	nexthdr = et->nexthdr;
-	if(payload <= 0) {
-		qunlock(c);
-		netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%lud\n",
-			vers.raddr, vers.laddr, vers.spi);
-		freeb(bp);
-		return;
-	}
-
-	/* trim packet */
-	bp->rp += vers.hdrlen + ecb->espivlen; /* toss original IP & ESP hdrs */
-	bp->wp = bp->rp + payload;
-	if(ecb->header) {
-		/* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */
-		bp->rp -= Userhdrlen;
-		uh = (Userhdr*)bp->rp;
-		memset(uh, 0, Userhdrlen);
-		uh->nexthdr = nexthdr;
-	}
-
-	/* ingress filtering here? */
-
-	if(qfull(c->rq)){
-		netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", vers.raddr,
-			vers.laddr, vers.spi);
-		freeblist(bp);
-	}else {
-//		print("esp: pass up: %uld\n", BLEN(bp));
-		qpass(c->rq, bp);	/* pass packet up the read queue */
-	}
-
-	qunlock(c);
-}
-
-char*
-espctl(Conv *c, char **f, int n)
-{
-	Espcb *ecb = c->ptcl;
-	char *e = nil;
-
-	if(strcmp(f[0], "esp") == 0)
-		e = setalg(ecb, f, n, espalg);
-	else if(strcmp(f[0], "ah") == 0)
-		e = setalg(ecb, f, n, ahalg);
-	else if(strcmp(f[0], "header") == 0)
-		ecb->header = 1;
-	else if(strcmp(f[0], "noheader") == 0)
-		ecb->header = 0;
-	else
-		e = "unknown control request";
-	return e;
-}
-
-/* called from icmp(v6) for unreachable hosts, time exceeded, etc. */
-void
-espadvise(Proto *esp, Block *bp, char *msg)
-{
-	Conv *c;
-	Versdep vers;
-
-	getverslens(pktipvers(esp->f, &bp), &vers);
-	getpktspiaddrs(bp->rp, &vers);
-
-	qlock(esp);
-	c = convlookup(esp, vers.spi);
-	if(c != nil) {
-		qhangup(c->rq, msg);
-		qhangup(c->wq, msg);
-	}
-	qunlock(esp);
-	freeblist(bp);
-}
-
-int
-espstats(Proto *esp, char *buf, int len)
-{
-	Esppriv *upriv;
-
-	upriv = esp->priv;
-	return snprint(buf, len, "%llud %lud\n",
-		upriv->in,
-		upriv->inerrors);
-}
-
-static int
-esplocal(Conv *c, char *buf, int len)
-{
-	Espcb *ecb = c->ptcl;
-	int n;
-
-	qlock(c);
-	if(ecb->incoming)
-		n = snprint(buf, len, "%I!%uld\n", c->laddr, ecb->spi);
-	else
-		n = snprint(buf, len, "%I\n", c->laddr);
-	qunlock(c);
-	return n;
-}
-
-static int
-espremote(Conv *c, char *buf, int len)
-{
-	Espcb *ecb = c->ptcl;
-	int n;
-
-	qlock(c);
-	if(ecb->incoming)
-		n = snprint(buf, len, "%I\n", c->raddr);
-	else
-		n = snprint(buf, len, "%I!%uld\n", c->raddr, ecb->spi);
-	qunlock(c);
-	return n;
-}
-
-static	Conv*
-convlookup(Proto *esp, ulong spi)
-{
-	Conv *c, **p;
-	Espcb *ecb;
-
-	for(p=esp->conv; *p; p++){
-		c = *p;
-		ecb = c->ptcl;
-		if(ecb->incoming && ecb->spi == spi)
-			return c;
-	}
-	return nil;
-}
-
-static char *
-setalg(Espcb *ecb, char **f, int n, Algorithm *alg)
-{
-	uchar *key;
-	int c, nbyte, nchar;
-	uint i;
-
-	if(n < 2 || n > 3)
-		return "bad format";
-	for(; alg->name; alg++)
-		if(strcmp(f[1], alg->name) == 0)
-			break;
-	if(alg->name == nil)
-		return "unknown algorithm";
-
-	nbyte = (alg->keylen + 7) >> 3;
-	if (n == 2)
-		nchar = 0;
-	else
-		nchar = strlen(f[2]);
-	if(nchar != 2 * nbyte)			/* TODO: maybe < is ok */
-		return "key not required length";
-	/* convert hex digits from ascii, in place */
-	for(i=0; i<nchar; i++) {
-		c = f[2][i];
-		if(c >= '0' && c <= '9')
-			f[2][i] -= '0';
-		else if(c >= 'a' && c <= 'f')
-			f[2][i] -= 'a'-10;
-		else if(c >= 'A' && c <= 'F')
-			f[2][i] -= 'A'-10;
-		else
-			return "non-hex character in key";
-	}
-	/* collapse hex digits into complete bytes in reverse order in key */
-	key = smalloc(nbyte);
-	for(i = 0; i < nchar && i/2 < nbyte; i++) {
-		c = f[2][nchar-i-1];
-		if(i&1)
-			c <<= 4;
-		key[i/2] |= c;
-	}
-
-	alg->init(ecb, alg->name, key, alg->keylen);
-	free(key);
-	return nil;
-}
-
-
-/*
- * null encryption
- */
-
-static int
-nullcipher(Espcb*, uchar*, int)
-{
-	return 1;
-}
-
-static void
-nullespinit(Espcb *ecb, char *name, uchar*, unsigned)
-{
-	ecb->espalg = name;
-	ecb->espblklen = 1;
-	ecb->espivlen = 0;
-	ecb->cipher = nullcipher;
-}
-
-static int
-nullauth(Espcb*, uchar*, int, uchar*)
-{
-	return 1;
-}
-
-static void
-nullahinit(Espcb *ecb, char *name, uchar*, unsigned)
-{
-	ecb->ahalg = name;
-	ecb->ahblklen = 1;
-	ecb->ahlen = 0;
-	ecb->auth = nullauth;
-}
-
-
-/*
- * sha1
- */
-
-static void
-seanq_hmac_sha1(uchar hash[SHA1dlen], uchar *t, long tlen, uchar *key, long klen)
-{
-	int i;
-	uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[SHA1dlen];
-	DigestState *digest;
-
-	memset(ipad, 0x36, Hmacblksz);
-	memset(opad, 0x5c, Hmacblksz);
-	ipad[Hmacblksz] = opad[Hmacblksz] = 0;
-	for(i = 0; i < klen; i++){
-		ipad[i] ^= key[i];
-		opad[i] ^= key[i];
-	}
-	digest = sha1(ipad, Hmacblksz, nil, nil);
-	sha1(t, tlen, innerhash, digest);
-	digest = sha1(opad, Hmacblksz, nil, nil);
-	sha1(innerhash, SHA1dlen, hash, digest);
-}
-
-static int
-shaauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
-{
-	int r;
-	uchar hash[SHA1dlen];
-
-	memset(hash, 0, SHA1dlen);
-	seanq_hmac_sha1(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
-	r = memcmp(auth, hash, ecb->ahlen) == 0;
-	memmove(auth, hash, ecb->ahlen);
-	return r;
-}
-
-static void
-shaahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
-{
-	if(klen != 128)
-		panic("shaahinit: bad keylen");
-	klen /= BI2BY;
-
-	ecb->ahalg = name;
-	ecb->ahblklen = 1;
-	ecb->ahlen = BITS2BYTES(96);
-	ecb->auth = shaauth;
-	ecb->ahstate = smalloc(klen);
-	memmove(ecb->ahstate, key, klen);
-}
-
-
-/*
- * aes
- */
-
-/* ah_aes_xcbc_mac_96, rfc3566 */
-static int
-aesahauth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
-{
-	int r;
-	uchar hash[AESdlen];
-
-	memset(hash, 0, AESdlen);
-	ecb->ds = hmac_aes(t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(96), hash,
-		ecb->ds);
-	r = memcmp(auth, hash, ecb->ahlen) == 0;
-	memmove(auth, hash, ecb->ahlen);
-	return r;
-}
-
-static void
-aesahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
-{
-	if(klen != 128)
-		panic("aesahinit: keylen not 128");
-	klen /= BI2BY;
-
-	ecb->ahalg = name;
-	ecb->ahblklen = 1;
-	ecb->ahlen = BITS2BYTES(96);
-	ecb->auth = aesahauth;
-	ecb->ahstate = smalloc(klen);
-	memmove(ecb->ahstate, key, klen);
-}
-
-static int
-aescbccipher(Espcb *ecb, uchar *p, int n)	/* 128-bit blocks */
-{
-	uchar tmp[AESbsize], q[AESbsize];
-	uchar *pp, *tp, *ip, *eip, *ep;
-	AESstate *ds = ecb->espstate;
-
-	ep = p + n;
-	if(ecb->incoming) {
-		memmove(ds->ivec, p, AESbsize);
-		p += AESbsize;
-		while(p < ep){
-			memmove(tmp, p, AESbsize);
-			aes_decrypt(ds->dkey, ds->rounds, p, q);
-			memmove(p, q, AESbsize);
-			tp = tmp;
-			ip = ds->ivec;
-			for(eip = ip + AESbsize; ip < eip; ){
-				*p++ ^= *ip;
-				*ip++ = *tp++;
-			}
-		}
-	} else {
-		memmove(p, ds->ivec, AESbsize);
-		for(p += AESbsize; p < ep; p += AESbsize){
-			pp = p;
-			ip = ds->ivec;
-			for(eip = ip + AESbsize; ip < eip; )
-				*pp++ ^= *ip++;
-			aes_encrypt(ds->ekey, ds->rounds, p, q);
-			memmove(ds->ivec, q, AESbsize);
-			memmove(p, q, AESbsize);
-		}
-	}
-	return 1;
-}
-
-static void
-aescbcespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
-{
-	uchar key[Aeskeysz], ivec[Aeskeysz];
-	int i;
-
-	n = BITS2BYTES(n);
-	if(n > Aeskeysz)
-		n = Aeskeysz;
-	memset(key, 0, sizeof(key));
-	memmove(key, k, n);
-	for(i = 0; i < Aeskeysz; i++)
-		ivec[i] = nrand(256);
-	ecb->espalg = name;
-	ecb->espblklen = Aesblk;
-	ecb->espivlen = Aesblk;
-	ecb->cipher = aescbccipher;
-	ecb->espstate = smalloc(sizeof(AESstate));
-	setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
-}
-
-static int
-aesctrcipher(Espcb *ecb, uchar *p, int n)	/* 128-bit blocks */
-{
-	uchar tmp[AESbsize], q[AESbsize];
-	uchar *pp, *tp, *ip, *eip, *ep;
-	AESstate *ds = ecb->espstate;
-
-	ep = p + n;
-	if(ecb->incoming) {
-		memmove(ds->ivec, p, AESbsize);
-		p += AESbsize;
-		while(p < ep){
-			memmove(tmp, p, AESbsize);
-			aes_decrypt(ds->dkey, ds->rounds, p, q);
-			memmove(p, q, AESbsize);
-			tp = tmp;
-			ip = ds->ivec;
-			for(eip = ip + AESbsize; ip < eip; ){
-				*p++ ^= *ip;
-				*ip++ = *tp++;
-			}
-		}
-	} else {
-		memmove(p, ds->ivec, AESbsize);
-		for(p += AESbsize; p < ep; p += AESbsize){
-			pp = p;
-			ip = ds->ivec;
-			for(eip = ip + AESbsize; ip < eip; )
-				*pp++ ^= *ip++;
-			aes_encrypt(ds->ekey, ds->rounds, p, q);
-			memmove(ds->ivec, q, AESbsize);
-			memmove(p, q, AESbsize);
-		}
-	}
-	return 1;
-}
-
-static void
-aesctrespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
-{
-	uchar key[Aesblk], ivec[Aesblk];
-	int i;
-
-	n = BITS2BYTES(n);
-	if(n > Aeskeysz)
-		n = Aeskeysz;
-	memset(key, 0, sizeof(key));
-	memmove(key, k, n);
-	for(i = 0; i < Aesblk; i++)
-		ivec[i] = nrand(256);
-	ecb->espalg = name;
-	ecb->espblklen = Aesblk;
-	ecb->espivlen = Aesblk;
-	ecb->cipher = aesctrcipher;
-	ecb->espstate = smalloc(sizeof(AESstate));
-	setupAESstate(ecb->espstate, key, n /* keybytes */, ivec);
-}
-
-
-/*
- * md5
- */
-
-static void
-seanq_hmac_md5(uchar hash[MD5dlen], uchar *t, long tlen, uchar *key, long klen)
-{
-	int i;
-	uchar ipad[Hmacblksz+1], opad[Hmacblksz+1], innerhash[MD5dlen];
-	DigestState *digest;
-
-	memset(ipad, 0x36, Hmacblksz);
-	memset(opad, 0x5c, Hmacblksz);
-	ipad[Hmacblksz] = opad[Hmacblksz] = 0;
-	for(i = 0; i < klen; i++){
-		ipad[i] ^= key[i];
-		opad[i] ^= key[i];
-	}
-	digest = md5(ipad, Hmacblksz, nil, nil);
-	md5(t, tlen, innerhash, digest);
-	digest = md5(opad, Hmacblksz, nil, nil);
-	md5(innerhash, MD5dlen, hash, digest);
-}
-
-static int
-md5auth(Espcb *ecb, uchar *t, int tlen, uchar *auth)
-{
-	uchar hash[MD5dlen];
-	int r;
-
-	memset(hash, 0, MD5dlen);
-	seanq_hmac_md5(hash, t, tlen, (uchar*)ecb->ahstate, BITS2BYTES(128));
-	r = memcmp(auth, hash, ecb->ahlen) == 0;
-	memmove(auth, hash, ecb->ahlen);
-	return r;
-}
-
-static void
-md5ahinit(Espcb *ecb, char *name, uchar *key, unsigned klen)
-{
-	if(klen != 128)
-		panic("md5ahinit: bad keylen");
-	klen = BITS2BYTES(klen);
-	ecb->ahalg = name;
-	ecb->ahblklen = 1;
-	ecb->ahlen = BITS2BYTES(96);
-	ecb->auth = md5auth;
-	ecb->ahstate = smalloc(klen);
-	memmove(ecb->ahstate, key, klen);
-}
-
-
-/*
- * des, single and triple
- */
-
-static int
-descipher(Espcb *ecb, uchar *p, int n)
-{
-	DESstate *ds = ecb->espstate;
-
-	if(ecb->incoming) {
-		memmove(ds->ivec, p, Desblk);
-		desCBCdecrypt(p + Desblk, n - Desblk, ds);
-	} else {
-		memmove(p, ds->ivec, Desblk);
-		desCBCencrypt(p + Desblk, n - Desblk, ds);
-	}
-	return 1;
-}
-
-static int
-des3cipher(Espcb *ecb, uchar *p, int n)
-{
-	DES3state *ds = ecb->espstate;
-
-	if(ecb->incoming) {
-		memmove(ds->ivec, p, Desblk);
-		des3CBCdecrypt(p + Desblk, n - Desblk, ds);
-	} else {
-		memmove(p, ds->ivec, Desblk);
-		des3CBCencrypt(p + Desblk, n - Desblk, ds);
-	}
-	return 1;
-}
-
-static void
-desespinit(Espcb *ecb, char *name, uchar *k, unsigned n)
-{
-	uchar key[Desblk], ivec[Desblk];
-	int i;
-
-	n = BITS2BYTES(n);
-	if(n > Desblk)
-		n = Desblk;
-	memset(key, 0, sizeof(key));
-	memmove(key, k, n);
-	for(i = 0; i < Desblk; i++)
-		ivec[i] = nrand(256);
-	ecb->espalg = name;
-	ecb->espblklen = Desblk;
-	ecb->espivlen = Desblk;
-
-	ecb->cipher = descipher;
-	ecb->espstate = smalloc(sizeof(DESstate));
-	setupDESstate(ecb->espstate, key, ivec);
-}
-
-static void
-des3espinit(Espcb *ecb, char *name, uchar *k, unsigned n)
-{
-	uchar key[3][Desblk], ivec[Desblk];
-	int i;
-
-	n = BITS2BYTES(n);
-	if(n > Des3keysz)
-		n = Des3keysz;
-	memset(key, 0, sizeof(key));
-	memmove(key, k, n);
-	for(i = 0; i < Desblk; i++)
-		ivec[i] = nrand(256);
-	ecb->espalg = name;
-	ecb->espblklen = Desblk;
-	ecb->espivlen = Desblk;
-
-	ecb->cipher = des3cipher;
-	ecb->espstate = smalloc(sizeof(DES3state));
-	setupDES3state(ecb->espstate, key, ivec);
-}
-
-
-/*
- * interfacing to devip
- */
-void
-espinit(Fs *fs)
-{
-	Proto *esp;
-
-	esp = smalloc(sizeof(Proto));
-	esp->priv = smalloc(sizeof(Esppriv));
-	esp->name = "esp";
-	esp->connect = espconnect;
-	esp->announce = nil;
-	esp->ctl = espctl;
-	esp->state = espstate;
-	esp->create = espcreate;
-	esp->close = espclose;
-	esp->rcv = espiput;
-	esp->advise = espadvise;
-	esp->stats = espstats;
-	esp->local = esplocal;
-	esp->remote = espremote;
-	esp->ipproto = IP_ESPPROTO;
-	esp->nc = Nchans;
-	esp->ptclsize = sizeof(Espcb);
-
-	Fsproto(fs, esp);
-}

+ 0 - 774
sys/src/9/ip/ethermedium.c

@@ -1,774 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "../port/netif.h"
-#include "ip.h"
-#include "ipv6.h"
-
-typedef struct Etherhdr Etherhdr;
-struct Etherhdr
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	t[2];
-};
-
-static uchar ipbroadcast[IPaddrlen] = {
-	0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff,0xff,
-	0xff,0xff,0xff,0xff,
-};
-
-static uchar etherbroadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
-static void	etherread4(void *a);
-static void	etherread6(void *a);
-static void	etherbind(Ipifc *ifc, int argc, char **argv);
-static void	etherunbind(Ipifc *ifc);
-static void	etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
-static void	etheraddmulti(Ipifc *ifc, uchar *a, uchar *ia);
-static void	etherremmulti(Ipifc *ifc, uchar *a, uchar *ia);
-static Block*	multicastarp(Fs *f, Arpent *a, Medium*, uchar *mac);
-static void	sendarp(Ipifc *ifc, Arpent *a);
-static void	sendgarp(Ipifc *ifc, uchar*);
-static int	multicastea(uchar *ea, uchar *ip);
-static void	recvarpproc(void*);
-static void	resolveaddr6(Ipifc *ifc, Arpent *a);
-static void	etherpref2addr(uchar *pref, uchar *ea);
-
-Medium ethermedium =
-{
-.name=		"ether",
-.hsize=		14,
-.mintu=		60,
-.maxtu=		1514,
-.maclen=	6,
-.bind=		etherbind,
-.unbind=	etherunbind,
-.bwrite=	etherbwrite,
-.addmulti=	etheraddmulti,
-.remmulti=	etherremmulti,
-.ares=		arpenter,
-.areg=		sendgarp,
-.pref2addr=	etherpref2addr,
-};
-
-Medium gbemedium =
-{
-.name=		"gbe",
-.hsize=		14,
-.mintu=		60,
-.maxtu=		9014,
-.maclen=	6,
-.bind=		etherbind,
-.unbind=	etherunbind,
-.bwrite=	etherbwrite,
-.addmulti=	etheraddmulti,
-.remmulti=	etherremmulti,
-.ares=		arpenter,
-.areg=		sendgarp,
-.pref2addr=	etherpref2addr,
-};
-
-typedef struct	Etherrock Etherrock;
-struct Etherrock
-{
-	Fs	*f;		/* file system we belong to */
-	Proc	*arpp;		/* arp process */
-	Proc	*read4p;	/* reading process (v4)*/
-	Proc	*read6p;	/* reading process (v6)*/
-	Chan	*mchan4;	/* Data channel for v4 */
-	Chan	*achan;		/* Arp channel */
-	Chan	*cchan4;	/* Control channel for v4 */
-	Chan	*mchan6;	/* Data channel for v6 */
-	Chan	*cchan6;	/* Control channel for v6 */
-};
-
-/*
- *  ethernet arp request
- */
-enum
-{
-	ARPREQUEST	= 1,
-	ARPREPLY	= 2,
-};
-
-typedef struct Etherarp Etherarp;
-struct Etherarp
-{
-	uchar	d[6];
-	uchar	s[6];
-	uchar	type[2];
-	uchar	hrd[2];
-	uchar	pro[2];
-	uchar	hln;
-	uchar	pln;
-	uchar	op[2];
-	uchar	sha[6];
-	uchar	spa[4];
-	uchar	tha[6];
-	uchar	tpa[4];
-};
-
-static char *nbmsg = "nonblocking";
-
-/*
- *  called to bind an IP ifc to an ethernet device
- *  called with ifc wlock'd
- */
-static void
-etherbind(Ipifc *ifc, int argc, char **argv)
-{
-	Chan *mchan4, *cchan4, *achan, *mchan6, *cchan6, *schan;
-	char addr[Maxpath];	//char addr[2*KNAMELEN];
-	char dir[Maxpath];	//char dir[2*KNAMELEN];
-	char *buf;
-	int n;
-	char *ptr;
-	Etherrock *er;
-
-	if(argc < 2)
-		error(Ebadarg);
-
-	mchan4 = cchan4 = achan = mchan6 = cchan6 = nil;
-	buf = nil;
-	if(waserror()){
-		if(mchan4 != nil)
-			cclose(mchan4);
-		if(cchan4 != nil)
-			cclose(cchan4);
-		if(achan != nil)
-			cclose(achan);
-		if(mchan6 != nil)
-			cclose(mchan6);
-		if(cchan6 != nil)
-			cclose(cchan6);
-		if(buf != nil)
-			free(buf);
-		nexterror();
-	}
-
-	/*
-	 *  open ipv4 conversation
-	 *
-	 *  the dial will fail if the type is already open on
-	 *  this device.
-	 */
-	snprint(addr, sizeof(addr), "%s!0x800", argv[2]);	/* ETIP4 */
-	mchan4 = chandial(addr, nil, dir, &cchan4);
-
-	/*
-	 *  make it non-blocking
-	 */
-	devtab[cchan4->type]->write(cchan4, nbmsg, strlen(nbmsg), 0);
-
-	/*
-	 *  get mac address and speed
-	 */
-	snprint(addr, sizeof(addr), "%s/stats", argv[2]);
-	buf = smalloc(512);
-	schan = namec(addr, Aopen, OREAD, 0);
-	if(waserror()){
-		cclose(schan);
-		nexterror();
-	}
-	n = devtab[schan->type]->read(schan, buf, 511, 0);
-	cclose(schan);
-	poperror();
-	buf[n] = 0;
-
-	ptr = strstr(buf, "addr: ");
-	if(!ptr)
-		error(Eio);
-	ptr += 6;
-	parsemac(ifc->mac, ptr, 6);
-
-	ptr = strstr(buf, "mbps: ");
-	if(ptr){
-		ptr += 6;
-		ifc->mbps = atoi(ptr);
-	} else
-		ifc->mbps = 100;
-
-	/*
- 	 *  open arp conversation
-	 */
-	snprint(addr, sizeof(addr), "%s!0x806", argv[2]);	/* ETARP */
-	achan = chandial(addr, nil, nil, nil);
-
-	/*
-	 *  open ipv6 conversation
-	 *
-	 *  the dial will fail if the type is already open on
-	 *  this device.
-	 */
-	snprint(addr, sizeof(addr), "%s!0x86DD", argv[2]);	/* ETIP6 */
-	mchan6 = chandial(addr, nil, dir, &cchan6);
-
-	/*
-	 *  make it non-blocking
-	 */
-	devtab[cchan6->type]->write(cchan6, nbmsg, strlen(nbmsg), 0);
-
-	er = smalloc(sizeof(*er));
-	er->mchan4 = mchan4;
-	er->cchan4 = cchan4;
-	er->achan = achan;
-	er->mchan6 = mchan6;
-	er->cchan6 = cchan6;
-	er->f = ifc->conv->p->f;
-	ifc->arg = er;
-
-	free(buf);
-	poperror();
-
-	kproc("etherread4", etherread4, ifc);
-	kproc("recvarpproc", recvarpproc, ifc);
-	kproc("etherread6", etherread6, ifc);
-}
-
-/*
- *  called with ifc wlock'd
- */
-static void
-etherunbind(Ipifc *ifc)
-{
-	Etherrock *er = ifc->arg;
-
-	if(er->read4p)
-		postnote(er->read4p, 1, "unbind", 0);
-	if(er->read6p)
-		postnote(er->read6p, 1, "unbind", 0);
-	if(er->arpp)
-		postnote(er->arpp, 1, "unbind", 0);
-
-	/* wait for readers to die */
-	while(er->arpp != 0 || er->read4p != 0 || er->read6p != 0)
-		tsleep(&up->sleep, return0, 0, 300);
-
-	if(er->mchan4 != nil)
-		cclose(er->mchan4);
-	if(er->achan != nil)
-		cclose(er->achan);
-	if(er->cchan4 != nil)
-		cclose(er->cchan4);
-	if(er->mchan6 != nil)
-		cclose(er->mchan6);
-	if(er->cchan6 != nil)
-		cclose(er->cchan6);
-
-	free(er);
-}
-
-/*
- *  called by ipoput with a single block to write with ifc rlock'd
- */
-static void
-etherbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip)
-{
-	Etherhdr *eh;
-	Arpent *a;
-	uchar mac[6];
-	Etherrock *er = ifc->arg;
-
-	/* get mac address of destination */
-	a = arpget(er->f->arp, bp, version, ifc, ip, mac);
-	if(a){
-		/* check for broadcast or multicast */
-		bp = multicastarp(er->f, a, ifc->m, mac);
-		if(bp==nil){
-			switch(version){
-			case V4:
-				sendarp(ifc, a);
-				break;
-			case V6:
-				resolveaddr6(ifc, a);
-				break;
-			default:
-				panic("etherbwrite: version %d", version);
-			}
-			return;
-		}
-	}
-
-	/* make it a single block with space for the ether header */
-	bp = padblock(bp, ifc->m->hsize);
-	if(bp->next)
-		bp = concatblock(bp);
-	if(BLEN(bp) < ifc->mintu)
-		bp = adjustblock(bp, ifc->mintu);
-	eh = (Etherhdr*)bp->rp;
-
-	/* copy in mac addresses and ether type */
-	memmove(eh->s, ifc->mac, sizeof(eh->s));
-	memmove(eh->d, mac, sizeof(eh->d));
-
- 	switch(version){
-	case V4:
-		eh->t[0] = 0x08;
-		eh->t[1] = 0x00;
-		devtab[er->mchan4->type]->bwrite(er->mchan4, bp, 0);
-		break;
-	case V6:
-		eh->t[0] = 0x86;
-		eh->t[1] = 0xDD;
-		devtab[er->mchan6->type]->bwrite(er->mchan6, bp, 0);
-		break;
-	default:
-		panic("etherbwrite2: version %d", version);
-	}
-	ifc->out++;
-}
-
-
-/*
- *  process to read from the ethernet
- */
-static void
-etherread4(void *a)
-{
-	Ipifc *ifc;
-	Block *bp;
-	Etherrock *er;
-
-	ifc = a;
-	er = ifc->arg;
-	er->read4p = up;	/* hide identity under a rock for unbind */
-	if(waserror()){
-		er->read4p = 0;
-		pexit("hangup", 1);
-	}
-	for(;;){
-		bp = devtab[er->mchan4->type]->bread(er->mchan4, ifc->maxtu, 0);
-		if(!canrlock(ifc)){
-			freeb(bp);
-			continue;
-		}
-		if(waserror()){
-			runlock(ifc);
-			nexterror();
-		}
-		ifc->in++;
-		bp->rp += ifc->m->hsize;
-		if(ifc->lifc == nil)
-			freeb(bp);
-		else
-			ipiput4(er->f, ifc, bp);
-		runlock(ifc);
-		poperror();
-	}
-}
-
-
-/*
- *  process to read from the ethernet, IPv6
- */
-static void
-etherread6(void *a)
-{
-	Ipifc *ifc;
-	Block *bp;
-	Etherrock *er;
-
-	ifc = a;
-	er = ifc->arg;
-	er->read6p = up;	/* hide identity under a rock for unbind */
-	if(waserror()){
-		er->read6p = 0;
-		pexit("hangup", 1);
-	}
-	for(;;){
-		bp = devtab[er->mchan6->type]->bread(er->mchan6, ifc->maxtu, 0);
-		if(!canrlock(ifc)){
-			freeb(bp);
-			continue;
-		}
-		if(waserror()){
-			runlock(ifc);
-			nexterror();
-		}
-		ifc->in++;
-		bp->rp += ifc->m->hsize;
-		if(ifc->lifc == nil)
-			freeb(bp);
-		else
-			ipiput6(er->f, ifc, bp);
-		runlock(ifc);
-		poperror();
-	}
-}
-
-static void
-etheraddmulti(Ipifc *ifc, uchar *a, uchar *)
-{
-	uchar mac[6];
-	char buf[64];
-	Etherrock *er = ifc->arg;
-	int version;
-
-	version = multicastea(mac, a);
-	snprint(buf, sizeof buf, "addmulti %E", mac);
-	switch(version){
-	case V4:
-		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
-		break;
-	case V6:
-		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
-		break;
-	default:
-		panic("etheraddmulti: version %d", version);
-	}
-}
-
-static void
-etherremmulti(Ipifc *ifc, uchar *a, uchar *)
-{
-	uchar mac[6];
-	char buf[64];
-	Etherrock *er = ifc->arg;
-	int version;
-
-	version = multicastea(mac, a);
-	snprint(buf, sizeof buf, "remmulti %E", mac);
-	switch(version){
-	case V4:
-		devtab[er->cchan4->type]->write(er->cchan4, buf, strlen(buf), 0);
-		break;
-	case V6:
-		devtab[er->cchan6->type]->write(er->cchan6, buf, strlen(buf), 0);
-		break;
-	default:
-		panic("etherremmulti: version %d", version);
-	}
-}
-
-/*
- *  send an ethernet arp
- *  (only v4, v6 uses the neighbor discovery, rfc1970)
- */
-static void
-sendarp(Ipifc *ifc, Arpent *a)
-{
-	int n;
-	Block *bp;
-	Etherarp *e;
-	Etherrock *er = ifc->arg;
-
-	/* don't do anything if it's been less than a second since the last */
-	if(NOW - a->ctime < 1000){
-		arprelease(er->f->arp, a);
-		return;
-	}
-
-	/* remove all but the last message */
-	while((bp = a->hold) != nil){
-		if(bp == a->last)
-			break;
-		a->hold = bp->list;
-		freeblist(bp);
-	}
-
-	/* try to keep it around for a second more */
-	a->ctime = NOW;
-	arprelease(er->f->arp, a);
-
-	n = sizeof(Etherarp);
-	if(n < a->type->mintu)
-		n = a->type->mintu;
-	bp = allocb(n);
-	memset(bp->rp, 0, n);
-	e = (Etherarp*)bp->rp;
-	memmove(e->tpa, a->ip+IPv4off, sizeof(e->tpa));
-	ipv4local(ifc, e->spa);
-	memmove(e->sha, ifc->mac, sizeof(e->sha));
-	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */
-	memmove(e->s, ifc->mac, sizeof(e->s));
-
-	hnputs(e->type, ETARP);
-	hnputs(e->hrd, 1);
-	hnputs(e->pro, ETIP4);
-	e->hln = sizeof(e->sha);
-	e->pln = sizeof(e->spa);
-	hnputs(e->op, ARPREQUEST);
-	bp->wp += n;
-
-	devtab[er->achan->type]->bwrite(er->achan, bp, 0);
-}
-
-static void
-resolveaddr6(Ipifc *ifc, Arpent *a)
-{
-	int sflag;
-	Block *bp;
-	Etherrock *er = ifc->arg;
-	uchar ipsrc[IPaddrlen];
-
-	/* don't do anything if it's been less than a second since the last */
-	if(NOW - a->ctime < ReTransTimer){
-		arprelease(er->f->arp, a);
-		return;
-	}
-
-	/* remove all but the last message */
-	while((bp = a->hold) != nil){
-		if(bp == a->last)
-			break;
-		a->hold = bp->list;
-		freeblist(bp);
-	}
-
-	/* try to keep it around for a second more */
-	a->ctime = NOW;
-	a->rtime = NOW + ReTransTimer;
-	if(a->rxtsrem <= 0) {
-		arprelease(er->f->arp, a);
-		return;
-	}
-
-	a->rxtsrem--;
-	arprelease(er->f->arp, a);
-
-	if(sflag = ipv6anylocal(ifc, ipsrc))
-		icmpns(er->f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac);
-}
-
-/*
- *  send a gratuitous arp to refresh arp caches
- */
-static void
-sendgarp(Ipifc *ifc, uchar *ip)
-{
-	int n;
-	Block *bp;
-	Etherarp *e;
-	Etherrock *er = ifc->arg;
-
-	/* don't arp for our initial non address */
-	if(ipcmp(ip, IPnoaddr) == 0)
-		return;
-
-	n = sizeof(Etherarp);
-	if(n < ifc->m->mintu)
-		n = ifc->m->mintu;
-	bp = allocb(n);
-	memset(bp->rp, 0, n);
-	e = (Etherarp*)bp->rp;
-	memmove(e->tpa, ip+IPv4off, sizeof(e->tpa));
-	memmove(e->spa, ip+IPv4off, sizeof(e->spa));
-	memmove(e->sha, ifc->mac, sizeof(e->sha));
-	memset(e->d, 0xff, sizeof(e->d));		/* ethernet broadcast */
-	memmove(e->s, ifc->mac, sizeof(e->s));
-
-	hnputs(e->type, ETARP);
-	hnputs(e->hrd, 1);
-	hnputs(e->pro, ETIP4);
-	e->hln = sizeof(e->sha);
-	e->pln = sizeof(e->spa);
-	hnputs(e->op, ARPREQUEST);
-	bp->wp += n;
-
-	devtab[er->achan->type]->bwrite(er->achan, bp, 0);
-}
-
-static void
-recvarp(Ipifc *ifc)
-{
-	int n;
-	Block *ebp, *rbp;
-	Etherarp *e, *r;
-	uchar ip[IPaddrlen];
-	static uchar eprinted[4];
-	Etherrock *er = ifc->arg;
-
-	ebp = devtab[er->achan->type]->bread(er->achan, ifc->maxtu, 0);
-	if(ebp == nil)
-		return;
-
-	e = (Etherarp*)ebp->rp;
-	switch(nhgets(e->op)) {
-	default:
-		break;
-
-	case ARPREPLY:
-		/* check for machine using my ip address */
-		v4tov6(ip, e->spa);
-		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
-			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
-				print("arprep: 0x%E/0x%E also has ip addr %V\n",
-					e->s, e->sha, e->spa);
-				break;
-			}
-		}
-
-		/* make sure we're not entering broadcast addresses */
-		if(ipcmp(ip, ipbroadcast) == 0 ||
-			!memcmp(e->sha, etherbroadcast, sizeof(e->sha))){
-			print("arprep: 0x%E/0x%E cannot register broadcast address %I\n",
-				e->s, e->sha, e->spa);
-			break;
-		}
-
-		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 0);
-		break;
-
-	case ARPREQUEST:
-		/* don't answer arps till we know who we are */
-		if(ifc->lifc == 0)
-			break;
-
-		/* check for machine using my ip or ether address */
-		v4tov6(ip, e->spa);
-		if(iplocalonifc(ifc, ip) || ipproxyifc(er->f, ifc, ip)){
-			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) != 0){
-				if (memcmp(eprinted, e->spa, sizeof(e->spa))){
-					/* print only once */
-					print("arpreq: 0x%E also has ip addr %V\n", e->sha, e->spa);
-					memmove(eprinted, e->spa, sizeof(e->spa));
-				}
-			}
-		} else {
-			if(memcmp(e->sha, ifc->mac, sizeof(e->sha)) == 0){
-				print("arpreq: %V also has ether addr %E\n", e->spa, e->sha);
-				break;
-			}
-		}
-
-		/* refresh what we know about sender */
-		arpenter(er->f, V4, e->spa, e->sha, sizeof(e->sha), 1);
-
-		/* answer only requests for our address or systems we're proxying for */
-		v4tov6(ip, e->tpa);
-		if(!iplocalonifc(ifc, ip))
-		if(!ipproxyifc(er->f, ifc, ip))
-			break;
-
-		n = sizeof(Etherarp);
-		if(n < ifc->mintu)
-			n = ifc->mintu;
-		rbp = allocb(n);
-		r = (Etherarp*)rbp->rp;
-		memset(r, 0, sizeof(Etherarp));
-		hnputs(r->type, ETARP);
-		hnputs(r->hrd, 1);
-		hnputs(r->pro, ETIP4);
-		r->hln = sizeof(r->sha);
-		r->pln = sizeof(r->spa);
-		hnputs(r->op, ARPREPLY);
-		memmove(r->tha, e->sha, sizeof(r->tha));
-		memmove(r->tpa, e->spa, sizeof(r->tpa));
-		memmove(r->sha, ifc->mac, sizeof(r->sha));
-		memmove(r->spa, e->tpa, sizeof(r->spa));
-		memmove(r->d, e->sha, sizeof(r->d));
-		memmove(r->s, ifc->mac, sizeof(r->s));
-		rbp->wp += n;
-
-		devtab[er->achan->type]->bwrite(er->achan, rbp, 0);
-	}
-	freeb(ebp);
-}
-
-static void
-recvarpproc(void *v)
-{
-	Ipifc *ifc = v;
-	Etherrock *er = ifc->arg;
-
-	er->arpp = up;
-	if(waserror()){
-		er->arpp = 0;
-		pexit("hangup", 1);
-	}
-	for(;;)
-		recvarp(ifc);
-}
-
-static int
-multicastea(uchar *ea, uchar *ip)
-{
-	int x;
-
-	switch(x = ipismulticast(ip)){
-	case V4:
-		ea[0] = 0x01;
-		ea[1] = 0x00;
-		ea[2] = 0x5e;
-		ea[3] = ip[13] & 0x7f;
-		ea[4] = ip[14];
-		ea[5] = ip[15];
-		break;
- 	case V6:
- 		ea[0] = 0x33;
- 		ea[1] = 0x33;
- 		ea[2] = ip[12];
-		ea[3] = ip[13];
- 		ea[4] = ip[14];
- 		ea[5] = ip[15];
- 		break;
-	}
-	return x;
-}
-
-/*
- *  fill in an arp entry for broadcast or multicast
- *  addresses.  Return the first queued packet for the
- *  IP address.
- */
-static Block*
-multicastarp(Fs *f, Arpent *a, Medium *medium, uchar *mac)
-{
-	/* is it broadcast? */
-	switch(ipforme(f, a->ip)){
-	case Runi:
-		return nil;
-	case Rbcast:
-		memset(mac, 0xff, 6);
-		return arpresolve(f->arp, a, medium, mac);
-	default:
-		break;
-	}
-
-	/* if multicast, fill in mac */
-	switch(multicastea(mac, a->ip)){
-	case V4:
-	case V6:
-		return arpresolve(f->arp, a, medium, mac);
-	}
-
-	/* let arp take care of it */
-	return nil;
-}
-
-void
-ethermediumlink(void)
-{
-	addipmedium(&ethermedium);
-	addipmedium(&gbemedium);
-}
-
-
-static void
-etherpref2addr(uchar *pref, uchar *ea)
-{
-	pref[8] = ea[0] | 0x2;
-	pref[9] = ea[1];
-	pref[10] = ea[2];
-	pref[11] = 0xFF;
-	pref[12] = 0xFE;
-	pref[13] = ea[3];
-	pref[14] = ea[4];
-	pref[15] = ea[5];
-}

+ 0 - 980
sys/src/9/ip/gre.c

@@ -1,980 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Generic Routing Encapsulation over IPv4, rfc1702
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-enum {
-	GRE_IPONLY	= 12,		/* size of ip header */
-	GRE_IPPLUSGRE	= 12,		/* minimum size of GRE header */
-	IP_GREPROTO	= 47,
-
-	GRErxms		= 200,
-	GREtickms	= 100,
-	GREmaxxmit	= 10,
-
-	K		= 1024,
-	GREqlen		= 256 * K,
-
-	GRE_cksum	= 0x8000,
-	GRE_routing	= 0x4000,
-	GRE_key		= 0x2000,
-	GRE_seq		= 0x1000,
-
-	Nring		= 1 << 10,	/* power of two, please */
-	Ringmask	= Nring - 1,
-
-	GREctlraw	= 0,
-	GREctlcooked,
-	GREctlretunnel,
-	GREctlreport,
-	GREctldlsuspend,
-	GREctlulsuspend,
-	GREctldlresume,
-	GREctlulresume,
-	GREctlforward,
-	GREctlulkey,
-	Ncmds,
-};
-
-typedef struct GREhdr GREhdr;
-struct GREhdr{
-	/* ip header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	len[2];		/* packet length (including headers) */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-
-	/* gre header */
-	uchar	flags[2];
-	uchar	eproto[2];	/* encapsulation protocol */
-};
-
-typedef struct GREpriv GREpriv;
-struct GREpriv{
-	/* non-MIB stats */
-	ulong	lenerr;			/* short packet */
-};
-
-typedef struct Bring	Bring;
-struct Bring{
-	Block	*ring[Nring];
-	long	produced;
-	long	consumed;
-};
-
-typedef struct GREconv	GREconv;
-struct GREconv{
-	int	raw;
-
-	/* Retunnelling information.  v4 only */
-	uchar	north[4];			/* HA */
-	uchar	south[4];			/* Base station */
-	uchar	hoa[4];				/* Home address */
-	uchar	coa[4];				/* Careof address */
-	ulong	seq;				/* Current sequence # */
-	int	dlsusp;				/* Downlink suspended? */
-	int	ulsusp;				/* Uplink suspended? */
-	ulong	ulkey;				/* GRE key */
-
-	QLock	lock;				/* Lock for rings */
-	Bring	dlpending;			/* Ring of pending packets */
-	Bring	dlbuffered;			/* Received while suspended */
-	Bring	ulbuffered;			/* Received while suspended */
-};
-
-typedef struct Metablock Metablock;
-struct Metablock{
-	uchar	*rp;
-	ulong	seq;
-};
-
-static char *grectlcooked(Conv *, int, char **);
-static char *grectldlresume(Conv *, int, char **);
-static char *grectldlsuspend(Conv *, int, char **);
-static char *grectlforward(Conv *, int, char **);
-static char *grectlraw(Conv *, int, char **);
-static char *grectlreport(Conv *, int, char **);
-static char *grectlretunnel(Conv *, int, char **);
-static char *grectlulkey(Conv *, int, char **);
-static char *grectlulresume(Conv *, int, char **);
-static char *grectlulsuspend(Conv *, int, char **);
-
-static struct{
-	char	*cmd;
-	int	argc;
-	char	*(*f)(Conv *, int, char **);
-} grectls[Ncmds] = {
-[GREctlraw]	=	{	"raw",		1,	grectlraw,	},
-[GREctlcooked]	=	{	"cooked",	1,	grectlcooked,	},
-[GREctlretunnel]=	{	"retunnel",	5,	grectlretunnel,	},
-[GREctlreport]	=	{	"report",	2,	grectlreport,	},
-[GREctldlsuspend]=	{	"dlsuspend",	1,	grectldlsuspend,},
-[GREctlulsuspend]=	{	"ulsuspend",	1,	grectlulsuspend,},
-[GREctldlresume]=	{	"dlresume",	1,	grectldlresume,	},
-[GREctlulresume]=	{	"ulresume",	1,	grectlulresume,	},
-[GREctlforward]	=	{	"forward",	2,	grectlforward,	},
-[GREctlulkey]	=	{	"ulkey",	2,	grectlulkey,	},
-};
-
-static uchar nulladdr[4];
-static char *sessend = "session end";
-
-static void grekick(void *x, Block *bp);
-static char *gresetup(Conv *, char *, char *, char *);
-
-ulong grepdin, grepdout, grebdin, grebdout;
-ulong grepuin, grepuout, grebuin, grebuout;
-
-static Block *
-getring(Bring *r)
-{
-	Block *bp;
-
-	if(r->consumed == r->produced)
-		return nil;
-
-	bp = r->ring[r->consumed & Ringmask];
-	r->ring[r->consumed & Ringmask] = nil;
-	r->consumed++;
-	return bp;
-}
-
-static void
-addring(Bring *r, Block *bp)
-{
-	Block *tbp;
-
-	if(r->produced - r->consumed > Ringmask){
-		/* Full! */
-		tbp = r->ring[r->produced & Ringmask];
-		assert(tbp);
-		freeb(tbp);
-		r->consumed++;
-	}
-	r->ring[r->produced & Ringmask] = bp;
-	r->produced++;
-}
-
-static char *
-greconnect(Conv *c, char **argv, int argc)
-{
-	Proto *p;
-	char *err;
-	Conv *tc, **cp, **ecp;
-
-	err = Fsstdconnect(c, argv, argc);
-	if(err != nil)
-		return err;
-
-	/* make sure noone's already connected to this other sys */
-	p = c->p;
-	qlock(p);
-	ecp = &p->conv[p->nc];
-	for(cp = p->conv; cp < ecp; cp++){
-		tc = *cp;
-		if(tc == nil)
-			break;
-		if(tc == c)
-			continue;
-		if(tc->rport == c->rport && ipcmp(tc->raddr, c->raddr) == 0){
-			err = "already connected to that addr/proto";
-			ipmove(c->laddr, IPnoaddr);
-			ipmove(c->raddr, IPnoaddr);
-			break;
-		}
-	}
-	qunlock(p);
-
-	if(err != nil)
-		return err;
-	Fsconnected(c, nil);
-
-	return nil;
-}
-
-static void
-grecreate(Conv *c)
-{
-	c->rq = qopen(GREqlen, Qmsg, 0, c);
-	c->wq = qbypass(grekick, c);
-}
-
-static int
-grestate(Conv *c, char *state, int n)
-{
-	GREconv *grec;
-	char *ep, *p;
-
-	grec = c->ptcl;
-	p    = state;
-	ep   = p + n;
-	p    = seprint(p, ep, "%s%s%s%shoa %V north %V south %V seq %ulx "
-	 "pending %uld  %uld buffered dl %uld %uld ul %uld %uld ulkey %.8ulx\n",
-			c->inuse? "Open ": "Closed ",
-			grec->raw? "raw ": "",
-			grec->dlsusp? "DL suspended ": "",
-			grec->ulsusp? "UL suspended ": "",
-			grec->hoa, grec->north, grec->south, grec->seq,
-			grec->dlpending.consumed, grec->dlpending.produced,
-			grec->dlbuffered.consumed, grec->dlbuffered.produced,
-			grec->ulbuffered.consumed, grec->ulbuffered.produced,
-			grec->ulkey);
-	return p - state;
-}
-
-static char*
-greannounce(Conv*, char**, int)
-{
-	return "gre does not support announce";
-}
-
-static void
-greclose(Conv *c)
-{
-	GREconv *grec;
-	Block *bp;
-
-	grec = c->ptcl;
-
-	/* Make sure we don't forward any more packets */
-	memset(grec->hoa, 0, sizeof grec->hoa);
-	memset(grec->north, 0, sizeof grec->north);
-	memset(grec->south, 0, sizeof grec->south);
-
-	qlock(&grec->lock);
-	while((bp = getring(&grec->dlpending)) != nil)
-		freeb(bp);
-
-	while((bp = getring(&grec->dlbuffered)) != nil)
-		freeb(bp);
-
-	while((bp = getring(&grec->ulbuffered)) != nil)
-		freeb(bp);
-
-	grec->dlpending.produced = grec->dlpending.consumed = 0;
-	grec->dlbuffered.produced = grec->dlbuffered.consumed = 0;
-	grec->ulbuffered.produced = grec->ulbuffered.consumed = 0;
-	qunlock(&grec->lock);
-
-	grec->raw = 0;
-	grec->seq = 0;
-	grec->dlsusp = grec->ulsusp = 1;
-
-	qhangup(c->rq, sessend);
-	qhangup(c->wq, sessend);
-	qhangup(c->eq, sessend);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->lport = c->rport = 0;
-}
-
-static void
-grekick(void *x, Block *bp)
-{
-	Conv *c;
-	GREconv *grec;
-	GREhdr *gre;
-	uchar laddr[IPaddrlen], raddr[IPaddrlen];
-
-	if(bp == nil)
-		return;
-
-	c    = x;
-	grec = c->ptcl;
-
-	/* Make space to fit ip header (gre header already there) */
-	bp = padblock(bp, GRE_IPONLY);
-	if(bp == nil)
-		return;
-
-	/* make sure the message has a GRE header */
-	bp = pullupblock(bp, GRE_IPONLY+GRE_IPPLUSGRE);
-	if(bp == nil)
-		return;
-
-	gre = (GREhdr *)bp->rp;
-	gre->vihl = IP_VER4;
-
-	if(grec->raw == 0){
-		v4tov6(raddr, gre->dst);
-		if(ipcmp(raddr, v4prefix) == 0)
-			memmove(gre->dst, c->raddr + IPv4off, IPv4addrlen);
-		v4tov6(laddr, gre->src);
-		if(ipcmp(laddr, v4prefix) == 0){
-			if(ipcmp(c->laddr, IPnoaddr) == 0)
-				/* pick interface closest to dest */
-				findlocalip(c->p->f, c->laddr, raddr);
-			memmove(gre->src, c->laddr + IPv4off, sizeof gre->src);
-		}
-		hnputs(gre->eproto, c->rport);
-	}
-
-	gre->proto = IP_GREPROTO;
-	gre->frag[0] = gre->frag[1] = 0;
-
-	grepdout++;
-	grebdout += BLEN(bp);
-	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
-}
-
-static void
-gredownlink(Conv *c, Block *bp)
-{
-	Metablock *m;
-	GREconv *grec;
-	GREhdr *gre;
-	int hdrlen, suspended, extra;
-	ushort flags;
-	ulong seq;
-
-	gre = (GREhdr *)bp->rp;
-	if(gre->ttl == 1){
-		freeb(bp);
-		return;
-	}
-
-	/*
-	 * We've received a packet with a GRE header and we need to
-	 * re-adjust the packet header to strip all unwanted parts
-	 * but leave room for only a sequence number.
-	 */
-	grec   = c->ptcl;
-	flags  = nhgets(gre->flags);
-	hdrlen = 0;
-	if(flags & GRE_cksum)
-		hdrlen += 2;
-	if(flags & GRE_routing){
-		print("%V routing info present.  Discarding packet", gre->src);
-		freeb(bp);
-		return;
-	}
-	if(flags & (GRE_cksum|GRE_routing))
-		hdrlen += 2;			/* Offset field */
-	if(flags & GRE_key)
-		hdrlen += 4;
-	if(flags & GRE_seq)
-		hdrlen += 4;
-
-	/*
-	 * The outgoing packet only has the sequence number set.  Make room
-	 * for the sequence number.
-	 */
-	if(hdrlen != sizeof(ulong)){
-		extra = hdrlen - sizeof(ulong);
-		if(extra < 0 && bp->rp - bp->base < -extra){
-			print("gredownlink: cannot add sequence number\n");
-			freeb(bp);
-			return;
-		}
-		memmove(bp->rp + extra, bp->rp, sizeof(GREhdr));
-		bp->rp += extra;
-		assert(BLEN(bp) >= sizeof(GREhdr) + sizeof(ulong));
-		gre = (GREhdr *)bp->rp;
-	}
-	seq = grec->seq++;
-	hnputs(gre->flags, GRE_seq);
-	hnputl(bp->rp + sizeof(GREhdr), seq);
-
-	/*
-	 * Keep rp and seq at the base.  ipoput4 consumes rp for
-	 * refragmentation.
-	 */
-	assert(bp->rp - bp->base >= sizeof(Metablock));
-	m = (Metablock *)bp->base;
-	m->rp  = bp->rp;
-	m->seq = seq;
-
-	/*
-	 * Here we make a decision what we're doing with the packet.  We're
-	 * doing this w/o holding a lock which means that later on in the
-	 * process we may discover we've done the wrong thing.  I don't want
-	 * to call ipoput with the lock held.
-	 */
-restart:
-	suspended = grec->dlsusp;
-	if(suspended){
-		if(!canqlock(&grec->lock)){
-			/*
-			 * just give up.  too bad, we lose a packet.  this
-			 * is just too hard and my brain already hurts.
-			 */
-			freeb(bp);
-			return;
-		}
-
-		if(!grec->dlsusp){
-			/*
-			 * suspend race.  We though we were suspended, but
-			 * we really weren't.
-			 */
-			qunlock(&grec->lock);
-			goto restart;
-		}
-
-		/* Undo the incorrect ref count addition */
-		addring(&grec->dlbuffered, bp);
-		qunlock(&grec->lock);
-		return;
-	}
-
-	/*
-	 * When we get here, we're not suspended.  Proceed to send the
-	 * packet.
-	 */
-	memmove(gre->src, grec->coa, sizeof gre->dst);
-	memmove(gre->dst, grec->south, sizeof gre->dst);
-
-	/*
-	 * Make sure the packet does not go away.
-	 */
-	_xinc(&bp->ref);
-	assert(bp->ref == 2);
-
-	ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-	grepdout++;
-	grebdout += BLEN(bp);
-
-	/*
-	 * Now make sure we didn't do the wrong thing.
-	 */
-	if(!canqlock(&grec->lock)){
-		freeb(bp);		/* The packet just goes away */
-		return;
-	}
-
-	/* We did the right thing */
-	addring(&grec->dlpending, bp);
-	qunlock(&grec->lock);
-}
-
-static void
-greuplink(Conv *c, Block *bp)
-{
-	GREconv *grec;
-	GREhdr *gre;
-	ushort flags;
-
-	gre = (GREhdr *)bp->rp;
-	if(gre->ttl == 1)
-		return;
-
-	grec = c->ptcl;
-	memmove(gre->src, grec->coa, sizeof gre->src);
-	memmove(gre->dst, grec->north, sizeof gre->dst);
-
-	/*
-	 * Add a key, if needed.
-	 */
-	if(grec->ulkey){
-		flags = nhgets(gre->flags);
-		if(flags & (GRE_cksum|GRE_routing)){
-			print("%V routing info present.  Discarding packet\n",
-				gre->src);
-			freeb(bp);
-			return;
-		}
-
-		if((flags & GRE_key) == 0){
-			/* Make room for the key */
-			if(bp->rp - bp->base < sizeof(ulong)){
-				print("%V can't add key\n", gre->src);
-				freeb(bp);
-				return;
-			}
-
-			bp->rp -= 4;
-			memmove(bp->rp, bp->rp + 4, sizeof(GREhdr));
-
-			gre = (GREhdr *)bp->rp;
-			hnputs(gre->flags, flags | GRE_key);
-		}
-
-		/* Add the key */
-		hnputl(bp->rp + sizeof(GREhdr), grec->ulkey);
-	}
-
-	if(!canqlock(&grec->lock)){
-		freeb(bp);
-		return;
-	}
-
-	if(grec->ulsusp)
-		addring(&grec->ulbuffered, bp);
-	else{
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-		grepuout++;
-		grebuout += BLEN(bp);
-	}
-	qunlock(&grec->lock);
-}
-
-static void
-greiput(Proto *proto, Ipifc *, Block *bp)
-{
-	int len, hdrlen;
-	ushort eproto, flags;
-	uchar raddr[IPaddrlen];
-	Conv *c, **p;
-	GREconv *grec;
-	GREhdr *gre;
-	GREpriv *gpriv;
-	Ip4hdr *ip;
-
-	/*
-	 * We don't want to deal with block lists.  Ever.  The problem is
-	 * that when the block is forwarded, devether.c puts the block into
-	 * a queue that also uses ->next.  Just do not use ->next here!
-	 */
-	if(bp->next){
-		len = blocklen(bp);
-		bp  = pullupblock(bp, len);
-		assert(BLEN(bp) == len && bp->next == nil);
-	}
-
-	gre = (GREhdr *)bp->rp;
-	if(BLEN(bp) < sizeof(GREhdr) || gre->proto != IP_GREPROTO){
-		freeb(bp);
-		return;
-	}
-
-	v4tov6(raddr, gre->src);
-	eproto = nhgets(gre->eproto);
-	flags  = nhgets(gre->flags);
-	hdrlen = sizeof(GREhdr);
-
-	if(flags & GRE_cksum)
-		hdrlen += 2;
-	if(flags & GRE_routing){
-		print("%I routing info present.  Discarding packet\n", raddr);
-		freeb(bp);
-		return;
-	}
-	if(flags & (GRE_cksum|GRE_routing))
-		hdrlen += 2;			/* Offset field */
-	if(flags & GRE_key)
-		hdrlen += 4;
-	if(flags & GRE_seq)
-		hdrlen += 4;
-
-	if(BLEN(bp) - hdrlen < sizeof(Ip4hdr)){
-		print("greretunnel: packet too short (s=%V d=%V)\n",
-			gre->src, gre->dst);
-		freeb(bp);
-		return;
-	}
-	ip = (Ip4hdr *)(bp->rp + hdrlen);
-
-	qlock(proto);
-	/*
-	 * Look for a conversation structure for this port and address, or
-	 * match the retunnel part, or match on the raw flag.
-	 */
-	for(p = proto->conv; *p; p++) {
-		c = *p;
-
-		if(c->inuse == 0)
-			continue;
-
-		/*
-		 * Do not stop this session - blocking here
-		 * implies that etherread is blocked.
-		 */
-		grec = c->ptcl;
-		if(memcmp(ip->dst, grec->hoa, sizeof ip->dst) == 0){
-			grepdin++;
-			grebdin += BLEN(bp);
-			gredownlink(c, bp);
-			qunlock(proto);
-			return;
-		}
-
-		if(memcmp(ip->src, grec->hoa, sizeof ip->src) == 0){
-			grepuin++;
-			grebuin += BLEN(bp);
-			greuplink(c, bp);
-			qunlock(proto);
-			return;
-		}
-	}
-
-	/*
-	 * when we get here, none of the forwarding tunnels matched.  now
-	 * try to match on raw and conversational sessions.
-	 */
-	for(c = nil, p = proto->conv; *p; p++) {
-		c = *p;
-
-		if(c->inuse == 0)
-			continue;
-
-		/*
-		 * Do not stop this session - blocking here
-		 * implies that etherread is blocked.
-		 */
-		grec = c->ptcl;
-		if(c->rport == eproto &&
-		    (grec->raw || ipcmp(c->raddr, raddr) == 0))
-			break;
-	}
-
-	qunlock(proto);
-
-	if(*p == nil){
-		freeb(bp);
-		return;
-	}
-
-	/*
-	 * Trim the packet down to data size
-	 */
-	len = nhgets(gre->len) - GRE_IPONLY;
-	if(len < GRE_IPPLUSGRE){
-		freeb(bp);
-		return;
-	}
-
-	bp = trimblock(bp, GRE_IPONLY, len);
-	if(bp == nil){
-		gpriv = proto->priv;
-		gpriv->lenerr++;
-		return;
-	}
-
-	/*
-	 *  Can't delimit packet so pull it all into one block.
-	 */
-	if(qlen(c->rq) > GREqlen)
-		freeb(bp);
-	else{
-		bp = concatblock(bp);
-		if(bp == 0)
-			panic("greiput");
-		qpass(c->rq, bp);
-	}
-}
-
-int
-grestats(Proto *gre, char *buf, int len)
-{
-	GREpriv *gpriv;
-
-	gpriv = gre->priv;
-	return snprint(buf, len,
-		"gre: %lud %lud %lud %lud %lud %lud %lud %lud, lenerrs %lud\n",
-		grepdin, grepdout, grepuin, grepuout,
-		grebdin, grebdout, grebuin, grebuout, gpriv->lenerr);
-}
-
-static char *
-grectlraw(Conv *c, int, char **)
-{
-	GREconv *grec;
-
-	grec = c->ptcl;
-	grec->raw = 1;
-	return nil;
-}
-
-static char *
-grectlcooked(Conv *c, int, char **)
-{
-	GREconv *grec;
-
-	grec = c->ptcl;
-	grec->raw = 0;
-	return nil;
-}
-
-static char *
-grectlretunnel(Conv *c, int, char **argv)
-{
-	GREconv *grec;
-	uchar ipaddr[4];
-
-	grec = c->ptcl;
-	if(memcmp(grec->hoa, nulladdr, sizeof grec->hoa))
-		return "tunnel already set up";
-
-	v4parseip(ipaddr, argv[1]);
-	if(memcmp(ipaddr, nulladdr, sizeof ipaddr) == 0)
-		return "bad hoa";
-	memmove(grec->hoa, ipaddr, sizeof grec->hoa);
-	v4parseip(ipaddr, argv[2]);
-	memmove(grec->north, ipaddr, sizeof grec->north);
-	v4parseip(ipaddr, argv[3]);
-	memmove(grec->south, ipaddr, sizeof grec->south);
-	v4parseip(ipaddr, argv[4]);
-	memmove(grec->coa, ipaddr, sizeof grec->coa);
-	grec->ulsusp = 1;
-	grec->dlsusp = 0;
-
-	return nil;
-}
-
-static char *
-grectlreport(Conv *c, int, char **argv)
-{
-	ulong seq;
-	Block *bp;
-	Bring *r;
-	GREconv *grec;
-	Metablock *m;
-
-	grec = c->ptcl;
-	seq  = strtoul(argv[1], nil, 0);
-
-	qlock(&grec->lock);
-	r = &grec->dlpending;
-	while(r->produced - r->consumed > 0){
-		bp = r->ring[r->consumed & Ringmask];
-
-		assert(bp && bp->rp - bp->base >= sizeof(Metablock));
-		m = (Metablock *)bp->base;
-		if((long)(seq - m->seq) <= 0)
-			break;
-
-		r->ring[r->consumed & Ringmask] = nil;
-		r->consumed++;
-
-		freeb(bp);
-	}
-	qunlock(&grec->lock);
-	return nil;
-}
-
-static char *
-grectldlsuspend(Conv *c, int, char **)
-{
-	GREconv *grec;
-
-	grec = c->ptcl;
-	if(grec->dlsusp)
-		return "already suspended";
-
-	grec->dlsusp = 1;
-	return nil;
-}
-
-static char *
-grectlulsuspend(Conv *c, int, char **)
-{
-	GREconv *grec;
-
-	grec = c->ptcl;
-	if(grec->ulsusp)
-		return "already suspended";
-
-	grec->ulsusp = 1;
-	return nil;
-}
-
-static char *
-grectldlresume(Conv *c, int, char **)
-{
-	GREconv *grec;
-	GREhdr *gre;
-	Block *bp;
-
-	grec = c->ptcl;
-
-	qlock(&grec->lock);
-	if(!grec->dlsusp){
-		qunlock(&grec->lock);
-		return "not suspended";
-	}
-
-	while((bp = getring(&grec->dlbuffered)) != nil){
-		gre = (GREhdr *)bp->rp;
-		qunlock(&grec->lock);
-
-		/*
-		 * Make sure the packet does not go away.
-		 */
-		_xinc(&bp->ref);
-		assert(bp->ref == 2);
-
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-
-		qlock(&grec->lock);
-		addring(&grec->dlpending, bp);
-	}
-	grec->dlsusp = 0;
-	qunlock(&grec->lock);
-	return nil;
-}
-
-static char *
-grectlulresume(Conv *c, int, char **)
-{
-	GREconv *grec;
-	GREhdr *gre;
-	Block *bp;
-
-	grec = c->ptcl;
-
-	qlock(&grec->lock);
-	while((bp = getring(&grec->ulbuffered)) != nil){
-		gre = (GREhdr *)bp->rp;
-
-		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-		qlock(&grec->lock);
-	}
-	grec->ulsusp = 0;
-	qunlock(&grec->lock);
-	return nil;
-}
-
-static char *
-grectlforward(Conv *c, int, char **argv)
-{
-	int len;
-	Block *bp, *nbp;
-	GREconv *grec;
-	GREhdr *gre;
-	Metablock *m;
-
-	grec = c->ptcl;
-
-	v4parseip(grec->south, argv[1]);
-	memmove(grec->north, grec->south, sizeof grec->north);
-
-	qlock(&grec->lock);
-	if(!grec->dlsusp){
-		qunlock(&grec->lock);
-		return "not suspended";
-	}
-	grec->dlsusp = 0;
-	grec->ulsusp = 0;
-
-	while((bp = getring(&grec->dlpending)) != nil){
-
-		assert(bp->rp - bp->base >= sizeof(Metablock));
-		m = (Metablock *)bp->base;
-		assert(m->rp >= bp->base && m->rp < bp->lim);
-
-		/*
-		 * If the packet is still held inside the IP transmit
-		 * system, make a copy of the packet first.
-		 */
-		if(bp->ref > 1){
-			len = bp->wp - m->rp;
-			nbp = allocb(len);
-			memmove(nbp->wp, m->rp, len);
-			nbp->wp += len;
-			freeb(bp);
-			bp  = nbp;
-		}
-		else{
-			/* Patch up rp */
-			bp->rp = m->rp;
-		}
-
-		gre = (GREhdr *)bp->rp;
-		memmove(gre->src, grec->coa, sizeof gre->dst);
-		memmove(gre->dst, grec->south, sizeof gre->dst);
-
-		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-		qlock(&grec->lock);
-	}
-
-	while((bp = getring(&grec->dlbuffered)) != nil){
-		gre = (GREhdr *)bp->rp;
-		memmove(gre->src, grec->coa, sizeof gre->dst);
-		memmove(gre->dst, grec->south, sizeof gre->dst);
-
-		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-		qlock(&grec->lock);
-	}
-
-	while((bp = getring(&grec->ulbuffered)) != nil){
-		gre = (GREhdr *)bp->rp;
-
-		memmove(gre->src, grec->coa, sizeof gre->dst);
-		memmove(gre->dst, grec->south, sizeof gre->dst);
-
-		qunlock(&grec->lock);
-		ipoput4(c->p->f, bp, 0, gre->ttl - 1, gre->tos, nil);
-		qlock(&grec->lock);
-	}
-	qunlock(&grec->lock);
-	return nil;
-}
-
-static char *
-grectlulkey(Conv *c, int, char **argv)
-{
-	GREconv *grec;
-
-	grec = c->ptcl;
-	grec->ulkey = strtoul(argv[1], nil, 0);
-	return nil;
-}
-
-char *
-grectl(Conv *c, char **f, int n)
-{
-	int i;
-
-	if(n < 1)
-		return "too few arguments";
-
-	for(i = 0; i < Ncmds; i++)
-		if(strcmp(f[0], grectls[i].cmd) == 0)
-			break;
-
-	if(i == Ncmds)
-		return "no such command";
-	if(grectls[i].argc != 0 && grectls[i].argc != n)
-		return "incorrect number of arguments";
-
-	return grectls[i].f(c, n, f);
-}
-
-void
-greinit(Fs *fs)
-{
-	Proto *gre;
-
-	gre = smalloc(sizeof(Proto));
-	gre->priv = smalloc(sizeof(GREpriv));
-	gre->name = "gre";
-	gre->connect = greconnect;
-	gre->announce = greannounce;
-	gre->state = grestate;
-	gre->create = grecreate;
-	gre->close = greclose;
-	gre->rcv = greiput;
-	gre->ctl = grectl;
-	gre->advise = nil;
-	gre->stats = grestats;
-	gre->ipproto = IP_GREPROTO;
-	gre->nc = 64;
-	gre->ptclsize = sizeof(GREconv);
-
-	Fsproto(fs, gre);
-}

+ 0 - 501
sys/src/9/ip/icmp.c

@@ -1,501 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-typedef struct Icmp {
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	ipcksum[2];	/* Header checksum */
-	uchar	src[4];		/* Ip source */
-	uchar	dst[4];		/* Ip destination */
-	uchar	type;
-	uchar	code;
-	uchar	cksum[2];
-	uchar	icmpid[2];
-	uchar	seq[2];
-	uchar	data[1];
-} Icmp;
-
-enum {			/* Packet Types */
-	EchoReply	= 0,
-	Unreachable	= 3,
-	SrcQuench	= 4,
-	Redirect	= 5,
-	EchoRequest	= 8,
-	TimeExceed	= 11,
-	InParmProblem	= 12,
-	Timestamp	= 13,
-	TimestampReply	= 14,
-	InfoRequest	= 15,
-	InfoReply	= 16,
-	AddrMaskRequest = 17,
-	AddrMaskReply   = 18,
-
-	Maxtype		= 18,
-};
-
-enum
-{
-	MinAdvise	= 24,	/* minimum needed for us to advise another protocol */
-};
-
-char *icmpnames[Maxtype+1] =
-{
-[EchoReply]		"EchoReply",
-[Unreachable]		"Unreachable",
-[SrcQuench]		"SrcQuench",
-[Redirect]		"Redirect",
-[EchoRequest]		"EchoRequest",
-[TimeExceed]		"TimeExceed",
-[InParmProblem]		"InParmProblem",
-[Timestamp]		"Timestamp",
-[TimestampReply]	"TimestampReply",
-[InfoRequest]		"InfoRequest",
-[InfoReply]		"InfoReply",
-[AddrMaskRequest]	"AddrMaskRequest",
-[AddrMaskReply  ]	"AddrMaskReply  ",
-};
-
-enum {
-	IP_ICMPPROTO	= 1,
-	ICMP_IPSIZE	= 20,
-	ICMP_HDRSIZE	= 8,
-};
-
-enum
-{
-	InMsgs,
-	InErrors,
-	OutMsgs,
-	CsumErrs,
-	LenErrs,
-	HlenErrs,
-
-	Nstats,
-};
-
-static char *statnames[Nstats] =
-{
-[InMsgs]	"InMsgs",
-[InErrors]	"InErrors",
-[OutMsgs]	"OutMsgs",
-[CsumErrs]	"CsumErrs",
-[LenErrs]	"LenErrs",
-[HlenErrs]	"HlenErrs",
-};
-
-typedef struct Icmppriv Icmppriv;
-struct Icmppriv
-{
-	ulong	stats[Nstats];
-
-	/* message counts */
-	ulong	in[Maxtype+1];
-	ulong	out[Maxtype+1];
-};
-
-static void icmpkick(void *x, Block*);
-
-static void
-icmpcreate(Conv *c)
-{
-	c->rq = qopen(64*1024, Qmsg, 0, c);
-	c->wq = qbypass(icmpkick, c);
-}
-
-extern char*
-icmpconnect(Conv *c, char **argv, int argc)
-{
-	char *e;
-
-	e = Fsstdconnect(c, argv, argc);
-	if(e != nil)
-		return e;
-	Fsconnected(c, e);
-
-	return nil;
-}
-
-extern int
-icmpstate(Conv *c, char *state, int n)
-{
-	USED(c);
-	return snprint(state, n, "%s qin %d qout %d\n",
-		"Datagram",
-		c->rq ? qlen(c->rq) : 0,
-		c->wq ? qlen(c->wq) : 0
-	);
-}
-
-extern char*
-icmpannounce(Conv *c, char **argv, int argc)
-{
-	char *e;
-
-	e = Fsstdannounce(c, argv, argc);
-	if(e != nil)
-		return e;
-	Fsconnected(c, nil);
-
-	return nil;
-}
-
-extern void
-icmpclose(Conv *c)
-{
-	qclose(c->rq);
-	qclose(c->wq);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->lport = 0;
-}
-
-static void
-icmpkick(void *x, Block *bp)
-{
-	Conv *c = x;
-	Icmp *p;
-	Icmppriv *ipriv;
-
-	if(bp == nil)
-		return;
-
-	if(blocklen(bp) < ICMP_IPSIZE + ICMP_HDRSIZE){
-		freeblist(bp);
-		return;
-	}
-	p = (Icmp *)(bp->rp);
-	p->vihl = IP_VER4;
-	ipriv = c->p->priv;
-	if(p->type <= Maxtype)
-		ipriv->out[p->type]++;
-
-	v6tov4(p->dst, c->raddr);
-	v6tov4(p->src, c->laddr);
-	p->proto = IP_ICMPPROTO;
-	hnputs(p->icmpid, c->lport);
-	memset(p->cksum, 0, sizeof(p->cksum));
-	hnputs(p->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
-	ipriv->stats[OutMsgs]++;
-	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, nil);
-}
-
-extern void
-icmpttlexceeded(Fs *f, uchar *ia, Block *bp)
-{
-	Block	*nbp;
-	Icmp	*p, *np;
-
-	p = (Icmp *)bp->rp;
-
-	netlog(f, Logicmp, "sending icmpttlexceeded -> %V\n", p->src);
-	nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
-	nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
-	np = (Icmp *)nbp->rp;
-	np->vihl = IP_VER4;
-	memmove(np->dst, p->src, sizeof(np->dst));
-	v6tov4(np->src, ia);
-	memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
-	np->type = TimeExceed;
-	np->code = 0;
-	np->proto = IP_ICMPPROTO;
-	hnputs(np->icmpid, 0);
-	hnputs(np->seq, 0);
-	memset(np->cksum, 0, sizeof(np->cksum));
-	hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
-	ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-
-}
-
-static void
-icmpunreachable(Fs *f, Block *bp, int code, int seq)
-{
-	Block	*nbp;
-	Icmp	*p, *np;
-	int	i;
-	uchar	addr[IPaddrlen];
-
-	p = (Icmp *)bp->rp;
-
-	/* only do this for unicast sources and destinations */
-	v4tov6(addr, p->dst);
-	i = ipforme(f, addr);
-	if((i&Runi) == 0)
-		return;
-	v4tov6(addr, p->src);
-	i = ipforme(f, addr);
-	if(i != 0 && (i&Runi) == 0)
-		return;
-
-	netlog(f, Logicmp, "sending icmpnoconv -> %V\n", p->src);
-	nbp = allocb(ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8);
-	nbp->wp += ICMP_IPSIZE + ICMP_HDRSIZE + ICMP_IPSIZE + 8;
-	np = (Icmp *)nbp->rp;
-	np->vihl = IP_VER4;
-	memmove(np->dst, p->src, sizeof(np->dst));
-	memmove(np->src, p->dst, sizeof(np->src));
-	memmove(np->data, bp->rp, ICMP_IPSIZE + 8);
-	np->type = Unreachable;
-	np->code = code;
-	np->proto = IP_ICMPPROTO;
-	hnputs(np->icmpid, 0);
-	hnputs(np->seq, seq);
-	memset(np->cksum, 0, sizeof(np->cksum));
-	hnputs(np->cksum, ptclcsum(nbp, ICMP_IPSIZE, blocklen(nbp) - ICMP_IPSIZE));
-	ipoput4(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-}
-
-extern void
-icmpnoconv(Fs *f, Block *bp)
-{
-	icmpunreachable(f, bp, 3, 0);
-}
-
-extern void
-icmpcantfrag(Fs *f, Block *bp, int mtu)
-{
-	icmpunreachable(f, bp, 4, mtu);
-}
-
-static void
-goticmpkt(Proto *icmp, Block *bp)
-{
-	Conv	**c, *s;
-	Icmp	*p;
-	uchar	dst[IPaddrlen];
-	ushort	recid;
-
-	p = (Icmp *) bp->rp;
-	v4tov6(dst, p->src);
-	recid = nhgets(p->icmpid);
-
-	for(c = icmp->conv; *c; c++) {
-		s = *c;
-		if(s->lport == recid)
-		if(ipcmp(s->raddr, dst) == 0){
-			bp = concatblock(bp);
-			if(bp != nil)
-				qpass(s->rq, bp);
-			return;
-		}
-	}
-	freeblist(bp);
-}
-
-static Block *
-mkechoreply(Block *bp)
-{
-	Icmp	*q;
-	uchar	ip[4];
-
-	q = (Icmp *)bp->rp;
-	q->vihl = IP_VER4;
-	memmove(ip, q->src, sizeof(q->dst));
-	memmove(q->src, q->dst, sizeof(q->src));
-	memmove(q->dst, ip,  sizeof(q->dst));
-	q->type = EchoReply;
-	memset(q->cksum, 0, sizeof(q->cksum));
-	hnputs(q->cksum, ptclcsum(bp, ICMP_IPSIZE, blocklen(bp) - ICMP_IPSIZE));
-
-	return bp;
-}
-
-static char *unreachcode[] =
-{
-[0]	"net unreachable",
-[1]	"host unreachable",
-[2]	"protocol unreachable",
-[3]	"port unreachable",
-[4]	"fragmentation needed and DF set",
-[5]	"source route failed",
-};
-
-static void
-icmpiput(Proto *icmp, Ipifc*, Block *bp)
-{
-	int	n, iplen;
-	Icmp	*p;
-	Block	*r;
-	Proto	*pr;
-	char	*msg;
-	char	m2[128];
-	Icmppriv *ipriv;
-
-	ipriv = icmp->priv;
-
-	ipriv->stats[InMsgs]++;
-
-	p = (Icmp *)bp->rp;
-	netlog(icmp->f, Logicmp, "icmpiput %s (%d) %d\n",
-		(p->type < nelem(icmpnames)? icmpnames[p->type]: ""),
-		p->type, p->code);
-	n = blocklen(bp);
-	if(n < ICMP_IPSIZE+ICMP_HDRSIZE){
-		ipriv->stats[InErrors]++;
-		ipriv->stats[HlenErrs]++;
-		netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
-		goto raise;
-	}
-	iplen = nhgets(p->length);
-	if(iplen > n){
-		ipriv->stats[LenErrs]++;
-		ipriv->stats[InErrors]++;
-		netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
-		goto raise;
-	}
-	if(ptclcsum(bp, ICMP_IPSIZE, iplen - ICMP_IPSIZE)){
-		ipriv->stats[InErrors]++;
-		ipriv->stats[CsumErrs]++;
-		netlog(icmp->f, Logicmp, "icmp checksum error\n");
-		goto raise;
-	}
-	if(p->type <= Maxtype)
-		ipriv->in[p->type]++;
-
-	switch(p->type) {
-	case EchoRequest:
-		if (iplen < n)
-			bp = trimblock(bp, 0, iplen);
-		r = mkechoreply(concatblock(bp));
-		ipriv->out[EchoReply]++;
-		ipoput4(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	case Unreachable:
-		if(p->code > 5)
-			msg = unreachcode[1];
-		else
-			msg = unreachcode[p->code];
-
-		bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
-		if(blocklen(bp) < MinAdvise){
-			ipriv->stats[LenErrs]++;
-			goto raise;
-		}
-		p = (Icmp *)bp->rp;
-		pr = Fsrcvpcolx(icmp->f, p->proto);
-		if(pr != nil && pr->advise != nil) {
-			(*pr->advise)(pr, bp, msg);
-			return;
-		}
-
-		bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
-		goticmpkt(icmp, bp);
-		break;
-	case TimeExceed:
-		if(p->code == 0){
-			snprint(m2, sizeof m2, "ttl exceeded at %V", p->src);
-
-			bp->rp += ICMP_IPSIZE+ICMP_HDRSIZE;
-			if(blocklen(bp) < MinAdvise){
-				ipriv->stats[LenErrs]++;
-				goto raise;
-			}
-			p = (Icmp *)bp->rp;
-			pr = Fsrcvpcolx(icmp->f, p->proto);
-			if(pr != nil && pr->advise != nil) {
-				(*pr->advise)(pr, bp, m2);
-				return;
-			}
-			bp->rp -= ICMP_IPSIZE+ICMP_HDRSIZE;
-		}
-
-		goticmpkt(icmp, bp);
-		break;
-	default:
-		goticmpkt(icmp, bp);
-		break;
-	}
-	return;
-
-raise:
-	freeblist(bp);
-}
-
-void
-icmpadvise(Proto *icmp, Block *bp, char *msg)
-{
-	Conv	**c, *s;
-	Icmp	*p;
-	uchar	dst[IPaddrlen];
-	ushort	recid;
-
-	p = (Icmp *) bp->rp;
-	v4tov6(dst, p->dst);
-	recid = nhgets(p->icmpid);
-
-	for(c = icmp->conv; *c; c++) {
-		s = *c;
-		if(s->lport == recid)
-		if(ipcmp(s->raddr, dst) == 0){
-			qhangup(s->rq, msg);
-			qhangup(s->wq, msg);
-			break;
-		}
-	}
-	freeblist(bp);
-}
-
-int
-icmpstats(Proto *icmp, char *buf, int len)
-{
-	Icmppriv *priv;
-	char *p, *e;
-	int i;
-
-	priv = icmp->priv;
-	p = buf;
-	e = p+len;
-	for(i = 0; i < Nstats; i++)
-		p = seprint(p, e, "%s: %lud\n", statnames[i], priv->stats[i]);
-	for(i = 0; i <= Maxtype; i++){
-		if(icmpnames[i])
-			p = seprint(p, e, "%s: %lud %lud\n", icmpnames[i], priv->in[i], priv->out[i]);
-		else
-			p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i], priv->out[i]);
-	}
-	return p - buf;
-}
-
-void
-icmpinit(Fs *fs)
-{
-	Proto *icmp;
-
-	icmp = smalloc(sizeof(Proto));
-	icmp->priv = smalloc(sizeof(Icmppriv));
-	icmp->name = "icmp";
-	icmp->connect = icmpconnect;
-	icmp->announce = icmpannounce;
-	icmp->state = icmpstate;
-	icmp->create = icmpcreate;
-	icmp->close = icmpclose;
-	icmp->rcv = icmpiput;
-	icmp->stats = icmpstats;
-	icmp->ctl = nil;
-	icmp->advise = icmpadvise;
-	icmp->gc = nil;
-	icmp->ipproto = IP_ICMPPROTO;
-	icmp->nc = 128;
-	icmp->ptclsize = 0;
-
-	Fsproto(fs, icmp);
-}

+ 0 - 891
sys/src/9/ip/icmp6.c

@@ -1,891 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Internet Control Message Protocol for IPv6
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "ip.h"
-#include "ipv6.h"
-
-enum
-{
-	InMsgs6,
-	InErrors6,
-	OutMsgs6,
-	CsumErrs6,
-	LenErrs6,
-	HlenErrs6,
-	HoplimErrs6,
-	IcmpCodeErrs6,
-	TargetErrs6,
-	OptlenErrs6,
-	AddrmxpErrs6,
-	RouterAddrErrs6,
-
-	Nstats6,
-};
-
-enum {
-	ICMP_USEAD6	= 40,
-};
-
-enum {
-	Oflag	= 1<<5,
-	Sflag	= 1<<6,
-	Rflag	= 1<<7,
-};
-
-enum {
-	/* ICMPv6 types */
-	EchoReply	= 0,
-	UnreachableV6	= 1,
-	PacketTooBigV6	= 2,
-	TimeExceedV6	= 3,
-	SrcQuench	= 4,
-	ParamProblemV6	= 4,
-	Redirect	= 5,
-	EchoRequest	= 8,
-	TimeExceed	= 11,
-	InParmProblem	= 12,
-	Timestamp	= 13,
-	TimestampReply	= 14,
-	InfoRequest	= 15,
-	InfoReply	= 16,
-	AddrMaskRequest = 17,
-	AddrMaskReply   = 18,
-	EchoRequestV6	= 128,
-	EchoReplyV6	= 129,
-	RouterSolicit	= 133,
-	RouterAdvert	= 134,
-	NbrSolicit	= 135,
-	NbrAdvert	= 136,
-	RedirectV6	= 137,
-
-	Maxtype6	= 137,
-};
-
-/* on-the-wire packet formats */
-typedef struct IPICMP IPICMP;
-typedef struct Ndpkt Ndpkt;
-typedef struct NdiscC NdiscC;
-
-/* we do this to avoid possible struct padding  */
-#define ICMPHDR \
-	IPV6HDR; \
-	uchar	type; \
-	uchar	code; \
-	uchar	cksum[2]; \
-	uchar	icmpid[2]; \
-	uchar	seq[2]
-
-struct IPICMP {
-	ICMPHDR;
-	uchar	payload[];
-};
-
-#define IPICMPSZ offsetof(IPICMP, payload[0])
-
-struct NdiscC {
-	ICMPHDR;
-	uchar	target[IPaddrlen];
-	uchar	payload[];
-};
-
-#define NDISCSZ offsetof(NdiscC, payload[0])
-
-struct Ndpkt {
-	ICMPHDR;
-	uchar	target[IPaddrlen];
-	uchar	otype;
-	uchar	olen;		/* length in units of 8 octets(incl type, code),
-				 * 1 for IEEE 802 addresses */
-	uchar	lnaddr[6];	/* link-layer address */
-	uchar	payload[];
-};
-
-#define NDPKTSZ offsetof(Ndpkt, payload[0])
-
-typedef struct Icmppriv6
-{
-	ulong	stats[Nstats6];
-
-	/* message counts */
-	ulong	in[Maxtype6+1];
-	ulong	out[Maxtype6+1];
-} Icmppriv6;
-
-typedef struct Icmpcb6
-{
-	QLock;
-	uchar	headers;
-} Icmpcb6;
-
-char *icmpnames6[Maxtype6+1] =
-{
-[EchoReply]		"EchoReply",
-[UnreachableV6]		"UnreachableV6",
-[PacketTooBigV6]	"PacketTooBigV6",
-[TimeExceedV6]		"TimeExceedV6",
-[SrcQuench]		"SrcQuench",
-[Redirect]		"Redirect",
-[EchoRequest]		"EchoRequest",
-[TimeExceed]		"TimeExceed",
-[InParmProblem]		"InParmProblem",
-[Timestamp]		"Timestamp",
-[TimestampReply]	"TimestampReply",
-[InfoRequest]		"InfoRequest",
-[InfoReply]		"InfoReply",
-[AddrMaskRequest]	"AddrMaskRequest",
-[AddrMaskReply]		"AddrMaskReply",
-[EchoRequestV6]		"EchoRequestV6",
-[EchoReplyV6]		"EchoReplyV6",
-[RouterSolicit]		"RouterSolicit",
-[RouterAdvert]		"RouterAdvert",
-[NbrSolicit]		"NbrSolicit",
-[NbrAdvert]		"NbrAdvert",
-[RedirectV6]		"RedirectV6",
-};
-
-static char *statnames6[Nstats6] =
-{
-[InMsgs6]	"InMsgs",
-[InErrors6]	"InErrors",
-[OutMsgs6]	"OutMsgs",
-[CsumErrs6]	"CsumErrs",
-[LenErrs6]	"LenErrs",
-[HlenErrs6]	"HlenErrs",
-[HoplimErrs6]	"HoplimErrs",
-[IcmpCodeErrs6]	"IcmpCodeErrs",
-[TargetErrs6]	"TargetErrs",
-[OptlenErrs6]	"OptlenErrs",
-[AddrmxpErrs6]	"AddrmxpErrs",
-[RouterAddrErrs6]	"RouterAddrErrs",
-};
-
-static char *unreachcode[] =
-{
-[Icmp6_no_route]	"no route to destination",
-[Icmp6_ad_prohib]	"comm with destination administratively prohibited",
-[Icmp6_out_src_scope]	"beyond scope of source address",
-[Icmp6_adr_unreach]	"address unreachable",
-[Icmp6_port_unreach]	"port unreachable",
-[Icmp6_gress_src_fail]	"source address failed ingress/egress policy",
-[Icmp6_rej_route]	"reject route to destination",
-[Icmp6_unknown]		"icmp unreachable: unknown code",
-};
-
-static void icmpkick6(void *x, Block *bp);
-
-static void
-icmpcreate6(Conv *c)
-{
-	c->rq = qopen(64*1024, Qmsg, 0, c);
-	c->wq = qbypass(icmpkick6, c);
-}
-
-static void
-set_cksum(Block *bp)
-{
-	IPICMP *p = (IPICMP *)(bp->rp);
-
-	hnputl(p->vcf, 0);  	/* borrow IP header as pseudoheader */
-	hnputs(p->ploadlen, blocklen(bp) - IP6HDR);
-	p->proto = 0;
-	p->ttl = ICMPv6;	/* ttl gets set later */
-	hnputs(p->cksum, 0);
-	hnputs(p->cksum, ptclcsum(bp, 0, blocklen(bp)));
-	p->proto = ICMPv6;
-}
-
-static Block *
-newIPICMP(int packetlen)
-{
-	Block *nbp;
-
-	nbp = allocb(packetlen);
-	nbp->wp += packetlen;
-	memset(nbp->rp, 0, packetlen);
-	return nbp;
-}
-
-void
-icmpadvise6(Proto *icmp, Block *bp, char *msg)
-{
-	ushort recid;
-	Conv **c, *s;
-	IPICMP *p;
-
-	p = (IPICMP *)bp->rp;
-	recid = nhgets(p->icmpid);
-
-	for(c = icmp->conv; *c; c++) {
-		s = *c;
-		if(s->lport == recid && ipcmp(s->raddr, p->dst) == 0){
-			qhangup(s->rq, msg);
-			qhangup(s->wq, msg);
-			break;
-		}
-	}
-	freeblist(bp);
-}
-
-static void
-icmpkick6(void *x, Block *bp)
-{
-	uchar laddr[IPaddrlen], raddr[IPaddrlen];
-	Conv *c = x;
-	IPICMP *p;
-	Icmppriv6 *ipriv = c->p->priv;
-	Icmpcb6 *icb = (Icmpcb6*)c->ptcl;
-
-	if(bp == nil)
-		return;
-
-	if(icb->headers==6) {
-		/* get user specified addresses */
-		bp = pullupblock(bp, ICMP_USEAD6);
-		if(bp == nil)
-			return;
-		bp->rp += 8;
-		ipmove(laddr, bp->rp);
-		bp->rp += IPaddrlen;
-		ipmove(raddr, bp->rp);
-		bp->rp += IPaddrlen;
-		bp = padblock(bp, IP6HDR);
-	}
-
-	if(blocklen(bp) < IPICMPSZ){
-		freeblist(bp);
-		return;
-	}
-	p = (IPICMP *)(bp->rp);
-	if(icb->headers == 6) {
-		ipmove(p->dst, raddr);
-		ipmove(p->src, laddr);
-	} else {
-		ipmove(p->dst, c->raddr);
-		ipmove(p->src, c->laddr);
-		hnputs(p->icmpid, c->lport);
-	}
-
-	set_cksum(bp);
-	p->vcf[0] = 0x06 << 4;
-	if(p->type <= Maxtype6)
-		ipriv->out[p->type]++;
-	ipoput6(c->p->f, bp, 0, c->ttl, c->tos, nil);
-}
-
-char*
-icmpctl6(Conv *c, char **argv, int argc)
-{
-	Icmpcb6 *icb;
-
-	icb = (Icmpcb6*) c->ptcl;
-	if(argc==1 && strcmp(argv[0], "headers")==0) {
-		icb->headers = 6;
-		return nil;
-	}
-	return "unknown control request";
-}
-
-static void
-goticmpkt6(Proto *icmp, Block *bp, int muxkey)
-{
-	ushort recid;
-	uchar *addr;
-	Conv **c, *s;
-	IPICMP *p = (IPICMP *)bp->rp;
-
-	if(muxkey == 0) {
-		recid = nhgets(p->icmpid);
-		addr = p->src;
-	} else {
-		recid = muxkey;
-		addr = p->dst;
-	}
-
-	for(c = icmp->conv; *c; c++){
-		s = *c;
-		if(s->lport == recid && ipcmp(s->raddr, addr) == 0){
-			bp = concatblock(bp);
-			if(bp != nil)
-				qpass(s->rq, bp);
-			return;
-		}
-	}
-
-	freeblist(bp);
-}
-
-static Block *
-mkechoreply6(Block *bp, Ipifc *ifc)
-{
-	uchar addr[IPaddrlen];
-	IPICMP *p = (IPICMP *)(bp->rp);
-
-	ipmove(addr, p->src);
-	if(!isv6mcast(p->dst))
-		ipmove(p->src, p->dst);
-	else if (!ipv6anylocal(ifc, p->src))
-		return nil;
-	ipmove(p->dst, addr);
-	p->type = EchoReplyV6;
-	set_cksum(bp);
-	return bp;
-}
-
-/*
- * sends out an ICMPv6 neighbor solicitation
- * 	suni == SRC_UNSPEC or SRC_UNI,
- *	tuni == TARG_MULTI => multicast for address resolution,
- * 	and tuni == TARG_UNI => neighbor reachability.
- */
-extern void
-icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac)
-{
-	Block *nbp;
-	Ndpkt *np;
-	Proto *icmp = f->t2p[ICMPv6];
-	Icmppriv6 *ipriv = icmp->priv;
-
-	nbp = newIPICMP(NDPKTSZ);
-	np = (Ndpkt*) nbp->rp;
-
-	if(suni == SRC_UNSPEC)
-		memmove(np->src, v6Unspecified, IPaddrlen);
-	else
-		memmove(np->src, src, IPaddrlen);
-
-	if(tuni == TARG_UNI)
-		memmove(np->dst, targ, IPaddrlen);
-	else
-		ipv62smcast(np->dst, targ);
-
-	np->type = NbrSolicit;
-	np->code = 0;
-	memmove(np->target, targ, IPaddrlen);
-	if(suni != SRC_UNSPEC) {
-		np->otype = SRC_LLADDR;
-		np->olen = 1;		/* 1+1+6 = 8 = 1 8-octet */
-		memmove(np->lnaddr, mac, sizeof(np->lnaddr));
-	} else
-		nbp->wp -= NDPKTSZ - NDISCSZ;
-
-	set_cksum(nbp);
-	np = (Ndpkt*)nbp->rp;
-	np->ttl = HOP_LIMIT;
-	np->vcf[0] = 0x06 << 4;
-	ipriv->out[NbrSolicit]++;
-	netlog(f, Logicmp, "sending neighbor solicitation %I\n", targ);
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-}
-
-/*
- * sends out an ICMPv6 neighbor advertisement. pktflags == RSO flags.
- */
-extern void
-icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags)
-{
-	Block *nbp;
-	Ndpkt *np;
-	Proto *icmp = f->t2p[ICMPv6];
-	Icmppriv6 *ipriv = icmp->priv;
-
-	nbp = newIPICMP(NDPKTSZ);
-	np = (Ndpkt*)nbp->rp;
-
-	memmove(np->src, src, IPaddrlen);
-	memmove(np->dst, dst, IPaddrlen);
-
-	np->type = NbrAdvert;
-	np->code = 0;
-	np->icmpid[0] = flags;
-	memmove(np->target, targ, IPaddrlen);
-
-	np->otype = TARGET_LLADDR;
-	np->olen = 1;
-	memmove(np->lnaddr, mac, sizeof(np->lnaddr));
-
-	set_cksum(nbp);
-	np = (Ndpkt*) nbp->rp;
-	np->ttl = HOP_LIMIT;
-	np->vcf[0] = 0x06 << 4;
-	ipriv->out[NbrAdvert]++;
-	netlog(f, Logicmp, "sending neighbor advertisement %I\n", src);
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-}
-
-/* if free is true, freeblist(bp) before return. */
-extern void
-icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free)
-{
-	int osz, sz;
-	Block *nbp;
-	IPICMP *np;
-	Icmppriv6 *ipriv;
-	Ip6hdr *p;
-	Proto *icmp;
-
-	osz = BLEN(bp);
-	sz = MIN(IPICMPSZ + osz, v6MINTU);
-	icmp = f->t2p[ICMPv6];
-	ipriv = icmp->priv;
-	p = (Ip6hdr *)bp->rp;
-	if(isv6mcast(p->src))
-		goto freebl;
-	nbp = newIPICMP(sz);
-	np = (IPICMP *)nbp->rp;
-
-	rlock(ifc);
-	if(!ipv6anylocal(ifc, np->src)){
-		netlog(f, Logicmp, "icmphostunr fail -> src %I dst %I\n",
-			p->src, p->dst);
-		runlock(ifc);
-		freeblist(nbp);
-		goto freebl;
-	}
-
-	netlog(f, Logicmp, "send icmphostunr -> src %I dst %I\n", p->src, p->dst);
-	memmove(np->dst, p->src, IPaddrlen);
-	np->type = UnreachableV6;
-	np->code = code;
-	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
-	set_cksum(nbp);
-	np->ttl = HOP_LIMIT;
-	np->vcf[0] = 0x06 << 4;
-	ipriv->out[UnreachableV6]++;
-
-	if(free)
-		ipiput6(f, ifc, nbp);
-	else
-		ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-	runlock(ifc);
-freebl:
-	if(free)
-		freeblist(bp);
-}
-
-extern void
-icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp)
-{
-	int osz = BLEN(bp);
-	int sz = MIN(IPICMPSZ + osz, v6MINTU);
-	Block *nbp;
-	IPICMP *np;
-	Ip6hdr *p;
-	Proto *icmp = f->t2p[ICMPv6];
-	Icmppriv6 *ipriv = icmp->priv;
-
-	p = (Ip6hdr *)bp->rp;
-	if(isv6mcast(p->src))
-		return;
-
-	nbp = newIPICMP(sz);
-	np = (IPICMP *) nbp->rp;
-	if(ipv6anylocal(ifc, np->src))
-		netlog(f, Logicmp, "send icmpttlexceeded6 -> src %I dst %I\n",
-			p->src, p->dst);
-	else {
-		netlog(f, Logicmp, "icmpttlexceeded6 fail -> src %I dst %I\n",
-			p->src, p->dst);
-		return;
-	}
-
-	memmove(np->dst, p->src, IPaddrlen);
-	np->type = TimeExceedV6;
-	np->code = 0;
-	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
-	set_cksum(nbp);
-	np->ttl = HOP_LIMIT;
-	np->vcf[0] = 0x06 << 4;
-	ipriv->out[TimeExceedV6]++;
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-}
-
-extern void
-icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp)
-{
-	int osz = BLEN(bp);
-	int sz = MIN(IPICMPSZ + osz, v6MINTU);
-	Block *nbp;
-	IPICMP *np;
-	Ip6hdr *p;
-	Proto *icmp = f->t2p[ICMPv6];
-	Icmppriv6 *ipriv = icmp->priv;
-
-	p = (Ip6hdr *)bp->rp;
-	if(isv6mcast(p->src))
-		return;
-
-	nbp = newIPICMP(sz);
-	np = (IPICMP *)nbp->rp;
-	if(ipv6anylocal(ifc, np->src))
-		netlog(f, Logicmp, "send icmppkttoobig6 -> src %I dst %I\n",
-			p->src, p->dst);
-	else {
-		netlog(f, Logicmp, "icmppkttoobig6 fail -> src %I dst %I\n",
-			p->src, p->dst);
-		return;
-	}
-
-	memmove(np->dst, p->src, IPaddrlen);
-	np->type = PacketTooBigV6;
-	np->code = 0;
-	hnputl(np->icmpid, ifc->maxtu - ifc->m->hsize);
-	memmove(nbp->rp + IPICMPSZ, bp->rp, sz - IPICMPSZ);
-	set_cksum(nbp);
-	np->ttl = HOP_LIMIT;
-	np->vcf[0] = 0x06 << 4;
-	ipriv->out[PacketTooBigV6]++;
-	ipoput6(f, nbp, 0, MAXTTL, DFLTTOS, nil);
-}
-
-/*
- * RFC 2461, pages 39-40, pages 57-58.
- */
-static int
-valid(Proto *icmp, Ipifc *, Block *bp, Icmppriv6 *ipriv)
-{
-	int sz, osz, unsp, n, ttl, iplen, pktsz;
-	uchar *packet;
-	IPICMP *p;
-	Ndpkt *np;
-
-	n = blocklen(bp);
-	if(n < IPICMPSZ) {
-		ipriv->stats[HlenErrs6]++;
-		netlog(icmp->f, Logicmp, "icmp hlen %d\n", n);
-		goto err;
-	}
-
-	packet = bp->rp;
-	p = (IPICMP *)packet;
-	pktsz = BLEN(bp);
-	iplen = nhgets(p->ploadlen);
-	if(iplen > n - IP6HDR) {
-		ipriv->stats[LenErrs6]++;
-		netlog(icmp->f, Logicmp, "icmp length %d\n", iplen);
-		goto err;
-	}
-
-	/* Rather than construct explicit pseudoheader, overwrite IPv6 header */
-	if(p->proto != ICMPv6) {
-		/* This code assumes no extension headers!!! */
-		netlog(icmp->f, Logicmp, "icmp error: extension header\n");
-		goto err;
-	}
-	memset(packet, 0, 4);
-	ttl = p->ttl;
-	p->ttl = p->proto;
-	p->proto = 0;
-	if(ptclcsum(bp, 0, iplen + IP6HDR)) {
-		ipriv->stats[CsumErrs6]++;
-		netlog(icmp->f, Logicmp, "icmp checksum error\n");
-		goto err;
-	}
-	p->proto = p->ttl;
-	p->ttl = ttl;
-
-	/* additional tests for some pkt types */
-	if (p->type != NbrSolicit   && p->type != NbrAdvert &&
-	    p->type != RouterAdvert && p->type != RouterSolicit &&
-	    p->type != RedirectV6)
-		return 1;	/* TODO: unknown, presumed valid; why? */
-	if(p->ttl != HOP_LIMIT) {
-		ipriv->stats[HoplimErrs6]++;
-		goto err;
-	}
-	if(p->code != 0) {
-		ipriv->stats[IcmpCodeErrs6]++;
-		goto err;
-	}
-
-	switch (p->type) {
-	case NbrSolicit:
-	case NbrAdvert:
-		np = (Ndpkt*) p;
-		if(isv6mcast(np->target)) {
-			ipriv->stats[TargetErrs6]++;
-			goto err;
-		}
-		if(optexsts(np) && np->olen == 0) {
-			ipriv->stats[OptlenErrs6]++;
-			goto err;
-		}
-		if (p->type == NbrSolicit && ipcmp(np->src, v6Unspecified) == 0)
-			if(!issmcast(np->dst) || optexsts(np)) {
-				ipriv->stats[AddrmxpErrs6]++;
-				goto err;
-			}
-		if(p->type == NbrAdvert && isv6mcast(np->dst) &&
-		    nhgets(np->icmpid) & Sflag){
-			ipriv->stats[AddrmxpErrs6]++;
-			goto err;
-		}
-		break;
-	case RouterAdvert:
-		if(pktsz - IP6HDR < 16) {
-			ipriv->stats[HlenErrs6]++;
-			goto err;
-		}
-		if(!islinklocal(p->src)) {
-			ipriv->stats[RouterAddrErrs6]++;
-			goto err;
-		}
-		for (sz = IPICMPSZ + 8; sz+1 < pktsz; sz += 8*osz) {
-			osz = packet[sz+1];
-			if(osz <= 0) {
-				ipriv->stats[OptlenErrs6]++;
-				goto err;
-			}
-		}
-		break;
-	case RouterSolicit:
-		if(pktsz - IP6HDR < 8) {
-			ipriv->stats[HlenErrs6]++;
-			goto err;
-		}
-		unsp = (ipcmp(p->src, v6Unspecified) == 0);
-		for (sz = IPICMPSZ + 8; sz+1 < pktsz; sz += 8*osz) {
-			osz = packet[sz+1];
-			if(osz <= 0 || (unsp && packet[sz] == SRC_LLADDR)) {
-				ipriv->stats[OptlenErrs6]++;
-				goto err;
-			}
-		}
-		break;
-	case RedirectV6:
-		/* TODO: fill in */
-		break;
-	default:
-		goto err;
-	}
-	return 1;
-err:
-	ipriv->stats[InErrors6]++;
-	return 0;
-}
-
-static int
-targettype(Fs *f, Ipifc *ifc, uchar *target)
-{
-	Iplifc *lifc;
-	int t;
-
-	rlock(ifc);
-	if(ipproxyifc(f, ifc, target)) {
-		runlock(ifc);
-		return Tuniproxy;
-	}
-
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next)
-		if(ipcmp(lifc->local, target) == 0) {
-			t = (lifc->tentative)? Tunitent: Tunirany;
-			runlock(ifc);
-			return t;
-		}
-
-	runlock(ifc);
-	return 0;
-}
-
-/* bp needs to be freed with freeblist or passed on. */
-static void
-icmpiput6(Proto *icmp, Ipifc *ipifc, Block *bp)
-{
-	int type;
-	char *msg, m2[128];
-	uchar pktflags;
-	uchar *packet, *src;
-	uchar lsrc[IPaddrlen];
-	Block *r;
-	IPICMP *p;
-	Icmppriv6 *ipriv;
-	Iplifc *lifc;
-	Ndpkt* np;
-	Proto *pr;
-
-	packet = bp->rp;
-	p = (IPICMP *)packet;
-	type = p->type;
-	ipriv = icmp->priv;
-	if(!valid(icmp, ipifc, bp, ipriv) || type > Maxtype6)
-		goto raise;
-
-	ipriv->in[type]++;
-	switch(type) {
-	case EchoRequestV6:
-		bp = concatblock(bp);
-		r = mkechoreply6(bp, ipifc);
-		if(r == nil)
-			goto raise;
-		ipriv->out[EchoReply]++;
-		ipoput6(icmp->f, r, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	case UnreachableV6:
-		if(p->code >= nelem(unreachcode))
-			msg = unreachcode[Icmp6_unknown];
-		else
-			msg = unreachcode[p->code];
-
-		bp->rp += IPICMPSZ;
-		if(blocklen(bp) < 8){
-			ipriv->stats[LenErrs6]++;
-			goto raise;
-		}
-		p = (IPICMP *)bp->rp;
-		pr = Fsrcvpcolx(icmp->f, p->proto);
-		if(pr != nil && pr->advise != nil) {
-			(*pr->advise)(pr, bp, msg);
-			return;
-		}
-
-		bp->rp -= IPICMPSZ;
-		goticmpkt6(icmp, bp, 0);
-		break;
-	case TimeExceedV6:
-		if(p->code == 0){
-			snprint(m2, sizeof m2, "ttl exceeded at %I", p->src);
-			bp->rp += IPICMPSZ;
-			if(blocklen(bp) < 8){
-				ipriv->stats[LenErrs6]++;
-				goto raise;
-			}
-			p = (IPICMP *)bp->rp;
-			pr = Fsrcvpcolx(icmp->f, p->proto);
-			if(pr && pr->advise) {
-				(*pr->advise)(pr, bp, m2);
-				return;
-			}
-			bp->rp -= IPICMPSZ;
-		}
-		goticmpkt6(icmp, bp, 0);
-		break;
-	case RouterAdvert:
-	case RouterSolicit:
-		/* using lsrc as a temp, munge hdr for goticmp6 */
-		if (0) {
-			memmove(lsrc, p->src, IPaddrlen);
-			memmove(p->src, p->dst, IPaddrlen);
-			memmove(p->dst, lsrc, IPaddrlen);
-		}
-		goticmpkt6(icmp, bp, type);
-		break;
-	case NbrSolicit:
-		np = (Ndpkt*)p;			/* within bp */
-		pktflags = 0;
-		switch (targettype(icmp->f, ipifc, np->target)) {
-		case Tunirany:
-			pktflags |= Oflag;
-			/* fall through */
-		case Tuniproxy:
-			if(ipcmp(np->src, v6Unspecified) != 0) {
-				arpenter(icmp->f, V6, np->src, np->lnaddr,
-					8*np->olen-2, 0);
-				pktflags |= Sflag;
-			}
-			if(ipv6local(ipifc, lsrc)) {
-				src = np->src;
-				if(ipcmp(src, v6Unspecified) == 0)
-					src = v6allnodesL;
-				icmpna(icmp->f, lsrc, src, np->target,
-					ipifc->mac, pktflags);
-			}
-			break;
-		case Tunitent:
-			/*
-			 * not clear what needs to be done.  send up
-			 * an icmp mesg saying `don't use this address'?
-			 */
-			break;
-		}
-		freeblist(bp);
-		break;
-	case NbrAdvert:
-		/*
-		 * if the target address matches one of the local interface
-		 * addresses and the local interface address has tentative bit
-		 * set, insert into ARP table. this is so the duplicate address
-		 * detection part of ipconfig can discover duplication through
-		 * the arp table.
-		 */
-		np = (Ndpkt*)p;			/* within bp */
-		lifc = iplocalonifc(ipifc, np->target);
-		arpenter(icmp->f, V6, np->target, np->lnaddr, 8*np->olen-2,
-			lifc && lifc->tentative);
-		freeblist(bp);
-		break;
-	case PacketTooBigV6:
-	default:
-		goticmpkt6(icmp, bp, 0);
-		break;
-	}
-	return;
-
-raise:
-	freeblist(bp);
-}
-
-int
-icmpstats6(Proto *icmp6, char *buf, int len)
-{
-	Icmppriv6 *priv;
-	char *p, *e;
-	int i;
-
-	priv = icmp6->priv;
-	p = buf;
-	e = p+len;
-	for(i = 0; i < Nstats6; i++)
-		p = seprint(p, e, "%s: %lud\n", statnames6[i], priv->stats[i]);
-	for(i = 0; i <= Maxtype6; i++)
-		if(icmpnames6[i])
-			p = seprint(p, e, "%s: %lud %lud\n", icmpnames6[i],
-				priv->in[i], priv->out[i]);
-		else if (0)
-			p = seprint(p, e, "%d: %lud %lud\n", i, priv->in[i],
-				priv->out[i]);
-	return p - buf;
-}
-
-/* import from icmp.c */
-extern int	icmpstate(Conv *c, char *state, int n);
-extern char*	icmpannounce(Conv *c, char **argv, int argc);
-extern char*	icmpconnect(Conv *c, char **argv, int argc);
-extern void	icmpclose(Conv *c);
-
-void
-icmp6init(Fs *fs)
-{
-	Proto *icmp6 = smalloc(sizeof(Proto));
-
-	icmp6->priv = smalloc(sizeof(Icmppriv6));
-	icmp6->name = "icmpv6";
-	icmp6->connect = icmpconnect;
-	icmp6->announce = icmpannounce;
-	icmp6->state = icmpstate;
-	icmp6->create = icmpcreate6;
-	icmp6->close = icmpclose;
-	icmp6->rcv = icmpiput6;
-	icmp6->stats = icmpstats6;
-	icmp6->ctl = icmpctl6;
-	icmp6->advise = icmpadvise6;
-	icmp6->gc = nil;
-	icmp6->ipproto = ICMPv6;
-	icmp6->nc = 16;
-	icmp6->ptclsize = sizeof(Icmpcb6);
-
-	Fsproto(fs, icmp6);
-}

+ 0 - 308
sys/src/9/ip/igmp.c

@@ -1,308 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * igmp - internet group management protocol
- * unfinished.
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-enum
-{
-	IGMP_IPHDRSIZE	= 20,		/* size of ip header */
-	IGMP_HDRSIZE	= 8,		/* size of IGMP header */
-	IP_IGMPPROTO	= 2,
-
-	IGMPquery	= 1,
-	IGMPreport	= 2,
-
-	MSPTICK		= 100,
-	MAXTIMEOUT	= 10000/MSPTICK,	/* at most 10 secs for a response */
-};
-
-typedef struct IGMPpkt IGMPpkt;
-struct IGMPpkt
-{
-	/* ip header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	len[2];		/* packet length (including headers) */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	Unused;
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* checksum of ip portion */
-	uchar	src[IPaddrlen];		/* Ip source */
-	uchar	dst[IPaddrlen];		/* Ip destination */
-
-	/* igmp header */
-	uchar	vertype;	/* version and type */
-	uchar	unused;
-	uchar	igmpcksum[2];		/* checksum of igmp portion */
-	uchar	group[IPaddrlen];	/* multicast group */
-
-	uchar	payload[];
-};
-
-#define IGMPPKTSZ offsetof(IGMPpkt, payload[0])
-
-/*
- *  lists for group reports
- */
-typedef struct IGMPrep IGMPrep;
-struct IGMPrep
-{
-	IGMPrep		*next;
-	Medium		*m;
-	int		ticks;
-	Multicast	*multi;
-};
-
-typedef struct IGMP IGMP;
-struct IGMP
-{
-	Lock;
-	Rendez	r;
-	IGMPrep	*reports;
-};
-
-IGMP igmpalloc;
-
-	Proto	igmp;
-extern	Fs	fs;
-
-static struct Stats
-{
-	ulong 	inqueries;
-	ulong	outqueries;
-	ulong	inreports;
-	ulong	outreports;
-} stats;
-
-void
-igmpsendreport(Medium *m, uchar *addr)
-{
-	IGMPpkt *p;
-	Block *bp;
-
-	bp = allocb(sizeof(IGMPpkt));
-	if(bp == nil)
-		return;
-	p = (IGMPpkt*)bp->wp;
-	p->vihl = IP_VER4;
-	bp->wp += IGMPPKTSZ;
-	memset(bp->rp, 0, IGMPPKTSZ);
-	hnputl(p->src, Mediumgetaddr(m));
-	hnputl(p->dst, Ipallsys);
-	p->vertype = (1<<4) | IGMPreport;
-	p->proto = IP_IGMPPROTO;
-	memmove(p->group, addr, IPaddrlen);
-	hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE));
-	netlog(Logigmp, "igmpreport %I\n", p->group);
-	stats.outreports++;
-	ipoput4(bp, 0, 1, DFLTTOS, nil);	/* TTL of 1 */
-}
-
-static int
-isreport(void *a)
-{
-	USED(a);
-	return igmpalloc.reports != 0;
-}
-
-
-void
-igmpproc(void *a)
-{
-	IGMPrep *rp, **lrp;
-	Multicast *mp, **lmp;
-	uchar ip[IPaddrlen];
-
-	USED(a);
-
-	for(;;){
-		sleep(&igmpalloc.r, isreport, 0);
-		for(;;){
-			lock(&igmpalloc);
-
-			if(igmpalloc.reports == nil)
-				break;
-
-			/* look for a single report */
-			lrp = &igmpalloc.reports;
-			mp = nil;
-			for(rp = *lrp; rp; rp = *lrp){
-				rp->ticks++;
-				lmp = &rp->multi;
-				for(mp = *lmp; mp; mp = *lmp){
-					if(rp->ticks >= mp->timeout){
-						*lmp = mp->next;
-						break;
-					}
-					lmp = &mp->next;
-				}
-				if(mp != nil)
-					break;
-
-				if(rp->multi != nil){
-					lrp = &rp->next;
-					continue;
-				} else {
-					*lrp = rp->next;
-					free(rp);
-				}
-			}
-			unlock(&igmpalloc);
-
-			if(mp){
-				/* do a single report and try again */
-				hnputl(ip, mp->addr);
-				igmpsendreport(rp->m, ip);
-				free(mp);
-				continue;
-			}
-
-			tsleep(&up->sleep, return0, 0, MSPTICK);
-		}
-		unlock(&igmpalloc);
-	}
-
-}
-
-void
-igmpiput(Medium *m, Ipifc *, Block *bp)
-{
-	int n;
-	IGMPpkt *ghp;
-	Ipaddr group;
-	IGMPrep *rp, **lrp;
-	Multicast *mp, **lmp;
-
-	ghp = (IGMPpkt*)(bp->rp);
-	netlog(Logigmp, "igmpiput: %d %I\n", ghp->vertype, ghp->group);
-
-	n = blocklen(bp);
-	if(n < IGMP_IPHDRSIZE+IGMP_HDRSIZE){
-		netlog(Logigmp, "igmpiput: bad len\n");
-		goto error;
-	}
-	if((ghp->vertype>>4) != 1){
-		netlog(Logigmp, "igmpiput: bad igmp type\n");
-		goto error;
-	}
-	if(ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE)){
-		netlog(Logigmp, "igmpiput: checksum error %I\n", ghp->src);
-		goto error;
-	}
-
-	group = nhgetl(ghp->group);
-
-	lock(&igmpalloc);
-	switch(ghp->vertype & 0xf){
-	case IGMPquery:
-		/*
-		 *  start reporting groups that we're a member of.
-		 */
-		stats.inqueries++;
-		for(rp = igmpalloc.reports; rp; rp = rp->next)
-			if(rp->m == m)
-				break;
-		if(rp != nil)
-			break;	/* already reporting */
-
-		mp = Mediumcopymulti(m);
-		if(mp == nil)
-			break;
-
-		rp = malloc(sizeof(*rp));
-		if(rp == nil)
-			break;
-
-		rp->m = m;
-		rp->multi = mp;
-		rp->ticks = 0;
-		for(; mp; mp = mp->next)
-			mp->timeout = nrand(MAXTIMEOUT);
-		rp->next = igmpalloc.reports;
-		igmpalloc.reports = rp;
-
-		wakeup(&igmpalloc.r);
-
-		break;
-	case IGMPreport:
-		/*
-		 *  find report list for this medium
-		 */
-		stats.inreports++;
-		lrp = &igmpalloc.reports;
-		for(rp = *lrp; rp; rp = *lrp){
-			if(rp->m == m)
-				break;
-			lrp = &rp->next;
-		}
-		if(rp == nil)
-			break;
-
-		/*
-		 *  if someone else has reported a group,
-		 *  we don't have to.
-		 */
-		lmp = &rp->multi;
-		for(mp = *lmp; mp; mp = *lmp){
-			if(mp->addr == group){
-				*lmp = mp->next;
-				free(mp);
-				break;
-			}
-			lmp = &mp->next;
-		}
-
-		break;
-	}
-	unlock(&igmpalloc);
-
-error:
-	freeb(bp);
-}
-
-int
-igmpstats(char *buf, int len)
-{
-	return snprint(buf, len, "\trcvd %d %d\n\tsent %d %d\n",
-		stats.inqueries, stats.inreports,
-		stats.outqueries, stats.outreports);
-}
-
-void
-igmpinit(Fs *fs)
-{
-	igmp.name = "igmp";
-	igmp.connect = nil;
-	igmp.announce = nil;
-	igmp.ctl = nil;
-	igmp.state = nil;
-	igmp.close = nil;
-	igmp.rcv = igmpiput;
-	igmp.stats = igmpstats;
-	igmp.ipproto = IP_IGMPPROTO;
-	igmp.nc = 0;
-	igmp.ptclsize = 0;
-
-	igmpreportfn = igmpsendreport;
-	kproc("igmpproc", igmpproc, 0);
-
-	Fsproto(fs, &igmp);
-}

+ 0 - 37
sys/src/9/ip/inferno.c

@@ -1,37 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-/*
- *  some hacks for commonality twixt inferno and plan9
- */
-
-char*
-commonuser(void)
-{
-	return up->user;
-}
-
-char*
-commonerror(void)
-{
-	return up->errstr;
-}
-
-int
-bootpread(char*, ulong, int)
-{
-	return	0;
-}

+ 0 - 716
sys/src/9/ip/ip.c

@@ -1,716 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-
-#define BLKIPVER(xp)	(((Ip4hdr*)((xp)->rp))->vihl&0xF0)
-
-static char *statnames[] =
-{
-[Forwarding]	"Forwarding",
-[DefaultTTL]	"DefaultTTL",
-[InReceives]	"InReceives",
-[InHdrErrors]	"InHdrErrors",
-[InAddrErrors]	"InAddrErrors",
-[ForwDatagrams]	"ForwDatagrams",
-[InUnknownProtos]	"InUnknownProtos",
-[InDiscards]	"InDiscards",
-[InDelivers]	"InDelivers",
-[OutRequests]	"OutRequests",
-[OutDiscards]	"OutDiscards",
-[OutNoRoutes]	"OutNoRoutes",
-[ReasmTimeout]	"ReasmTimeout",
-[ReasmReqds]	"ReasmReqds",
-[ReasmOKs]	"ReasmOKs",
-[ReasmFails]	"ReasmFails",
-[FragOKs]	"FragOKs",
-[FragFails]	"FragFails",
-[FragCreates]	"FragCreates",
-};
-
-#define BLKIP(xp)	((Ip4hdr*)((xp)->rp))
-/*
- * This sleazy macro relies on the media header size being
- * larger than sizeof(Ipfrag). ipreassemble checks this is true
- */
-#define BKFG(xp)	((Ipfrag*)((xp)->base))
-
-ushort		ipcsum(uchar*);
-Block*		ip4reassemble(IP*, int, Block*, Ip4hdr*);
-void		ipfragfree4(IP*, Fragment4*);
-Fragment4*	ipfragallo4(IP*);
-
-void
-ip_init_6(Fs *f)
-{
-	v6params *v6p;
-
-	v6p = smalloc(sizeof(v6params));
-
-	v6p->rp.mflag		= 0;		/* default not managed */
-	v6p->rp.oflag		= 0;
-	v6p->rp.maxraint	= 600000;	/* millisecs */
-	v6p->rp.minraint	= 200000;
-	v6p->rp.linkmtu		= 0;		/* no mtu sent */
-	v6p->rp.reachtime	= 0;
-	v6p->rp.rxmitra		= 0;
-	v6p->rp.ttl		= MAXTTL;
-	v6p->rp.routerlt	= 3 * v6p->rp.maxraint;
-
-	v6p->hp.rxmithost	= 1000;		/* v6 RETRANS_TIMER */
-
-	v6p->cdrouter 		= -1;
-
-	f->v6p			= v6p;
-}
-
-void
-initfrag(IP *ip, int size)
-{
-	Fragment4 *fq4, *eq4;
-	Fragment6 *fq6, *eq6;
-
-	ip->fragfree4 = (Fragment4*)malloc(sizeof(Fragment4) * size);
-	if(ip->fragfree4 == nil)
-		panic("initfrag");
-
-	eq4 = &ip->fragfree4[size];
-	for(fq4 = ip->fragfree4; fq4 < eq4; fq4++)
-		fq4->next = fq4+1;
-
-	ip->fragfree4[size-1].next = nil;
-
-	ip->fragfree6 = (Fragment6*)malloc(sizeof(Fragment6) * size);
-	if(ip->fragfree6 == nil)
-		panic("initfrag");
-
-	eq6 = &ip->fragfree6[size];
-	for(fq6 = ip->fragfree6; fq6 < eq6; fq6++)
-		fq6->next = fq6+1;
-
-	ip->fragfree6[size-1].next = nil;
-}
-
-void
-ip_init(Fs *f)
-{
-	IP *ip;
-
-	ip = smalloc(sizeof(IP));
-	initfrag(ip, 100);
-	f->ip = ip;
-
-	ip_init_6(f);
-}
-
-void
-iprouting(Fs *f, int on)
-{
-	f->ip->iprouting = on;
-	if(f->ip->iprouting==0)
-		f->ip->stats[Forwarding] = 2;
-	else
-		f->ip->stats[Forwarding] = 1;
-}
-
-int
-ipoput4(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
-{
-	Ipifc *ifc;
-	uchar *gate;
-	ulong fragoff;
-	Block *xp, *nb;
-	Ip4hdr *eh, *feh;
-	int lid, len, seglen, chunk, dlen, blklen, offset, medialen;
-	Route *r, *sr;
-	IP *ip;
-	int rv = 0;
-
-	ip = f->ip;
-
-	/* Fill out the ip header */
-	eh = (Ip4hdr*)(bp->rp);
-
-	ip->stats[OutRequests]++;
-
-	/* Number of uchars in data and ip header to write */
-	len = blocklen(bp);
-
-	if(gating){
-		chunk = nhgets(eh->length);
-		if(chunk > len){
-			ip->stats[OutDiscards]++;
-			netlog(f, Logip, "short gated packet\n");
-			goto free;
-		}
-		if(chunk < len)
-			len = chunk;
-	}
-	if(len >= IP_MAX){
-		ip->stats[OutDiscards]++;
-		netlog(f, Logip, "exceeded ip max size %V\n", eh->dst);
-		goto free;
-	}
-
-	r = v4lookup(f, eh->dst, c);
-	if(r == nil){
-		ip->stats[OutNoRoutes]++;
-		netlog(f, Logip, "no interface %V\n", eh->dst);
-		rv = -1;
-		goto free;
-	}
-
-	ifc = r->ifc;
-	if(r->type & (Rifc|Runi))
-		gate = eh->dst;
-	else
-	if(r->type & (Rbcast|Rmulti)) {
-		gate = eh->dst;
-		sr = v4lookup(f, eh->src, nil);
-		if(sr != nil && (sr->type & Runi))
-			ifc = sr->ifc;
-	}
-	else
-		gate = r->v4.gate;
-
-	if(!gating)
-		eh->vihl = IP_VER4|IP_HLEN4;
-	eh->ttl = ttl;
-	if(!gating)
-		eh->tos = tos;
-
-	if(!canrlock(ifc))
-		goto free;
-	if(waserror()){
-		runlock(ifc);
-		nexterror();
-	}
-	if(ifc->m == nil)
-		goto raise;
-
-	/* If we dont need to fragment just send it */
-	if(c && c->maxfragsize && c->maxfragsize < ifc->maxtu)
-		medialen = c->maxfragsize - ifc->m->hsize;
-	else
-		medialen = ifc->maxtu - ifc->m->hsize;
-	if(len <= medialen) {
-		if(!gating)
-			hnputs(eh->id, incref(&ip->id4));
-		hnputs(eh->length, len);
-		if(!gating){
-			eh->frag[0] = 0;
-			eh->frag[1] = 0;
-		}
-		eh->cksum[0] = 0;
-		eh->cksum[1] = 0;
-		hnputs(eh->cksum, ipcsum(&eh->vihl));
-		assert(bp->next == nil);
-		ifc->m->bwrite(ifc, bp, V4, gate);
-		runlock(ifc);
-		poperror();
-		return 0;
-	}
-
-	if((eh->frag[0] & (IP_DF>>8)) && !gating)
-		print("%V: DF set\n", eh->dst);
-
-	if(eh->frag[0] & (IP_DF>>8)){
-		ip->stats[FragFails]++;
-		ip->stats[OutDiscards]++;
-		icmpcantfrag(f, bp, medialen);
-		netlog(f, Logip, "%V: eh->frag[0] & (IP_DF>>8)\n", eh->dst);
-		goto raise;
-	}
-
-	seglen = (medialen - IP4HDR) & ~7;
-	if(seglen < 8){
-		ip->stats[FragFails]++;
-		ip->stats[OutDiscards]++;
-		netlog(f, Logip, "%V seglen < 8\n", eh->dst);
-		goto raise;
-	}
-
-	dlen = len - IP4HDR;
-	xp = bp;
-	if(gating)
-		lid = nhgets(eh->id);
-	else
-		lid = incref(&ip->id4);
-
-	offset = IP4HDR;
-	while(xp != nil && offset && offset >= BLEN(xp)) {
-		offset -= BLEN(xp);
-		xp = xp->next;
-	}
-	xp->rp += offset;
-
-	if(gating)
-		fragoff = nhgets(eh->frag)<<3;
-	else
-		fragoff = 0;
-	dlen += fragoff;
-	for(; fragoff < dlen; fragoff += seglen) {
-		nb = allocb(IP4HDR+seglen);
-		feh = (Ip4hdr*)(nb->rp);
-
-		memmove(nb->wp, eh, IP4HDR);
-		nb->wp += IP4HDR;
-
-		if((fragoff + seglen) >= dlen) {
-			seglen = dlen - fragoff;
-			hnputs(feh->frag, fragoff>>3);
-		}
-		else
-			hnputs(feh->frag, (fragoff>>3)|IP_MF);
-
-		hnputs(feh->length, seglen + IP4HDR);
-		hnputs(feh->id, lid);
-
-		/* Copy up the data area */
-		chunk = seglen;
-		while(chunk) {
-			if(!xp) {
-				ip->stats[OutDiscards]++;
-				ip->stats[FragFails]++;
-				freeblist(nb);
-				netlog(f, Logip, "!xp: chunk %d\n", chunk);
-				goto raise;
-			}
-			blklen = chunk;
-			if(BLEN(xp) < chunk)
-				blklen = BLEN(xp);
-			memmove(nb->wp, xp->rp, blklen);
-			nb->wp += blklen;
-			xp->rp += blklen;
-			chunk -= blklen;
-			if(xp->rp == xp->wp)
-				xp = xp->next;
-		}
-
-		feh->cksum[0] = 0;
-		feh->cksum[1] = 0;
-		hnputs(feh->cksum, ipcsum(&feh->vihl));
-		ifc->m->bwrite(ifc, nb, V4, gate);
-		ip->stats[FragCreates]++;
-	}
-	ip->stats[FragOKs]++;
-raise:
-	runlock(ifc);
-	poperror();
-free:
-	freeblist(bp);
-	return rv;
-}
-
-void
-ipiput4(Fs *f, Ipifc *ifc, Block *bp)
-{
-	int hl;
-	int hop, tos, proto, olen;
-	Ip4hdr *h;
-	Proto *p;
-	ushort frag;
-	int notforme;
-	uchar *dp, v6dst[IPaddrlen];
-	IP *ip;
-	Route *r;
-	Conv conv;
-
-	if(BLKIPVER(bp) != IP_VER4) {
-		ipiput6(f, ifc, bp);
-		return;
-	}
-
-	ip = f->ip;
-	ip->stats[InReceives]++;
-
-	/*
-	 *  Ensure we have all the header info in the first
-	 *  block.  Make life easier for other protocols by
-	 *  collecting up to the first 64 bytes in the first block.
-	 */
-	if(BLEN(bp) < 64) {
-		hl = blocklen(bp);
-		if(hl < IP4HDR)
-			hl = IP4HDR;
-		if(hl > 64)
-			hl = 64;
-		bp = pullupblock(bp, hl);
-		if(bp == nil)
-			return;
-	}
-
-	h = (Ip4hdr*)(bp->rp);
-
-	/* dump anything that whose header doesn't checksum */
-	if((bp->flag & Bipck) == 0 && ipcsum(&h->vihl)) {
-		ip->stats[InHdrErrors]++;
-		netlog(f, Logip, "ip: checksum error %V\n", h->src);
-		freeblist(bp);
-		return;
-	}
-	v4tov6(v6dst, h->dst);
-	notforme = ipforme(f, v6dst) == 0;
-
-	/* Check header length and version */
-	if((h->vihl&0x0F) != IP_HLEN4) {
-		hl = (h->vihl&0xF)<<2;
-		if(hl < (IP_HLEN4<<2)) {
-			ip->stats[InHdrErrors]++;
-			netlog(f, Logip, "ip: %V bad hivl %ux\n", h->src, h->vihl);
-			freeblist(bp);
-			return;
-		}
-		/* If this is not routed strip off the options */
-		if(notforme == 0) {
-			olen = nhgets(h->length);
-			dp = bp->rp + (hl - (IP_HLEN4<<2));
-			memmove(dp, h, IP_HLEN4<<2);
-			bp->rp = dp;
-			h = (Ip4hdr*)(bp->rp);
-			h->vihl = (IP_VER4|IP_HLEN4);
-			hnputs(h->length, olen-hl+(IP_HLEN4<<2));
-		}
-	}
-
-	/* route */
-	if(notforme) {
-		if(!ip->iprouting){
-			freeblist(bp);
-			return;
-		}
-
-		/* don't forward to source's network */
-		memset(&conv, 0, sizeof conv);
-		conv.r = nil;
-		r = v4lookup(f, h->dst, &conv);
-		if(r == nil || r->ifc == ifc){
-			ip->stats[OutDiscards]++;
-			freeblist(bp);
-			return;
-		}
-
-		/* don't forward if packet has timed out */
-		hop = h->ttl;
-		if(hop < 1) {
-			ip->stats[InHdrErrors]++;
-			icmpttlexceeded(f, ifc->lifc->local, bp);
-			freeblist(bp);
-			return;
-		}
-
-		/* reassemble if the interface expects it */
-if(r->ifc == nil) panic("nil route rfc");
-		if(r->ifc->reassemble){
-			frag = nhgets(h->frag);
-			if(frag) {
-				h->tos = 0;
-				if(frag & IP_MF)
-					h->tos = 1;
-				bp = ip4reassemble(ip, frag, bp, h);
-				if(bp == nil)
-					return;
-				h = (Ip4hdr*)(bp->rp);
-			}
-		}
-
-		ip->stats[ForwDatagrams]++;
-		tos = h->tos;
-		hop = h->ttl;
-		ipoput4(f, bp, 1, hop - 1, tos, &conv);
-		return;
-	}
-
-	frag = nhgets(h->frag);
-	if(frag) {
-		h->tos = 0;
-		if(frag & IP_MF)
-			h->tos = 1;
-		bp = ip4reassemble(ip, frag, bp, h);
-		if(bp == nil)
-			return;
-		h = (Ip4hdr*)(bp->rp);
-	}
-
-	/* don't let any frag info go up the stack */
-	h->frag[0] = 0;
-	h->frag[1] = 0;
-
-	proto = h->proto;
-	p = Fsrcvpcol(f, proto);
-	if(p != nil && p->rcv != nil) {
-		ip->stats[InDelivers]++;
-		(*p->rcv)(p, ifc, bp);
-		return;
-	}
-	ip->stats[InDiscards]++;
-	ip->stats[InUnknownProtos]++;
-	freeblist(bp);
-}
-
-int
-ipstats(Fs *f, char *buf, int len)
-{
-	IP *ip;
-	char *p, *e;
-	int i;
-
-	ip = f->ip;
-	ip->stats[DefaultTTL] = MAXTTL;
-
-	p = buf;
-	e = p+len;
-	for(i = 0; i < Nipstats; i++)
-		p = seprint(p, e, "%s: %llud\n", statnames[i], ip->stats[i]);
-	return p - buf;
-}
-
-Block*
-ip4reassemble(IP *ip, int offset, Block *bp, Ip4hdr *ih)
-{
-	int fend;
-	ushort id;
-	Fragment4 *f, *fnext;
-	ulong src, dst;
-	Block *bl, **l, *last, *prev;
-	int ovlap, len, fragsize, pktposn;
-
-	src = nhgetl(ih->src);
-	dst = nhgetl(ih->dst);
-	id = nhgets(ih->id);
-
-	/*
-	 *  block lists are too hard, pullupblock into a single block
-	 */
-	if(bp->next){
-		bp = pullupblock(bp, blocklen(bp));
-		ih = (Ip4hdr*)(bp->rp);
-	}
-
-	qlock(&ip->fraglock4);
-
-	/*
-	 *  find a reassembly queue for this fragment
-	 */
-	for(f = ip->flisthead4; f; f = fnext){
-		fnext = f->next;	/* because ipfragfree4 changes the list */
-		if(f->src == src && f->dst == dst && f->id == id)
-			break;
-		if(f->age < NOW){
-			ip->stats[ReasmTimeout]++;
-			ipfragfree4(ip, f);
-		}
-	}
-
-	/*
-	 *  if this isn't a fragmented packet, accept it
-	 *  and get rid of any fragments that might go
-	 *  with it.
-	 */
-	if(!ih->tos && (offset & ~(IP_MF|IP_DF)) == 0) {
-		if(f != nil) {
-			ipfragfree4(ip, f);
-			ip->stats[ReasmFails]++;
-		}
-		qunlock(&ip->fraglock4);
-		return bp;
-	}
-
-	if(bp->base+IPFRAGSZ >= bp->rp){
-		bp = padblock(bp, IPFRAGSZ);
-		bp->rp += IPFRAGSZ;
-	}
-
-	BKFG(bp)->foff = offset<<3;
-	BKFG(bp)->flen = nhgets(ih->length)-IP4HDR;
-
-	/* First fragment allocates a reassembly queue */
-	if(f == nil) {
-		f = ipfragallo4(ip);
-		f->id = id;
-		f->src = src;
-		f->dst = dst;
-
-		f->blist = bp;
-
-		qunlock(&ip->fraglock4);
-		ip->stats[ReasmReqds]++;
-		return nil;
-	}
-
-	/*
-	 *  find the new fragment's position in the queue
-	 */
-	prev = nil;
-	l = &f->blist;
-	bl = f->blist;
-	while(bl != nil && BKFG(bp)->foff > BKFG(bl)->foff) {
-		prev = bl;
-		l = &bl->next;
-		bl = bl->next;
-	}
-
-	/* Check overlap of a previous fragment - trim away as necessary */
-	if(prev) {
-		ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
-		if(ovlap > 0) {
-			if(ovlap >= BKFG(bp)->flen) {
-				freeblist(bp);
-				qunlock(&ip->fraglock4);
-				return nil;
-			}
-			BKFG(prev)->flen -= ovlap;
-		}
-	}
-
-	/* Link onto assembly queue */
-	bp->next = *l;
-	*l = bp;
-
-	/* Check to see if succeeding segments overlap */
-	if(bp->next) {
-		l = &bp->next;
-		fend = BKFG(bp)->foff + BKFG(bp)->flen;
-		/* Take completely covered segments out */
-		while(*l) {
-			ovlap = fend - BKFG(*l)->foff;
-			if(ovlap <= 0)
-				break;
-			if(ovlap < BKFG(*l)->flen) {
-				BKFG(*l)->flen -= ovlap;
-				BKFG(*l)->foff += ovlap;
-				/* move up ih hdrs */
-				memmove((*l)->rp + ovlap, (*l)->rp, IP4HDR);
-				(*l)->rp += ovlap;
-				break;
-			}
-			last = (*l)->next;
-			(*l)->next = nil;
-			freeblist(*l);
-			*l = last;
-		}
-	}
-
-	/*
-	 *  look for a complete packet.  if we get to a fragment
-	 *  without IP_MF set, we're done.
-	 */
-	pktposn = 0;
-	for(bl = f->blist; bl; bl = bl->next) {
-		if(BKFG(bl)->foff != pktposn)
-			break;
-		if((BLKIP(bl)->frag[0]&(IP_MF>>8)) == 0) {
-			bl = f->blist;
-			len = nhgets(BLKIP(bl)->length);
-			bl->wp = bl->rp + len;
-
-			/* Pullup all the fragment headers and
-			 * return a complete packet
-			 */
-			for(bl = bl->next; bl; bl = bl->next) {
-				fragsize = BKFG(bl)->flen;
-				len += fragsize;
-				bl->rp += IP4HDR;
-				bl->wp = bl->rp + fragsize;
-			}
-
-			bl = f->blist;
-			f->blist = nil;
-			ipfragfree4(ip, f);
-			ih = BLKIP(bl);
-			hnputs(ih->length, len);
-			qunlock(&ip->fraglock4);
-			ip->stats[ReasmOKs]++;
-			return bl;
-		}
-		pktposn += BKFG(bl)->flen;
-	}
-	qunlock(&ip->fraglock4);
-	return nil;
-}
-
-/*
- * ipfragfree4 - Free a list of fragments - assume hold fraglock4
- */
-void
-ipfragfree4(IP *ip, Fragment4 *frag)
-{
-	Fragment4 *fl, **l;
-
-	if(frag->blist)
-		freeblist(frag->blist);
-
-	frag->src = 0;
-	frag->id = 0;
-	frag->blist = nil;
-
-	l = &ip->flisthead4;
-	for(fl = *l; fl; fl = fl->next) {
-		if(fl == frag) {
-			*l = frag->next;
-			break;
-		}
-		l = &fl->next;
-	}
-
-	frag->next = ip->fragfree4;
-	ip->fragfree4 = frag;
-
-}
-
-/*
- * ipfragallo4 - allocate a reassembly queue - assume hold fraglock4
- */
-Fragment4 *
-ipfragallo4(IP *ip)
-{
-	Fragment4 *f;
-
-	while(ip->fragfree4 == nil) {
-		/* free last entry on fraglist */
-		for(f = ip->flisthead4; f->next; f = f->next)
-			;
-		ipfragfree4(ip, f);
-	}
-	f = ip->fragfree4;
-	ip->fragfree4 = f->next;
-	f->next = ip->flisthead4;
-	ip->flisthead4 = f;
-	f->age = NOW + 30000;
-
-	return f;
-}
-
-ushort
-ipcsum(uchar *addr)
-{
-	int len;
-	ulong sum;
-
-	sum = 0;
-	len = (addr[0]&0xf)<<2;
-
-	while(len > 0) {
-		sum += addr[0]<<8 | addr[1] ;
-		len -= 2;
-		addr += 2;
-	}
-
-	sum = (sum & 0xffff) + (sum >> 16);
-	sum = (sum & 0xffff) + (sum >> 16);
-
-	return (sum^0xffff);
-}

+ 0 - 753
sys/src/9/ip/ip.h

@@ -1,753 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-typedef struct	Conv	Conv;
-typedef struct	Fragment4 Fragment4;
-typedef struct	Fragment6 Fragment6;
-typedef struct	Fs	Fs;
-typedef union	Hwaddr	Hwaddr;
-typedef struct	IP	IP;
-typedef struct	IPaux	IPaux;
-typedef struct	Ip4hdr	Ip4hdr;
-typedef struct	Ipfrag	Ipfrag;
-typedef struct	Ipself	Ipself;
-typedef struct	Ipselftab	Ipselftab;
-typedef struct	Iplink	Iplink;
-typedef struct	Iplifc	Iplifc;
-typedef struct	Ipmulti	Ipmulti;
-typedef struct	Ipifc	Ipifc;
-typedef struct	Iphash	Iphash;
-typedef struct	Ipht	Ipht;
-typedef struct	Netlog	Netlog;
-typedef struct	Medium	Medium;
-typedef struct	Proto	Proto;
-typedef struct	Arpent	Arpent;
-typedef struct	Arp Arp;
-typedef struct	Route	Route;
-
-typedef struct	Routerparams	Routerparams;
-typedef struct 	Hostparams	Hostparams;
-typedef struct 	v6router	v6router;
-typedef struct	v6params	v6params;
-
-#pragma incomplete Arp
-#pragma incomplete Ipself
-#pragma incomplete Ipselftab
-#pragma incomplete IP
-#pragma incomplete Netlog
-
-enum
-{
-	Addrlen=	64,
-	Maxproto=	20,
-	Nhash=		64,
-	Maxincall=	64,	/* max. conn.s in listen q not accepted yet */
-	Nchans=		1024,
-	MAClen=		16,		/* longest mac address */
-
-	MAXTTL=		255,
-	DFLTTOS=	0,
-
-	IPaddrlen=	16,
-	IPv4addrlen=	4,
-	IPv4off=	12,
-	IPllen=		4,
-
-	/* ip versions */
-	V4=		4,
-	V6=		6,
-	IP_VER4= 	0x40,
-	IP_VER6=	0x60,
-	IP_HLEN4=	5,		/* v4: Header length in words */
-	IP_DF=		0x4000,		/* v4: Don't fragment */
-	IP_MF=		0x2000,		/* v4: More fragments */
-	IP4HDR=		20,		/* sizeof(Ip4hdr) */
-	IP_MAX=		64*1024,	/* Max. Internet packet size, v4 & v6 */
-
-	/* 2^Lroot trees in the root table */
-	Lroot=		10,
-
-	Maxpath =	64,
-};
-
-enum
-{
-	Idle=		0,
-	Announcing=	1,
-	Announced=	2,
-	Connecting=	3,
-	Connected=	4,
-};
-
-/* MIB II counters */
-enum
-{
-	Forwarding,
-	DefaultTTL,
-	InReceives,
-	InHdrErrors,
-	InAddrErrors,
-	ForwDatagrams,
-	InUnknownProtos,
-	InDiscards,
-	InDelivers,
-	OutRequests,
-	OutDiscards,
-	OutNoRoutes,
-	ReasmTimeout,
-	ReasmReqds,
-	ReasmOKs,
-	ReasmFails,
-	FragOKs,
-	FragFails,
-	FragCreates,
-
-	Nipstats,
-};
-
-struct Fragment4
-{
-	Block*	blist;
-	Fragment4*	next;
-	ulong 	src;
-	ulong 	dst;
-	ushort	id;
-	ulong 	age;
-};
-
-struct Fragment6
-{
-	Block*	blist;
-	Fragment6*	next;
-	uchar 	src[IPaddrlen];
-	uchar 	dst[IPaddrlen];
-	uint	id;
-	ulong 	age;
-};
-
-struct Ipfrag
-{
-	ushort	foff;
-	ushort	flen;
-
-	uchar	payload[];
-};
-
-#define IPFRAGSZ offsetof(Ipfrag, payload[0])
-
-/* an instance of IP */
-struct IP
-{
-	uvlong		stats[Nipstats];
-
-	QLock		fraglock4;
-	Fragment4*	flisthead4;
-	Fragment4*	fragfree4;
-	Ref		id4;
-
-	QLock		fraglock6;
-	Fragment6*	flisthead6;
-	Fragment6*	fragfree6;
-	Ref		id6;
-
-	int		iprouting;	/* true if we route like a gateway */
-};
-
-/* on the wire packet header */
-struct Ip4hdr
-{
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* ip->identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;      	/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* IP source */
-	uchar	dst[4];		/* IP destination */
-};
-
-/*
- *  one per conversation directory
- */
-struct Conv
-{
-	QLock;
-
-	int	x;			/* conversation index */
-	Proto*	p;
-
-	int	restricted;		/* remote port is restricted */
-	uint	ttl;			/* max time to live */
-	uint	tos;			/* type of service */
-	int	ignoreadvice;		/* don't terminate connection on icmp errors */
-
-	uchar	ipversion;
-	uchar	laddr[IPaddrlen];	/* local IP address */
-	uchar	raddr[IPaddrlen];	/* remote IP address */
-	ushort	lport;			/* local port number */
-	ushort	rport;			/* remote port number */
-
-	char	*owner;			/* protections */
-	int	perm;
-	int	inuse;			/* opens of listen/data/ctl */
-	int	length;
-	int	state;
-
-	int	maxfragsize;		/* If set, used for fragmentation */
-
-	/* udp specific */
-	int	headers;		/* data src/dst headers in udp */
-	int	reliable;		/* true if reliable udp */
-
-	Conv*	incall;			/* calls waiting to be listened for */
-	Conv*	next;
-
-	Queue*	rq;			/* queued data waiting to be read */
-	Queue*	wq;			/* queued data waiting to be written */
-	Queue*	eq;			/* returned error packets */
-	Queue*	sq;			/* snooping queue */
-	Ref	snoopers;		/* number of processes with snoop open */
-
-	QLock	car;
-	Rendez	cr;
-	char	cerr[ERRMAX];
-
-	QLock	listenq;
-	Rendez	listenr;
-
-	Ipmulti	*multi;			/* multicast bindings for this interface */
-
-	void*	ptcl;			/* protocol specific stuff */
-
-	Route	*r;			/* last route used */
-	ulong	rgen;			/* routetable generation for *r */
-};
-
-struct Medium
-{
-	char	*name;
-	int	hsize;		/* medium header size */
-	int	mintu;		/* default min mtu */
-	int	maxtu;		/* default max mtu */
-	int	maclen;		/* mac address length  */
-	void	(*bind)(Ipifc*, int, char**);
-	void	(*unbind)(Ipifc*);
-	void	(*bwrite)(Ipifc *ifc, Block *b, int version, uchar *ip);
-
-	/* for arming interfaces to receive multicast */
-	void	(*addmulti)(Ipifc *ifc, uchar *a, uchar *ia);
-	void	(*remmulti)(Ipifc *ifc, uchar *a, uchar *ia);
-
-	/* process packets written to 'data' */
-	void	(*pktin)(Fs *f, Ipifc *ifc, Block *bp);
-
-	/* routes for router boards */
-	void	(*addroute)(Ipifc *ifc, int, uchar*, uchar*, uchar*, int);
-	void	(*remroute)(Ipifc *ifc, int, uchar*, uchar*);
-	void	(*flushroutes)(Ipifc *ifc);
-
-	/* for routing multicast groups */
-	void	(*joinmulti)(Ipifc *ifc, uchar *a, uchar *ia);
-	void	(*leavemulti)(Ipifc *ifc, uchar *a, uchar *ia);
-
-	/* address resolution */
-	void	(*ares)(Fs*, int, uchar*, uchar*, int, int);	/* resolve */
-	void	(*areg)(Ipifc*, uchar*);			/* register */
-
-	/* v6 address generation */
-	void	(*pref2addr)(uchar *pref, uchar *ea);
-
-	int	unbindonclose;	/* if non-zero, unbind on last close */
-};
-
-/* logical interface associated with a physical one */
-struct Iplifc
-{
-	uchar	local[IPaddrlen];
-	uchar	mask[IPaddrlen];
-	uchar	remote[IPaddrlen];
-	uchar	net[IPaddrlen];
-	uchar	tentative;	/* =1 => v6 dup disc on, =0 => confirmed unique */
-	uchar	onlink;		/* =1 => onlink, =0 offlink. */
-	uchar	autoflag;	/* v6 autonomous flag */
-	long 	validlt;	/* v6 valid lifetime */
-	long 	preflt;		/* v6 preferred lifetime */
-	long	origint;	/* time when addr was added */
-	Iplink	*link;		/* addresses linked to this lifc */
-	Iplifc	*next;
-};
-
-/* binding twixt Ipself and Iplifc */
-struct Iplink
-{
-	Ipself	*self;
-	Iplifc	*lifc;
-	Iplink	*selflink;	/* next link for this local address */
-	Iplink	*lifclink;	/* next link for this ifc */
-	ulong	expire;
-	Iplink	*next;		/* free list */
-	int	ref;
-};
-
-/* rfc 2461, pp.40—43. */
-
-/* default values, one per stack */
-struct Routerparams {
-	int	mflag;		/* flag: managed address configuration */
-	int	oflag;		/* flag: other stateful configuration */
-	int 	maxraint;	/* max. router adv interval (ms) */
-	int	minraint;	/* min. router adv interval (ms) */
-	int	linkmtu;	/* mtu options */
-	int	reachtime;	/* reachable time */
-	int	rxmitra;	/* retransmit interval */
-	int	ttl;		/* cur hop count limit */
-	int	routerlt;	/* router lifetime */
-};
-
-struct Hostparams {
-	int	rxmithost;
-};
-
-struct Ipifc
-{
-	RWlock;
-
-	Conv	*conv;		/* link to its conversation structure */
-	char	dev[64];	/* device we're attached to */
-	Medium	*m;		/* Media pointer */
-	int	maxtu;		/* Maximum transfer unit */
-	int	mintu;		/* Minumum tranfer unit */
-	int	mbps;		/* megabits per second */
-	void	*arg;		/* medium specific */
-	int	reassemble;	/* reassemble IP packets before forwarding */
-
-	/* these are used so that we can unbind on the fly */
-	Lock	idlock;
-	uchar	ifcid;		/* incremented each 'bind/unbind/add/remove' */
-	int	ref;		/* number of proc's using this ipifc */
-	Rendez	wait;		/* where unbinder waits for ref == 0 */
-	int	unbinding;
-
-	uchar	mac[MAClen];	/* MAC address */
-
-	Iplifc	*lifc;		/* logical interfaces on this physical one */
-
-	ulong	in, out;	/* message statistics */
-	ulong	inerr, outerr;	/* ... */
-
-	uchar	sendra6;	/* flag: send router advs on this ifc */
-	uchar	recvra6;	/* flag: recv router advs on this ifc */
-	Routerparams rp;	/* router parameters as in RFC 2461, pp.40—43.
-					used only if node is router */
-};
-
-/*
- *  one per multicast-lifc pair used by a Conv
- */
-struct Ipmulti
-{
-	uchar	ma[IPaddrlen];
-	uchar	ia[IPaddrlen];
-	Ipmulti	*next;
-};
-
-/*
- *  hash table for 2 ip addresses + 2 ports
- */
-enum
-{
-	Nipht=		521,	/* convenient prime */
-
-	IPmatchexact=	0,	/* match on 4 tuple */
-	IPmatchany,		/* *!* */
-	IPmatchport,		/* *!port */
-	IPmatchaddr,		/* addr!* */
-	IPmatchpa,		/* addr!port */
-};
-struct Iphash
-{
-	Iphash	*next;
-	Conv	*c;
-	int	match;
-};
-struct Ipht
-{
-	Lock;
-	Iphash	*tab[Nipht];
-};
-void iphtadd(Ipht*, Conv*);
-void iphtrem(Ipht*, Conv*);
-Conv* iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp);
-
-/*
- *  one per multiplexed protocol
- */
-struct Proto
-{
-	QLock;
-	char*		name;		/* protocol name */
-	int		x;		/* protocol index */
-	int		ipproto;	/* ip protocol type */
-
-	char*		(*connect)(Conv*, char**, int);
-	char*		(*announce)(Conv*, char**, int);
-	char*		(*bind)(Conv*, char**, int);
-	int		(*state)(Conv*, char*, int);
-	void		(*create)(Conv*);
-	void		(*close)(Conv*);
-	void		(*rcv)(Proto*, Ipifc*, Block*);
-	char*		(*ctl)(Conv*, char**, int);
-	void		(*advise)(Proto*, Block*, char*);
-	int		(*stats)(Proto*, char*, int);
-	int		(*local)(Conv*, char*, int);
-	int		(*remote)(Conv*, char*, int);
-	int		(*inuse)(Conv*);
-	int		(*gc)(Proto*);	/* returns true if any conversations are freed */
-
-	Fs		*f;		/* file system this proto is part of */
-	Conv		**conv;		/* array of conversations */
-	int		ptclsize;	/* size of per protocol ctl block */
-	int		nc;		/* number of conversations */
-	int		ac;
-	Qid		qid;		/* qid for protocol directory */
-	ushort		nextrport;
-
-	void		*priv;
-};
-
-
-/*
- *  one per IP protocol stack
- */
-struct Fs
-{
-	RWlock;
-	int	dev;
-
-	int	np;
-	Proto*	p[Maxproto+1];		/* list of supported protocols */
-	Proto*	t2p[256];		/* vector of all protocols */
-	Proto*	ipifc;			/* kludge for ipifcremroute & ipifcaddroute */
-	Proto*	ipmux;			/* kludge for finding an ip multiplexor */
-
-	IP	*ip;
-	Ipselftab	*self;
-	Arp	*arp;
-	v6params	*v6p;
-
-	Route	*v4root[1<<Lroot];	/* v4 routing forest */
-	Route	*v6root[1<<Lroot];	/* v6 routing forest */
-	Route	*queue;			/* used as temp when reinjecting routes */
-
-	Netlog	*alog;
-
-	char	ndb[1024];		/* an ndb entry for this interface */
-	int	ndbvers;
-	long	ndbmtime;
-};
-
-/* one per default router known to host */
-struct v6router {
-	uchar	inuse;
-	Ipifc	*ifc;
-	int	ifcid;
-	uchar	routeraddr[IPaddrlen];
-	long	ltorigin;
-	Routerparams	rp;
-};
-
-struct v6params
-{
-	Routerparams	rp;		/* v6 params, one copy per node now */
-	Hostparams	hp;
-	v6router	v6rlist[3];	/* max 3 default routers, currently */
-	int		cdrouter;	/* uses only v6rlist[cdrouter] if   */
-					/* cdrouter >= 0. */
-};
-
-
-int	Fsconnected(Conv*, char*);
-Conv*	Fsnewcall(Conv*, uchar*, ushort, uchar*, ushort, uchar);
-int	Fspcolstats(char*, int);
-int	Fsproto(Fs*, Proto*);
-int	Fsbuiltinproto(Fs*, uchar);
-Conv*	Fsprotoclone(Proto*, char*);
-Proto*	Fsrcvpcol(Fs*, uchar);
-Proto*	Fsrcvpcolx(Fs*, uchar);
-char*	Fsstdconnect(Conv*, char**, int);
-char*	Fsstdannounce(Conv*, char**, int);
-char*	Fsstdbind(Conv*, char**, int);
-ulong	scalednconv(void);
-void	closeconv(Conv*);
-/*
- *  logging
- */
-enum
-{
-	Logip=		1<<1,
-	Logtcp=		1<<2,
-	Logfs=		1<<3,
-	Logicmp=	1<<5,
-	Logudp=		1<<6,
-	Logcompress=	1<<7,
-	Loggre=		1<<9,
-	Logppp=		1<<10,
-	Logtcprxmt=	1<<11,
-	Logigmp=	1<<12,
-	Logudpmsg=	1<<13,
-	Logipmsg=	1<<14,
-	Logrudp=	1<<15,
-	Logrudpmsg=	1<<16,
-	Logesp=		1<<17,
-	Logtcpwin=	1<<18,
-};
-
-void	netloginit(Fs*);
-void	netlogopen(Fs*);
-void	netlogclose(Fs*);
-void	netlogctl(Fs*, char*, int);
-long	netlogread(Fs*, void*, ulong, long);
-void	netlog(Fs*, int, char*, ...);
-void	ifcloginit(Fs*);
-long	ifclogread(Fs*, Chan *,void*, ulong, long);
-void	ifclog(Fs*, uchar *, int);
-void	ifclogopen(Fs*, Chan*);
-void	ifclogclose(Fs*, Chan*);
-
-#pragma varargck argpos netlog	3
-
-/*
- *  iproute.c
- */
-typedef	struct RouteTree RouteTree;
-typedef struct Routewalk Routewalk;
-typedef struct V4route V4route;
-typedef struct V6route V6route;
-
-enum
-{
-
-	/* type bits */
-	Rv4=		(1<<0),		/* this is a version 4 route */
-	Rifc=		(1<<1),		/* this route is a directly connected interface */
-	Rptpt=		(1<<2),		/* this route is a pt to pt interface */
-	Runi=		(1<<3),		/* a unicast self address */
-	Rbcast=		(1<<4),		/* a broadcast self address */
-	Rmulti=		(1<<5),		/* a multicast self address */
-	Rproxy=		(1<<6),		/* this route should be proxied */
-};
-
-struct Routewalk
-{
-	int	o;
-	int	h;
-	char*	p;
-	char*	e;
-	void*	state;
-	void	(*walk)(Route*, Routewalk*);
-};
-
-struct	RouteTree
-{
-	Route*	right;
-	Route*	left;
-	Route*	mid;
-	uchar	depth;
-	uchar	type;
-	uchar	ifcid;		/* must match ifc->id */
-	Ipifc	*ifc;
-	char	tag[4];
-	int	ref;
-};
-
-struct V4route
-{
-	ulong	address;
-	ulong	endaddress;
-	uchar	gate[IPv4addrlen];
-};
-
-struct V6route
-{
-	ulong	address[IPllen];
-	ulong	endaddress[IPllen];
-	uchar	gate[IPaddrlen];
-};
-
-struct Route
-{
-	RouteTree;
-
-	union {
-		V6route	v6;
-		V4route v4;
-	};
-};
-extern void	v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
-extern void	v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type);
-extern void	v4delroute(Fs *f, uchar *a, uchar *mask, int dolock);
-extern void	v6delroute(Fs *f, uchar *a, uchar *mask, int dolock);
-extern Route*	v4lookup(Fs *f, uchar *a, Conv *c);
-extern Route*	v6lookup(Fs *f, uchar *a, Conv *c);
-extern long	routeread(Fs *f, char*, ulong, int);
-extern long	routewrite(Fs *f, Chan*, char*, int);
-extern void	routetype(int, char*);
-extern void	ipwalkroutes(Fs*, Routewalk*);
-extern void	convroute(Route*, uchar*, uchar*, uchar*, char*, int*);
-
-/*
- *  devip.c
- */
-
-/*
- *  Hanging off every ip channel's ->aux is the following structure.
- *  It maintains the state used by devip and iproute.
- */
-struct IPaux
-{
-	char	*owner;		/* the user that did the attach */
-	char	tag[4];
-};
-
-extern IPaux*	newipaux(char*, char*);
-
-/*
- *  arp.c
- */
-struct Arpent
-{
-	uchar	ip[IPaddrlen];
-	uchar	mac[MAClen];
-	Medium	*type;			/* media type */
-	Arpent*	hash;
-	Block*	hold;
-	Block*	last;
-	uint	ctime;			/* time entry was created or refreshed */
-	uint	utime;			/* time entry was last used */
-	uchar	state;
-	Arpent	*nextrxt;		/* re-transmit chain */
-	uint	rtime;			/* time for next retransmission */
-	uchar	rxtsrem;
-	Ipifc	*ifc;
-	uchar	ifcid;			/* must match ifc->id */
-};
-
-extern void	arpinit(Fs*);
-extern int	arpread(Arp*, char*, ulong, int);
-extern int	arpwrite(Fs*, char*, int);
-extern Arpent*	arpget(Arp*, Block *bp, int version, Ipifc *ifc, uchar *ip, uchar *h);
-extern void	arprelease(Arp*, Arpent *a);
-extern Block*	arpresolve(Arp*, Arpent *a, Medium *type, uchar *mac);
-extern void	arpenter(Fs*, int version, uchar *ip, uchar *mac, int len, int norefresh);
-
-/*
- * ipaux.c
- */
-
-extern int	myetheraddr(uchar*, char*);
-extern vlong	parseip(uchar*, char*);
-extern vlong	parseipmask(uchar*, char*);
-extern char*	v4parseip(uchar*, char*);
-extern void	maskip(uchar *from, uchar *mask, uchar *to);
-extern int	parsemac(uchar *to, char *from, int len);
-extern uchar*	defmask(uchar*);
-extern int	isv4(uchar*);
-extern void	v4tov6(uchar *v6, uchar *v4);
-extern int	v6tov4(uchar *v4, uchar *v6);
-extern int	eipfmt(Fmt*);
-
-#define	ipmove(x, y) memmove(x, y, IPaddrlen)
-#define	ipcmp(x, y) ( (x)[IPaddrlen-1] != (y)[IPaddrlen-1] || memcmp(x, y, IPaddrlen) )
-
-extern uchar IPv4bcast[IPaddrlen];
-extern uchar IPv4bcastobs[IPaddrlen];
-extern uchar IPv4allsys[IPaddrlen];
-extern uchar IPv4allrouter[IPaddrlen];
-extern uchar IPnoaddr[IPaddrlen];
-extern uchar v4prefix[IPaddrlen];
-extern uchar IPallbits[IPaddrlen];
-
-#define	NOW	TK2MS(MACHP(0)->ticks)
-
-/*
- *  media
- */
-extern Medium	ethermedium;
-extern Medium	nullmedium;
-extern Medium	pktmedium;
-
-/*
- *  ipifc.c
- */
-extern Medium*	ipfindmedium(char *name);
-extern void	addipmedium(Medium *med);
-extern int	ipforme(Fs*, uchar *addr);
-extern int	iptentative(Fs*, uchar *addr);
-extern int	ipisbm(uchar *);
-extern int	ipismulticast(uchar *);
-extern Ipifc*	findipifc(Fs*, uchar *remote, int type);
-extern void	findlocalip(Fs*, uchar *local, uchar *remote);
-extern int	ipv4local(Ipifc *ifc, uchar *addr);
-extern int	ipv6local(Ipifc *ifc, uchar *addr);
-extern int	ipv6anylocal(Ipifc *ifc, uchar *addr);
-extern Iplifc*	iplocalonifc(Ipifc *ifc, uchar *ip);
-extern int	ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip);
-extern int	ipismulticast(uchar *ip);
-extern int	ipisbooting(void);
-extern int	ipifccheckin(Ipifc *ifc, Medium *med);
-extern void	ipifccheckout(Ipifc *ifc);
-extern int	ipifcgrab(Ipifc *ifc);
-extern void	ipifcaddroute(Fs*, int, uchar*, uchar*, uchar*, int);
-extern void	ipifcremroute(Fs*, int, uchar*, uchar*);
-extern void	ipifcremmulti(Conv *c, uchar *ma, uchar *ia);
-extern void	ipifcaddmulti(Conv *c, uchar *ma, uchar *ia);
-extern char*	ipifcrem(Ipifc *ifc, char **argv, int argc);
-extern char*	ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp);
-extern long	ipselftabread(Fs*, char *a, ulong offset, int n);
-extern char*	ipifcadd6(Ipifc *ifc, char**argv, int argc);
-/*
- *  ip.c
- */
-extern void	iprouting(Fs*, int);
-extern void	icmpnoconv(Fs*, Block*);
-extern void	icmpcantfrag(Fs*, Block*, int);
-extern void	icmpttlexceeded(Fs*, uchar*, Block*);
-extern ushort	ipcsum(uchar*);
-extern void	ipiput4(Fs*, Ipifc*, Block*);
-extern void	ipiput6(Fs*, Ipifc*, Block*);
-extern int	ipoput4(Fs*, Block*, int, int, int, Conv*);
-extern int	ipoput6(Fs*, Block*, int, int, int, Conv*);
-extern int	ipstats(Fs*, char*, int);
-extern ushort	ptclbsum(uchar*, int);
-extern ushort	ptclcsum(Block*, int, int);
-extern void	ip_init(Fs*);
-extern void	update_mtucache(uchar*, ulong);
-extern ulong	restrict_mtu(uchar*, ulong);
-/*
- * bootp.c
- */
-extern int	bootpread(char*, ulong, int);
-
-/*
- *  resolving inferno/plan9 differences
- */
-char*		commonuser(void);
-char*		commonerror(void);
-
-/*
- * chandial.c
- */
-extern Chan*	chandial(char*, char*, char*, Chan**);
-
-/*
- *  global to all of the stack
- */
-extern void	(*igmpreportfn)(Ipifc*, uchar*);

+ 0 - 377
sys/src/9/ip/ipaux.c

@@ -1,377 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"ip.h"
-#include	"ipv6.h"
-
-char *v6hdrtypes[Maxhdrtype] =
-{
-	[HBH]		"HopbyHop",
-	[ICMP]		"ICMP",
-	[IGMP]		"IGMP",
-	[GGP]		"GGP",
-	[IPINIP]	"IP",
-	[ST]		"ST",
-	[TCP]		"TCP",
-	[UDP]		"UDP",
-	[ISO_TP4]	"ISO_TP4",
-	[RH]		"Routinghdr",
-	[FH]		"Fraghdr",
-	[IDRP]		"IDRP",
-	[RSVP]		"RSVP",
-	[AH]		"Authhdr",
-	[ESP]		"ESP",
-	[ICMPv6]	"ICMPv6",
-	[NNH]		"Nonexthdr",
-	[ISO_IP]	"ISO_IP",
-	[IGRP]		"IGRP",
-	[OSPF]		"OSPF",
-};
-
-/*
- *  well known IPv6 addresses
- */
-uchar v6Unspecified[IPaddrlen] = {
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-uchar v6loopback[IPaddrlen] = {
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x01
-};
-
-uchar v6linklocal[IPaddrlen] = {
-	0xfe, 0x80, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-uchar v6linklocalmask[IPaddrlen] = {
-	0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-int v6llpreflen = 8;	/* link-local prefix length in bytes */
-
-uchar v6multicast[IPaddrlen] = {
-	0xff, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-uchar v6multicastmask[IPaddrlen] = {
-	0xff, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-int v6mcpreflen = 1;	/* multicast prefix length */
-
-uchar v6allnodesN[IPaddrlen] = {
-	0xff, 0x01, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x01
-};
-uchar v6allroutersN[IPaddrlen] = {
-	0xff, 0x01, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x02
-};
-uchar v6allnodesNmask[IPaddrlen] = {
-	0xff, 0xff, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-int v6aNpreflen = 2;	/* all nodes (N) prefix */
-
-uchar v6allnodesL[IPaddrlen] = {
-	0xff, 0x02, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x01
-};
-uchar v6allroutersL[IPaddrlen] = {
-	0xff, 0x02, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x02
-};
-uchar v6allnodesLmask[IPaddrlen] = {
-	0xff, 0xff, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0
-};
-int v6aLpreflen = 2;	/* all nodes (L) prefix */
-
-uchar v6solicitednode[IPaddrlen] = {
-	0xff, 0x02, 0, 0,
-	0, 0, 0, 0,
-	0, 0, 0, 0x01,
-	0xff, 0, 0, 0
-};
-uchar v6solicitednodemask[IPaddrlen] = {
-	0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff,
-	0xff, 0xff, 0xff, 0xff,
-	0xff, 0x0, 0x0, 0x0
-};
-int v6snpreflen = 13;
-
-ushort
-ptclcsum(Block *bp, int offset, int len)
-{
-	uchar *addr;
-	ulong losum, hisum;
-	ushort csum;
-	int odd, blocklen, x;
-
-	/* Correct to front of data area */
-	while(bp != nil && offset && offset >= BLEN(bp)) {
-		offset -= BLEN(bp);
-		bp = bp->next;
-	}
-	if(bp == nil)
-		return 0;
-
-	addr = bp->rp + offset;
-	blocklen = BLEN(bp) - offset;
-
-	if(bp->next == nil) {
-		if(blocklen < len)
-			len = blocklen;
-		return ~ptclbsum(addr, len) & 0xffff;
-	}
-
-	losum = 0;
-	hisum = 0;
-
-	odd = 0;
-	while(len) {
-		x = blocklen;
-		if(len < x)
-			x = len;
-
-		csum = ptclbsum(addr, x);
-		if(odd)
-			hisum += csum;
-		else
-			losum += csum;
-		odd = (odd+x) & 1;
-		len -= x;
-
-		bp = bp->next;
-		if(bp == nil)
-			break;
-		blocklen = BLEN(bp);
-		addr = bp->rp;
-	}
-
-	losum += hisum>>8;
-	losum += (hisum&0xff)<<8;
-	while((csum = losum>>16) != 0)
-		losum = csum + (losum & 0xffff);
-
-	return ~losum & 0xffff;
-}
-
-enum
-{
-	Isprefix= 16,
-};
-
-#define CLASS(p) ((*(uchar*)(p))>>6)
-
-void
-ipv62smcast(uchar *smcast, uchar *a)
-{
-	assert(IPaddrlen == 16);
-	memmove(smcast, v6solicitednode, IPaddrlen);
-	smcast[13] = a[13];
-	smcast[14] = a[14];
-	smcast[15] = a[15];
-}
-
-
-/*
- *  parse a hex mac address
- */
-int
-parsemac(uchar *to, char *from, int len)
-{
-	char nip[4];
-	char *p;
-	int i;
-
-	p = from;
-	memset(to, 0, len);
-	for(i = 0; i < len; i++){
-		if(p[0] == '\0' || p[1] == '\0')
-			break;
-
-		nip[0] = p[0];
-		nip[1] = p[1];
-		nip[2] = '\0';
-		p += 2;
-
-		to[i] = strtoul(nip, 0, 16);
-		if(*p == ':')
-			p++;
-	}
-	return i;
-}
-
-/*
- *  hashing tcp, udp, ... connections
- */
-ulong
-iphash(uchar *sa, ushort sp, uchar *da, ushort dp)
-{
-	return ((sa[IPaddrlen-1]<<24) ^ (sp << 16) ^ (da[IPaddrlen-1]<<8) ^ dp ) % Nhash;
-}
-
-void
-iphtadd(Ipht *ht, Conv *c)
-{
-	ulong hv;
-	Iphash *h;
-
-	hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
-	h = smalloc(sizeof(*h));
-	if(ipcmp(c->raddr, IPnoaddr) != 0)
-		h->match = IPmatchexact;
-	else {
-		if(ipcmp(c->laddr, IPnoaddr) != 0){
-			if(c->lport == 0)
-				h->match = IPmatchaddr;
-			else
-				h->match = IPmatchpa;
-		} else {
-			if(c->lport == 0)
-				h->match = IPmatchany;
-			else
-				h->match = IPmatchport;
-		}
-	}
-	h->c = c;
-
-	lock(ht);
-	h->next = ht->tab[hv];
-	ht->tab[hv] = h;
-	unlock(ht);
-}
-
-void
-iphtrem(Ipht *ht, Conv *c)
-{
-	ulong hv;
-	Iphash **l, *h;
-
-	hv = iphash(c->raddr, c->rport, c->laddr, c->lport);
-	lock(ht);
-	for(l = &ht->tab[hv]; (*l) != nil; l = &(*l)->next)
-		if((*l)->c == c){
-			h = *l;
-			(*l) = h->next;
-			free(h);
-			break;
-		}
-	unlock(ht);
-}
-
-/* look for a matching conversation with the following precedence
- *	connected && raddr,rport,laddr,lport
- *	announced && laddr,lport
- *	announced && *,lport
- *	announced && laddr,*
- *	announced && *,*
- */
-Conv*
-iphtlook(Ipht *ht, uchar *sa, ushort sp, uchar *da, ushort dp)
-{
-	ulong hv;
-	Iphash *h;
-	Conv *c;
-
-	/* exact 4 pair match (connection) */
-	hv = iphash(sa, sp, da, dp);
-	lock(ht);
-	for(h = ht->tab[hv]; h != nil; h = h->next){
-		if(h->match != IPmatchexact)
-			continue;
-		c = h->c;
-		if(sp == c->rport && dp == c->lport
-		&& ipcmp(sa, c->raddr) == 0 && ipcmp(da, c->laddr) == 0){
-			unlock(ht);
-			return c;
-		}
-	}
-
-	/* match local address and port */
-	hv = iphash(IPnoaddr, 0, da, dp);
-	for(h = ht->tab[hv]; h != nil; h = h->next){
-		if(h->match != IPmatchpa)
-			continue;
-		c = h->c;
-		if(dp == c->lport && ipcmp(da, c->laddr) == 0){
-			unlock(ht);
-			return c;
-		}
-	}
-
-	/* match just port */
-	hv = iphash(IPnoaddr, 0, IPnoaddr, dp);
-	for(h = ht->tab[hv]; h != nil; h = h->next){
-		if(h->match != IPmatchport)
-			continue;
-		c = h->c;
-		if(dp == c->lport){
-			unlock(ht);
-			return c;
-		}
-	}
-
-	/* match local address */
-	hv = iphash(IPnoaddr, 0, da, 0);
-	for(h = ht->tab[hv]; h != nil; h = h->next){
-		if(h->match != IPmatchaddr)
-			continue;
-		c = h->c;
-		if(ipcmp(da, c->laddr) == 0){
-			unlock(ht);
-			return c;
-		}
-	}
-
-	/* look for something that matches anything */
-	hv = iphash(IPnoaddr, 0, IPnoaddr, 0);
-	for(h = ht->tab[hv]; h != nil; h = h->next){
-		if(h->match != IPmatchany)
-			continue;
-		c = h->c;
-		unlock(ht);
-		return c;
-	}
-	unlock(ht);
-	return nil;
-}

+ 0 - 1678
sys/src/9/ip/ipifc.c

@@ -1,1678 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-#include "ipv6.h"
-
-#define DPRINT if(0)print
-
-enum {
-	Maxmedia	= 32,
-	Nself		= Maxmedia*5,
-	NHASH		= 1<<6,
-	NCACHE		= 256,
-	QMAX		= 192*1024-1,
-	Maxv6repr	= (128/(4*4))*(4+1), /* limit of xxxx:xxxx:⋯ notation */
-};
-
-Medium *media[Maxmedia] = { 0 };
-
-/*
- *  cache of local addresses (addresses we answer to)
- */
-struct Ipself
-{
-	uchar	a[IPaddrlen];
-	Ipself	*hnext;		/* next address in the hash table */
-	Iplink	*link;		/* binding twixt Ipself and Ipifc */
-	ulong	expire;
-	uchar	type;		/* type of address */
-	int	ref;
-	Ipself	*next;		/* free list */
-};
-
-struct Ipselftab
-{
-	QLock;
-	int	inited;
-	int	acceptall;	/* true if an interface has the null address */
-	Ipself	*hash[NHASH];	/* hash chains */
-};
-
-/*
- *  Multicast addresses are chained onto a Chan so that
- *  we can remove them when the Chan is closed.
- */
-typedef struct Ipmcast Ipmcast;
-struct Ipmcast
-{
-	Ipmcast	*next;
-	uchar	ma[IPaddrlen];	/* multicast address */
-	uchar	ia[IPaddrlen];	/* interface address */
-};
-
-/* quick hash for ip addresses */
-#define hashipa(a) ( ( ((a)[IPaddrlen-2]<<8) | (a)[IPaddrlen-1] )%NHASH )
-
-static char tifc[] = "ifc ";
-
-static void	addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type);
-static void	remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a);
-static char*	ipifcjoinmulti(Ipifc *ifc, char **argv, int argc);
-static char*	ipifcleavemulti(Ipifc *ifc, char **argv, int argc);
-static void	ipifcregisterproxy(Fs*, Ipifc*, uchar*);
-static char*	ipifcremlifc(Ipifc*, Iplifc*);
-
-/*
- *  link in a new medium
- */
-void
-addipmedium(Medium *med)
-{
-	int i;
-
-	for(i = 0; i < nelem(media)-1; i++)
-		if(media[i] == nil){
-			media[i] = med;
-			break;
-		}
-}
-
-/*
- *  find the medium with this name
- */
-Medium*
-ipfindmedium(char *name)
-{
-	Medium **mp;
-
-	for(mp = media; *mp != nil; mp++)
-		if(strcmp((*mp)->name, name) == 0)
-			break;
-	return *mp;
-}
-
-/*
- *  attach a device (or pkt driver) to the interface.
- *  called with c locked
- */
-static char*
-ipifcbind(Conv *c, char **argv, int argc)
-{
-	Ipifc *ifc;
-	Medium *m;
-
-	if(argc < 2)
-		return Ebadarg;
-
-	ifc = (Ipifc*)c->ptcl;
-
-	/* bind the device to the interface */
-	m = ipfindmedium(argv[1]);
-	if(m == nil)
-		return "unknown interface type";
-
-	wlock(ifc);
-	if(ifc->m != nil){
-		wunlock(ifc);
-		return "interface already bound";
-	}
-	if(waserror()){
-		wunlock(ifc);
-		nexterror();
-	}
-
-	/* do medium specific binding */
-	(*m->bind)(ifc, argc, argv);
-
-	/* set the bound device name */
-	if(argc > 2)
-		strncpy(ifc->dev, argv[2], sizeof(ifc->dev));
-	else
-		snprint(ifc->dev, sizeof ifc->dev, "%s%d", m->name, c->x);
-	ifc->dev[sizeof(ifc->dev)-1] = 0;
-
-	/* set up parameters */
-	ifc->m = m;
-	ifc->mintu = ifc->m->mintu;
-	ifc->maxtu = ifc->m->maxtu;
-	if(ifc->m->unbindonclose == 0)
-		ifc->conv->inuse++;
-	ifc->rp.mflag = 0;		/* default not managed */
-	ifc->rp.oflag = 0;
-	ifc->rp.maxraint = 600000;	/* millisecs */
-	ifc->rp.minraint = 200000;
-	ifc->rp.linkmtu = 0;		/* no mtu sent */
-	ifc->rp.reachtime = 0;
-	ifc->rp.rxmitra = 0;
-	ifc->rp.ttl = MAXTTL;
-	ifc->rp.routerlt = 3 * ifc->rp.maxraint;
-
-	/* any ancillary structures (like routes) no longer pertain */
-	ifc->ifcid++;
-
-	/* reopen all the queues closed by a previous unbind */
-	qreopen(c->rq);
-	qreopen(c->eq);
-	qreopen(c->sq);
-
-	wunlock(ifc);
-	poperror();
-
-	return nil;
-}
-
-/*
- *  detach a device from an interface, close the interface
- *  called with ifc->conv closed
- */
-static char*
-ipifcunbind(Ipifc *ifc)
-{
-	char *err;
-
-	if(waserror()){
-		wunlock(ifc);
-		nexterror();
-	}
-	wlock(ifc);
-
-	/* dissociate routes */
-	if(ifc->m != nil && ifc->m->unbindonclose == 0)
-		ifc->conv->inuse--;
-	ifc->ifcid++;
-
-	/* disassociate logical interfaces (before zeroing ifc->arg) */
-	while(ifc->lifc){
-		err = ipifcremlifc(ifc, ifc->lifc);
-		/*
-		 * note: err non-zero means lifc not found,
-		 * which can't happen in this case.
-		 */
-		if(err)
-			error(err);
-	}
-
-	/* disassociate device */
-	if(ifc->m && ifc->m->unbind)
-		(*ifc->m->unbind)(ifc);
-	memset(ifc->dev, 0, sizeof(ifc->dev));
-	ifc->arg = nil;
-	ifc->reassemble = 0;
-
-	/* close queues to stop queuing of packets */
-	qclose(ifc->conv->rq);
-	qclose(ifc->conv->wq);
-	qclose(ifc->conv->sq);
-
-	ifc->m = nil;
-	wunlock(ifc);
-	poperror();
-	return nil;
-}
-
-char sfixedformat[] = "device %s maxtu %d sendra %d recvra %d mflag %d oflag"
-" %d maxraint %d minraint %d linkmtu %d reachtime %d rxmitra %d ttl %d routerlt"
-" %d pktin %lud pktout %lud errin %lud errout %lud\n";
-
-char slineformat[] = "	%-40I %-10M %-40I %-12lud %-12lud\n";
-
-static int
-ipifcstate(Conv *c, char *state, int n)
-{
-	Ipifc *ifc;
-	Iplifc *lifc;
-	int m;
-
-	ifc = (Ipifc*)c->ptcl;
-	m = snprint(state, n, sfixedformat,
-		ifc->dev, ifc->maxtu, ifc->sendra6, ifc->recvra6,
-		ifc->rp.mflag, ifc->rp.oflag, ifc->rp.maxraint,
-		ifc->rp.minraint, ifc->rp.linkmtu, ifc->rp.reachtime,
-		ifc->rp.rxmitra, ifc->rp.ttl, ifc->rp.routerlt,
-		ifc->in, ifc->out, ifc->inerr, ifc->outerr);
-
-	rlock(ifc);
-	for(lifc = ifc->lifc; lifc && n > m; lifc = lifc->next)
-		m += snprint(state+m, n - m, slineformat, lifc->local,
-			lifc->mask, lifc->remote, lifc->validlt, lifc->preflt);
-	if(ifc->lifc == nil)
-		m += snprint(state+m, n - m, "\n");
-	runlock(ifc);
-	return m;
-}
-
-static int
-ipifclocal(Conv *c, char *state, int n)
-{
-	Ipifc *ifc;
-	Iplifc *lifc;
-	Iplink *link;
-	int m;
-
-	ifc = (Ipifc*)c->ptcl;
-	m = 0;
-
-	rlock(ifc);
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		m += snprint(state+m, n - m, "%-40.40I ->", lifc->local);
-		for(link = lifc->link; link; link = link->lifclink)
-			m += snprint(state+m, n - m, " %-40.40I", link->self->a);
-		m += snprint(state+m, n - m, "\n");
-	}
-	runlock(ifc);
-	return m;
-}
-
-static int
-ipifcinuse(Conv *c)
-{
-	Ipifc *ifc;
-
-	ifc = (Ipifc*)c->ptcl;
-	return ifc->m != nil;
-}
-
-/*
- *  called when a process writes to an interface's 'data'
- */
-static void
-ipifckick(void *x)
-{
-	Conv *c = x;
-	Block *bp;
-	Ipifc *ifc;
-
-	bp = qget(c->wq);
-	if(bp == nil)
-		return;
-
-	ifc = (Ipifc*)c->ptcl;
-	if(!canrlock(ifc)){
-		freeb(bp);
-		return;
-	}
-	if(waserror()){
-		runlock(ifc);
-		nexterror();
-	}
-	if(ifc->m == nil || ifc->m->pktin == nil)
-		freeb(bp);
-	else
-		(*ifc->m->pktin)(c->p->f, ifc, bp);
-	runlock(ifc);
-	poperror();
-}
-
-/*
- *  called when a new ipifc structure is created
- */
-static void
-ipifccreate(Conv *c)
-{
-	Ipifc *ifc;
-
-	c->rq = qopen(QMAX, 0, 0, 0);
-	c->sq = qopen(QMAX, 0, 0, 0);
-	c->wq = qopen(QMAX, Qkick, ipifckick, c);
-	ifc = (Ipifc*)c->ptcl;
-	ifc->conv = c;
-	ifc->unbinding = 0;
-	ifc->m = nil;
-	ifc->reassemble = 0;
-}
-
-/*
- *  called after last close of ipifc data or ctl
- *  called with c locked, we must unlock
- */
-static void
-ipifcclose(Conv *c)
-{
-	Ipifc *ifc;
-	Medium *m;
-
-	ifc = (Ipifc*)c->ptcl;
-	m = ifc->m;
-	if(m && m->unbindonclose)
-		ipifcunbind(ifc);
-}
-
-/*
- *  change an interface's mtu
- */
-char*
-ipifcsetmtu(Ipifc *ifc, char **argv, int argc)
-{
-	int mtu;
-
-	if(argc < 2 || ifc->m == nil)
-		return Ebadarg;
-	mtu = strtoul(argv[1], 0, 0);
-	if(mtu < ifc->m->mintu || mtu > ifc->m->maxtu)
-		return Ebadarg;
-	ifc->maxtu = mtu;
-	return nil;
-}
-
-/*
- *  add an address to an interface.
- */
-char*
-ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp)
-{
-	int i, type, mtu, sendnbrdisc = 0;
-	uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
-	uchar bcast[IPaddrlen], net[IPaddrlen];
-	Iplifc *lifc, **l;
-	Fs *f;
-
-	if(ifc->m == nil)
-		return "ipifc not yet bound to device";
-
-	f = ifc->conv->p->f;
-
-	type = Rifc;
-	memset(ip, 0, IPaddrlen);
-	memset(mask, 0, IPaddrlen);
-	memset(rem, 0, IPaddrlen);
-	switch(argc){
-	case 6:
-		if(strcmp(argv[5], "proxy") == 0)
-			type |= Rproxy;
-		/* fall through */
-	case 5:
-		mtu = strtoul(argv[4], 0, 0);
-		if(mtu >= ifc->m->mintu && mtu <= ifc->m->maxtu)
-			ifc->maxtu = mtu;
-		/* fall through */
-	case 4:
-		if (parseip(ip, argv[1]) == -1 || parseip(rem, argv[3]) == -1)
-			return Ebadip;
-		parseipmask(mask, argv[2]);
-		maskip(rem, mask, net);
-		break;
-	case 3:
-		if (parseip(ip, argv[1]) == -1)
-			return Ebadip;
-		parseipmask(mask, argv[2]);
-		maskip(ip, mask, rem);
-		maskip(rem, mask, net);
-		break;
-	case 2:
-		if (parseip(ip, argv[1]) == -1)
-			return Ebadip;
-		memmove(mask, defmask(ip), IPaddrlen);
-		maskip(ip, mask, rem);
-		maskip(rem, mask, net);
-		break;
-	default:
-		return Ebadarg;
-	}
-	if(isv4(ip))
-		tentative = 0;
-	wlock(ifc);
-
-	/* ignore if this is already a local address for this ifc */
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next) {
-		if(ipcmp(lifc->local, ip) == 0) {
-			if(lifc->tentative != tentative)
-				lifc->tentative = tentative;
-			if(lifcp) {
-				lifc->onlink = lifcp->onlink;
-				lifc->autoflag = lifcp->autoflag;
-				lifc->validlt = lifcp->validlt;
-				lifc->preflt = lifcp->preflt;
-				lifc->origint = lifcp->origint;
-			}
-			goto out;
-		}
-	}
-
-	/* add the address to the list of logical ifc's for this ifc */
-	lifc = smalloc(sizeof(Iplifc));
-	ipmove(lifc->local, ip);
-	ipmove(lifc->mask, mask);
-	ipmove(lifc->remote, rem);
-	ipmove(lifc->net, net);
-	lifc->tentative = tentative;
-	if(lifcp) {
-		lifc->onlink = lifcp->onlink;
-		lifc->autoflag = lifcp->autoflag;
-		lifc->validlt = lifcp->validlt;
-		lifc->preflt = lifcp->preflt;
-		lifc->origint = lifcp->origint;
-	} else {		/* default values */
-		lifc->onlink = lifc->autoflag = 1;
-		lifc->validlt = lifc->preflt = ~0L;
-		lifc->origint = NOW / 1000;
-	}
-	lifc->next = nil;
-
-	for(l = &ifc->lifc; *l; l = &(*l)->next)
-		;
-	*l = lifc;
-
-	/* check for point-to-point interface */
-	if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */
-	if(ipcmp(mask, IPallbits) == 0)
-		type |= Rptpt;
-
-	/* add local routes */
-	if(isv4(ip))
-		v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type);
-	else
-		v6addroute(f, tifc, rem, mask, rem, type);
-
-	addselfcache(f, ifc, lifc, ip, Runi);
-
-	if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){
-		ipifcregisterproxy(f, ifc, rem);
-		goto out;
-	}
-
-	if(isv4(ip) || ipcmp(ip, IPnoaddr) == 0) {
-		/* add subnet directed broadcast address to the self cache */
-		for(i = 0; i < IPaddrlen; i++)
-			bcast[i] = (ip[i] & mask[i]) | ~mask[i];
-		addselfcache(f, ifc, lifc, bcast, Rbcast);
-
-		/* add subnet directed network address to the self cache */
-		for(i = 0; i < IPaddrlen; i++)
-			bcast[i] = (ip[i] & mask[i]) & mask[i];
-		addselfcache(f, ifc, lifc, bcast, Rbcast);
-
-		/* add network directed broadcast address to the self cache */
-		memmove(mask, defmask(ip), IPaddrlen);
-		for(i = 0; i < IPaddrlen; i++)
-			bcast[i] = (ip[i] & mask[i]) | ~mask[i];
-		addselfcache(f, ifc, lifc, bcast, Rbcast);
-
-		/* add network directed network address to the self cache */
-		memmove(mask, defmask(ip), IPaddrlen);
-		for(i = 0; i < IPaddrlen; i++)
-			bcast[i] = (ip[i] & mask[i]) & mask[i];
-		addselfcache(f, ifc, lifc, bcast, Rbcast);
-
-		addselfcache(f, ifc, lifc, IPv4bcast, Rbcast);
-	}
-	else {
-		if(ipcmp(ip, v6loopback) == 0) {
-			/* add node-local mcast address */
-			addselfcache(f, ifc, lifc, v6allnodesN, Rmulti);
-
-			/* add route for all node multicast */
-			v6addroute(f, tifc, v6allnodesN, v6allnodesNmask,
-				v6allnodesN, Rmulti);
-		}
-
-		/* add all nodes multicast address */
-		addselfcache(f, ifc, lifc, v6allnodesL, Rmulti);
-
-		/* add route for all nodes multicast */
-		v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL,
-			Rmulti);
-
-		/* add solicited-node multicast address */
-		ipv62smcast(bcast, ip);
-		addselfcache(f, ifc, lifc, bcast, Rmulti);
-
-		sendnbrdisc = 1;
-	}
-
-	/* register the address on this network for address resolution */
-	if(isv4(ip) && ifc->m->areg != nil)
-		(*ifc->m->areg)(ifc, ip);
-
-out:
-	wunlock(ifc);
-	if(tentative && sendnbrdisc)
-		icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac);
-	return nil;
-}
-
-/*
- *  remove a logical interface from an ifc
- *  always called with ifc wlock'd
- */
-static char*
-ipifcremlifc(Ipifc *ifc, Iplifc *lifc)
-{
-	Iplifc **l;
-	Fs *f;
-
-	f = ifc->conv->p->f;
-
-	/*
-	 *  find address on this interface and remove from chain.
-	 *  for pt to pt we actually specify the remote address as the
-	 *  addresss to remove.
-	 */
-	for(l = &ifc->lifc; *l != nil && *l != lifc; l = &(*l)->next)
-		;
-	if(*l == nil)
-		return "address not on this interface";
-	*l = lifc->next;
-
-	/* disassociate any addresses */
-	while(lifc->link)
-		remselfcache(f, ifc, lifc, lifc->link->self->a);
-
-	/* remove the route for this logical interface */
-	if(isv4(lifc->local))
-		v4delroute(f, lifc->remote+IPv4off, lifc->mask+IPv4off, 1);
-	else {
-		v6delroute(f, lifc->remote, lifc->mask, 1);
-		if(ipcmp(lifc->local, v6loopback) == 0)
-			/* remove route for all node multicast */
-			v6delroute(f, v6allnodesN, v6allnodesNmask, 1);
-		else if(memcmp(lifc->local, v6linklocal, v6llpreflen) == 0)
-			/* remove route for all link multicast */
-			v6delroute(f, v6allnodesL, v6allnodesLmask, 1);
-	}
-
-	free(lifc);
-	return nil;
-}
-
-/*
- *  remove an address from an interface.
- *  called with c->car locked
- */
-char*
-ipifcrem(Ipifc *ifc, char **argv, int argc)
-{
-	char *rv;
-	uchar ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen];
-	Iplifc *lifc;
-
-	if(argc < 3)
-		return Ebadarg;
-
-	if (parseip(ip, argv[1]) == -1)
-		return Ebadip;
-	parseipmask(mask, argv[2]);
-	if(argc < 4)
-		maskip(ip, mask, rem);
-	else
-		if (parseip(rem, argv[3]) == -1)
-			return Ebadip;
-
-	wlock(ifc);
-
-	/*
-	 *  find address on this interface and remove from chain.
-	 *  for pt to pt we actually specify the remote address as the
-	 *  addresss to remove.
-	 */
-	for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) {
-		if (memcmp(ip, lifc->local, IPaddrlen) == 0
-		&& memcmp(mask, lifc->mask, IPaddrlen) == 0
-		&& memcmp(rem, lifc->remote, IPaddrlen) == 0)
-			break;
-	}
-
-	rv = ipifcremlifc(ifc, lifc);
-	wunlock(ifc);
-	return rv;
-}
-
-/*
- * distribute routes to active interfaces like the
- * TRIP linecards
- */
-void
-ipifcaddroute(Fs *f, int vers, uchar *addr, uchar *mask, uchar *gate, int type)
-{
-	Medium *m;
-	Conv **cp, **e;
-	Ipifc *ifc;
-
-	e = &f->ipifc->conv[f->ipifc->nc];
-	for(cp = f->ipifc->conv; cp < e; cp++){
-		if(*cp != nil) {
-			ifc = (Ipifc*)(*cp)->ptcl;
-			m = ifc->m;
-			if(m && m->addroute)
-				m->addroute(ifc, vers, addr, mask, gate, type);
-		}
-	}
-}
-
-void
-ipifcremroute(Fs *f, int vers, uchar *addr, uchar *mask)
-{
-	Medium *m;
-	Conv **cp, **e;
-	Ipifc *ifc;
-
-	e = &f->ipifc->conv[f->ipifc->nc];
-	for(cp = f->ipifc->conv; cp < e; cp++){
-		if(*cp != nil) {
-			ifc = (Ipifc*)(*cp)->ptcl;
-			m = ifc->m;
-			if(m && m->remroute)
-				m->remroute(ifc, vers, addr, mask);
-		}
-	}
-}
-
-/*
- *  associate an address with the interface.  This wipes out any previous
- *  addresses.  This is a macro that means, remove all the old interfaces
- *  and add a new one.
- */
-static char*
-ipifcconnect(Conv* c, char **argv, int argc)
-{
-	char *err;
-	Ipifc *ifc;
-
-	ifc = (Ipifc*)c->ptcl;
-
-	if(ifc->m == nil)
-		 return "ipifc not yet bound to device";
-
-	if(waserror()){
-		wunlock(ifc);
-		nexterror();
-	}
-	wlock(ifc);
-	while(ifc->lifc){
-		err = ipifcremlifc(ifc, ifc->lifc);
-		if(err)
-			error(err);
-	}
-	wunlock(ifc);
-	poperror();
-
-	err = ipifcadd(ifc, argv, argc, 0, nil);
-	if(err)
-		return err;
-
-	Fsconnected(c, nil);
-	return nil;
-}
-
-char*
-ipifcra6(Ipifc *ifc, char **argv, int argc)
-{
-	int i, argsleft, vmax = ifc->rp.maxraint, vmin = ifc->rp.minraint;
-
-	argsleft = argc - 1;
-	i = 1;
-
-	if(argsleft % 2 != 0)
-		return Ebadarg;
-
-	while (argsleft > 1) {
-		if(strcmp(argv[i], "recvra") == 0)
-			ifc->recvra6 = (atoi(argv[i+1]) != 0);
-		else if(strcmp(argv[i], "sendra") == 0)
-			ifc->sendra6 = (atoi(argv[i+1]) != 0);
-		else if(strcmp(argv[i], "mflag") == 0)
-			ifc->rp.mflag = (atoi(argv[i+1]) != 0);
-		else if(strcmp(argv[i], "oflag") == 0)
-			ifc->rp.oflag = (atoi(argv[i+1]) != 0);
-		else if(strcmp(argv[i], "maxraint") == 0)
-			ifc->rp.maxraint = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "minraint") == 0)
-			ifc->rp.minraint = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "linkmtu") == 0)
-			ifc->rp.linkmtu = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "reachtime") == 0)
-			ifc->rp.reachtime = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "rxmitra") == 0)
-			ifc->rp.rxmitra = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "ttl") == 0)
-			ifc->rp.ttl = atoi(argv[i+1]);
-		else if(strcmp(argv[i], "routerlt") == 0)
-			ifc->rp.routerlt = atoi(argv[i+1]);
-		else
-			return Ebadarg;
-
-		argsleft -= 2;
-		i += 2;
-	}
-
-	/* consistency check */
-	if(ifc->rp.maxraint < ifc->rp.minraint) {
-		ifc->rp.maxraint = vmax;
-		ifc->rp.minraint = vmin;
-		return Ebadarg;
-	}
-	return nil;
-}
-
-/*
- *  non-standard control messages.
- *  called with c->car locked.
- */
-static char*
-ipifcctl(Conv* c, char**argv, int argc)
-{
-	Ipifc *ifc;
-	int i;
-
-	ifc = (Ipifc*)c->ptcl;
-	if(strcmp(argv[0], "add") == 0)
-		return ipifcadd(ifc, argv, argc, 0, nil);
-	else if(strcmp(argv[0], "try") == 0)
-		return ipifcadd(ifc, argv, argc, 1, nil);
-	else if(strcmp(argv[0], "remove") == 0)
-		return ipifcrem(ifc, argv, argc);
-	else if(strcmp(argv[0], "unbind") == 0)
-		return ipifcunbind(ifc);
-	else if(strcmp(argv[0], "joinmulti") == 0)
-		return ipifcjoinmulti(ifc, argv, argc);
-	else if(strcmp(argv[0], "leavemulti") == 0)
-		return ipifcleavemulti(ifc, argv, argc);
-	else if(strcmp(argv[0], "mtu") == 0)
-		return ipifcsetmtu(ifc, argv, argc);
-	else if(strcmp(argv[0], "reassemble") == 0){
-		ifc->reassemble = 1;
-		return nil;
-	}
-	else if(strcmp(argv[0], "iprouting") == 0){
-		i = 1;
-		if(argc > 1)
-			i = atoi(argv[1]);
-		iprouting(c->p->f, i);
-		return nil;
-	}
-	else if(strcmp(argv[0], "add6") == 0)
-		return ipifcadd6(ifc, argv, argc);
-	else if(strcmp(argv[0], "ra6") == 0)
-		return ipifcra6(ifc, argv, argc);
-	return "unsupported ctl";
-}
-
-int
-ipifcstats(Proto *ipifc, char *buf, int len)
-{
-	return ipstats(ipifc->f, buf, len);
-}
-
-void
-ipifcinit(Fs *f)
-{
-	Proto *ipifc;
-
-	ipifc = smalloc(sizeof(Proto));
-	ipifc->name = "ipifc";
-	ipifc->connect = ipifcconnect;
-	ipifc->announce = nil;
-	ipifc->bind = ipifcbind;
-	ipifc->state = ipifcstate;
-	ipifc->create = ipifccreate;
-	ipifc->close = ipifcclose;
-	ipifc->rcv = nil;
-	ipifc->ctl = ipifcctl;
-	ipifc->advise = nil;
-	ipifc->stats = ipifcstats;
-	ipifc->inuse = ipifcinuse;
-	ipifc->local = ipifclocal;
-	ipifc->ipproto = -1;
-	ipifc->nc = Maxmedia;
-	ipifc->ptclsize = sizeof(Ipifc);
-
-	f->ipifc = ipifc;	/* hack for ipifcremroute, findipifc, ... */
-	f->self = smalloc(sizeof(Ipselftab));	/* hack for ipforme */
-
-	Fsproto(f, ipifc);
-}
-
-/*
- *  add to self routing cache
- *	called with c->car locked
- */
-static void
-addselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a, int type)
-{
-	Ipself *p;
-	Iplink *lp;
-	int h;
-
-	qlock(f->self);
-
-	/* see if the address already exists */
-	h = hashipa(a);
-	for(p = f->self->hash[h]; p; p = p->next)
-		if(memcmp(a, p->a, IPaddrlen) == 0)
-			break;
-
-	/* allocate a local address and add to hash chain */
-	if(p == nil){
-		p = smalloc(sizeof(*p));
-		ipmove(p->a, a);
-		p->type = type;
-		p->next = f->self->hash[h];
-		f->self->hash[h] = p;
-
-		/* if the null address, accept all packets */
-		if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
-			f->self->acceptall = 1;
-	}
-
-	/* look for a link for this lifc */
-	for(lp = p->link; lp; lp = lp->selflink)
-		if(lp->lifc == lifc)
-			break;
-
-	/* allocate a lifc-to-local link and link to both */
-	if(lp == nil){
-		lp = smalloc(sizeof(*lp));
-		lp->ref = 1;
-		lp->lifc = lifc;
-		lp->self = p;
-		lp->selflink = p->link;
-		p->link = lp;
-		lp->lifclink = lifc->link;
-		lifc->link = lp;
-
-		/* add to routing table */
-		if(isv4(a))
-			v4addroute(f, tifc, a+IPv4off, IPallbits+IPv4off,
-				a+IPv4off, type);
-		else
-			v6addroute(f, tifc, a, IPallbits, a, type);
-
-		if((type & Rmulti) && ifc->m->addmulti != nil)
-			(*ifc->m->addmulti)(ifc, a, lifc->local);
-	} else
-		lp->ref++;
-
-	qunlock(f->self);
-}
-
-/*
- *  These structures are unlinked from their chains while
- *  other threads may be using them.  To avoid excessive locking,
- *  just put them aside for a while before freeing them.
- *	called with f->self locked
- */
-static Iplink *freeiplink;
-static Ipself *freeipself;
-
-static void
-iplinkfree(Iplink *p)
-{
-	Iplink **l, *np;
-	ulong now = NOW;
-
-	l = &freeiplink;
-	for(np = *l; np; np = *l){
-		if(np->expire > now){
-			*l = np->next;
-			free(np);
-			continue;
-		}
-		l = &np->next;
-	}
-	p->expire = now + 5000;	/* give other threads 5 secs to get out */
-	p->next = nil;
-	*l = p;
-}
-
-static void
-ipselffree(Ipself *p)
-{
-	Ipself **l, *np;
-	ulong now = NOW;
-
-	l = &freeipself;
-	for(np = *l; np; np = *l){
-		if(np->expire > now){
-			*l = np->next;
-			free(np);
-			continue;
-		}
-		l = &np->next;
-	}
-	p->expire = now + 5000;	/* give other threads 5 secs to get out */
-	p->next = nil;
-	*l = p;
-}
-
-/*
- *  Decrement reference for this address on this link.
- *  Unlink from selftab if this is the last ref.
- *	called with c->car locked
- */
-static void
-remselfcache(Fs *f, Ipifc *ifc, Iplifc *lifc, uchar *a)
-{
-	Ipself *p, **l;
-	Iplink *link, **l_self, **l_lifc;
-
-	qlock(f->self);
-
-	/* find the unique selftab entry */
-	l = &f->self->hash[hashipa(a)];
-	for(p = *l; p; p = *l){
-		if(ipcmp(p->a, a) == 0)
-			break;
-		l = &p->next;
-	}
-
-	if(p == nil)
-		goto out;
-
-	/*
-	 *  walk down links from an ifc looking for one
-	 *  that matches the selftab entry
-	 */
-	l_lifc = &lifc->link;
-	for(link = *l_lifc; link; link = *l_lifc){
-		if(link->self == p)
-			break;
-		l_lifc = &link->lifclink;
-	}
-
-	if(link == nil)
-		goto out;
-
-	/*
-	 *  walk down the links from the selftab looking for
-	 *  the one we just found
-	 */
-	l_self = &p->link;
-	for(link = *l_self; link; link = *l_self){
-		if(link == *l_lifc)
-			break;
-		l_self = &link->selflink;
-	}
-
-	if(link == nil)
-		panic("remselfcache");
-
-	if(--(link->ref) != 0)
-		goto out;
-
-	if((p->type & Rmulti) && ifc->m->remmulti != nil)
-		(*ifc->m->remmulti)(ifc, a, lifc->local);
-
-	/* ref == 0, remove from both chains and free the link */
-	*l_lifc = link->lifclink;
-	*l_self = link->selflink;
-	iplinkfree(link);
-
-	if(p->link != nil)
-		goto out;
-
-	/* remove from routing table */
-	if(isv4(a))
-		v4delroute(f, a+IPv4off, IPallbits+IPv4off, 1);
-	else
-		v6delroute(f, a, IPallbits, 1);
-
-	/* no more links, remove from hash and free */
-	*l = p->next;
-	ipselffree(p);
-
-	/* if IPnoaddr, forget */
-	if(ipcmp(a, v4prefix) == 0 || ipcmp(a, IPnoaddr) == 0)
-		f->self->acceptall = 0;
-
-out:
-	qunlock(f->self);
-}
-
-static char *stformat = "%-44.44I %2.2d %4.4s\n";
-enum
-{
-	Nstformat= 41,
-};
-
-long
-ipselftabread(Fs *f, char *cp, ulong offset, int n)
-{
-	int i, m, nifc, off;
-	Ipself *p;
-	Iplink *link;
-	char state[8];
-
-	m = 0;
-	off = offset;
-	qlock(f->self);
-	for(i = 0; i < NHASH && m < n; i++){
-		for(p = f->self->hash[i]; p != nil && m < n; p = p->next){
-			nifc = 0;
-			for(link = p->link; link; link = link->selflink)
-				nifc++;
-			routetype(p->type, state);
-			m += snprint(cp + m, n - m, stformat, p->a, nifc, state);
-			if(off > 0){
-				off -= m;
-				m = 0;
-			}
-		}
-	}
-	qunlock(f->self);
-	return m;
-}
-
-int
-iptentative(Fs *f, uchar *addr)
-{
- 	Ipself *p;
-
-	p = f->self->hash[hashipa(addr)];
-	for(; p; p = p->next){
-		if(ipcmp(addr, p->a) == 0)
-			return p->link->lifc->tentative;
-	}
-	return 0;
-}
-
-/*
- *  returns
- *	0		- no match
- *	Runi
- *	Rbcast
- *	Rmcast
- */
-int
-ipforme(Fs *f, uchar *addr)
-{
-	Ipself *p;
-
-	p = f->self->hash[hashipa(addr)];
-	for(; p; p = p->next){
-		if(ipcmp(addr, p->a) == 0)
-			return p->type;
-	}
-
-	/* hack to say accept anything */
-	if(f->self->acceptall)
-		return Runi;
-	return 0;
-}
-
-/*
- *  find the ifc on same net as the remote system.  If none,
- *  return nil.
- */
-Ipifc*
-findipifc(Fs *f, uchar *remote, int type)
-{
-	Ipifc *ifc, *x;
-	Iplifc *lifc;
-	Conv **cp, **e;
-	uchar gnet[IPaddrlen], xmask[IPaddrlen];
-
-	x = nil;
-	memset(xmask, 0, IPaddrlen);
-
-	/* find most specific match */
-	e = &f->ipifc->conv[f->ipifc->nc];
-	for(cp = f->ipifc->conv; cp < e; cp++){
-		if(*cp == 0)
-			continue;
-		ifc = (Ipifc*)(*cp)->ptcl;
-		for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-			maskip(remote, lifc->mask, gnet);
-			if(ipcmp(gnet, lifc->net) == 0){
-				if(x == nil || ipcmp(lifc->mask, xmask) > 0){
-					x = ifc;
-					ipmove(xmask, lifc->mask);
-				}
-			}
-		}
-	}
-	if(x != nil)
-		return x;
-
-	/* for now for broadcast and multicast, just use first interface */
-	if(type & (Rbcast|Rmulti)){
-		for(cp = f->ipifc->conv; cp < e; cp++){
-			if(*cp == 0)
-				continue;
-			ifc = (Ipifc*)(*cp)->ptcl;
-			if(ifc->lifc != nil)
-				return ifc;
-		}
-	}
-	return nil;
-}
-
-enum {
-	unknownv6,		/* UGH */
-//	multicastv6,
-	unspecifiedv6,
-	linklocalv6,
-	globalv6,
-};
-
-int
-v6addrtype(uchar *addr)
-{
-	if(isv4(addr) || ipcmp(addr, IPnoaddr) == 0)
-		return unknownv6;
-	else if(islinklocal(addr) ||
-	    isv6mcast(addr) && (addr[1] & 0xF) <= Link_local_scop)
-		return linklocalv6;
-	else
-		return globalv6;
-}
-
-#define v6addrcurr(lifc) ((lifc)->preflt == ~0L || \
-			(lifc)->origint + (lifc)->preflt >= NOW/1000)
-
-static void
-findprimaryipv6(Fs *f, uchar *local)
-{
-	int atype, atypel;
-	Conv **cp, **e;
-	Ipifc *ifc;
-	Iplifc *lifc;
-
-	ipmove(local, v6Unspecified);
-	atype = unspecifiedv6;
-
-	/*
-	 * find "best" (global > link local > unspecified)
-	 * local address; address must be current.
-	 */
-	e = &f->ipifc->conv[f->ipifc->nc];
-	for(cp = f->ipifc->conv; cp < e; cp++){
-		if(*cp == 0)
-			continue;
-		ifc = (Ipifc*)(*cp)->ptcl;
-		for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-			atypel = v6addrtype(lifc->local);
-			if(atypel > atype && v6addrcurr(lifc)) {
-				ipmove(local, lifc->local);
-				atype = atypel;
-				if(atype == globalv6)
-					return;
-			}
-		}
-	}
-}
-
-/*
- *  returns first ip address configured
- */
-static void
-findprimaryipv4(Fs *f, uchar *local)
-{
-	Conv **cp, **e;
-	Ipifc *ifc;
-	Iplifc *lifc;
-
-	/* find first ifc local address */
-	e = &f->ipifc->conv[f->ipifc->nc];
-	for(cp = f->ipifc->conv; cp < e; cp++){
-		if(*cp == 0)
-			continue;
-		ifc = (Ipifc*)(*cp)->ptcl;
-		if((lifc = ifc->lifc) != nil){
-			ipmove(local, lifc->local);
-			return;
-		}
-	}
-}
-
-/*
- *  find the local address 'closest' to the remote system, copy it to
- *  local and return the ifc for that address
- */
-void
-findlocalip(Fs *f, uchar *local, uchar *remote)
-{
-	int version, atype = unspecifiedv6, atypel = unknownv6;
-	int atyper, deprecated;
-	uchar gate[IPaddrlen], gnet[IPaddrlen];
-	Ipifc *ifc;
-	Iplifc *lifc;
-	Route *r;
-
-	USED(atype);
-	USED(atypel);
-	qlock(f->ipifc);
-	r = v6lookup(f, remote, nil);
- 	version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6;
-
-	if(r != nil){
-		ifc = r->ifc;
-		if(r->type & Rv4)
-			v4tov6(gate, r->v4.gate);
-		else {
-			ipmove(gate, r->v6.gate);
-			ipmove(local, v6Unspecified);
-		}
-
-		switch(version) {
-		case V4:
-			/* find ifc address closest to the gateway to use */
-			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-				maskip(gate, lifc->mask, gnet);
-				if(ipcmp(gnet, lifc->net) == 0){
-					ipmove(local, lifc->local);
-					goto out;
-				}
-			}
-			break;
-		case V6:
-			/* find ifc address with scope matching the destination */
-			atyper = v6addrtype(remote);
-			deprecated = 0;
-			for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-				atypel = v6addrtype(lifc->local);
-				/* prefer appropriate scope */
-				if(atypel > atype && atype < atyper ||
-				   atypel < atype && atype > atyper){
-					ipmove(local, lifc->local);
-					deprecated = !v6addrcurr(lifc);
-					atype = atypel;
-				} else if(atypel == atype){
-					/* avoid deprecated addresses */
-					if(deprecated && v6addrcurr(lifc)){
-						ipmove(local, lifc->local);
-						atype = atypel;
-						deprecated = 0;
-					}
-				}
-				if(atype == atyper && !deprecated)
-					goto out;
-			}
-			if(atype >= atyper)
-				goto out;
-			break;
-		default:
-			panic("findlocalip: version %d", version);
-		}
-	}
-
-	switch(version){
-	case V4:
-		findprimaryipv4(f, local);
-		break;
-	case V6:
-		findprimaryipv6(f, local);
-		break;
-	default:
-		panic("findlocalip2: version %d", version);
-	}
-
-out:
-	qunlock(f->ipifc);
-}
-
-/*
- *  return first v4 address associated with an interface
- */
-int
-ipv4local(Ipifc *ifc, uchar *addr)
-{
-	Iplifc *lifc;
-
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(isv4(lifc->local)){
-			memmove(addr, lifc->local+IPv4off, IPv4addrlen);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-/*
- *  return first v6 address associated with an interface
- */
-int
-ipv6local(Ipifc *ifc, uchar *addr)
-{
-	Iplifc *lifc;
-
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(!isv4(lifc->local) && !(lifc->tentative)){
-			ipmove(addr, lifc->local);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-int
-ipv6anylocal(Ipifc *ifc, uchar *addr)
-{
-	Iplifc *lifc;
-
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		if(!isv4(lifc->local)){
-			ipmove(addr, lifc->local);
-			return SRC_UNI;
-		}
-	}
-	return SRC_UNSPEC;
-}
-
-/*
- *  see if this address is bound to the interface
- */
-Iplifc*
-iplocalonifc(Ipifc *ifc, uchar *ip)
-{
-	Iplifc *lifc;
-
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next)
-		if(ipcmp(ip, lifc->local) == 0)
-			return lifc;
-	return nil;
-}
-
-
-/*
- *  See if we're proxying for this address on this interface
- */
-int
-ipproxyifc(Fs *f, Ipifc *ifc, uchar *ip)
-{
-	Route *r;
-	uchar net[IPaddrlen];
-	Iplifc *lifc;
-
-	/* see if this is a direct connected pt to pt address */
-	r = v6lookup(f, ip, nil);
-	if(r == nil || (r->type & (Rifc|Rproxy)) != (Rifc|Rproxy))
-		return 0;
-
-	/* see if this is on the right interface */
-	for(lifc = ifc->lifc; lifc; lifc = lifc->next){
-		maskip(ip, lifc->mask, net);
-		if(ipcmp(net, lifc->remote) == 0)
-			return 1;
-	}
-	return 0;
-}
-
-/*
- *  return multicast version if any
- */
-int
-ipismulticast(uchar *ip)
-{
-	if(isv4(ip)){
-		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
-			return V4;
-	}
-	else if(ip[0] == 0xff)
-		return V6;
-	return 0;
-}
-int
-ipisbm(uchar *ip)
-{
-	if(isv4(ip)){
-		if(ip[IPv4off] >= 0xe0 && ip[IPv4off] < 0xf0)
-			return V4;
-		else if(ipcmp(ip, IPv4bcast) == 0)
-			return V4;
-	}
-	else if(ip[0] == 0xff)
-		return V6;
-	return 0;
-}
-
-
-/*
- *  add a multicast address to an interface, called with c->car locked
- */
-void
-ipifcaddmulti(Conv *c, uchar *ma, uchar *ia)
-{
-	Ipifc *ifc;
-	Iplifc *lifc;
-	Conv **p;
-	Ipmulti *multi, **l;
-	Fs *f;
-
-	f = c->p->f;
-
-	for(l = &c->multi; *l; l = &(*l)->next)
-		if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
-			return;		/* it's already there */
-
-	multi = *l = smalloc(sizeof(*multi));
-	ipmove(multi->ma, ma);
-	ipmove(multi->ia, ia);
-	multi->next = nil;
-
-	for(p = f->ipifc->conv; *p; p++){
-		if((*p)->inuse == 0)
-			continue;
-		ifc = (Ipifc*)(*p)->ptcl;
-		if(waserror()){
-			wunlock(ifc);
-			nexterror();
-		}
-		wlock(ifc);
-		for(lifc = ifc->lifc; lifc; lifc = lifc->next)
-			if(ipcmp(ia, lifc->local) == 0)
-				addselfcache(f, ifc, lifc, ma, Rmulti);
-		wunlock(ifc);
-		poperror();
-	}
-}
-
-
-/*
- *  remove a multicast address from an interface, called with c->car locked
- */
-void
-ipifcremmulti(Conv *c, uchar *ma, uchar *ia)
-{
-	Ipmulti *multi, **l;
-	Iplifc *lifc;
-	Conv **p;
-	Ipifc *ifc;
-	Fs *f;
-
-	f = c->p->f;
-
-	for(l = &c->multi; *l; l = &(*l)->next)
-		if(ipcmp(ma, (*l)->ma) == 0 && ipcmp(ia, (*l)->ia) == 0)
-			break;
-
-	multi = *l;
-	if(multi == nil)
-		return; 	/* we don't have it open */
-
-	*l = multi->next;
-
-	for(p = f->ipifc->conv; *p; p++){
-		if((*p)->inuse == 0)
-			continue;
-
-		ifc = (Ipifc*)(*p)->ptcl;
-		if(waserror()){
-			wunlock(ifc);
-			nexterror();
-		}
-		wlock(ifc);
-		for(lifc = ifc->lifc; lifc; lifc = lifc->next)
-			if(ipcmp(ia, lifc->local) == 0)
-				remselfcache(f, ifc, lifc, ma);
-		wunlock(ifc);
-		poperror();
-	}
-
-	free(multi);
-}
-
-/*
- *  make lifc's join and leave multicast groups
- */
-static char*
-ipifcjoinmulti(Ipifc *ifc, char **argv, int argc)
-{
-	USED(ifc, argv, argc);
-	return nil;
-}
-
-static char*
-ipifcleavemulti(Ipifc *ifc, char **argv, int argc)
-{
-	USED(ifc, argv, argc);
-	return nil;
-}
-
-static void
-ipifcregisterproxy(Fs *f, Ipifc *ifc, uchar *ip)
-{
-	Conv **cp, **e;
-	Ipifc *nifc;
-	Iplifc *lifc;
-	Medium *m;
-	uchar net[IPaddrlen];
-
-	/* register the address on any network that will proxy for us */
-	e = &f->ipifc->conv[f->ipifc->nc];
-
-	if(!isv4(ip)) {				/* V6 */
-		for(cp = f->ipifc->conv; cp < e; cp++){
-			if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc)
-				continue;
-			rlock(nifc);
-			m = nifc->m;
-			if(m == nil || m->addmulti == nil) {
-				runlock(nifc);
-				continue;
-			}
-			for(lifc = nifc->lifc; lifc; lifc = lifc->next){
-				maskip(ip, lifc->mask, net);
-				if(ipcmp(net, lifc->remote) == 0) {
-					/* add solicited-node multicast addr */
-					ipv62smcast(net, ip);
-					addselfcache(f, nifc, lifc, net, Rmulti);
-					arpenter(f, V6, ip, nifc->mac, 6, 0);
-					// (*m->addmulti)(nifc, net, ip);
-					break;
-				}
-			}
-			runlock(nifc);
-		}
-	}
-	else {					/* V4 */
-		for(cp = f->ipifc->conv; cp < e; cp++){
-			if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc)
-				continue;
-			rlock(nifc);
-			m = nifc->m;
-			if(m == nil || m->areg == nil){
-				runlock(nifc);
-				continue;
-			}
-			for(lifc = nifc->lifc; lifc; lifc = lifc->next){
-				maskip(ip, lifc->mask, net);
-				if(ipcmp(net, lifc->remote) == 0){
-					(*m->areg)(nifc, ip);
-					break;
-				}
-			}
-			runlock(nifc);
-		}
-	}
-}
-
-
-/* added for new v6 mesg types */
-static void
-adddefroute6(Fs *f, uchar *gate, int force)
-{
-	Route *r;
-
-	r = v6lookup(f, v6Unspecified, nil);
-	/*
-	 * route entries generated by all other means take precedence
-	 * over router announcements.
-	 */
-	if (r && !force && strcmp(r->tag, "ra") != 0)
-		return;
-
-	v6delroute(f, v6Unspecified, v6Unspecified, 1);
-	v6addroute(f, "ra", v6Unspecified, v6Unspecified, gate, 0);
-}
-
-enum {
-	Ngates = 3,
-};
-
-char*
-ipifcadd6(Ipifc *ifc, char**argv, int argc)
-{
-	int plen = 64;
-	long origint = NOW / 1000, preflt = ~0L, validlt = ~0L;
-	char addr[Maxv6repr], preflen[6];
-	char *params[3];
-	uchar autoflag = 1, onlink = 1;
-	uchar prefix[IPaddrlen];
-	Iplifc *lifc;
-
-	switch(argc) {
-	case 7:
-		preflt = atoi(argv[6]);
-		/* fall through */
-	case 6:
-		validlt = atoi(argv[5]);
-		/* fall through */
-	case 5:
-		autoflag = atoi(argv[4]);
-		/* fall through */
-	case 4:
-		onlink = atoi(argv[3]);
-		/* fall through */
-	case 3:
-		plen = atoi(argv[2]);
-		/* fall through */
-	case 2:
-		break;
-	default:
-		return Ebadarg;
-	}
-
-	if (parseip(prefix, argv[1]) != 6)
-		return "bad ipv6 address";
-	if (validlt < preflt)
-		return "valid ipv6 lifetime less than preferred lifetime";
-	if (plen < 0)
-		return "negative ipv6 prefix length";
-	/* i think that this length limit is bogus - geoff */
-//	if (plen > 64)
-//		return "ipv6 prefix length greater than 64;
-	if (islinklocal(prefix))
-		return "ipv6 prefix is link-local";
-
-	lifc = smalloc(sizeof(Iplifc));
-	lifc->onlink = (onlink != 0);
-	lifc->autoflag = (autoflag != 0);
-	lifc->validlt = validlt;
-	lifc->preflt = preflt;
-	lifc->origint = origint;
-
-	/* issue "add" ctl msg for v6 link-local addr and prefix len */
-	if(!ifc->m->pref2addr)
-		return "no pref2addr on interface";
-	ifc->m->pref2addr(prefix, ifc->mac);	/* mac → v6 link-local addr */
-	snprint(addr, sizeof addr, "%I", prefix);
-	snprint(preflen, sizeof preflen, "/%d", plen);
-	params[0] = "add";
-	params[1] = addr;
-	params[2] = preflen;
-
-	return ipifcadd(ifc, params, 3, 0, lifc);
-}

+ 0 - 849
sys/src/9/ip/ipmux.c

@@ -1,849 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * IP packet filter
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-#include "ipv6.h"
-
-typedef struct Ipmuxrock  Ipmuxrock;
-typedef struct Ipmux      Ipmux;
-
-typedef struct Myip4hdr Myip4hdr;
-struct Myip4hdr
-{
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* ip->identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	ttl;		/* Time to live */
-	uchar	proto;		/* Protocol */
-	uchar	cksum[2];	/* Header checksum */
-	uchar	src[4];		/* IP source */
-	uchar	dst[4];		/* IP destination */
-
-	uchar	data[1];	/* start of data */
-};
-Myip4hdr *ipoff = 0;
-
-enum
-{
-	Tproto,
-	Tdata,
-	Tiph,
-	Tdst,
-	Tsrc,
-	Tifc,
-
-	Cother = 0,
-	Cbyte,		/* single byte */
-	Cmbyte,		/* single byte with mask */
-	Cshort,		/* single short */
-	Cmshort,	/* single short with mask */
-	Clong,		/* single long */
-	Cmlong,		/* single long with mask */
-	Cifc,
-	Cmifc,
-};
-
-char *ftname[] =
-{
-[Tproto]	"proto",
-[Tdata]		"data",
-[Tiph]	 	"iph",
-[Tdst]		"dst",
-[Tsrc]		"src",
-[Tifc]		"ifc",
-};
-
-/*
- *  a node in the decision tree
- */
-struct Ipmux
-{
-	Ipmux	*yes;
-	Ipmux	*no;
-	uchar	type;		/* type of field(Txxxx) */
-	uchar	ctype;		/* tupe of comparison(Cxxxx) */
-	uchar	len;		/* length in bytes of item to compare */
-	uchar	n;		/* number of items val points to */
-	short	off;		/* offset of comparison */
-	short	eoff;		/* end offset of comparison */
-	uchar	skiphdr;	/* should offset start after ipheader */
-	uchar	*val;
-	uchar	*mask;
-	uchar	*e;		/* val+n*len*/
-
-	int	ref;		/* so we can garbage collect */
-	Conv	*conv;
-};
-
-/*
- *  someplace to hold per conversation data
- */
-struct Ipmuxrock
-{
-	Ipmux	*chain;
-};
-
-static int	ipmuxsprint(Ipmux*, int, char*, int);
-static void	ipmuxkick(void *x);
-
-static char*
-skipwhite(char *p)
-{
-	while(*p == ' ' || *p == '\t')
-		p++;
-	return p;
-}
-
-static char*
-follows(char *p, char c)
-{
-	char *f;
-
-	f = strchr(p, c);
-	if(f == nil)
-		return nil;
-	*f++ = 0;
-	f = skipwhite(f);
-	if(*f == 0)
-		return nil;
-	return f;
-}
-
-static Ipmux*
-parseop(char **pp)
-{
-	char *p = *pp;
-	int type, off, end, len;
-	Ipmux *f;
-
-	p = skipwhite(p);
-	if(strncmp(p, "dst", 3) == 0){
-		type = Tdst;
-		off = (ulong)(ipoff->dst);
-		len = IPv4addrlen;
-		p += 3;
-	}
-	else if(strncmp(p, "src", 3) == 0){
-		type = Tsrc;
-		off = (ulong)(ipoff->src);
-		len = IPv4addrlen;
-		p += 3;
-	}
-	else if(strncmp(p, "ifc", 3) == 0){
-		type = Tifc;
-		off = -IPv4addrlen;
-		len = IPv4addrlen;
-		p += 3;
-	}
-	else if(strncmp(p, "proto", 5) == 0){
-		type = Tproto;
-		off = (ulong)&(ipoff->proto);
-		len = 1;
-		p += 5;
-	}
-	else if(strncmp(p, "data", 4) == 0 || strncmp(p, "iph", 3) == 0){
-		if(strncmp(p, "data", 4) == 0) {
-			type = Tdata;
-			p += 4;
-		}
-		else {
-			type = Tiph;
-			p += 3;
-		}
-		p = skipwhite(p);
-		if(*p != '[')
-			return nil;
-		p++;
-		off = strtoul(p, &p, 0);
-		if(off < 0 || off > (64-IP4HDR))
-			return nil;
-		p = skipwhite(p);
-		if(*p != ':')
-			end = off;
-		else {
-			p++;
-			p = skipwhite(p);
-			end = strtoul(p, &p, 0);
-			if(end < off)
-				return nil;
-			p = skipwhite(p);
-		}
-		if(*p != ']')
-			return nil;
-		p++;
-		len = end - off + 1;
-	}
-	else
-		return nil;
-
-	f = smalloc(sizeof(*f));
-	f->type = type;
-	f->len = len;
-	f->off = off;
-	f->val = nil;
-	f->mask = nil;
-	f->n = 1;
-	f->ref = 1;
-	if(type == Tdata)
-		f->skiphdr = 1;
-	else
-		f->skiphdr = 0;
-
-	return f;
-}
-
-static int
-htoi(char x)
-{
-	if(x >= '0' && x <= '9')
-		x -= '0';
-	else if(x >= 'a' && x <= 'f')
-		x -= 'a' - 10;
-	else if(x >= 'A' && x <= 'F')
-		x -= 'A' - 10;
-	else
-		x = 0;
-	return x;
-}
-
-static int
-hextoi(char *p)
-{
-	return (htoi(p[0])<<4) | htoi(p[1]);
-}
-
-static void
-parseval(uchar *v, char *p, int len)
-{
-	while(*p && len-- > 0){
-		*v++ = hextoi(p);
-		p += 2;
-	}
-}
-
-static Ipmux*
-parsemux(char *p)
-{
-	int n, nomask;
-	Ipmux *f;
-	char *val;
-	char *mask;
-	char *vals[20];
-	uchar *v;
-
-	/* parse operand */
-	f = parseop(&p);
-	if(f == nil)
-		return nil;
-
-	/* find value */
-	val = follows(p, '=');
-	if(val == nil)
-		goto parseerror;
-
-	/* parse mask */
-	mask = follows(p, '&');
-	if(mask != nil){
-		switch(f->type){
-		case Tsrc:
-		case Tdst:
-		case Tifc:
-			f->mask = smalloc(f->len);
-			v4parseip(f->mask, mask);
-			break;
-		case Tdata:
-		case Tiph:
-			f->mask = smalloc(f->len);
-			parseval(f->mask, mask, f->len);
-			break;
-		default:
-			goto parseerror;
-		}
-		nomask = 0;
-	} else {
-		nomask = 1;
-		f->mask = smalloc(f->len);
-		memset(f->mask, 0xff, f->len);
-	}
-
-	/* parse vals */
-	f->n = getfields(val, vals, sizeof(vals)/sizeof(char*), 1, "|");
-	if(f->n == 0)
-		goto parseerror;
-	f->val = smalloc(f->n*f->len);
-	v = f->val;
-	for(n = 0; n < f->n; n++){
-		switch(f->type){
-		case Tsrc:
-		case Tdst:
-		case Tifc:
-			v4parseip(v, vals[n]);
-			break;
-		case Tproto:
-		case Tdata:
-		case Tiph:
-			parseval(v, vals[n], f->len);
-			break;
-		}
-		v += f->len;
-	}
-
-	f->eoff = f->off + f->len;
-	f->e = f->val + f->n*f->len;
-	f->ctype = Cother;
-	if(f->n == 1){
-		switch(f->len){
-		case 1:
-			f->ctype = nomask ? Cbyte : Cmbyte;
-			break;
-		case 2:
-			f->ctype = nomask ? Cshort : Cmshort;
-			break;
-		case 4:
-			if(f->type == Tifc)
-				f->ctype = nomask ? Cifc : Cmifc;
-			else
-				f->ctype = nomask ? Clong : Cmlong;
-			break;
-		}
-	}
-	return f;
-
-parseerror:
-	if(f->mask)
-		free(f->mask);
-	if(f->val)
-		free(f->val);
-	free(f);
-	return nil;
-}
-
-/*
- *  Compare relative ordering of two ipmuxs.  This doesn't compare the
- *  values, just the fields being looked at.
- *
- *  returns:	<0 if a is a more specific match
- *		 0 if a and b are matching on the same fields
- *		>0 if b is a more specific match
- */
-static int
-ipmuxcmp(Ipmux *a, Ipmux *b)
-{
-	int n;
-
-	/* compare types, lesser ones are more important */
-	n = a->type - b->type;
-	if(n != 0)
-		return n;
-
-	/* compare offsets, call earlier ones more specific */
-	n = (a->off+((int)a->skiphdr)*(ulong)ipoff->data) -
-		(b->off+((int)b->skiphdr)*(ulong)ipoff->data);
-	if(n != 0)
-		return n;
-
-	/* compare match lengths, longer ones are more specific */
-	n = b->len - a->len;
-	if(n != 0)
-		return n;
-
-	/*
-	 *  if we get here we have two entries matching
-	 *  the same bytes of the record.  Now check
-	 *  the mask for equality.  Longer masks are
-	 *  more specific.
-	 */
-	if(a->mask != nil && b->mask == nil)
-		return -1;
-	if(a->mask == nil && b->mask != nil)
-		return 1;
-	if(a->mask != nil && b->mask != nil){
-		n = memcmp(b->mask, a->mask, a->len);
-		if(n != 0)
-			return n;
-	}
-	return 0;
-}
-
-/*
- *  Compare the values of two ipmuxs.  We're assuming that ipmuxcmp
- *  returned 0 comparing them.
- */
-static int
-ipmuxvalcmp(Ipmux *a, Ipmux *b)
-{
-	int n;
-
-	n = b->len*b->n - a->len*a->n;
-	if(n != 0)
-		return n;
-	return memcmp(a->val, b->val, a->len*a->n);
-}
-
-/*
- *  add onto an existing ipmux chain in the canonical comparison
- *  order
- */
-static void
-ipmuxchain(Ipmux **l, Ipmux *f)
-{
-	for(; *l; l = &(*l)->yes)
-		if(ipmuxcmp(f, *l) < 0)
-			break;
-	f->yes = *l;
-	*l = f;
-}
-
-/*
- *  copy a tree
- */
-static Ipmux*
-ipmuxcopy(Ipmux *f)
-{
-	Ipmux *nf;
-
-	if(f == nil)
-		return nil;
-	nf = smalloc(sizeof *nf);
-	*nf = *f;
-	nf->no = ipmuxcopy(f->no);
-	nf->yes = ipmuxcopy(f->yes);
-	nf->val = smalloc(f->n*f->len);
-	nf->e = nf->val + f->len*f->n;
-	memmove(nf->val, f->val, f->n*f->len);
-	return nf;
-}
-
-static void
-ipmuxfree(Ipmux *f)
-{
-	if(f->val != nil)
-		free(f->val);
-	free(f);
-}
-
-static void
-ipmuxtreefree(Ipmux *f)
-{
-	if(f == nil)
-		return;
-	if(f->no != nil)
-		ipmuxfree(f->no);
-	if(f->yes != nil)
-		ipmuxfree(f->yes);
-	ipmuxfree(f);
-}
-
-/*
- *  merge two trees
- */
-static Ipmux*
-ipmuxmerge(Ipmux *a, Ipmux *b)
-{
-	int n;
-	Ipmux *f;
-
-	if(a == nil)
-		return b;
-	if(b == nil)
-		return a;
-	n = ipmuxcmp(a, b);
-	if(n < 0){
-		f = ipmuxcopy(b);
-		a->yes = ipmuxmerge(a->yes, b);
-		a->no = ipmuxmerge(a->no, f);
-		return a;
-	}
-	if(n > 0){
-		f = ipmuxcopy(a);
-		b->yes = ipmuxmerge(b->yes, a);
-		b->no = ipmuxmerge(b->no, f);
-		return b;
-	}
-	if(ipmuxvalcmp(a, b) == 0){
-		a->yes = ipmuxmerge(a->yes, b->yes);
-		a->no = ipmuxmerge(a->no, b->no);
-		a->ref++;
-		ipmuxfree(b);
-		return a;
-	}
-	a->no = ipmuxmerge(a->no, b);
-	return a;
-}
-
-/*
- *  remove a chain from a demux tree.  This is like merging accept that
- *  we remove instead of insert.
- */
-static int
-ipmuxremove(Ipmux **l, Ipmux *f)
-{
-	int n, rv;
-	Ipmux *ft;
-
-	if(f == nil)
-		return 0;		/* we've removed it all */
-	if(*l == nil)
-		return -1;
-
-	ft = *l;
-	n = ipmuxcmp(ft, f);
-	if(n < 0){
-		/* *l is maching an earlier field, descend both paths */
-		rv = ipmuxremove(&ft->yes, f);
-		rv += ipmuxremove(&ft->no, f);
-		return rv;
-	}
-	if(n > 0){
-		/* f represents an earlier field than *l, this should be impossible */
-		return -1;
-	}
-
-	/* if we get here f and *l are comparing the same fields */
-	if(ipmuxvalcmp(ft, f) != 0){
-		/* different values mean mutually exclusive */
-		return ipmuxremove(&ft->no, f);
-	}
-
-	/* we found a match */
-	if(--(ft->ref) == 0){
-		/*
-		 *  a dead node implies the whole yes side is also dead.
-		 *  since our chain is constrained to be on that side,
-		 *  we're done.
-		 */
-		ipmuxtreefree(ft->yes);
-		*l = ft->no;
-		ipmuxfree(ft);
-		return 0;
-	}
-
-	/*
-	 *  free the rest of the chain.  it is constrained to match the
-	 *  yes side.
-	 */
-	return ipmuxremove(&ft->yes, f->yes);
-}
-
-/*
- *  connection request is a semi separated list of filters
- *  e.g. proto=17;data[0:4]=11aa22bb;ifc=135.104.9.2&255.255.255.0
- *
- *  there's no protection against overlapping specs.
- */
-static char*
-ipmuxconnect(Conv *c, char **argv, int argc)
-{
-	int i, n;
-	char *field[10];
-	Ipmux *mux, *chain;
-	Ipmuxrock *r;
-	Fs *f;
-
-	f = c->p->f;
-
-	if(argc != 2)
-		return Ebadarg;
-
-	n = getfields(argv[1], field, nelem(field), 1, ";");
-	if(n <= 0)
-		return Ebadarg;
-
-	chain = nil;
-	mux = nil;
-	for(i = 0; i < n; i++){
-		mux = parsemux(field[i]);
-		if(mux == nil){
-			ipmuxtreefree(chain);
-			return Ebadarg;
-		}
-		ipmuxchain(&chain, mux);
-	}
-	if(chain == nil)
-		return Ebadarg;
-	mux->conv = c;
-
-	/* save a copy of the chain so we can later remove it */
-	mux = ipmuxcopy(chain);
-	r = (Ipmuxrock*)(c->ptcl);
-	r->chain = chain;
-
-	/* add the chain to the protocol demultiplexor tree */
-	wlock(f);
-	f->ipmux->priv = ipmuxmerge(f->ipmux->priv, mux);
-	wunlock(f);
-
-	Fsconnected(c, nil);
-	return nil;
-}
-
-static int
-ipmuxstate(Conv *c, char *state, int n)
-{
-	Ipmuxrock *r;
-
-	r = (Ipmuxrock*)(c->ptcl);
-	return ipmuxsprint(r->chain, 0, state, n);
-}
-
-static void
-ipmuxcreate(Conv *c)
-{
-	Ipmuxrock *r;
-
-	c->rq = qopen(64*1024, Qmsg, 0, c);
-	c->wq = qopen(64*1024, Qkick, ipmuxkick, c);
-	r = (Ipmuxrock*)(c->ptcl);
-	r->chain = nil;
-}
-
-static char*
-ipmuxannounce(Conv*, char**, int)
-{
-	return "ipmux does not support announce";
-}
-
-static void
-ipmuxclose(Conv *c)
-{
-	Ipmuxrock *r;
-	Fs *f = c->p->f;
-
-	r = (Ipmuxrock*)(c->ptcl);
-
-	qclose(c->rq);
-	qclose(c->wq);
-	qclose(c->eq);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->lport = 0;
-	c->rport = 0;
-
-	wlock(f);
-	ipmuxremove(&(c->p->priv), r->chain);
-	wunlock(f);
-	ipmuxtreefree(r->chain);
-	r->chain = nil;
-}
-
-/*
- *  takes a fully formed ip packet and just passes it down
- *  the stack
- */
-static void
-ipmuxkick(void *x)
-{
-	Conv *c = x;
-	Block *bp;
-
-	bp = qget(c->wq);
-	if(bp != nil) {
-		Myip4hdr *ih4 = (Myip4hdr*)(bp->rp);
-
-		if((ih4->vihl & 0xF0) != IP_VER6)
-			ipoput4(c->p->f, bp, 0, ih4->ttl, ih4->tos, nil);
-		else
-			ipoput6(c->p->f, bp, 0, ((Ip6hdr*)ih4)->ttl, 0, nil);
-	}
-}
-
-static void
-ipmuxiput(Proto *p, Ipifc *ifc, Block *bp)
-{
-	int len, hl;
-	Fs *f = p->f;
-	uchar *m, *h, *v, *e, *ve, *hp;
-	Conv *c;
-	Ipmux *mux;
-	Myip4hdr *ip;
-	Ip6hdr *ip6;
-
-	ip = (Myip4hdr*)bp->rp;
-	hl = (ip->vihl&0x0F)<<2;
-
-	if(p->priv == nil)
-		goto nomatch;
-
-	h = bp->rp;
-	len = BLEN(bp);
-
-	/* run the v4 filter */
-	rlock(f);
-	c = nil;
-	mux = f->ipmux->priv;
-	while(mux != nil){
-		if(mux->eoff > len){
-			mux = mux->no;
-			continue;
-		}
-		hp = h + mux->off + ((int)mux->skiphdr)*hl;
-		switch(mux->ctype){
-		case Cbyte:
-			if(*mux->val == *hp)
-				goto yes;
-			break;
-		case Cmbyte:
-			if((*hp & *mux->mask) == *mux->val)
-				goto yes;
-			break;
-		case Cshort:
-			if(*((ushort*)mux->val) == *(ushort*)hp)
-				goto yes;
-			break;
-		case Cmshort:
-			if((*(ushort*)hp & (*((ushort*)mux->mask))) == *((ushort*)mux->val))
-				goto yes;
-			break;
-		case Clong:
-			if(*((ulong*)mux->val) == *(ulong*)hp)
-				goto yes;
-			break;
-		case Cmlong:
-			if((*(ulong*)hp & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
-				goto yes;
-			break;
-		case Cifc:
-			if(*((ulong*)mux->val) == *(ulong*)(ifc->lifc->local + IPv4off))
-				goto yes;
-			break;
-		case Cmifc:
-			if((*(ulong*)(ifc->lifc->local + IPv4off) & (*((ulong*)mux->mask))) == *((ulong*)mux->val))
-				goto yes;
-			break;
-		default:
-			v = mux->val;
-			for(e = mux->e; v < e; v = ve){
-				m = mux->mask;
-				hp = h + mux->off;
-				for(ve = v + mux->len; v < ve; v++){
-					if((*hp++ & *m++) != *v)
-						break;
-				}
-				if(v == ve)
-					goto yes;
-			}
-		}
-		mux = mux->no;
-		continue;
-yes:
-		if(mux->conv != nil)
-			c = mux->conv;
-		mux = mux->yes;
-	}
-	runlock(f);
-
-	if(c != nil){
-		/* tack on interface address */
-		bp = padblock(bp, IPaddrlen);
-		ipmove(bp->rp, ifc->lifc->local);
-		bp = concatblock(bp);
-		if(bp != nil)
-			if(qpass(c->rq, bp) < 0)
-				print("ipmuxiput: qpass failed\n");
-		return;
-	}
-
-nomatch:
-	/* doesn't match any filter, hand it to the specific protocol handler */
-	ip = (Myip4hdr*)bp->rp;
-	if((ip->vihl & 0xF0) == IP_VER4) {
-		p = f->t2p[ip->proto];
-	} else {
-		ip6 = (Ip6hdr*)bp->rp;
-		p = f->t2p[ip6->proto];
-	}
-	if(p && p->rcv)
-		(*p->rcv)(p, ifc, bp);
-	else
-		freeblist(bp);
-	return;
-}
-
-static int
-ipmuxsprint(Ipmux *mux, int level, char *buf, int len)
-{
-	int i, j, n;
-	uchar *v;
-
-	n = 0;
-	for(i = 0; i < level; i++)
-		n += snprint(buf+n, len-n, " ");
-	if(mux == nil){
-		n += snprint(buf+n, len-n, "\n");
-		return n;
-	}
-	n += snprint(buf+n, len-n, "h[%d:%d]&",
-               mux->off+((int)mux->skiphdr)*((int)ipoff->data),
-               mux->off+(((int)mux->skiphdr)*((int)ipoff->data))+mux->len-1);
-	for(i = 0; i < mux->len; i++)
-		n += snprint(buf+n, len - n, "%2.2ux", mux->mask[i]);
-	n += snprint(buf+n, len-n, "=");
-	v = mux->val;
-	for(j = 0; j < mux->n; j++){
-		for(i = 0; i < mux->len; i++)
-			n += snprint(buf+n, len - n, "%2.2ux", *v++);
-		n += snprint(buf+n, len-n, "|");
-	}
-	n += snprint(buf+n, len-n, "\n");
-	level++;
-	n += ipmuxsprint(mux->no, level, buf+n, len-n);
-	n += ipmuxsprint(mux->yes, level, buf+n, len-n);
-	return n;
-}
-
-static int
-ipmuxstats(Proto *p, char *buf, int len)
-{
-	int n;
-	Fs *f = p->f;
-
-	rlock(f);
-	n = ipmuxsprint(p->priv, 0, buf, len);
-	runlock(f);
-
-	return n;
-}
-
-void
-ipmuxinit(Fs *f)
-{
-	Proto *ipmux;
-
-	ipmux = smalloc(sizeof(Proto));
-	ipmux->priv = nil;
-	ipmux->name = "ipmux";
-	ipmux->connect = ipmuxconnect;
-	ipmux->announce = ipmuxannounce;
-	ipmux->state = ipmuxstate;
-	ipmux->create = ipmuxcreate;
-	ipmux->close = ipmuxclose;
-	ipmux->rcv = ipmuxiput;
-	ipmux->ctl = nil;
-	ipmux->advise = nil;
-	ipmux->stats = ipmuxstats;
-	ipmux->ipproto = -1;
-	ipmux->nc = 64;
-	ipmux->ptclsize = sizeof(Ipmuxrock);
-
-	f->ipmux = ipmux;			/* hack for Fsrcvpcol */
-
-	Fsproto(f, ipmux);
-}

+ 0 - 901
sys/src/9/ip/iproute.c

@@ -1,901 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-
-static void	walkadd(Fs*, Route**, Route*);
-static void	addnode(Fs*, Route**, Route*);
-static void	calcd(Route*);
-
-/* these are used for all instances of IP */
-static Route*	v4freelist;
-static Route*	v6freelist;
-static RWlock	routelock;
-static ulong	v4routegeneration, v6routegeneration;
-
-static void
-freeroute(Route *r)
-{
-	Route **l;
-
-	r->left = nil;
-	r->right = nil;
-	if(r->type & Rv4)
-		l = &v4freelist;
-	else
-		l = &v6freelist;
-	r->mid = *l;
-	*l = r;
-}
-
-static Route*
-allocroute(int type)
-{
-	Route *r;
-	int n;
-	Route **l;
-
-	if(type & Rv4){
-		n = sizeof(RouteTree) + sizeof(V4route);
-		l = &v4freelist;
-	} else {
-		n = sizeof(RouteTree) + sizeof(V6route);
-		l = &v6freelist;
-	}
-
-	r = *l;
-	if(r != nil){
-		*l = r->mid;
-	} else {
-		r = malloc(n);
-		if(r == nil)
-			panic("out of routing nodes");
-	}
-	memset(r, 0, n);
-	r->type = type;
-	r->ifc = nil;
-	r->ref = 1;
-
-	return r;
-}
-
-static void
-addqueue(Route **q, Route *r)
-{
-	Route *l;
-
-	if(r == nil)
-		return;
-
-	l = allocroute(r->type);
-	l->mid = *q;
-	*q = l;
-	l->left = r;
-}
-
-/*
- *   compare 2 v6 addresses
- */
-static int
-lcmp(ulong *a, ulong *b)
-{
-	int i;
-
-	for(i = 0; i < IPllen; i++){
-		if(a[i] > b[i])
-			return 1;
-		if(a[i] < b[i])
-			return -1;
-	}
-	return 0;
-}
-
-/*
- *  compare 2 v4 or v6 ranges
- */
-enum
-{
-	Rpreceeds,
-	Rfollows,
-	Requals,
-	Rcontains,
-	Rcontained,
-};
-
-static int
-rangecompare(Route *a, Route *b)
-{
-	if(a->type & Rv4){
-		if(a->v4.endaddress < b->v4.address)
-			return Rpreceeds;
-
-		if(a->v4.address > b->v4.endaddress)
-			return Rfollows;
-
-		if(a->v4.address <= b->v4.address
-		&& a->v4.endaddress >= b->v4.endaddress){
-			if(a->v4.address == b->v4.address
-			&& a->v4.endaddress == b->v4.endaddress)
-				return Requals;
-			return Rcontains;
-		}
-		return Rcontained;
-	}
-
-	if(lcmp(a->v6.endaddress, b->v6.address) < 0)
-		return Rpreceeds;
-
-	if(lcmp(a->v6.address, b->v6.endaddress) > 0)
-		return Rfollows;
-
-	if(lcmp(a->v6.address, b->v6.address) <= 0
-	&& lcmp(a->v6.endaddress, b->v6.endaddress) >= 0){
-		if(lcmp(a->v6.address, b->v6.address) == 0
-		&& lcmp(a->v6.endaddress, b->v6.endaddress) == 0)
-				return Requals;
-		return Rcontains;
-	}
-
-	return Rcontained;
-}
-
-static void
-copygate(Route *old, Route *new)
-{
-	if(new->type & Rv4)
-		memmove(old->v4.gate, new->v4.gate, IPv4addrlen);
-	else
-		memmove(old->v6.gate, new->v6.gate, IPaddrlen);
-}
-
-/*
- *  walk down a tree adding nodes back in
- */
-static void
-walkadd(Fs *f, Route **root, Route *p)
-{
-	Route *l, *r;
-
-	l = p->left;
-	r = p->right;
-	p->left = 0;
-	p->right = 0;
-	addnode(f, root, p);
-	if(l)
-		walkadd(f, root, l);
-	if(r)
-		walkadd(f, root, r);
-}
-
-/*
- *  calculate depth
- */
-static void
-calcd(Route *p)
-{
-	Route *q;
-	int d;
-
-	if(p) {
-		d = 0;
-		q = p->left;
-		if(q)
-			d = q->depth;
-		q = p->right;
-		if(q && q->depth > d)
-			d = q->depth;
-		q = p->mid;
-		if(q && q->depth > d)
-			d = q->depth;
-		p->depth = d+1;
-	}
-}
-
-/*
- *  balance the tree at the current node
- */
-static void
-balancetree(Route **cur)
-{
-	Route *p, *l, *r;
-	int dl, dr;
-
-	/*
-	 * if left and right are
-	 * too out of balance,
-	 * rotate tree node
-	 */
-	p = *cur;
-	dl = 0; if(l = p->left) dl = l->depth;
-	dr = 0; if(r = p->right) dr = r->depth;
-
-	if(dl > dr+1) {
-		p->left = l->right;
-		l->right = p;
-		*cur = l;
-		calcd(p);
-		calcd(l);
-	} else
-	if(dr > dl+1) {
-		p->right = r->left;
-		r->left = p;
-		*cur = r;
-		calcd(p);
-		calcd(r);
-	} else
-		calcd(p);
-}
-
-/*
- *  add a new node to the tree
- */
-static void
-addnode(Fs *f, Route **cur, Route *new)
-{
-	Route *p;
-
-	p = *cur;
-	if(p == 0) {
-		*cur = new;
-		new->depth = 1;
-		return;
-	}
-
-	switch(rangecompare(new, p)){
-	case Rpreceeds:
-		addnode(f, &p->left, new);
-		break;
-	case Rfollows:
-		addnode(f, &p->right, new);
-		break;
-	case Rcontains:
-		/*
-		 *  if new node is superset
-		 *  of tree node,
-		 *  replace tree node and
-		 *  queue tree node to be
-		 *  merged into root.
-		 */
-		*cur = new;
-		new->depth = 1;
-		addqueue(&f->queue, p);
-		break;
-	case Requals:
-		/*
-		 *  supercede the old entry if the old one isn't
-		 *  a local interface.
-		 */
-		if((p->type & Rifc) == 0){
-			p->type = new->type;
-			p->ifcid = -1;
-			copygate(p, new);
-		} else if(new->type & Rifc)
-			p->ref++;
-		freeroute(new);
-		break;
-	case Rcontained:
-		addnode(f, &p->mid, new);
-		break;
-	}
-
-	balancetree(cur);
-}
-
-#define	V4H(a)	((a&0x07ffffff)>>(32-Lroot-5))
-
-void
-v4addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
-{
-	Route *p;
-	ulong sa;
-	ulong m;
-	ulong ea;
-	int h, eh;
-
-	m = nhgetl(mask);
-	sa = nhgetl(a) & m;
-	ea = sa | ~m;
-
-	eh = V4H(ea);
-	for(h=V4H(sa); h<=eh; h++) {
-		p = allocroute(Rv4 | type);
-		p->v4.address = sa;
-		p->v4.endaddress = ea;
-		memmove(p->v4.gate, gate, sizeof(p->v4.gate));
-		memmove(p->tag, tag, sizeof(p->tag));
-
-		wlock(&routelock);
-		addnode(f, &f->v4root[h], p);
-		while(p = f->queue) {
-			f->queue = p->mid;
-			walkadd(f, &f->v4root[h], p->left);
-			freeroute(p);
-		}
-		wunlock(&routelock);
-	}
-	v4routegeneration++;
-
-	ipifcaddroute(f, Rv4, a, mask, gate, type);
-}
-
-#define	V6H(a)	(((a)[IPllen-1] & 0x07ffffff)>>(32-Lroot-5))
-#define ISDFLT(a, mask, tag) ((ipcmp((a),v6Unspecified)==0) && (ipcmp((mask),v6Unspecified)==0) && (strcmp((tag), "ra")!=0))
-
-void
-v6addroute(Fs *f, char *tag, uchar *a, uchar *mask, uchar *gate, int type)
-{
-	Route *p;
-	ulong sa[IPllen], ea[IPllen];
-	ulong x, y;
-	int h, eh;
-
-	/*
-	if(ISDFLT(a, mask, tag))
-		f->v6p->cdrouter = -1;
-	*/
-
-
-	for(h = 0; h < IPllen; h++){
-		x = nhgetl(a+4*h);
-		y = nhgetl(mask+4*h);
-		sa[h] = x & y;
-		ea[h] = x | ~y;
-	}
-
-	eh = V6H(ea);
-	for(h = V6H(sa); h <= eh; h++) {
-		p = allocroute(type);
-		memmove(p->v6.address, sa, IPaddrlen);
-		memmove(p->v6.endaddress, ea, IPaddrlen);
-		memmove(p->v6.gate, gate, IPaddrlen);
-		memmove(p->tag, tag, sizeof(p->tag));
-
-		wlock(&routelock);
-		addnode(f, &f->v6root[h], p);
-		while(p = f->queue) {
-			f->queue = p->mid;
-			walkadd(f, &f->v6root[h], p->left);
-			freeroute(p);
-		}
-		wunlock(&routelock);
-	}
-	v6routegeneration++;
-
-	ipifcaddroute(f, 0, a, mask, gate, type);
-}
-
-Route**
-looknode(Route **cur, Route *r)
-{
-	Route *p;
-
-	for(;;){
-		p = *cur;
-		if(p == 0)
-			return 0;
-
-		switch(rangecompare(r, p)){
-		case Rcontains:
-			return 0;
-		case Rpreceeds:
-			cur = &p->left;
-			break;
-		case Rfollows:
-			cur = &p->right;
-			break;
-		case Rcontained:
-			cur = &p->mid;
-			break;
-		case Requals:
-			return cur;
-		}
-	}
-}
-
-void
-v4delroute(Fs *f, uchar *a, uchar *mask, int dolock)
-{
-	Route **r, *p;
-	Route rt;
-	int h, eh;
-	ulong m;
-
-	m = nhgetl(mask);
-	rt.v4.address = nhgetl(a) & m;
-	rt.v4.endaddress = rt.v4.address | ~m;
-	rt.type = Rv4;
-
-	eh = V4H(rt.v4.endaddress);
-	for(h=V4H(rt.v4.address); h<=eh; h++) {
-		if(dolock)
-			wlock(&routelock);
-		r = looknode(&f->v4root[h], &rt);
-		if(r) {
-			p = *r;
-			if(--(p->ref) == 0){
-				*r = 0;
-				addqueue(&f->queue, p->left);
-				addqueue(&f->queue, p->mid);
-				addqueue(&f->queue, p->right);
-				freeroute(p);
-				while(p = f->queue) {
-					f->queue = p->mid;
-					walkadd(f, &f->v4root[h], p->left);
-					freeroute(p);
-				}
-			}
-		}
-		if(dolock)
-			wunlock(&routelock);
-	}
-	v4routegeneration++;
-
-	ipifcremroute(f, Rv4, a, mask);
-}
-
-void
-v6delroute(Fs *f, uchar *a, uchar *mask, int dolock)
-{
-	Route **r, *p;
-	Route rt;
-	int h, eh;
-	ulong x, y;
-
-	for(h = 0; h < IPllen; h++){
-		x = nhgetl(a+4*h);
-		y = nhgetl(mask+4*h);
-		rt.v6.address[h] = x & y;
-		rt.v6.endaddress[h] = x | ~y;
-	}
-	rt.type = 0;
-
-	eh = V6H(rt.v6.endaddress);
-	for(h=V6H(rt.v6.address); h<=eh; h++) {
-		if(dolock)
-			wlock(&routelock);
-		r = looknode(&f->v6root[h], &rt);
-		if(r) {
-			p = *r;
-			if(--(p->ref) == 0){
-				*r = 0;
-				addqueue(&f->queue, p->left);
-				addqueue(&f->queue, p->mid);
-				addqueue(&f->queue, p->right);
-				freeroute(p);
-				while(p = f->queue) {
-					f->queue = p->mid;
-					walkadd(f, &f->v6root[h], p->left);
-					freeroute(p);
-				}
-			}
-		}
-		if(dolock)
-			wunlock(&routelock);
-	}
-	v6routegeneration++;
-
-	ipifcremroute(f, 0, a, mask);
-}
-
-Route*
-v4lookup(Fs *f, uchar *a, Conv *c)
-{
-	Route *p, *q;
-	ulong la;
-	uchar gate[IPaddrlen];
-	Ipifc *ifc;
-
-	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v4routegeneration)
-		return c->r;
-
-	la = nhgetl(a);
-	q = nil;
-	for(p=f->v4root[V4H(la)]; p;)
-		if(la >= p->v4.address) {
-			if(la <= p->v4.endaddress) {
-				q = p;
-				p = p->mid;
-			} else
-				p = p->right;
-		} else
-			p = p->left;
-
-	if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
-		if(q->type & Rifc) {
-			hnputl(gate+IPv4off, q->v4.address);
-			memmove(gate, v4prefix, IPv4off);
-		} else
-			v4tov6(gate, q->v4.gate);
-		ifc = findipifc(f, gate, q->type);
-		if(ifc == nil)
-			return nil;
-		q->ifc = ifc;
-		q->ifcid = ifc->ifcid;
-	}
-
-	if(c != nil){
-		c->r = q;
-		c->rgen = v4routegeneration;
-	}
-
-	return q;
-}
-
-Route*
-v6lookup(Fs *f, uchar *a, Conv *c)
-{
-	Route *p, *q;
-	ulong la[IPllen];
-	int h;
-	ulong x, y;
-	uchar gate[IPaddrlen];
-	Ipifc *ifc;
-
-	if(memcmp(a, v4prefix, IPv4off) == 0){
-		q = v4lookup(f, a+IPv4off, c);
-		if(q != nil)
-			return q;
-	}
-
-	if(c != nil && c->r != nil && c->r->ifc != nil && c->rgen == v6routegeneration)
-		return c->r;
-
-	for(h = 0; h < IPllen; h++)
-		la[h] = nhgetl(a+4*h);
-
-	q = 0;
-	for(p=f->v6root[V6H(la)]; p;){
-		for(h = 0; h < IPllen; h++){
-			x = la[h];
-			y = p->v6.address[h];
-			if(x == y)
-				continue;
-			if(x < y){
-				p = p->left;
-				goto next;
-			}
-			break;
-		}
-		for(h = 0; h < IPllen; h++){
-			x = la[h];
-			y = p->v6.endaddress[h];
-			if(x == y)
-				continue;
-			if(x > y){
-				p = p->right;
-				goto next;
-			}
-			break;
-		}
-		q = p;
-		p = p->mid;
-next:		;
-	}
-
-	if(q && (q->ifc == nil || q->ifcid != q->ifc->ifcid)){
-		if(q->type & Rifc) {
-			for(h = 0; h < IPllen; h++)
-				hnputl(gate+4*h, q->v6.address[h]);
-			ifc = findipifc(f, gate, q->type);
-		} else
-			ifc = findipifc(f, q->v6.gate, q->type);
-		if(ifc == nil)
-			return nil;
-		q->ifc = ifc;
-		q->ifcid = ifc->ifcid;
-	}
-	if(c != nil){
-		c->r = q;
-		c->rgen = v6routegeneration;
-	}
-
-	return q;
-}
-
-void
-routetype(int type, char *p)
-{
-	memset(p, ' ', 4);
-	p[4] = 0;
-	if(type & Rv4)
-		*p++ = '4';
-	else
-		*p++ = '6';
-	if(type & Rifc)
-		*p++ = 'i';
-	if(type & Runi)
-		*p++ = 'u';
-	else if(type & Rbcast)
-		*p++ = 'b';
-	else if(type & Rmulti)
-		*p++ = 'm';
-	if(type & Rptpt)
-		*p = 'p';
-}
-
-static char *rformat = "%-15I %-4M %-15I %4.4s %4.4s %3s\n";
-
-void
-convroute(Route *r, uchar *addr, uchar *mask, uchar *gate, char *t, int *nifc)
-{
-	int i;
-
-	if(r->type & Rv4){
-		memmove(addr, v4prefix, IPv4off);
-		hnputl(addr+IPv4off, r->v4.address);
-		memset(mask, 0xff, IPv4off);
-		hnputl(mask+IPv4off, ~(r->v4.endaddress ^ r->v4.address));
-		memmove(gate, v4prefix, IPv4off);
-		memmove(gate+IPv4off, r->v4.gate, IPv4addrlen);
-	} else {
-		for(i = 0; i < IPllen; i++){
-			hnputl(addr + 4*i, r->v6.address[i]);
-			hnputl(mask + 4*i, ~(r->v6.endaddress[i] ^ r->v6.address[i]));
-		}
-		memmove(gate, r->v6.gate, IPaddrlen);
-	}
-
-	routetype(r->type, t);
-
-	if(r->ifc)
-		*nifc = r->ifc->conv->x;
-	else
-		*nifc = -1;
-}
-
-/*
- *  this code is not in rr to reduce stack size
- */
-static void
-sprintroute(Route *r, Routewalk *rw)
-{
-	int nifc, n;
-	char t[5], *iname, ifbuf[5];
-	uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
-	char *p;
-
-	convroute(r, addr, mask, gate, t, &nifc);
-	iname = "-";
-	if(nifc != -1) {
-		iname = ifbuf;
-		snprint(ifbuf, sizeof ifbuf, "%d", nifc);
-	}
-	p = seprint(rw->p, rw->e, rformat, addr, mask, gate, t, r->tag, iname);
-	if(rw->o < 0){
-		n = p - rw->p;
-		if(n > -rw->o){
-			memmove(rw->p, rw->p-rw->o, n+rw->o);
-			rw->p = p + rw->o;
-		}
-		rw->o += n;
-	} else
-		rw->p = p;
-}
-
-/*
- *  recurse descending tree, applying the function in Routewalk
- */
-static int
-rr(Route *r, Routewalk *rw)
-{
-	int h;
-
-	if(rw->e <= rw->p)
-		return 0;
-	if(r == nil)
-		return 1;
-
-	if(rr(r->left, rw) == 0)
-		return 0;
-
-	if(r->type & Rv4)
-		h = V4H(r->v4.address);
-	else
-		h = V6H(r->v6.address);
-
-	if(h == rw->h)
-		rw->walk(r, rw);
-
-	if(rr(r->mid, rw) == 0)
-		return 0;
-
-	return rr(r->right, rw);
-}
-
-void
-ipwalkroutes(Fs *f, Routewalk *rw)
-{
-	rlock(&routelock);
-	if(rw->e > rw->p) {
-		for(rw->h = 0; rw->h < nelem(f->v4root); rw->h++)
-			if(rr(f->v4root[rw->h], rw) == 0)
-				break;
-	}
-	if(rw->e > rw->p) {
-		for(rw->h = 0; rw->h < nelem(f->v6root); rw->h++)
-			if(rr(f->v6root[rw->h], rw) == 0)
-				break;
-	}
-	runlock(&routelock);
-}
-
-long
-routeread(Fs *f, char *p, ulong offset, int n)
-{
-	Routewalk rw;
-
-	rw.p = p;
-	rw.e = p+n;
-	rw.o = -offset;
-	rw.walk = sprintroute;
-
-	ipwalkroutes(f, &rw);
-
-	return rw.p - p;
-}
-
-/*
- *  this code is not in routeflush to reduce stack size
- */
-void
-delroute(Fs *f, Route *r, int dolock)
-{
-	uchar addr[IPaddrlen];
-	uchar mask[IPaddrlen];
-	uchar gate[IPaddrlen];
-	char t[5];
-	int nifc;
-
-	convroute(r, addr, mask, gate, t, &nifc);
-	if(r->type & Rv4)
-		v4delroute(f, addr+IPv4off, mask+IPv4off, dolock);
-	else
-		v6delroute(f, addr, mask, dolock);
-}
-
-/*
- *  recurse until one route is deleted
- *    returns 0 if nothing is deleted, 1 otherwise
- */
-int
-routeflush(Fs *f, Route *r, char *tag)
-{
-	if(r == nil)
-		return 0;
-	if(routeflush(f, r->mid, tag))
-		return 1;
-	if(routeflush(f, r->left, tag))
-		return 1;
-	if(routeflush(f, r->right, tag))
-		return 1;
-	if((r->type & Rifc) == 0){
-		if(tag == nil || strncmp(tag, r->tag, sizeof(r->tag)) == 0){
-			delroute(f, r, 0);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-Route *
-iproute(Fs *fs, uchar *ip)
-{
-	if(isv4(ip))
-		return v4lookup(fs, ip+IPv4off, nil);
-	else
-		return v6lookup(fs, ip, nil);
-}
-
-static void
-printroute(Route *r)
-{
-	int nifc;
-	char t[5], *iname, ifbuf[5];
-	uchar addr[IPaddrlen], mask[IPaddrlen], gate[IPaddrlen];
-
-	convroute(r, addr, mask, gate, t, &nifc);
-	iname = "-";
-	if(nifc != -1) {
-		iname = ifbuf;
-		snprint(ifbuf, sizeof ifbuf, "%d", nifc);
-	}
-	print(rformat, addr, mask, gate, t, r->tag, iname);
-}
-
-long
-routewrite(Fs *f, Chan *c, char *p, int n)
-{
-	int h, changed;
-	char *tag;
-	Cmdbuf *cb;
-	uchar addr[IPaddrlen];
-	uchar mask[IPaddrlen];
-	uchar gate[IPaddrlen];
-	IPaux *a, *na;
-	Route *q;
-
-	cb = parsecmd(p, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-
-	if(strcmp(cb->f[0], "flush") == 0){
-		tag = cb->f[1];
-		for(h = 0; h < nelem(f->v4root); h++)
-			for(changed = 1; changed;){
-				wlock(&routelock);
-				changed = routeflush(f, f->v4root[h], tag);
-				wunlock(&routelock);
-			}
-		for(h = 0; h < nelem(f->v6root); h++)
-			for(changed = 1; changed;){
-				wlock(&routelock);
-				changed = routeflush(f, f->v6root[h], tag);
-				wunlock(&routelock);
-			}
-	} else if(strcmp(cb->f[0], "remove") == 0){
-		if(cb->nf < 3)
-			error(Ebadarg);
-		if (parseip(addr, cb->f[1]) == -1)
-			error(Ebadip);
-		parseipmask(mask, cb->f[2]);
-		if(memcmp(addr, v4prefix, IPv4off) == 0)
-			v4delroute(f, addr+IPv4off, mask+IPv4off, 1);
-		else
-			v6delroute(f, addr, mask, 1);
-	} else if(strcmp(cb->f[0], "add") == 0){
-		if(cb->nf < 4)
-			error(Ebadarg);
-		if(parseip(addr, cb->f[1]) == -1 ||
-		    parseip(gate, cb->f[3]) == -1)
-			error(Ebadip);
-		parseipmask(mask, cb->f[2]);
-		tag = "none";
-		if(c != nil){
-			a = c->aux;
-			tag = a->tag;
-		}
-		if(memcmp(addr, v4prefix, IPv4off) == 0)
-			v4addroute(f, tag, addr+IPv4off, mask+IPv4off, gate+IPv4off, 0);
-		else
-			v6addroute(f, tag, addr, mask, gate, 0);
-	} else if(strcmp(cb->f[0], "tag") == 0) {
-		if(cb->nf < 2)
-			error(Ebadarg);
-
-		a = c->aux;
-		na = newipaux(a->owner, cb->f[1]);
-		c->aux = na;
-		free(a);
-	} else if(strcmp(cb->f[0], "route") == 0) {
-		if(cb->nf < 2)
-			error(Ebadarg);
-		if (parseip(addr, cb->f[1]) == -1)
-			error(Ebadip);
-
-		q = iproute(f, addr);
-		print("%I: ", addr);
-		if(q == nil)
-			print("no route\n");
-		else
-			printroute(q);
-	}
-
-	poperror();
-	free(cb);
-	return n;
-}

+ 0 - 630
sys/src/9/ip/ipv6.c

@@ -1,630 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-#include	"ipv6.h"
-
-enum
-{
-	IP6FHDR		= 8, 		/* sizeof(Fraghdr6) */
-};
-
-#define IPV6CLASS(hdr)	(((hdr)->vcf[0]&0x0F)<<2 | ((hdr)->vcf[1]&0xF0)>>2)
-#define BLKIPVER(xp)	(((Ip6hdr*)((xp)->rp))->vcf[0] & 0xF0)
-/*
- * This sleazy macro is stolen shamelessly from ip.c, see comment there.
- */
-#define BKFG(xp)	((Ipfrag*)((xp)->base))
-
-Block*		ip6reassemble(IP*, int, Block*, Ip6hdr*);
-Fragment6*	ipfragallo6(IP*);
-void		ipfragfree6(IP*, Fragment6*);
-Block*		procopts(Block *bp);
-static Block*	procxtns(IP *ip, Block *bp, int doreasm);
-int		unfraglen(Block *bp, uchar *nexthdr, int setfh);
-
-int
-ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c)
-{
-	int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff;
-	int morefrags, blklen, rv = 0, tentative;
-	uchar *gate, nexthdr;
-	Block *xp, *nb;
-	Fraghdr6 fraghdr;
-	IP *ip;
-	Ip6hdr *eh;
-	Ipifc *ifc;
-	Route *r, *sr;
-
-	ip = f->ip;
-
-	/* Fill out the ip header */
-	eh = (Ip6hdr*)(bp->rp);
-
-	ip->stats[OutRequests]++;
-
-	/* Number of uchars in data and ip header to write */
-	len = blocklen(bp);
-
-	tentative = iptentative(f, eh->src);
-	if(tentative){
-		netlog(f, Logip, "reject tx of packet with tentative src address %I\n",
-			eh->src);
-		goto free;
-	}
-
-	if(gating){
-		chunk = nhgets(eh->ploadlen);
-		if(chunk > len){
-			ip->stats[OutDiscards]++;
-			netlog(f, Logip, "short gated packet\n");
-			goto free;
-		}
-		if(chunk + IP6HDR < len)
-			len = chunk + IP6HDR;
-	}
-
-	if(len >= IP_MAX){
-		ip->stats[OutDiscards]++;
-		netlog(f, Logip, "exceeded ip max size %I\n", eh->dst);
-		goto free;
-	}
-
-	r = v6lookup(f, eh->dst, c);
-	if(r == nil){
-//		print("no route for %I, src %I free\n", eh->dst, eh->src);
-		ip->stats[OutNoRoutes]++;
-		netlog(f, Logip, "no interface %I\n", eh->dst);
-		rv = -1;
-		goto free;
-	}
-
-	ifc = r->ifc;
-	if(r->type & (Rifc|Runi))
-		gate = eh->dst;
-	else if(r->type & (Rbcast|Rmulti)) {
-		gate = eh->dst;
-		sr = v6lookup(f, eh->src, nil);
-		if(sr && (sr->type & Runi))
-			ifc = sr->ifc;
-	}
-	else
-		gate = r->v6.gate;
-
-	if(!gating)
-		eh->vcf[0] = IP_VER6;
-	eh->ttl = ttl;
-	if(!gating) {
-		eh->vcf[0] |= tos >> 4;
-		eh->vcf[1]  = tos << 4;
-	}
-
-	if(!canrlock(ifc))
-		goto free;
-
-	if(waserror()){
-		runlock(ifc);
-		nexterror();
-	}
-
-	if(ifc->m == nil)
-		goto raise;
-
-	/* If we dont need to fragment just send it */
-	medialen = ifc->maxtu - ifc->m->hsize;
-	if(len <= medialen) {
-		hnputs(eh->ploadlen, len - IP6HDR);
-		ifc->m->bwrite(ifc, bp, V6, gate);
-		runlock(ifc);
-		poperror();
-		return 0;
-	}
-
-	if(gating && ifc->reassemble <= 0) {
-		/*
-		 * v6 intermediate nodes are not supposed to fragment pkts;
-		 * we fragment if ifc->reassemble is turned on; an exception
-		 * needed for nat.
-		 */
-		ip->stats[OutDiscards]++;
-		icmppkttoobig6(f, ifc, bp);
-		netlog(f, Logip, "%I: gated pkts not fragmented\n", eh->dst);
-		goto raise;
-	}
-
-	/* start v6 fragmentation */
-	uflen = unfraglen(bp, &nexthdr, 1);
-	if(uflen > medialen) {
-		ip->stats[FragFails]++;
-		ip->stats[OutDiscards]++;
-		netlog(f, Logip, "%I: unfragmentable part too big\n", eh->dst);
-		goto raise;
-	}
-
-	flen = len - uflen;
-	seglen = (medialen - (uflen + IP6FHDR)) & ~7;
-	if(seglen < 8) {
-		ip->stats[FragFails]++;
-		ip->stats[OutDiscards]++;
-		netlog(f, Logip, "%I: seglen < 8\n", eh->dst);
-		goto raise;
-	}
-
-	lid = incref(&ip->id6);
-	fraghdr.nexthdr = nexthdr;
-	fraghdr.res = 0;
-	hnputl(fraghdr.id, lid);
-
-	xp = bp;
-	offset = uflen;
-	while (xp && offset && offset >= BLEN(xp)) {
-		offset -= BLEN(xp);
-		xp = xp->next;
-	}
-	xp->rp += offset;
-
-	fragoff = 0;
-	morefrags = 1;
-
-	for(; fragoff < flen; fragoff += seglen) {
-		nb = allocb(uflen + IP6FHDR + seglen);
-
-		if(fragoff + seglen >= flen) {
-			seglen = flen - fragoff;
-			morefrags = 0;
-		}
-
-		hnputs(eh->ploadlen, seglen+IP6FHDR);
-		memmove(nb->wp, eh, uflen);
-		nb->wp += uflen;
-
-		hnputs(fraghdr.offsetRM, fragoff); /* last 3 bits must be 0 */
-		fraghdr.offsetRM[1] |= morefrags;
-		memmove(nb->wp, &fraghdr, IP6FHDR);
-		nb->wp += IP6FHDR;
-
-		/* Copy data */
-		chunk = seglen;
-		while (chunk) {
-			if(!xp) {
-				ip->stats[OutDiscards]++;
-				ip->stats[FragFails]++;
-				freeblist(nb);
-				netlog(f, Logip, "!xp: chunk in v6%d\n", chunk);
-				goto raise;
-			}
-			blklen = chunk;
-			if(BLEN(xp) < chunk)
-				blklen = BLEN(xp);
-			memmove(nb->wp, xp->rp, blklen);
-
-			nb->wp += blklen;
-			xp->rp += blklen;
-			chunk -= blklen;
-			if(xp->rp == xp->wp)
-				xp = xp->next;
-		}
-
-		ifc->m->bwrite(ifc, nb, V6, gate);
-		ip->stats[FragCreates]++;
-	}
-	ip->stats[FragOKs]++;
-
-raise:
-	runlock(ifc);
-	poperror();
-free:
-	freeblist(bp);
-	return rv;
-}
-
-void
-ipiput6(Fs *f, Ipifc *ifc, Block *bp)
-{
-	int hl, hop, tos, notforme, tentative;
-	uchar proto;
-	uchar v6dst[IPaddrlen];
-	IP *ip;
-	Ip6hdr *h;
-	Proto *p;
-	Route *r, *sr;
-
-	ip = f->ip;
-	ip->stats[InReceives]++;
-
-	/*
-	 *  Ensure we have all the header info in the first
-	 *  block.  Make life easier for other protocols by
-	 *  collecting up to the first 64 bytes in the first block.
-	 */
-	if(BLEN(bp) < 64) {
-		hl = blocklen(bp);
-		if(hl < IP6HDR)
-			hl = IP6HDR;
-		if(hl > 64)
-			hl = 64;
-		bp = pullupblock(bp, hl);
-		if(bp == nil)
-			return;
-	}
-
-	h = (Ip6hdr *)bp->rp;
-
-	memmove(&v6dst[0], &h->dst[0], IPaddrlen);
-	notforme = ipforme(f, v6dst) == 0;
-	tentative = iptentative(f, v6dst);
-
-	if(tentative && h->proto != ICMPv6) {
-		print("ipv6 non-icmp tentative addr %I, drop\n", v6dst);
-		freeblist(bp);
-		return;
-	}
-
-	/* Check header version */
-	if(BLKIPVER(bp) != IP_VER6) {
-		ip->stats[InHdrErrors]++;
-		netlog(f, Logip, "ip: bad version %ux\n", (h->vcf[0]&0xF0)>>2);
-		freeblist(bp);
-		return;
-	}
-
-	/* route */
-	if(notforme) {
-		if(!ip->iprouting){
-			freeblist(bp);
-			return;
-		}
-
-		/* don't forward to link-local destinations */
-		if(islinklocal(h->dst) ||
-		   (isv6mcast(h->dst) && (h->dst[1]&0xF) <= Link_local_scop)){
-			ip->stats[OutDiscards]++;
-			freeblist(bp);
-			return;
-		}
-
-		/* don't forward to source's network */
-		sr = v6lookup(f, h->src, nil);
-		r  = v6lookup(f, h->dst, nil);
-
-		if(r == nil || sr == r){
-			ip->stats[OutDiscards]++;
-			freeblist(bp);
-			return;
-		}
-
-		/* don't forward if packet has timed out */
-		hop = h->ttl;
-		if(hop < 1) {
-			ip->stats[InHdrErrors]++;
-			icmpttlexceeded6(f, ifc, bp);
-			freeblist(bp);
-			return;
-		}
-
-		/* process headers & reassemble if the interface expects it */
-		bp = procxtns(ip, bp, r->ifc->reassemble);
-		if(bp == nil)
-			return;
-
-		ip->stats[ForwDatagrams]++;
-		h = (Ip6hdr *)bp->rp;
-		tos = IPV6CLASS(h);
-		hop = h->ttl;
-		ipoput6(f, bp, 1, hop-1, tos, nil);
-		return;
-	}
-
-	/* reassemble & process headers if needed */
-	bp = procxtns(ip, bp, 1);
-	if(bp == nil)
-		return;
-
-	h = (Ip6hdr *) (bp->rp);
-	proto = h->proto;
-	p = Fsrcvpcol(f, proto);
-	if(p && p->rcv) {
-		ip->stats[InDelivers]++;
-		(*p->rcv)(p, ifc, bp);
-		return;
-	}
-
-	ip->stats[InDiscards]++;
-	ip->stats[InUnknownProtos]++;
-	freeblist(bp);
-}
-
-/*
- * ipfragfree6 - copied from ipfragfree4 - assume hold fraglock6
- */
-void
-ipfragfree6(IP *ip, Fragment6 *frag)
-{
-	Fragment6 *fl, **l;
-
-	if(frag->blist)
-		freeblist(frag->blist);
-
-	memset(frag->src, 0, IPaddrlen);
-	frag->id = 0;
-	frag->blist = nil;
-
-	l = &ip->flisthead6;
-	for(fl = *l; fl; fl = fl->next) {
-		if(fl == frag) {
-			*l = frag->next;
-			break;
-		}
-		l = &fl->next;
-	}
-
-	frag->next = ip->fragfree6;
-	ip->fragfree6 = frag;
-}
-
-/*
- * ipfragallo6 - copied from ipfragalloc4
- */
-Fragment6*
-ipfragallo6(IP *ip)
-{
-	Fragment6 *f;
-
-	while(ip->fragfree6 == nil) {
-		/* free last entry on fraglist */
-		for(f = ip->flisthead6; f->next; f = f->next)
-			;
-		ipfragfree6(ip, f);
-	}
-	f = ip->fragfree6;
-	ip->fragfree6 = f->next;
-	f->next = ip->flisthead6;
-	ip->flisthead6 = f;
-	f->age = NOW + 30000;
-
-	return f;
-}
-
-static Block*
-procxtns(IP *ip, Block *bp, int doreasm)
-{
-	int offset;
-	uchar proto;
-	Ip6hdr *h;
-
-	h = (Ip6hdr *)bp->rp;
-	offset = unfraglen(bp, &proto, 0);
-
-	if(proto == FH && doreasm != 0) {
-		bp = ip6reassemble(ip, offset, bp, h);
-		if(bp == nil)
-			return nil;
-		offset = unfraglen(bp, &proto, 0);
-	}
-
-	if(proto == DOH || offset > IP6HDR)
-		bp = procopts(bp);
-	return bp;
-}
-
-/*
- * returns length of "Unfragmentable part", i.e., sum of lengths of ipv6 hdr,
- * hop-by-hop & routing headers if present; *nexthdr is set to nexthdr value
- * of the last header in the "Unfragmentable part"; if setfh != 0, nexthdr
- * field of the last header in the "Unfragmentable part" is set to FH.
- */
-int
-unfraglen(Block *bp, uchar *nexthdr, int setfh)
-{
-	uchar *p, *q;
-	int ufl, hs;
-
-	p = bp->rp;
-	q = p+6;   /* proto, = p+sizeof(Ip6hdr.vcf)+sizeof(Ip6hdr.ploadlen) */
-	*nexthdr = *q;
-	ufl = IP6HDR;
-	p += ufl;
-
-	while (*nexthdr == HBH || *nexthdr == RH) {
-		*nexthdr = *p;
-		hs = ((int)*(p+1) + 1) * 8;
-		ufl += hs;
-		q = p;
-		p += hs;
-	}
-
-	if(*nexthdr == FH)
-		*q = *p;
-	if(setfh)
-		*q = FH;
-	return ufl;
-}
-
-Block*
-procopts(Block *bp)
-{
-	return bp;
-}
-
-Block*
-ip6reassemble(IP* ip, int uflen, Block* bp, Ip6hdr* ih)
-{
-	int fend, offset, ovlap, len, fragsize, pktposn;
-	uint id;
-	uchar src[IPaddrlen], dst[IPaddrlen];
-	Block *bl, **l, *last, *prev;
-	Fraghdr6 *fraghdr;
-	Fragment6 *f, *fnext;
-
-	fraghdr = (Fraghdr6 *)(bp->rp + uflen);
-	memmove(src, ih->src, IPaddrlen);
-	memmove(dst, ih->dst, IPaddrlen);
-	id = nhgetl(fraghdr->id);
-	offset = nhgets(fraghdr->offsetRM) & ~7;
-
-	/*
-	 *  block lists are too hard, pullupblock into a single block
-	 */
-	if(bp->next){
-		bp = pullupblock(bp, blocklen(bp));
-		ih = (Ip6hdr *)bp->rp;
-	}
-
-	qlock(&ip->fraglock6);
-
-	/*
-	 *  find a reassembly queue for this fragment
-	 */
-	for(f = ip->flisthead6; f; f = fnext){
-		fnext = f->next;
-		if(ipcmp(f->src, src)==0 && ipcmp(f->dst, dst)==0 && f->id == id)
-			break;
-		if(f->age < NOW){
-			ip->stats[ReasmTimeout]++;
-			ipfragfree6(ip, f);
-		}
-	}
-
-	/*
-	 *  if this isn't a fragmented packet, accept it
-	 *  and get rid of any fragments that might go
-	 *  with it.
-	 */
-	if(nhgets(fraghdr->offsetRM) == 0) {	/* 1st frag is also last */
-		if(f) {
-			ipfragfree6(ip, f);
-			ip->stats[ReasmFails]++;
-		}
-		qunlock(&ip->fraglock6);
-		return bp;
-	}
-
-	if(bp->base+IPFRAGSZ >= bp->rp){
-		bp = padblock(bp, IPFRAGSZ);
-		bp->rp += IPFRAGSZ;
-	}
-
-	BKFG(bp)->foff = offset;
-	BKFG(bp)->flen = nhgets(ih->ploadlen) + IP6HDR - uflen - IP6FHDR;
-
-	/* First fragment allocates a reassembly queue */
-	if(f == nil) {
-		f = ipfragallo6(ip);
-		f->id = id;
-		memmove(f->src, src, IPaddrlen);
-		memmove(f->dst, dst, IPaddrlen);
-
-		f->blist = bp;
-
-		qunlock(&ip->fraglock6);
-		ip->stats[ReasmReqds]++;
-		return nil;
-	}
-
-	/*
-	 *  find the new fragment's position in the queue
-	 */
-	prev = nil;
-	l = &f->blist;
-	bl = f->blist;
-	while(bl != nil && BKFG(bp)->foff > BKFG(bl)->foff) {
-		prev = bl;
-		l = &bl->next;
-		bl = bl->next;
-	}
-
-	/* Check overlap of a previous fragment - trim away as necessary */
-	if(prev) {
-		ovlap = BKFG(prev)->foff + BKFG(prev)->flen - BKFG(bp)->foff;
-		if(ovlap > 0) {
-			if(ovlap >= BKFG(bp)->flen) {
-				freeblist(bp);
-				qunlock(&ip->fraglock6);
-				return nil;
-			}
-			BKFG(prev)->flen -= ovlap;
-		}
-	}
-
-	/* Link onto assembly queue */
-	bp->next = *l;
-	*l = bp;
-
-	/* Check to see if succeeding segments overlap */
-	if(bp->next) {
-		l = &bp->next;
-		fend = BKFG(bp)->foff + BKFG(bp)->flen;
-
-		/* Take completely covered segments out */
-		while(*l) {
-			ovlap = fend - BKFG(*l)->foff;
-			if(ovlap <= 0)
-				break;
-			if(ovlap < BKFG(*l)->flen) {
-				BKFG(*l)->flen -= ovlap;
-				BKFG(*l)->foff += ovlap;
-				/* move up ih hdrs */
-				memmove((*l)->rp + ovlap, (*l)->rp, uflen);
-				(*l)->rp += ovlap;
-				break;
-			}
-			last = (*l)->next;
-			(*l)->next = nil;
-			freeblist(*l);
-			*l = last;
-		}
-	}
-
-	/*
-	 *  look for a complete packet.  if we get to a fragment
-	 *  with the trailing bit of fraghdr->offsetRM[1] set, we're done.
-	 */
-	pktposn = 0;
-	for(bl = f->blist; bl && BKFG(bl)->foff == pktposn; bl = bl->next) {
-		fraghdr = (Fraghdr6 *)(bl->rp + uflen);
-		if((fraghdr->offsetRM[1] & 1) == 0) {
-			bl = f->blist;
-
-			/* get rid of frag header in first fragment */
-			memmove(bl->rp + IP6FHDR, bl->rp, uflen);
-			bl->rp += IP6FHDR;
-			len = nhgets(((Ip6hdr*)bl->rp)->ploadlen) - IP6FHDR;
-			bl->wp = bl->rp + len + IP6HDR;
-			/*
-			 * Pullup all the fragment headers and
-			 * return a complete packet
-			 */
-			for(bl = bl->next; bl; bl = bl->next) {
-				fragsize = BKFG(bl)->flen;
-				len += fragsize;
-				bl->rp += uflen + IP6FHDR;
-				bl->wp = bl->rp + fragsize;
-			}
-
-			bl = f->blist;
-			f->blist = nil;
-			ipfragfree6(ip, f);
-			ih = (Ip6hdr*)bl->rp;
-			hnputs(ih->ploadlen, len);
-			qunlock(&ip->fraglock6);
-			ip->stats[ReasmOKs]++;
-			return bl;
-		}
-		pktposn += BKFG(bl)->flen;
-	}
-	qunlock(&ip->fraglock6);
-	return nil;
-}

+ 0 - 193
sys/src/9/ip/ipv6.h

@@ -1,193 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Internet Protocol Version 6
- *
- * rfc2460 defines the protocol, rfc2461 neighbour discovery, and
- * rfc2462 address autoconfiguration.  rfc4443 defines ICMP; was rfc2463.
- * rfc4291 defines the address architecture (including prefices), was rfc3513.
- * rfc4007 defines the scoped address architecture.
- *
- * global unicast is anything but unspecified (::), loopback (::1),
- * multicast (ff00::/8), and link-local unicast (fe80::/10).
- *
- * site-local (fec0::/10) is now deprecated, originally by rfc3879.
- *
- * Unique Local IPv6 Unicast Addresses are defined by rfc4193.
- * prefix is fc00::/7, scope is global, routing is limited to roughly a site.
- */
-#define isv6mcast(addr)	  ((addr)[0] == 0xff)
-#define islinklocal(addr) ((addr)[0] == 0xfe && ((addr)[1] & 0xc0) == 0x80)
-
-#define optexsts(np)	(nhgets((np)->ploadlen) > 24)
-#define issmcast(addr)	(memcmp((addr), v6solicitednode, 13) == 0)
-
-enum {				/* Header Types */
-	HBH		= 0,	/* hop-by-hop multicast routing protocol */
-	ICMP		= 1,
-	IGMP		= 2,
-	GGP		= 3,
-	IPINIP		= 4,
-	ST		= 5,
-	TCP		= 6,
-	UDP		= 17,
-	ISO_TP4		= 29,
-	RH		= 43,
-	FH		= 44,
-	IDRP		= 45,
-	RSVP		= 46,
-	AH		= 51,
-	ESP		= 52,
-	ICMPv6		= 58,
-	NNH		= 59,
-	DOH		= 60,
-	ISO_IP		= 80,
-	IGRP		= 88,
-	OSPF		= 89,
-
-	Maxhdrtype	= 256,
-};
-
-enum {
-	/* multicast flags and scopes */
-
-//	Well_known_flg	= 0,
-//	Transient_flg	= 1,
-
-//	Interface_local_scop = 1,
-	Link_local_scop	= 2,
-//	Site_local_scop	= 5,
-//	Org_local_scop	= 8,
-	Global_scop	= 14,
-
-	/* various prefix lengths */
-	SOLN_PREF_LEN	= 13,
-
-	/* icmpv6 unreachability codes */
-	Icmp6_no_route		= 0,
-	Icmp6_ad_prohib		= 1,
-	Icmp6_out_src_scope	= 2,
-	Icmp6_adr_unreach	= 3,
-	Icmp6_port_unreach	= 4,
-	Icmp6_gress_src_fail	= 5,
-	Icmp6_rej_route		= 6,
-	Icmp6_unknown		= 7,  /* our own invention for internal use */
-
-	/* various flags & constants */
-	v6MINTU		= 1280,
-	HOP_LIMIT	= 255,
-	IP6HDR		= 40,		/* sizeof(Ip6hdr) = 8 + 2*16 */
-
-	/* option types */
-
-	/* neighbour discovery */
-	SRC_LLADDR	= 1,
-	TARGET_LLADDR	= 2,
-	PREFIX_INFO	= 3,
-	REDIR_HEADER	= 4,
-	MTU_OPTION	= 5,
-	/* new since rfc2461; see iana.org/assignments/icmpv6-parameters */
-	V6nd_home	= 8,
-	V6nd_srcaddrs	= 9,		/* rfc3122 */
-	V6nd_ip		= 17,
-	/* /lib/rfc/drafts/draft-jeong-dnsop-ipv6-dns-discovery-12.txt */
-	V6nd_rdns	= 25,
-	/* plan 9 extensions */
-	V6nd_9fs	= 250,
-	V6nd_9auth	= 251,
-
-	SRC_UNSPEC	= 0,
-	SRC_UNI		= 1,
-	TARG_UNI	= 2,
-	TARG_MULTI	= 3,
-
-	Tunitent	= 1,
-	Tuniproxy	= 2,
-	Tunirany	= 3,
-
-	/* Node constants */
-	MAX_MULTICAST_SOLICIT	= 3,
-	RETRANS_TIMER		= 1000,
-};
-
-typedef struct Ip6hdr	Ip6hdr;
-typedef struct Opthdr	Opthdr;
-typedef struct Routinghdr Routinghdr;
-typedef struct Fraghdr6	Fraghdr6;
-
-/* we do this in case there's padding at the end of Ip6hdr */
-#define IPV6HDR \
-	uchar	vcf[4];		/* version:4, traffic class:8, flow label:20 */\
-	uchar	ploadlen[2];	/* payload length: packet length - 40 */ \
-	uchar	proto;		/* next header type */ \
-	uchar	ttl;		/* hop limit */ \
-	uchar	src[IPaddrlen]; \
-	uchar	dst[IPaddrlen]
-
-struct	Ip6hdr {
-	IPV6HDR;
-	uchar	payload[];
-};
-
-struct	Opthdr {		/* unused */
-	uchar	nexthdr;
-	uchar	len;
-};
-
-/*
- * Beware routing header type 0 (loose source routing); see
- * http://www.secdev.org/conf/IPv6_RH_security-csw07.pdf.
- * Type 1 is unused.  Type 2 is for MIPv6 (mobile IPv6) filtering
- * against type 0 header.
- */
-struct	Routinghdr {		/* unused */
-	uchar	nexthdr;
-	uchar	len;
-	uchar	rtetype;
-	uchar	segrem;
-};
-
-struct	Fraghdr6 {
-	uchar	nexthdr;
-	uchar	res;
-	uchar	offsetRM[2];	/* Offset, Res, M flag */
-	uchar	id[4];
-};
-
-extern uchar v6allnodesN[IPaddrlen];
-extern uchar v6allnodesL[IPaddrlen];
-extern uchar v6allroutersN[IPaddrlen];
-extern uchar v6allroutersL[IPaddrlen];
-extern uchar v6allnodesNmask[IPaddrlen];
-extern uchar v6allnodesLmask[IPaddrlen];
-extern uchar v6solicitednode[IPaddrlen];
-extern uchar v6solicitednodemask[IPaddrlen];
-extern uchar v6Unspecified[IPaddrlen];
-extern uchar v6loopback[IPaddrlen];
-extern uchar v6loopbackmask[IPaddrlen];
-extern uchar v6linklocal[IPaddrlen];
-extern uchar v6linklocalmask[IPaddrlen];
-extern uchar v6multicast[IPaddrlen];
-extern uchar v6multicastmask[IPaddrlen];
-
-extern int v6llpreflen;
-extern int v6mcpreflen;
-extern int v6snpreflen;
-extern int v6aNpreflen;
-extern int v6aLpreflen;
-
-extern int ReTransTimer;
-
-void ipv62smcast(uchar *, uchar *);
-void icmpns(Fs *f, uchar* src, int suni, uchar* targ, int tuni, uchar* mac);
-void icmpna(Fs *f, uchar* src, uchar* dst, uchar* targ, uchar* mac, uchar flags);
-void icmpttlexceeded6(Fs *f, Ipifc *ifc, Block *bp);
-void icmppkttoobig6(Fs *f, Ipifc *ifc, Block *bp);
-void icmphostunr(Fs *f, Ipifc *ifc, Block *bp, int code, int free);

+ 0 - 129
sys/src/9/ip/loopbackmedium.c

@@ -1,129 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-enum
-{
-	Maxtu=	16*1024,
-};
-
-typedef struct LB LB;
-struct LB
-{
-	Proc	*readp;
-	Queue	*q;
-	Fs	*f;
-};
-
-static void loopbackread(void *a);
-
-static void
-loopbackbind(Ipifc *ifc, int, char**)
-{
-	LB *lb;
-
-	lb = smalloc(sizeof(*lb));
-	lb->f = ifc->conv->p->f;
-	lb->q = qopen(1024*1024, Qmsg, nil, nil);
-	ifc->arg = lb;
-	ifc->mbps = 1000;
-
-	kproc("loopbackread", loopbackread, ifc);
-
-}
-
-static void
-loopbackunbind(Ipifc *ifc)
-{
-	LB *lb = ifc->arg;
-
-	if(lb->readp)
-		postnote(lb->readp, 1, "unbind", 0);
-
-	/* wait for reader to die */
-	while(lb->readp != 0)
-		tsleep(&up->sleep, return0, 0, 300);
-
-	/* clean up */
-	qfree(lb->q);
-	free(lb);
-}
-
-static void
-loopbackbwrite(Ipifc *ifc, Block *bp, int, uchar*)
-{
-	LB *lb;
-
-	lb = ifc->arg;
-	if(qpass(lb->q, bp) < 0)
-		ifc->outerr++;
-	ifc->out++;
-}
-
-static void
-loopbackread(void *a)
-{
-	Ipifc *ifc;
-	Block *bp;
-	LB *lb;
-
-	ifc = a;
-	lb = ifc->arg;
-	lb->readp = up;	/* hide identity under a rock for unbind */
-	if(waserror()){
-		lb->readp = 0;
-		pexit("hangup", 1);
-	}
-	for(;;){
-		bp = qbread(lb->q, Maxtu);
-		if(bp == nil)
-			continue;
-		ifc->in++;
-		if(!canrlock(ifc)){
-			freeb(bp);
-			continue;
-		}
-		if(waserror()){
-			runlock(ifc);
-			nexterror();
-		}
-		if(ifc->lifc == nil)
-			freeb(bp);
-		else
-			ipiput4(lb->f, ifc, bp);
-		runlock(ifc);
-		poperror();
-	}
-}
-
-Medium loopbackmedium =
-{
-.hsize=		0,
-.mintu=		0,
-.maxtu=		Maxtu,
-.maclen=	0,
-.name=		"loopback",
-.bind=		loopbackbind,
-.unbind=	loopbackunbind,
-.bwrite=	loopbackbwrite,
-};
-
-void
-loopbackmediumlink(void)
-{
-	addipmedium(&loopbackmedium);
-}

+ 0 - 162
sys/src/9/ip/netdevmedium.c

@@ -1,162 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-static void	netdevbind(Ipifc *ifc, int argc, char **argv);
-static void	netdevunbind(Ipifc *ifc);
-static void	netdevbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
-static void	netdevread(void *a);
-
-typedef struct	Netdevrock Netdevrock;
-struct Netdevrock
-{
-	Fs	*f;		/* file system we belong to */
-	Proc	*readp;		/* reading process */
-	Chan	*mchan;		/* Data channel */
-};
-
-Medium netdevmedium =
-{
-.name=		"netdev",
-.hsize=		0,
-.mintu=	0,
-.maxtu=	64000,
-.maclen=	0,
-.bind=		netdevbind,
-.unbind=	netdevunbind,
-.bwrite=	netdevbwrite,
-.unbindonclose=	0,
-};
-
-/*
- *  called to bind an IP ifc to a generic network device
- *  called with ifc qlock'd
- */
-static void
-netdevbind(Ipifc *ifc, int argc, char **argv)
-{
-	Chan *mchan;
-	Netdevrock *er;
-
-	if(argc < 2)
-		error(Ebadarg);
-
-	mchan = namec(argv[2], Aopen, ORDWR, 0);
-
-	er = smalloc(sizeof(*er));
-	er->mchan = mchan;
-	er->f = ifc->conv->p->f;
-
-	ifc->arg = er;
-
-	kproc("netdevread", netdevread, ifc);
-}
-
-/*
- *  called with ifc wlock'd
- */
-static void
-netdevunbind(Ipifc *ifc)
-{
-	Netdevrock *er = ifc->arg;
-
-	if(er->readp != nil)
-		postnote(er->readp, 1, "unbind", 0);
-
-	/* wait for readers to die */
-	while(er->readp != nil)
-		tsleep(&up->sleep, return0, 0, 300);
-
-	if(er->mchan != nil)
-		cclose(er->mchan);
-
-	free(er);
-}
-
-/*
- *  called by ipoput with a single block to write
- */
-static void
-netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)
-{
-	Netdevrock *er = ifc->arg;
-
-	if(bp->next)
-		bp = concatblock(bp);
-	if(BLEN(bp) < ifc->mintu)
-		bp = adjustblock(bp, ifc->mintu);
-
-	devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
-	ifc->out++;
-}
-
-/*
- *  process to read from the device
- */
-static void
-netdevread(void *a)
-{
-	Ipifc *ifc;
-	Block *bp;
-	Netdevrock *er;
-	char *argv[1];
-
-	ifc = a;
-	er = ifc->arg;
-	er->readp = up;	/* hide identity under a rock for unbind */
-	if(waserror()){
-		er->readp = nil;
-		pexit("hangup", 1);
-	}
-	for(;;){
-		bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
-		if(bp == nil){
-			/*
-			 * get here if mchan is a pipe and other side hangs up
-			 * clean up this interface & get out
-ZZZ is this a good idea?
-			 */
-			poperror();
-			er->readp = nil;
-			argv[0] = "unbind";
-			if(!waserror())
-				ifc->conv->p->ctl(ifc->conv, argv, 1);
-			pexit("hangup", 1);
-		}
-		if(!canrlock(ifc)){
-			freeb(bp);
-			continue;
-		}
-		if(waserror()){
-			runlock(ifc);
-			nexterror();
-		}
-		ifc->in++;
-		if(ifc->lifc == nil)
-			freeb(bp);
-		else
-			ipiput4(er->f, ifc, bp);
-		runlock(ifc);
-		poperror();
-	}
-}
-
-void
-netdevmediumlink(void)
-{
-	addipmedium(&netdevmedium);
-}

+ 0 - 273
sys/src/9/ip/netlog.c

@@ -1,273 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"../ip/ip.h"
-
-enum {
-	Nlog		= 16*1024,
-};
-
-/*
- *  action log
- */
-struct Netlog {
-	Lock;
-	int	opens;
-	char*	buf;
-	char	*end;
-	char	*rptr;
-	int	len;
-
-	int	logmask;			/* mask of things to debug */
-	uchar	iponly[IPaddrlen];		/* ip address to print debugging for */
-	int	iponlyset;
-
-	QLock;
-	Rendez;
-};
-
-typedef struct Netlogflag {
-	char*	name;
-	int	mask;
-} Netlogflag;
-
-static Netlogflag flags[] =
-{
-	{ "ppp",	Logppp, },
-	{ "ip",		Logip, },
-	{ "fs",		Logfs, },
-	{ "tcp",	Logtcp, },
-	{ "icmp",	Logicmp, },
-	{ "udp",	Logudp, },
-	{ "compress",	Logcompress, },
-	{ "gre",	Loggre, },
-	{ "tcpwin",	Logtcp|Logtcpwin, },
-	{ "tcprxmt",	Logtcp|Logtcprxmt, },
-	{ "udpmsg",	Logudp|Logudpmsg, },
-	{ "ipmsg",	Logip|Logipmsg, },
-	{ "esp",	Logesp, },
-	{ nil,		0, },
-};
-
-char Ebadnetctl[] = "too few arguments for netlog control message";
-
-enum
-{
-	CMset,
-	CMclear,
-	CMonly,
-};
-
-static
-Cmdtab routecmd[] = {
-	CMset,		"set",		0,
-	CMclear,	"clear",	0,
-	CMonly,		"only",		0,
-};
-
-void
-netloginit(Fs *f)
-{
-	f->alog = smalloc(sizeof(Netlog));
-}
-
-void
-netlogopen(Fs *f)
-{
-	lock(f->alog);
-	if(waserror()){
-		unlock(f->alog);
-		nexterror();
-	}
-	if(f->alog->opens == 0){
-		if(f->alog->buf == nil)
-			f->alog->buf = malloc(Nlog);
-		if(f->alog->buf == nil)
-			error(Enomem);
-		f->alog->rptr = f->alog->buf;
-		f->alog->end = f->alog->buf + Nlog;
-	}
-	f->alog->opens++;
-	unlock(f->alog);
-	poperror();
-}
-
-void
-netlogclose(Fs *f)
-{
-	lock(f->alog);
-	if(waserror()){
-		unlock(f->alog);
-		nexterror();
-	}
-	f->alog->opens--;
-	if(f->alog->opens == 0){
-		free(f->alog->buf);
-		f->alog->buf = nil;
-	}
-	unlock(f->alog);
-	poperror();
-}
-
-static int
-netlogready(void *a)
-{
-	Fs *f = a;
-
-	return f->alog->len;
-}
-
-long
-netlogread(Fs *f, void *a, ulong, long n)
-{
-	int i, d;
-	char *p, *rptr;
-
-	qlock(f->alog);
-	if(waserror()){
-		qunlock(f->alog);
-		nexterror();
-	}
-
-	for(;;){
-		lock(f->alog);
-		if(f->alog->len){
-			if(n > f->alog->len)
-				n = f->alog->len;
-			d = 0;
-			rptr = f->alog->rptr;
-			f->alog->rptr += n;
-			if(f->alog->rptr >= f->alog->end){
-				d = f->alog->rptr - f->alog->end;
-				f->alog->rptr = f->alog->buf + d;
-			}
-			f->alog->len -= n;
-			unlock(f->alog);
-
-			i = n-d;
-			p = a;
-			memmove(p, rptr, i);
-			memmove(p+i, f->alog->buf, d);
-			break;
-		}
-		else
-			unlock(f->alog);
-
-		sleep(f->alog, netlogready, f);
-	}
-
-	qunlock(f->alog);
-	poperror();
-
-	return n;
-}
-
-void
-netlogctl(Fs *f, char* s, int n)
-{
-	int i, set;
-	Netlogflag *fp;
-	Cmdbuf *cb;
-	Cmdtab *ct;
-
-	cb = parsecmd(s, n);
-	if(waserror()){
-		free(cb);
-		nexterror();
-	}
-
-	if(cb->nf < 2)
-		error(Ebadnetctl);
-
-	ct = lookupcmd(cb, routecmd, nelem(routecmd));
-
-	SET(set);
-
-	switch(ct->index){
-	case CMset:
-		set = 1;
-		break;
-
-	case CMclear:
-		set = 0;
-		break;
-
-	case CMonly:
-		parseip(f->alog->iponly, cb->f[1]);
-		if(ipcmp(f->alog->iponly, IPnoaddr) == 0)
-			f->alog->iponlyset = 0;
-		else
-			f->alog->iponlyset = 1;
-		free(cb);
-		poperror();
-		return;
-
-	default:
-		cmderror(cb, "unknown netlog control message");
-	}
-
-	for(i = 1; i < cb->nf; i++){
-		for(fp = flags; fp->name; fp++)
-			if(strcmp(fp->name, cb->f[i]) == 0)
-				break;
-		if(fp->name == nil)
-			continue;
-		if(set)
-			f->alog->logmask |= fp->mask;
-		else
-			f->alog->logmask &= ~fp->mask;
-	}
-
-	free(cb);
-	poperror();
-}
-
-void
-netlog(Fs *f, int mask, char *fmt, ...)
-{
-	char buf[256], *t, *fp;
-	int i, n;
-	va_list arg;
-
-	if(!(f->alog->logmask & mask))
-		return;
-
-	if(f->alog->opens == 0)
-		return;
-
-	va_start(arg, fmt);
-	n = vseprint(buf, buf+sizeof(buf), fmt, arg) - buf;
-	va_end(arg);
-
-	lock(f->alog);
-	i = f->alog->len + n - Nlog;
-	if(i > 0){
-		f->alog->len -= i;
-		f->alog->rptr += i;
-		if(f->alog->rptr >= f->alog->end)
-			f->alog->rptr = f->alog->buf + (f->alog->rptr - f->alog->end);
-	}
-	t = f->alog->rptr + f->alog->len;
-	fp = buf;
-	f->alog->len += n;
-	while(n-- > 0){
-		if(t >= f->alog->end)
-			t = f->alog->buf + (t - f->alog->end);
-		*t++ = *fp++;
-	}
-	unlock(f->alog);
-
-	wakeup(f->alog);
-}

+ 0 - 48
sys/src/9/ip/nullmedium.c

@@ -1,48 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-static void
-nullbind(Ipifc*, int, char**)
-{
-	error("cannot bind null device");
-}
-
-static void
-nullunbind(Ipifc*)
-{
-}
-
-static void
-nullbwrite(Ipifc*, Block*, int, uchar*)
-{
-	error("nullbwrite");
-}
-
-Medium nullmedium =
-{
-.name=		"null",
-.bind=		nullbind,
-.unbind=	nullunbind,
-.bwrite=	nullbwrite,
-};
-
-void
-nullmediumlink(void)
-{
-	addipmedium(&nullmedium);
-}

+ 0 - 88
sys/src/9/ip/pktmedium.c

@@ -1,88 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include "ip.h"
-
-
-static void	pktbind(Ipifc*, int, char**);
-static void	pktunbind(Ipifc*);
-static void	pktbwrite(Ipifc*, Block*, int, uchar*);
-static void	pktin(Fs*, Ipifc*, Block*);
-
-Medium pktmedium =
-{
-.name=		"pkt",
-.hsize=		14,
-.mintu=		40,
-.maxtu=		4*1024,
-.maclen=	6,
-.bind=		pktbind,
-.unbind=	pktunbind,
-.bwrite=	pktbwrite,
-.pktin=		pktin,
-};
-
-/*
- *  called to bind an IP ifc to an ethernet device
- *  called with ifc wlock'd
- */
-static void
-pktbind(Ipifc*, int argc, char **argv)
-{
-	USED(argc, argv);
-}
-
-/*
- *  called with ifc wlock'd
- */
-static void
-pktunbind(Ipifc*)
-{
-}
-
-/*
- *  called by ipoput with a single packet to write
- */
-static void
-pktbwrite(Ipifc *ifc, Block *bp, int, uchar*)
-{
-	/* enqueue onto the conversation's rq */
-	bp = concatblock(bp);
-	if(ifc->conv->snoopers.ref > 0)
-		qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
-	qpass(ifc->conv->rq, bp);
-}
-
-/*
- *  called with ifc rlocked when someone write's to 'data'
- */
-static void
-pktin(Fs *f, Ipifc *ifc, Block *bp)
-{
-	if(ifc->lifc == nil)
-		freeb(bp);
-	else {
-		if(ifc->conv->snoopers.ref > 0)
-			qpass(ifc->conv->sq, copyblock(bp, BLEN(bp)));
-		ipiput4(f, ifc, bp);
-	}
-}
-
-void
-pktmediumlink(void)
-{
-	addipmedium(&pktmedium);
-}

+ 0 - 81
sys/src/9/ip/ptclbsum.c

@@ -1,81 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-#include	"ip.h"
-
-static	short	endian	= 1;
-static	uchar*	aendian	= (uchar*)&endian;
-#define	LITTLE	*aendian
-
-ushort
-ptclbsum(uchar *addr, int len)
-{
-	ulong losum, hisum, mdsum, x;
-	ulong t1, t2;
-
-	losum = 0;
-	hisum = 0;
-	mdsum = 0;
-
-	x = 0;
-	if((ulong)addr & 1) {
-		if(len) {
-			hisum += addr[0];
-			len--;
-			addr++;
-		}
-		x = 1;
-	}
-	while(len >= 16) {
-		t1 = *(ushort*)(addr+0);
-		t2 = *(ushort*)(addr+2);	mdsum += t1;
-		t1 = *(ushort*)(addr+4);	mdsum += t2;
-		t2 = *(ushort*)(addr+6);	mdsum += t1;
-		t1 = *(ushort*)(addr+8);	mdsum += t2;
-		t2 = *(ushort*)(addr+10);	mdsum += t1;
-		t1 = *(ushort*)(addr+12);	mdsum += t2;
-		t2 = *(ushort*)(addr+14);	mdsum += t1;
-		mdsum += t2;
-		len -= 16;
-		addr += 16;
-	}
-	while(len >= 2) {
-		mdsum += *(ushort*)addr;
-		len -= 2;
-		addr += 2;
-	}
-	if(x) {
-		if(len)
-			losum += addr[0];
-		if(LITTLE)
-			losum += mdsum;
-		else
-			hisum += mdsum;
-	} else {
-		if(len)
-			hisum += addr[0];
-		if(LITTLE)
-			hisum += mdsum;
-		else
-			losum += mdsum;
-	}
-
-	losum += hisum >> 8;
-	losum += (hisum & 0xff) << 8;
-	while(hisum = losum>>16)
-		losum = hisum + (losum & 0xffff);
-
-	return losum & 0xffff;
-}

+ 0 - 1065
sys/src/9/ip/rudp.c

@@ -1,1065 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- *  Reliable User Datagram Protocol, currently only for IPv4.
- *  This protocol is compatible with UDP's packet format.
- *  It could be done over UDP if need be.
- */
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-
-#define DEBUG	0
-#define DPRINT if(DEBUG)print
-
-#define SEQDIFF(a,b) ( (a)>=(b)?\
-			(a)-(b):\
-			0xffffffffUL-((b)-(a)) )
-#define INSEQ(a,start,end) ( (start)<=(end)?\
-				((a)>(start)&&(a)<=(end)):\
-				((a)>(start)||(a)<=(end)) )
-#define UNACKED(r) SEQDIFF(r->sndseq, r->ackrcvd)
-#define NEXTSEQ(a) ( (a)+1 == 0 ? 1 : (a)+1 )
-
-enum
-{
-	UDP_PHDRSIZE	= 12,	/* pseudo header */
-//	UDP_HDRSIZE	= 20,	/* pseudo header + udp header */
-	UDP_RHDRSIZE	= 36,	/* pseudo header + udp header + rudp header */
-	UDP_IPHDR	= 8,	/* ip header */
-	IP_UDPPROTO	= 254,
-	UDP_USEAD7	= 52,	/* size of new ipv6 headers struct */
-
-	Rudprxms	= 200,
-	Rudptickms	= 50,
-	Rudpmaxxmit	= 10,
-	Maxunacked	= 100,
-};
-
-#define Hangupgen	0xffffffff	/* used only in hangup messages */
-
-typedef struct Udphdr Udphdr;
-struct Udphdr
-{
-	/* ip header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* pseudo header starts here */
-	uchar	Unused;
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-
-	/* udp header */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Rudphdr Rudphdr;
-struct Rudphdr
-{
-	/* ip header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-
-	/* pseudo header starts here */
-	uchar	Unused;
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[4];	/* Ip source */
-	uchar	udpdst[4];	/* Ip destination */
-
-	/* udp header */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length (includes rudp header) */
-	uchar	udpcksum[2];	/* Checksum */
-
-	/* rudp header */
-	uchar	relseq[4];	/* id of this packet (or 0) */
-	uchar	relsgen[4];	/* generation/time stamp */
-	uchar	relack[4];	/* packet being acked (or 0) */
-	uchar	relagen[4];	/* generation/time stamp */
-};
-
-
-/*
- *  one state structure per destination
- */
-typedef struct Reliable Reliable;
-struct Reliable
-{
-	Ref;
-
-	Reliable *next;
-
-	uchar	addr[IPaddrlen];	/* always V6 when put here */
-	ushort	port;
-
-	Block	*unacked;	/* unacked msg list */
-	Block	*unackedtail;	/*  and its tail */
-
-	int	timeout;	/* time since first unacked msg sent */
-	int	xmits;		/* number of times first unacked msg sent */
-
-	ulong	sndseq;		/* next packet to be sent */
-	ulong	sndgen;		/*  and its generation */
-
-	ulong	rcvseq;		/* last packet received */
-	ulong	rcvgen;		/*  and its generation */
-
-	ulong	acksent;	/* last ack sent */
-	ulong	ackrcvd;	/* last msg for which ack was rcvd */
-
-	/* flow control */
-	QLock	lock;
-	Rendez	vous;
-	int	blocked;
-};
-
-
-
-/* MIB II counters */
-typedef struct Rudpstats Rudpstats;
-struct Rudpstats
-{
-	ulong	rudpInDatagrams;
-	ulong	rudpNoPorts;
-	ulong	rudpInErrors;
-	ulong	rudpOutDatagrams;
-};
-
-typedef struct Rudppriv Rudppriv;
-struct Rudppriv
-{
-	Ipht	ht;
-
-	/* MIB counters */
-	Rudpstats	ustats;
-
-	/* non-MIB stats */
-	ulong	csumerr;		/* checksum errors */
-	ulong	lenerr;			/* short packet */
-	ulong	rxmits;			/* # of retransmissions */
-	ulong	orders;			/* # of out of order pkts */
-
-	/* keeping track of the ack kproc */
-	int	ackprocstarted;
-	QLock	apl;
-};
-
-
-static ulong generation = 0;
-static Rendez rend;
-
-/*
- *  protocol specific part of Conv
- */
-typedef struct Rudpcb Rudpcb;
-struct Rudpcb
-{
-	QLock;
-	uchar	headers;
-	uchar	randdrop;
-	Reliable *r;
-};
-
-/*
- * local functions
- */
-void	relsendack(Conv*, Reliable*, int);
-int	reliput(Conv*, Block*, uchar*, ushort);
-Reliable *relstate(Rudpcb*, uchar*, ushort, char*);
-void	relput(Reliable*);
-void	relforget(Conv *, uchar*, int, int);
-void	relackproc(void *);
-void	relackq(Reliable *, Block*);
-void	relhangup(Conv *, Reliable*);
-void	relrexmit(Conv *, Reliable*);
-void	relput(Reliable*);
-void	rudpkick(void *x);
-
-static void
-rudpstartackproc(Proto *rudp)
-{
-	Rudppriv *rpriv;
-	char kpname[KNAMELEN];
-
-	rpriv = rudp->priv;
-	if(rpriv->ackprocstarted == 0){
-		qlock(&rpriv->apl);
-		if(rpriv->ackprocstarted == 0){
-			snprint(kpname, sizeof kpname, "#I%drudpack",
-				rudp->f->dev);
-			kproc(kpname, relackproc, rudp);
-			rpriv->ackprocstarted = 1;
-		}
-		qunlock(&rpriv->apl);
-	}
-}
-
-static char*
-rudpconnect(Conv *c, char **argv, int argc)
-{
-	char *e;
-	Rudppriv *upriv;
-
-	upriv = c->p->priv;
-	rudpstartackproc(c->p);
-	e = Fsstdconnect(c, argv, argc);
-	Fsconnected(c, e);
-	iphtadd(&upriv->ht, c);
-
-	return e;
-}
-
-
-static int
-rudpstate(Conv *c, char *state, int n)
-{
-	Rudpcb *ucb;
-	Reliable *r;
-	int m;
-
-	m = snprint(state, n, "%s", c->inuse?"Open":"Closed");
-	ucb = (Rudpcb*)c->ptcl;
-	qlock(ucb);
-	for(r = ucb->r; r; r = r->next)
-		m += snprint(state+m, n-m, " %I/%ld", r->addr, UNACKED(r));
-	m += snprint(state+m, n-m, "\n");
-	qunlock(ucb);
-	return m;
-}
-
-static char*
-rudpannounce(Conv *c, char** argv, int argc)
-{
-	char *e;
-	Rudppriv *upriv;
-
-	upriv = c->p->priv;
-	rudpstartackproc(c->p);
-	e = Fsstdannounce(c, argv, argc);
-	if(e != nil)
-		return e;
-	Fsconnected(c, nil);
-	iphtadd(&upriv->ht, c);
-
-	return nil;
-}
-
-static void
-rudpcreate(Conv *c)
-{
-	c->rq = qopen(64*1024, Qmsg, 0, 0);
-	c->wq = qopen(64*1024, Qkick, rudpkick, c);
-}
-
-static void
-rudpclose(Conv *c)
-{
-	Rudpcb *ucb;
-	Reliable *r, *nr;
-	Rudppriv *upriv;
-
-	upriv = c->p->priv;
-	iphtrem(&upriv->ht, c);
-
-	/* force out any delayed acks */
-	ucb = (Rudpcb*)c->ptcl;
-	qlock(ucb);
-	for(r = ucb->r; r; r = r->next){
-		if(r->acksent != r->rcvseq)
-			relsendack(c, r, 0);
-	}
-	qunlock(ucb);
-
-	qclose(c->rq);
-	qclose(c->wq);
-	qclose(c->eq);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->lport = 0;
-	c->rport = 0;
-
-	ucb->headers = 0;
-	ucb->randdrop = 0;
-	qlock(ucb);
-	for(r = ucb->r; r; r = nr){
-		if(r->acksent != r->rcvseq)
-			relsendack(c, r, 0);
-		nr = r->next;
-		relhangup(c, r);
-		relput(r);
-	}
-	ucb->r = 0;
-
-	qunlock(ucb);
-}
-
-/*
- *  randomly don't send packets
- */
-static void
-doipoput(Conv *c, Fs *f, Block *bp, int x, int ttl, int tos)
-{
-	Rudpcb *ucb;
-
-	ucb = (Rudpcb*)c->ptcl;
-	if(ucb->randdrop && nrand(100) < ucb->randdrop)
-		freeblist(bp);
-	else
-		ipoput4(f, bp, x, ttl, tos, nil);
-}
-
-int
-flow(void *v)
-{
-	Reliable *r = v;
-
-	return UNACKED(r) <= Maxunacked;
-}
-
-void
-rudpkick(void *x)
-{
-	Conv *c = x;
-	Udphdr *uh;
-	ushort rport;
-	uchar laddr[IPaddrlen], raddr[IPaddrlen];
-	Block *bp;
-	Rudpcb *ucb;
-	Rudphdr *rh;
-	Reliable *r;
-	int dlen, ptcllen;
-	Rudppriv *upriv;
-	Fs *f;
-
-	upriv = c->p->priv;
-	f = c->p->f;
-
-	netlog(c->p->f, Logrudp, "rudp: kick\n");
-	bp = qget(c->wq);
-	if(bp == nil)
-		return;
-
-	ucb = (Rudpcb*)c->ptcl;
-	switch(ucb->headers) {
-	case 7:
-		/* get user specified addresses */
-		bp = pullupblock(bp, UDP_USEAD7);
-		if(bp == nil)
-			return;
-		ipmove(raddr, bp->rp);
-		bp->rp += IPaddrlen;
-		ipmove(laddr, bp->rp);
-		bp->rp += IPaddrlen;
-		/* pick interface closest to dest */
-		if(ipforme(f, laddr) != Runi)
-			findlocalip(f, laddr, raddr);
-		bp->rp += IPaddrlen;		/* Ignore ifc address */
-		rport = nhgets(bp->rp);
-		bp->rp += 2+2;			/* Ignore local port */
-		break;
-	default:
-		ipmove(raddr, c->raddr);
-		ipmove(laddr, c->laddr);
-		rport = c->rport;
-		break;
-	}
-
-	dlen = blocklen(bp);
-
-	/* Make space to fit rudp & ip header */
-	bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE);
-	if(bp == nil)
-		return;
-
-	uh = (Udphdr *)(bp->rp);
-	uh->vihl = IP_VER4;
-
-	rh = (Rudphdr*)uh;
-
-	ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE);
-	uh->Unused = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-	switch(ucb->headers){
-	case 7:
-		v6tov4(uh->udpdst, raddr);
-		hnputs(uh->udpdport, rport);
-		v6tov4(uh->udpsrc, laddr);
-		break;
-	default:
-		v6tov4(uh->udpdst, c->raddr);
-		hnputs(uh->udpdport, c->rport);
-		if(ipcmp(c->laddr, IPnoaddr) == 0)
-			findlocalip(f, c->laddr, c->raddr);
-		v6tov4(uh->udpsrc, c->laddr);
-		break;
-	}
-	hnputs(uh->udpsport, c->lport);
-	hnputs(uh->udplen, ptcllen);
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-
-	qlock(ucb);
-	r = relstate(ucb, raddr, rport, "kick");
-	r->sndseq = NEXTSEQ(r->sndseq);
-	hnputl(rh->relseq, r->sndseq);
-	hnputl(rh->relsgen, r->sndgen);
-
-	hnputl(rh->relack, r->rcvseq);  /* ACK last rcvd packet */
-	hnputl(rh->relagen, r->rcvgen);
-
-	if(r->rcvseq != r->acksent)
-		r->acksent = r->rcvseq;
-
-	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE));
-
-	relackq(r, bp);
-	qunlock(ucb);
-
-	upriv->ustats.rudpOutDatagrams++;
-
-	DPRINT("sent: %lud/%lud, %lud/%lud\n",
-		r->sndseq, r->sndgen, r->rcvseq, r->rcvgen);
-
-	doipoput(c, f, bp, 0, c->ttl, c->tos);
-
-	if(waserror()) {
-		relput(r);
-		qunlock(&r->lock);
-		nexterror();
-	}
-
-	/* flow control of sorts */
-	qlock(&r->lock);
-	if(UNACKED(r) > Maxunacked){
-		r->blocked = 1;
-		sleep(&r->vous, flow, r);
-		r->blocked = 0;
-	}
-
-	qunlock(&r->lock);
-	relput(r);
-	poperror();
-}
-
-void
-rudpiput(Proto *rudp, Ipifc *ifc, Block *bp)
-{
-	int len, olen, ottl;
-	Udphdr *uh;
-	Conv *c;
-	Rudpcb *ucb;
-	uchar raddr[IPaddrlen], laddr[IPaddrlen];
-	ushort rport, lport;
-	Rudppriv *upriv;
-	Fs *f;
-	uchar *p;
-
-	upriv = rudp->priv;
-	f = rudp->f;
-
-	upriv->ustats.rudpInDatagrams++;
-
-	uh = (Udphdr*)(bp->rp);
-
-	/* Put back pseudo header for checksum
-	 * (remember old values for icmpnoconv())
-	 */
-	ottl = uh->Unused;
-	uh->Unused = 0;
-	len = nhgets(uh->udplen);
-	olen = nhgets(uh->udpplen);
-	hnputs(uh->udpplen, len);
-
-	v4tov6(raddr, uh->udpsrc);
-	v4tov6(laddr, uh->udpdst);
-	lport = nhgets(uh->udpdport);
-	rport = nhgets(uh->udpsport);
-
-	if(nhgets(uh->udpcksum)) {
-		if(ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE)) {
-			upriv->ustats.rudpInErrors++;
-			upriv->csumerr++;
-			netlog(f, Logrudp, "rudp: checksum error %I\n", raddr);
-			DPRINT("rudp: checksum error %I\n", raddr);
-			freeblist(bp);
-			return;
-		}
-	}
-
-	qlock(rudp);
-
-	c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
-	if(c == nil){
-		/* no conversation found */
-		upriv->ustats.rudpNoPorts++;
-		qunlock(rudp);
-		netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
-			laddr, lport);
-		uh->Unused = ottl;
-		hnputs(uh->udpplen, olen);
-		icmpnoconv(f, bp);
-		freeblist(bp);
-		return;
-	}
-	ucb = (Rudpcb*)c->ptcl;
-	qlock(ucb);
-	qunlock(rudp);
-
-	if(reliput(c, bp, raddr, rport) < 0){
-		qunlock(ucb);
-		freeb(bp);
-		return;
-	}
-
-	/*
-	 * Trim the packet down to data size
-	 */
-
-	len -= (UDP_RHDRSIZE-UDP_PHDRSIZE);
-	bp = trimblock(bp, UDP_IPHDR+UDP_RHDRSIZE, len);
-	if(bp == nil) {
-		netlog(f, Logrudp, "rudp: len err %I.%d -> %I.%d\n",
-			raddr, rport, laddr, lport);
-		DPRINT("rudp: len err %I.%d -> %I.%d\n",
-			raddr, rport, laddr, lport);
-		upriv->lenerr++;
-		return;
-	}
-
-	netlog(f, Logrudpmsg, "rudp: %I.%d -> %I.%d l %d\n",
-		raddr, rport, laddr, lport, len);
-
-	switch(ucb->headers){
-	case 7:
-		/* pass the src address */
-		bp = padblock(bp, UDP_USEAD7);
-		p = bp->rp;
-		ipmove(p, raddr); p += IPaddrlen;
-		ipmove(p, laddr); p += IPaddrlen;
-		ipmove(p, ifc->lifc->local); p += IPaddrlen;
-		hnputs(p, rport); p += 2;
-		hnputs(p, lport);
-		break;
-	default:
-		/* connection oriented rudp */
-		if(ipcmp(c->raddr, IPnoaddr) == 0){
-			/* save the src address in the conversation */
-		 	ipmove(c->raddr, raddr);
-			c->rport = rport;
-
-			/* reply with the same ip address (if not broadcast) */
-			if(ipforme(f, laddr) == Runi)
-				ipmove(c->laddr, laddr);
-			else
-				v4tov6(c->laddr, ifc->lifc->local);
-		}
-		break;
-	}
-	if(bp->next)
-		bp = concatblock(bp);
-
-	if(qfull(c->rq)) {
-		netlog(f, Logrudp, "rudp: qfull %I.%d -> %I.%d\n", raddr, rport,
-			laddr, lport);
-		freeblist(bp);
-	}
-	else
-		qpass(c->rq, bp);
-
-	qunlock(ucb);
-}
-
-static char *rudpunknown = "unknown rudp ctl request";
-
-char*
-rudpctl(Conv *c, char **f, int n)
-{
-	Rudpcb *ucb;
-	uchar ip[IPaddrlen];
-	int x;
-
-	ucb = (Rudpcb*)c->ptcl;
-	if(n < 1)
-		return rudpunknown;
-
-	if(strcmp(f[0], "headers") == 0){
-		ucb->headers = 7;		/* new headers format */
-		return nil;
-	} else if(strcmp(f[0], "hangup") == 0){
-		if(n < 3)
-			return "bad syntax";
-		if (parseip(ip, f[1]) == -1)
-			return Ebadip;
-		x = atoi(f[2]);
-		qlock(ucb);
-		relforget(c, ip, x, 1);
-		qunlock(ucb);
-		return nil;
-	} else if(strcmp(f[0], "randdrop") == 0){
-		x = 10;			/* default is 10% */
-		if(n > 1)
-			x = atoi(f[1]);
-		if(x > 100 || x < 0)
-			return "illegal rudp drop rate";
-		ucb->randdrop = x;
-		return nil;
-	}
-	return rudpunknown;
-}
-
-void
-rudpadvise(Proto *rudp, Block *bp, char *msg)
-{
-	Udphdr *h;
-	uchar source[IPaddrlen], dest[IPaddrlen];
-	ushort psource, pdest;
-	Conv *s, **p;
-
-	h = (Udphdr*)(bp->rp);
-
-	v4tov6(dest, h->udpdst);
-	v4tov6(source, h->udpsrc);
-	psource = nhgets(h->udpsport);
-	pdest = nhgets(h->udpdport);
-
-	/* Look for a connection */
-	for(p = rudp->conv; *p; p++) {
-		s = *p;
-		if(s->rport == pdest)
-		if(s->lport == psource)
-		if(ipcmp(s->raddr, dest) == 0)
-		if(ipcmp(s->laddr, source) == 0){
-			qhangup(s->rq, msg);
-			qhangup(s->wq, msg);
-			break;
-		}
-	}
-	freeblist(bp);
-}
-
-int
-rudpstats(Proto *rudp, char *buf, int len)
-{
-	Rudppriv *upriv;
-
-	upriv = rudp->priv;
-	return snprint(buf, len, "%lud %lud %lud %lud %lud %lud\n",
-		upriv->ustats.rudpInDatagrams,
-		upriv->ustats.rudpNoPorts,
-		upriv->ustats.rudpInErrors,
-		upriv->ustats.rudpOutDatagrams,
-		upriv->rxmits,
-		upriv->orders);
-}
-
-void
-rudpinit(Fs *fs)
-{
-
-	Proto *rudp;
-
-	rudp = smalloc(sizeof(Proto));
-	rudp->priv = smalloc(sizeof(Rudppriv));
-	rudp->name = "rudp";
-	rudp->connect = rudpconnect;
-	rudp->announce = rudpannounce;
-	rudp->ctl = rudpctl;
-	rudp->state = rudpstate;
-	rudp->create = rudpcreate;
-	rudp->close = rudpclose;
-	rudp->rcv = rudpiput;
-	rudp->advise = rudpadvise;
-	rudp->stats = rudpstats;
-	rudp->ipproto = IP_UDPPROTO;
-	rudp->nc = 32;
-	rudp->ptclsize = sizeof(Rudpcb);
-
-	Fsproto(fs, rudp);
-}
-
-/*********************************************/
-/* Here starts the reliable helper functions */
-/*********************************************/
-/*
- *  Enqueue a copy of an unacked block for possible retransmissions
- */
-void
-relackq(Reliable *r, Block *bp)
-{
-	Block *np;
-
-	np = copyblock(bp, blocklen(bp));
-	if(r->unacked)
-		r->unackedtail->list = np;
-	else {
-		/* restart timer */
-		r->timeout = 0;
-		r->xmits = 1;
-		r->unacked = np;
-	}
-	r->unackedtail = np;
-	np->list = nil;
-}
-
-/*
- *  retransmit unacked blocks
- */
-void
-relackproc(void *a)
-{
-	Rudpcb *ucb;
-	Proto *rudp;
-	Reliable *r;
-	Conv **s, *c;
-
-	rudp = (Proto *)a;
-
-loop:
-	tsleep(&up->sleep, return0, 0, Rudptickms);
-
-	for(s = rudp->conv; *s; s++) {
-		c = *s;
-		ucb = (Rudpcb*)c->ptcl;
-		qlock(ucb);
-
-		for(r = ucb->r; r; r = r->next) {
-			if(r->unacked != nil){
-				r->timeout += Rudptickms;
-				if(r->timeout > Rudprxms*r->xmits)
-					relrexmit(c, r);
-			}
-			if(r->acksent != r->rcvseq)
-				relsendack(c, r, 0);
-		}
-		qunlock(ucb);
-	}
-	goto loop;
-}
-
-/*
- *  get the state record for a conversation
- */
-Reliable*
-relstate(Rudpcb *ucb, uchar *addr, ushort port, char *from)
-{
-	Reliable *r, **l;
-
-	l = &ucb->r;
-	for(r = *l; r; r = *l){
-		if(memcmp(addr, r->addr, IPaddrlen) == 0 &&
-		    port == r->port)
-			break;
-		l = &r->next;
-	}
-
-	/* no state for this addr/port, create some */
-	if(r == nil){
-		while(generation == 0)
-			generation = rand();
-
-		DPRINT("from %s new state %lud for %I!%ud\n",
-		        from, generation, addr, port);
-
-		r = smalloc(sizeof(Reliable));
-		memmove(r->addr, addr, IPaddrlen);
-		r->port = port;
-		r->unacked = 0;
-		if(generation == Hangupgen)
-			generation++;
-		r->sndgen = generation++;
-		r->sndseq = 0;
-		r->ackrcvd = 0;
-		r->rcvgen = 0;
-		r->rcvseq = 0;
-		r->acksent = 0;
-		r->xmits = 0;
-		r->timeout = 0;
-		r->ref = 0;
-		incref(r);	/* one reference for being in the list */
-
-		*l = r;
-	}
-
-	incref(r);
-	return r;
-}
-
-void
-relput(Reliable *r)
-{
-	if(decref(r) == 0)
-		free(r);
-}
-
-/*
- *  forget a Reliable state
- */
-void
-relforget(Conv *c, uchar *ip, int port, int originator)
-{
-	Rudpcb *ucb;
-	Reliable *r, **l;
-
-	ucb = (Rudpcb*)c->ptcl;
-
-	l = &ucb->r;
-	for(r = *l; r; r = *l){
-		if(ipcmp(ip, r->addr) == 0 && port == r->port){
-			*l = r->next;
-			if(originator)
-				relsendack(c, r, 1);
-			relhangup(c, r);
-			relput(r);	/* remove from the list */
-			break;
-		}
-		l = &r->next;
-	}
-}
-
-/*
- *  process a rcvd reliable packet. return -1 if not to be passed to user process,
- *  0 therwise.
- *
- *  called with ucb locked.
- */
-int
-reliput(Conv *c, Block *bp, uchar *addr, ushort port)
-{
-	Block *nbp;
-	Rudpcb *ucb;
-	Rudppriv *upriv;
-	Udphdr *uh;
-	Reliable *r;
-	Rudphdr *rh;
-	ulong seq, ack, sgen, agen, ackreal;
-	int rv = -1;
-
-	/* get fields */
-	uh = (Udphdr*)(bp->rp);
-	rh = (Rudphdr*)uh;
-	seq = nhgetl(rh->relseq);
-	sgen = nhgetl(rh->relsgen);
-	ack = nhgetl(rh->relack);
-	agen = nhgetl(rh->relagen);
-
-	upriv = c->p->priv;
-	ucb = (Rudpcb*)c->ptcl;
-	r = relstate(ucb, addr, port, "input");
-
-	DPRINT("rcvd %lud/%lud, %lud/%lud, r->sndgen = %lud\n",
-		seq, sgen, ack, agen, r->sndgen);
-
-	/* if acking an incorrect generation, ignore */
-	if(ack && agen != r->sndgen)
-		goto out;
-
-	/* Look for a hangup */
-	if(sgen == Hangupgen) {
-		if(agen == r->sndgen)
-			relforget(c, addr, port, 0);
-		goto out;
-	}
-
-	/* make sure we're not talking to a new remote side */
-	if(r->rcvgen != sgen){
-		if(seq != 0 && seq != 1)
-			goto out;
-
-		/* new connection */
-		if(r->rcvgen != 0){
-			DPRINT("new con r->rcvgen = %lud, sgen = %lud\n", r->rcvgen, sgen);
-			relhangup(c, r);
-		}
-		r->rcvgen = sgen;
-	}
-
-	/* dequeue acked packets */
-	if(ack && agen == r->sndgen){
-		ackreal = 0;
-		while(r->unacked != nil && INSEQ(ack, r->ackrcvd, r->sndseq)){
-			nbp = r->unacked;
-			r->unacked = nbp->list;
-			DPRINT("%lud/%lud acked, r->sndgen = %lud\n",
-			       ack, agen, r->sndgen);
-			freeb(nbp);
-			r->ackrcvd = NEXTSEQ(r->ackrcvd);
-			ackreal = 1;
-		}
-
-		/* flow control */
-		if(UNACKED(r) < Maxunacked/8 && r->blocked)
-			wakeup(&r->vous);
-
-		/*
-		 *  retransmit next packet if the acked packet
-		 *  was transmitted more than once
-		 */
-		if(ackreal && r->unacked != nil){
-			r->timeout = 0;
-			if(r->xmits > 1){
-				r->xmits = 1;
-				relrexmit(c, r);
-			}
-		}
-
-	}
-
-	/* no message or input queue full */
-	if(seq == 0 || qfull(c->rq))
-		goto out;
-
-	/* refuse out of order delivery */
-	if(seq != NEXTSEQ(r->rcvseq)){
-		relsendack(c, r, 0);	/* tell him we got it already */
-		upriv->orders++;
-		DPRINT("out of sequence %lud not %lud\n", seq, NEXTSEQ(r->rcvseq));
-		goto out;
-	}
-	r->rcvseq = seq;
-
-	rv = 0;
-out:
-	relput(r);
-	return rv;
-}
-
-void
-relsendack(Conv *c, Reliable *r, int hangup)
-{
-	Udphdr *uh;
-	Block *bp;
-	Rudphdr *rh;
-	int ptcllen;
-	Fs *f;
-
-	bp = allocb(UDP_IPHDR + UDP_RHDRSIZE);
-	if(bp == nil)
-		return;
-	bp->wp += UDP_IPHDR + UDP_RHDRSIZE;
-	f = c->p->f;
-	uh = (Udphdr *)(bp->rp);
-	uh->vihl = IP_VER4;
-	rh = (Rudphdr*)uh;
-
-	ptcllen = (UDP_RHDRSIZE-UDP_PHDRSIZE);
-	uh->Unused = 0;
-	uh->udpproto = IP_UDPPROTO;
-	uh->frag[0] = 0;
-	uh->frag[1] = 0;
-	hnputs(uh->udpplen, ptcllen);
-
-	v6tov4(uh->udpdst, r->addr);
-	hnputs(uh->udpdport, r->port);
-	hnputs(uh->udpsport, c->lport);
-	if(ipcmp(c->laddr, IPnoaddr) == 0)
-		findlocalip(f, c->laddr, c->raddr);
-	v6tov4(uh->udpsrc, c->laddr);
-	hnputs(uh->udplen, ptcllen);
-
-	if(hangup)
-		hnputl(rh->relsgen, Hangupgen);
-	else
-		hnputl(rh->relsgen, r->sndgen);
-	hnputl(rh->relseq, 0);
-	hnputl(rh->relagen, r->rcvgen);
-	hnputl(rh->relack, r->rcvseq);
-
-	if(r->acksent < r->rcvseq)
-		r->acksent = r->rcvseq;
-
-	uh->udpcksum[0] = 0;
-	uh->udpcksum[1] = 0;
-	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));
-
-	DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
-	doipoput(c, f, bp, 0, c->ttl, c->tos);
-}
-
-
-/*
- *  called with ucb locked (and c locked if user initiated close)
- */
-void
-relhangup(Conv *c, Reliable *r)
-{
-	int n;
-	Block *bp;
-	char hup[ERRMAX];
-
-	n = snprint(hup, sizeof(hup), "hangup %I!%d", r->addr, r->port);
-	qproduce(c->eq, hup, n);
-
-	/*
-	 *  dump any unacked outgoing messages
-	 */
-	for(bp = r->unacked; bp != nil; bp = r->unacked){
-		r->unacked = bp->list;
-		bp->list = nil;
-		freeb(bp);
-	}
-
-	r->rcvgen = 0;
-	r->rcvseq = 0;
-	r->acksent = 0;
-	if(generation == Hangupgen)
-		generation++;
-	r->sndgen = generation++;
-	r->sndseq = 0;
-	r->ackrcvd = 0;
-	r->xmits = 0;
-	r->timeout = 0;
-	wakeup(&r->vous);
-}
-
-/*
- *  called with ucb locked
- */
-void
-relrexmit(Conv *c, Reliable *r)
-{
-	Rudppriv *upriv;
-	Block *np;
-	Fs *f;
-
-	upriv = c->p->priv;
-	f = c->p->f;
-	r->timeout = 0;
-	if(r->xmits++ > Rudpmaxxmit){
-		relhangup(c, r);
-		return;
-	}
-
-	upriv->rxmits++;
-	np = copyblock(r->unacked, blocklen(r->unacked));
-	DPRINT("rxmit r->ackrvcd+1 = %lud\n", r->ackrcvd+1);
-	doipoput(c, f, np, 0, c->ttl, c->tos);
-}

+ 0 - 3449
sys/src/9/ip/tcp.c

@@ -1,3449 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-
-enum
-{
-	QMAX		= 64*1024-1,
-	IP_TCPPROTO	= 6,
-
-	TCP4_IPLEN	= 8,
-	TCP4_PHDRSIZE	= 12,
-	TCP4_HDRSIZE	= 20,
-	TCP4_TCBPHDRSZ	= 40,
-	TCP4_PKT	= TCP4_IPLEN+TCP4_PHDRSIZE,
-
-	TCP6_IPLEN	= 0,
-	TCP6_PHDRSIZE	= 40,
-	TCP6_HDRSIZE	= 20,
-	TCP6_TCBPHDRSZ	= 60,
-	TCP6_PKT	= TCP6_IPLEN+TCP6_PHDRSIZE,
-
-	TcptimerOFF	= 0,
-	TcptimerON	= 1,
-	TcptimerDONE	= 2,
-	MAX_TIME 	= (1<<20),	/* Forever */
-	TCP_ACK		= 50,		/* Timed ack sequence in ms */
-	MAXBACKMS	= 9*60*1000,	/* longest backoff time (ms) before hangup */
-
-	URG		= 0x20,		/* Data marked urgent */
-	ACK		= 0x10,		/* Acknowledge is valid */
-	PSH		= 0x08,		/* Whole data pipe is pushed */
-	RST		= 0x04,		/* Reset connection */
-	SYN		= 0x02,		/* Pkt. is synchronise */
-	FIN		= 0x01,		/* Start close down */
-
-	EOLOPT		= 0,
-	NOOPOPT		= 1,
-	MSSOPT		= 2,
-	MSS_LENGTH	= 4,		/* Maximum segment size */
-	WSOPT		= 3,
-	WS_LENGTH	= 3,		/* Bits to scale window size by */
-	MSL2		= 10,
-	MSPTICK		= 50,		/* Milliseconds per timer tick */
-	DEF_MSS		= 1460,		/* Default maximum segment */
-	DEF_MSS6	= 1280,		/* Default maximum segment (min) for v6 */
-	DEF_RTT		= 500,		/* Default round trip */
-	DEF_KAT		= 120000,	/* Default time (ms) between keep alives */
-	TCP_LISTEN	= 0,		/* Listen connection */
-	TCP_CONNECT	= 1,		/* Outgoing connection */
-	SYNACK_RXTIMER	= 250,		/* ms between SYNACK retransmits */
-
-	TCPREXMTTHRESH	= 3,		/* dupack threshhold for rxt */
-
-	FORCE		= 1,
-	CLONE		= 2,
-	RETRAN		= 4,
-	ACTIVE		= 8,
-	SYNACK		= 16,
-
-	LOGAGAIN	= 3,
-	LOGDGAIN	= 2,
-
-	Closed		= 0,		/* Connection states */
-	Listen,
-	Syn_sent,
-	Syn_received,
-	Established,
-	Finwait1,
-	Finwait2,
-	Close_wait,
-	Closing,
-	Last_ack,
-	Time_wait,
-
-	Maxlimbo	= 1000,		/* maximum procs waiting for response to SYN ACK */
-	NLHT		= 256,		/* hash table size, must be a power of 2 */
-	LHTMASK		= NLHT-1,
-
-	/*
-	 * window is 64kb * 2ⁿ
-	 * these factors determine the ultimate bandwidth-delay product.
-	 * 64kb * 2⁵ = 2mb, or 2× overkill for 100mbps * 70ms.
-	 */
-	Maxqscale	= 4,		/* maximum queuing scale */
-	Defadvscale	= 4,		/* default advertisement */
-};
-
-/* Must correspond to the enumeration above */
-char *tcpstates[] =
-{
-	"Closed", 	"Listen", 	"Syn_sent", "Syn_received",
-	"Established", 	"Finwait1",	"Finwait2", "Close_wait",
-	"Closing", 	"Last_ack", 	"Time_wait"
-};
-
-typedef struct Tcptimer Tcptimer;
-struct Tcptimer
-{
-	Tcptimer	*next;
-	Tcptimer	*prev;
-	Tcptimer	*readynext;
-	int	state;
-	int	start;
-	int	count;
-	void	(*func)(void*);
-	void	*arg;
-};
-
-/*
- *  v4 and v6 pseudo headers used for
- *  checksuming tcp
- */
-typedef struct Tcp4hdr Tcp4hdr;
-struct Tcp4hdr
-{
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	Unused;
-	uchar	proto;
-	uchar	tcplen[2];
-	uchar	tcpsrc[4];
-	uchar	tcpdst[4];
-	/* same as v6 from here on */
-	uchar	tcpsport[2];
-	uchar	tcpdport[2];
-	uchar	tcpseq[4];
-	uchar	tcpack[4];
-	uchar	tcpflag[2];
-	uchar	tcpwin[2];
-	uchar	tcpcksum[2];
-	uchar	tcpurg[2];
-	/* Options segment */
-	uchar	tcpopt[1];
-};
-
-typedef struct Tcp6hdr Tcp6hdr;
-struct Tcp6hdr
-{
-	uchar	vcf[4];
-	uchar	ploadlen[2];
-	uchar	proto;
-	uchar	ttl;
-	uchar	tcpsrc[IPaddrlen];
-	uchar	tcpdst[IPaddrlen];
-	/* same as v4 from here on */
-	uchar	tcpsport[2];
-	uchar	tcpdport[2];
-	uchar	tcpseq[4];
-	uchar	tcpack[4];
-	uchar	tcpflag[2];
-	uchar	tcpwin[2];
-	uchar	tcpcksum[2];
-	uchar	tcpurg[2];
-	/* Options segment */
-	uchar	tcpopt[1];
-};
-
-/*
- *  this represents the control info
- *  for a single packet.  It is derived from
- *  a packet in ntohtcp{4,6}() and stuck into
- *  a packet in htontcp{4,6}().
- */
-typedef struct Tcp Tcp;
-struct	Tcp
-{
-	ushort	source;
-	ushort	dest;
-	ulong	seq;
-	ulong	ack;
-	uchar	flags;
-	uchar	update;
-	ushort	ws;	/* window scale option */
-	ulong	wnd;	/* prescaled window*/
-	ushort	urg;
-	ushort	mss;	/* max segment size option (if not zero) */
-	ushort	len;	/* size of data */
-};
-
-/*
- *  this header is malloc'd to thread together fragments
- *  waiting to be coalesced
- */
-typedef struct Reseq Reseq;
-struct Reseq
-{
-	Reseq	*next;
-	Tcp	seg;
-	Block	*bp;
-	ushort	length;
-};
-
-/*
- *  the qlock in the Conv locks this structure
- */
-typedef struct Tcpctl Tcpctl;
-struct Tcpctl
-{
-	uchar	state;			/* Connection state */
-	uchar	type;			/* Listening or active connection */
-	uchar	code;			/* Icmp code */
-	struct {
-		ulong	una;		/* Unacked data pointer */
-		ulong	nxt;		/* Next sequence expected */
-		ulong	ptr;		/* Data pointer */
-		ulong	wnd;		/* Tcp send window */
-		ulong	urg;		/* Urgent data pointer */
-		ulong	wl2;
-		uint	scale;		/* how much to right shift window */
-					/* in xmitted packets */
-		/* to implement tahoe and reno TCP */
-		ulong	dupacks;	/* number of duplicate acks rcvd */
-		ulong	partialack;
-		int	recovery;	/* loss recovery flag */
-		int	retransmit;	/* retransmit 1 packet @ una flag */
-		int	rto;
-		ulong	rxt;		/* right window marker for recovery */
-					/* "recover" rfc3782 */
-	} snd;
-	struct {
-		ulong	nxt;		/* Receive pointer to next uchar slot */
-		ulong	wnd;		/* Receive window incoming */
-		ulong	wsnt;		/* Last wptr sent.  important to */
-					/* track for large bdp */
-		ulong	wptr;
-		ulong	urg;		/* Urgent pointer */
-		ulong	ackptr;		/* last acked sequence */
-		int	blocked;
-		uint	scale;		/* how much to left shift window in */
-					/* rcv'd packets */
-	} rcv;
-	ulong	iss;			/* Initial sequence number */
-	ulong	cwind;			/* Congestion window */
-	ulong	abcbytes;		/* appropriate byte counting rfc 3465 */
-	uint	scale;			/* desired snd.scale */
-	ulong	ssthresh;		/* Slow start threshold */
-	int	resent;			/* Bytes just resent */
-	int	irs;			/* Initial received squence */
-	ushort	mss;			/* Maximum segment size */
-	int	rerecv;			/* Overlap of data rerecevived */
-	ulong	window;			/* Our receive window (queue) */
-	uint	qscale;			/* Log2 of our receive window (queue) */
-	uchar	backoff;		/* Exponential backoff counter */
-	int	backedoff;		/* ms we've backed off for rexmits */
-	uchar	flags;			/* State flags */
-	Reseq	*reseq;			/* Resequencing queue */
-	int	nreseq;
-	int	reseqlen;
-	Tcptimer	timer;			/* Activity timer */
-	Tcptimer	acktimer;		/* Acknowledge timer */
-	Tcptimer	rtt_timer;		/* Round trip timer */
-	Tcptimer	katimer;		/* keep alive timer */
-	ulong	rttseq;			/* Round trip sequence */
-	int	srtt;			/* Smoothed round trip */
-	int	mdev;			/* Mean deviation of round trip */
-	int	kacounter;		/* count down for keep alive */
-	uint	sndsyntime;		/* time syn sent */
-	ulong	time;			/* time Finwait2 or Syn_received was sent */
-	ulong	timeuna;		/* snd.una when time was set */
-	int	nochecksum;		/* non-zero means don't send checksums */
-	int	flgcnt;			/* number of flags in the sequence (FIN,SEQ) */
-
-	union {
-		Tcp4hdr	tcp4hdr;
-		Tcp6hdr	tcp6hdr;
-	} protohdr;		/* prototype header */
-};
-
-/*
- *  New calls are put in limbo rather than having a conversation structure
- *  allocated.  Thus, a SYN attack results in lots of limbo'd calls but not
- *  any real Conv structures mucking things up.  Calls in limbo rexmit their
- *  SYN ACK every SYNACK_RXTIMER ms up to 4 times, i.e., they disappear after 1 second.
- *
- *  In particular they aren't on a listener's queue so that they don't figure
- *  in the input queue limit.
- *
- *  If 1/2 of a T3 was attacking SYN packets, we'ld have a permanent queue
- *  of 70000 limbo'd calls.  Not great for a linear list but doable.  Therefore
- *  there is no hashing of this list.
- */
-typedef struct Limbo Limbo;
-struct Limbo
-{
-	Limbo	*next;
-
-	uchar	laddr[IPaddrlen];
-	uchar	raddr[IPaddrlen];
-	ushort	lport;
-	ushort	rport;
-	ulong	irs;		/* initial received sequence */
-	ulong	iss;		/* initial sent sequence */
-	ushort	mss;		/* mss from the other end */
-	ushort	rcvscale;	/* how much to scale rcvd windows */
-	ushort	sndscale;	/* how much to scale sent windows */
-	ulong	lastsend;	/* last time we sent a synack */
-	uchar	version;	/* v4 or v6 */
-	uchar	rexmits;	/* number of retransmissions */
-};
-
-int	tcp_irtt = DEF_RTT;	/* Initial guess at round trip time */
-
-enum {
-	/* MIB stats */
-	MaxConn,
-	Mss,
-	ActiveOpens,
-	PassiveOpens,
-	EstabResets,
-	CurrEstab,
-	InSegs,
-	OutSegs,
-	RetransSegs,
-	RetransSegsSent,
-	RetransTimeouts,
-	InErrs,
-	OutRsts,
-
-	/* non-MIB stats */
-	CsumErrs,
-	HlenErrs,
-	LenErrs,
-	Resequenced,
-	OutOfOrder,
-	ReseqBytelim,
-	ReseqPktlim,
-	Delayack,
-	Wopenack,
-
-	Recovery,
-	RecoveryDone,
-	RecoveryRTO,
-	RecoveryNoSeq,
-	RecoveryCwind,
-	RecoveryPA,
-
-	Nstats
-};
-
-static char *statnames[Nstats] =
-{
-[MaxConn]	"MaxConn",
-[Mss]		"MaxSegment",
-[ActiveOpens]	"ActiveOpens",
-[PassiveOpens]	"PassiveOpens",
-[EstabResets]	"EstabResets",
-[CurrEstab]	"CurrEstab",
-[InSegs]	"InSegs",
-[OutSegs]	"OutSegs",
-[RetransSegs]	"RetransSegs",
-[RetransSegsSent]	"RetransSegsSent",
-[RetransTimeouts]	"RetransTimeouts",
-[InErrs]	"InErrs",
-[OutRsts]	"OutRsts",
-[CsumErrs]	"CsumErrs",
-[HlenErrs]	"HlenErrs",
-[LenErrs]	"LenErrs",
-[OutOfOrder]	"OutOfOrder",
-[Resequenced]	"Resequenced",
-[ReseqBytelim]	"ReseqBytelim",
-[ReseqPktlim]	"ReseqPktlim",
-[Delayack]	"Delayack",
-[Wopenack]	"Wopenack",
-
-[Recovery]	"Recovery",
-[RecoveryDone]	"RecoveryDone",
-[RecoveryRTO]	"RecoveryRTO",
-
-[RecoveryNoSeq]	"RecoveryNoSeq",
-[RecoveryCwind]	"RecoveryCwind",
-[RecoveryPA]	"RecoveryPA",
-};
-
-typedef struct Tcppriv Tcppriv;
-struct Tcppriv
-{
-	/* List of active timers */
-	QLock 	tl;
-	Tcptimer *timers;
-
-	/* hash table for matching conversations */
-	Ipht	ht;
-
-	/* calls in limbo waiting for an ACK to our SYN ACK */
-	int	nlimbo;
-	Limbo	*lht[NLHT];
-
-	/* for keeping track of tcpackproc */
-	QLock	apl;
-	int	ackprocstarted;
-
-	uvlong	stats[Nstats];
-};
-
-/*
- *  Setting tcpporthogdefense to non-zero enables Dong Lin's
- *  solution to hijacked systems staking out port's as a form
- *  of DoS attack.
- *
- *  To avoid stateless Conv hogs, we pick a sequence number at random.  If
- *  that number gets acked by the other end, we shut down the connection.
- *  Look for tcpporthogdefense in the code.
- */
-int tcpporthogdefense = 0;
-
-static	int	addreseq(Fs*, Tcpctl*, Tcppriv*, Tcp*, Block*, ushort);
-static	int	dumpreseq(Tcpctl*);
-static	void	getreseq(Tcpctl*, Tcp*, Block**, ushort*);
-static	void	limbo(Conv*, uchar*, uchar*, Tcp*, int);
-static	void	limborexmit(Proto*);
-static	void	localclose(Conv*, char*);
-static	void	procsyn(Conv*, Tcp*);
-static	void	tcpacktimer(void*);
-static	void	tcpiput(Proto*, Ipifc*, Block*);
-static	void	tcpkeepalive(void*);
-static	void	tcpoutput(Conv*);
-static	void	tcprcvwin(Conv*);
-static	void	tcprxmit(Conv*);
-static	void	tcpsetkacounter(Tcpctl*);
-static	void	tcpsetscale(Conv*, Tcpctl*, ushort, ushort);
-static	void	tcpsettimer(Tcpctl*);
-static	void	tcpsndsyn(Conv*, Tcpctl*);
-static	void	tcpstart(Conv*, int);
-static	void	tcpsynackrtt(Conv*);
-static	void	tcptimeout(void*);
-static	int	tcptrim(Tcpctl*, Tcp*, Block**, ushort*);
-
-static void
-tcpsetstate(Conv *s, uchar newstate)
-{
-	Tcpctl *tcb;
-	uchar oldstate;
-	Tcppriv *tpriv;
-
-	tpriv = s->p->priv;
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	oldstate = tcb->state;
-	if(oldstate == newstate)
-		return;
-
-	if(oldstate == Established)
-		tpriv->stats[CurrEstab]--;
-	if(newstate == Established)
-		tpriv->stats[CurrEstab]++;
-
-	switch(newstate) {
-	case Closed:
-		qclose(s->rq);
-		qclose(s->wq);
-		qclose(s->eq);
-		break;
-
-	case Close_wait:		/* Remote closes */
-		qhangup(s->rq, nil);
-		break;
-	}
-
-	tcb->state = newstate;
-
-	if(oldstate == Syn_sent && newstate != Closed)
-		Fsconnected(s, nil);
-}
-
-static char*
-tcpconnect(Conv *c, char **argv, int argc)
-{
-	char *e;
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)(c->ptcl);
-	if(tcb->state != Closed)
-		return Econinuse;
-
-	e = Fsstdconnect(c, argv, argc);
-	if(e != nil)
-		return e;
-	tcpstart(c, TCP_CONNECT);
-
-	return nil;
-}
-
-static int
-tcpstate(Conv *c, char *state, int n)
-{
-	Tcpctl *s;
-
-	s = (Tcpctl*)(c->ptcl);
-
-	return snprint(state, n,
-		"%s qin %d qout %d rq %d.%d srtt %d mdev %d sst %lud cwin %lud "
-		"swin %lud>>%d rwin %lud>>%d qscale %d timer.start %d "
-		"timer.count %d rerecv %d katimer.start %d katimer.count %d\n",
-		tcpstates[s->state],
-		c->rq ? qlen(c->rq) : 0,
-		c->wq ? qlen(c->wq) : 0,
-		s->nreseq, s->reseqlen,
-		s->srtt, s->mdev, s->ssthresh,
-		s->cwind, s->snd.wnd, s->rcv.scale, s->rcv.wnd, s->snd.scale,
-		s->qscale,
-		s->timer.start, s->timer.count, s->rerecv,
-		s->katimer.start, s->katimer.count);
-}
-
-static int
-tcpinuse(Conv *c)
-{
-	Tcpctl *s;
-
-	s = (Tcpctl*)(c->ptcl);
-	return s->state != Closed;
-}
-
-static char*
-tcpannounce(Conv *c, char **argv, int argc)
-{
-	char *e;
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)(c->ptcl);
-	if(tcb->state != Closed)
-		return Econinuse;
-
-	e = Fsstdannounce(c, argv, argc);
-	if(e != nil)
-		return e;
-	tcpstart(c, TCP_LISTEN);
-	Fsconnected(c, nil);
-
-	return nil;
-}
-
-/*
- *  tcpclose is always called with the q locked
- */
-static void
-tcpclose(Conv *c)
-{
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)c->ptcl;
-
-	qhangup(c->rq, nil);
-	qhangup(c->wq, nil);
-	qhangup(c->eq, nil);
-	qflush(c->rq);
-
-	switch(tcb->state) {
-	case Listen:
-		/*
-		 *  reset any incoming calls to this listener
-		 */
-		Fsconnected(c, "Hangup");
-
-		localclose(c, nil);
-		break;
-	case Closed:
-	case Syn_sent:
-		localclose(c, nil);
-		break;
-	case Syn_received:
-	case Established:
-		tcb->flgcnt++;
-		tcb->snd.nxt++;
-		tcpsetstate(c, Finwait1);
-		tcpoutput(c);
-		break;
-	case Close_wait:
-		tcb->flgcnt++;
-		tcb->snd.nxt++;
-		tcpsetstate(c, Last_ack);
-		tcpoutput(c);
-		break;
-	}
-}
-
-static void
-tcpkick(void *x)
-{
-	Conv *s = x;
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	if(waserror()){
-		qunlock(s);
-		nexterror();
-	}
-	qlock(s);
-
-	switch(tcb->state) {
-	case Syn_sent:
-	case Syn_received:
-	case Established:
-	case Close_wait:
-		/*
-		 * Push data
-		 */
-		tcpoutput(s);
-		break;
-	default:
-		localclose(s, "Hangup");
-		break;
-	}
-
-	qunlock(s);
-	poperror();
-}
-
-static int seq_lt(ulong, ulong);
-
-static void
-tcprcvwin(Conv *s)				/* Call with tcb locked */
-{
-	int w;
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)s->ptcl;
-	w = tcb->window - qlen(s->rq);
-	if(w < 0)
-		w = 0;
-	/* RFC 1122 § 4.2.2.17 do not move right edge of window left */
-	if(seq_lt(tcb->rcv.nxt + w, tcb->rcv.wptr))
-		w = tcb->rcv.wptr - tcb->rcv.nxt;
-	if(w != tcb->rcv.wnd)
-	if(w>>tcb->rcv.scale == 0 || tcb->window > 4*tcb->mss && w < tcb->mss/4){
-		tcb->rcv.blocked = 1;
-		netlog(s->p->f, Logtcp, "tcprcvwin: window %lud qlen %d ws %ud lport %d\n",
-			tcb->window, qlen(s->rq), tcb->rcv.scale, s->lport);
-	}
-	tcb->rcv.wnd = w;
-	tcb->rcv.wptr = tcb->rcv.nxt + w;
-}
-
-static void
-tcpacktimer(void *v)
-{
-	Tcpctl *tcb;
-	Conv *s;
-
-	s = v;
-	tcb = (Tcpctl*)s->ptcl;
-
-	if(waserror()){
-		qunlock(s);
-		nexterror();
-	}
-	qlock(s);
-	if(tcb->state != Closed){
-		tcb->flags |= FORCE;
-		tcpoutput(s);
-	}
-	qunlock(s);
-	poperror();
-}
-
-static void
-tcpcongestion(Tcpctl *tcb)
-{
-	ulong inflight;
-
-	inflight = tcb->snd.nxt - tcb->snd.una;
-	if(inflight > tcb->cwind)
-		inflight = tcb->cwind;
-	tcb->ssthresh = inflight / 2;
-	if(tcb->ssthresh < 2*tcb->mss)
-		tcb->ssthresh = 2*tcb->mss;
-}
-
-enum {
-	L	= 2,	/* aggressive slow start; legal values ∈ (1.0, 2.0) */
-};
-
-static void
-tcpabcincr(Tcpctl *tcb, uint acked)
-{
-	uint limit;
-
-	tcb->abcbytes += acked;
-	if(tcb->cwind < tcb->ssthresh){
-		/* slow start */
-		if(tcb->snd.rto)
-			limit = tcb->mss;
-		else
-			limit = L*tcb->mss;
-		tcb->cwind += MIN(tcb->abcbytes, limit);
-		tcb->abcbytes = 0;
-	} else {
-		tcb->snd.rto = 0;
-		/* avoidance */
-		if(tcb->abcbytes >= tcb->cwind){
-			tcb->abcbytes -= tcb->cwind;
-			tcb->cwind += tcb->mss;
-		}
-	}
-}
-
-static void
-tcpcreate(Conv *c)
-{
-	c->rq = qopen(QMAX, Qcoalesce, tcpacktimer, c);
-	c->wq = qopen(QMAX, Qkick, tcpkick, c);
-}
-
-static void
-timerstate(Tcppriv *priv, Tcptimer *t, int newstate)
-{
-	if(newstate != TcptimerON){
-		if(t->state == TcptimerON){
-			/* unchain */
-			if(priv->timers == t){
-				priv->timers = t->next;
-				if(t->prev != nil)
-					panic("timerstate1");
-			}
-			if(t->next)
-				t->next->prev = t->prev;
-			if(t->prev)
-				t->prev->next = t->next;
-			t->next = t->prev = nil;
-		}
-	} else {
-		if(t->state != TcptimerON){
-			/* chain */
-			if(t->prev != nil || t->next != nil)
-				panic("timerstate2");
-			t->prev = nil;
-			t->next = priv->timers;
-			if(t->next)
-				t->next->prev = t;
-			priv->timers = t;
-		}
-	}
-	t->state = newstate;
-}
-
-static void
-tcpackproc(void *a)
-{
-	Tcptimer *t, *tp, *timeo;
-	Proto *tcp;
-	Tcppriv *priv;
-	int loop;
-
-	tcp = a;
-	priv = tcp->priv;
-
-	for(;;) {
-		tsleep(&up->sleep, return0, 0, MSPTICK);
-
-		qlock(&priv->tl);
-		timeo = nil;
-		loop = 0;
-		for(t = priv->timers; t != nil; t = tp) {
-			if(loop++ > 10000)
-				panic("tcpackproc1");
-			tp = t->next;
- 			if(t->state == TcptimerON) {
-				t->count--;
-				if(t->count == 0) {
-					timerstate(priv, t, TcptimerDONE);
-					t->readynext = timeo;
-					timeo = t;
-				}
-			}
-		}
-		qunlock(&priv->tl);
-
-		loop = 0;
-		for(t = timeo; t != nil; t = t->readynext) {
-			if(loop++ > 10000)
-				panic("tcpackproc2");
-			if(t->state == TcptimerDONE && t->func != nil && !waserror()){
-				(*t->func)(t->arg);
-				poperror();
-			}
-		}
-
-		limborexmit(tcp);
-	}
-}
-
-static void
-tcpgo(Tcppriv *priv, Tcptimer *t)
-{
-	if(t == nil || t->start == 0)
-		return;
-
-	qlock(&priv->tl);
-	t->count = t->start;
-	timerstate(priv, t, TcptimerON);
-	qunlock(&priv->tl);
-}
-
-static void
-tcphalt(Tcppriv *priv, Tcptimer *t)
-{
-	if(t == nil)
-		return;
-
-	qlock(&priv->tl);
-	timerstate(priv, t, TcptimerOFF);
-	qunlock(&priv->tl);
-}
-
-static int
-backoff(int n)
-{
-	return 1 << n;
-}
-
-static void
-localclose(Conv *s, char *reason)	/* called with tcb locked */
-{
-	Tcpctl *tcb;
-	Tcppriv *tpriv;
-
-	tpriv = s->p->priv;
-	tcb = (Tcpctl*)s->ptcl;
-
-	iphtrem(&tpriv->ht, s);
-
-	tcphalt(tpriv, &tcb->timer);
-	tcphalt(tpriv, &tcb->rtt_timer);
-	tcphalt(tpriv, &tcb->acktimer);
-	tcphalt(tpriv, &tcb->katimer);
-
-	/* Flush reassembly queue; nothing more can arrive */
-	dumpreseq(tcb);
-
-	if(tcb->state == Syn_sent)
-		Fsconnected(s, reason);
-	if(s->state == Announced)
-		wakeup(&s->listenr);
-
-	qhangup(s->rq, reason);
-	qhangup(s->wq, reason);
-
-	tcpsetstate(s, Closed);
-}
-
-/* mtu (- TCP + IP hdr len) of 1st hop */
-static int
-tcpmtu(Proto *tcp, uchar *addr, int version, uint *scale)
-{
-	Ipifc *ifc;
-	int mtu;
-
-	ifc = findipifc(tcp->f, addr, 0);
-	switch(version){
-	default:
-	case V4:
-		mtu = DEF_MSS;
-		if(ifc != nil)
-			mtu = ifc->maxtu - ifc->m->hsize - (TCP4_PKT + TCP4_HDRSIZE);
-		break;
-	case V6:
-		mtu = DEF_MSS6;
-		if(ifc != nil)
-			mtu = ifc->maxtu - ifc->m->hsize - (TCP6_PKT + TCP6_HDRSIZE);
-		break;
-	}
-	/*
-	 * set the ws.  it doesn't commit us to anything.
-	 * ws is the ultimate limit to the bandwidth-delay product.
-	 */
-	*scale = Defadvscale;
-
-	return mtu;
-}
-
-static void
-inittcpctl(Conv *s, int mode)
-{
-	Tcpctl *tcb;
-	Tcp4hdr* h4;
-	Tcp6hdr* h6;
-	Tcppriv *tpriv;
-	int mss;
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	memset(tcb, 0, sizeof(Tcpctl));
-
-	tcb->ssthresh = QMAX;			/* reset by tcpsetscale() */
-	tcb->srtt = tcp_irtt<<LOGAGAIN;
-	tcb->mdev = 0;
-
-	/* setup timers */
-	tcb->timer.start = tcp_irtt / MSPTICK;
-	tcb->timer.func = tcptimeout;
-	tcb->timer.arg = s;
-	tcb->rtt_timer.start = MAX_TIME;
-	tcb->acktimer.start = TCP_ACK / MSPTICK;
-	tcb->acktimer.func = tcpacktimer;
-	tcb->acktimer.arg = s;
-	tcb->katimer.start = DEF_KAT / MSPTICK;
-	tcb->katimer.func = tcpkeepalive;
-	tcb->katimer.arg = s;
-
-	mss = DEF_MSS;
-
-	/* create a prototype(pseudo) header */
-	if(mode != TCP_LISTEN){
-		if(ipcmp(s->laddr, IPnoaddr) == 0)
-			findlocalip(s->p->f, s->laddr, s->raddr);
-
-		switch(s->ipversion){
-		case V4:
-			h4 = &tcb->protohdr.tcp4hdr;
-			memset(h4, 0, sizeof(*h4));
-			h4->proto = IP_TCPPROTO;
-			hnputs(h4->tcpsport, s->lport);
-			hnputs(h4->tcpdport, s->rport);
-			v6tov4(h4->tcpsrc, s->laddr);
-			v6tov4(h4->tcpdst, s->raddr);
-			break;
-		case V6:
-			h6 = &tcb->protohdr.tcp6hdr;
-			memset(h6, 0, sizeof(*h6));
-			h6->proto = IP_TCPPROTO;
-			hnputs(h6->tcpsport, s->lport);
-			hnputs(h6->tcpdport, s->rport);
-			ipmove(h6->tcpsrc, s->laddr);
-			ipmove(h6->tcpdst, s->raddr);
-			mss = DEF_MSS6;
-			break;
-		default:
-			panic("inittcpctl: version %d", s->ipversion);
-		}
-	}
-
-	tcb->mss = tcb->cwind = mss;
-	tcb->abcbytes = 0;
-	tpriv = s->p->priv;
-	tpriv->stats[Mss] = tcb->mss;
-
-	/* default is no window scaling */
-	tcpsetscale(s, tcb, 0, 0);
-}
-
-/*
- *  called with s qlocked
- */
-static void
-tcpstart(Conv *s, int mode)
-{
-	Tcpctl *tcb;
-	Tcppriv *tpriv;
-	char kpname[KNAMELEN];
-
-	tpriv = s->p->priv;
-
-	if(tpriv->ackprocstarted == 0){
-		qlock(&tpriv->apl);
-		if(tpriv->ackprocstarted == 0){
-			snprint(kpname, sizeof kpname, "#I%dtcpack", s->p->f->dev);
-			kproc(kpname, tcpackproc, s->p);
-			tpriv->ackprocstarted = 1;
-		}
-		qunlock(&tpriv->apl);
-	}
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	inittcpctl(s, mode);
-
-	iphtadd(&tpriv->ht, s);
-	switch(mode) {
-	case TCP_LISTEN:
-		tpriv->stats[PassiveOpens]++;
-		tcb->flags |= CLONE;
-		tcpsetstate(s, Listen);
-		break;
-
-	case TCP_CONNECT:
-		tpriv->stats[ActiveOpens]++;
-		tcb->flags |= ACTIVE;
-		tcpsndsyn(s, tcb);
-		tcpsetstate(s, Syn_sent);
-		tcpoutput(s);
-		break;
-	}
-}
-
-static char*
-tcpflag(char *buf, char *e, ushort flag)
-{
-	char *p;
-
-	p = seprint(buf, e, "%d", flag>>10);	/* Head len */
-	if(flag & URG)
-		p = seprint(p, e, " URG");
-	if(flag & ACK)
-		p = seprint(p, e, " ACK");
-	if(flag & PSH)
-		p = seprint(p, e, " PSH");
-	if(flag & RST)
-		p = seprint(p, e, " RST");
-	if(flag & SYN)
-		p = seprint(p, e, " SYN");
-	if(flag & FIN)
-		p = seprint(p, e, " FIN");
-	USED(p);
-	return buf;
-}
-
-static Block*
-htontcp6(Tcp *tcph, Block *data, Tcp6hdr *ph, Tcpctl *tcb)
-{
-	int dlen;
-	Tcp6hdr *h;
-	ushort csum;
-	ushort hdrlen, optpad = 0;
-	uchar *opt;
-
-	hdrlen = TCP6_HDRSIZE;
-	if(tcph->flags & SYN){
-		if(tcph->mss)
-			hdrlen += MSS_LENGTH;
-		if(tcph->ws)
-			hdrlen += WS_LENGTH;
-		optpad = hdrlen & 3;
-		if(optpad)
-			optpad = 4 - optpad;
-		hdrlen += optpad;
-	}
-
-	if(data) {
-		dlen = blocklen(data);
-		data = padblock(data, hdrlen + TCP6_PKT);
-		if(data == nil)
-			return nil;
-	}
-	else {
-		dlen = 0;
-		data = allocb(hdrlen + TCP6_PKT + 64);	/* the 64 pad is to meet mintu's */
-		if(data == nil)
-			return nil;
-		data->wp += hdrlen + TCP6_PKT;
-	}
-
-	/* copy in pseudo ip header plus port numbers */
-	h = (Tcp6hdr *)(data->rp);
-	memmove(h, ph, TCP6_TCBPHDRSZ);
-
-	/* compose pseudo tcp header, do cksum calculation */
-	hnputl(h->vcf, hdrlen + dlen);
-	h->ploadlen[0] = h->ploadlen[1] = h->proto = 0;
-	h->ttl = ph->proto;
-
-	/* copy in variable bits */
-	hnputl(h->tcpseq, tcph->seq);
-	hnputl(h->tcpack, tcph->ack);
-	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
-	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
-	hnputs(h->tcpurg, tcph->urg);
-
-	if(tcph->flags & SYN){
-		opt = h->tcpopt;
-		if(tcph->mss != 0){
-			*opt++ = MSSOPT;
-			*opt++ = MSS_LENGTH;
-			hnputs(opt, tcph->mss);
-			opt += 2;
-		}
-		if(tcph->ws != 0){
-			*opt++ = WSOPT;
-			*opt++ = WS_LENGTH;
-			*opt++ = tcph->ws;
-		}
-		while(optpad-- > 0)
-			*opt++ = NOOPOPT;
-	}
-
-	if(tcb != nil && tcb->nochecksum){
-		h->tcpcksum[0] = h->tcpcksum[1] = 0;
-	} else {
-		csum = ptclcsum(data, TCP6_IPLEN, hdrlen+dlen+TCP6_PHDRSIZE);
-		hnputs(h->tcpcksum, csum);
-	}
-
-	/* move from pseudo header back to normal ip header */
-	memset(h->vcf, 0, 4);
-	h->vcf[0] = IP_VER6;
-	hnputs(h->ploadlen, hdrlen+dlen);
-	h->proto = ph->proto;
-
-	return data;
-}
-
-static Block*
-htontcp4(Tcp *tcph, Block *data, Tcp4hdr *ph, Tcpctl *tcb)
-{
-	int dlen;
-	Tcp4hdr *h;
-	ushort csum;
-	ushort hdrlen, optpad = 0;
-	uchar *opt;
-
-	hdrlen = TCP4_HDRSIZE;
-	if(tcph->flags & SYN){
-		if(tcph->mss)
-			hdrlen += MSS_LENGTH;
-		if(1)
-			hdrlen += WS_LENGTH;
-		optpad = hdrlen & 3;
-		if(optpad)
-			optpad = 4 - optpad;
-		hdrlen += optpad;
-	}
-
-	if(data) {
-		dlen = blocklen(data);
-		data = padblock(data, hdrlen + TCP4_PKT);
-		if(data == nil)
-			return nil;
-	}
-	else {
-		dlen = 0;
-		data = allocb(hdrlen + TCP4_PKT + 64);	/* the 64 pad is to meet mintu's */
-		if(data == nil)
-			return nil;
-		data->wp += hdrlen + TCP4_PKT;
-	}
-
-	/* copy in pseudo ip header plus port numbers */
-	h = (Tcp4hdr *)(data->rp);
-	memmove(h, ph, TCP4_TCBPHDRSZ);
-
-	/* copy in variable bits */
-	hnputs(h->tcplen, hdrlen + dlen);
-	hnputl(h->tcpseq, tcph->seq);
-	hnputl(h->tcpack, tcph->ack);
-	hnputs(h->tcpflag, (hdrlen<<10) | tcph->flags);
-	hnputs(h->tcpwin, tcph->wnd>>(tcb != nil ? tcb->snd.scale : 0));
-	hnputs(h->tcpurg, tcph->urg);
-
-	if(tcph->flags & SYN){
-		opt = h->tcpopt;
-		if(tcph->mss != 0){
-			*opt++ = MSSOPT;
-			*opt++ = MSS_LENGTH;
-			hnputs(opt, tcph->mss);
-			opt += 2;
-		}
-		/* always offer.  rfc1323 §2.2 */
-		if(1){
-			*opt++ = WSOPT;
-			*opt++ = WS_LENGTH;
-			*opt++ = tcph->ws;
-		}
-		while(optpad-- > 0)
-			*opt++ = NOOPOPT;
-	}
-
-	if(tcb != nil && tcb->nochecksum){
-		h->tcpcksum[0] = h->tcpcksum[1] = 0;
-	} else {
-		csum = ptclcsum(data, TCP4_IPLEN, hdrlen+dlen+TCP4_PHDRSIZE);
-		hnputs(h->tcpcksum, csum);
-	}
-
-	return data;
-}
-
-static int
-ntohtcp6(Tcp *tcph, Block **bpp)
-{
-	Tcp6hdr *h;
-	uchar *optr;
-	ushort hdrlen;
-	ushort optlen;
-	int n;
-
-	*bpp = pullupblock(*bpp, TCP6_PKT+TCP6_HDRSIZE);
-	if(*bpp == nil)
-		return -1;
-
-	h = (Tcp6hdr *)((*bpp)->rp);
-	tcph->source = nhgets(h->tcpsport);
-	tcph->dest = nhgets(h->tcpdport);
-	tcph->seq = nhgetl(h->tcpseq);
-	tcph->ack = nhgetl(h->tcpack);
-	hdrlen = (h->tcpflag[0]>>2) & ~3;
-	if(hdrlen < TCP6_HDRSIZE) {
-		freeblist(*bpp);
-		return -1;
-	}
-
-	tcph->flags = h->tcpflag[1];
-	tcph->wnd = nhgets(h->tcpwin);
-	tcph->urg = nhgets(h->tcpurg);
-	tcph->mss = 0;
-	tcph->ws = 0;
-	tcph->update = 0;
-	tcph->len = nhgets(h->ploadlen) - hdrlen;
-
-	*bpp = pullupblock(*bpp, hdrlen+TCP6_PKT);
-	if(*bpp == nil)
-		return -1;
-
-	optr = h->tcpopt;
-	n = hdrlen - TCP6_HDRSIZE;
-	while(n > 0 && *optr != EOLOPT) {
-		if(*optr == NOOPOPT) {
-			n--;
-			optr++;
-			continue;
-		}
-		optlen = optr[1];
-		if(optlen < 2 || optlen > n)
-			break;
-		switch(*optr) {
-		case MSSOPT:
-			if(optlen == MSS_LENGTH)
-				tcph->mss = nhgets(optr+2);
-			break;
-		case WSOPT:
-			if(optlen == WS_LENGTH && *(optr+2) <= 14)
-				tcph->ws = *(optr+2);
-			break;
-		}
-		n -= optlen;
-		optr += optlen;
-	}
-	return hdrlen;
-}
-
-static int
-ntohtcp4(Tcp *tcph, Block **bpp)
-{
-	Tcp4hdr *h;
-	uchar *optr;
-	ushort hdrlen;
-	ushort optlen;
-	int n;
-
-	*bpp = pullupblock(*bpp, TCP4_PKT+TCP4_HDRSIZE);
-	if(*bpp == nil)
-		return -1;
-
-	h = (Tcp4hdr *)((*bpp)->rp);
-	tcph->source = nhgets(h->tcpsport);
-	tcph->dest = nhgets(h->tcpdport);
-	tcph->seq = nhgetl(h->tcpseq);
-	tcph->ack = nhgetl(h->tcpack);
-
-	hdrlen = (h->tcpflag[0]>>2) & ~3;
-	if(hdrlen < TCP4_HDRSIZE) {
-		freeblist(*bpp);
-		return -1;
-	}
-
-	tcph->flags = h->tcpflag[1];
-	tcph->wnd = nhgets(h->tcpwin);
-	tcph->urg = nhgets(h->tcpurg);
-	tcph->mss = 0;
-	tcph->ws = 0;
-	tcph->update = 0;
-	tcph->len = nhgets(h->length) - (hdrlen + TCP4_PKT);
-
-	*bpp = pullupblock(*bpp, hdrlen+TCP4_PKT);
-	if(*bpp == nil)
-		return -1;
-
-	optr = h->tcpopt;
-	n = hdrlen - TCP4_HDRSIZE;
-	while(n > 0 && *optr != EOLOPT) {
-		if(*optr == NOOPOPT) {
-			n--;
-			optr++;
-			continue;
-		}
-		optlen = optr[1];
-		if(optlen < 2 || optlen > n)
-			break;
-		switch(*optr) {
-		case MSSOPT:
-			if(optlen == MSS_LENGTH)
-				tcph->mss = nhgets(optr+2);
-			break;
-		case WSOPT:
-			if(optlen == WS_LENGTH && *(optr+2) <= 14)
-				tcph->ws = *(optr+2);
-			break;
-		}
-		n -= optlen;
-		optr += optlen;
-	}
-	return hdrlen;
-}
-
-/*
- *  For outgoing calls, generate an initial sequence
- *  number and put a SYN on the send queue
- */
-static void
-tcpsndsyn(Conv *s, Tcpctl *tcb)
-{
-	Tcppriv *tpriv;
-
-	tcb->iss = (nrand(1<<16)<<16)|nrand(1<<16);
-	tcb->rttseq = tcb->iss;
-	tcb->snd.wl2 = tcb->iss;
-	tcb->snd.una = tcb->iss;
-	tcb->snd.rxt = tcb->iss;
-	tcb->snd.ptr = tcb->rttseq;
-	tcb->snd.nxt = tcb->rttseq;
-	tcb->flgcnt++;
-	tcb->flags |= FORCE;
-	tcb->sndsyntime = NOW;
-
-	/* set desired mss and scale */
-	tcb->mss = tcpmtu(s->p, s->laddr, s->ipversion, &tcb->scale);
-	tpriv = s->p->priv;
-	tpriv->stats[Mss] = tcb->mss;
-}
-
-void
-sndrst(Proto *tcp, uchar *source, uchar *dest, ushort length, Tcp *seg, uchar version, char *reason)
-{
-	Block *hbp;
-	uchar rflags;
-	Tcppriv *tpriv;
-	Tcp4hdr ph4;
-	Tcp6hdr ph6;
-
-	netlog(tcp->f, Logtcp, "sndrst: %s\n", reason);
-
-	tpriv = tcp->priv;
-
-	if(seg->flags & RST)
-		return;
-
-	/* make pseudo header */
-	switch(version) {
-	case V4:
-		memset(&ph4, 0, sizeof(ph4));
-		ph4.vihl = IP_VER4;
-		v6tov4(ph4.tcpsrc, dest);
-		v6tov4(ph4.tcpdst, source);
-		ph4.proto = IP_TCPPROTO;
-		hnputs(ph4.tcplen, TCP4_HDRSIZE);
-		hnputs(ph4.tcpsport, seg->dest);
-		hnputs(ph4.tcpdport, seg->source);
-		break;
-	case V6:
-		memset(&ph6, 0, sizeof(ph6));
-		ph6.vcf[0] = IP_VER6;
-		ipmove(ph6.tcpsrc, dest);
-		ipmove(ph6.tcpdst, source);
-		ph6.proto = IP_TCPPROTO;
-		hnputs(ph6.ploadlen, TCP6_HDRSIZE);
-		hnputs(ph6.tcpsport, seg->dest);
-		hnputs(ph6.tcpdport, seg->source);
-		break;
-	default:
-		panic("sndrst: version %d", version);
-	}
-
-	tpriv->stats[OutRsts]++;
-	rflags = RST;
-
-	/* convince the other end that this reset is in band */
-	if(seg->flags & ACK) {
-		seg->seq = seg->ack;
-		seg->ack = 0;
-	}
-	else {
-		rflags |= ACK;
-		seg->ack = seg->seq;
-		seg->seq = 0;
-		if(seg->flags & SYN)
-			seg->ack++;
-		seg->ack += length;
-		if(seg->flags & FIN)
-			seg->ack++;
-	}
-	seg->flags = rflags;
-	seg->wnd = 0;
-	seg->urg = 0;
-	seg->mss = 0;
-	seg->ws = 0;
-	switch(version) {
-	case V4:
-		hbp = htontcp4(seg, nil, &ph4, nil);
-		if(hbp == nil)
-			return;
-		ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	case V6:
-		hbp = htontcp6(seg, nil, &ph6, nil);
-		if(hbp == nil)
-			return;
-		ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	default:
-		panic("sndrst2: version %d", version);
-	}
-}
-
-/*
- *  send a reset to the remote side and close the conversation
- *  called with s qlocked
- */
-static char*
-tcphangup(Conv *s)
-{
-	Tcp seg;
-	Tcpctl *tcb;
-	Block *hbp;
-
-	tcb = (Tcpctl*)s->ptcl;
-	if(waserror())
-		return commonerror();
-	if(ipcmp(s->raddr, IPnoaddr) != 0) {
-		if(!waserror()){
-			memset(&seg, 0, sizeof seg);
-			seg.flags = RST | ACK;
-			seg.ack = tcb->rcv.nxt;
-			tcb->rcv.ackptr = seg.ack;
-			seg.seq = tcb->snd.ptr;
-			seg.wnd = 0;
-			seg.urg = 0;
-			seg.mss = 0;
-			seg.ws = 0;
-			switch(s->ipversion) {
-			case V4:
-				tcb->protohdr.tcp4hdr.vihl = IP_VER4;
-				hbp = htontcp4(&seg, nil, &tcb->protohdr.tcp4hdr, tcb);
-				ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
-				break;
-			case V6:
-				tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
-				hbp = htontcp6(&seg, nil, &tcb->protohdr.tcp6hdr, tcb);
-				ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
-				break;
-			default:
-				panic("tcphangup: version %d", s->ipversion);
-			}
-			poperror();
-		}
-	}
-	localclose(s, nil);
-	poperror();
-	return nil;
-}
-
-/*
- *  (re)send a SYN ACK
- */
-static int
-sndsynack(Proto *tcp, Limbo *lp)
-{
-	Block *hbp;
-	Tcp4hdr ph4;
-	Tcp6hdr ph6;
-	Tcp seg;
-	uint scale;
-
-	/* make pseudo header */
-	switch(lp->version) {
-	case V4:
-		memset(&ph4, 0, sizeof(ph4));
-		ph4.vihl = IP_VER4;
-		v6tov4(ph4.tcpsrc, lp->laddr);
-		v6tov4(ph4.tcpdst, lp->raddr);
-		ph4.proto = IP_TCPPROTO;
-		hnputs(ph4.tcplen, TCP4_HDRSIZE);
-		hnputs(ph4.tcpsport, lp->lport);
-		hnputs(ph4.tcpdport, lp->rport);
-		break;
-	case V6:
-		memset(&ph6, 0, sizeof(ph6));
-		ph6.vcf[0] = IP_VER6;
-		ipmove(ph6.tcpsrc, lp->laddr);
-		ipmove(ph6.tcpdst, lp->raddr);
-		ph6.proto = IP_TCPPROTO;
-		hnputs(ph6.ploadlen, TCP6_HDRSIZE);
-		hnputs(ph6.tcpsport, lp->lport);
-		hnputs(ph6.tcpdport, lp->rport);
-		break;
-	default:
-		panic("sndrst: version %d", lp->version);
-	}
-
-	memset(&seg, 0, sizeof seg);
-	seg.seq = lp->iss;
-	seg.ack = lp->irs+1;
-	seg.flags = SYN|ACK;
-	seg.urg = 0;
-	seg.mss = tcpmtu(tcp, lp->laddr, lp->version, &scale);
-	seg.wnd = QMAX;
-
-	/* if the other side set scale, we should too */
-	if(lp->rcvscale){
-		seg.ws = scale;
-		lp->sndscale = scale;
-	} else {
-		seg.ws = 0;
-		lp->sndscale = 0;
-	}
-
-	switch(lp->version) {
-	case V4:
-		hbp = htontcp4(&seg, nil, &ph4, nil);
-		if(hbp == nil)
-			return -1;
-		ipoput4(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	case V6:
-		hbp = htontcp6(&seg, nil, &ph6, nil);
-		if(hbp == nil)
-			return -1;
-		ipoput6(tcp->f, hbp, 0, MAXTTL, DFLTTOS, nil);
-		break;
-	default:
-		panic("sndsnack: version %d", lp->version);
-	}
-	lp->lastsend = NOW;
-	return 0;
-}
-
-#define hashipa(a, p) ( ( (a)[IPaddrlen-2] + (a)[IPaddrlen-1] + p )&LHTMASK )
-
-/*
- *  put a call into limbo and respond with a SYN ACK
- *
- *  called with proto locked
- */
-static void
-limbo(Conv *s, uchar *source, uchar *dest, Tcp *seg, int version)
-{
-	Limbo *lp, **l;
-	Tcppriv *tpriv;
-	int h;
-
-	tpriv = s->p->priv;
-	h = hashipa(source, seg->source);
-
-	for(l = &tpriv->lht[h]; *l != nil; l = &lp->next){
-		lp = *l;
-		if(lp->lport != seg->dest || lp->rport != seg->source || lp->version != version)
-			continue;
-		if(ipcmp(lp->raddr, source) != 0)
-			continue;
-		if(ipcmp(lp->laddr, dest) != 0)
-			continue;
-
-		/* each new SYN restarts the retransmits */
-		lp->irs = seg->seq;
-		break;
-	}
-	lp = *l;
-	if(lp == nil){
-		if(tpriv->nlimbo >= Maxlimbo && tpriv->lht[h]){
-			lp = tpriv->lht[h];
-			tpriv->lht[h] = lp->next;
-			lp->next = nil;
-		} else {
-			lp = malloc(sizeof(*lp));
-			if(lp == nil)
-				return;
-			tpriv->nlimbo++;
-		}
-		*l = lp;
-		lp->version = version;
-		ipmove(lp->laddr, dest);
-		ipmove(lp->raddr, source);
-		lp->lport = seg->dest;
-		lp->rport = seg->source;
-		lp->mss = seg->mss;
-		lp->rcvscale = seg->ws;
-		lp->irs = seg->seq;
-		lp->iss = (nrand(1<<16)<<16)|nrand(1<<16);
-	}
-
-	if(sndsynack(s->p, lp) < 0){
-		*l = lp->next;
-		tpriv->nlimbo--;
-		free(lp);
-	}
-}
-
-/*
- *  resend SYN ACK's once every SYNACK_RXTIMER ms.
- */
-static void
-limborexmit(Proto *tcp)
-{
-	Tcppriv *tpriv;
-	Limbo **l, *lp;
-	int h;
-	int seen;
-	ulong now;
-
-	tpriv = tcp->priv;
-
-	if(!canqlock(tcp))
-		return;
-	seen = 0;
-	now = NOW;
-	for(h = 0; h < NLHT && seen < tpriv->nlimbo; h++){
-		for(l = &tpriv->lht[h]; *l != nil && seen < tpriv->nlimbo; ){
-			lp = *l;
-			seen++;
-			if(now - lp->lastsend < (lp->rexmits+1)*SYNACK_RXTIMER)
-				continue;
-
-			/* time it out after 1 second */
-			if(++(lp->rexmits) > 5){
-				tpriv->nlimbo--;
-				*l = lp->next;
-				free(lp);
-				continue;
-			}
-
-			/* if we're being attacked, don't bother resending SYN ACK's */
-			if(tpriv->nlimbo > 100)
-				continue;
-
-			if(sndsynack(tcp, lp) < 0){
-				tpriv->nlimbo--;
-				*l = lp->next;
-				free(lp);
-				continue;
-			}
-
-			l = &lp->next;
-		}
-	}
-	qunlock(tcp);
-}
-
-/*
- *  lookup call in limbo.  if found, throw it out.
- *
- *  called with proto locked
- */
-static void
-limborst(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
-{
-	Limbo *lp, **l;
-	int h;
-	Tcppriv *tpriv;
-
-	tpriv = s->p->priv;
-
-	/* find a call in limbo */
-	h = hashipa(src, segp->source);
-	for(l = &tpriv->lht[h]; *l != nil; l = &lp->next){
-		lp = *l;
-		if(lp->lport != segp->dest || lp->rport != segp->source || lp->version != version)
-			continue;
-		if(ipcmp(lp->laddr, dst) != 0)
-			continue;
-		if(ipcmp(lp->raddr, src) != 0)
-			continue;
-
-		/* RST can only follow the SYN */
-		if(segp->seq == lp->irs+1){
-			tpriv->nlimbo--;
-			*l = lp->next;
-			free(lp);
-		}
-		break;
-	}
-}
-
-static void
-initialwindow(Tcpctl *tcb)
-{
-	/* RFC 3390 initial window */
-	if(tcb->mss < 1095)
-		tcb->cwind = 4*tcb->mss;
-	else if(tcb->mss < 2190)
-		tcb->cwind = 2*2190;
-	else
-		tcb->cwind = 2*tcb->mss;
-}
-
-/*
- *  come here when we finally get an ACK to our SYN-ACK.
- *  lookup call in limbo.  if found, create a new conversation
- *
- *  called with proto locked
- */
-static Conv*
-tcpincoming(Conv *s, Tcp *segp, uchar *src, uchar *dst, uchar version)
-{
-	Conv *new;
-	Tcpctl *tcb;
-	Tcppriv *tpriv;
-	Tcp4hdr *h4;
-	Tcp6hdr *h6;
-	Limbo *lp, **l;
-	int h;
-
-	/* unless it's just an ack, it can't be someone coming out of limbo */
-	if((segp->flags & SYN) || (segp->flags & ACK) == 0)
-		return nil;
-
-	tpriv = s->p->priv;
-
-	/* find a call in limbo */
-	h = hashipa(src, segp->source);
-	for(l = &tpriv->lht[h]; (lp = *l) != nil; l = &lp->next){
-		netlog(s->p->f, Logtcp, "tcpincoming s %I!%ud/%I!%ud d %I!%ud/%I!%ud v %d/%d\n",
-			src, segp->source, lp->raddr, lp->rport,
-			dst, segp->dest, lp->laddr, lp->lport,
-			version, lp->version
- 		);
-
-		if(lp->lport != segp->dest || lp->rport != segp->source || lp->version != version)
-			continue;
-		if(ipcmp(lp->laddr, dst) != 0)
-			continue;
-		if(ipcmp(lp->raddr, src) != 0)
-			continue;
-
-		/* we're assuming no data with the initial SYN */
-		if(segp->seq != lp->irs+1 || segp->ack != lp->iss+1){
-			netlog(s->p->f, Logtcp, "tcpincoming s %lux/%lux a %lux %lux\n",
-				segp->seq, lp->irs+1, segp->ack, lp->iss+1);
-			lp = nil;
-		} else {
-			tpriv->nlimbo--;
-			*l = lp->next;
-		}
-		break;
-	}
-	if(lp == nil)
-		return nil;
-
-	new = Fsnewcall(s, src, segp->source, dst, segp->dest, version);
-	if(new == nil)
-		return nil;
-
-	memmove(new->ptcl, s->ptcl, sizeof(Tcpctl));
-	tcb = (Tcpctl*)new->ptcl;
-	tcb->flags &= ~CLONE;
-	tcb->timer.arg = new;
-	tcb->timer.state = TcptimerOFF;
-	tcb->acktimer.arg = new;
-	tcb->acktimer.state = TcptimerOFF;
-	tcb->katimer.arg = new;
-	tcb->katimer.state = TcptimerOFF;
-	tcb->rtt_timer.arg = new;
-	tcb->rtt_timer.state = TcptimerOFF;
-
-	tcb->irs = lp->irs;
-	tcb->rcv.nxt = tcb->irs+1;
-	tcb->rcv.wptr = tcb->rcv.nxt;
-	tcb->rcv.wsnt = 0;
-	tcb->rcv.urg = tcb->rcv.nxt;
-
-	tcb->iss = lp->iss;
-	tcb->rttseq = tcb->iss;
-	tcb->snd.wl2 = tcb->iss;
-	tcb->snd.una = tcb->iss+1;
-	tcb->snd.ptr = tcb->iss+1;
-	tcb->snd.nxt = tcb->iss+1;
-	tcb->snd.rxt = tcb->iss+1;
-	tcb->flgcnt = 0;
-	tcb->flags |= SYNACK;
-
-	/* our sending max segment size cannot be bigger than what he asked for */
-	if(lp->mss != 0 && lp->mss < tcb->mss) {
-		tcb->mss = lp->mss;
-		tpriv->stats[Mss] = tcb->mss;
-	}
-
-	/* window scaling */
-	tcpsetscale(new, tcb, lp->rcvscale, lp->sndscale);
-
-	/* congestion window */
-	tcb->snd.wnd = segp->wnd;
-	initialwindow(tcb);
-
-	/* set initial round trip time */
-	tcb->sndsyntime = lp->lastsend+lp->rexmits*SYNACK_RXTIMER;
-	tcpsynackrtt(new);
-
-	free(lp);
-
-	/* set up proto header */
-	switch(version){
-	case V4:
-		h4 = &tcb->protohdr.tcp4hdr;
-		memset(h4, 0, sizeof(*h4));
-		h4->proto = IP_TCPPROTO;
-		hnputs(h4->tcpsport, new->lport);
-		hnputs(h4->tcpdport, new->rport);
-		v6tov4(h4->tcpsrc, dst);
-		v6tov4(h4->tcpdst, src);
-		break;
-	case V6:
-		h6 = &tcb->protohdr.tcp6hdr;
-		memset(h6, 0, sizeof(*h6));
-		h6->proto = IP_TCPPROTO;
-		hnputs(h6->tcpsport, new->lport);
-		hnputs(h6->tcpdport, new->rport);
-		ipmove(h6->tcpsrc, dst);
-		ipmove(h6->tcpdst, src);
-		break;
-	default:
-		panic("tcpincoming: version %d", new->ipversion);
-	}
-
-	tcpsetstate(new, Established);
-
-	iphtadd(&tpriv->ht, new);
-
-	return new;
-}
-
-static int
-seq_within(ulong x, ulong low, ulong high)
-{
-	if(low <= high){
-		if(low <= x && x <= high)
-			return 1;
-	}
-	else {
-		if(x >= low || x <= high)
-			return 1;
-	}
-	return 0;
-}
-
-static int
-seq_lt(ulong x, ulong y)
-{
-	return (int)(x-y) < 0;
-}
-
-static int
-seq_le(ulong x, ulong y)
-{
-	return (int)(x-y) <= 0;
-}
-
-static int
-seq_gt(ulong x, ulong y)
-{
-	return (int)(x-y) > 0;
-}
-
-static int
-seq_ge(ulong x, ulong y)
-{
-	return (int)(x-y) >= 0;
-}
-
-/*
- *  use the time between the first SYN and it's ack as the
- *  initial round trip time
- */
-static void
-tcpsynackrtt(Conv *s)
-{
-	Tcpctl *tcb;
-	int delta;
-	Tcppriv *tpriv;
-
-	tcb = (Tcpctl*)s->ptcl;
-	tpriv = s->p->priv;
-
-	delta = NOW - tcb->sndsyntime;
-	tcb->srtt = delta<<LOGAGAIN;
-	tcb->mdev = delta<<LOGDGAIN;
-
-	/* halt round trip timer */
-	tcphalt(tpriv, &tcb->rtt_timer);
-}
-
-static void
-update(Conv *s, Tcp *seg)
-{
-	int rtt, delta;
-	Tcpctl *tcb;
-	ulong acked;
-	Tcppriv *tpriv;
-
-	if(seg->update)
-		return;
-	seg->update = 1;
-
-	tpriv = s->p->priv;
-	tcb = (Tcpctl*)s->ptcl;
-
-	/* catch zero-window updates, update window & recover */
-	if(tcb->snd.wnd == 0 && seg->wnd > 0 &&
-	    seq_lt(seg->ack, tcb->snd.ptr)){
-		netlog(s->p->f, Logtcp, "tcp: zwu ack %lud una %lud ptr %lud win %lud\n",
-			seg->ack,  tcb->snd.una, tcb->snd.ptr, seg->wnd);
-		tcb->snd.wnd = seg->wnd;
-		goto recovery;
-	}
-
-	/* newreno fast retransmit */
-	if(seg->ack == tcb->snd.una && tcb->snd.una != tcb->snd.nxt &&
-	    ++tcb->snd.dupacks == 3){		/* was TCPREXMTTHRESH */
-recovery:
-		if(tcb->snd.recovery){
-			tpriv->stats[RecoveryCwind]++;
-			tcb->cwind += tcb->mss;
-		}else if(seq_le(tcb->snd.rxt, seg->ack)){
-			tpriv->stats[Recovery]++;
-			tcb->abcbytes = 0;
-			tcb->snd.recovery = 1;
-			tcb->snd.partialack = 0;
-			tcb->snd.rxt = tcb->snd.nxt;
-			tcpcongestion(tcb);
-			tcb->cwind = tcb->ssthresh + 3*tcb->mss;
-			netlog(s->p->f, Logtcpwin, "recovery inflate %ld ss %ld @%lud\n",
-				tcb->cwind, tcb->ssthresh, tcb->snd.rxt);
-			tcprxmit(s);
-		}else{
-			tpriv->stats[RecoveryNoSeq]++;
-			netlog(s->p->f, Logtcpwin, "!recov %lud not ≤ %lud %ld\n",
-				tcb->snd.rxt, seg->ack, tcb->snd.rxt - seg->ack);
-			/* don't enter fast retransmit, don't change ssthresh */
-		}
-	}else if(tcb->snd.recovery){
-		tpriv->stats[RecoveryCwind]++;
-		tcb->cwind += tcb->mss;
-	}
-
-	/*
-	 *  update window
-	 */
-	if(seq_gt(seg->ack, tcb->snd.wl2)
-	|| (tcb->snd.wl2 == seg->ack && seg->wnd > tcb->snd.wnd)){
-		/* clear dupack if we advance wl2 */
-		if(tcb->snd.wl2 != seg->ack)
-			tcb->snd.dupacks = 0;
-		tcb->snd.wnd = seg->wnd;
-		tcb->snd.wl2 = seg->ack;
-	}
-
-	if(!seq_gt(seg->ack, tcb->snd.una)){
-		/*
-		 *  don't let us hangup if sending into a closed window and
-		 *  we're still getting acks
-		 */
-		if((tcb->flags&RETRAN) && tcb->snd.wnd == 0)
-			tcb->backedoff = MAXBACKMS/4;
-		return;
-	}
-
-	/* Compute the new send window size */
-	acked = seg->ack - tcb->snd.una;
-
-	/* avoid slow start and timers for SYN acks */
-	if((tcb->flags & SYNACK) == 0) {
-		tcb->flags |= SYNACK;
-		acked--;
-		tcb->flgcnt--;
-		goto done;
-	}
-
-	/*
-	 * congestion control
-	 */
-	if(tcb->snd.recovery){
-		if(seq_ge(seg->ack, tcb->snd.rxt)){
-			/* recovery finished; deflate window */
-			tpriv->stats[RecoveryDone]++;
-			tcb->snd.dupacks = 0;
-			tcb->snd.recovery = 0;
-			tcb->cwind = (tcb->snd.nxt - tcb->snd.una) + tcb->mss;
-			if(tcb->ssthresh < tcb->cwind)
-				tcb->cwind = tcb->ssthresh;
-			netlog(s->p->f, Logtcpwin, "recovery deflate %ld %ld\n",
-				tcb->cwind, tcb->ssthresh);
-		} else {
-			/* partial ack; we lost more than one segment */
-			tpriv->stats[RecoveryPA]++;
-			if(tcb->cwind > acked)
-				tcb->cwind -= acked;
-			else{
-				netlog(s->p->f, Logtcpwin, "partial ack neg\n");
-				tcb->cwind = tcb->mss;
-			}
-			netlog(s->p->f, Logtcpwin, "partial ack %ld left %ld cwind %ld\n",
-				acked, tcb->snd.rxt - seg->ack, tcb->cwind);
-
-			if(acked >= tcb->mss)
-				tcb->cwind += tcb->mss;
-			tcb->snd.partialack++;
-		}
-	} else
-		tcpabcincr(tcb, acked);
-
-	/* Adjust the timers according to the round trip time */
-	/* TODO: fix sloppy treatment of overflow cases here. */
-	if(tcb->rtt_timer.state == TcptimerON && seq_ge(seg->ack, tcb->rttseq)) {
-		tcphalt(tpriv, &tcb->rtt_timer);
-		if((tcb->flags&RETRAN) == 0) {
-			tcb->backoff = 0;
-			tcb->backedoff = 0;
-			rtt = tcb->rtt_timer.start - tcb->rtt_timer.count;
-			if(rtt == 0)
-				rtt = 1; /* else all close sys's will rexmit in 0 time */
-			rtt *= MSPTICK;
-			if(tcb->srtt == 0) {
-				tcb->srtt = rtt << LOGAGAIN;
-				tcb->mdev = rtt << LOGDGAIN;
-			} else {
-				delta = rtt - (tcb->srtt>>LOGAGAIN);
-				tcb->srtt += delta;
-				if(tcb->srtt <= 0)
-					tcb->srtt = 1;
-
-				delta = abs(delta) - (tcb->mdev>>LOGDGAIN);
-				tcb->mdev += delta;
-				if(tcb->mdev <= 0)
-					tcb->mdev = 1;
-			}
-			tcpsettimer(tcb);
-		}
-	}
-
-done:
-	if(qdiscard(s->wq, acked) < acked)
-		tcb->flgcnt--;
-	tcb->snd.una = seg->ack;
-
-	/* newreno fast recovery */
-	if(tcb->snd.recovery)
-		tcprxmit(s);
-
-	if(seq_gt(seg->ack, tcb->snd.urg))
-		tcb->snd.urg = seg->ack;
-
-	if(tcb->snd.una != tcb->snd.nxt){
-		/* `impatient' variant */
-		if(!tcb->snd.recovery || tcb->snd.partialack == 1){
-			tcb->time = NOW;
-			tcb->timeuna = tcb->snd.una;
-			tcpgo(tpriv, &tcb->timer);
-		}
-	} else
-		tcphalt(tpriv, &tcb->timer);
-
-	if(seq_lt(tcb->snd.ptr, tcb->snd.una))
-		tcb->snd.ptr = tcb->snd.una;
-
-	if(!tcb->snd.recovery)
-		tcb->flags &= ~RETRAN;
-	tcb->backoff = 0;
-	tcb->backedoff = 0;
-}
-
-static void
-tcpiput(Proto *tcp, Ipifc*, Block *bp)
-{
-	Tcp seg;
-	Tcp4hdr *h4;
-	Tcp6hdr *h6;
-	int hdrlen;
-	Tcpctl *tcb;
-	ushort length, csum;
-	uchar source[IPaddrlen], dest[IPaddrlen];
-	Conv *s;
-	Fs *f;
-	Tcppriv *tpriv;
-	uchar version;
-
-	f = tcp->f;
-	tpriv = tcp->priv;
-
-	tpriv->stats[InSegs]++;
-
-	h4 = (Tcp4hdr*)(bp->rp);
-	h6 = (Tcp6hdr*)(bp->rp);
-
-	if((h4->vihl&0xF0)==IP_VER4) {
-		version = V4;
-		length = nhgets(h4->length);
-		v4tov6(dest, h4->tcpdst);
-		v4tov6(source, h4->tcpsrc);
-
-		h4->Unused = 0;
-		hnputs(h4->tcplen, length-TCP4_PKT);
-		if(!(bp->flag & Btcpck) && (h4->tcpcksum[0] || h4->tcpcksum[1]) &&
-			ptclcsum(bp, TCP4_IPLEN, length-TCP4_IPLEN)) {
-			tpriv->stats[CsumErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp, "bad tcp proto cksum\n");
-			freeblist(bp);
-			return;
-		}
-
-		hdrlen = ntohtcp4(&seg, &bp);
-		if(hdrlen < 0){
-			tpriv->stats[HlenErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp, "bad tcp hdr len\n");
-			return;
-		}
-
-		/* trim the packet to the size claimed by the datagram */
-		length -= hdrlen+TCP4_PKT;
-		bp = trimblock(bp, hdrlen+TCP4_PKT, length);
-		if(bp == nil){
-			tpriv->stats[LenErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp, "tcp len < 0 after trim\n");
-			return;
-		}
-	}
-	else {
-		int ttl = h6->ttl;
-		int proto = h6->proto;
-
-		version = V6;
-		length = nhgets(h6->ploadlen);
-		ipmove(dest, h6->tcpdst);
-		ipmove(source, h6->tcpsrc);
-
-		h6->ploadlen[0] = h6->ploadlen[1] = h6->proto = 0;
-		h6->ttl = proto;
-		hnputl(h6->vcf, length);
-		if((h6->tcpcksum[0] || h6->tcpcksum[1]) &&
-		    (csum = ptclcsum(bp, TCP6_IPLEN, length+TCP6_PHDRSIZE)) != 0) {
-			tpriv->stats[CsumErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp,
-			    "bad tcpv6 proto cksum: got %#ux, computed %#ux\n",
-				h6->tcpcksum[0]<<8 | h6->tcpcksum[1], csum);
-			freeblist(bp);
-			return;
-		}
-		h6->ttl = ttl;
-		h6->proto = proto;
-		hnputs(h6->ploadlen, length);
-
-		hdrlen = ntohtcp6(&seg, &bp);
-		if(hdrlen < 0){
-			tpriv->stats[HlenErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp, "bad tcpv6 hdr len\n");
-			return;
-		}
-
-		/* trim the packet to the size claimed by the datagram */
-		length -= hdrlen;
-		bp = trimblock(bp, hdrlen+TCP6_PKT, length);
-		if(bp == nil){
-			tpriv->stats[LenErrs]++;
-			tpriv->stats[InErrs]++;
-			netlog(f, Logtcp, "tcpv6 len < 0 after trim\n");
-			return;
-		}
-	}
-
-	/* lock protocol while searching for a conversation */
-	qlock(tcp);
-
-	/* Look for a matching conversation */
-	s = iphtlook(&tpriv->ht, source, seg.source, dest, seg.dest);
-	if(s == nil){
-		netlog(f, Logtcp, "iphtlook(src %I!%d, dst %I!%d) failed\n",
-			source, seg.source, dest, seg.dest);
-reset:
-		qunlock(tcp);
-		sndrst(tcp, source, dest, length, &seg, version, "no conversation");
-		freeblist(bp);
-		return;
-	}
-
-	/* if it's a listener, look for the right flags and get a new conv */
-	tcb = (Tcpctl*)s->ptcl;
-	if(tcb->state == Listen){
-		if(seg.flags & RST){
-			limborst(s, &seg, source, dest, version);
-			qunlock(tcp);
-			freeblist(bp);
-			return;
-		}
-
-		/* if this is a new SYN, put the call into limbo */
-		if((seg.flags & SYN) && (seg.flags & ACK) == 0){
-			limbo(s, source, dest, &seg, version);
-			qunlock(tcp);
-			freeblist(bp);
-			return;
-		}
-
-		/*
-		 *  if there's a matching call in limbo, tcpincoming will
-		 *  return it in state Syn_received
-		 */
-		s = tcpincoming(s, &seg, source, dest, version);
-		if(s == nil)
-			goto reset;
-	}
-
-	/* The rest of the input state machine is run with the control block
-	 * locked and implements the state machine directly out of the RFC.
-	 * Out-of-band data is ignored - it was always a bad idea.
-	 */
-	tcb = (Tcpctl*)s->ptcl;
-	if(waserror()){
-		qunlock(s);
-		nexterror();
-	}
-	qlock(s);
-	qunlock(tcp);
-
-	/* fix up window */
-	seg.wnd <<= tcb->rcv.scale;
-
-	/* every input packet in puts off the keep alive time out */
-	tcpsetkacounter(tcb);
-
-	switch(tcb->state) {
-	case Closed:
-		sndrst(tcp, source, dest, length, &seg, version, "sending to Closed");
-		goto raise;
-	case Syn_sent:
-		if(seg.flags & ACK) {
-			if(!seq_within(seg.ack, tcb->iss+1, tcb->snd.nxt)) {
-				sndrst(tcp, source, dest, length, &seg, version,
-					 "bad seq in Syn_sent");
-				goto raise;
-			}
-		}
-		if(seg.flags & RST) {
-			if(seg.flags & ACK)
-				localclose(s, Econrefused);
-			goto raise;
-		}
-
-		if(seg.flags & SYN) {
-			procsyn(s, &seg);
-			if(seg.flags & ACK){
-				update(s, &seg);
-				tcpsynackrtt(s);
-				tcpsetstate(s, Established);
-				tcpsetscale(s, tcb, seg.ws, tcb->scale);
-			}
-			else {
-				tcb->time = NOW;
-				tcpsetstate(s, Syn_received);	/* DLP - shouldn't this be a reset? */
-			}
-
-			if(length != 0 || (seg.flags & FIN))
-				break;
-
-			freeblist(bp);
-			goto output;
-		}
-		else
-			freeblist(bp);
-
-		qunlock(s);
-		poperror();
-		return;
-	case Syn_received:
-		/* doesn't matter if it's the correct ack, we're just trying to set timing */
-		if(seg.flags & ACK)
-			tcpsynackrtt(s);
-		break;
-	}
-
-	/*
-	 *  One DOS attack is to open connections to us and then forget about them,
-	 *  thereby tying up a conv at no long term cost to the attacker.
-	 *  This is an attempt to defeat these stateless DOS attacks.  See
-	 *  corresponding code in tcpsendka().
-	 */
-	if(tcb->state != Syn_received && (seg.flags & RST) == 0){
-		if(tcpporthogdefense
-		&& seq_within(seg.ack, tcb->snd.una-(1<<31), tcb->snd.una-(1<<29))){
-			print("stateless hog %I.%d->%I.%d f %ux %lux - %lux - %lux\n",
-				source, seg.source, dest, seg.dest, seg.flags,
-				tcb->snd.una-(1<<31), seg.ack, tcb->snd.una-(1<<29));
-			localclose(s, "stateless hog");
-		}
-	}
-
-	/* Cut the data to fit the receive window */
-	tcprcvwin(s);
-	if(tcptrim(tcb, &seg, &bp, &length) == -1) {
-		if(seg.seq+1 != tcb->rcv.nxt || length != 1)
-		netlog(f, Logtcp, "tcp: trim: !inwind: seq %lud-%lud win "
-			"%lud-%lud l %d from %I\n", seg.seq,
-			seg.seq + length - 1, tcb->rcv.nxt,
-			tcb->rcv.nxt + tcb->rcv.wnd-1, length, s->raddr);
-		update(s, &seg);
-		if(qlen(s->wq)+tcb->flgcnt == 0 && tcb->state == Closing) {
-			tcphalt(tpriv, &tcb->rtt_timer);
-			tcphalt(tpriv, &tcb->acktimer);
-			tcphalt(tpriv, &tcb->katimer);
-			tcpsetstate(s, Time_wait);
-			tcb->timer.start = MSL2*(1000 / MSPTICK);
-			tcpgo(tpriv, &tcb->timer);
-		}
-		if(!(seg.flags & RST)) {
-			tcb->flags |= FORCE;
-			goto output;
-		}
-		qunlock(s);
-		poperror();
-		return;
-	}
-
-	/* Cannot accept so answer with a rst */
-	if(length && tcb->state == Closed) {
-		sndrst(tcp, source, dest, length, &seg, version, "sending to Closed");
-		goto raise;
-	}
-
-	/* The segment is beyond the current receive pointer so
-	 * queue the data in the resequence queue
-	 */
-	if(seg.seq != tcb->rcv.nxt)
-	if(length != 0 || (seg.flags & (SYN|FIN))) {
-		update(s, &seg);
-		if(addreseq(f, tcb, tpriv, &seg, bp, length) < 0)
-			print("reseq %I.%d -> %I.%d\n", s->raddr, s->rport,
-				s->laddr, s->lport);
-		tcb->flags |= FORCE;	/* force duplicate ack; RFC 5681 §3.2 */
-		goto output;
-	}
-
-	if(tcb->nreseq > 0)
-		tcb->flags |= FORCE; /* filled hole in seq. space; RFC 5681 §3.2 */
-
-	/*
-	 *  keep looping till we've processed this packet plus any
-	 *  adjacent packets in the resequence queue
-	 */
-	for(;;) {
-		if(seg.flags & RST) {
-			if(tcb->state == Established) {
-				tpriv->stats[EstabResets]++;
-				if(tcb->rcv.nxt != seg.seq)
-					netlog(f, Logtcp, "out of order RST "
-						"rcvd: %I.%d -> %I.%d, rcv.nxt "
-						"%lux seq %lux\n",
-						s->raddr, s->rport, s->laddr,
-						s->lport, tcb->rcv.nxt, seg.seq);
-			}
-			localclose(s, Econrefused);
-			goto raise;
-		}
-
-		if((seg.flags&ACK) == 0)
-			goto raise;
-
-		switch(tcb->state) {
-		case Syn_received:
-			if(!seq_within(seg.ack, tcb->snd.una+1, tcb->snd.nxt)){
-				sndrst(tcp, source, dest, length, &seg, version,
-					"bad seq in Syn_received");
-				goto raise;
-			}
-			update(s, &seg);
-			tcpsetstate(s, Established);
-		case Established:
-		case Close_wait:
-			update(s, &seg);
-			break;
-		case Finwait1:
-			update(s, &seg);
-			if(qlen(s->wq)+tcb->flgcnt == 0){
-				tcphalt(tpriv, &tcb->rtt_timer);
-				tcphalt(tpriv, &tcb->acktimer);
-				tcpsetkacounter(tcb);
-				tcb->time = NOW;
-				tcpsetstate(s, Finwait2);
-				tcb->katimer.start = MSL2 * (1000 / MSPTICK);
-				tcpgo(tpriv, &tcb->katimer);
-			}
-			break;
-		case Finwait2:
-			update(s, &seg);
-			break;
-		case Closing:
-			update(s, &seg);
-			if(qlen(s->wq)+tcb->flgcnt == 0) {
-				tcphalt(tpriv, &tcb->rtt_timer);
-				tcphalt(tpriv, &tcb->acktimer);
-				tcphalt(tpriv, &tcb->katimer);
-				tcpsetstate(s, Time_wait);
-				tcb->timer.start = MSL2*(1000 / MSPTICK);
-				tcpgo(tpriv, &tcb->timer);
-			}
-			break;
-		case Last_ack:
-			update(s, &seg);
-			if(qlen(s->wq)+tcb->flgcnt == 0) {
-				localclose(s, nil);
-				goto raise;
-			}
-		case Time_wait:
-			tcb->flags |= FORCE;
-			if(tcb->timer.state != TcptimerON)
-				tcpgo(tpriv, &tcb->timer);
-		}
-
-		if((seg.flags&URG) && seg.urg) {
-			if(seq_gt(seg.urg + seg.seq, tcb->rcv.urg)) {
-				tcb->rcv.urg = seg.urg + seg.seq;
-				pullblock(&bp, seg.urg);
-			}
-		}
-		else
-		if(seq_gt(tcb->rcv.nxt, tcb->rcv.urg))
-			tcb->rcv.urg = tcb->rcv.nxt;
-
-		if(length == 0) {
-			if(bp != nil)
-				freeblist(bp);
-		}
-		else {
-			switch(tcb->state){
-			default:
-				/* Ignore segment text */
-				if(bp != nil)
-					freeblist(bp);
-				break;
-
-			case Syn_received:
-			case Established:
-			case Finwait1:
-				/* If we still have some data place on
-				 * receive queue
-				 */
-				if(bp) {
-					bp = packblock(bp);
-					if(bp == nil)
-						panic("tcp packblock");
-					qpassnolim(s->rq, bp);
-					bp = nil;
-				}
-				tcb->rcv.nxt += length;
-
-				/*
-				 *  turn on the acktimer if there's something
-				 *  to ack
-				 */
-				if(tcb->acktimer.state != TcptimerON)
-					tcpgo(tpriv, &tcb->acktimer);
-
-				break;
-			case Finwait2:
-				/* no process to read the data, send a reset */
-				if(bp != nil)
-					freeblist(bp);
-				sndrst(tcp, source, dest, length, &seg, version,
-					"send to Finwait2");
-				qunlock(s);
-				poperror();
-				return;
-			}
-		}
-
-		if(seg.flags & FIN) {
-			tcb->flags |= FORCE;
-
-			switch(tcb->state) {
-			case Syn_received:
-			case Established:
-				tcb->rcv.nxt++;
-				tcpsetstate(s, Close_wait);
-				break;
-			case Finwait1:
-				tcb->rcv.nxt++;
-				if(qlen(s->wq)+tcb->flgcnt == 0) {
-					tcphalt(tpriv, &tcb->rtt_timer);
-					tcphalt(tpriv, &tcb->acktimer);
-					tcphalt(tpriv, &tcb->katimer);
-					tcpsetstate(s, Time_wait);
-					tcb->timer.start = MSL2*(1000/MSPTICK);
-					tcpgo(tpriv, &tcb->timer);
-				}
-				else
-					tcpsetstate(s, Closing);
-				break;
-			case Finwait2:
-				tcb->rcv.nxt++;
-				tcphalt(tpriv, &tcb->rtt_timer);
-				tcphalt(tpriv, &tcb->acktimer);
-				tcphalt(tpriv, &tcb->katimer);
-				tcpsetstate(s, Time_wait);
-				tcb->timer.start = MSL2 * (1000/MSPTICK);
-				tcpgo(tpriv, &tcb->timer);
-				break;
-			case Close_wait:
-			case Closing:
-			case Last_ack:
-				break;
-			case Time_wait:
-				tcpgo(tpriv, &tcb->timer);
-				break;
-			}
-		}
-
-		/*
-		 *  get next adjacent segment from the resequence queue.
-		 *  dump/trim any overlapping segments
-		 */
-		for(;;) {
-			if(tcb->reseq == nil)
-				goto output;
-
-			if(seq_ge(tcb->rcv.nxt, tcb->reseq->seg.seq) == 0)
-				goto output;
-
-			getreseq(tcb, &seg, &bp, &length);
-
-			tcprcvwin(s);
-			if(tcptrim(tcb, &seg, &bp, &length) == 0){
-				tcb->flags |= FORCE;
-				break;
-			}
-		}
-	}
-output:
-	tcpoutput(s);
-	qunlock(s);
-	poperror();
-	return;
-raise:
-	qunlock(s);
-	poperror();
-	freeblist(bp);
-	tcpkick(s);
-}
-
-/*
- *  always enters and exits with the s locked.  We drop
- *  the lock to ipoput the packet so some care has to be
- *  taken by callers.
- */
-static void
-tcpoutput(Conv *s)
-{
-	Tcp seg;
-	uint msgs;
-	Tcpctl *tcb;
-	Block *hbp, *bp;
-	int sndcnt;
-	ulong ssize, dsize, sent;
-	Fs *f;
-	Tcppriv *tpriv;
-	uchar version;
-
-	f = s->p->f;
-	tpriv = s->p->priv;
-	version = s->ipversion;
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	/* force ack every 2*mss */
-	if((tcb->flags & FORCE) == 0 &&
-	    tcb->rcv.nxt - tcb->rcv.ackptr >= 2*tcb->mss){
-		tpriv->stats[Delayack]++;
-		tcb->flags |= FORCE;
-	}
-
-	/* force ack if window opening */
-	if((tcb->flags & FORCE) == 0){
-		tcprcvwin(s);
-		if((int)(tcb->rcv.wptr - tcb->rcv.wsnt) >= 2*tcb->mss){
-			tpriv->stats[Wopenack]++;
-			tcb->flags |= FORCE;
-		}
-	}
-
-	for(msgs = 0; msgs < 100; msgs++) {
-		switch(tcb->state) {
-		case Listen:
-		case Closed:
-		case Finwait2:
-			return;
-		}
-
-		/* Don't send anything else until our SYN has been acked */
-		if(tcb->snd.ptr != tcb->iss && (tcb->flags & SYNACK) == 0)
-			break;
-
-		/* force an ack when a window has opened up */
-		tcprcvwin(s);
-		if(tcb->rcv.blocked && tcb->rcv.wnd > 0){
-			tcb->rcv.blocked = 0;
-			tcb->flags |= FORCE;
-		}
-
-		sndcnt = qlen(s->wq)+tcb->flgcnt;
-		sent = tcb->snd.ptr - tcb->snd.una;
-		ssize = sndcnt;
-		if(tcb->snd.wnd == 0){
-			/* zero window probe */
-			if(sent > 0 && !(tcb->flags & FORCE))
-				break;	/* already probing, rto re-probes */
-			if(ssize < sent)
-				ssize = 0;
-			else{
-				ssize -= sent;
-				if(ssize > 0)
-					ssize = 1;
-			}
-		} else {
-			/* calculate usable segment size */
-			if(ssize > tcb->cwind)
-				ssize = tcb->cwind;
-			if(ssize > tcb->snd.wnd)
-				ssize = tcb->snd.wnd;
-
-			if(ssize < sent)
-				ssize = 0;
-			else {
-				ssize -= sent;
-				if(ssize > tcb->mss)
-					ssize = tcb->mss;
-			}
-		}
-
-		dsize = ssize;
-		seg.urg = 0;
-
-		if(!(tcb->flags & FORCE))
-			if(ssize == 0 ||
-			    ssize < tcb->mss && tcb->snd.nxt == tcb->snd.ptr &&
-			    sent > TCPREXMTTHRESH * tcb->mss)
-				break;
-
-		tcb->flags &= ~FORCE;
-
-		/* By default we will generate an ack */
-		tcphalt(tpriv, &tcb->acktimer);
-		seg.source = s->lport;
-		seg.dest = s->rport;
-		seg.flags = ACK;
-		seg.mss = 0;
-		seg.ws = 0;
-		seg.update = 0;
-		switch(tcb->state){
-		case Syn_sent:
-			seg.flags = 0;
-			if(tcb->snd.ptr == tcb->iss){
-				seg.flags |= SYN;
-				dsize--;
-				seg.mss = tcb->mss;
-				seg.ws = tcb->scale;
-			}
-			break;
-		case Syn_received:
-			/*
-			 *  don't send any data with a SYN/ACK packet
-			 *  because Linux rejects the packet in its
-			 *  attempt to solve the SYN attack problem
-			 */
-			if(tcb->snd.ptr == tcb->iss){
-				seg.flags |= SYN;
-				dsize = 0;
-				ssize = 1;
-				seg.mss = tcb->mss;
-				seg.ws = tcb->scale;
-			}
-			break;
-		}
-		seg.seq = tcb->snd.ptr;
-		seg.ack = tcb->rcv.nxt;
-		seg.wnd = tcb->rcv.wnd;
-
-		/* Pull out data to send */
-		bp = nil;
-		if(dsize != 0) {
-			bp = qcopy(s->wq, dsize, sent);
-			if(BLEN(bp) != dsize) {
-				seg.flags |= FIN;
-				dsize--;
-			}
-		}
-
-		if(sent+dsize == sndcnt && dsize)
-			seg.flags |= PSH;
-
-		tcb->snd.ptr += ssize;
-
-		/* Pull up the send pointer so we can accept acks
-		 * for this window
-		 */
-		if(seq_gt(tcb->snd.ptr,tcb->snd.nxt))
-			tcb->snd.nxt = tcb->snd.ptr;
-
-		/* Build header, link data and compute cksum */
-		switch(version){
-		case V4:
-			tcb->protohdr.tcp4hdr.vihl = IP_VER4;
-			hbp = htontcp4(&seg, bp, &tcb->protohdr.tcp4hdr, tcb);
-			if(hbp == nil) {
-				freeblist(bp);
-				return;
-			}
-			break;
-		case V6:
-			tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
-			hbp = htontcp6(&seg, bp, &tcb->protohdr.tcp6hdr, tcb);
-			if(hbp == nil) {
-				freeblist(bp);
-				return;
-			}
-			break;
-		default:
-			hbp = nil;	/* to suppress a warning */
-			panic("tcpoutput: version %d", version);
-		}
-
-		/* Start the transmission timers if there is new data and we
-		 * expect acknowledges
-		 */
-		if(ssize != 0){
-			if(tcb->timer.state != TcptimerON){
-				tcb->time = NOW;
-				tcb->timeuna = tcb->snd.una;
-				tcpgo(tpriv, &tcb->timer);
-			}
-
-			/*  If round trip timer isn't running, start it.
-			 *  measure the longest packet only in case the
-			 *  transmission time dominates RTT
-			 */
-			if(tcb->snd.retransmit == 0)
-			if(tcb->rtt_timer.state != TcptimerON)
-			if(ssize == tcb->mss) {
-				tcpgo(tpriv, &tcb->rtt_timer);
-				tcb->rttseq = tcb->snd.ptr;
-			}
-		}
-
-		tpriv->stats[OutSegs]++;
-		if(tcb->snd.retransmit)
-			tpriv->stats[RetransSegsSent]++;
-		tcb->rcv.ackptr = seg.ack;
-		tcb->rcv.wsnt = tcb->rcv.wptr;
-
-		/* put off the next keep alive */
-		tcpgo(tpriv, &tcb->katimer);
-
-		switch(version){
-		case V4:
-			if(ipoput4(f, hbp, 0, s->ttl, s->tos, s) < 0){
-				/* a negative return means no route */
-				localclose(s, "no route");
-			}
-			break;
-		case V6:
-			if(ipoput6(f, hbp, 0, s->ttl, s->tos, s) < 0){
-				/* a negative return means no route */
-				localclose(s, "no route");
-			}
-			break;
-		default:
-			panic("tcpoutput2: version %d", version);
-		}
-		if((msgs%4) == 3){
-			qunlock(s);
-			qlock(s);
-		}
-	}
-}
-
-/*
- *  the BSD convention (hack?) for keep alives.  resend last uchar acked.
- */
-static void
-tcpsendka(Conv *s)
-{
-	Tcp seg;
-	Tcpctl *tcb;
-	Block *hbp,*dbp;
-
-	tcb = (Tcpctl*)s->ptcl;
-
-	dbp = nil;
-	memset(&seg, 0, sizeof seg);
-	seg.urg = 0;
-	seg.source = s->lport;
-	seg.dest = s->rport;
-	seg.flags = ACK|PSH;
-	seg.mss = 0;
-	seg.ws = 0;
-	if(tcpporthogdefense)
-		seg.seq = tcb->snd.una-(1<<30)-nrand(1<<20);
-	else
-		seg.seq = tcb->snd.una-1;
-	seg.ack = tcb->rcv.nxt;
-	tcb->rcv.ackptr = seg.ack;
-	tcprcvwin(s);
-	seg.wnd = tcb->rcv.wnd;
-	if(tcb->state == Finwait2){
-		seg.flags |= FIN;
-	} else {
-		dbp = allocb(1);
-		dbp->wp++;
-	}
-
-	if(isv4(s->raddr)) {
-		/* Build header, link data and compute cksum */
-		tcb->protohdr.tcp4hdr.vihl = IP_VER4;
-		hbp = htontcp4(&seg, dbp, &tcb->protohdr.tcp4hdr, tcb);
-		if(hbp == nil) {
-			freeblist(dbp);
-			return;
-		}
-		ipoput4(s->p->f, hbp, 0, s->ttl, s->tos, s);
-	}
-	else {
-		/* Build header, link data and compute cksum */
-		tcb->protohdr.tcp6hdr.vcf[0] = IP_VER6;
-		hbp = htontcp6(&seg, dbp, &tcb->protohdr.tcp6hdr, tcb);
-		if(hbp == nil) {
-			freeblist(dbp);
-			return;
-		}
-		ipoput6(s->p->f, hbp, 0, s->ttl, s->tos, s);
-	}
-}
-
-/*
- *  set connection to time out after 12 minutes
- */
-static void
-tcpsetkacounter(Tcpctl *tcb)
-{
-	tcb->kacounter = (12 * 60 * 1000) / (tcb->katimer.start*MSPTICK);
-	if(tcb->kacounter < 3)
-		tcb->kacounter = 3;
-}
-
-/*
- *  if we've timed out, close the connection
- *  otherwise, send a keepalive and restart the timer
- */
-static void
-tcpkeepalive(void *v)
-{
-	Tcpctl *tcb;
-	Conv *s;
-
-	s = v;
-	tcb = (Tcpctl*)s->ptcl;
-	if(waserror()){
-		qunlock(s);
-		nexterror();
-	}
-	qlock(s);
-	if(tcb->state != Closed){
-		if(--(tcb->kacounter) <= 0) {
-			localclose(s, Etimedout);
-		} else {
-			tcpsendka(s);
-			tcpgo(s->p->priv, &tcb->katimer);
-		}
-	}
-	qunlock(s);
-	poperror();
-}
-
-/*
- *  start keepalive timer
- */
-static char*
-tcpstartka(Conv *s, char **f, int n)
-{
-	Tcpctl *tcb;
-	int x;
-
-	tcb = (Tcpctl*)s->ptcl;
-	if(tcb->state != Established)
-		return "connection must be in Establised state";
-	if(n > 1){
-		x = atoi(f[1]);
-		if(x >= MSPTICK)
-			tcb->katimer.start = x/MSPTICK;
-	}
-	tcpsetkacounter(tcb);
-	tcpgo(s->p->priv, &tcb->katimer);
-
-	return nil;
-}
-
-/*
- *  turn checksums on/off
- */
-static char*
-tcpsetchecksum(Conv *s, char **f, int)
-{
-	Tcpctl *tcb;
-
-	tcb = (Tcpctl*)s->ptcl;
-	tcb->nochecksum = !atoi(f[1]);
-
-	return nil;
-}
-
-/*
- *  retransmit (at most) one segment at snd.una.
- *  preserve cwind & snd.ptr
- */
-static void
-tcprxmit(Conv *s)
-{
-	Tcpctl *tcb;
-	Tcppriv *tpriv;
-	ulong tcwind, tptr;
-
-	tcb = (Tcpctl*)s->ptcl;
-	tcb->flags |= RETRAN|FORCE;
-
-	tptr = tcb->snd.ptr;
-	tcwind = tcb->cwind;
-	tcb->snd.ptr = tcb->snd.una;
-	tcb->cwind = tcb->mss;
-	tcb->snd.retransmit = 1;
-	tcpoutput(s);
-	tcb->snd.retransmit = 0;
-	tcb->cwind = tcwind;
-	tcb->snd.ptr = tptr;
-
-	tpriv = s->p->priv;
-	tpriv->stats[RetransSegs]++;
-}
-
-/*
- *  TODO: RFC 4138 F-RTO
- */
-static void
-tcptimeout(void *arg)
-{
-	Conv *s;
-	Tcpctl *tcb;
-	int maxback;
-	Tcppriv *tpriv;
-
-	s = (Conv*)arg;
-	tpriv = s->p->priv;
-	tcb = (Tcpctl*)s->ptcl;
-
-	if(waserror()){
-		qunlock(s);
-		nexterror();
-	}
-	qlock(s);
-	switch(tcb->state){
-	default:
-		tcb->backoff++;
-		if(tcb->state == Syn_sent)
-			maxback = MAXBACKMS/2;
-		else
-			maxback = MAXBACKMS;
-		tcb->backedoff += tcb->timer.start * MSPTICK;
-		if(tcb->backedoff >= maxback) {
-			localclose(s, Etimedout);
-			break;
-		}
-		netlog(s->p->f, Logtcprxmt, "rxm %d/%d %ldms %lud rto %d %lud %s\n",
-			tcb->srtt, tcb->mdev, NOW - tcb->time,
-			tcb->snd.una - tcb->timeuna, tcb->snd.rto, tcb->snd.ptr,
-			tcpstates[s->state]);
-		tcpsettimer(tcb);
-		if(tcb->snd.rto == 0)
-			tcpcongestion(tcb);
-		tcprxmit(s);
-		tcb->snd.ptr = tcb->snd.una;
-		tcb->cwind = tcb->mss;
-		tcb->snd.rto = 1;
-		tpriv->stats[RetransTimeouts]++;
-
-		if(tcb->snd.recovery){
-			tcb->snd.dupacks = 0;		/* reno rto */
-			tcb->snd.recovery = 0;
-			tpriv->stats[RecoveryRTO]++;
-			tcb->snd.rxt = tcb->snd.nxt;
-			netlog(s->p->f, Logtcpwin,
-				"rto recovery rxt @%lud\n", tcb->snd.nxt);
-		}
-
-		tcb->abcbytes = 0;
-		break;
-	case Time_wait:
-		localclose(s, nil);
-		break;
-	case Closed:
-		break;
-	}
-	qunlock(s);
-	poperror();
-}
-
-static int
-inwindow(Tcpctl *tcb, int seq)
-{
-	return seq_within(seq, tcb->rcv.nxt, tcb->rcv.nxt+tcb->rcv.wnd-1);
-}
-
-/*
- *  set up state for a received SYN (or SYN ACK) packet
- */
-static void
-procsyn(Conv *s, Tcp *seg)
-{
-	Tcpctl *tcb;
-	Tcppriv *tpriv;
-
-	tcb = (Tcpctl*)s->ptcl;
-	tcb->flags |= FORCE;
-
-	tcb->rcv.nxt = seg->seq + 1;
-	tcb->rcv.wptr = tcb->rcv.nxt;
-	tcb->rcv.wsnt = 0;
-	tcb->rcv.urg = tcb->rcv.nxt;
-	tcb->irs = seg->seq;
-
-	/* our sending max segment size cannot be bigger than what he asked for */
-	if(seg->mss != 0 && seg->mss < tcb->mss) {
-		tcb->mss = seg->mss;
-		tpriv = s->p->priv;
-		tpriv->stats[Mss] = tcb->mss;
-	}
-
-	tcb->snd.wnd = seg->wnd;
-	initialwindow(tcb);
-}
-
-static int
-dumpreseq(Tcpctl *tcb)
-{
-	Reseq *r, *next;
-
-	for(r = tcb->reseq; r != nil; r = next){
-		next = r->next;
-		freeblist(r->bp);
-		free(r);
-	}
-	tcb->reseq = nil;
-	tcb->nreseq = 0;
-	tcb->reseqlen = 0;
-	return -1;
-}
-
-static void
-logreseq(Fs *f, Reseq *r, ulong n)
-{
-	char *s;
-
-	for(; r != nil; r = r->next){
-		s = nil;
-		if(r->next == nil && r->seg.seq != n)
-			s = "hole/end";
-		else if(r->next == nil)
-			s = "end";
-		else if(r->seg.seq != n)
-			s = "hole";
-		if(s != nil)
-			netlog(f, Logtcp, "%s %lud-%lud (%ld) %#ux\n", s,
-				n, r->seg.seq, r->seg.seq - n, r->seg.flags);
-		n = r->seg.seq + r->seg.len;
-	}
-}
-
-static int
-addreseq(Fs *f, Tcpctl *tcb, Tcppriv *tpriv, Tcp *seg, Block *bp, ushort length)
-{
-	Reseq *rp, **rr;
-	int qmax;
-
-	rp = malloc(sizeof *rp);
-	if(rp == nil){
-		freeblist(bp);		/* bp always consumed by addreseq */
-		return 0;
-	}
-
-	rp->seg = *seg;
-	rp->bp = bp;
-	rp->length = length;
-
-	tcb->reseqlen += length;
-	tcb->nreseq++;
-
-	/* Place on reassembly list sorting by starting seq number */
-	for(rr = &tcb->reseq; ; rr = &(*rr)->next)
-		if(*rr == nil || seq_lt(seg->seq, (*rr)->seg.seq)){
-			rp->next = *rr;
-			*rr = rp;
-			tpriv->stats[Resequenced]++;
-			if(rp->next != nil)
-				tpriv->stats[OutOfOrder]++;
-			break;
-		}
-
-	qmax = tcb->window;
-	if(tcb->reseqlen > qmax){
-		netlog(f, Logtcp, "tcp: reseq: queue > window: %d > %d; %d packets\n",
-			tcb->reseqlen, qmax, tcb->nreseq);
-		logreseq(f, tcb->reseq, tcb->rcv.nxt);
-		tpriv->stats[ReseqBytelim]++;
-		return dumpreseq(tcb);
-	}
-	qmax = tcb->window / tcb->mss; /* ~190 for qscale=2, 390 for qscale=3 */
-	if(tcb->nreseq > qmax){
-		netlog(f, Logtcp, "resequence queue > packets: %d %d; %d bytes\n",
-			tcb->nreseq, qmax, tcb->reseqlen);
-		logreseq(f, tcb->reseq, tcb->rcv.nxt);
-		tpriv->stats[ReseqPktlim]++;
-		return dumpreseq(tcb);
-	}
-	return 0;
-}
-
-static void
-getreseq(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
-{
-	Reseq *rp;
-
-	rp = tcb->reseq;
-	if(rp == nil)
-		return;
-
-	tcb->reseq = rp->next;
-
-	*seg = rp->seg;
-	*bp = rp->bp;
-	*length = rp->length;
-
-	tcb->nreseq--;
-	tcb->reseqlen -= rp->length;
-
-	free(rp);
-}
-
-static int
-tcptrim(Tcpctl *tcb, Tcp *seg, Block **bp, ushort *length)
-{
-	ushort len;
-	uchar accept;
-	int dupcnt, excess;
-
-	accept = 0;
-	len = *length;
-	if(seg->flags & SYN)
-		len++;
-	if(seg->flags & FIN)
-		len++;
-
-	if(tcb->rcv.wnd == 0) {
-		if(len == 0 && seg->seq == tcb->rcv.nxt)
-			return 0;
-	}
-	else {
-		/* Some part of the segment should be in the window */
-		if(inwindow(tcb,seg->seq))
-			accept++;
-		else
-		if(len != 0) {
-			if(inwindow(tcb, seg->seq+len-1) ||
-			seq_within(tcb->rcv.nxt, seg->seq,seg->seq+len-1))
-				accept++;
-		}
-	}
-	if(!accept) {
-		freeblist(*bp);
-		return -1;
-	}
-	dupcnt = tcb->rcv.nxt - seg->seq;
-	if(dupcnt > 0){
-		tcb->rerecv += dupcnt;
-		if(seg->flags & SYN){
-			seg->flags &= ~SYN;
-			seg->seq++;
-
-			if(seg->urg > 1)
-				seg->urg--;
-			else
-				seg->flags &= ~URG;
-			dupcnt--;
-		}
-		if(dupcnt > 0){
-			pullblock(bp, (ushort)dupcnt);
-			seg->seq += dupcnt;
-			*length -= dupcnt;
-
-			if(seg->urg > dupcnt)
-				seg->urg -= dupcnt;
-			else {
-				seg->flags &= ~URG;
-				seg->urg = 0;
-			}
-		}
-	}
-	excess = seg->seq + *length - (tcb->rcv.nxt + tcb->rcv.wnd);
-	if(excess > 0) {
-		tcb->rerecv += excess;
-		*length -= excess;
-		*bp = trimblock(*bp, 0, *length);
-		if(*bp == nil)
-			panic("presotto is a boofhead");
-		seg->flags &= ~FIN;
-	}
-	return 0;
-}
-
-static void
-tcpadvise(Proto *tcp, Block *bp, char *msg)
-{
-	Tcp4hdr *h4;
-	Tcp6hdr *h6;
-	Tcpctl *tcb;
-	uchar source[IPaddrlen];
-	uchar dest[IPaddrlen];
-	ushort psource, pdest;
-	Conv *s, **p;
-
-	h4 = (Tcp4hdr*)(bp->rp);
-	h6 = (Tcp6hdr*)(bp->rp);
-
-	if((h4->vihl&0xF0)==IP_VER4) {
-		v4tov6(dest, h4->tcpdst);
-		v4tov6(source, h4->tcpsrc);
-		psource = nhgets(h4->tcpsport);
-		pdest = nhgets(h4->tcpdport);
-	}
-	else {
-		ipmove(dest, h6->tcpdst);
-		ipmove(source, h6->tcpsrc);
-		psource = nhgets(h6->tcpsport);
-		pdest = nhgets(h6->tcpdport);
-	}
-
-	/* Look for a connection */
-	qlock(tcp);
-	for(p = tcp->conv; *p; p++) {
-		s = *p;
-		tcb = (Tcpctl*)s->ptcl;
-		if(s->rport == pdest)
-		if(s->lport == psource)
-		if(tcb->state != Closed)
-		if(ipcmp(s->raddr, dest) == 0)
-		if(ipcmp(s->laddr, source) == 0){
-			qlock(s);
-			qunlock(tcp);
-			switch(tcb->state){
-			case Syn_sent:
-				localclose(s, msg);
-				break;
-			}
-			qunlock(s);
-			freeblist(bp);
-			return;
-		}
-	}
-	qunlock(tcp);
-	freeblist(bp);
-}
-
-static char*
-tcpporthogdefensectl(char *val)
-{
-	if(strcmp(val, "on") == 0)
-		tcpporthogdefense = 1;
-	else if(strcmp(val, "off") == 0)
-		tcpporthogdefense = 0;
-	else
-		return "unknown value for tcpporthogdefense";
-	return nil;
-}
-
-/* called with c qlocked */
-static char*
-tcpctl(Conv* c, char** f, int n)
-{
-	if(n == 1 && strcmp(f[0], "hangup") == 0)
-		return tcphangup(c);
-	if(n >= 1 && strcmp(f[0], "keepalive") == 0)
-		return tcpstartka(c, f, n);
-	if(n >= 1 && strcmp(f[0], "checksum") == 0)
-		return tcpsetchecksum(c, f, n);
-	if(n >= 1 && strcmp(f[0], "tcpporthogdefense") == 0)
-		return tcpporthogdefensectl(f[1]);
-	return "unknown control request";
-}
-
-static int
-tcpstats(Proto *tcp, char *buf, int len)
-{
-	Tcppriv *priv;
-	char *p, *e;
-	int i;
-
-	priv = tcp->priv;
-	p = buf;
-	e = p+len;
-	for(i = 0; i < Nstats; i++)
-		p = seprint(p, e, "%s: %llud\n", statnames[i], priv->stats[i]);
-	return p - buf;
-}
-
-/*
- *  garbage collect any stale conversations:
- *	- SYN received but no SYN-ACK after 5 seconds (could be the SYN attack)
- *	- Finwait2 after 5 minutes
- *
- *  this is called whenever we run out of channels.  Both checks are
- *  of questionable validity so we try to use them only when we're
- *  up against the wall.
- */
-static int
-tcpgc(Proto *tcp)
-{
-	Conv *c, **pp, **ep;
-	int n;
-	Tcpctl *tcb;
-
-
-	n = 0;
-	ep = &tcp->conv[tcp->nc];
-	for(pp = tcp->conv; pp < ep; pp++) {
-		c = *pp;
-		if(c == nil)
-			break;
-		if(!canqlock(c))
-			continue;
-		tcb = (Tcpctl*)c->ptcl;
-		switch(tcb->state){
-		case Syn_received:
-			if(NOW - tcb->time > 5000){
-				localclose(c, Etimedout);
-				n++;
-			}
-			break;
-		case Finwait2:
-			if(NOW - tcb->time > 5*60*1000){
-				localclose(c, Etimedout);
-				n++;
-			}
-			break;
-		}
-		qunlock(c);
-	}
-	return n;
-}
-
-static void
-tcpsettimer(Tcpctl *tcb)
-{
-	int x;
-
-	/* round trip dependency */
-	x = backoff(tcb->backoff) *
-		(tcb->mdev + (tcb->srtt>>LOGAGAIN) + MSPTICK) / MSPTICK;
-
-	/* bounded twixt 0.3 and 64 seconds */
-	if(x < 300/MSPTICK)
-		x = 300/MSPTICK;
-	else if(x > (64000/MSPTICK))
-		x = 64000/MSPTICK;
-	tcb->timer.start = x;
-}
-
-void
-tcpinit(Fs *fs)
-{
-	Proto *tcp;
-	Tcppriv *tpriv;
-
-	tcp = smalloc(sizeof(Proto));
-	tpriv = tcp->priv = smalloc(sizeof(Tcppriv));
-	tcp->name = "tcp";
-	tcp->connect = tcpconnect;
-	tcp->announce = tcpannounce;
-	tcp->ctl = tcpctl;
-	tcp->state = tcpstate;
-	tcp->create = tcpcreate;
-	tcp->close = tcpclose;
-	tcp->rcv = tcpiput;
-	tcp->advise = tcpadvise;
-	tcp->stats = tcpstats;
-	tcp->inuse = tcpinuse;
-	tcp->gc = tcpgc;
-	tcp->ipproto = IP_TCPPROTO;
-	tcp->nc = scalednconv();
-	tcp->ptclsize = sizeof(Tcpctl);
-	tpriv->stats[MaxConn] = tcp->nc;
-
-	Fsproto(fs, tcp);
-}
-
-static void
-tcpsetscale(Conv *s, Tcpctl *tcb, ushort rcvscale, ushort sndscale)
-{
-	/*
-	 * guess at reasonable queue sizes.  there's no current way
-	 * to know how many nic receive buffers we can safely tie up in the
-	 * tcp stack, and we don't adjust our queues to maximize throughput
-	 * and minimize bufferbloat.  n.b. the offer (rcvscale) needs to be
-	 * respected, but we still control our own buffer commitment by
-	 * keeping a seperate qscale.
-	 */
-	tcb->rcv.scale = rcvscale & 0xff;
-	tcb->snd.scale = sndscale & 0xff;
-	tcb->qscale = rcvscale & 0xff;
-	if(rcvscale > Maxqscale)
-		tcb->qscale = Maxqscale;
-
-	if(rcvscale != tcb->rcv.scale)
-		netlog(s->p->f, Logtcp, "tcpsetscale: window %lud "
-			"qlen %d >> window %ud lport %d\n",
-			tcb->window, qlen(s->rq), QMAX<<tcb->qscale, s->lport);
-	tcb->window = QMAX << tcb->qscale;
-	tcb->ssthresh = tcb->window;
-
-	/*
-	 * it's important to set wq large enough to cover the full
-	 * bandwidth-delay product.  it's possible to be in loss
-	 * recovery with a big window, and we need to keep sending
-	 * into the inflated window.  the difference can be huge
-	 * for even modest (70ms) ping times.
-	 */
-	qsetlimit(s->rq, tcb->window);
-	qsetlimit(s->wq, tcb->window);
-	tcprcvwin(s);
-}

+ 0 - 629
sys/src/9/ip/udp.c

@@ -1,629 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include	"u.h"
-#include	"../port/lib.h"
-#include	"mem.h"
-#include	"dat.h"
-#include	"fns.h"
-#include	"../port/error.h"
-
-#include	"ip.h"
-#include	"ipv6.h"
-
-
-#define DPRINT if(0)print
-
-enum
-{
-	UDP_UDPHDR_SZ	= 8,
-
-	UDP4_PHDR_OFF = 8,
-	UDP4_PHDR_SZ = 12,
-	UDP4_IPHDR_SZ = 20,
-	UDP6_IPHDR_SZ = 40,
-	UDP6_PHDR_SZ = 40,
-	UDP6_PHDR_OFF = 0,
-
-	IP_UDPPROTO	= 17,
-	UDP_USEAD7	= 52,
-
-	Udprxms		= 200,
-	Udptickms	= 100,
-	Udpmaxxmit	= 10,
-};
-
-typedef struct Udp4hdr Udp4hdr;
-struct Udp4hdr
-{
-	/* ip header */
-	uchar	vihl;		/* Version and header length */
-	uchar	tos;		/* Type of service */
-	uchar	length[2];	/* packet length */
-	uchar	id[2];		/* Identification */
-	uchar	frag[2];	/* Fragment information */
-	uchar	Unused;
-	uchar	udpproto;	/* Protocol */
-	uchar	udpplen[2];	/* Header plus data length */
-	uchar	udpsrc[IPv4addrlen];	/* Ip source */
-	uchar	udpdst[IPv4addrlen];	/* Ip destination */
-
-	/* udp header */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-typedef struct Udp6hdr Udp6hdr;
-struct Udp6hdr {
-	uchar viclfl[4];
-	uchar len[2];
-	uchar nextheader;
-	uchar hoplimit;
-	uchar udpsrc[IPaddrlen];
-	uchar udpdst[IPaddrlen];
-
-	/* udp header */
-	uchar	udpsport[2];	/* Source port */
-	uchar	udpdport[2];	/* Destination port */
-	uchar	udplen[2];	/* data length */
-	uchar	udpcksum[2];	/* Checksum */
-};
-
-/* MIB II counters */
-typedef struct Udpstats Udpstats;
-struct Udpstats
-{
-	uvlong	udpInDatagrams;
-	ulong	udpNoPorts;
-	ulong	udpInErrors;
-	uvlong	udpOutDatagrams;
-};
-
-typedef struct Udppriv Udppriv;
-struct Udppriv
-{
-	Ipht		ht;
-
-	/* MIB counters */
-	Udpstats	ustats;
-
-	/* non-MIB stats */
-	ulong		csumerr;		/* checksum errors */
-	ulong		lenerr;			/* short packet */
-};
-
-void (*etherprofiler)(char *name, int qlen);
-void udpkick(void *x, Block *bp);
-
-/*
- *  protocol specific part of Conv
- */
-typedef struct Udpcb Udpcb;
-struct Udpcb
-{
-	QLock;
-	uchar	headers;
-};
-
-static char*
-udpconnect(Conv *c, char **argv, int argc)
-{
-	char *e;
-	Udppriv *upriv;
-
-	upriv = c->p->priv;
-	e = Fsstdconnect(c, argv, argc);
-	Fsconnected(c, e);
-	if(e != nil)
-		return e;
-
-	iphtadd(&upriv->ht, c);
-	return nil;
-}
-
-
-static int
-udpstate(Conv *c, char *state, int n)
-{
-	return snprint(state, n, "%s qin %d qout %d\n",
-		c->inuse ? "Open" : "Closed",
-		c->rq ? qlen(c->rq) : 0,
-		c->wq ? qlen(c->wq) : 0
-	);
-}
-
-static char*
-udpannounce(Conv *c, char** argv, int argc)
-{
-	char *e;
-	Udppriv *upriv;
-
-	upriv = c->p->priv;
-	e = Fsstdannounce(c, argv, argc);
-	if(e != nil)
-		return e;
-	Fsconnected(c, nil);
-	iphtadd(&upriv->ht, c);
-
-	return nil;
-}
-
-static void
-udpcreate(Conv *c)
-{
-	c->rq = qopen(128*1024, Qmsg, 0, 0);
-	c->wq = qbypass(udpkick, c);
-}
-
-static void
-udpclose(Conv *c)
-{
-	Udpcb *ucb;
-	Udppriv *upriv;
-
-	upriv = c->p->priv;
-	iphtrem(&upriv->ht, c);
-
-	c->state = 0;
-	qclose(c->rq);
-	qclose(c->wq);
-	qclose(c->eq);
-	ipmove(c->laddr, IPnoaddr);
-	ipmove(c->raddr, IPnoaddr);
-	c->lport = 0;
-	c->rport = 0;
-
-	ucb = (Udpcb*)c->ptcl;
-	ucb->headers = 0;
-}
-
-void
-udpkick(void *x, Block *bp)
-{
-	Conv *c = x;
-	Udp4hdr *uh4;
-	Udp6hdr *uh6;
-	ushort rport;
-	uchar laddr[IPaddrlen], raddr[IPaddrlen];
-	Udpcb *ucb;
-	int dlen, ptcllen;
-	Udppriv *upriv;
-	Fs *f;
-	int version;
-	Conv *rc;
-
-	upriv = c->p->priv;
-	f = c->p->f;
-
-//	netlog(c->p->f, Logudp, "udp: kick\n");	/* frequent and uninteresting */
-	if(bp == nil)
-		return;
-
-	ucb = (Udpcb*)c->ptcl;
-	switch(ucb->headers) {
-	case 7:
-		/* get user specified addresses */
-		bp = pullupblock(bp, UDP_USEAD7);
-		if(bp == nil)
-			return;
-		ipmove(raddr, bp->rp);
-		bp->rp += IPaddrlen;
-		ipmove(laddr, bp->rp);
-		bp->rp += IPaddrlen;
-		/* pick interface closest to dest */
-		if(ipforme(f, laddr) != Runi)
-			findlocalip(f, laddr, raddr);
-		bp->rp += IPaddrlen;		/* Ignore ifc address */
-		rport = nhgets(bp->rp);
-		bp->rp += 2+2;			/* Ignore local port */
-		break;
-	default:
-		rport = 0;
-		break;
-	}
-
-	if(ucb->headers) {
-		if(memcmp(laddr, v4prefix, IPv4off) == 0
-		|| ipcmp(laddr, IPnoaddr) == 0)
-			version = 4;
-		else
-			version = 6;
-	} else {
-		if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
-			memcmp(c->laddr, v4prefix, IPv4off) == 0)
-			|| ipcmp(c->raddr, IPnoaddr) == 0)
-			version = 4;
-		else
-			version = 6;
-	}
-
-	dlen = blocklen(bp);
-
-	/* fill in pseudo header and compute checksum */
-	switch(version){
-	case V4:
-		bp = padblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ);
-		if(bp == nil)
-			return;
-
-		uh4 = (Udp4hdr *)(bp->rp);
-		ptcllen = dlen + UDP_UDPHDR_SZ;
-		uh4->Unused = 0;
-		uh4->udpproto = IP_UDPPROTO;
-		uh4->frag[0] = 0;
-		uh4->frag[1] = 0;
-		hnputs(uh4->udpplen, ptcllen);
-		if(ucb->headers) {
-			v6tov4(uh4->udpdst, raddr);
-			hnputs(uh4->udpdport, rport);
-			v6tov4(uh4->udpsrc, laddr);
-			rc = nil;
-		} else {
-			v6tov4(uh4->udpdst, c->raddr);
-			hnputs(uh4->udpdport, c->rport);
-			if(ipcmp(c->laddr, IPnoaddr) == 0)
-				findlocalip(f, c->laddr, c->raddr);
-			v6tov4(uh4->udpsrc, c->laddr);
-			rc = c;
-		}
-		hnputs(uh4->udpsport, c->lport);
-		hnputs(uh4->udplen, ptcllen);
-		uh4->udpcksum[0] = 0;
-		uh4->udpcksum[1] = 0;
-		hnputs(uh4->udpcksum,
-		       ptclcsum(bp, UDP4_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
-		uh4->vihl = IP_VER4;
-		ipoput4(f, bp, 0, c->ttl, c->tos, rc);
-		break;
-
-	case V6:
-		bp = padblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ);
-		if(bp == nil)
-			return;
-
-		/*
-		 * using the v6 ip header to create pseudo header
-		 * first then reset it to the normal ip header
-		 */
-		uh6 = (Udp6hdr *)(bp->rp);
-		memset(uh6, 0, 8);
-		ptcllen = dlen + UDP_UDPHDR_SZ;
-		hnputl(uh6->viclfl, ptcllen);
-		uh6->hoplimit = IP_UDPPROTO;
-		if(ucb->headers) {
-			ipmove(uh6->udpdst, raddr);
-			hnputs(uh6->udpdport, rport);
-			ipmove(uh6->udpsrc, laddr);
-			rc = nil;
-		} else {
-			ipmove(uh6->udpdst, c->raddr);
-			hnputs(uh6->udpdport, c->rport);
-			if(ipcmp(c->laddr, IPnoaddr) == 0)
-				findlocalip(f, c->laddr, c->raddr);
-			ipmove(uh6->udpsrc, c->laddr);
-			rc = c;
-		}
-		hnputs(uh6->udpsport, c->lport);
-		hnputs(uh6->udplen, ptcllen);
-		uh6->udpcksum[0] = 0;
-		uh6->udpcksum[1] = 0;
-		hnputs(uh6->udpcksum,
-		       ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ));
-		memset(uh6, 0, 8);
-		uh6->viclfl[0] = IP_VER6;
-		hnputs(uh6->len, ptcllen);
-		uh6->nextheader = IP_UDPPROTO;
-		ipoput6(f, bp, 0, c->ttl, c->tos, rc);
-		break;
-
-	default:
-		panic("udpkick: version %d", version);
-	}
-	upriv->ustats.udpOutDatagrams++;
-}
-
-void
-udpiput(Proto *udp, Ipifc *ifc, Block *bp)
-{
-	int len;
-	Udp4hdr *uh4;
-	Udp6hdr *uh6;
-	Conv *c;
-	Udpcb *ucb;
-	uchar raddr[IPaddrlen], laddr[IPaddrlen];
-	ushort rport, lport;
-	Udppriv *upriv;
-	Fs *f;
-	int version;
-	int ottl, oviclfl, olen;
-	uchar *p;
-
-	upriv = udp->priv;
-	f = udp->f;
-	upriv->ustats.udpInDatagrams++;
-
-	uh4 = (Udp4hdr*)(bp->rp);
-	version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;
-
-	/* Put back pseudo header for checksum
-	 * (remember old values for icmpnoconv()) */
-	switch(version) {
-	case V4:
-		ottl = uh4->Unused;
-		uh4->Unused = 0;
-		len = nhgets(uh4->udplen);
-		olen = nhgets(uh4->udpplen);
-		hnputs(uh4->udpplen, len);
-
-		v4tov6(raddr, uh4->udpsrc);
-		v4tov6(laddr, uh4->udpdst);
-		lport = nhgets(uh4->udpdport);
-		rport = nhgets(uh4->udpsport);
-
-		if(nhgets(uh4->udpcksum)) {
-			if(ptclcsum(bp, UDP4_PHDR_OFF, len+UDP4_PHDR_SZ)) {
-				upriv->ustats.udpInErrors++;
-				netlog(f, Logudp, "udp: checksum error %I\n", raddr);
-				DPRINT("udp: checksum error %I\n", raddr);
-				freeblist(bp);
-				return;
-			}
-		}
-		uh4->Unused = ottl;
-		hnputs(uh4->udpplen, olen);
-		break;
-	case V6:
-		uh6 = (Udp6hdr*)(bp->rp);
-		len = nhgets(uh6->udplen);
-		oviclfl = nhgetl(uh6->viclfl);
-		olen = nhgets(uh6->len);
-		ottl = uh6->hoplimit;
-		ipmove(raddr, uh6->udpsrc);
-		ipmove(laddr, uh6->udpdst);
-		lport = nhgets(uh6->udpdport);
-		rport = nhgets(uh6->udpsport);
-		memset(uh6, 0, 8);
-		hnputl(uh6->viclfl, len);
-		uh6->hoplimit = IP_UDPPROTO;
-		if(ptclcsum(bp, UDP6_PHDR_OFF, len+UDP6_PHDR_SZ)) {
-			upriv->ustats.udpInErrors++;
-			netlog(f, Logudp, "udp: checksum error %I\n", raddr);
-			DPRINT("udp: checksum error %I\n", raddr);
-			freeblist(bp);
-			return;
-		}
-		hnputl(uh6->viclfl, oviclfl);
-		hnputs(uh6->len, olen);
-		uh6->nextheader = IP_UDPPROTO;
-		uh6->hoplimit = ottl;
-		break;
-	default:
-		panic("udpiput: version %d", version);
-		return;	/* to avoid a warning */
-	}
-
-	qlock(udp);
-
-	c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
-	if(c == nil){
-		/* no conversation found */
-		upriv->ustats.udpNoPorts++;
-		qunlock(udp);
-		netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport,
-		       laddr, lport);
-
-		switch(version){
-		case V4:
-			icmpnoconv(f, bp);
-			break;
-		case V6:
-			icmphostunr(f, ifc, bp, Icmp6_port_unreach, 0);
-			break;
-		default:
-			panic("udpiput2: version %d", version);
-		}
-
-		freeblist(bp);
-		return;
-	}
-	ucb = (Udpcb*)c->ptcl;
-
-	if(c->state == Announced){
-		if(ucb->headers == 0){
-			/* create a new conversation */
-			if(ipforme(f, laddr) != Runi) {
-				switch(version){
-				case V4:
-					v4tov6(laddr, ifc->lifc->local);
-					break;
-				case V6:
-					ipmove(laddr, ifc->lifc->local);
-					break;
-				default:
-					panic("udpiput3: version %d", version);
-				}
-			}
-			c = Fsnewcall(c, raddr, rport, laddr, lport, version);
-			if(c == nil){
-				qunlock(udp);
-				freeblist(bp);
-				return;
-			}
-			iphtadd(&upriv->ht, c);
-			ucb = (Udpcb*)c->ptcl;
-		}
-	}
-
-	qlock(c);
-	qunlock(udp);
-
-	/*
-	 * Trim the packet down to data size
-	 */
-	len -= UDP_UDPHDR_SZ;
-	switch(version){
-	case V4:
-		bp = trimblock(bp, UDP4_IPHDR_SZ+UDP_UDPHDR_SZ, len);
-		break;
-	case V6:
-		bp = trimblock(bp, UDP6_IPHDR_SZ+UDP_UDPHDR_SZ, len);
-		break;
-	default:
-		bp = nil;
-		panic("udpiput4: version %d", version);
-	}
-	if(bp == nil){
-		qunlock(c);
-		netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport,
-		       laddr, lport);
-		upriv->lenerr++;
-		return;
-	}
-
-	netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport,
-	       laddr, lport, len);
-
-	switch(ucb->headers){
-	case 7:
-		/* pass the src address */
-		bp = padblock(bp, UDP_USEAD7);
-		p = bp->rp;
-		ipmove(p, raddr); p += IPaddrlen;
-		ipmove(p, laddr); p += IPaddrlen;
-		ipmove(p, ifc->lifc->local); p += IPaddrlen;
-		hnputs(p, rport); p += 2;
-		hnputs(p, lport);
-		break;
-	}
-
-	if(bp->next)
-		bp = concatblock(bp);
-
-	if(qfull(c->rq)){
-		qunlock(c);
-		netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,
-		       laddr, lport);
-		freeblist(bp);
-		return;
-	}
-
-	qpass(c->rq, bp);
-	qunlock(c);
-
-}
-
-char*
-udpctl(Conv *c, char **f, int n)
-{
-	Udpcb *ucb;
-
-	ucb = (Udpcb*)c->ptcl;
-	if(n == 1){
-		if(strcmp(f[0], "headers") == 0){
-			ucb->headers = 7;	/* new headers format */
-			return nil;
-		}
-	}
-	return "unknown control request";
-}
-
-void
-udpadvise(Proto *udp, Block *bp, char *msg)
-{
-	Udp4hdr *h4;
-	Udp6hdr *h6;
-	uchar source[IPaddrlen], dest[IPaddrlen];
-	ushort psource, pdest;
-	Conv *s, **p;
-	int version;
-
-	h4 = (Udp4hdr*)(bp->rp);
-	version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;
-
-	switch(version) {
-	case V4:
-		v4tov6(dest, h4->udpdst);
-		v4tov6(source, h4->udpsrc);
-		psource = nhgets(h4->udpsport);
-		pdest = nhgets(h4->udpdport);
-		break;
-	case V6:
-		h6 = (Udp6hdr*)(bp->rp);
-		ipmove(dest, h6->udpdst);
-		ipmove(source, h6->udpsrc);
-		psource = nhgets(h6->udpsport);
-		pdest = nhgets(h6->udpdport);
-		break;
-	default:
-		panic("udpadvise: version %d", version);
-		return;  /* to avoid a warning */
-	}
-
-	/* Look for a connection */
-	qlock(udp);
-	for(p = udp->conv; *p; p++) {
-		s = *p;
-		if(s->rport == pdest)
-		if(s->lport == psource)
-		if(ipcmp(s->raddr, dest) == 0)
-		if(ipcmp(s->laddr, source) == 0){
-			if(s->ignoreadvice)
-				break;
-			qlock(s);
-			qunlock(udp);
-			qhangup(s->rq, msg);
-			qhangup(s->wq, msg);
-			qunlock(s);
-			freeblist(bp);
-			return;
-		}
-	}
-	qunlock(udp);
-	freeblist(bp);
-}
-
-int
-udpstats(Proto *udp, char *buf, int len)
-{
-	Udppriv *upriv;
-
-	upriv = udp->priv;
-	return snprint(buf, len, "InDatagrams: %llud\nNoPorts: %lud\n"
-		"InErrors: %lud\nOutDatagrams: %llud\n",
-		upriv->ustats.udpInDatagrams,
-		upriv->ustats.udpNoPorts,
-		upriv->ustats.udpInErrors,
-		upriv->ustats.udpOutDatagrams);
-}
-
-void
-udpinit(Fs *fs)
-{
-	Proto *udp;
-
-	udp = smalloc(sizeof(Proto));
-	udp->priv = smalloc(sizeof(Udppriv));
-	udp->name = "udp";
-	udp->connect = udpconnect;
-	udp->announce = udpannounce;
-	udp->ctl = udpctl;
-	udp->state = udpstate;
-	udp->create = udpcreate;
-	udp->close = udpclose;
-	udp->rcv = udpiput;
-	udp->advise = udpadvise;
-	udp->stats = udpstats;
-	udp->ipproto = IP_UDPPROTO;
-	udp->nc = Nchans;
-	udp->ptclsize = sizeof(Udpcb);
-
-	Fsproto(fs, udp);
-}

+ 0 - 248
sys/src/9/kw/arch.c

@@ -1,248 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-#include <tos.h>
-#include "ureg.h"
-
-#include "arm.h"
-
-/*
- * A lot of this stuff doesn't belong here
- * but this is a convenient dumping ground for
- * later sorting into the appropriate buckets.
- */
-
-/* Give enough context in the ureg to produce a kernel stack for
- * a sleeping process
- */
-void
-setkernur(Ureg* ureg, Proc* p)
-{
-	ureg->pc = p->sched.pc;
-	ureg->sp = p->sched.sp+4;
-	ureg->r14 = PTR2UINT(sched);
-}
-
-/*
- * called in syscallfmt.c, sysfile.c, sysproc.c
- */
-void
-validalign(uintptr addr, unsigned align)
-{
-	/*
-	 * Plan 9 is a 32-bit O/S, and the hardware it runs on
-	 * does not usually have instructions which move 64-bit
-	 * quantities directly, synthesizing the operations
-	 * with 32-bit move instructions. Therefore, the compiler
-	 * (and hardware) usually only enforce 32-bit alignment,
-	 * if at all.
-	 *
-	 * Take this out if the architecture warrants it.
-	 */
-	if(align == sizeof(vlong))
-		align = sizeof(long);
-
-	/*
-	 * Check align is a power of 2, then addr alignment.
-	 */
-	if((align != 0 && !(align & (align-1))) && !(addr & (align-1)))
-		return;
-	postnote(up, 1, "sys: odd address", NDebug);
-	error(Ebadarg);
-	/*NOTREACHED*/
-}
-
-/* go to user space */
-void
-kexit(Ureg*)
-{
-	uvlong t;
-	Tos *tos;
-
-	/* precise time accounting, kernel exit */
-	tos = (Tos*)(USTKTOP-sizeof(Tos));
-	t = fastticks(nil);
-	tos->kcycles += t - up->kentry;
-	tos->pcycles = up->pcycles;
-	tos->cyclefreq = Frequency;
-	tos->pid = up->pid;
-
-	/* make visible immediately to user proc */
-	cachedwbinvse(tos, sizeof *tos);
-}
-
-/*
- *  return the userpc the last exception happened at
- */
-uintptr
-userpc(void)
-{
-	Ureg *ureg = up->dbgreg;
-	return ureg->pc;
-}
-
-/* This routine must save the values of registers the user is not permitted
- * to write from devproc and then restore the saved values before returning.
- */
-void
-setregisters(Ureg* ureg, char* pureg, char* uva, int n)
-{
-	USED(ureg, pureg, uva, n);
-}
-
-/*
- *  this is the body for all kproc's
- */
-static void
-linkproc(void)
-{
-	spllo();
-	up->kpfun(up->kparg);
-	pexit("kproc exiting", 0);
-}
-
-/*
- *  setup stack and initial PC for a new kernel proc.  This is architecture
- *  dependent because of the starting stack location
- */
-void
-kprocchild(Proc *p, void (*func)(void*), void *arg)
-{
-	p->sched.pc = PTR2UINT(linkproc);
-	p->sched.sp = PTR2UINT(p->kstack+KSTACK);
-
-	p->kpfun = func;
-	p->kparg = arg;
-}
-
-/*
- *  pc output by dumpaproc
- */
-uintptr
-dbgpc(Proc* p)
-{
-	Ureg *ureg;
-
-	ureg = p->dbgreg;
-	if(ureg == 0)
-		return 0;
-
-	return ureg->pc;
-}
-
-/*
- *  set mach dependent process state for a new process
- */
-void
-procsetup(Proc* p)
-{
-	fpusysprocsetup(p);
-}
-
-/*
- *  Save the mach dependent part of the process state.
- */
-void
-procsave(Proc* p)
-{
-	uvlong t;
-
-	cycles(&t);
-	p->pcycles += t;
-
-	fpuprocsave(p);
-}
-
-void
-procrestore(Proc* p)
-{
-	uvlong t;
-
-	if(p->kp)
-		return;
-	t = lcycles();
-	p->pcycles -= t;
-
-	fpuprocrestore(p);
-}
-
-int
-userureg(Ureg* ureg)
-{
-	return (ureg->psr & PsrMask) == PsrMusr;
-}
-
-/*
- * atomic ops
- * make sure that we don't drag in the C library versions
- */
-
-long
-_xdec(long *p)
-{
-	int s, v;
-
-	s = splhi();
-	v = --*p;
-	splx(s);
-	return v;
-}
-
-void
-_xinc(long *p)
-{
-	int s;
-
-	s = splhi();
-	++*p;
-	splx(s);
-}
-
-int
-ainc(int *p)
-{
-	int s, v;
-
-	s = splhi();
-	v = ++*p;
-	splx(s);
-	return v;
-}
-
-int
-adec(int *p)
-{
-	int s, v;
-
-	s = splhi();
-	v = --*p;
-	splx(s);
-	return v;
-}
-
-int
-cas32(void* addr, u32int old, u32int new)
-{
-	int r, s;
-
-	s = splhi();
-	if(r = (*(u32int*)addr == old))
-		*(u32int*)addr = new;
-	splx(s);
-	if (r)
-		coherence();
-	return r;
-}

+ 0 - 540
sys/src/9/kw/archkw.c

@@ -1,540 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * stuff specific to marvell's kirkwood architecture
- * as seen in the sheevaplug
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-#include "io.h"
-
-#include "../port/netif.h"
-#include "etherif.h"
-#include "../port/flashif.h"
-
-#include "arm.h"
-
-enum {
-	L2writeback = 1,
-	Debug = 0,
-};
-
-typedef struct GpioReg GpioReg;
-struct GpioReg {
-	ulong	dataout;
-	ulong	dataoutena;
-	ulong	blinkena;
-	ulong	datainpol;
-	ulong	datain;
-	ulong	intrcause;
-	ulong	intrmask;
-	ulong	intrlevelmask;
-};
-
-typedef struct L2uncache L2uncache;
-typedef struct L2win L2win;
-struct L2uncache {
-	struct L2win {
-		ulong	base;	/* phys addr */
-		ulong	size;
-	} win[4];
-};
-
-enum {
-	/* L2win->base bits */
-	L2enable	= 1<<0,
-};
-
-typedef struct Dramctl Dramctl;
-struct Dramctl {
-	ulong	ctl;
-	ulong	ddrctllo;
-	struct {
-		ulong	lo;
-		ulong	hi;
-	} time;
-	ulong	addrctl;
-	ulong	opagectl;
-	ulong	oper;
-	ulong	mode;
-	ulong	extmode;
-	ulong	ddrctlhi;
-	ulong	ddr2timelo;
-	ulong	operctl;
-	struct {
-		ulong	lo;
-		ulong	hi;
-	} mbusctl;
-	ulong	mbustimeout;
-	ulong	ddrtimehi;
-	ulong	sdinitctl;
-	ulong	extsdmode1;
-	ulong	extsdmode2;
-	struct {
-		ulong	lo;
-		ulong	hi;
-	} odtctl;
-	ulong	ddrodtctl;
-	ulong	rbuffsel;
-
-	ulong	accalib;
-	ulong	dqcalib;
-	ulong	dqscalib;
-};
-
-/* unused so far */
-typedef struct SDramdReg SDramdReg;
-struct SDramdReg {
-	struct {
-		ulong	base;
-		ulong	size;
-	} win[4];
-};
-
-typedef struct Addrmap Addrmap;
-typedef struct Addrwin Addrwin;
-struct Addrmap {
-	struct Addrwin {
-		ulong	ctl;		/* see Winenable in io.h */
-		ulong	base;		/* virtual address */
-		ulong	remaplo;	/* physical address sent to target */
-		ulong	remaphi;	/* " */
-	} win[8];
-	ulong	dirba;		/* device internal reg's base addr.: PHYSIO */
-};
-
-Soc soc = {
-	.cpu		= PHYSIO+0x20100,
-	.devid		= PHYSIO+0x10034,
-	.l2cache	= PHYSIO+0x20a00,  	/* uncachable addrs for L2 */
-	.sdramc		= PHYSIO+0x01400,
-//	.sdramd		= PHYSIO+0x01500,	/* unused */
-
-	.iocfg		= PHYSIO+0x100e0,
-	.addrmap	= PHYSIO+0x20000,	/* cpu address map */
-	.intr		= PHYSIO+0x20200,
-	.nand		= PHYSIO+0x10418,
-	.cesa		= PHYSIO+0x30000,	/* crypto accelerator */
-	.ehci		= PHYSIO+0x50000,
-	.spi		= PHYSIO+0x10600,
- 	.twsi		= PHYSIO+0x11000,
-
-	.analog		= PHYSIO+0x1007c,
-	.pci		= PHYSIO+0x40000,
-	.pcibase	= PHYSIO+0x41800,
-
-	.rtc		= PHYSIO+0x10300,
-	.clock		= PHYSIO+0x20300,
-//	.clockctl	= PHYSIO+0x1004c,	/* unused */
-
-	.ether		= { PHYSIO+0x72000, PHYSIO+0x76000, },
-	.sata		= { PHYSIO+0x80000,	/* sata config reg here */
-			PHYSIO+0x82000,		/* edma config reg here */
-			PHYSIO+0x84000,		/* edma config reg here */
-			},
-	.uart		= { PHYSIO+0x12000, PHYSIO+0x12100, },
-	.gpio		= { PHYSIO+0x10100, PHYSIO+0x10140, },
-};
-
-/*
- * sheeva/openrd u-boot leaves us with this address map:
- *
- * 0 targ 4 attr 0xe8 size 256MB addr 0x9::  remap addr 0x9::	pci mem
- * 1 targ 1 attr 0x2f size   8MB addr 0xf9:: remap addr 0xf9::	nand flash
- * 2 targ 4 attr 0xe0 size  16MB addr 0xf::  remap addr 0xc::	pci i/o
- * 3 targ 1 attr 0x1e size  16MB addr 0xf8:: remap addr 0x0	spi flash
- * 4 targ 1 attr 0x1d size  16MB addr 0xff::			boot rom
- * 5 targ 1 attr 0x1e size 128MB addr 0xe8::	disabled	spi flash
- * 6 targ 1 attr 0x1d size 128MB addr 0xf::	disabled	boot rom
- * 7 targ 3 attr 0x1  size  64K  addr 0xfb::			crypto sram
- *
- * dreamplug u-boot leaves us with this address map:
- *
- * 0 targ 4 attr 0xe8 size 256MB addr 0x9::  remap addr 0x9::	pci mem
- * 1 targ 4 attr 0xe0 size  64KB addr 0xc::  remap addr 0xc::	pci i/o
- * 2 targ 1 attr 0x2f size 128MB addr 0xd8:: remap addr 0xd8::	nand flash
- * 3 targ 1 attr 0x1e size 128MB addr 0xe8:: remap addr 0xe8::	spi flash
- * 4 targ 1 attr 0x1d size 128MB addr 0xf8::			boot rom
- * 5 targ 3 attr 0x1  size  64K  addr 0xc801::			crypto sram
- * 6 targ 0 attr 0x0  size  64K  addr 0xf::	disabled	ram?
- * 7 targ 0 attr 0x0  size  64K  addr 0xf8::	disabled	ram?
- */
-
-#define WINTARG(ctl)	(((ctl) >> 4) & 017)
-#define WINATTR(ctl)	(((ctl) >> 8) & 0377)
-#define WIN64KSIZE(ctl)	(((ctl) >> 16) + 1)
-
-static void
-praddrwin(Addrwin *win, int i)
-{
-	ulong ctl, targ, attr, size64k;
-
-	if (!Debug) {
-		USED(win, i);
-		return;
-	}
-	ctl = win->ctl;
-	targ = WINTARG(ctl);
-	attr = WINATTR(ctl);
-	size64k = WIN64KSIZE(ctl);
-	print("cpu addr map: %s window %d: targ %ld attr %#lux size %,ld addr %#lux",
-		ctl & Winenable? "enabled": "disabled", i, targ, attr,
-		size64k * 64*1024, win->base);
-	if (i < 4)
-		print(" remap addr %#llux", (uvlong)win->remaphi<<32 |
-			win->remaplo);
-	print("\n");
-}
-
-static void
-fixaddrmap(void)
-{
-	int i;
-	ulong ctl, targ, attr, size64k;
-	Addrmap *map;
-	Addrwin *win;
-
-	map = (Addrmap *)soc.addrmap;
-	for (i = 0; i < nelem(map->win); i++) {
-		win = &map->win[i];
-		ctl = win->ctl;
-		targ = WINTARG(ctl);
-		attr = WINATTR(ctl);
-		size64k = WIN64KSIZE(ctl);
-
-		USED(attr, size64k);
-		if (targ == Targcesasram) {
-			win->ctl |= Winenable;
-			win->base = PHYSCESASRAM;
-			coherence();
-			praddrwin(win, i);
-		}
-	}
-	if (map->dirba != PHYSIO)
-		panic("dirba not %#ux", PHYSIO);
-}
-
-static void
-praddrmap(void)
-{
-	int i;
-	Addrmap *map;
-
-	map = (Addrmap *)soc.addrmap;
-	for (i = 0; i < nelem(map->win); i++)
-		praddrwin(&map->win[i], i);
-}
-
-int
-ispow2(uvlong ul)
-{
-	/* see Hacker's Delight if this isn't obvious */
-	return (ul & (ul - 1)) == 0;
-}
-
-/*
- * return exponent of smallest power of 2 ≥ n
- */
-int
-log2(ulong n)
-{
-	int i;
-
-	i = 31 - clz(n);
-	if (!ispow2(n) || n == 0)
-		i++;
-	return i;
-}
-
-void
-cacheinfo(int level, int kind, Memcache *cp)		/* l1 only */
-{
-	uint len, assoc, size;
-	ulong setsways;
-
-	/* get cache types & sizes (read-only reg) */
-	setsways = cprdsc(0, CpID, CpIDidct, CpIDct);
-
-	cp->level = level;
-	cp->kind = kind;
-
-	if ((setsways & (1<<24)) == 0)
-		kind = Unified;
-	if (kind != Icache)
-		setsways >>= 12;
-
-	assoc = (setsways >> 3) & MASK(3);
-	cp->nways = 1 << assoc;
-	size = (setsways >> 6) & MASK(4);
-	cp->size  = 1 << (size + 9);
-	len = setsways & MASK(2);
-	cp->log2linelen = len + 3;
-	cp->linelen = 1 << cp->log2linelen;
-	cp->setsways = setsways;
-
-	cp->nsets = 1 << (size + 6 - assoc - len);
-	cp->setsh = cp->log2linelen;
-	cp->waysh = 32 - log2(cp->nways);
-}
-
-static char *
-wbtype(uint type)
-{
-	static char *types[] = {
-		"write-through",
-		"read data block",
-		"reg 7 ops, no lock-down",
-	[06]	"reg 7 ops, format A",
-	[07]	"reg 7 ops, format B deprecated",
-	[016]	"reg 7 ops, format C",
-	[05]	"reg 7 ops, format D",
-	};
-
-	if (type >= nelem(types) || types[type] == nil)
-		return "GOK";
-	return types[type];
-}
-
-static void
-prcache(Memcache *mcp)
-{
-	int type;
-	char id;
-
-	if (mcp->kind == Unified)
-		id = 'U';
-	else if (mcp->kind == Icache)
-		id = 'I';
-	else if (mcp->kind == Dcache)
-		id = 'D';
-	else
-		id = '?';
-	print("l%d %c: %d bytes, %d ways %d sets %d bytes/line",
-		mcp->level, id, mcp->size, mcp->nways, mcp->nsets,
-		mcp->linelen);
-	if (mcp->linelen != CACHELINESZ)
-		print(" *should* be %d", CACHELINESZ);
-	type = (mcp->setsways >> 25) & MASK(4);
-	if (type == 0)
-		print("; write-through only");
-	else
-		print("; write-back type `%s' (%#o) possible",
-			wbtype(type), type);
-	if (mcp->setsways & (1<<11))
-		print("; page table mapping restrictions apply");
-	if (mcp->setsways & (1<<2))
-		print("; M bit is set in cache type reg");
-	print("\n");
-}
-
-static void
-prcachecfg(void)
-{
-	Memcache mc;
-
-	cacheinfo(1, Dcache, &mc);
-	prcache(&mc);
-	cacheinfo(1, Icache, &mc);
-	prcache(&mc);
-}
-
-void
-l2cacheon(void)
-{
-	ulong cfg;
-	CpucsReg *cpu;
-	L2uncache *l2p;
-
-	cacheuwbinv();
-	l2cacheuwbinv();
-	l1cachesoff();			/* turns off L2 as a side effect */
-
-	cpwrsc(CpDef, CpCLD, 0, 0, 0);  /* GL-CPU-100: set D cache lockdown reg. */
-
-	/* marvell guideline GL-CPU-130 */
-	cpu = (CpucsReg *)soc.cpu;
-	cfg = cpu->cpucfg | L2exists | L2ecc | Cfgiprefetch | Cfgdprefetch;
-
-	if (L2writeback)
-		cfg &= ~L2writethru;	/* see PTE Cached & Buffered bits */
-	else
-		cfg |= L2writethru;
-	cpu->l2cfg = cfg;
-	coherence();			/* force l2 cache to pay attention */
-	cpu->l2tm1 = cpu->l2tm0 = 0x66666666; /* marvell guideline GL-CPU-120 */
-	coherence();
-
-	cpwrsc(CpL2, CpTESTCFG, CpTCl2waylck, CpTCl2waylock, 0);
-
-	cachedinv();
-	l2cacheuinv();
-
-	/* disable l2 caching of i/o registers */
-	l2p = (L2uncache *)soc.l2cache;
-	memset(l2p, 0, sizeof *l2p);
-	/*
-	 * l2: don't cache upper half of address space.
-	 * the L2 cache is PIPT, so the addresses are physical.
-	 */
-	l2p->win[0].base = 0x80000000 | L2enable;	/* 64K multiple */
-	l2p->win[0].size = (32*1024-1) << 16;		/* 64K multiples */
-	coherence();
-
-	l2cachecfgon();
-	l1cacheson();			/* turns L2 on as a side effect */
-	print("l2 cache: 256K or 512K: 4 ways, 32-byte lines, write-%s, sdram only\n",
-		cpu->l2cfg & L2writethru? "through": "back");
-}
-
-/* called late in main */
-void
-archconfinit(void)
-{
-	m->cpuhz = Frequency;
-	m->delayloop = m->cpuhz/2000; 	 /* initial estimate */
-	fixaddrmap();
-	if (Debug)
-		praddrmap();
-	prcachecfg();
-
-	l2cacheon();
-}
-
-void
-archkwlink(void)
-{
-}
-
-int
-archether(unsigned ctlno, Ether *ether)
-{
-	if(ctlno >= 2)
-		return -1;
-	ether->type = "88e1116";
-	ether->port = ctlno;
-//	ether->mbps = 1000;
-	return 1;
-}
-
-/* LED/USB gpios */
-enum {
-	/*
-	 * the bit assignments are MPP pin numbers from the last page of the
-	 * sheevaplug 6.0.1 schematic.
-	 */
-	KWOEValHigh	= 1<<(49-32),	/* pin 49: LED pin */
-	KWOEValLow	= 1<<29,	/* pin 29: USB_PWEN, pin 28: usb_pwerr */
-	KWOELow		= ~0,
-	KWOEHigh	= ~0,
-};
-
-/* called early in main */
-void
-archreset(void)
-{
-	ulong clocks;
-	CpucsReg *cpu;
-	Dramctl *dram;
-	GpioReg *gpio;
-
-	clockshutdown();		/* watchdog disabled */
-
-	/* configure gpios */
-	gpio = (GpioReg*)soc.gpio[0];
-	gpio->dataout = KWOEValLow;
-	coherence();
-	gpio->dataoutena = KWOELow;
-
-	gpio = (GpioReg*)soc.gpio[1];
-	gpio->dataout = KWOEValHigh;
-	coherence();
-	gpio->dataoutena = KWOEHigh;
-	coherence();
-
-	cpu = (CpucsReg *)soc.cpu;
-	cpu->mempm = 0;			/* turn everything on */
-	coherence();
-
-	clocks = MASK(10);
-	clocks |= MASK(21) & ~MASK(14);
-	clocks &= ~(1<<18 | 1<<1);	/* reserved bits */
-	cpu->clockgate |= clocks;	/* enable all the clocks */
-	cpu->l2cfg |= L2exists;		/* when L2exists is 0, the l2 ignores us */
-	coherence();
-
-	dram = (Dramctl *)soc.sdramc;
-	dram->ddrctllo &= ~(1<<6);	/* marvell guideline GL-MEM-70 */
-
-	*(ulong *)soc.analog = 0x68;	/* marvell guideline GL-MISC-40 */
-	coherence();
-}
-
-void
-archreboot(void)
-{
-	CpucsReg *cpu;
-
-	iprint("reset!\n");
-	delay(10);
-
-	cpu = (CpucsReg *)soc.cpu;
-	cpu->rstout = RstoutSoft;
-	cpu->softreset = ResetSystem;
-	coherence();
-	cpu->cpucsr = Reset;
-	coherence();
-	delay(500);
-
-	splhi();
-	iprint("waiting...");
-	for(;;)
-		idlehands();
-}
-
-void
-archconsole(void)
-{
-//	uartconsole(0, "b115200");
-//serialputs("uart0 console @ 115200\n", strlen("uart0 console @ 115200\n"));
-}
-
-void
-archflashwp(Flash*, int)
-{
-}
-
-int	flashat(Flash *f, uintptr pa);
-
-/*
- * for ../port/devflash.c:/^flashreset
- * retrieve flash type, virtual base and length and return 0;
- * return -1 on error (no flash)
- */
-int
-archflashreset(int bank, Flash *f)
-{
-	if(bank != 0)
-		return -1;
-	f->type = "nand";
-	if (flashat(f, PHYSNAND1))
-		f->addr = (void*)PHYSNAND1;
-	else if (flashat(f, PHYSNAND2))
-		f->addr = (void*)PHYSNAND2;
-	else
-		f->addr = nil;
-	f->size = 0;		/* done by probe */
-	f->width = 1;
-	f->interleave = 0;
-	return 0;
-}

+ 0 - 203
sys/src/9/kw/arm.h

@@ -1,203 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * Program Status Registers
- */
-#define PsrMusr		0x00000010		/* mode */
-#define PsrMfiq		0x00000011
-#define PsrMirq		0x00000012
-#define PsrMsvc		0x00000013
-#define PsrMabt		0x00000017
-#define PsrMund		0x0000001B
-#define PsrMsys		0x0000001F
-#define PsrMask		0x0000001F
-
-#define PsrDfiq		0x00000040		/* disable FIQ interrupts */
-#define PsrDirq		0x00000080		/* disable IRQ interrupts */
-
-#define PsrV		0x10000000		/* overflow */
-#define PsrC		0x20000000		/* carry/borrow/extend */
-#define PsrZ		0x40000000		/* zero */
-#define PsrN		0x80000000		/* negative/less than */
-
-/*
- * Coprocessors
- */
-#define CpFP		10			/* float FP, VFP cfg. */
-#define CpDFP		11			/* double FP */
-#define CpSC		15			/* System Control */
-
-/*
- * opcode 1
- */
-#define	CpDef		0			/* default */
-#define CpL2		1			/* L2 cache operations */
-
-/*
- * Primary (CRn) CpSC registers.
- */
-#define	CpID		0			/* ID and cache type */
-#define	CpCONTROL	1			/* miscellaneous control */
-#define	CpTTB		2			/* Translation Table Base */
-#define	CpDAC		3			/* Domain Access Control */
-#define	CpFSR		5			/* Fault Status */
-#define	CpFAR		6			/* Fault Address */
-#define	CpCACHE		7			/* cache/write buffer control */
-#define	CpTLB		8			/* TLB control */
-#define	CpCLD		9			/* Cache Lockdown */
-#define CpTLD		10			/* TLB Lockdown */
-#define	CpPID		13			/* Process ID */
-#define CpTESTCFG	15			/* test config. (arm926) */
-
-/*
- * CpID Secondary (CRm) registers.
- */
-#define CpIDidct	0
-/*
- * CpID op1==0 opcode2 fields.
- */
-#define CpIDid		0			/* main ID */
-#define CpIDct		1			/* cache type */
-
-/*
- * CpCONTROL
- */
-#define CpCmmu		0x00000001		/* M: MMU enable */
-#define CpCalign	0x00000002		/* A: alignment fault enable */
-#define CpCdcache	0x00000004		/* C: data cache on */
-#define CpCwb		0x00000008		/* W: write buffer turned on */
-#define CpCi32		0x00000010		/* P: 32-bit program space */
-#define CpCd32		0x00000020		/* D: 32-bit data space */
-#define CpCbe		0x00000080		/* B: big-endian operation */
-#define CpCsystem	0x00000100		/* S: system permission */
-#define CpCrom		0x00000200		/* R: ROM permission */
-#define CpCicache	0x00001000		/* I: instruction cache on */
-#define CpChv		0x00002000		/* V: high vectors */
-
-/*
- * CpCACHE Secondary (CRm) registers and opcode2 fields.
- * In ARM-speak, 'flush' means invalidate and 'clean' means writeback.
- * In arm arch v6, these must be available in user mode:
- *	CpCACHEinvi, CpCACHEwait (prefetch flush)
- *	CpCACHEwb, CpCACHEwait (DSB: data sync barrier)
- *	CpCACHEwb, CpCACHEdmbarr (DMB: data memory barrier)
- */
-#define CpCACHEintr	0			/* interrupt */
-#define CpCACHEinvi	5			/* instruction */
-#define CpCACHEinvd	6			/* data */
-#define CpCACHEinvu	7			/* unified (I+D) */
-#define CpCACHEwb	10			/* writeback D */
-#define CpCACHEwbu	11			/* writeback U (not 926ejs) */
-#define CpCACHEwbi	14			/* writeback D + invalidate */
-#define CpCACHEwbui	15			/* writeback U + inval (not 926ejs) */
-
-/*
- * the 926ejs manual says that we can't use CpCACHEall nor CpCACHEwait
- * for writeback operations on the 926ejs, except for CpCACHEwb + CpCACHEwait,
- * which means `drain write buffer'.
- */
-#define CpCACHEall	0			/* entire */
-#define CpCACHEse	1			/* single entry */
-#define CpCACHEsi	2			/* set/index */
-#define CpCACHEtest	3			/* test loop */
-#define CpCACHEwait	4			/* wait */
-#define CpCACHEdmbarr	5			/* wb: data memory barrier */
-
-/*
- * CpTLB Secondary (CRm) registers and opcode2 fields.
- */
-#define CpTLBinvi	5			/* instruction */
-#define CpTLBinvd	6			/* data */
-#define CpTLBinvu	7			/* unified */
-
-#define CpTLBinv	0			/* invalidate all */
-#define CpTLBinvse	1			/* invalidate single entry */
-
-/*
- * CpTESTCFG Secondary (CRm) registers and opcode2 fields; sheeva only.
- * opcode1 == CpL2 (1).  L2 cache operations block the CPU until finished.
- * Specifically, write-back (clean) blocks until all dirty lines have been
- * drained from the L2 buffers.
- */
-#define CpTCl2cfg	1
-#define CpTCl2flush	9			/* cpu blocks until flush done */
-#define CpTCl2waylck	10
-#define CpTCl2inv	11
-#define CpTCl2perfctl	12
-#define CpTCl2perfcnt	13
-
-/* CpTCl2cfg */
-#define CpTCl2conf	0
-
-/* CpTCl2conf bits */
-#define	CpTCldcstream	(1<<29)			/* D cache streaming switch */
-#define	CpTCl2wralloc	(1<<28)			/* cache write allocate */
-#define	CpTCl2prefdis	(1<<24)			/* l2 cache prefetch disable */
-#define	CpTCl2ena	(1<<22)			/* l2 cache enable */
-
-/* CpTCl2flush & CpTCl2inv */
-#define CpTCl2all	0
-#define CpTCl2seva	1
-#define CpTCl2way	2
-#define CpTCl2sepa	3
-#define CpTCl2valow	4
-#define CpTCl2vahigh	5			/* also triggers flush or inv */
-
-/* CpTCl2flush
-#define CpTCecccnt	6			/* ecc error count */
-#define CpTCeccthr	7			/* ecc error threshold */
-
-/* CpTCl2waylck */
-#define CpTCl2waylock	7
-
-/* CpTCl2inv */
-#define CpTCl2erraddr	7			/* ecc error address */
-
-/* CpTCl2perfctl */
-#define CpTCl2perf0ctl	0
-#define CpTCl2perf1ctl	1
-
-/* CpTCl2perfcnt */
-#define CpTCl2perf0low	0
-#define CpTCl2perf0high	1
-#define CpTCl2perf1low	2
-#define CpTCl2perf1high	3
-
-/*
- * MMU page table entries.
- * Mbo (0x10) bit is implementation-defined and mandatory on some pre-v7 arms.
- */
-#define Mbo		0x10			/* must be 1 on earlier arms */
-#define Fault		0x00000000		/* L[12] pte: unmapped */
-
-#define Coarse		(Mbo|1)			/* L1 */
-#define Section		(Mbo|2)			/* L1 1MB */
-#define Fine		(Mbo|3)			/* L1 */
-
-#define Large		0x00000001u		/* L2 64KB */
-#define Small		0x00000002u		/* L2 4KB */
-#define Tiny		0x00000003u		/* L2 1KB, deprecated */
-#define Buffered	0x00000004u		/* L[12]: write-back not -thru */
-#define Cached		0x00000008u		/* L[12] */
-
-#define Dom0		0
-#define Noaccess	0			/* AP, DAC */
-#define Krw		1			/* AP */
-#define Uro		2			/* AP */
-#define Urw		3			/* AP */
-#define Client		1			/* DAC */
-#define Manager		3			/* DAC */
-
-#define AP(n, v) F((v), ((n)*2)+4, 2)
-#define L1AP(ap) (AP(3, (ap)))		/* in L1, only Sections have AP */
-#define L2AP(ap) (AP(3, (ap))|AP(2, (ap))|AP(1, (ap))|AP(0, (ap))) /* pre-armv7 */
-#define DAC(n, v) F((v), (n)*2, 2)
-
-#define HVECTORS	0xffff0000		/* addr of vectors */

+ 0 - 72
sys/src/9/kw/arm.s

@@ -1,72 +0,0 @@
-/*
- * sheevaplug machine assist, definitions
- * arm926ej-s processor at 1.2GHz
- *
- * loader uses R11 as scratch.
- */
-#include "mem.h"
-#include "arm.h"
-
-#undef B					/* B is for 'botch' */
-
-#define PADDR(a)	((a) & ~KZERO)
-#define KADDR(a)	(KZERO|(a))
-
-#define L1X(va)		(((((va))>>20) & 0x0fff)<<2)
-
-#define MACHADDR	(L1-MACHSIZE)
-
-#define PTEDRAM		(Dom0|L1AP(Krw)|Section|Cached|Buffered)
-#define PTEIO		(Dom0|L1AP(Krw)|Section)
-
-/* wave at the user; clobbers R1 & R7; needs R12 (SB) set */
-#define PUTC(c) \
-	ISB; \
-	MOVW	$PHYSCONS, R7; \
-	MOVW	$(c), R1; \
-	MOVW	R1, (R7); \
-	ISB
-
-/* new instructions */
-#define CLZ(s, d) WORD	$(0xe16f0f10 | (d) << 12 | (s))	/* count leading 0s */
-
-#define DMB	\
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEdmbarr
-/*
- * data synchronisation barrier (formerly drain write buffer).
- * waits for cache flushes, eviction buffer drain, tlb flushes,
- * branch-prediction flushes, writes to memory; the lot.
- * on sheeva, also flushes L2 eviction buffer.
- * zeroes R0.
- */
-#define DSB	\
-	MOVW	$0, R0; \
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEwb), CpCACHEwait
-/*
- * prefetch flush; zeroes R0.
- * arm926ej-s manual says we need to sync with l2 cache in isb,
- * and uncached load is the easiest way.  doesn't seem to matter.
- */
-#define ISB	\
-	MOVW	$0, R0; \
-	MCR	CpSC, 0, R0, C(CpCACHE), C(CpCACHEinvi), CpCACHEwait
-//	MOVW	(R0), R0; MOVW $0, R0
-
-/* zeroes R0 */
-#define	BARRIERS	ISB; DSB
-
-/*
- * invoked with PTE bits in R2, pa in R3, PTE pointed to by R4.
- * fill PTE pointed to by R4 and increment R4 past it.
- * increment R3 by a MB.  clobbers R1.
- */
-#define FILLPTE() \
-	ORR	R3, R2, R1;			/* pte bits in R2, pa in R3 */ \
-	MOVW	R1, (R4); \
-	ADD	$4, R4;				/* bump PTE address */ \
-	ADD	$MiB, R3;			/* bump pa */ \
-
-/* zero PTE pointed to by R4 and increment R4 past it. assumes R0 is 0. */
-#define ZEROPTE() \
-	MOVW	R0, (R4); \
-	ADD	$4, R4;				/* bump PTE address */

+ 0 - 141
sys/src/9/kw/cga.c

@@ -1,141 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "../port/error.h"
-
-enum {
-	Black,
-	Blue,
-	Green,
-	Cyan,
-	Red,
-	Magenta,
-	Brown,
-	Grey,
-
-	Bright = 0x08,
-	Blinking = 0x80,
-
-	Yellow = Bright|Brown,
-	White = Bright|Grey,
-};
-	
-enum {
-	Width		= 80*2,
-	Height		= 25,
-
-	Attr		= (Black<<4)|Grey,	/* high nibble background
-						 * low foreground
-						 */
-};
-
-#define CGASCREENBASE	((uchar*)KADDR(0xB8000))
-
-#define inb(x)		0	/* TODO */
-#define outb(x, y)			/* TODO */
-
-static int cgapos;
-static Lock cgascreenlock;
-
-static uchar
-cgaregr(int index)
-{
-	USED(index);
-	outb(0x3D4, index);
-	return inb(0x3D4+1) & 0xFF;
-}
-
-static void
-cgaregw(int index, int data)
-{
-	USED(index, data);
-	outb(0x3D4, index);
-	outb(0x3D4+1, data);
-}
-
-static void
-movecursor(void)
-{
-	cgaregw(0x0E, (cgapos/2>>8) & 0xFF);
-	cgaregw(0x0F, cgapos/2 & 0xFF);
-	CGASCREENBASE[cgapos+1] = Attr;
-}
-
-static void
-cgascreenputc(int c)
-{
-	int i;
-	uchar *p;
-
-	if(c == '\n'){
-		cgapos = cgapos/Width;
-		cgapos = (cgapos+1)*Width;
-	}
-	else if(c == '\t'){
-		i = 8 - ((cgapos/2)&7);
-		while(i-->0)
-			cgascreenputc(' ');
-	}
-	else if(c == '\b'){
-		if(cgapos >= 2)
-			cgapos -= 2;
-		cgascreenputc(' ');
-		cgapos -= 2;
-	}
-	else{
-		CGASCREENBASE[cgapos++] = c;
-		CGASCREENBASE[cgapos++] = Attr;
-	}
-	if(cgapos >= Width*Height){
-		memmove(CGASCREENBASE, &CGASCREENBASE[Width], Width*(Height-1));
-		p = &CGASCREENBASE[Width*(Height-1)];
-		for(i=0; i<Width/2; i++){
-			*p++ = ' ';
-			*p++ = Attr;
-		}
-		cgapos = Width*(Height-1);
-	}
-	movecursor();
-}
-
-static void
-cgascreenputs(char* s, int n)
-{
-	if(!islo()){
-		/*
-		 * Don't deadlock trying to
-		 * print in an interrupt.
-		 */
-		if(!canlock(&cgascreenlock))
-			return;
-	}
-	else
-		lock(&cgascreenlock);
-
-	while(n-- > 0)
-		cgascreenputc(*s++);
-
-	unlock(&cgascreenlock);
-}
-
-void
-screeninit(void)
-{
-
-	cgapos = cgaregr(0x0E)<<8;
-	cgapos |= cgaregr(0x0F);
-	cgapos *= 2;
-
-	screenputs = cgascreenputs;
-}

+ 0 - 214
sys/src/9/kw/clock.c

@@ -1,214 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * kirkwood clocks
- *
- * timers count down to zero.
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "ureg.h"
-
-enum {
-	Tcycles		= CLOCKFREQ / HZ,	/* cycles per clock tick */
-	Dogperiod	= 15 * CLOCKFREQ, /* at most 21 s.; must fit in ulong */
-	MaxPeriod	= Tcycles,
-	MinPeriod	= MaxPeriod / 100,
-
-	/* timer ctl bits */
-	Tmr0enable	= 1<<0,
-	Tmr0reload	= 1<<1,	/* at 0 count, load timer0 from reload0 */
-	Tmr1enable	= 1<<2,
-	Tmr1reload	= 1<<3,	/* at 0 count, load timer1 from reload1 */
-	TmrWDenable	= 1<<4,
-	TmrWDreload	= 1<<5,
-};
-
-typedef struct TimerReg TimerReg;
-struct TimerReg
-{
-	ulong	ctl;
-	ulong	pad[3];
-	ulong	reload0;
-	ulong	timer0;			/* cycles until zero */
-	ulong	reload1;
-	ulong	timer1;			/* cycles until zero */
-	ulong	reloadwd;
-	ulong	timerwd;
-};
-
-static int ticks; /* for sanity checking; m->ticks doesn't always get updated */
-
-static void
-clockintr(Ureg *ureg, void *arg)
-{
-	TimerReg *tmr = arg;
-	static int nesting;
-
-	tmr->timerwd = Dogperiod;		/* reassure the watchdog */
-	ticks++;
-	coherence();
-
-	if (nesting == 0) {	/* if the clock interrupted itself, bail out */
-		++nesting;
-		timerintr(ureg, 0);
-		--nesting;
-	}
-
-	intrclear(Irqbridge, IRQcputimer0);
-}
-
-/* stop clock interrupts and disable the watchdog timer */
-void
-clockshutdown(void)
-{
-	TimerReg *tmr = (TimerReg *)soc.clock;
-
-	tmr->ctl = 0;
-	coherence();
-}
-
-void
-clockinit(void)
-{
-	int i, s;
-	CpucsReg *cpu = (CpucsReg *)soc.cpu;
-	TimerReg *tmr = (TimerReg *)soc.clock;
-
-	clockshutdown();
-
-	/*
-	 * verify sanity of timer0
-	 */
-
-	intrenable(Irqbridge, IRQcputimer0, clockintr, tmr, "clock0");
-	s = spllo();			/* risky */
-	/* take any deferred clock (& other) interrupts here */
-	splx(s);
-
-	/* adjust m->bootdelay, used by delay()? */
-	m->ticks = ticks = 0;
-	m->fastclock = 0;
-
-	tmr->timer0 = 1;
-	tmr->ctl = Tmr0enable;		/* just once */
-	coherence();
-
-	s = spllo();			/* risky */
-	for (i = 0; i < 10 && ticks == 0; i++) {
-		delay(1);
-		coherence();
-	}
-	splx(s);
-	if (ticks == 0) {
-		serialputc('?');
-		if (tmr->timer0 == 0)
-			panic("clock not interrupting");
-		else if (tmr->timer0 == tmr->reload0)
-			panic("clock not ticking");
-		else
-			panic("clock running very slowly");
-	}
-
-	/*
-	 * configure all timers
-	 */
-	clockshutdown();
-	tmr->reload0 = tmr->timer0 = Tcycles;	/* tick clock */
-	tmr->reload1 = tmr->timer1 = ~0;	/* cycle clock */
-	tmr->timerwd = Dogperiod;		/* watch dog timer */
-	coherence();
-	tmr->ctl = Tmr0enable | Tmr0reload | Tmr1enable | Tmr1reload |
-		TmrWDenable;
-	cpu->rstout |= RstoutWatchdog;
-	coherence();
-}
-
-void
-timerset(Tval next)
-{
-	int offset;
-	TimerReg *tmr = (TimerReg *)soc.clock;
-
-	offset = next - fastticks(nil);
-	if(offset < MinPeriod)
-		offset = MinPeriod;
-	else if(offset > MaxPeriod)
-		offset = MaxPeriod;
-	tmr->timer0 = offset;
-	coherence();
-}
-
-uvlong
-fastticks(uvlong *hz)
-{
-	uvlong now;
-	int s;
-
-	if(hz)
-		*hz = CLOCKFREQ;
-	s = splhi();
-	/* zero low ulong of fastclock */
-	now = (m->fastclock & ~(uvlong)~0ul) | perfticks();
-	if(now < m->fastclock)		/* low bits must have wrapped */
-		now += 1ll << 32;
-	m->fastclock = now;
-	splx(s);
-	return now;
-}
-
-ulong
-perfticks(void)
-{
-	TimerReg *tmr = (TimerReg *)soc.clock;
-
-	return ~tmr->timer1;
-}
-
-long
-lcycles(void)
-{
-	return perfticks();
-}
-
-ulong
-µs(void)
-{
-	return fastticks2us(fastticks(nil));
-}
-
-void
-microdelay(int l)
-{
-	int i;
-
-	l *= m->delayloop;
-	l /= 1000;
-	if(l <= 0)
-		l = 1;
-	for(i = 0; i < l; i++)
-		;
-}
-
-void
-delay(int l)
-{
-	ulong i, j;
-
-	j = m->delayloop;
-	while(l-- > 0)
-		for(i=0; i < j; i++)
-			;
-}

+ 0 - 162
sys/src/9/kw/coproc.c

@@ -1,162 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-/*
- * arm co-processors
- * CP15 (system control) is the one that gets used the most in practice.
- */
-#include "u.h"
-#include "../port/lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
-#include "io.h"
-
-#include "arm.h"
-
-#define MAP2PCSPACE(va, pc) ((uintptr)(va) & ~KSEGM | (pc) & KSEGM)
-
-enum {
-	/* alternates:	0xe12fff1e	BX (R14); last e is R14 */
-	/*		0xe28ef000	B 0(R14); second e is R14 (ken) */
-	Retinst	= 0xe1a0f00e,		/* MOVW R14, R15 */
-
-	Fpproc	= 10,			/* for vfp 3+; also 11 for doubles */
-};
-
-void
-cpwr(int cp, int op1, int crn, int crm, int op2, ulong val)
-{
-	int s;
-	volatile ulong instr[2];
-	void *pcaddr;
-	void (*fp)(ulong);
-
-	s = splhi();
-	op1 &= 7;
-	op2 &= 7;
-	crn &= 017;
-	crm &= 017;
-	cp &= 017;
-	/* MCR.  Rt will be R0. */
-	instr[0] = 0xee000010 |
-		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
-	instr[1] = Retinst;
-	coherence();
-
-	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
-	cachedwbse(pcaddr, sizeof instr);
-	cacheiinv();
-
-	fp = (void (*)(ulong))pcaddr;
-	(*fp)(val);
-	coherence();
-	splx(s);
-}
-
-void
-cpwrsc(int op1, int crn, int crm, int op2, ulong val)
-{
-	cpwr(CpSC, op1, crn, crm, op2, val);
-}
-
-ulong
-cprd(int cp, int op1, int crn, int crm, int op2)
-{
-	int s;
-	ulong res;
-	volatile ulong instr[2];
-	void *pcaddr;
-	ulong (*fp)(void);
-
-	s = splhi();
-	op1 &= 7;
-	op2 &= 7;
-	crn &= 017;
-	crm &= 017;
-	/*
-	 * MRC.  return value will be in R0, which is convenient.
-	 * Rt will be R0.
-	 */
-	instr[0] = 0xee100010 |
-		op1 << 21 | crn << 16 | cp << 8 | op2 << 5 | crm;
-	instr[1] = Retinst;
-	coherence();
-
-	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&cp));
-	cachedwbse(pcaddr, sizeof instr);
-	cacheiinv();
-
-	fp = (ulong (*)(void))pcaddr;
-	res = (*fp)();
-	splx(s);
-	return res;
-}
-
-ulong
-cprdsc(int op1, int crn, int crm, int op2)
-{
-	return cprd(CpSC, op1, crn, crm, op2);
-}
-
-/* floating point */
-
-ulong
-fprd(int fpreg)
-{
-	int s;
-	ulong res;
-	volatile ulong instr[2];
-	void *pcaddr;
-	ulong (*fp)(void);
-
-	s = splhi();
-	fpreg &= 017;
-	/*
-	 * VMRS.  return value will be in R0, which is convenient.
-	 * Rt will be R0.
-	 */
-	instr[0] = 0xeef00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
-	instr[1] = Retinst;
-	coherence();
-
-	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
-	cachedwbse(pcaddr, sizeof instr);
-	cacheiinv();
-
-	fp = (ulong (*)(void))pcaddr;
-	res = (*fp)();
-	splx(s);
-	return res;
-}
-
-void
-fpwr(int fpreg, ulong val)
-{
-	int s;
-	volatile ulong instr[2];
-	void *pcaddr;
-	void (*fp)(ulong);
-
-	s = splhi();
-	fpreg &= 017;
-	/* VMSR.  Rt will be R0. */
-	instr[0] = 0xeee00010 | fpreg << 16 | 0 << 12 | Fpproc << 8;
-	instr[1] = Retinst;
-	coherence();
-
-	pcaddr = (void *)MAP2PCSPACE(instr, getcallerpc(&fpreg));
-	cachedwbse(pcaddr, sizeof instr);
-	cacheiinv();
-
-	fp = (void (*)(ulong))pcaddr;
-	(*fp)(val);
-	coherence();
-	splx(s);
-}

+ 0 - 330
sys/src/9/kw/dat.h

@@ -1,330 +0,0 @@
-/*
- * This file is part of the UCB release of Plan 9. It is subject to the license
- * terms in the LICENSE file found in the top-level directory of this
- * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
- * part of the UCB release of Plan 9, including this file, may be copied,
- * modified, propagated, or distributed except according to the terms contained
- * in the LICENSE file.
- */
-
-typedef struct Conf	Conf;
-typedef struct Confmem	Confmem;
-typedef struct FPsave	FPsave;
-typedef struct ISAConf	ISAConf;
-typedef struct Label	Label;
-typedef struct Lock	Lock;
-typedef struct Memcache	Memcache;
-typedef struct MMMU	MMMU;
-typedef struct Mach	Mach;
-typedef struct Notsave	Notsave;
-typedef struct Page	Page;
-typedef struct Pcidev	Pcidev;
-typedef struct PhysUart	PhysUart;
-typedef struct PMMU	PMMU;
-typedef struct Proc	Proc;
-typedef u32int		PTE;
-typedef struct Soc	Soc;
-typedef struct Uart	Uart;
-typedef struct Ureg	Ureg;
-typedef uvlong		Tval;
-
-#pragma incomplete Pcidev
-#pragma incomplete Ureg
-
-#define MAXSYSARG	5	/* for mount(fd, mpt, flag, arg, srv) */
-
-/*
- *  parameters for sysproc.c
- */
-#define AOUT_MAGIC	(E_MAGIC)
-
-struct Lock
-{
-	ulong	key;
-	u32int	sr;
-	uintptr	pc;
-	Proc*	p;
-	Mach*	m;
-	int	isilock;
-};
-
-struct Label
-{
-	uintptr	sp;
-	uintptr	pc;
-};
-
-/*
- * emulated floating point
- */
-struct FPsave
-{
-	ulong	status;
-	ulong	control;
-	ulong	regs[8][3];
-
-	int	fpstate;
-};
-
-/*
- * FPsave.status
- */
-enum
-{
-	FPinit,
-	FPactive,
-	FPinactive,
-
-	/* bit or'd with the state */
-	FPillegal= 0x100,
-};
-
-struct Confmem
-{
-	uintptr	base;
-	usize	npage;
-	uintptr	limit;
-	uintptr	kbase;
-	uintptr	klimit;
-};
-
-struct Conf
-{
-	ulong	nmach;		/* processors */
-	ulong	nproc;		/* processes */
-	ulong	monitor;	/* has monitor? */
-	Confmem	mem[1];		/* physical memory */
-	ulong	npage;		/* total physical pages of memory */
-	usize	upages;		/* user page pool */
-	ulong	copymode;	/* 0 is copy on write, 1 is copy on reference */
-	ulong	ialloc;		/* max interrupt time allocation in bytes */
-	ulong	pipeqsize;	/* size in bytes of pipe queues */
-	ulong	nimage;		/* number of page cache image headers */
-	ulong	nswap;		/* number of swap pages */
-	int	nswppo;		/* max # of pageouts per segment pass */
-//	ulong	hz;		/* processor cycle freq */
-//	ulong	mhz;
-};
-
-/*
- *  things saved in the Proc structure during a notify
- */
-struct Notsave {
-	int	emptiness;
-};
-
-/*
- *  MMU stuff in Mach.
- */
-struct MMMU
-{
-	PTE*	mmul1;		/* l1 for this processor */
-	int	mmul1lo;
-	int	mmul1hi;
-	int	mmupid;
-};
-
-/*
- *  MMU stuff in proc
- */
-#define NCOLOR	1		/* 1 level cache, don't worry about VCE's */
-struct PMMU
-{
-	Page*	mmul2;
-	Page*	mmul2cache;	/* free mmu pages */
-};
-
-#include "../port/portdat.h"
-
-struct Mach
-{
-	int	machno;			/* physical id of processor */
-	uintptr	splpc;			/* pc of last caller to splhi */
-
-	Proc*	proc;			/* current process */
-
-	MMMU;
-	int	flushmmu;		/* flush current proc mmu state */
-
-	ulong	ticks;			/* of the clock since boot time */
-	Label	sched;			/* scheduler wakeup */
-	Lock	alarmlock;		/* access to alarm list */
-	void*	alarm;			/* alarms bound to this clock */
-	int	inclockintr;
-
-	Proc*	readied;		/* for runproc */
-	ulong	schedticks;		/* next forced context switch */
-
-	int	cputype;
-	int	socrev;			/* system-on-chip revision */
-	ulong	delayloop;
-
-	/* stats */
-	int	tlbfault;
-	int	tlbpurge;
-	int	pfault;
-	int	cs;
-	int	syscall;
-	int	load;
-	int	intr;
-	vlong	fastclock;		/* last sampled value */
-	ulong	spuriousintr;
-	int	lastintr;
-	int	ilockdepth;
-	Perf	perf;			/* performance counters */
-
-	uvlong	cpuhz;			/* speed of cpu */
-	uvlong	cyclefreq;		/* Frequency of user readable cycle counter */
-
-	/* save areas for exceptions */
-	u32int	sfiq[5];
-	u32int	sirq[5];
-	u32int	sund[5];
-	u32int	sabt[5];
-#define fiqstack sfiq
-#define irqstack sirq
-#define abtstack sabt
-#define undstack sund
-
-	int	stack[1];
-};
-
-/*
- * Fake kmap.
- */
-typedef void		KMap;
-#define	VA(k)		((uintptr)(k))
-#define	kmap(p)		(KMap*)((p)->pa|kseg0)
-#define	kunmap(k)
-
-struct
-{
-	Lock;
-	int	machs;			/* bitmap of active CPUs */
-	int	exiting;		/* shutdown */
-	int	ispanic;		/* shutdown in response to a panic */
-}active;
-
-enum {
-	Frequency	= 1200*1000*1000,	/* the processor clock */
-};
-
-extern register Mach* m;			/* R10 */
-extern register Proc* up;			/* R9 */
-
-extern uintptr kseg0;
-extern Mach* machaddr[MAXMACH];
-extern ulong memsize;
-
-enum {
-	Nvec = 8,	/* # of vectors at start of lexception.s */
-};
-
-/*
- * Layout of physical 0.
- */
-typedef struct Vectorpage {
-	void	(*vectors[Nvec])(void);
-	uint	vtable[Nvec];
-} Vectorpage;
-
-/*
- *  a parsed plan9.ini line
- */
-#define NISAOPT		8
-
-struct ISAConf {
-	char		*type;
-	ulong	port;
-	int	irq;
-	ulong	dma;
-	ulong	mem;
-	ulong	size;
-	ulong	freq;
-
-	int	nopt;
-	char	*opt[NISAOPT];
-};
-
-#define	MACHP(n)	(machaddr[n])
-
-/*
- * Horrid. But the alternative is 'defined'.
- */
-#ifdef _DBGC_
-#define DBGFLG		(dbgflg[_DBGC_])
-#else
-#define DBGFLG		(0)
-#endif /* _DBGC_ */
-
-int vflag;
-extern char dbgflg[256];
-
-#define dbgprint	print		/* for now */
-
-/*
- *  hardware info about a device
- */
-typedef struct {
-	ulong	port;	
-	int	size;
-} Devport;
-
-struct DevConf
-{
-	ulong	intnum;			/* interrupt number */
-	char	*type;			/* card type, malloced */
-	int	nports;			/* Number of ports */
-	Devport	*ports;			/* The ports themselves */
-};
-
-enum {
-	Dcache,
-	Icache,
-	Unified,
-};
-
-/* characteristics of a given cache level */
-struct Memcache {
-	uint	level;		/* 1 is nearest processor, 2 further away */
-	uint	kind;		/* I, D or unified */
-
-	uint	size;
-	uint	nways;		/* associativity */
-	uint	nsets;
-	uint	linelen;	/* bytes per cache line */
-	uint	setsways;
-
-	uint	log2linelen;
-	uint	waysh;		/* shifts for set/way register */
-	uint	setsh;
-};
-
-struct Soc {			/* addr's of SoC controllers */
-	uintptr	cpu;
-	uintptr	devid;
-	uintptr	l2cache;
-	uintptr	sdramc;
-
-	uintptr	iocfg;
-	uintptr addrmap;
-	uintptr	intr;
-	uintptr	nand;
-	uintptr	cesa;		/* crypto accel. */
-	uintptr	ehci;
-	uintptr spi;
-	uintptr	twsi;
-
-	uintptr	analog;
-	uintptr	pci;
-	uintptr	pcibase;
-
-	uintptr	rtc;		/* real-time clock */
-	uintptr	clock;
-
-	uintptr ether[2];
-	uintptr	sata[3];
-	uintptr	uart[2];
-	uintptr	gpio[2];
-} soc;
-extern Soc soc;

Some files were not shown because too many files changed in this diff