int fwormwrite(Device *d, Off b, void *c) { Iobuf *p; Device *fdev; Devsize l; if(DEBUG) print("fworm write %lld\n", (Wideoff)b); fdev = FDEV(d); l = devsize(fdev); l -= l/(BUFSIZE*8) + 1; if(b >= l) panic("fworm: wbounds %lld", (Wideoff)b); l += b/(BUFSIZE*8); p = getbuf(fdev, l, Brd|Bmod|Bres); if(!p || checktag(p, Tvirgo, l)) panic("fworm: checktag %lld", (Wideoff)l); l = b % (BUFSIZE*8); if((p->iobuf[l/8] & (1<<(l%8)))) { putbuf(p); print("fworm: write %lld\n", (Wideoff)b); return 1; } p->iobuf[l/8] |= 1<<(l%8); putbuf(p); return devwrite(fdev, b, c); }
void dputs(void *handle, char *s){ size_t buflen = (strlen(s) * 2); char *buf = (char*)malloc(buflen); for(size_t i = 0; i < buflen; ++i){ buf[i * 2] = s[i]; buf[(i * 2) + 1] = 0x07; } devwrite(handle, buflen, buf); free(buf); }
void putbuf(Iobuf *p) { if(canqlock(p)) print("buffer not locked %Z(%lld)\n", p->dev, (Wideoff)p->addr); if(p->flags & Bimm) { if(!(p->flags & Bmod)) print("imm and no mod %Z(%lld)\n", p->dev, (Wideoff)p->addr); if(!devwrite(p->dev, p->addr, p->iobuf)) p->flags &= ~(Bmod|Bimm); } iobufunmap(p); qunlock(p); }
/* * syncblock tries to put out a block per hashline * returns 0 all done, * returns 1 if it missed something */ int syncblock(void) { Iobuf *p, *s, *q; Hiob *hp; int32_t h; int flag; flag = 0; for(h=0; h<nhiob; h++) { q = 0; hp = &hiob[h]; lock(hp); s = hp->link; for(p=s;;) { if(p->flags & Bmod) { if(q) flag = 1; /* more than 1 mod/line */ q = p; } p = p->fore; if(p == s) break; } unlock(hp); if(q) { if(!canqlock(q)) { flag = 1; /* missed -- was locked */ continue; } if(!(q->flags & Bmod)) { qunlock(q); continue; } if(iobufmap(q)) { if(!devwrite(q->dev, q->addr, q->iobuf)) q->flags &= ~(Bmod|Bimm); iobufunmap(q); } else flag = 1; qunlock(q); } } return flag; }
/* copy device from src to dest */ static int dodevcopy(void) { Device *from, *to; Iobuf *p; Off a; Devsize lim, tosize; /* * convert config strings into Devices. */ from = iconfig(src); if(f.error || from == nil) { print("bad src device %s\n", src); return -1; } to = iconfig(dest); if(f.error || to == nil) { print("bad dest device %s\n", dest); return -1; } /* * initialise devices, size them, more sanity checking. */ devinit(from); lim = devsize(from); if(lim == 0) panic("no blocks to copy on %Z", from); devinit(to); tosize = devsize(to); if(tosize == 0) panic("no blocks to copy on %Z", to); /* use smaller of the device sizes */ if (tosize < lim) lim = tosize; print("copy %Z to %Z in 8 seconds\n", from, to); delay(8000); if (userabort("preparing to copy")) return -1; print("copying dev: %lld blocks from %Z to %Z\n", (Wideoff)lim, from, to); /* * Copy all blocks, a block at a time. */ for (a = 0; a < lim; a++) { if (userabort("copy")) break; p = getbuf(from, a, Brd); /* * if from is a real WORM device, we'll get errors trying to * read unwritten blocks, but the unwritten blocks need not * be contiguous. */ if (p == 0) { print("%lld not written yet; can't read\n", (Wideoff)a); continue; } if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) { print("out block %lld: write error; bailing", (Wideoff)a); break; } putbuf(p); if(a % 20000 == 0) print("block %lld %T\n", (Wideoff)a, time(nil)); } /* * wrap up: sync target */ print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to); sync("devcopy"); return 0; }
/* copy worm fs from "main"'s inner worm to "output" */ static void dowormcopy(void) { Filsys *f1, *f2; Device *fdev, *from, *to = nil; Iobuf *p; Off a; Devsize lim; /* * convert file system names into Filsyss and Devices. */ f1 = fsstr("main"); if(f1 == nil) panic("main file system missing"); fdev = f1->dev; from = wormof(fdev); /* fake worm special */ if (from->type != Devfworm && from->type != Devcw) { print("main file system is not a worm; copyworm may not do what you want!\n"); print("waiting for 20 seconds...\n"); delay(20000); } f2 = fsstr("output"); if(f2 == nil) { print("no output file system - check only\n\n"); print("reading worm from %Z (worm %Z)\n", fdev, from); } else { to = f2->dev; print("\ncopying worm from %Z (worm %Z) to %Z, starting in 8 seconds\n", fdev, from, to); delay(8000); } if (userabort("preparing to copy")) return; /* * initialise devices, size them, more sanity checking. */ devinit(from); if (0 && fdev != from) { devinit(fdev); print("debugging, sizing %Z first\n", fdev); writtensize(fdev); } lim = writtensize(from); if(lim == 0) panic("no blocks to copy on %Z", from); if (to) { print("reaming %Z in 8 seconds\n", to); delay(8000); if (userabort("preparing to ream & copy")) return; devream(to, 0); devinit(to); print("copying worm: %lld blocks from %Z to %Z\n", (Wideoff)lim, from, to); } /* can't read to's blocks in case to is a real WORM device */ /* * Copy written fs blocks, a block at a time (or just read * if no "output" fs). */ for (a = 0; a < lim; a++) { if (userabort("copy")) break; p = getbuf(from, a, Brd); /* * if from is a real WORM device, we'll get errors trying to * read unwritten blocks, but the unwritten blocks need not * be contiguous. */ if (p == 0) { print("%lld not written yet; can't read\n", (Wideoff)a); continue; } if (to != 0 && devwrite(to, p->addr, p->iobuf) != 0) { print("out block %lld: write error; bailing", (Wideoff)a); break; } putbuf(p); if(a % 20000 == 0) print("block %lld %T\n", (Wideoff)a, time(nil)); } /* * wrap up: sync target, loop */ print("copied %lld blocks from %Z to %Z\n", (Wideoff)a, from, to); sync("wormcopy"); delay(2000); print("looping; reset the machine at any time.\n"); for (; ; ) continue; /* await reset */ }
int devwrite(Device *d, Off b, void *c) { int e; /* * set readonly to non-0 to prevent all writes; * mainly for trying dangerous experiments. */ if (readonly) return 0; for (;;) switch(d->type) { case Devcw: return cwwrite(d, b, c); case Devjuke: d = d->j.m; break; case Devro: print("write to ro device %Z(%lld)\n", d, (Wideoff)b); return 1; case Devwren: return wrenwrite(d, b, c); case Devworm: case Devlworm: return wormwrite(d, b, c); case Devfworm: return fwormwrite(d, b, c); case Devmcat: return mcatwrite(d, b, c); case Devmlev: return mlevwrite(d, b, c); case Devmirr: return mirrwrite(d, b, c); case Devpart: return partwrite(d, b, c); case Devswab: swab(c, 1); e = devwrite(d->swab.d, b, c); swab(c, 0); return e; case Devnone: /* checktag() can generate blocks with type devnone */ return 0; default: panic("illegal device in devwrite: %Z %lld", d, (Wideoff)b); return 1; } }
Iobuf* getbuf(Device *d, Off addr, int flag) { Iobuf *p, *s; Hiob *hp; Off h; if(DEBUG) print("getbuf %Z(%lld) f=%x\n", d, (Wideoff)addr, flag); h = addr + (Off)(uintptr)d*1009; if(h < 0) h = ~h; h %= nhiob; hp = &hiob[h]; loop: lock(hp); /* * look for it in the active list */ s = hp->link; for(p=s;;) { if(p->addr == addr && p->dev == d) { if(p != s) { p->back->fore = p->fore; p->fore->back = p->back; p->fore = s; p->back = s->back; s->back = p; p->back->fore = p; hp->link = p; } unlock(hp); qlock(p); if(p->addr != addr || p->dev != d || iobufmap(p) == 0) { qunlock(p); goto loop; } p->flags |= flag; return p; } p = p->fore; if(p == s) break; } if(flag & Bprobe) { unlock(hp); return 0; } /* * not found * take oldest unlocked entry in this queue */ xloop: p = s->back; if(!canqlock(p)) { if(p == hp->link) { unlock(hp); print("iobuf all locked\n"); goto loop; } s = p; goto xloop; } /* * its dangerous to flush the pseudo * devices since they recursively call * getbuf/putbuf. deadlock! */ if(p->flags & Bres) { qunlock(p); if(p == hp->link) { unlock(hp); print("iobuf all reserved\n"); goto loop; } s = p; goto xloop; } if(p->flags & Bmod) { unlock(hp); if(iobufmap(p)) { if(!devwrite(p->dev, p->addr, p->iobuf)) p->flags &= ~(Bimm|Bmod); iobufunmap(p); } qunlock(p); goto loop; } hp->link = p; p->addr = addr; p->dev = d; p->flags = flag; unlock(hp); if(iobufmap(p)) if(flag & Brd) { if(!devread(p->dev, p->addr, p->iobuf)) return p; iobufunmap(p); } else return p; else print("iobuf cant map buffer\n"); p->flags = 0; p->dev = devnone; p->addr = -1; qunlock(p); return 0; }
int ethertxpkt(int ctlrno, Etherpkt *pkt, int len, int timo) { USED(timo); return devwrite(ctlrno, (uchar*)pkt, len, 0); }
/* out */ /*{{{*/ void out(unsigned int port, unsigned char byte) { switch (port) { /* COND */ /*{{{*/ case COND: devwrite(conout,byte); break; /*}}}*/ /* AUXD */ /*{{{*/ case AUXD: devwrite(pun,byte); break; /*}}}*/ /* PRTD */ /*{{{*/ case PRTD: devwrite(lst,byte); break; /*}}}*/ /* FDCD */ /*{{{*/ case FDCD: if (byte>15 || disks[byte]->fd==-1) status=FDCX_NODRIVE; else { drive=byte; status=FDCX_OK; } break; /*}}}*/ /* FDCTL */ /*{{{*/ case FDCTL: track=(track&0xff00)|byte; break; /*}}}*/ /* FDCTH */ /*{{{*/ case FDCTH: track=(track&0xff)|(((unsigned int)byte)<<8); break; /*}}}*/ /* FDCS */ /*{{{*/ case FDCS: sector=byte; break; /*}}}*/ /* FDCO */ /*{{{*/ case FDCO: /* * I/O handler for write FDC command: * transfer one sector in the wanted direction, * 0 = read, 1 = write * * The status byte of the FDC is set as follows: * 0 - ok * 1 - illegal drive * 2 - illegal track * 3 - illegal sector * 4 - seek error * 5 - read error * 6 - write error * 7 - illegal command to FDC * 9 - illegal dma address */ { register int size; if (disks[drive]->fd==-1) { status=FDCX_NODRIVE; return; } if (track>disks[drive]->tracks) fprintf(stderr,"YAZE: track %04x selected\r\n",track); if (track>disks[drive]->tracks) { status=FDCX_NOTRACK; return; } if (sector>disks[drive]->sectors) { status=FDCX_NOSECTOR; return; } size=disks[drive]->secsize; if (dma+size>(64*1024)) { status=FDCX_DMAFAIL; return; } if (lseek(disks[drive]->fd, (((off_t)track)*((off_t)disks[drive]->sectors)+(off_t)(sector-1))*(off_t)size,SEEK_SET)==(off_t)-1) { status=FDCX_SEEKFAIL; return; } switch (byte) { case FDCO_READ: status=(read(disks[drive]->fd,&ram[dma],size)==size ? FDCX_OK : FDCX_READFAIL); benice=0; break; case FDCO_WRITE: status=(write(disks[drive]->fd,&ram[dma],size)==size ? FDCX_OK : FDCX_WRITEFAIL); benice=0; break; default: status=FDCX_NOCMD; break; } break; } /*}}}*/ /* DMAL */ /*{{{*/ case DMAL: dma=(dma&0xff00)|byte; break; /*}}}*/ /* DMAH */ /*{{{*/ case DMAH: dma=(dma&0xff)|(((unsigned int)byte)<<8); break; /*}}}*/ /* CLKC */ /*{{{*/ case CLKC: clkcmd=byte; break; /*}}}*/ /* HALT */ /*{{{*/ case HALT: do_halt=1; break; /*}}}*/ } }