M port/malloc.c => port/malloc.c +61 -405
@@ 1,430 1,86 @@
-/* compile-time features
- IALLOC use all blocks given to ifree, otherwise ignore unordered blocks
- MSTATS enable statistics
- debug enable assertion checking
- longdebug full arena checks at every transaction
-*/
-#include "u.h"
-#include "lib.h"
-#include "mem.h"
-#include "dat.h"
-#include "fns.h"
+#include <u.h>
+#include <libc.h>
-#define INT int
-#define ALIGN int
-#define NALIGN 1
-#define WORD sizeof(union store)
-#define BLOCK 4096
-#define BUSY 1
-#define NULL 0
-#define testbusy(p) ((INT)(p)&BUSY)
-#define setbusy(p) (union store *)((INT)(p)|BUSY)
-#define clearbusy(p) (union store *)((INT)(p)&~BUSY)
-#define IALLOC
-
-typedef
-union store
+enum
{
- union store *ptr;
- ALIGN dummy[NALIGN];
- int calloc; /*calloc clears an array of integers*/
-} Store;
-
-static int draincache(void);
-static void* stdmalloc(long);
-static int stdfree(Store*);
-static void ifree(char*, long);
+ MAGIC = 0xDEADBABE,
+ MAX2SIZE = 20
+};
-#ifdef longdebug
-#define debug 1
-#endif
-#ifdef debug
-#define ASSERT(p) if(!(p))botch("p");else
-static
-botch(char *s)
+typedef struct Bucket Bucket;
+struct Bucket
{
- char *c;
-
- c = "assertion botched: ";
- write(2, c, strlen(c));
- write(2, s, strlen(s));
- write(2, "\n", 1);
- abort();
-}
-static int allock(Store*);
-#else
-#define ASSERT(p)
-#endif
-
-/* C storage allocator
- * circular first-fit strategy
- * works with noncontiguous, but monotonically linked, arena
- * each block is preceded by a ptr to the (pointer of)
- * the next following block
- * blocks are exact number of words long
- * aligned to the data type requirements of ALIGN
- * pointers to blocks must have BUSY bit 0
- * bit in ptr is 1 for busy, 0 for idle
- * gaps in arena are merely noted as busy blocks
- * last block of arena is empty and
- * has a pointer to first
- * idle blocks are coalesced during space search
- *
- * a different implementation may need to redefine
- * ALIGN, NALIGN, BLOCK, BUSY, INT
- * where INT is integer type to which a pointer can be cast
- */
-
-
-/* alloca should have type union store.
- * The funny business gets it initialized without complaint
- */
-#define addr(a) (Store*)&a
-static char *alloca;
-static char *alloca = (char*)&alloca + BUSY; /* initial arena */
-static Store *allocs = addr(alloca); /*arena base*/
-static Store *allocc = addr(alloca); /*all prev blocks known busy*/
-static Store *allocp = addr(alloca); /*search ptr*/
-static Store *alloct = addr(alloca); /*top cell*/
-static Store *allocx; /*for benefit of realloc*/
-
-/* a cache list of frequently-used sizes is maintained. From each
- * cache entry hangs a chain of available blocks
- * malloc(0) shuts off caching (to keep freed data clean)
- */
-
-#define CACHEMAX 256 /* largest block to be cached (in words) */
-#define CACHESIZ 53 /* number of entries (prime) */
-
-static Store *cache[CACHESIZ];
-static int cachemax = CACHEMAX;
-
-#ifdef MSTATS
-#define Mstats(e) e
-static long nmalloc, nrealloc, nfree; /* call statistics */
-static long walloc, wfree; /* space statistics */
-static long chit, ccoll, cdrain, cavail; /* cache statistics */
-#else
-#define Mstats(e)
-#endif
+ int size;
+ int magic;
+ Bucket *next;
+ char data[1];
+};
+
+typedef struct Arena Arena;
+struct Arena
+{
+ Lock;
+ Bucket *btab[MAX2SIZE];
+};
-static QLock mlock;
+static Arena arena;
+#define datoff ((int)&((Bucket*)0)->data)
void*
-malloc(ulong nbytes)
+malloc(uint size)
{
- Store *p;
- long nw;
- Store **cp;
- void *mem;
+ int pow;
+ Bucket *bp;
- nw = (nbytes+WORD+WORD-1)/WORD;
- qlock(&mlock);
- Mstats((nmalloc++, walloc += nw));
- if(nw<cachemax) {
- if(nw >= 2) {
- cp = &cache[nw%CACHESIZ];
- p = *cp;
- if(p && nw == clearbusy(p->ptr)-p) {
- ASSERT(testbusy(p->ptr));
- *cp = (++p)->ptr;
- Mstats((chit++, cavail--));
- qunlock(&mlock);
- return (char*)p;
- }
- } else {
- draincache();
- cachemax = 0;
- }
+ for(pow = 1; pow < MAX2SIZE; pow++) {
+ if(size <= (1<<pow))
+ goto good;
}
- p = stdmalloc(nw);
- qunlock(&mlock);
- return p;
-}
-
-static void*
-stdmalloc(long nw)
-{
- Store *p, *q;
- int temp;
- Page *page;
- ASSERT(allock(allocp));
- for(;;) { /* done at most thrice */
- p = allocp;
- for(temp=0; ; ) {
- if(!testbusy(p->ptr)) {
- allocp = p;
- while(!testbusy((q=p->ptr)->ptr)) {
- ASSERT(q>p);
- p->ptr = q->ptr;
- }
- if(q>=p+nw && p+nw>=p)
- goto found;
- }
- q = p;
- p = clearbusy(p->ptr);
- if(p <= q) {
- ASSERT(p == allocs && q == alloct);
- if(++temp>1)
- break;
- ASSERT(allock(allocc));
- p = allocc;
- }
- }
+ return nil;
+good:
+ /* Allocate off this list */
+ lock(&arena);
+ bp = arena.btab[pow];
+ if(bp) {
+ arena.btab[pow] = bp->next;
+ arena.unlock();
- /* No memory in the free list. Call newpage and kmap to get
- * some more, and ifree to put it in the list.
- */
- page = newpage(1, 0, 0);
- page->va = VA(kmap(page));
- draincache();
- ifree((char *) page->va, 1 << PGSHIFT);
- }
-found:
- allocp += nw;
- if(q>allocp) {
- allocx = allocp->ptr;
- allocp->ptr = p->ptr;
- }
- p->ptr = setbusy(allocp);
- if(p<=allocc) {
- ASSERT(p==allocc);
- while(testbusy(allocc->ptr)
- && (q=clearbusy(allocc->ptr))>allocc)
- allocc = q;
- }
- return(p+1);
-}
+ if(bp->magic != 0)
+ abort();
-void
-free(void *ap)
-{
- Store *p = ap, *q;
- long nw;
- Store **cp;
+ bp->magic = MAGIC;
- if(p==NULL)
- return;
- --p;
- qlock(&mlock);
- ASSERT(allock(p));
- ASSERT(testbusy(p->ptr));
- ASSERT(!cached(p));
- nw = clearbusy(p->ptr) - p;
- Mstats((nfree++, wfree += nw));
- ASSERT(nw>0);
- if(nw<cachemax && nw>=2) {
- cp = &cache[nw%CACHESIZ];
- q = *cp;
- if(!q || nw==clearbusy(q->ptr)-q) {
- p[1].ptr = q;
- *cp = p;
- Mstats(cavail++);
- qunlock(&mlock);
- return;
- } else Mstats(q && ccoll++);
+ memset(bp->data, 0, size);
+ return bp->data;
}
- stdfree(p+1);
- qunlock(&mlock);
-}
-
-/* freeing strategy tuned for LIFO allocation
-*/
-static
-stdfree(Store *p)
-{
- allocp = --p;
- if(p < allocc)
- allocc = p;
- ASSERT(allock(allocp));
- p->ptr = clearbusy(p->ptr);
- ASSERT(p->ptr > allocp);
-}
+ unlock(&arena);
+ size = sizeof(Bucket)+(1<<pow);
+ bp = sbrk(size);
+ if((int)bp < 0)
+ return nil;
-static
-draincache(void)
-{
- Store **cp = cache+CACHESIZ;
- Store *q;
- int anyfreed = 0;
+ bp->size = pow;
+ bp->magic = MAGIC;
- while(--cp>=cache) {
- while(q = *cp) {
- ASSERT(testbusy(q->ptr));
- ASSERT((clearbusy(q->ptr)-q)%CACHESIZ==cp-cache);
- ASSERT(q>=allocs&&q<=alloct);
- stdfree(++q);
- anyfreed++;
- *cp = q->ptr;
- }
- }
- Mstats((cdrain+=anyfreed, cavail=0));
- return anyfreed;
+ return bp->data;
}
-/* ifree(q, nbytes) inserts a block that did not come
- * from malloc into the arena
- *
- * q points to new block
- * r points to last of new block
- * p points to last cell of arena before new block
- * s points to first cell of arena after new block
-*/
-
-static
void
-ifree(char *qq, long nbytes)
-{
- Store *p, *q, *r, *s;
-
- q = (Store *)qq;
- r = q + (nbytes/WORD) - 1;
- q->ptr = r;
- if(q > alloct) {
- p = alloct;
- s = allocs;
- alloct = r;
- } else {
-#ifdef IALLOC
- /* useful only in small address spaces */
- for(p=allocs; ; p=s) {
- s = clearbusy(p->ptr);
- if(s==allocs)
- break;
- ASSERT(s>p);
- if(s>r) {
- if(p<q)
- break;
- else
- ASSERT(p>r);
- }
- }
- if(allocs > q)
- allocs = q;
- if(allocc > q)
- allocc = q;
- allocp = allocc;
-#else
- return;
-#endif
- }
- p->ptr = q==p+1? q: setbusy(q);
- r->ptr = s==r+1? s: setbusy(s);
- while(testbusy(allocc->ptr))
- allocc = clearbusy(allocc->ptr);
-}
-
-/* realloc(p, nbytes) reallocates a block obtained from malloc()
- * and freed since last call of malloc()
- * to have new size nbytes, and old content
- * returns new location, or 0 on failure
-*/
-
-void*
-realloc(void *pp, ulong nbytes)
-{
- Store *p = pp;
- Store *s, *t;
- Store *q;
- long nw, onw;
-
- if(p==NULL)
- return malloc(nbytes);
- qlock(&mlock);
- Mstats(nrealloc++);
- ASSERT(allock(p-1));
- if(testbusy(p[-1].ptr))
- stdfree(p);
- onw = p[-1].ptr - p;
- nw = (nbytes+WORD-1)/WORD;
- q = (Store *)stdmalloc(nw+1);
- if(q!=NULL && q!=p) {
- ASSERT(q<p||q>p[-1].ptr);
- if(nw<onw) {
- Mstats(wfree += onw-nw);
- onw = nw;
- } else Mstats(walloc += nw-onw);
- for(s=p, t=q; onw--!=0; )
- *t++ = *s++;
- ASSERT(clearbusy(q[-1].ptr)-q==nw);
- if(q<p && q+nw>=p)
- (q+(q+nw-p))->ptr = allocx;
- ASSERT(allock(q-1));
- }
- qunlock(&mlock);
- return q;
-}
-
-#ifdef debug
-static
-allock(Store *q)
-{
-#ifdef longdebug
- register Store *p, *r;
- register Store **cp;
- int x, y;
- for(cp=cache+CACHESIZ; --cp>=cache; ) {
- if((p= *cp)==0)
- continue;
- x = clearbusy(p->ptr) - p;
- ASSERT(x%CACHESIZ==cp-cache);
- for( ; p; p = p[1].ptr) {
- ASSERT(testbusy(p->ptr));
- ASSERT(clearbusy(p->ptr)-p==x);
- }
- }
- x = 0, y = 0;
- p = allocs;
- for( ; (r=clearbusy(p->ptr)) > p; p=r) {
- if(p==allocc)
- y++;
- ASSERT(y||testbusy(p->ptr));
- if(p==q)
- x++;
- }
- ASSERT(r==allocs);
- ASSERT(x==1||p==q);
- ASSERT(y||p==allocc);
- return(1);
-#else
- ASSERT((unsigned)q/WORD*WORD==(unsigned)q);
- ASSERT(q>=allocs&&q<=alloct);
-#endif
-}
-#endif
-
-mstats(void)
+free(void *ptr)
{
-#ifdef MSTATS
- fprint(2, "Malloc statistics, including overhead bytes\n");
- fprint(2, "Arena: bottom %ld, top %ld\n",
- (long)clearbusy(alloca), (long)alloct);
- fprint(2, "Calls: malloc %ld, realloc %ld, free %ld\n",
- nmalloc, nrealloc, nfree);
- fprint(2, "Bytes: allocated or extended %ld, ",
- walloc*WORD);
- fprint(2, "freed or cut %ld\n", wfree*WORD);
- fprint(2,"Cache: hits %ld, collisions %ld, discards %ld, avail %ld\n",
- chit, ccoll, cdrain, cavail);
-#endif
-}
+ Bucket *bp, **l;
-#ifdef debug
-cached(Store *p)
-{
- Store *q = cache[(clearbusy(p->ptr)-p)%CACHESIZ];
- for( ; q; q=q[1].ptr)
- ASSERT(p!=q);
- return 0;
-}
-#endif
+ /* Find the start of the structure */
+ bp = (Bucket*)((uint)ptr - datoff);
-void *calloc(ulong n, ulong size){
- void *p;
+ if(bp->magic != MAGIC)
+ panic("free");
- size = size*n;
- p = malloc(size);
- memset(p, 0, size);
- return p;
+ bp->magic = 0;
+ lock(&arena);
+ l = &arena.btab[bp->size];
+ bp->next = *l;
+ *l = bp;
+ unlock(&arena);
}
M power/devhotrod.c => power/devhotrod.c +5 -2
@@ 261,7 261,7 @@ hotrodread(Chan *c, void *buf, long n, ulong offset)
isflush = 1;
}
mp->param[2] = 0; /* reply checksum */
- mp->param[3] = 0; /* reply count */
+ mp->param[3] = 0xDEADBEEF; /* reply count */
mp->cmd = Uread;
mp->param[0] = MP2VME(buf);
mp->param[1] = n;
@@ 273,6 273,7 @@ hotrodread(Chan *c, void *buf, long n, ulong offset)
do
m = mp->param[3];
while(m==0 && --l>0);
+ print("isflush blocked\n");
}else{
if(waserror()){
if(*hmp && *hmp==mp)
@@ 284,7 285,7 @@ hotrodread(Chan *c, void *buf, long n, ulong offset)
m = mp->param[3];
}
if(m==0 || m>n){
- print("devhotrod: count %ld %ld\n", m, n);
+ print("devhotrod: count 0x%lux 0x%lux\n", m, n);
error(Egreg);
}
if(mp->param[2] != hotsum(buf, m, mp->param[2])){
@@ 424,6 425,8 @@ hotrodintr(int vec)
if(h->ri >= NRQ)
h->ri = 0;
hm->intr = 1;
+ if(hm->param[3]==0 || hm->param[3] > 10000)
+ print("hotrodintr count 0x%lux\n", hm->param[3]);
if(!hm->abort)
wakeup(&hm->r);
}
M power/devhs.c => power/devhs.c +123 -125
@@ 8,37 8,53 @@
#include "io.h"
-typedef struct Hsvme Hsvme;
-typedef struct Device Device;
+typedef struct Hs Hs;
enum {
Maxburst= 1023, /* maximum transmit burst size */
- Vmevec= 0xd0, /* vme vector for interrupts */
+ Intvec= 0xd0, /* vme vector for interrupts */
Intlevel= 5, /* level to interrupt on */
- Nhsvme= 1,
-};
+ Nhs= 1,
-#define NOW (MACHP(0)->ticks*MS2HZ)
+ /*
+ * csr flags
+ */
+ ALIVE = 0x0001,
+ IENABLE = 0x0004,
+ EXOFLOW = 0x0008,
+ IRQ = 0x0010,
+ EMUTE = 0x0020,
+ EPARITY = 0x0040,
+ EFRAME = 0x0080,
+ EROFLOW = 0x0100,
+ REF = 0x0800,
+ XFF = 0x4000,
+ XHF = 0x8000,
-/*
- * hsvme datakit board
- */
-struct Device {
- ushort version;
- ushort pad0x02;
- ushort vector;
- ushort pad0x06;
- ushort csr;
- ushort pad0x0A;
- ushort data;
+ /*
+ * csr reset flags
+ */
+ FORCEW = 0x0008,
+ NORESET = 0xFF00,
+ RESET = 0x0000,
+
+ /*
+ * data flags
+ */
+ CTL = 0x0100,
+ CHNO = 0x0200,
+ TXEOD = 0x0400,
+ NND = 0x8000,
};
-#define HSVME VMEA24SUP(Device, 0xF90000)
-struct Hsvme {
+#define NOW (MACHP(0)->ticks*MS2HZ)
+#define IPL(x) ((x)<<5)
+
+struct Hs {
QLock;
QLock xmit;
- Device *addr;
+ HSdev *addr;
int vec; /* interupt vector */
Rendez r; /* output process */
Rendez kr; /* input kernel process */
@@ 59,55 75,30 @@ struct Hsvme {
ulong out; /* bytes out */
};
-Hsvme hsvme[Nhsvme];
-
-#define ALIVE 0x0001
-#define IENABLE 0x0004
-#define EXOFLOW 0x0008
-#define IRQ 0x0010
-#define EMUTE 0x0020
-#define EPARITY 0x0040
-#define EFRAME 0x0080
-#define EROFLOW 0x0100
-#define REF 0x0800
-#define XFF 0x4000
-#define XHF 0x8000
-
-#define FORCEW 0x0008
-#define IPL(x) ((x)<<5)
-#define NORESET 0xFF00
-#define RESET 0x0000
-
-#define CTL 0x0100
-#define CHNO 0x0200
-#define TXEOD 0x0400
-#define NND 0x8000
+Hs hs[Nhs];
-static void hsvmeintr(int);
-static void hsvmekproc(void*);
+static void hsintr(int);
+static void hskproc(void*);
/*
- * hsvme stream module definition
+ * hs stream module definition
*/
-static void hsvmeoput(Queue*, Block*);
-static void hsvmestopen(Queue*, Stream*);
-static void hsvmestclose(Queue*);
-Qinfo hsvmeinfo =
+static void hsoput(Queue*, Block*);
+static void hsstopen(Queue*, Stream*);
+static void hsstclose(Queue*);
+Qinfo hsinfo =
{
nullput,
- hsvmeoput,
- hsvmestopen,
- hsvmestclose,
- "hsvme"
+ hsoput,
+ hsstopen,
+ hsstclose,
+ "hs"
};
-/*
- * restart a VME board
- */
void
-hsvmerestart(Hsvme *hp)
+hsrestart(Hs *hp)
{
- Device *addr;
+ HSdev *addr;
addr = hp->addr;
@@ 117,7 108,7 @@ hsvmerestart(Hsvme *hp)
/*
* set interrupt vector
- * turn on addrice
+ * turn on device
* set forcew to a known value
* interrupt on level `Intlevel'
*/
@@ 135,23 126,24 @@ hsvmerestart(Hsvme *hp)
* reset all vme boards
*/
void
-hsvmereset(void)
+hsreset(void)
{
int i;
- Hsvme *hp;
-
- for(i=0; i<Nhsvme; i++){
- hsvme[i].addr = HSVME+i;
- hsvme[i].vec = Vmevec+i;
- hsvme[i].addr->csr = RESET;
- setvmevec(hsvme[i].vec, hsvmeintr);
+ Hs *hp;
+
+ for(i=0; i<Nhs; i++){
+ hp = &hs[i];
+ hp->addr = HSDEV+i;
+ hp->vec = Intvec+i;
+ hp->addr->csr = RESET;
+ setvmevec(hp->vec, hsintr);
}
wbflush();
delay(20);
}
void
-hsvmeinit(void)
+hsinit(void)
{
}
@@ 159,18 151,18 @@ hsvmeinit(void)
* enable the device for interrupts, spec is the device number
*/
Chan*
-hsvmeattach(char *spec)
+hsattach(char *spec)
{
- Hsvme *hp;
+ Hs *hp;
int i;
Chan *c;
i = strtoul(spec, 0, 0);
- if(i >= Nhsvme)
+ if(i >= Nhs)
error(Ebadarg);
- hp = &hsvme[i];
+ hp = &hs[i];
if(!hp->started)
- hsvmerestart(hp);
+ hsrestart(hp);
c = devattach('h', spec);
c->dev = i;
@@ 179,31 171,31 @@ hsvmeattach(char *spec)
}
Chan*
-hsvmeclone(Chan *c, Chan *nc)
+hsclone(Chan *c, Chan *nc)
{
return devclone(c, nc);
}
int
-hsvmewalk(Chan *c, char *name)
+hswalk(Chan *c, char *name)
{
return devwalk(c, name, 0, 0, streamgen);
}
void
-hsvmestat(Chan *c, char *dp)
+hsstat(Chan *c, char *dp)
{
devstat(c, dp, 0, 0, streamgen);
}
Chan*
-hsvmeopen(Chan *c, int omode)
+hsopen(Chan *c, int omode)
{
if(c->qid.path == CHDIR){
if(omode != OREAD)
error(Eperm);
}else
- streamopen(c, &hsvmeinfo);
+ streamopen(c, &hsinfo);
c->mode = openmode(omode);
c->flag |= COPEN;
c->offset = 0;
@@ 211,40 203,40 @@ hsvmeopen(Chan *c, int omode)
}
void
-hsvmecreate(Chan *c, char *name, int omode, ulong perm)
+hscreate(Chan *c, char *name, int omode, ulong perm)
{
USED(c);
error(Eperm);
}
void
-hsvmeclose(Chan *c)
+hsclose(Chan *c)
{
if(c->qid.path != CHDIR)
streamclose(c);
}
long
-hsvmeread(Chan *c, void *buf, long n, ulong offset)
+hsread(Chan *c, void *buf, long n, ulong offset)
{
return streamread(c, buf, n);
}
long
-hsvmewrite(Chan *c, void *buf, long n, ulong offset)
+hswrite(Chan *c, void *buf, long n, ulong offset)
{
return streamwrite(c, buf, n, 0);
}
void
-hsvmeremove(Chan *c)
+hsremove(Chan *c)
{
USED(c);
error(Eperm);
}
void
-hsvmewstat(Chan *c, char *dp)
+hswstat(Chan *c, char *dp)
{
USED(c);
error(Eperm);
@@ 258,40 250,45 @@ hsvmewstat(Chan *c, char *dp)
* create the kernel process for input
*/
static void
-hsvmestopen(Queue *q, Stream *s)
+hsstopen(Queue *q, Stream *s)
{
- Hsvme *hp;
+ Hs *hp;
char name[32];
- hp = &hsvme[s->dev];
- sprint(name, "hsvme%d", s->dev);
+ hp = &hs[s->dev];
+ sprint(name, "hs%d", s->dev);
q->ptr = q->other->ptr = hp;
hp->rq = q;
- kproc(name, hsvmekproc, hp);
+ kproc(name, hskproc, hp);
}
/*
- * kill off the kernel process
+ * ask kproc to die and wait till it happens
*/
static int
kdead(void *arg)
{
- Hsvme *hp;
+ Hs *hp;
- hp = (Hsvme *)arg;
+ hp = (Hs *)arg;
return hp->kstarted == 0;
}
static void
-hsvmestclose(Queue * q)
+hsstclose(Queue * q)
{
- Hsvme *hp;
+ Hs *hp;
- hp = (Hsvme *)q->ptr;
+ hp = (Hs *)q->ptr;
qlock(hp);
hp->rq = 0;
qunlock(hp);
- wakeup(&hp->kr);
- sleep(&hp->r, kdead, hp);
+ while(waserror())
+ ;
+ while(hp->kstarted){
+ wakeup(&hp->kr);
+ sleep(&hp->r, kdead, hp);
+ }
+ poperror();
}
/*
@@ 317,9 314,9 @@ freemsg(Queue *q, Block *bp)
static int
halfempty(void *arg)
{
- Device *addr;
+ HSdev *addr;
- addr = (Device*)arg;
+ addr = (HSdev*)arg;
return addr->csr & XHF;
}
@@ 331,10 328,10 @@ halfempty(void *arg)
* character.
*/
void
-hsvmeoput(Queue *q, Block *bp)
+hsoput(Queue *q, Block *bp)
{
- Device *addr;
- Hsvme *hp;
+ HSdev *addr;
+ Hs *hp;
int burst;
int chan;
int ctl;
@@ 354,12 351,12 @@ hsvmeoput(Queue *q, Block *bp)
/*
* one transmitter at a time
*/
- hp = (Hsvme *)q->ptr;
+ hp = (Hs *)q->ptr;
+ qlock(&hp->xmit);
if(waserror()){
qunlock(&hp->xmit);
nexterror();
}
- qlock(&hp->xmit);
addr = hp->addr;
/*
@@ 369,6 366,7 @@ hsvmeoput(Queue *q, Block *bp)
if(bp->wptr - bp->rptr < 3){
freemsg(q, bp);
qunlock(&hp->xmit);
+ poperror();
return;
}
chan = CHNO | bp->rptr[0] | (bp->rptr[1]<<8);
@@ 435,9 433,9 @@ hsvmeoput(Queue *q, Block *bp)
static int
notempty(void *arg)
{
- Device *addr;
+ HSdev *addr;
- addr = (Device *)arg;
+ addr = (HSdev *)arg;
return addr->csr & REF;
}
@@ 445,7 443,7 @@ notempty(void *arg)
* fill a block with what is currently buffered and send it upstream
*/
static void
-upstream(Hsvme *hp, unsigned int ctl)
+upstream(Hs *hp, unsigned int ctl)
{
int n;
Block *bp;
@@ 470,14 468,14 @@ upstream(Hsvme *hp, unsigned int ctl)
* fifo fill up.
*/
static void
-hsvmekproc(void *arg)
+hskproc(void *arg)
{
- Hsvme *hp;
- Device *addr;
+ Hs *hp;
+ HSdev *addr;
unsigned int c;
int locked;
- hp = (Hsvme *)arg;
+ hp = (Hs *)arg;
addr = hp->addr;
hp->kstarted = 1;
hp->wptr = hp->buf;
@@ 509,7 507,7 @@ hsvmekproc(void *arg)
/*
* 0xFFFF means an empty fifo
*/
- while ((c = addr->data) != 0xFFFF) {
+ while((c = addr->data) != 0xFFFF){
hp->in++;
if(c & CHNO){
c &= 0x1FF;
@@ 561,31 559,31 @@ hsvmekproc(void *arg)
* and not empty bits to figure out whom to wake.
*/
static void
-hsvmeintr(int vec)
+hsintr(int vec)
{
ushort csr;
- Device *addr;
- Hsvme *hp;
+ HSdev *addr;
+ Hs *hp;
- hp = &hsvme[vec - Vmevec];
- if(hp < hsvme || hp > &hsvme[Nhsvme]){
- print("bad hsvme vec\n");
+ hp = &hs[vec - Intvec];
+ if(hp < hs || hp > &hs[Nhs]){
+ print("bad hs vec\n");
return;
}
csr = hp->addr->csr;
- if (csr & REF) {
+ if(csr & REF){
hp->rintr++;
wakeup(&hp->kr);
}
- if (csr & XHF) {
+ if(csr & XHF){
hp->tintr++;
wakeup(&hp->r);
}
- if ((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)) {
+ if((csr^XFF) & (XFF|EROFLOW|EFRAME|EPARITY|EXOFLOW)){
hp->parity++;
- hsvmerestart(hp);
- print("hsvme %d: reset, csr = 0x%ux\n",
- vec - Vmevec, csr);
+ hsrestart(hp);
+ print("hs %d: reset, csr = 0x%ux\n",
+ vec - Intvec, csr);
}
}
M power/io.h => power/io.h +16 -0
@@ 117,3 117,19 @@ struct INTVEC {
#define PROM_REINIT 3 /* re-init monitor, then cmd loop */
#define PROM_REBOOT 4 /* check bootmode, no config */
#define PROM_AUTOBOOT 5 /* autoboot the system */
+
+/*
+ * hs datakit board
+ */
+typedef struct HSdev HSdev;
+struct HSdev {
+ ushort version;
+ ushort pad0x02;
+ ushort vector;
+ ushort pad0x06;
+ ushort csr;
+ ushort pad0x0A;
+ ushort data;
+};
+#define HSDEV VMEA24SUP(HSdev, 0xF90000)
+
M power/trap.c => power/trap.c +1 -1
@@ 599,7 599,7 @@ setvmevec(int v, void (*f)(int))
v &= 0xff;
g = vmevec[v];
- if(g && g != novme)
+ if(g && g != novme && g != f)
print("second setvmevec to 0x%.2x\n", v);
vmevec[v] = f;
}