summaryrefslogtreecommitdiff
path: root/sys/src
diff options
context:
space:
mode:
authorftrvxmtrx <ftrvxmtrx@gmail.com>2014-12-21 01:30:36 +0100
committerftrvxmtrx <ftrvxmtrx@gmail.com>2014-12-21 01:30:36 +0100
commita11fe1959db311c090c7a025d96643c7ad8b76e5 (patch)
treedf2fa652b5d6c74ba9cb6c135d62fc2920c09bc6 /sys/src
parent758496ecaa42b5f6c17c0bd1e0f43189e50e0745 (diff)
parent8ac28ac11cb9e96329e4d083208b3f13ee8d2b8a (diff)
merge
Diffstat (limited to 'sys/src')
-rw-r--r--sys/src/9/pc/archacpi.c58
-rw-r--r--sys/src/9/pc/archmp.c12
-rw-r--r--sys/src/9/pc/devarch.c3
-rw-r--r--sys/src/9/pc/fns.h2
-rw-r--r--sys/src/9/pc/main.c7
-rw-r--r--sys/src/9/pc/mmu.c6
-rw-r--r--sys/src/9/pc/mp.c23
-rw-r--r--sys/src/9/pc64/fns.h2
-rw-r--r--sys/src/9/pc64/main.c4
-rw-r--r--sys/src/9/pc64/pc646
-rw-r--r--sys/src/9/pc64/pccpu648
-rw-r--r--sys/src/9/port/fault.c4
-rw-r--r--sys/src/9/port/sdaoe.c34
-rw-r--r--sys/src/9/port/sdloop.c5
-rw-r--r--sys/src/9/port/xalloc.c6
-rw-r--r--sys/src/9/xen/fns.h5
-rw-r--r--sys/src/9/xen/l.s27
-rw-r--r--sys/src/9/xen/main.c64
-rw-r--r--sys/src/9/xen/mem.h57
-rw-r--r--sys/src/9/xen/mmu.c64
-rw-r--r--sys/src/cmd/acme/text.c10
-rw-r--r--sys/src/cmd/disk/mkfile1
-rw-r--r--sys/src/cmd/disk/vblade/aoe.h70
-rw-r--r--sys/src/cmd/disk/vblade/mkfile12
-rw-r--r--sys/src/cmd/disk/vblade/vblade.c666
-rw-r--r--sys/src/libflate/inflatezlibblock.c2
26 files changed, 840 insertions, 318 deletions
diff --git a/sys/src/9/pc/archacpi.c b/sys/src/9/pc/archacpi.c
index 6805f5c87..644df59b9 100644
--- a/sys/src/9/pc/archacpi.c
+++ b/sys/src/9/pc/archacpi.c
@@ -625,12 +625,42 @@ Foundapic:
mpinit();
}
+static void
+acpireset(void)
+{
+ uchar *p;
+ Tbl *t;
+ int i;
+
+ /* stop application processors */
+ mpshutdown();
+
+ /* locate and write platform reset register */
+ for(i=0; i < ntblmap; i++){
+ t = tblmap[i];
+ if(memcmp(t->sig, "FACP", 4) != 0)
+ continue;
+ if(get32(t->len) <= 128)
+ break;
+ p = (uchar*)t;
+ if((get32(p + 112) & (1<<10)) == 0)
+ break;
+ if(p[116+0] != IoSpace)
+ break;
+ outb(get32(p+116+4), p[128]);
+ break;
+ }
+
+ /* acpi shutdown failed, try generic reset */
+ archreset();
+}
+
static int identify(void);
PCArch archacpi = {
.id= "ACPI",
.ident= identify,
-.reset= mpshutdown,
+.reset= acpireset,
.intrinit= acpiinit,
.intrenable= mpintrenable,
.intron= lapicintron,
@@ -887,29 +917,3 @@ amldelay(int us)
{
microdelay(us);
}
-
-/*
- * reset machine by writing acpi reset register.
- */
-void
-acpireset(void)
-{
- uchar *p;
- Tbl *t;
- int i;
-
- for(i=0; i < ntblmap; i++){
- t = tblmap[i];
- if(memcmp(t->sig, "FACP", 4) != 0)
- continue;
- if(get32(t->len) <= 128)
- break;
- p = (uchar*)t;
- if((get32(p + 112) & (1<<10)) == 0)
- break;
- if(p[116+0] != IoSpace)
- break;
- outb(get32(p+116+4), p[128]);
- break;
- }
-}
diff --git a/sys/src/9/pc/archmp.c b/sys/src/9/pc/archmp.c
index 8fb269569..723433db8 100644
--- a/sys/src/9/pc/archmp.c
+++ b/sys/src/9/pc/archmp.c
@@ -354,12 +354,22 @@ pcmpinit(void)
mpinit();
}
+static void
+mpreset(void)
+{
+ /* stop application processors */
+ mpshutdown();
+
+ /* do generic reset */
+ archreset();
+}
+
static int identify(void);
PCArch archmp = {
.id= "_MP_",
.ident= identify,
-.reset= mpshutdown,
+.reset= mpreset,
.intrinit= pcmpinit,
.intrenable= mpintrenable,
.intron= lapicintron,
diff --git a/sys/src/9/pc/devarch.c b/sys/src/9/pc/devarch.c
index 412ca767e..24c5f0e7b 100644
--- a/sys/src/9/pc/devarch.c
+++ b/sys/src/9/pc/devarch.c
@@ -528,7 +528,7 @@ nop(void)
{
}
-static void
+void
archreset(void)
{
i8042reset();
@@ -548,6 +548,7 @@ archreset(void)
outb(0xcf9, 0x02);
outb(0xcf9, 0x06);
+ print("can't reset\n");
for(;;)
idle();
}
diff --git a/sys/src/9/pc/fns.h b/sys/src/9/pc/fns.h
index ccf5ea092..77eebd2fc 100644
--- a/sys/src/9/pc/fns.h
+++ b/sys/src/9/pc/fns.h
@@ -1,9 +1,9 @@
#include "../port/portfns.h"
void aamloop(int);
-void acpireset(void);
Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
void archinit(void);
+void archreset(void);
int bios32call(BIOS32ci*, u16int[3]);
int bios32ci(BIOS32si*, BIOS32ci*);
void bios32close(BIOS32si*);
diff --git a/sys/src/9/pc/main.c b/sys/src/9/pc/main.c
index 857c918cb..9d95c9f8a 100644
--- a/sys/src/9/pc/main.c
+++ b/sys/src/9/pc/main.c
@@ -121,7 +121,6 @@ options(void)
}
}
-extern void mmuinit0(void);
extern void (*i8237alloc)(void);
extern void bootscreeninit(void);
@@ -138,8 +137,6 @@ main(void)
print("\nPlan 9\n");
trapinit0();
- mmuinit0();
-
kbdinit();
i8253init();
cpuidentify();
@@ -908,8 +905,8 @@ shutdown(int ispanic)
once = active.machs & (1<<m->machno);
/*
* setting exiting will make hzclock() on each processor call exit(0),
- * which calls shutdown(0) and arch->reset(), which on mp systems is
- * mpshutdown, from which there is no return: the processor is idled
+ * which calls shutdown(0) and arch->reset(), which on mp systems calls
+ * mpshutdown(), from which there is no return: the processor is idled
* or initiates a reboot. clearing our bit in machs avoids calling
* exit(0) from hzclock() on this processor.
*/
diff --git a/sys/src/9/pc/mmu.c b/sys/src/9/pc/mmu.c
index 6fbc323af..0994d7be2 100644
--- a/sys/src/9/pc/mmu.c
+++ b/sys/src/9/pc/mmu.c
@@ -67,12 +67,6 @@ static void memglobal(void);
#define vpd (vpt+VPTX(VPT))
void
-mmuinit0(void)
-{
- memmove(m->gdt, gdt, sizeof gdt);
-}
-
-void
mmuinit(void)
{
ulong x, *p;
diff --git a/sys/src/9/pc/mp.c b/sys/src/9/pc/mp.c
index 63fe687fa..8bfc52204 100644
--- a/sys/src/9/pc/mp.c
+++ b/sys/src/9/pc/mp.c
@@ -562,7 +562,6 @@ mpintrenable(Vctl* v)
return -1;
}
-
void
mpshutdown(void)
{
@@ -572,7 +571,7 @@ mpshutdown(void)
if(m->machno != 0){
splhi();
arch->introff();
- idle();
+ for(;;) idle();
}
print("mpshutdown: active = %#8.8ux\n", active.machs);
@@ -585,24 +584,4 @@ mpshutdown(void)
lapicicrw(0, 0x000C0000|ApicINIT);
pcireset();
- acpireset();
- i8042reset();
-
- /*
- * Often the BIOS hangs during restart if a conventional 8042
- * warm-boot sequence is tried. The following is Intel specific and
- * seems to perform a cold-boot, but at least it comes back.
- * And sometimes there is no keyboard...
- *
- * The reset register (0xcf9) is usually in one of the bridge
- * chips. The actual location and sequence could be extracted from
- * ACPI but why bother, this is the end of the line anyway.
- */
- print("no kbd; trying bios warm boot...");
- *(ushort*)KADDR(0x472) = 0x1234; /* BIOS warm-boot flag */
- outb(0xCF9, 0x02);
- outb(0xCF9, 0x06);
-
- print("can't reset\n");
- idle();
}
diff --git a/sys/src/9/pc64/fns.h b/sys/src/9/pc64/fns.h
index 652d07737..0af15138f 100644
--- a/sys/src/9/pc64/fns.h
+++ b/sys/src/9/pc64/fns.h
@@ -1,9 +1,9 @@
#include "../port/portfns.h"
void aamloop(int);
-void acpireset(void);
Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,void*,long,vlong));
void archinit(void);
+void archreset(void);
int bios32call(BIOS32ci*, u16int[3]);
int bios32ci(BIOS32si*, BIOS32ci*);
void bios32close(BIOS32si*);
diff --git a/sys/src/9/pc64/main.c b/sys/src/9/pc64/main.c
index ee67d0b52..087450c55 100644
--- a/sys/src/9/pc64/main.c
+++ b/sys/src/9/pc64/main.c
@@ -537,8 +537,8 @@ shutdown(int ispanic)
once = active.machs & (1<<m->machno);
/*
* setting exiting will make hzclock() on each processor call exit(0),
- * which calls shutdown(0) and arch->reset(), which on mp systems is
- * mpshutdown, from which there is no return: the processor is idled
+ * which calls shutdown(0) and arch->reset(), which on mp systems calls
+ * mpshutdown(), from which there is no return: the processor is idled
* or initiates a reboot. clearing our bit in machs avoids calling
* exit(0) from hzclock() on this processor.
*/
diff --git a/sys/src/9/pc64/pc64 b/sys/src/9/pc64/pc64
index 0512bec61..9270ac820 100644
--- a/sys/src/9/pc64/pc64
+++ b/sys/src/9/pc64/pc64
@@ -28,7 +28,7 @@ dev
sd
# floppy dma
-# aoe
+ aoe
# lpt
audio dma
@@ -87,7 +87,7 @@ misc
archmp mp apic squidboy
mtrr
-# sdaoe
+ sdaoe
sdide pci sdscsi
# sd53c8xx pci sdscsi
# sdmylex pci sdscsi
@@ -95,7 +95,7 @@ misc
# sdodin pci sdscsi led
sdvirtio pci sdscsi
sdmmc pci pmmc
-# sdloop
+ sdloop
uarti8250
# uartisa
diff --git a/sys/src/9/pc64/pccpu64 b/sys/src/9/pc64/pccpu64
index ef82503d3..d9f556499 100644
--- a/sys/src/9/pc64/pccpu64
+++ b/sys/src/9/pc64/pccpu64
@@ -28,7 +28,7 @@ dev
sd
# floppy dma
-# aoe
+ aoe
# lpt
audio dma
@@ -87,15 +87,15 @@ misc
archmp mp apic squidboy
mtrr
-# sdaoe
+ sdaoe
sdide pci sdscsi
# sd53c8xx pci sdscsi
# sdmylex pci sdscsi
sdiahci pci sdscsi led
# sdodin pci sdscsi led
sdvirtio pci sdscsi
-# sdmmc pci pmmc
-# sdloop
+ sdmmc pci pmmc
+ sdloop
uarti8250
# uartisa
diff --git a/sys/src/9/port/fault.c b/sys/src/9/port/fault.c
index 478e29f3d..45c3959b3 100644
--- a/sys/src/9/port/fault.c
+++ b/sys/src/9/port/fault.c
@@ -389,7 +389,6 @@ extern void checkmmu(uintptr, uintptr);
void
checkpages(void)
{
- int checked;
uintptr addr, off;
Pte *p;
Page *pg;
@@ -398,7 +397,6 @@ checkpages(void)
if(up == nil)
return;
- checked = 0;
for(sp=up->seg, ep=&up->seg[NSEG]; sp<ep; sp++){
if((s = *sp) == nil)
continue;
@@ -411,9 +409,7 @@ checkpages(void)
if(pagedout(pg))
continue;
checkmmu(addr, pg->pa);
- checked++;
}
qunlock(s);
}
- print("%ld %s: checked %d page table entries\n", up->pid, up->text, checked);
}
diff --git a/sys/src/9/port/sdaoe.c b/sys/src/9/port/sdaoe.c
index 90259705d..7c3c7bf67 100644
--- a/sys/src/9/port/sdaoe.c
+++ b/sys/src/9/port/sdaoe.c
@@ -249,19 +249,6 @@ static char *probef[32];
static char *probebuf;
static int nprobe;
-static int
-pnpprobeid(char *s)
-{
- int id;
-
- if(strlen(s) < 2)
- return 0;
- id = 'e';
- if(s[1] == '!')
- id = s[0];
- return id;
-}
-
static SDev*
aoepnp(void)
{
@@ -275,9 +262,26 @@ aoepnp(void)
nprobe = tokenize(probebuf, probef, nelem(probef));
h = t = 0;
for(i = 0; i < nprobe; i++){
- id = pnpprobeid(probef[i]);
- if(id == 0)
+ p = probef[i];
+ if(strlen(p) < 2)
continue;
+ id = 'e';
+ if(p[1] == '!'){
+ id = p[0];
+ p += 2;
+ }
+ /*
+ * shorthand for: id!lun -> id!#æ/aoe/lun
+ * because we cannot type æ in the bootloader console.
+ */
+ if(strchr(p, '/') == nil){
+ char tmp[64];
+
+ snprint(tmp, sizeof(tmp), "%c!#æ/aoe/%s", (char)id, p);
+
+ probef[i] = nil;
+ kstrdup(&probef[i], tmp);
+ }
s = malloc(sizeof *s);
if(s == nil)
break;
diff --git a/sys/src/9/port/sdloop.c b/sys/src/9/port/sdloop.c
index 80118369d..49ea6886d 100644
--- a/sys/src/9/port/sdloop.c
+++ b/sys/src/9/port/sdloop.c
@@ -14,9 +14,6 @@
#include "../port/netif.h"
extern char Echange[];
-extern char Enotup[];
-
-#define uprint(...) snprint(up->genbuf, sizeof up->genbuf, __VA_ARGS__);
enum {
Maxpath = 256,
@@ -302,7 +299,7 @@ loopbio(SDunit *u, int, int write, void *a, long count, uvlong lba)
if(waserror()){
if(strcmp(up->errstr, Echange) == 0 ||
- strcmp(up->errstr, Enotup) == 0)
+ strstr(up->errstr, "device is down") != nil)
u->sectors = 0;
nexterror();
}
diff --git a/sys/src/9/port/xalloc.c b/sys/src/9/port/xalloc.c
index 15a5327e6..6db734160 100644
--- a/sys/src/9/port/xalloc.c
+++ b/sys/src/9/port/xalloc.c
@@ -242,7 +242,7 @@ xhole(uintptr addr, uintptr size)
if(xlists.flist == nil) {
iunlock(&xlists);
- print("xfree: no free holes, leaked %p bytes\n", size);
+ print("xfree: no free holes, leaked %llud bytes\n", (uvlong)size);
return;
}
@@ -270,8 +270,8 @@ xsummary(void)
s = 0;
for(h = xlists.table; h; h = h->link) {
- print("%#p %#p %p\n", h->addr, h->top, h->size);
+ print("%#8.8p %#8.8p %llud\n", h->addr, h->top, (uvlong)h->size);
s += h->size;
}
- print("%lld bytes free\n", (vlong)s);
+ print("%llud bytes free\n", (uvlong)s);
}
diff --git a/sys/src/9/xen/fns.h b/sys/src/9/xen/fns.h
index 3659354fa..71e64ac4c 100644
--- a/sys/src/9/xen/fns.h
+++ b/sys/src/9/xen/fns.h
@@ -4,8 +4,6 @@ Dirtab* addarchfile(char*, int, long(*)(Chan*,void*,long,vlong), long(*)(Chan*,v
void archinit(void);
void bootargs(ulong);
ulong cankaddr(ulong);
-int cistrcmp(char*, char*);
-int cistrncmp(char*, char*, int);
#define clearmmucache() /* x86 doesn't have one */
void clockintr(Ureg*, void*);
int (*cmpswap)(long*, long, long);
@@ -63,10 +61,7 @@ void ioinit(void);
int isaconfig(char*, int, ISAConf*);
void kbdenable(void);
#define kmapinval()
-void lgdt(ushort[3]); // XXX remove and in l.s
-void lidt(ushort[3]); // XXX remove and in l.s
void links(void);
-void ltr(ulong); // XXX remove?
void mach0init(void);
void mathinit(void);
void mb386(void);
diff --git a/sys/src/9/xen/l.s b/sys/src/9/xen/l.s
index ff9515c33..dbfbf248e 100644
--- a/sys/src/9/xen/l.s
+++ b/sys/src/9/xen/l.s
@@ -54,25 +54,6 @@ _idle:
* CR4 and the 'model specific registers' should only be read/written
* after it has been determined the processor supports them
*/
-TEXT lgdt(SB), $0 /* GDTR - global descriptor table */
- MOVL gdtptr+0(FP), AX
- MOVL (AX), GDTR
- RET
-
-TEXT lidt(SB), $0 /* IDTR - interrupt descriptor table */
- MOVL idtptr+0(FP), AX
- MOVL (AX), IDTR
- RET
-
-TEXT ltr(SB), $0 /* TR - task register */
- MOVL tptr+0(FP), AX
- MOVW AX, TASK
- RET
-
-TEXT rtsr(SB), $0
- MOVW TASK, AX
- RET
-
TEXT _cycles(SB), $0 /* time stamp counter; cycles since power up */
RDTSC
MOVL vlong+0(FP), CX /* &vlong */
@@ -88,13 +69,9 @@ TEXT rdmsr(SB), $0 /* model-specific register */
MOVL DX, 4(CX) /* hi */
RET
+/* Xen doesn't let us do this */
TEXT wrmsr(SB), $0
- MOVL index+0(FP), CX
- MOVL lo+4(FP), AX
- MOVL hi+8(FP), DX
-/* Xen doesn't let us do this
- WRMSR
- */
+ MOVL $-1, AX
RET
/*
diff --git a/sys/src/9/xen/main.c b/sys/src/9/xen/main.c
index cc06a4306..2cc4e2ca6 100644
--- a/sys/src/9/xen/main.c
+++ b/sys/src/9/xen/main.c
@@ -118,9 +118,6 @@ mach0init(void)
conf.nmach = 1;
MACHP(0) = (Mach*)CPU0MACH;
m->pdb = (ulong*)xenstart->pt_base;
-#ifdef NOT
- m->gdt = (Segdesc*)CPU0GDT;
-#endif
machinit();
@@ -133,15 +130,12 @@ machinit(void)
{
int machno;
ulong *pdb;
- Segdesc *gdt;
machno = m->machno;
pdb = m->pdb;
- gdt = m->gdt;
memset(m, 0, sizeof(Mach));
m->machno = machno;
m->pdb = pdb;
- m->gdt = gdt;
m->perf.period = 1;
/*
@@ -585,16 +579,6 @@ procfork(Proc *p)
p->kentry = up->kentry;
p->pcycles = -p->kentry;
- /* inherit user descriptors */
- memmove(p->gdt, up->gdt, sizeof(p->gdt));
-
- /* copy local descriptor table */
- if(up->ldt != nil && up->nldt > 0){
- p->ldt = smalloc(sizeof(Segdesc) * up->nldt);
- memmove(p->ldt, up->ldt, sizeof(Segdesc) * up->nldt);
- p->nldt = up->nldt;
- }
-
/* save floating point state */
s = splhi();
switch(up->fpstate & ~FPillegal){
@@ -750,51 +734,3 @@ exit(int ispanic)
shutdown(ispanic);
arch->reset();
}
-
-int
-cistrcmp(char *a, char *b)
-{
- int ac, bc;
-
- for(;;){
- ac = *a++;
- bc = *b++;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
- return 0;
-}
-
-int
-cistrncmp(char *a, char *b, int n)
-{
- unsigned ac, bc;
-
- while(n > 0){
- ac = *a++;
- bc = *b++;
- n--;
-
- if(ac >= 'A' && ac <= 'Z')
- ac = 'a' + (ac - 'A');
- if(bc >= 'A' && bc <= 'Z')
- bc = 'a' + (bc - 'A');
-
- ac -= bc;
- if(ac)
- return ac;
- if(bc == 0)
- break;
- }
-
- return 0;
-}
-
diff --git a/sys/src/9/xen/mem.h b/sys/src/9/xen/mem.h
index d0b3cc356..c4a6886ef 100644
--- a/sys/src/9/xen/mem.h
+++ b/sys/src/9/xen/mem.h
@@ -63,67 +63,14 @@
/*
* known x86 segments (in GDT) and their selectors
+ * using the selectors that xen gives us.
*/
-#define NULLSEG 0 /* null segment */
-#define KDSEG 1 /* kernel data/stack */
-#define KESEG 2 /* kernel executable */
-#define UDSEG 3 /* user data/stack */
-#define UESEG 4 /* user executable */
-#define TSSSEG 5 /* task segment */
-#define APMCSEG 6 /* APM code segment */
-#define APMCSEG16 7 /* APM 16-bit code segment */
-#define APMDSEG 8 /* APM data segment */
-#define PROCSEG0 11 /* per process descriptor0 */
-#define NPROCSEG 3 /* number of per process descriptors */
-#define NGDT 13 /* number of GDT entries required */
-/* #define APM40SEG 8 /* APM segment 0x40 */
-
-#define SELGDT (0<<2) /* selector is in gdt */
-#define SELLDT (1<<2) /* selector is in ldt */
-
-#define SELECTOR(i, t, p) (((i)<<3) | (t) | (p))
-
-#define NULLSEL SELECTOR(NULLSEG, SELGDT, 0)
-/* these are replaced by XEN entries */
-#ifdef NOPE // XXX investigate more
-#define KDSEL SELECTOR(KDSEG, SELGDT, 0)
-#define KESEL SELECTOR(KESEG, SELGDT, 0)
-#define UESEL SELECTOR(UESEG, SELGDT, 3)
-#define UDSEL SELECTOR(UDSEG, SELGDT, 3)
-/* comment out to make sure unused ... */
-
-#define TSSSEL SELECTOR(TSSSEG, SELGDT, 0)
-#define APMCSEL SELECTOR(APMCSEG, SELGDT, 0)
-#define APMCSEL16 SELECTOR(APMCSEG16, SELGDT, 0)
-#define APMDSEL SELECTOR(APMDSEG, SELGDT, 0)
-/* #define APM40SEL SELECTOR(APM40SEG, SELGDT, 0) */
-#else
-/* use the selectors that xen gives us */
#define KESEL FLAT_KERNEL_CS
#define KDSEL FLAT_KERNEL_DS
#define UESEL FLAT_USER_CS
#define UDSEL FLAT_USER_DS
-#endif
-
-/*
- * fields in segment descriptors
- */
-#define SEGDATA (0x10<<8) /* data/stack segment */
-#define SEGEXEC (0x18<<8) /* executable segment */
-#define SEGTSS (0x9<<8) /* TSS segment */
-#define SEGCG (0x0C<<8) /* call gate */
-#define SEGIG (0x0E<<8) /* interrupt gate */
-#define SEGTG (0x0F<<8) /* trap gate */
-#define SEGTYPE (0x1F<<8)
-#define SEGP (1<<15) /* segment present */
-#define SEGPL(x) ((x)<<13) /* priority level */
-#define SEGB (1<<22) /* granularity 1==4k (for expand-down) */
-#define SEGG (1<<23) /* granularity 1==4k (for other) */
-#define SEGE (1<<10) /* expand down */
-#define SEGW (1<<9) /* writable (for data/stack) */
-#define SEGR (1<<9) /* readable (for code) */
-#define SEGD (1<<22) /* default 1==32bit (for code) */
+#define NPROCSEG 1 /* number of per process descriptors */
/*
* virtual MMU
diff --git a/sys/src/9/xen/mmu.c b/sys/src/9/xen/mmu.c
index cd51b47ff..9adc9cfea 100644
--- a/sys/src/9/xen/mmu.c
+++ b/sys/src/9/xen/mmu.c
@@ -13,35 +13,10 @@ uvlong *xenpdpt; /* this needs to go in Mach for multiprocessor guest */
#define MFN(pa) (patomfn[(pa)>>PGSHIFT])
#define MAPPN(x) (paemode? matopfn[*(uvlong*)(&x)>>PGSHIFT]<<PGSHIFT : matopfn[(x)>>PGSHIFT]<<PGSHIFT)
-#define DATASEGM(p) { 0xFFFF, SEGG|SEGB|(0xF<<16)|SEGP|SEGPL(p)|SEGDATA|SEGW }
-#define EXECSEGM(p) { 0xFFFF, SEGG|SEGD|(0xF<<16)|SEGP|SEGPL(p)|SEGEXEC|SEGR }
-#define TSSSEGM(b,p) { ((b)<<16)|sizeof(Tss),\
- ((b)&0xFF000000)|(((b)>>16)&0xFF)|SEGTSS|SEGPL(p)|SEGP }
-
-Segdesc gdt[NGDT] =
-{
-[NULLSEG] { 0, 0}, /* null descriptor */
-[KDSEG] DATASEGM(0), /* kernel data/stack */
-[KESEG] EXECSEGM(0), /* kernel code */
-[UDSEG] DATASEGM(3), /* user data/stack */
-[UESEG] EXECSEGM(3), /* user code */
-[TSSSEG] TSSSEGM(0,0), /* tss segment */
-};
-
/* note: pdb must already be pinned */
static void
taskswitch(Page *pdb, ulong stack)
{
- Tss *tss;
-
- tss = m->tss;
- tss->ss0 = KDSEL;
- tss->esp0 = stack;
- tss->ss1 = KDSEL;
- tss->esp1 = stack;
- tss->ss2 = KDSEL;
- tss->esp2 = stack;
- //tss->cr3 = pdb;
HYPERVISOR_stack_switch(KDSEL, stack);
mmuflushtlb(pdb);
}
@@ -164,10 +139,7 @@ mmumapcpu0(void)
void
mmuinit(void)
{
-//XXX ulong x;
-//XXX ushort ptr[3];
ulong *pte, npgs, pa;
- extern int rtsr(void);
if(paemode){
int i;
@@ -193,39 +165,6 @@ mmuinit(void)
memglobal();
- m->tss = malloc(sizeof(Tss));
- memset(m->tss, 0, sizeof(Tss));
- m->tss->iomap = 0xDFFF<<16;
-
- /*
- * We used to keep the GDT in the Mach structure, but it
- * turns out that that slows down access to the rest of the
- * page. Since the Mach structure is accessed quite often,
- * it pays off anywhere from a factor of 1.25 to 2 on real
- * hardware to separate them (the AMDs are more sensitive
- * than Intels in this regard). Under VMware it pays off
- * a factor of about 10 to 100.
- */
-
-#ifdef we_dont_set_gdt_or_lidt
- memmove(m->gdt, gdt, sizeof gdt);
- x = (ulong)m->tss;
- m->gdt[TSSSEG].d0 = (x<<16)|sizeof(Tss);
- m->gdt[TSSSEG].d1 = (x&0xFF000000)|((x>>16)&0xFF)|SEGTSS|SEGPL(0)|SEGP;
-
- ptr[0] = sizeof(gdt)-1;
- x = (ulong)m->gdt;
- ptr[1] = x & 0xFFFF;
- ptr[2] = (x>>16) & 0xFFFF;
- lgdt(ptr);
-
- ptr[0] = sizeof(Segdesc)*256-1;
- x = IDTADDR;
- ptr[1] = x & 0xFFFF;
- ptr[2] = (x>>16) & 0xFFFF;
- lidt(ptr);
-#endif
-
#ifdef we_may_eventually_want_this
/* make kernel text unwritable */
for(x = KTZERO; x < (ulong)etext; x += BY2PG){
@@ -237,9 +176,6 @@ mmuinit(void)
#endif
taskswitch(0, (ulong)m + BY2PG);
-#ifdef we_dont_do_this
- ltr(TSSSEL);
-#endif
}
void
diff --git a/sys/src/cmd/acme/text.c b/sys/src/cmd/acme/text.c
index 957bca37d..7380d0163 100644
--- a/sys/src/cmd/acme/text.c
+++ b/sys/src/cmd/acme/text.c
@@ -643,8 +643,6 @@ texttype(Text *t, Rune r)
Rune *rp;
Text *u;
- if(t->what!=Body && r=='\n')
- return;
nr = 1;
rp = &r;
switch(r){
@@ -670,7 +668,8 @@ texttype(Text *t, Rune r)
n = 2*t->maxlines/3;
case_Down:
q0 = t->org+frcharofpt(t, Pt(t->r.min.x, t->r.min.y+n*t->font->height));
- textsetorigin(t, q0, TRUE);
+ if(t->what == Body)
+ textsetorigin(t, q0, TRUE);
return;
case Kup:
n = t->maxlines/3;
@@ -682,7 +681,8 @@ texttype(Text *t, Rune r)
n = 2*t->maxlines/3;
case_Up:
q0 = textbacknl(t, t->org, n);
- textsetorigin(t, q0, TRUE);
+ if(t->what == Body)
+ textsetorigin(t, q0, TRUE);
return;
case Khome:
typecommit(t);
@@ -776,7 +776,7 @@ texttype(Text *t, Rune r)
textfill(t->file->text[i]);
return;
case '\n':
- if(t->w->autoindent){
+ if(t->what == Body && t->w->autoindent){
/* find beginning of previous line using backspace code */
nnb = textbswidth(t, 0x15); /* ^U case */
rp = runemalloc(nnb + 1);
diff --git a/sys/src/cmd/disk/mkfile b/sys/src/cmd/disk/mkfile
index c762df038..7acb0fcef 100644
--- a/sys/src/cmd/disk/mkfile
+++ b/sys/src/cmd/disk/mkfile
@@ -14,6 +14,7 @@ DIRS=\
prep\
smart\
# sacfs\
+ vblade\
OFILES=
diff --git a/sys/src/cmd/disk/vblade/aoe.h b/sys/src/cmd/disk/vblade/aoe.h
new file mode 100644
index 000000000..1a9592a22
--- /dev/null
+++ b/sys/src/cmd/disk/vblade/aoe.h
@@ -0,0 +1,70 @@
+enum{
+ ACata,
+ ACconfig,
+};
+
+enum{
+ AQCread,
+ AQCtest,
+ AQCprefix,
+ AQCset,
+ AQCfset,
+};
+
+enum{
+ AEcmd = 1,
+ AEarg,
+ AEdev,
+ AEcfg,
+ AEver,
+};
+
+enum{
+ Aoetype = 0x88a2,
+ Aoesectsz = 512,
+ Aoemaxcfg = 1024,
+
+ Aoehsz = 24,
+ Aoeatasz = 12,
+ Aoecfgsz = 8,
+ Aoerrsz = 2,
+ Aoemsz = 4,
+ Aoemdsz = 8,
+
+ Aoever = 1,
+
+ AFerr = 1<<2,
+ AFrsp = 1<<3,
+
+ AAFwrite = 1,
+ AAFext = 1<<6,
+};
+
+typedef struct{
+ uchar dst[Eaddrlen];
+ uchar src[Eaddrlen];
+ uchar type[2];
+ uchar verflag;
+ uchar error;
+ uchar major[2];
+ uchar minor;
+ uchar cmd;
+ uchar tag[4];
+}Aoehdr;
+
+typedef struct{
+ uchar aflag;
+ uchar errfeat;
+ uchar scnt;
+ uchar cmdstat;
+ uchar lba[6];
+ uchar res[2];
+}Aoeata;
+
+typedef struct{
+ uchar bufcnt[2];
+ uchar fwver[2];
+ uchar scnt;
+ uchar verccmd;
+ uchar cslen[2];
+}Aoeqc;
diff --git a/sys/src/cmd/disk/vblade/mkfile b/sys/src/cmd/disk/vblade/mkfile
new file mode 100644
index 000000000..a03a7d0ef
--- /dev/null
+++ b/sys/src/cmd/disk/vblade/mkfile
@@ -0,0 +1,12 @@
+</$objtype/mkfile
+
+TARG=vblade
+
+OFILES=\
+ vblade.$O\
+
+HFILES=aoe.h
+
+BIN=/$objtype/bin/disk
+
+</sys/src/cmd/mkone
diff --git a/sys/src/cmd/disk/vblade/vblade.c b/sys/src/cmd/disk/vblade/vblade.c
new file mode 100644
index 000000000..fac1abe33
--- /dev/null
+++ b/sys/src/cmd/disk/vblade/vblade.c
@@ -0,0 +1,666 @@
+/*
+ * vblade -- virtual aoe target
+ * copyright © 2007 erik quanstrom
+ */
+
+#include <u.h>
+#include <libc.h>
+#include <thread.h>
+#include <ip.h> /* irony */
+#include <fis.h>
+
+enum {
+ Eaddrlen = 6, /* only defined in kernel */
+};
+#include "aoe.h"
+
+enum {
+ Fclone,
+ Fdata,
+ Flast,
+
+ Fraw = 1<<0,
+
+ Nether = 8,
+ Nvblade = 8,
+ Maxpkt = 10000,
+ Hdrlba = 128,
+ Conflen = 1024,
+};
+
+typedef struct {
+ int iflag;
+ int flag;
+ int shelf;
+ int slot;
+ uvlong maxlba;
+ char *config;
+} Conf;
+
+typedef struct {
+ char magic[32];
+ char size[32];
+ char address[16];
+ char configlen[6];
+ char pad[512-32-32-16-6];
+ char config[Conflen];
+} Vbhdr;
+
+typedef struct {
+ Vbhdr hdr;
+ vlong maxlba;
+ vlong hdrsz;
+ int shelf;
+ int slot;
+ int clen;
+ int flag;
+ int fd;
+} Vblade;
+
+static Vblade vblade[Nvblade];
+static int nblade;
+
+static char *ethertab[Nether] = {
+ "/net/ether0",
+};
+static int etheridx = 1;
+static int efdtab[Nether*Flast];
+static char pkttab[Nether][Maxpkt];
+static char bctab[Nether][Maxpkt];
+static int mtutab[Nether];
+static char Magic[] = "aoe vblade\n";
+
+static int
+getmtu(char *p)
+{
+ char buf[50];
+ int fd, mtu;
+
+ snprint(buf, sizeof buf, "%s/mtu", p);
+ if((fd = open(buf, OREAD)) == -1)
+ return 2;
+ if(read(fd, buf, 36) < 0)
+ return 2;
+ close(fd);
+ buf[36] = 0;
+ mtu = strtoul(buf+12, 0, 0)-Aoehsz;
+ return mtu>>9;
+}
+
+int
+parseshelf(char *s, int *shelf, int *slot)
+{
+ int a, b;
+
+ a = strtoul(s, &s, 0);
+ if(*s++ != '.')
+ return -1;
+ b = strtoul(s, &s, 0);
+ if(*s != 0)
+ return -1;
+ *shelf = a;
+ *slot = b;
+ return 0;
+}
+
+static vlong
+getsize(char *s)
+{
+ static char tab[] = "ptgmk";
+ char *p;
+ vlong v;
+
+ v = strtoull(s, &s, 0);
+ while((p = strchr(tab, *s++)) && *p)
+ while(*p++)
+ v *= 1024;
+ if(s[-1])
+ return -1;
+ return v;
+}
+
+vlong
+sizetolba(vlong size)
+{
+ if(size < 512 || size & 0x1ff){
+ fprint(2, "invalid size %lld\n", size);
+ exits("size");
+ }
+ return size>>9;
+}
+
+static int
+savevblade(int fd, Vblade *vb)
+{
+ int n, r;
+ char *p;
+
+ sprint(vb->hdr.size, "%lld", vb->maxlba<<9);
+ sprint(vb->hdr.address, "%d.%d", vb->shelf, vb->slot);
+ sprint(vb->hdr.configlen, "%d", vb->clen);
+
+ if(vb->flag & Fraw)
+ return 0;
+ p = (char*)vb;
+ for(n = 0; n < sizeof *vb; n += r)
+ if((r = pwrite(fd, p+n, sizeof *vb-n, n)) <= 0)
+ break;
+ if(n != sizeof *vb)
+ return -1;
+ return 0;
+}
+
+static char*
+chkvblade(int fd, Vblade *vb)
+{
+ Vbhdr *h;
+
+ h = &vb->hdr;
+ if(readn(fd, (char*)h, sizeof *h) != sizeof *h)
+ return "bad read";
+ if(memcmp(h->magic, Magic, sizeof Magic))
+ return "bad magic";
+ h->size[sizeof h->size-1] = 0;
+ vb->maxlba = sizetolba(strtoull(h->size, 0, 0));
+ if(parseshelf(h->address, &vb->shelf, &vb->slot) == -1)
+ return "bad shelf";
+ h->configlen[sizeof h->configlen-1] = 0;
+ vb->clen = strtoul(h->configlen, 0, 0);
+ return 0;
+}
+
+void
+checkfile(char *s, Vblade *vb, int iflag)
+{
+ char *e;
+
+ vb->fd = open(s, ORDWR);
+ if(vb->fd == -1)
+ sysfatal("can't open backing store: %r");
+ if(iflag == 0 && (e = chkvblade(vb->fd, vb)))
+ sysfatal("invalid vblade %s", e);
+}
+
+void
+recheck(int fd, Vblade *vb)
+{
+ Dir *d;
+ vlong v;
+
+ d = dirfstat(fd);
+ if(d == 0)
+ sysfatal("can't stat: %r");
+ if((vb->flag & Fraw) == 0)
+ vb->hdrsz = Hdrlba;
+ v = sizetolba(d->length & ~0x1ff) - vb->hdrsz;
+ free(d);
+ if(vb->maxlba > v)
+ sysfatal("cmdline size too large (%lld sector overhead)", vb->hdrsz);
+ if(vb->maxlba == 0)
+ vb->maxlba = v;
+
+ savevblade(fd, vb);
+}
+
+int
+aoeopen(char *e, int fds[])
+{
+ char buf[128], ctl[13];
+ int n;
+
+ snprint(buf, sizeof buf, "%s/clone", e);
+ if((fds[Fclone] = open(buf, ORDWR)) == -1)
+ return -1;
+ memset(ctl, 0, sizeof ctl);
+ if(read(fds[Fclone], ctl, sizeof ctl - 1) < 0)
+ return -1;
+ n = atoi(ctl);
+ snprint(buf, sizeof buf, "connect %d", Aoetype);
+ if(write(fds[Fclone], buf, strlen(buf)) != strlen(buf))
+ return -1;
+ snprint(buf, sizeof buf, "%s/%d/data", e, n);
+ fds[Fdata] = open(buf, ORDWR);
+ return fds[Fdata];
+}
+
+void
+replyhdr(Aoehdr *h, Vblade *vblade)
+{
+ uchar ea[Eaddrlen];
+
+ memmove(ea, h->dst, Eaddrlen);
+ memmove(h->dst, h->src, Eaddrlen);
+ memmove(h->src, ea, Eaddrlen);
+
+ hnputs(h->major, vblade->shelf);
+ h->minor = vblade->slot;
+ h->verflag |= AFrsp;
+}
+
+static int
+serveconfig(Aoehdr *h, Vblade *vb, int mtu)
+{
+ int cmd, reqlen, len;
+ char *cfg;
+ Aoeqc *q;
+
+ if(memcmp(h->src, h->dst, Eaddrlen) == 0)
+ return -1;
+
+ q = (Aoeqc*)((char*)h + Aoehsz);
+ reqlen = nhgets(q->cslen);
+ len = vb->clen;
+ cmd = q->verccmd&0xf;
+ cfg = (char*)q + Aoecfgsz;
+
+ switch(cmd){
+ case AQCtest:
+ if(reqlen != len)
+ return -1;
+ case AQCprefix:
+ if(reqlen > len)
+ return -1;
+ if(memcmp(vb->hdr.config, cfg, reqlen) != 0)
+ return -1;
+ case AQCread:
+ break;
+ case AQCset:
+ if(len && len != reqlen || memcmp(vb->hdr.config, cfg, reqlen) != 0){
+ h->verflag |= AFerr;
+ h->error = AEcfg;
+ break;
+ }
+ case AQCfset:
+ if(reqlen > Conflen){
+ h->verflag |= AFerr;
+ h->error = AEarg;
+ break;
+ }
+ memset(vb->hdr.config, 0, sizeof vb->hdr.config);
+ memmove(vb->hdr.config, cfg, reqlen);
+ vb->clen = len = reqlen;
+ savevblade(vb->fd, vb);
+ break;
+ default:
+ h->verflag |= AFerr;
+ h->error = AEarg;
+ }
+
+ memmove(cfg, vb->hdr.config, len);
+ hnputs(q->cslen, len);
+ hnputs(q->bufcnt, 24);
+ q->scnt = mtu;
+ hnputs(q->fwver, 2323);
+ q->verccmd = Aoever<<4 | cmd;
+
+ return Aoehsz+Aoecfgsz + len;
+}
+
+static ushort ident[256] = {
+ [47] 0x8000,
+ [49] 0x0200,
+ [50] 0x4000,
+ [83] 0x5400,
+ [84] 0x4000,
+ [86] 0x1400,
+ [87] 0x4000,
+ [93] 0x400b,
+};
+
+static void
+idmoveto(char *a, int idx, int len, char *s)
+{
+ char *p;
+
+ p = a+idx*2;
+ for(; len > 0; len -= 2) {
+ if(*s == 0)
+ p[1] = ' ';
+ else
+ p[1] = *s++;
+ if (*s == 0)
+ p[0] = ' ';
+ else
+ p[0] = *s++;
+ p += 2;
+ }
+}
+
+static void
+lbamoveto(char *p, int idx, int n, vlong lba)
+{
+ int i;
+
+ p += idx*2;
+ for(i = 0; i < n; i++)
+ *p++ = lba>>i*8;
+}
+
+enum {
+ Crd = 0x20,
+ Crdext = 0x24,
+ Cwr = 0x30,
+ Cwrext = 0x34,
+ Cid = 0xec,
+};
+
+static uvlong
+getlba(uchar *p)
+{
+ uvlong v;
+
+ v = p[0];
+ v |= p[1]<<8;
+ v |= p[2]<<16;
+ v |= p[3]<<24;
+ v |= (uvlong)p[4]<<32;
+ v |= (uvlong)p[5]<<40;
+ return v;
+}
+
+static void
+putlba(uchar *p, vlong lba)
+{
+ p[0] = lba;
+ p[1] = lba>>8;
+ p[2] = lba>>16;
+ p[3] = lba>>24;
+ p[5] = lba>>32;
+ p[6] = lba>>40;
+}
+
+static int
+serveata(Aoehdr *h, Vblade *vb, int mtu)
+{
+ Aoeata *a;
+ char *buf;
+ int rbytes, bytes, len;
+ vlong lba, off;
+
+ a = (Aoeata*)((char*)h + Aoehsz);
+ buf = (char*)a + Aoeatasz;
+ lba = getlba(a->lba);
+ len = a->scnt<<9;
+ off = lba+vb->hdrsz<<9;
+
+ rbytes = 0;
+ if(a->scnt > mtu || a->scnt == 0){
+ h->verflag |= AFerr;
+ a->cmdstat = ASdrdy|ASerr;
+ h->error = AEarg;
+ goto out;
+ }
+
+ if(a->cmdstat != Cid)
+ if(lba+a->scnt > vb->maxlba){
+ a->errfeat = Eidnf;
+ a->cmdstat = ASdrdy|ASerr;
+ goto out;
+ }
+
+ if(a->cmdstat&0xf0 == 0x20)
+ lba &= 0xfffffff;
+ switch(a->cmdstat){
+ default:
+ a->errfeat = Eabrt;
+ a->cmdstat = ASdrdy|ASerr;
+ goto out;
+ case Cid:
+ memmove(buf, ident, sizeof ident);
+ idmoveto(buf, 27, 40, "Plan 9 Vblade");
+ idmoveto(buf, 10, 20, "serial#");
+ idmoveto(buf, 23, 8, "2");
+ lbamoveto(buf, 60, 4, vb->maxlba);
+ lbamoveto(buf, 100, 8, vb->maxlba);
+ a->cmdstat = ASdrdy;
+ rbytes = 512;
+ goto out;
+ case Crd:
+ case Crdext:
+ bytes = pread(vb->fd, buf, len, off);
+ rbytes = bytes;
+ break;
+ case Cwr:
+ case Cwrext:
+ bytes = pwrite(vb->fd, buf, len, off);
+ break;
+ }
+ if(bytes != len){
+ a->errfeat = Eabrt;
+ a->cmdstat = ASdf|ASerr;
+ putlba(a->lba, lba+(len-bytes)>>9);
+ rbytes = 0;
+ goto out;
+ }
+
+ putlba(a->lba, lba+a->scnt);
+ a->scnt = 0;
+ a->errfeat = 0;
+ a->cmdstat = ASdrdy;
+out:
+ return Aoehsz+Aoeatasz + rbytes;
+}
+
+static int
+myea(uchar ea[6], char *p)
+{
+ char buf[50];
+ int fd;
+
+ snprint(buf, sizeof buf, "%s/addr", p);
+ if((fd = open(buf, OREAD)) == -1)
+ return -1;
+ if(read(fd, buf, 12) < 12)
+ return -1;
+ close(fd);
+ return parseether(ea, buf);
+}
+
+static void
+bcastpkt(Aoehdr *h, uint shelf, uint slot, int i)
+{
+ myea(h->dst, ethertab[i]);
+ memset(h->src, 0xff, Eaddrlen);
+ hnputs(h->type, Aoetype);
+ hnputs(h->major, shelf);
+ h->minor = slot;
+ h->cmd = ACconfig;
+ h->tag[0] = h->tag[1] = h->tag[2] = h->tag[3] = 0;
+}
+
+int
+bladereply(Vblade *v, int i, int fd, char *pkt)
+{
+ int n;
+ Aoehdr *h;
+
+ h = (Aoehdr*)pkt;
+ switch(h->cmd){
+ case ACata:
+ n = serveata(h, v, mtutab[i]);
+ break;
+ case ACconfig:
+ n = serveconfig(h, v, mtutab[i]);
+ break;
+ default:
+ n = -1;
+ break;
+ }
+ if(n == -1)
+ return -1;
+ replyhdr(h, v);
+ if(n < 60){
+ memset(pkt+n, 0, 60-n);
+ n = 60;
+ }
+ if(write(fd, h, n) != n){
+ fprint(2, "write to %s failed: %r\n", ethertab[i]);
+ return -1;
+ }
+ return 0;
+}
+
+void
+serve(void *v)
+{
+ int i, j, popcnt, vec, n, s, efd;
+ char *pkt, *bcpkt;
+ Aoehdr *h;
+
+fmtinstall('E', eipfmt);
+ i = (int)(uintptr)v;
+
+ efd = efdtab[i*Flast+Fdata];
+ pkt = pkttab[i];
+ bcpkt = bctab[i];
+
+ n = 60;
+ h = (Aoehdr*)pkt;
+ bcastpkt(h, 0xffff, 0xff, i);
+ goto start;
+
+ for(;;){
+ n = read(efd, pkt, Maxpkt);
+ start:
+ if(n < 60 || h->verflag & AFrsp)
+ continue;
+ s = nhgets(h->major);
+ popcnt = 0;
+ vec = 0;
+ for(j = 0; j < nblade; j++){
+ if((vblade[j].shelf == s || s == 0xffff)
+ && (vblade[j].slot == h->minor || h->minor == 0xff)){
+ popcnt++;
+ vec |= 1<<j;
+ }
+ }
+ for(j = 0; popcnt>0 && j < nblade; j++){
+ if((vec & 1<<j) == 0)
+ continue;
+ if(popcnt>0){
+ memcpy(bcpkt, pkt, n);
+ bladereply(vblade + j, i, efd, bcpkt);
+ }else
+ bladereply(vblade + j, i, efd, pkt);
+ popcnt--;
+ }
+ }
+}
+
+void
+launch(char *tab[], int fdtab[])
+{
+ int i;
+
+ for(i = 0; tab[i]; i++){
+ if(aoeopen(tab[i], fdtab+Flast*i) < 0)
+ sysfatal("network open: %r");
+ /*
+ * use proc not threads. otherwise we will block on read/write.
+ */
+ proccreate(serve, (void*)i, 32*1024);
+ }
+}
+
+void
+usage(void)
+{
+ fprint(2, "vblade [-ir] [-s size] [-a shelf.slot] [-c config] [-e ether] file\n");
+ exits("usage");
+}
+
+void
+goblade(Vblade *vblade, char *file, Conf *c)
+{
+ char *anal;
+
+ if(c->iflag == 1)
+ memcpy(vblade->hdr.magic, Magic, sizeof Magic);
+ checkfile(file, vblade, c->iflag);
+
+ vblade->flag = c->flag;
+ if(c->shelf != -1){
+ vblade->shelf = c->shelf;
+ vblade->slot = c->slot;
+ }
+ if(c->maxlba > 0)
+ vblade->maxlba = c->maxlba;
+ if(c->config != nil)
+ memmove(vblade->hdr.config, c->config, vblade->clen = strlen(c->config));
+
+ recheck(vblade->fd, vblade);
+
+ anal = "";
+ if(vblade->maxlba > 1)
+ anal = "s";
+ fprint(2, "lblade %d.%d %lld sector%s\n", vblade->shelf, vblade->slot, vblade->maxlba, anal);
+}
+
+void
+threadmain(int argc, char **argv)
+{
+ int i, lastc, anye;
+ Conf c;
+
+ anye = 0;
+ for(;;){
+ if(nblade == nelem(vblade))
+ sysfatal("too many blades");
+ c = (Conf){0, 0, -1, -1, 0, nil};
+ lastc = 0;
+ ARGBEGIN{
+ case 'a':
+ lastc = 'a';
+ if(parseshelf(EARGF(usage()), &c.shelf, &c.slot) == -1)
+ sysfatal("bad vblade address");
+ break;
+ case 'c':
+ lastc = 'c';
+ c.config = EARGF(usage());
+ break;
+ case 'e':
+ lastc = 'e';
+ if(anye++ == 0)
+ etheridx = 0;
+ if(etheridx == nelem(ethertab))
+ sysfatal("too many interfaces");
+ ethertab[etheridx++] = EARGF(usage());
+ break;
+ case 'i':
+ lastc = 'i';
+ c.iflag = 1;
+ break;
+ case 'r':
+ lastc = 'r';
+ c.flag |= Fraw;
+ c.iflag = 1;
+ break;
+ case 's':
+ lastc = 's';
+ c.maxlba = sizetolba(getsize(EARGF(usage())));
+ break;
+ default:
+ lastc = '?';
+ usage();
+ }ARGEND;
+
+ if(argc == 0 && lastc == 'e')
+ break;
+ if(argc == 0)
+ usage();
+ goblade(vblade + nblade++, *argv, &c);
+ if(argc == 1)
+ break;
+ }
+
+ if(nblade == 0)
+ usage();
+ for(i = 0; i < etheridx; i++)
+ mtutab[i] = getmtu(ethertab[i]);
+
+ launch(ethertab, efdtab);
+
+ for(; sleep(1*1000) != -1;)
+ ;
+ threadexitsall("interrupted");
+}
diff --git a/sys/src/libflate/inflatezlibblock.c b/sys/src/libflate/inflatezlibblock.c
index 477bb4b01..54b2ca130 100644
--- a/sys/src/libflate/inflatezlibblock.c
+++ b/sys/src/libflate/inflatezlibblock.c
@@ -61,7 +61,7 @@ inflatezlibblock(uchar *dst, int dsize, uchar *src, int ssize)
if(ok != FlateOk)
return ok;
- if(adler32(1, dst, bs.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
+ if(adler32(1, dst, bd.pos - dst) != ((bs.pos[0] << 24) | (bs.pos[1] << 16) | (bs.pos[2] << 8) | bs.pos[3]))
return FlateCorrupted;
return bd.pos - dst;