From mboxrd@z Thu Jan 1 00:00:00 1970 To: 9fans@cse.psu.edu From: nemo@gsyc.escet.urjc.es MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="upas-aucgxwhjpzzokbfwaidrjufnxa" Message-Id: <20010516125649.67D48199E6@mail.cse.psu.edu> Subject: [9fans] ide fs patch for the current plan9 version Date: Wed, 16 May 2001 15:02:52 +0200 Topicbox-Message-UUID: a0353e06-eac9-11e9-9e20-41e7f4b1d025 This is a multi-part message in MIME format. --upas-aucgxwhjpzzokbfwaidrjufnxa Content-Disposition: inline Content-Type: text/plain; charset="US-ASCII" Content-Transfer-Encoding: 7bit Hi, this is just edorman's patch for the fs kernel to let it work with ide disks. Unlike the original patch as posted in 9fans, this one can be `applied' to the current fs kernel source. There is almost no change actually. I don't know if the patch might break the fs code for regular scsi disks, since it is `removing' some code which seems to be working on a scsi-based fs. I couldn't try because I don't have scsi disks around. In any case, I'm using the current fs code w/ this patch applied and it seems to work ok. My configuration string (if I remember well) is ch0fh2. The block size is 16K, but you may change the define for RBUFSIZE in plan9pc/dat.h. I'll try to keep the patch up-to-date wrt the distributed fs code until the day when the new integrated fs code be done and released. To apply the patch, I suggest you create two directories ./idefs/port and ./idefs/plan9pc, then run rc idefs.rc on ./idefs and bind -bc ./idefs/port /sys/src/fs/port bind -bc ./idefs/plan9pc /sys/src/fs/plan9pc after that you can mk in /sys/src/fs/plan9pc. hope this helps --upas-aucgxwhjpzzokbfwaidrjufnxa Content-Type: message/rfc822 Content-Disposition: inline # To unbundle, run this file echo plan9pc/dat.h sed 's/.//' >plan9pc/dat.h <<'//GO.SYSIN DD plan9pc/dat.h' -#define RBUFSIZE (16*1024) /* raw buffer size */ -#define DSIZE 546000 - -#include "../port/portdat.h" - -extern Mach mach0; - -typedef struct Segdesc Segdesc; -struct Segdesc -{ - ulong d0; - ulong d1; -}; - -typedef struct Mbank { - ulong base; - ulong limit; -} Mbank; - -#define MAXBANK 8 - -typedef struct Mconf { - Lock; - Mbank bank[MAXBANK]; - int nbank; - ulong topofmem; -} Mconf; -extern Mconf mconf; - -/* - * a parsed plan9.ini line - */ -#define ISAOPTLEN 16 -#define NISAOPT 8 - -typedef struct ISAConf { - char type[NAMELEN]; - ulong port; - ulong irq; - ulong dma; - ulong mem; - ulong size; - ulong freq; - - int nopt; - char opt[NISAOPT][ISAOPTLEN]; -} ISAConf; - -typedef struct Pcidev Pcidev; - -extern char nvrfile[128]; //GO.SYSIN DD plan9pc/dat.h echo plan9pc/devata.c sed 's/.//' >plan9pc/devata.c <<'//GO.SYSIN DD plan9pc/devata.c' -#include "all.h" -#include "io.h" -#include "mem.h" - - -/* There were some chunks of code commented out in the originial - ide patches for version 2 which are not commented out in version 3 - I leave those pieces of code commented out here too. - */ - -#define DEBUG 0 -#define DPRINT if(DEBUG)print -#define IDEBUG 0 -#define IDPRINT if(IDEBUG)print - -typedef struct Drive Drive; -typedef struct Ident Ident; -typedef struct Controller Controller; - -enum -{ - /* ports */ - Pbase0= 0x1F0, /* primary */ - Pbase1= 0x170, /* secondary */ - Pbase2= 0x1E8, /* tertiary */ - Pbase3= 0x168, /* quaternary */ - Pdata= 0, /* data port (16 bits) */ - Perror= 1, /* error port (read) */ - Eabort= (1<<2), - Pfeature= 1, /* buffer mode port (write) */ - Pcount= 2, /* sector count port */ - Psector= 3, /* sector number port */ - Pcyllsb= 4, /* least significant byte cylinder # */ - Pcylmsb= 5, /* most significant byte cylinder # */ - Pdh= 6, /* drive/head port */ - DHmagic= 0xA0, - DHslave= 0x10, - Pstatus= 7, /* status port (read) */ - Sbusy= (1<<7), - Sready= (1<<6), - Sdrq= (1<<3), - Serr= (1<<0), - Pcmd= 7, /* cmd port (write) */ - - /* commands */ - Crecal= 0x10, - Cread= 0x20, - Cwrite= 0x30, - Cident= 0xEC, - Cident2= 0xFF, /* pseudo command for post Cident interrupt */ - Csetbuf= 0xEF, - - Cpktcmd= 0xA0, - Cidentd= 0xA1, - Ctur= 0x00, - Creqsense= 0x03, - Ccapacity= 0x25, - Cread2= 0x28, - Cwrite2= 0x2A, - - ATAtimo= 6000, /* ms to wait for things to complete */ - ATAPItimo= 10000, - - NCtlr= 4, - NDrive= NCtlr*2, - - Maxloop= 1000000, -}; - -/* - * ident sector from drive. this is from ANSI X3.221-1994 - */ -struct Ident -{ - ushort config; /* general configuration info */ - ushort cyls; /* # of cylinders (default) */ - ushort reserved0; - ushort heads; /* # of heads (default) */ - ushort b2t; /* unformatted bytes/track */ - ushort b2s; /* unformated bytes/sector */ - ushort s2t; /* sectors/track (default) */ - ushort reserved1[3]; -/* 10 */ - ushort serial[10]; /* serial number */ - ushort type; /* buffer type */ - ushort bsize; /* buffer size/512 */ - ushort ecc; /* ecc bytes returned by read long */ - ushort firm[4]; /* firmware revision */ - ushort model[20]; /* model number */ -/* 47 */ - ushort s2i; /* number of sectors/interrupt */ - ushort dwtf; /* double word transfer flag */ - ushort capabilities; - ushort reserved2; - ushort piomode; - ushort dmamode; - ushort cvalid; /* (cvald&1) if next 4 words are valid */ - ushort ccyls; /* current # cylinders */ - ushort cheads; /* current # heads */ - ushort cs2t; /* current sectors/track */ - ushort ccap[2]; /* current capacity in sectors */ - ushort cs2i; /* current number of sectors/interrupt */ -/* 60 */ - ushort lbasecs[2]; /* # LBA user addressable sectors */ - ushort dmasingle; - ushort dmadouble; -/* 64 */ - ushort reserved3[64]; - ushort vendor[32]; /* vendor specific */ - ushort reserved4[96]; -}; - -enum { - Maxxfer = 16*1024, /* maximum transfer size/cmd */ - Npart = 8+2, /* 8 sub partitions, disk, and partition */ -}; - -typedef struct { - ulong start; - ulong end; - char name[NAMELEN+1]; -} Partition; - -typedef struct { - int online; - int npart; /* number of real partitions */ - Partition p[Npart]; - ulong offset; - Partition *current; /* current partition */ - - ulong cap; /* total sectors */ - int bytes; /* bytes/sector */ - int sectors; /* sectors/track */ - int heads; /* heads/cyl */ - long cyl; /* cylinders/drive */ - - char lba; /* true if drive has logical block addressing */ - char multi; /* non-zero if drive does multiple block xfers */ -} Disc; - -/* - * an ata drive - */ -struct Drive -{ - Controller *cp; - uchar driveno; - uchar dh; - uchar atapi; /* ATAPI */ - uchar drqintr; /* ATAPI */ - ulong vers; /* ATAPI */ - - int partok; - - Disc; -}; - -/* - * a controller for 2 drives - */ -struct Controller -{ - QLock; - int pbase; /* base port */ - uchar ctlrno; - - /* - * current operation - */ - int cmd; /* current command */ - uchar cmdblk[12]; /* ATAPI */ - int len; /* ATAPI */ - int count; /* ATAPI */ - uchar lastcmd; /* debugging info */ - uchar *buf; /* xfer buffer */ - int tcyl; /* target cylinder */ - int thead; /* target head */ - int tsec; /* target sector */ - int tbyte; /* target byte */ - int nsecs; /* length of transfer (sectors) */ - int sofar; /* sectors transferred so far */ - int status; - int error; - Drive *dp; /* drive being accessed */ -}; - -static int atactlrmask; -static Controller *atactlr[NCtlr]; -static int atadrivemask; -static Drive *atadrive[NDrive]; -static int pbase[NCtlr] = { - Pbase0, Pbase1, Pbase2, Pbase3, -}; -static int defirq[NCtlr] = { - 14, 15, 0, 0, -}; - -static void ataintr(Ureg*, void*); -static long ataxfer(Drive*, Partition*, int, ulong, long); -static int ataident(Drive*); -static Drive* atapart(Drive*); -static int ataparams(Drive*); -static void atarecal(Drive*); -static int ataprobe(Drive*, int, int, int); -static Drive* atapipart(Drive*); -static void atapiintr(Controller*); -static long atapiio(Drive*, long); - -static void -atactlrprobe(int ctlrno, int irq) -{ - Controller *ctlr; - Drive *drive; - int driveno, port; - - if(atactlrmask & (1<pbase = port; - ctlr->ctlrno = ctlrno; - ctlr->buf = ialloc(Maxxfer, 0); - inb(ctlr->pbase+Pstatus); - setvec(irq, ataintr, ctlr); - - driveno = ctlrno*2; - atadrive[driveno] = ialloc(sizeof(Drive), 0); - drive = atadrive[driveno]; - drive->cp = ctlr; - drive->driveno = driveno; - drive->dh = DHmagic; - - driveno++; - atadrive[driveno] = ialloc(sizeof(Drive), 0); - drive = atadrive[driveno]; - drive->cp = ctlr; - drive->driveno = driveno; - drive->dh = DHmagic|DHslave; -} - -static Drive* -atadriveprobe(int driveno) -{ - Drive *drive; - int ctlrno; - ISAConf isa; - - ctlrno = driveno/2; - if(atactlr[ctlrno] == 0){ - if(atactlrmask & (1<driveno = driveno; - if(drive->online == 0){ - if(atadrivemask & (1<lba) - print("hd%d: LBA %lud sectors\n", - drive->driveno, drive->cap); - else - print("hd%d: CHS %ld/%d/%d %lud sectors\n", - drive->driveno, drive->cyl, drive->heads, - drive->sectors, drive->cap); - drive->online = 1; - } - - return atapart(drive); -} - -int -atainit(void) -{ - ISAConf isa; - int ctlrno; - - for(ctlrno = 0; ctlrno < NCtlr; ctlrno++){ - memset(&isa, 0, sizeof(ISAConf)); - if(isaconfig("ata", ctlrno, &isa) == 0 && ctlrno > 1) - continue; - if(isa.irq == 0 && (isa.irq = defirq[ctlrno]) == 0) - continue; - atactlrprobe(ctlrno, Int0vec+isa.irq); - } - DPRINT("atainit: mask 0x%ux 0x%ux\n", atactlrmask, atadrivemask); - - return 0xFF; -} - -long -ataseek(int driveno, long offset) -{ - Drive *drive; -// more permissive for ide disks - drive = atadrive[driveno]; - if (drive->online == 0) - return -1; - -// real check was -// if((drive = atadriveprobe(driveno)) == 0) -// return -1; - - drive->offset = offset; - return offset; -} - -/* - * did an interrupt happen? - */ -static void -atawait(Controller *cp, int timo) -{ - ulong start; - int x; - - x = spllo(); - start = m->ticks; - while(TK2MS(m->ticks - start) < timo){ - if(cp->cmd == 0) - break; - if(cp->cmd == Cident2 && TK2MS(m->ticks - start) >= 1000) - break; - } - if(TK2MS(m->ticks - start) >= timo){ - DPRINT("atawait timed out 0x%ux\n", inb(cp->pbase+Pstatus)); - ataintr(0, cp); - } - splx(x); -} - -int -setatapart(int driveno, char *p) -{ - Partition *pp; - Drive *dp; - - if((dp = atadriveprobe(driveno)) == 0) - return 0; - - for(pp = dp->p; pp < &dp->p[dp->npart]; pp++) - if(strcmp(pp->name, p) == 0){ - dp->current = pp; - return 1; - } - return 0; -} - -long -ataread(int driveno, void *a, long n) -{ - Drive *dp; - long rv, i; - int skip; - uchar *aa = a; - Partition *pp; - Controller *cp; - -// for ide - dp = atadrive[ driveno ]; - if( dp->online == 0 ) - return 0; - -// real code was -// if((dp = atadriveprobe(driveno)) == 0) -// return 0; - - pp = dp->current; -// can ide leave pp as nil? -// if(pp == 0) -// return -1; - cp = dp->cp; - - skip = dp->offset % dp->bytes; - for(rv = 0; rv < n; rv += i){ - i = ataxfer(dp, pp, Cread, dp->offset+rv-skip, n-rv+skip); - if(i == 0) - break; - if(i < 0) - return -1; - i -= skip; - if(i > n - rv) - i = n - rv; - memmove(aa+rv, cp->buf + skip, i); - skip = 0; - } - dp->offset += rv; - - return rv; -} - -long -atawrite(int driveno, void *a, long n) -{ - Drive *dp; - long rv, i, partial; - uchar *aa = a; - Partition *pp; - Controller *cp; - -// ide - dp = atadrive[ driveno ]; - if( dp->online == 0 ) - return 0; -// if((dp = atadriveprobe(driveno)) == 0) -// return 0; - - pp = dp->current; -// if(pp == 0) -// return -1; - cp = dp->cp; - - /* - * if not starting on a sector boundary, - * read in the first sector before writing - * it out. - */ - partial = dp->offset % dp->bytes; - if(partial){ - ataxfer(dp, pp, Cread, dp->offset-partial, dp->bytes); - if(partial+n > dp->bytes) - rv = dp->bytes - partial; - else - rv = n; - memmove(cp->buf+partial, aa, rv); - if(ataxfer(dp, pp, Cwrite, dp->offset-partial, dp->bytes) < 0) - return -1; - } else - rv = 0; - - /* - * write out the full sectors - */ - partial = (n - rv) % dp->bytes; - n -= partial; - for(; rv < n; rv += i){ - i = n - rv; - if(i > Maxxfer) - i = Maxxfer; - memmove(cp->buf, aa+rv, i); - i = ataxfer(dp, pp, Cwrite, dp->offset+rv, i); - if(i == 0) - break; - if(i < 0) - return -1; - } - - /* - * if not ending on a sector boundary, - * read in the last sector before writing - * it out. - */ - if(partial){ - if(ataxfer(dp, pp, Cread, dp->offset+rv, dp->bytes) < 0) - return -1; - memmove(cp->buf, aa+rv, partial); - if(ataxfer(dp, pp, Cwrite, dp->offset+rv, dp->bytes) < 0) - return -1; - rv += partial; - } - dp->offset += rv; - return rv; -} - -/* - * wait for the controller to be ready to accept a command - */ -static int -cmdreadywait(Drive *drive) -{ - ulong end; - uchar dh, status; - Controller *ctlr; - - ctlr = drive->cp; - end = m->ticks+MS2TK(10)+1; - dh = (inb(ctlr->pbase+Pdh) & DHslave)^(drive->dh & DHslave); - - status = 0; - while(m->ticks < end){ - status = inb(ctlr->pbase+Pstatus); - if(status & Sbusy) - continue; - if(dh){ - outb(ctlr->pbase+Pdh, drive->dh); - dh = 0; - continue; - } - if(drive->atapi || (status & Sready)) - return 0; - } - USED(status); - - DPRINT("hd%d: cmdreadywait failed 0x%ux\n", drive->driveno, status); - outb(ctlr->pbase+Pdh, DHmagic); - return -1; -} - -/* - * transfer a number of sectors. ataintr will perform all the iterative - * parts. - */ -static long -ataxfer(Drive *dp, Partition *pp, int cmd, ulong start, long len) -{ - Controller *cp; - long lsec; - int loop; - - if(dp->online == 0){ - DPRINT("hd%d: disk not on line\n", dp->driveno); - return -1; - } - - /* - * cut transfer size down to disk buffer size - */ - start = start / dp->bytes; - if(len > Maxxfer) - len = Maxxfer; - len = (len + dp->bytes - 1) / dp->bytes; - - /* - * calculate physical address - */ - cp = dp->cp; - if (pp){ // ide did not check; was assumed non-nil by 3rd ed fs. - lsec = start + pp->start; - if(lsec >= pp->end){ - DPRINT("hd%d: read past end of partition\n", dp->driveno); - return 0; - } - } else - lsec = start; - - if(dp->lba){ - cp->tsec = lsec & 0xff; - cp->tcyl = (lsec>>8) & 0xffff; - cp->thead = (lsec>>24) & 0xf; - } else { - cp->tcyl = lsec/(dp->sectors*dp->heads); - cp->tsec = (lsec % dp->sectors) + 1; - cp->thead = (lsec/dp->sectors) % dp->heads; - } - - /* - * can't xfer past end of disk - */ - if (pp) // ide did not check - if(lsec+len > pp->end) - len = pp->end - lsec; - cp->nsecs = len; - - if(dp->atapi){ - if(cmd == Cread) - cp->cmd = Cread2; - else - cp->cmd = Cwrite2; - cp->dp = dp; - cp->sofar = 0; - cp->status = 0; - return atapiio(dp, lsec); - } - - if(cmdreadywait(dp) < 0) - return -1; - - /* - * start the transfer - */ - cp->cmd = cmd; - cp->dp = dp; - cp->sofar = 0; - cp->status = 0; - DPRINT("hd%d: xfer:\ttcyl %d, tsec %d, thead %d\n", - dp->driveno, cp->tcyl, cp->tsec, cp->thead); - DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar); - outb(cp->pbase+Pcount, cp->nsecs); - outb(cp->pbase+Psector, cp->tsec); - outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | cp->thead); - outb(cp->pbase+Pcyllsb, cp->tcyl); - outb(cp->pbase+Pcylmsb, cp->tcyl>>8); - outb(cp->pbase+Pcmd, cmd); - - if(cmd == Cwrite){ - loop = 0; - while((inb(cp->pbase+Pstatus) & Sdrq) == 0) - if(++loop > 10000) - panic("ataxfer"); - outss(cp->pbase+Pdata, cp->buf, dp->bytes/2); - } - - atawait(cp, ATAtimo); - - if(cp->status & Serr){ - DPRINT("hd%d: err: status 0x%ux, err 0x%ux\n", - dp->driveno, cp->status, cp->error); - DPRINT("\ttcyl %d, tsec %d, thead %d\n", - cp->tcyl, cp->tsec, cp->thead); - DPRINT("\tnsecs %d, sofar %d\n", cp->nsecs, cp->sofar); - return -1; - } - - return cp->nsecs*dp->bytes; -} - -static int -isatapi(Drive *drive) -{ - Controller *cp; - - cp = drive->cp; - outb(cp->pbase+Pdh, drive->dh); - IDPRINT("hd%d: isatapi %d\n", drive->driveno, drive->atapi); - outb(cp->pbase+Pcmd, 0x08); - drive->atapi = 1; - if(cmdreadywait(drive)){ - drive->atapi = 0; - return 0; - } - drive->atapi = 0; - drive->bytes = 512; - microdelay(1); - if(inb(cp->pbase+Pstatus)){ - IDPRINT("hd%d: isatapi status 0x%ux\n", - drive->driveno, inb(cp->pbase+Pstatus)); - return 0; - } - if(inb(cp->pbase+Pcylmsb) != 0xEB || inb(cp->pbase+Pcyllsb) != 0x14){ - IDPRINT("hd%d: isatapi cyl 0x%ux 0x%ux\n", - drive->driveno, inb(cp->pbase+Pcylmsb), inb(cp->pbase+Pcyllsb)); - return 0; - } - drive->atapi = 1; - - return 1; -} - -/* - * get parameters from the drive - */ -static int -ataident(Drive *dp) -{ - Controller *cp; - Ident *ip; - ulong lbasecs; - char id[21]; - - dp->bytes = 512; - cp = dp->cp; - -retryatapi: - cp->nsecs = 1; - cp->sofar = 0; - cp->dp = dp; - outb(cp->pbase+Pdh, dp->dh); - microdelay(1); - if(inb(cp->pbase+Pcylmsb) == 0xEB && inb(cp->pbase+Pcyllsb) == 0x14){ - dp->atapi = 1; - cp->cmd = Cidentd; - } - else - cp->cmd = Cident; - outb(cp->pbase+Pcmd, cp->cmd); - - IDPRINT("hd%d: ident command 0x%ux sent\n", dp->driveno, cp->cmd); - atawait(cp, ATAPItimo); - - if(cp->status & Serr){ - IDPRINT("hd%d: bad disk ident status\n", dp->driveno); - if(cp->error & Eabort){ - if(isatapi(dp) && cp->cmd != Cidentd) - goto retryatapi; - } - return -1; - } - - atawait(cp, ATAtimo); - - ip = (Ident*)cp->buf; - memmove(id, ip->model, sizeof(id)-1); - id[sizeof(id)-1] = 0; - - IDPRINT("hd%d: config 0x%ux capabilities 0x%ux\n", - dp->driveno, ip->config, ip->capabilities); - if(dp->atapi){ - if((ip->config & 0x0060) == 0x0020) - dp->drqintr = 1; - if((ip->config & 0x1F00) == 0x0000) - dp->atapi = 2; - } - - lbasecs = (ip->lbasecs[0]) | (ip->lbasecs[1]<<16); - if((ip->capabilities & (1<<9)) && (lbasecs & 0xf0000000) == 0){ - dp->lba = 1; - dp->cap = lbasecs; - } else { - dp->lba = 0; - - if(ip->cvalid&(1<<0)){ - /* use current settings */ - dp->cyl = ip->ccyls; - dp->heads = ip->cheads; - dp->sectors = ip->cs2t; - } - else{ - /* use default (unformatted) settings */ - dp->cyl = ip->cyls; - dp->heads = ip->heads; - dp->sectors = ip->s2t; - } - - /* - * Very strange, but some old non-LBA discs report - * sectors > 32. - if(dp->heads >= 64 || dp->sectors >= 32) - return -1; - */ - dp->cap = dp->cyl * dp->heads * dp->sectors; - } - IDPRINT("hd%d: %s lba/atapi/drqintr: %d/%d/%d C/H/S: %ld/%d/%d CAP: %ld\n", - dp->driveno, id, - dp->lba, dp->atapi, dp->drqintr, - dp->cyl, dp->heads, dp->sectors, - dp->cap); - - return 0; -} - -/* - * probe the given sector to see if it exists - */ -static int -ataprobe(Drive *dp, int cyl, int sec, int head) -{ - Controller *cp; - - cp = dp->cp; - if(cmdreadywait(dp) < 0) - return -1; - - /* - * start the transfer - */ - cp->cmd = Cread; - cp->dp = dp; - cp->sofar = 0; - cp->nsecs = 1; - cp->status = 0; - outb(cp->pbase+Pcount, 1); - outb(cp->pbase+Psector, sec+1); - outb(cp->pbase+Pdh, dp->dh | (dp->lba<<6) | head); - outb(cp->pbase+Pcyllsb, cyl); - outb(cp->pbase+Pcylmsb, cyl>>8); - outb(cp->pbase+Pcmd, Cread); - - atawait(cp, ATAtimo); - - if(cp->status & Serr) - return -1; - - return 0; -} - -/* - * figure out the drive parameters - */ -static int -ataparams(Drive *dp) -{ - int i, hi, lo; - - /* - * first try the easy way, ask the drive and make sure it - * isn't lying. - */ - dp->bytes = 512; - if(ataident(dp) < 0) - return -1; - if(dp->atapi) - return 0; - if(dp->lba){ - i = dp->cap - 1; - if(ataprobe(dp, (i>>8)&0xffff, (i&0xff)-1, (i>>24)&0xf) == 0) - return 0; - } else { - if(ataprobe(dp, dp->cyl-1, dp->sectors-1, dp->heads-1) == 0) - return 0; - } - - IDPRINT("hd%d: ataparam: cyl %ld sectors %d heads %d\n", - dp->driveno, dp->cyl, dp->sectors, dp->heads); - /* - * the drive lied, determine parameters by seeing which ones - * work to read sectors. - */ - dp->lba = 0; - for(i = 0; i < 16; i++) - if(ataprobe(dp, 0, 0, i) < 0) - break; - dp->heads = i; - for(i = 0; i < 64; i++) - if(ataprobe(dp, 0, i, 0) < 0) - break; - dp->sectors = i; - for(i = 512; ; i += 512) - if(ataprobe(dp, i, dp->sectors-1, dp->heads-1) < 0) - break; - lo = i - 512; - hi = i; - for(; hi-lo > 1;){ - i = lo + (hi - lo)/2; - if(ataprobe(dp, i, dp->sectors-1, dp->heads-1) < 0) - hi = i; - else - lo = i; - } - dp->cyl = lo + 1; - dp->cap = dp->cyl * dp->heads * dp->sectors; - - if(dp->cyl == 0 || dp->heads == 0 || dp->sectors == 0) - return -1; - - return 0; -} - -static Drive* -atapart(Drive *dp) -{ - Partition *pp; - - if(dp->partok) - return dp; - - /* - * we always have a partition for the whole disk - */ - pp = &dp->p[0]; - strcpy(pp->name, "disk"); - dp->npart = 1; - pp->start = 0; - if(dp->atapi) - return atapipart(dp); - pp->end = dp->cap; - dp->partok = 1; - - return dp; -} - -/* - * we get an interrupt for every sector transferred - */ -static void -ataintr(Ureg*, void *arg) -{ - Controller *cp; - Drive *dp; - long loop; - - cp = arg; - if((dp = cp->dp) == 0) - return; - - loop = 0; - while((cp->status = inb(cp->pbase+Pstatus)) & Sbusy) - if(++loop > Maxloop){ - print("hd%d: intr busy: status 0x%ux\n", dp->driveno, cp->status); - break; - } - switch(cp->cmd){ - case Cwrite: - if(cp->status & Serr){ - cp->error = inb(cp->pbase+Perror); - cp->cmd = 0; - return; - } - cp->sofar++; - if(cp->sofar < cp->nsecs){ - loop = 0; - while((inb(cp->pbase+Pstatus) & Sdrq) == 0) - if(++loop > 10000){ - print("ataintr 1"); - cp->cmd = 0; - return; - } - outss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes], - dp->bytes/2); - } else{ - cp->cmd = 0; - } - break; - case Cread: - case Cident: - case Cidentd: - if(cp->status & Serr){ - cp->cmd = 0; - cp->error = inb(cp->pbase+Perror); - return; - } - loop = 0; - while((inb(cp->pbase+Pstatus) & Sdrq) == 0) - if(++loop > Maxloop){ - print("hd%d: intr drq: cmd %ux status 0x%ux", - dp->driveno, cp->cmd, inb(cp->pbase+Pstatus)); - cp->cmd = 0; - return; - } - inss(cp->pbase+Pdata, &cp->buf[cp->sofar*dp->bytes], - dp->bytes/2); - cp->sofar++; - if(cp->sofar >= cp->nsecs){ - if(cp->cmd == Cident && (cp->status & Sready) == 0) - cp->cmd = Cident2; /* sometimes we get a second intr */ - else - cp->cmd = 0; - inb(cp->pbase+Pstatus); - } - break; - case Csetbuf: - case Cident2: - cp->cmd = 0; - break; - case Cpktcmd: - atapiintr(cp); - break; - default: - cp->cmd = 0; - break; - } -} - -static int -atapiexec(Drive *dp) -{ - Controller *cp; - int loop, s; - - cp = dp->cp; - - if(cmdreadywait(dp)) - return -1; - - s = splhi(); - cp->sofar = 0; - cp->error = 0; - cp->cmd = Cpktcmd; - outb(cp->pbase+Pcount, 0); - outb(cp->pbase+Psector, 0); - outb(cp->pbase+Pfeature, 0); - outb(cp->pbase+Pcyllsb, cp->len); - outb(cp->pbase+Pcylmsb, cp->len>>8); - outb(cp->pbase+Pdh, dp->dh); - outb(cp->pbase+Pcmd, cp->cmd); - - if(dp->drqintr == 0){ - microdelay(1); - for(loop = 0; (inb(cp->pbase+Pstatus) & (Serr|Sdrq)) == 0; loop++){ - if(loop < 10000) - continue; - panic("hd%d: cmddrqwait: cmd=0x%ux status=0x%ux\n", - dp->driveno, cp->cmd, inb(cp->pbase+Pstatus)); - } - outss(cp->pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); - } - splx(s); - - atawait(cp, ATAPItimo); - - if(cp->status & Serr){ - DPRINT("hd%d: Bad packet command 0x%ux, error 0x%ux\n", - dp->driveno, cp->cmdblk[0], cp->error); - return -1; - } - - return 0; -} - -static long -atapiio(Drive *dp, long lba) -{ - int n; - Controller *cp; - - cp = dp->cp; - - n = cp->nsecs*dp->bytes; - cp->len = n; - cp->count = 0; - memset(cp->cmdblk, 0, 12); - cp->cmdblk[0] = cp->cmd; - cp->cmdblk[2] = lba >> 24; - cp->cmdblk[3] = lba >> 16; - cp->cmdblk[4] = lba >> 8; - cp->cmdblk[5] = lba; - cp->cmdblk[7] = cp->nsecs>>8; - cp->cmdblk[8] = cp->nsecs; - if(atapiexec(dp)) - return -1; - if(cp->count != n) - print("hd%d: short read %d != %d\n", dp->driveno, cp->count, n); - - return n; -} - -static Drive* -atapipart(Drive *dp) -{ - Controller *cp; - Partition *pp; - int retrycount; - - cp = dp->cp; - - pp = &dp->p[0]; - pp->end = 0; - - retrycount = 0; -retry: - if(retrycount++){ - IDPRINT("hd%d: atapipart: cmd 0x%ux error 0x%ux, retry %d\n", - dp->driveno, cp->cmdblk[0], cp->error, retrycount); - if((cp->status & Serr) && (cp->error & 0xF0) == 0x60){ - dp->vers++; - if(retrycount < 3) - goto again; - } - cp->dp = 0; - IDPRINT("hd%d: atapipart: cmd %ux return error %ux, retry %d\n", - dp->driveno, cp->cmd, cp->error, retrycount); - return 0; - } -again: - cp->dp = dp; - - cp->len = 18; - cp->count = 0; - memset(cp->cmdblk, 0, sizeof(cp->cmdblk)); - cp->cmdblk[0] = Creqsense; - cp->cmdblk[4] = 18; - DPRINT("reqsense %d\n", retrycount); - atapiexec(dp); - //if(atapiexec(dp)) - // goto retry; - if(cp->count != 18){ - print("cmd=0x%2.2ux, lastcmd=0x%2.2ux ", cp->cmd, cp->lastcmd); - print("cdsize count %d, status 0x%2.2ux, error 0x%2.2ux\n", - cp->count, cp->status, cp->error); - return 0; - } - - cp->len = 8; - cp->count = 0; - memset(cp->cmdblk, 0, sizeof(cp->cmdblk)); - cp->cmdblk[0] = Ccapacity; - DPRINT("capacity %d\n", retrycount); - if(atapiexec(dp)) - goto retry; - if(cp->count != 8){ - print("cmd=0x%2.2ux, lastcmd=0x%2.2ux ", cp->cmd, cp->lastcmd); - print("cdsize count %d, status 0x%2.2ux, error 0x%2.2ux\n", - cp->count, cp->status, cp->error); - return 0; - } - dp->sectors = (cp->buf[0]<<24)|(cp->buf[1]<<16)|(cp->buf[2]<<8)|cp->buf[3]; - dp->bytes = (cp->buf[4]<<24)|(cp->buf[5]<<16)|(cp->buf[6]<<8)|cp->buf[7]; - if(dp->bytes > 2048 && dp->bytes <= 2352) - dp->bytes = 2048; - dp->cap = dp->sectors; - IDPRINT("hd%d: atapipart secs %ud, bytes %ud, cap %lud\n", - dp->driveno, dp->sectors, dp->bytes, dp->cap); - cp->dp = 0; - - pp->end = dp->sectors; - dp->partok = 1; - - return dp; -} - -static void -atapiintr(Controller *cp) -{ - uchar cause; - int count, loop, pbase; - - pbase = cp->pbase; - cause = inb(pbase+Pcount) & 0x03; - DPRINT("hd%d: atapiintr 0x%ux\n", cp->dp->driveno, cause); - switch(cause){ - - case 1: /* command */ - if(cp->status & Serr){ - cp->lastcmd = cp->cmd; - cp->cmd = 0; - cp->error = inb(pbase+Perror); - break; - } - outss(pbase+Pdata, cp->cmdblk, sizeof(cp->cmdblk)/2); - break; - - case 0: /* data out */ - case 2: /* data in */ - if(cp->buf == 0){ - cp->lastcmd = cp->cmd; - cp->cmd = 0; - if(cp->status & Serr) - cp->error = inb(pbase+Perror); - cp->cmd = 0; - break; - } - loop = 0; - while((cp->status & (Serr|Sdrq)) == 0){ - if(++loop > Maxloop){ - cp->status |= Serr; - break; - } - cp->status = inb(pbase+Pstatus); - } - if(cp->status & Serr){ - cp->lastcmd = cp->cmd; - cp->cmd = 0; - cp->error = inb(pbase+Perror); - print("hd%d: Cpktcmd status=0x%ux, error=0x%ux\n", - cp->dp->driveno, cp->status, cp->error); - break; - } - count = inb(pbase+Pcyllsb)|(inb(pbase+Pcylmsb)<<8); - if(cp->count+count > Maxxfer) - panic("hd%d: count %d, already %d\n", count, cp->count); - if(cause == 0) - outss(pbase+Pdata, cp->buf+cp->count, count/2); - else - inss(pbase+Pdata, cp->buf+cp->count, count/2); - cp->count += count; - break; - - case 3: /* status */ - cp->lastcmd = cp->cmd; - cp->cmd = 0; - if(cp->status & Serr) - cp->error = inb(cp->pbase+Perror); - break; - } -} - -ideread( Device *d, long b, void *c ) -{ - Drive *dp; - Controller *cp; - int x; - - dp = d->private; - cp = dp->cp; - - qlock( cp ); - - DPRINT("ideread(dev %x, %ld, %x, %d): %x\n" - , d, b, c, dp->driveno, dp ); - ataseek( dp->driveno, b * RBUFSIZE ); - x = ataread( dp->driveno, c, RBUFSIZE )==0; - qunlock( cp ); - - return x; -} - -idewrite( Device *d, long b, void *c) -{ - Drive *dp; - Controller *cp; - int x; - - dp = d->private; - cp = dp->cp; - - qlock( cp ); - - DPRINT("idewrite(%x, %ld, %x): driveno %d\n", d, b, c, dp->driveno ); - ataseek( dp->driveno, b * RBUFSIZE ); - x = atawrite( dp->driveno, c, RBUFSIZE )==0; - qunlock( cp ); - - return x; -} - -long atasize( Device *d ) -{ - Drive *dp; - - dp = d->private; - DPRINT("atasize(%x): %uld -> %uld\n", d, dp->cap, dp->cap / RBUFSIZE * 512); - return (dp->cap / RBUFSIZE * 512); -} - -void ideinit( Device *d ) -{ - Drive *dp; - - if( d->private ) - return; - - if( (dp = atadriveprobe( d->wren.ctrl * 2 + d->wren.targ ) ) ) { - DPRINT("ideinit( device %x ctrl %d targ %d ) driveno %d dp %x\n" - , d, d->wren.ctrl, d->wren.targ, dp->driveno, dp ); - d->private = dp; - } -} //GO.SYSIN DD plan9pc/devata.c echo plan9pc/fns.h sed 's/.//' >plan9pc/fns.h <<'//GO.SYSIN DD plan9pc/fns.h' -ulong strtoul(char*, char**, int); - -#include "../port/portfns.h" - -void aamloop(int); -void cgaputc(int); -void cgaputs(char*, int); -int cistrcmp(char*, char*); -int cistrncmp(char*, char*, int); -void (*coherence)(void); -void etherinit(void); -void etherstart(void); -int floppyinit(void); -void floppyproc(void); -long floppyread(int, void*, long); -long floppyseek(int, long); -long floppywrite(int, void*, long); -char* getconf(char*); -ulong getcr0(void); -ulong getcr2(void); -ulong getcr4(void); -int getfields(char*, char**, int, char); -ulong getstatus(void); -int atainit(void); -long ataread(int, void*, long); -long ataseek(int, long); -long atawrite(int, void*, long); -void i8042a20(void); -void i8042reset(void); -int inb(int); -void insb(int, void*, int); -ushort ins(int); -void inss(int, void*, int); -ulong inl(int); -void insl(int, void*, int); -int isaconfig(char*, int, ISAConf*); -void kbdinit(void); -int kbdintr0(void); -int kbdgetc(void); -long* mapaddr(ulong); -void microdelay(int); -void mmuinit(void); -uchar nvramread(int); -void outb(int, int); -void outsb(int, void*, int); -void outs(int, ushort); -void outss(int, void*, int); -void outl(int, ulong); -void outsl(int, void*, int); -int pcicfgr8(Pcidev*, int); -int pcicfgr16(Pcidev*, int); -int pcicfgr32(Pcidev*, int); -void pcicfgw8(Pcidev*, int, int); -void pcicfgw16(Pcidev*, int, int); -void pcicfgw32(Pcidev*, int, int); -void pcihinv(Pcidev*); -Pcidev* pcimatch(Pcidev*, int, int); -Pcidev* pcimatchtbdf(int); -void pcireset(void); -void pcisetbme(Pcidev*); -void printcpufreq(void); -void putgdt(Segdesc*, int); -void putidt(Segdesc*, int); -void putcr3(ulong); -void putcr4(ulong); -void puttr(ulong); -void rdmsr(int, vlong*); -void scsiinit(void); -long scsiread(int, void*, long); -long scsiseek(int, long); -long scsiwrite(int, void*, long); -int setatapart(int, char*); -int setscsipart(int, char*); -void setvec(int, void (*)(Ureg*, void*), void*); -int tas(Lock*); -void trapinit(void); -void uartspecial(int, void (*)(int), int (*)(void), int); -int uartgetc(void); -void uartputc(int); -void wbflush(void); -void cpuid(char*, int*, int*); -#define PADDR(a) ((ulong)(a)&~KZERO) - -void ideinit(Device *d); -int ideread(Device *d, long, void*); -int idewrite(Device *d, long, void*); -long atasize(Device *d); -void atainitstub(Device *d); //GO.SYSIN DD plan9pc/fns.h echo port/config.c sed 's/.//' >port/config.c <<'//GO.SYSIN DD port/config.c' -#include "all.h" -#include "io.h" - -struct -{ - char* icharp; - char* charp; - int error; - int newconf; /* clear befor start */ - int modconf; /* write back when done */ - int nextiter; - int lastiter; - int diriter; - int ipauthset; - Device* lastcw; - Device* devlist; -} f; - -int -devcmpr(Device *d1, Device *d2) -{ - -loop: - if(d1 == d2) - return 0; - if(d1 == 0 || d2 == 0 || d1->type != d2->type) - return 1; - - switch(d1->type) { - default: - print("cant compare dev: %D\n", d1); - panic("devcmp"); - break; - - case Devmcat: - case Devmlev: - d1 = d1->cat.first; - d2 = d2->cat.first; - while(d1 && d2) { - if(devcmpr(d1, d2)) - return 1; - d1 = d1->link; - d2 = d2->link; - } - goto loop; - - case Devnone: - return 0; - - case Devro: - d1 = d1->ro.parent; - d2 = d2->ro.parent; - goto loop; - - case Devjuke: - case Devcw: - if(devcmpr(d1->cw.c, d2->cw.c)) - break; - d1 = d1->cw.w; - d2 = d2->cw.w; - goto loop; - - case Devfworm: - d1 = d1->fw.fw; - d2 = d2->fw.fw; - goto loop; - - case Devwren: - case Devworm: - case Devlworm: - case Devide: - if(d1->wren.ctrl == d2->wren.ctrl) - if(d1->wren.targ == d2->wren.targ) - if(d1->wren.lun == d2->wren.lun) - return 0; - break; - - case Devpart: - if(d1->part.base == d2->part.base) - if(d1->part.size == d2->part.size) { - d1 = d1->part.d; - d2 = d2->part.d; - goto loop; - } - break; - } - return 1; -} - -void -cdiag(char *s, int c1) -{ - - f.charp--; - if(f.error == 0) { - print("config diag: %s -- <%c>\n", s, c1); - f.error = 1; - } -} - -int -cnumb(void) -{ - int c, n; - - c = *f.charp++; - if(c == '<') { - n = f.nextiter; - if(n >= 0) { - f.nextiter = n+f.diriter; - if(n == f.lastiter) { - f.nextiter = -1; - f.lastiter = -1; - } - for(;;) { - c = *f.charp++; - if(c == '>') - break; - } - return n; - } - n = cnumb(); - if(*f.charp++ != '-') { - cdiag("- expected", f.charp[-1]); - return 0; - } - c = cnumb(); - if(*f.charp++ != '>') { - cdiag("> expected", f.charp[-1]); - return 0; - } - f.lastiter = c; - f.diriter = 1; - if(n > c) - f.diriter = -1; - f.nextiter = n+f.diriter; - return n; - } - if(c < '0' || c > '9') { - cdiag("number expected", c); - return 0; - } - n = 0; - while(c >= '0' && c <= '9') { - n = n*10 + (c-'0'); - c = *f.charp++; - } - f.charp--; - return n; -} - -Device* -config1(int c) -{ - Device *d, *t; - int m; - - d = ialloc(sizeof(Device), 0); - for(;;) { - t = config(); - if(d->cat.first == 0) - d->cat.first = t; - else - d->cat.last->link = t; - d->cat.last = t; - if(f.error) - goto bad; - m = *f.charp; - if(c == '(' && m == ')') { - d->type = Devmcat; - break; - } - if(c == '[' && m == ']') { - d->type = Devmlev; - break; - } - } - f.charp++; - if(d->cat.first == d->cat.last) - d = d->cat.first; - return d; - -bad: - return devnone; -} - -Device* -config(void) -{ - int c, m; - Device *d; - char *icp; - - if(f.error) - goto bad; - d = ialloc(sizeof(Device), 0); - - c = *f.charp++; - switch(c) { - default: - cdiag("unknown type", c); - goto bad; - - case '(': /* (d+) one or multiple cat */ - case '[': /* [d+] one or multiple interleave */ - return config1(c); - - case 'f': /* fd fake worm */ - d->type = Devfworm; - d->fw.fw = config(); - break; - - case 'n': - d->type = Devnone; - break; - - case 'w': /* w[#.]# wren [ctrl] unit [part] */ - case 'r': /* r[#.]#[.#] worm [ctrl] unit [part] */ - case 'l': /* r[#.]#[.#] worm [ctrl] unit [part] */ - case 'h': /* h[#.]# ide [ctlr] unit [part] */ - icp = f.charp; - d->type = Devwren; - if(c == 'h') - d->type = Devide; - else - d->type = Devwren; - d->wren.ctrl = 0; - d->wren.targ = cnumb(); - d->wren.lun = 0; - m = *f.charp; - if(m == '.') { - f.charp++; - d->wren.lun = cnumb(); - m = *f.charp; - if(m == '.') { - f.charp++; - d->wren.ctrl = d->wren.targ; - d->wren.targ = d->wren.lun; - d->wren.lun = cnumb(); - } - } - if(f.nextiter >= 0) - f.charp = icp-1; - if(c == 'r') { /* worms are virtual and not uniqued */ - d->type = Devworm; - break; - } - if(c == 'l') { - d->type = Devlworm; - break; - } - break; - - case 'o': /* o ro part of last cw */ - if(f.lastcw == 0) { - cdiag("no cw to match", c); - goto bad; - } - return f.lastcw->cw.ro; - - case 'j': /* DD jukebox */ - d->type = Devjuke; - d->j.j = config(); - d->j.m = config(); - break; - - case 'c': /* cache/worm */ - d->type = Devcw; - d->cw.c = config(); - d->cw.w = config(); - d->cw.ro = ialloc(sizeof(Device), 0); - d->cw.ro->type = Devro; - d->cw.ro->ro.parent = d; - f.lastcw = d; - break; - - case 'p': /* pd#.# partition base% size% */ - d->type = Devpart; - d->part.d = config(); - d->part.base = cnumb(); - c = *f.charp++; - if(c != '.') - cdiag("dot expected", c); - d->part.size = cnumb(); - break; - - case 'x': /* xD swab a device */ - d->type = Devswab; - d->swab.d = config(); - break; - } - d->dlink = f.devlist; - f.devlist = d; - return d; - -bad: - return devnone; -} - -char* -strdup(char *s) -{ - int n; - char *s1; - - n = strlen(s); - s1 = ialloc(n+1, 0); - strcpy(s1, s); - return s1; -} - -Device* -iconfig(char *s) -{ - Device *d; - - f.nextiter = -1; - f.lastiter = -1; - f.error = 0; - f.icharp = s; - f.charp = f.icharp; - d = config(); - if(*f.charp) { - cdiag("junk on end", *f.charp); - f.error = 1; - } - return d; -} - -int -testconfig(char *s) -{ - - iconfig(s); - return f.error; -} - -int -astrcmp(char *a, char *b) -{ - int n, c; - - n = strlen(b); - if(memcmp(a, b, n)) - return 1; - c = a[n]; - if(c == 0) { - aindex = 0; - return 0; - } - if(a[n+1]) - return 1; - if(c >= '0' && c <= '9') { - aindex = c - '0'; - return 0; - } - return 1; -} - -void -mergeconf(Iobuf *p) -{ - char word[100]; - char *cp; - Filsys *fs; - - cp = p->iobuf; - goto line; - -loop: - if(*cp != '\n') - goto bad; - cp++; - -line: - cp = getwd(word, cp); - if(strcmp(word, "") == 0) - return; - if(strcmp(word, "service") == 0) { - cp = getwd(word, cp); - if(service[0] == 0) - strcpy(service, word); - goto loop; - } - if(strcmp(word, "ipauth") == 0) { - cp = getwd(word, cp); - if(!f.ipauthset) - if(chartoip(authip, word)) - goto bad; - goto loop; - } - if(astrcmp(word, "ip") == 0) { - cp = getwd(word, cp); - if(!nzip(ipaddr[aindex].sysip)) - if(chartoip(ipaddr[aindex].sysip, word)) - goto bad; - goto loop; - } - if(astrcmp(word, "ipgw") == 0) { - cp = getwd(word, cp); - if(!nzip(ipaddr[aindex].defgwip)) - if(chartoip(ipaddr[aindex].defgwip, word)) - goto bad; - goto loop; - } - if(astrcmp(word, "ipsntp") == 0) { - cp = getwd(word, cp); - if (!nzip(sntpip)) - if (chartoip(sntpip, word)) - goto bad; - goto loop; - } - if(astrcmp(word, "ipmask") == 0) { - cp = getwd(word, cp); - if(!nzip(ipaddr[aindex].defmask)) - if(chartoip(ipaddr[aindex].defmask, word)) - goto bad; - goto loop; - } - if(strcmp(word, "filsys") == 0) { - cp = getwd(word, cp); - for(fs=filsys; fs->name; fs++) - if(strcmp(fs->name, word) == 0) { - if(fs->flags & FEDIT) { - cp = getwd(word, cp); - goto loop; - } - break; - } - fs->name = strdup(word); - cp = getwd(word, cp); - fs->conf = strdup(word); - goto loop; - } - goto bad; - -bad: - putbuf(p); - panic("unknown word in config block: %s", word); -} - -void -sysinit(void) -{ - Filsys *fs; - int error, i; - Device *d; - Iobuf *p; - - dofilter(u->time+0, C0a, C0b, 1); - dofilter(u->time+1, C1a, C1b, 1); - dofilter(u->time+2, C2a, C2b, 1); - dofilter(cons.work+0, C0a, C0b, 1); - dofilter(cons.work+1, C1a, C1b, 1); - dofilter(cons.work+2, C2a, C2b, 1); - dofilter(cons.rate+0, C0a, C0b, 1000); - dofilter(cons.rate+1, C1a, C1b, 1000); - dofilter(cons.rate+2, C2a, C2b, 1000); - dofilter(cons.bhit+0, C0a, C0b, 1); - dofilter(cons.bhit+1, C1a, C1b, 1); - dofilter(cons.bhit+2, C2a, C2b, 1); - dofilter(cons.bread+0, C0a, C0b, 1); - dofilter(cons.bread+1, C1a, C1b, 1); - dofilter(cons.bread+2, C2a, C2b, 1); - dofilter(cons.brahead+0, C0a, C0b, 1); - dofilter(cons.brahead+1, C1a, C1b, 1); - dofilter(cons.brahead+2, C2a, C2b, 1); - dofilter(cons.binit+0, C0a, C0b, 1); - dofilter(cons.binit+1, C1a, C1b, 1); - dofilter(cons.binit+2, C2a, C2b, 1); - cons.chan = chaninit(Devcon, 1); - -start: - /* - * part 1 -- read the config file - */ - devnone = iconfig("n"); - - print("config %s\n", nvr.config); - - d = iconfig(nvr.config); - devinit(d); - if(f.newconf) { - p = getbuf(d, 0, Bmod); - memset(p->iobuf, 0, RBUFSIZE); - settag(p, Tconfig, 0); - } else - p = getbuf(d, 0, Bread|Bmod); - if(!p || checktag(p, Tconfig, 0)) - panic("config io"); - mergeconf(p); - if(f.modconf) { - memset(p->iobuf, 0, BUFSIZE); - p->flags |= Bmod|Bimm; - if(service[0]) - sprint(strchr(p->iobuf, 0), "service %s\n", service); - for(fs=filsys; fs->name; fs++) - if(fs->conf) - sprint(strchr(p->iobuf, 0), - "filsys %s %s\n", fs->name, fs->conf); - sprint(strchr(p->iobuf, 0), "ipauth %I\n", authip); - sprint(strchr(p->iobuf, 0), "ipsntp %I\n", sntpip); - for(i=0; i<10; i++) { - sprint(strchr(p->iobuf, 0), - "ip%d %I\n", i, ipaddr[i].sysip); - sprint(strchr(p->iobuf, 0), - "ipgw%d %I\n", i, ipaddr[i].defgwip); - sprint(strchr(p->iobuf, 0), - "ipmask%d %I\n", i, ipaddr[i].defmask); - } - putbuf(p); - f.modconf = 0; - f.newconf = 0; - print("config block written\n"); - goto start; - } - putbuf(p); - - print("service %s\n", service); - print("ipauth %I\n", authip); - print("ipsntp %I\n", sntpip); - for(i=0; i<10; i++) { - if(nzip(ipaddr[i].sysip)) { - print("ip%d %I\n", i, ipaddr[i].sysip); - print("ipgw%d %I\n", i, ipaddr[i].defgwip); - print("ipmask%d %I\n", i, ipaddr[i].defmask); - } - } - -loop: - /* - * part 2 -- squeeze out the deleted filesystems - */ - for(fs=filsys; fs->name; fs++) - if(fs->conf == 0) { - for(; fs->name; fs++) - *fs = *(fs+1); - goto loop; - } - if(filsys[0].name == 0) - panic("no filsys"); - - /* - * part 3 -- compile the device expression - */ - error = 0; - for(fs=filsys; fs->name; fs++) { - print("filsys %s %s\n", fs->name, fs->conf); - fs->dev = iconfig(fs->conf); - if(f.error) { - error = 1; - continue; - } - } - if(error) - panic("fs config"); - - /* - * part 4 -- initialize the devices - */ - for(fs=filsys; fs->name; fs++) { - print("sysinit: %s\n", fs->name); - if(fs->flags & FREAM) - devream(fs->dev, 1); - if(fs->flags & FRECOVER) - devrecover(fs->dev); - devinit(fs->dev); - } -} - -void -getline(char *line) -{ - char *p; - int c; - - p = line; - for(;;) { - c = rawchar(0); - if(c == 0 || c == '\n') { - *p = 0; - return; - } - if(c == '\b') { - p--; - continue; - } - *p++ = c; - } -} - -void -arginit(void) -{ - int verb, c; - char line[300], word[300], *cp; - uchar localip[Pasize]; - Filsys *fs; - uchar csum; - - print("nvr read\n"); - nvread(NVRAUTHADDR, &nvr, sizeof(nvr)); - csum = nvcsum(nvr.authkey, sizeof(nvr.authkey)); - if(csum != nvr.authsum) { - print("\n\n ** NVR key checksum is incorrect **\n"); - print(" ** set password to allow attaches **\n\n"); - memset(nvr.authkey, 0, sizeof(nvr.authkey)); - goto loop; - } - csum = nvcsum(nvr.config, sizeof(nvr.config)); - if(csum != nvr.configsum) { - print("\n\n ** NVR config checksum is incorrect **\n"); - memset(nvr.config, 0, sizeof(nvr.config)); - goto loop; - } - - print("for config mode hit a key within 5 seconds\n"); - c = rawchar(5); - if(c == 0) { - print(" no config\n"); - return; - } - -loop: - print("config: "); - getline(line); - cp = getwd(word, line); - if(strcmp(word, "end") == 0) - return; - if(strcmp(word, "halt") == 0) - exit(); - - if(strcmp(word, "allow") == 0) { - wstatallow = 1; - writeallow = 1; - goto loop; - } - - if(strcmp(word, "noauth") == 0) { - noauth = !noauth; - goto loop; - } - if(strcmp(word, "noattach") == 0) { - noattach = !noattach; - goto loop; - } - if(strcmp(word, "ream") == 0) { - verb = FREAM; - goto gfsname; - } - if(strcmp(word, "recover") == 0) { - verb = FRECOVER; - goto gfsname; - } - if(strcmp(word, "filsys") == 0) { - verb = FEDIT; - goto gfsname; - } - if(strcmp(word, "nvram") == 0) { - getwd(word, cp); - if(testconfig(word)) - goto loop; - c = strlen(word); - if(c >= sizeof(nvr.config)) { - print("config string too long\n"); - goto loop; - } - memset(nvr.config, 0, sizeof(nvr.config)); - memmove(nvr.config, word, c); - nvr.configsum = nvcsum(nvr.config, sizeof(nvr.config)); - nvwrite(NVRAUTHADDR, &nvr, sizeof(nvr)); - goto loop; - } - if(strcmp(word, "config") == 0) { - getwd(word, cp); - if(testconfig(word)) - goto loop; - c = strlen(word); - if(c >= sizeof(nvr.config)) { - print("config string too long\n"); - goto loop; - } - memset(nvr.config, 0, sizeof(nvr.config)); - memmove(nvr.config, word, c); - nvr.configsum = nvcsum(nvr.config, sizeof(nvr.config)); - nvwrite(NVRAUTHADDR, &nvr, sizeof(nvr)); - f.newconf = 1; - goto loop; - } - if(strcmp(word, "service") == 0) { - getwd(word, cp); - strcpy(service, word); - f.modconf = 1; - goto loop; - } - if(strcmp(word, "ipauth") == 0) { - f.ipauthset = 1; - verb = 2; - goto ipname; - } - if(astrcmp(word, "ip") == 0) { - verb = 0; - goto ipname; - } - if(astrcmp(word, "ipgw") == 0) { - verb = 1; - goto ipname; - } - if(astrcmp(word, "ipmask") == 0) { - verb = 3; - goto ipname; - } - if(astrcmp(word, "ipsntp") == 0) { - verb = 4; - goto ipname; - } - print("unknown config command\n"); - print(" type end to get out\n"); - goto loop; - -ipname: - getwd(word, cp); - if(chartoip(localip, word)) { - print("bad ip address\n"); - goto loop; - } - switch(verb) { - case 0: - memmove(ipaddr[aindex].sysip, localip, - sizeof(ipaddr[aindex].sysip)); - break; - case 1: - memmove(ipaddr[aindex].defgwip, localip, - sizeof(ipaddr[aindex].defgwip)); - break; - case 2: - memmove(authip, localip, - sizeof(authip)); - break; - case 3: - memmove(ipaddr[aindex].defmask, localip, - sizeof(ipaddr[aindex].defmask)); - break; - case 4: - memmove(sntpip, localip, - sizeof(sntpip)); - break; - } - f.modconf = 1; - goto loop; - -gfsname: - cp = getwd(word, cp); - for(fs=filsys; fs->name; fs++) - if(strcmp(word, fs->name) == 0) - goto found; - memset(fs, 0, sizeof(*fs)); - fs->name = strdup(word); - -found: - switch(verb) { - case FREAM: - if(strcmp(fs->name, "main") == 0) - wstatallow = 1; /* only set, never reset */ - case FRECOVER: - fs->flags |= verb; - goto loop; - case FEDIT: - f.modconf = 1; - getwd(word, cp); - fs->flags |= verb; - if(word[0] == 0) { - fs->conf = 0; - goto loop; - } - if(testconfig(word)) - goto loop; - fs->conf = strdup(word); - goto loop; - } -} //GO.SYSIN DD port/config.c echo port/main.c sed 's/.//' >port/main.c <<'//GO.SYSIN DD port/main.c' -#include "all.h" -#include "mem.h" -#include "io.h" -#include "ureg.h" - -void -machinit(void) -{ - int n; - - n = m->machno; - memset(m, 0, sizeof(Mach)); - m->machno = n; - m->mmask = 1<machno; - m->lights = 0; - - active.exiting = 0; - active.machs = 1; -} - -static -void -confinit(void) -{ - conf.nmach = 1; - conf.nproc = 50; - - conf.mem = meminit(); - conf.sparemem = conf.mem/12; /* 8% spare for chk etc */ - - conf.nalarm = 200; - conf.nuid = 1000; - conf.nserve = 15; - conf.nfile = 30000; - conf.nlgmsg = 100; - conf.nsmmsg = 500; - conf.wcpsize = 1024*1024; - localconfinit(); - - conf.nwpath = conf.nfile*8; - conf.gidspace = conf.nuid*3; - - cons.flags = 0; -} - -void -main(void) -{ - int i; - - echo = 1; - predawn = 1; - formatinit(); - machinit(); - vecinit(); - confinit(); - lockinit(); - printinit(); - procinit(); - clockinit(); - alarminit(); - - mainlock.wr.name = "mainr"; - mainlock.rd.name = "mainw"; - reflock.name = "ref"; - - qlock(&reflock); - qunlock(&reflock); - serveq = newqueue(1000); - raheadq = newqueue(1000); - authreply = newqueue(Nqueue); - - mbinit(); - - sntpinit(); - otherinit(); - - files = ialloc(conf.nfile * sizeof(*files), 0); - for(i=0; idev > rb->dev) - return 1; - if(ra->dev < rb->dev) - return -1; - if(ra->addr > rb->addr) - return 1; - if(ra->addr < rb->addr) - return -1; - return 0; -} - -void -rahead(void) -{ - Rabuf *rb[50]; - Iobuf *p; - int i, n; - -loop: - rb[0] = recv(raheadq, 0); - for(n=1; ncount <= 0) - break; - rb[n] = recv(raheadq, 0); - } - qsort(rb, n, sizeof(rb[0]), rbcmp); - for(i=0; idev, rb[i]->addr, Bread); - if(p) - putbuf(p); - lock(&rabuflock); - rb[i]->link = rabuffree; - rabuffree = rb[i]; - unlock(&rabuflock); - } - goto loop; -} - -/* - * main filesystem server loop. - * entered by many processes. - * they wait for message buffers and - * then process them. - */ -void -serve(void) -{ - Fcall fi, fo; - Msgbuf *mb, *mb1; - Chan *cp; - int t, n; - -loop: - qlock(&reflock); - mb = recv(serveq, 0); - cp = mb->chan; - rlock(&cp->reflock); - qunlock(&reflock); - - rlock(&mainlock); - - /* - * conversion to structure and - * simple syntax checks. - */ - if(convM2S(mb->data, &fi, mb->count) == 0) { - print("bad M2S conversion\n"); - goto error; - } - t = fi.type; - - if(t < 0 || t >= MAXSYSCALL || (t&1) || !p9call[t]) { - print("bad message type\n"); - goto error; - } - - /* - * allocate reply message - */ - if(t == Tread) { - mb1 = mballoc(MAXMSG+MAXDAT, cp, Mbreply2); - fo.data = mb1->data + 8; - } else - mb1 = mballoc(MAXMSG, cp, Mbreply3); - - /* - * call the file system - */ - cons.work[0].count++; - cons.work[1].count++; - cons.work[2].count++; - cp->work.count++; - cons.rate[0].count += mb->count; - cons.rate[1].count += mb->count; - cons.rate[2].count += mb->count; - cp->rate.count += mb->count; - fo.err = 0; - - (*p9call[t])(cp, &fi, &fo); - - fo.type = t+1; - fo.tag = fi.tag; - - if(fo.err) { - if(cons.flags&errorflag) - print(" type %d: error: %s\n", t, - errstr[fo.err]); - if(CHAT(cp)) - print(" error: %s\n", errstr[fo.err]); - fo.type = Rerror; - strncpy(fo.ename, errstr[fo.err], sizeof(fo.ename)); - } - - n = convS2M(&fo, mb1->data); - if(n == 0) { - print("bad S2M conversion\n"); - mbfree(mb1); - goto error; - } - mb1->count = n; - mb1->param = mb->param; - cons.rate[0].count += n; - cons.rate[1].count += n; - cons.rate[2].count += n; - cp->rate.count += n; - send(cp->reply, mb1); - -out: - mbfree(mb); - runlock(&mainlock); - runlock(&cp->reflock); - goto loop; - -error: - print("type=%d count=%d\n", mb->data[0], mb->count); - print(" %.2x %.2x %.2x %.2x\n", - mb->data[1]&0xff, mb->data[2]&0xff, - mb->data[3]&0xff, mb->data[4]&0xff); - print(" %.2x %.2x %.2x %.2x\n", - mb->data[5]&0xff, mb->data[6]&0xff, - mb->data[7]&0xff, mb->data[8]&0xff); - print(" %.2x %.2x %.2x %.2x\n", - mb->data[9]&0xff, mb->data[10]&0xff, - mb->data[11]&0xff, mb->data[12]&0xff); - - mb1 = mballoc(3, cp, Mbreply4); - mb1->data[0] = Rnop; /* your nop was ok */ - mb1->data[1] = ~0; - mb1->data[2] = ~0; - mb1->count = 3; - mb1->param = mb->param; - send(cp->reply, mb1); - goto out; -} - -void -init0(void) -{ - m->proc = u; - u->state = Running; - u->mach = m; - spllo(); - - (*u->start)(); -} - -void* -getarg(void) -{ - - return u->arg; -} - -void -exit(void) -{ - u = 0; - lock(&active); - active.machs &= ~(1<machno); - active.exiting = 1; - unlock(&active); - if(!predawn) - spllo(); - print("cpu %d exiting\n", m->machno); - while(active.machs) - delay(1); - print("halted. press a key to reboot.\n"); - delay(300); /* time to drain print q */ - splhi(); - rawchar(5 * 60); // reboot in 5mins or key press - consreset(); - firmware(); -} - -/* - * 1 sec timer - * process+alarm+rendez+rwlock - */ -static Rendez sec; - -static -void -callsec(Alarm *a, void *arg) -{ - User *u; - - cancel(a); - u = arg; - wakeup(&u->tsleep); -} - -void -waitsec(int msec) -{ - alarm(msec, callsec, u); - sleep(&u->tsleep, no, 0); -} - -#define DUMPTIME 5 /* 5 am */ -#define WEEKMASK 0 /* every day (1=sun, 2=mon 4=tue) */ - -/* - * process to copy dump blocks from - * cache to worm. it runs flat out when - * it gets work, but only looks for - * work every 10 seconds. - */ -void -wormcopy(void) -{ - int f; - Filsys *fs; - ulong nddate, ntoytime, t; - long dt; - -recalc: - /* - * calculate the next dump time. - * minimum delay is 100 minutes. - */ - t = time(); - nddate = nextime(t+MINUTE(100), DUMPTIME, WEEKMASK); - if(!conf.nodump) - print("next dump at %T\n", nddate); - - ntoytime = time() + HOUR(1); - -loop: - dt = time() - t; - if(dt < 0) { - print("time went back\n"); - goto recalc; - } - if(dt > MINUTE(100)) { - print("time jumped ahead\n"); - goto recalc; - } - t += dt; - f = 0; - - if(t > ntoytime) { - dt = time() - rtctime(); - if(dt < 0) - dt = -dt; - if(dt > 10) - print("rtc time more than 10 secounds out\n"); - else - if(dt > 1) - settime(rtctime()); - ntoytime = time() + HOUR(1); - goto loop; - } - - if(!f) { - if(t > nddate) { - if(!conf.nodump) { - print("automatic dump %T\n", t); - for(fs=filsys; fs->name; fs++) - if(fs->dev->type == Devcw) - cfsdump(fs); - } - goto recalc; - } - } - - rlock(&mainlock); - for(fs=filsys; fs->name; fs++) - if(fs->dev->type == Devcw) - f |= dumpblock(fs->dev); - runlock(&mainlock); - - if(!f) - f = dowcp(); - - if(!f) - waitsec(10000); - wormprobe(); - goto loop; -} - -/* - * process to synch blocks - * it puts out a block/line every second - * it waits 10 seconds if caught up. - * in both cases, it takes about 10 seconds - * to get up-to-date. - */ -void -synccopy(void) -{ - int f; - -loop: - rlock(&mainlock); - f = syncblock(); - runlock(&mainlock); - if(!f) - waitsec(10000); - else - waitsec(1000); -/* pokewcp(); */ - goto loop; -} //GO.SYSIN DD port/main.c echo port/portdat.h sed 's/.//' >port/portdat.h <<'//GO.SYSIN DD port/portdat.h' -/* - * fundamental constants - */ -#define SUPER_ADDR 2 /* address of superblock */ -#define ROOT_ADDR 3 /* address of superblock */ -#define ERRREC 64 /* size of a error record */ -#define DIRREC 116 /* size of a directory ascii record */ -#define NAMELEN 28 /* size of names */ -#define NDBLOCK 6 /* number of direct blocks in Dentry */ -#define MAXDAT 8192 /* max allowable data message */ -#define MAXMSG 128 /* max size protocol message sans data */ -#define OFFMSG 60 /* offset of msg in buffer */ -#define NDRIVE 16 /* size of drive structure */ -#define NTLOCK 200 /* number of active file Tlocks */ -#define LRES 3 /* profiling resolution */ -#define NATTID 10 /* the last 10 ID's in attaches */ -#define C0a 59 /* time constants for filters */ -#define C0b 60 -#define C1a 599 -#define C1b 600 -#define C2a 5999 -#define C2b 6000 - -/* - * more wonderful constants for authentication - */ -#include - -/* - * derived constants - */ -#define BUFSIZE (RBUFSIZE-sizeof(Tag)) -#define DIRPERBUF (BUFSIZE/sizeof(Dentry)) -#define INDPERBUF (BUFSIZE/sizeof(long)) -#define INDPERBUF2 (INDPERBUF*INDPERBUF) -#define FEPERBUF ((BUFSIZE-sizeof(Super1)-sizeof(long))/sizeof(long)) -#define SMALLBUF (MAXMSG) -#define LARGEBUF (MAXMSG+MAXDAT+256) -#define RAGAP (300*1024)/BUFSIZE /* readahead parameter */ -#define CEPERBK ((BUFSIZE-BKPERBLK*sizeof(long))/\ - (sizeof(Centry)*BKPERBLK)) -#define BKPERBLK 10 - -typedef struct Alarm Alarm; -typedef struct Conf Conf; -typedef struct Label Label; -typedef struct Lock Lock; -typedef struct Mach Mach; -typedef struct QLock QLock; -typedef struct Ureg Ureg; -typedef struct User User; -typedef struct Fcall Fcall; -typedef struct Fbuf Fbuf; -typedef struct Super1 Super1; -typedef struct Superb Superb; -typedef struct Filsys Filsys; -typedef struct Startsb Startsb; -typedef struct Dentry Dentry; -typedef struct Tag Tag; -typedef struct Talarm Talarm; -typedef struct Uid Uid; -typedef struct Device Device; -typedef struct Qid Qid; -typedef struct Iobuf Iobuf; -typedef struct Wpath Wpath; -typedef struct File File; -typedef struct Chan Chan; -typedef struct Cons Cons; -typedef struct Time Time; -typedef struct Tm Tm; -typedef struct Rtc Rtc; -typedef struct Hiob Hiob; -typedef struct RWlock RWlock; -typedef struct Msgbuf Msgbuf; -typedef struct Queue Queue; -typedef struct Command Command; -typedef struct Flag Flag; -typedef struct Bp Bp; -typedef struct Rabuf Rabuf; -typedef struct Rendez Rendez; -typedef struct Filter Filter; -typedef ulong Float; -typedef struct Tlock Tlock; -typedef struct Enpkt Enpkt; -typedef struct Arppkt Arppkt; -typedef struct Ippkt Ippkt; -typedef struct Ilpkt Ilpkt; -typedef struct Udppkt Udppkt; -typedef struct Icmppkt Icmppkt; -typedef struct Ifc Ifc; -typedef struct Cache Cache; -typedef struct Centry Centry; -typedef struct Bucket Bucket; - -struct Lock -{ - ulong* sbsem; /* addr of sync bus semaphore */ - ulong pc; - ulong sr; -}; - -struct Rendez -{ - Lock; - User* p; -}; - -struct Filter -{ - ulong count; /* count and old count kept separate */ - ulong oldcount; /* so interrput can read them */ - int c1; /* time const multiplier */ - int c2; /* time const divider */ - int c3; /* scale for printing */ - Float filter; /* filter */ -}; - -struct QLock -{ - Lock; /* to use object */ - User* head; /* next process waiting for object */ - User* tail; /* last process waiting for object */ - char* name; /* for diagnostics */ - int locked; /* flag, is locked */ -}; - -struct RWlock -{ - int nread; - QLock wr; - QLock rd; -}; - -/* - * send/recv queue structure - */ -struct Queue -{ - Lock; /* to manipulate values */ - int size; /* size of queue */ - int loc; /* circular pointer */ - int count; /* how many in queue */ - User* rhead; /* process's waiting for send */ - User* rtail; - User* whead; /* process's waiting for recv */ - User* wtail; - void* args[1]; /* list of saved pointers, [->size] */ -}; - -struct Tag -{ - short pad; - short tag; - long path; -}; - -struct Device -{ - uchar type; - uchar init; - Device* link; /* link for mcat/mlev */ - Device* dlink; /* link all devices */ - void* private; - long size; - union - { - struct /* worm wren */ - { - int ctrl; - int targ; - int lun; - } wren; - struct /* ata/ide */ - { - int ctrl; - int unit; - } ata; - struct /* mcat mlev */ - { - Device* first; - Device* last; - int ndev; - } cat; - struct /* cw */ - { - Device* c; - Device* w; - Device* ro; - } cw; - struct /* juke */ - { - Device* j; - Device* m; - } j; - struct /* ro */ - { - Device* parent; - } ro; - struct /* fworm */ - { - Device* fw; - } fw; - struct /* part */ - { - Device* d; - long base; - long size; - } part; - struct /* part */ - { - Device* d; - } swab; - }; -}; - -struct Rabuf -{ - union - { - struct - { - Device* dev; - long addr; - }; - Rabuf* link; - }; -}; - -/* DONT TOUCH, this is the disk structure */ -struct Qid -{ - long path; - long version; -}; - -struct Hiob -{ - Iobuf* link; - Lock; -}; - -enum -{ - Easize = 6, /* Ether address size */ - Pasize = 4, /* IP protocol address size */ -}; - -typedef -struct -{ - Queue* reply; /* ethernet output */ - uchar iphis[Pasize]; /* his ip address (index) */ - uchar ipgate[Pasize]; /* his ip/gateway address */ - Chan* link; /* list of il channels */ -} Enp; - -enum -{ - Nqt= 8, -}; - -typedef -struct Ilp -{ - Enp; /* must be first -- botch */ - - int alloc; /* 1 means allocated */ - int srcp; /* source port (index) */ - int dstp; /* dest port (index) */ - int state; /* connection state */ - - Msgbuf* unacked; - Msgbuf* unackedtail; - - Msgbuf* outoforder; - - ulong next; /* id of next to send */ - ulong recvd; /* last packet received */ - ulong start; /* local start id */ - ulong rstart; /* remote start id */ - ulong acksent; /* Last packet acked */ - - ulong lastxmit; /* time of last xmit */ - ulong lastrecv; /* time of last recv */ - ulong timeout; /* time out counter */ - ulong acktime; /* acknowledge timer */ - ulong querytime; /* Query timer */ - - ulong delay; /* Average of the fixed rtt delay */ - ulong rate; /* Average byte rate */ - ulong mdev; /* Mean deviation of predicted to real rtt */ - ulong maxrtt; /* largest rtt seen */ - ulong rttack; /* The ack we are waiting for */ - int rttlen; /* Length of rttack packet */ - ulong rttstart; /* Time we issued rttack packet */ - ulong unackedbytes; - int rexmit; /* number of rexmits of *unacked */ - - ulong qt[Nqt+1]; /* state table for query messages */ - int qtx; /* ... index into qt */ - - int window; /* maximum receive window */ - - Rendez syn; /* connect hang out */ -} Ilp; - -struct Chan -{ - char type; /* major driver type i.e. Dev* */ - char whochan[50]; - char whoname[NAMELEN]; - ulong flags; - int chan; /* overall channel number, mostly for printing */ - int nmsgs; /* outstanding messages, set under flock -- for flush */ - ulong whotime; - Filter work; - Filter rate; - int nfile; /* used by cmd_files */ - RWlock reflock; - Chan* next; /* link list of chans */ - Queue* send; - Queue* reply; - uchar chal[CHALLEN]; /* locally generated challenge */ - uchar rchal[CHALLEN]; /* remotely generated challenge */ - Lock idlock; - ulong idoffset; /* offset of id vector */ - ulong idvec; /* vector of acceptable id's */ - - Ifc* ifc; - union - { - /* - * il ether circuit structure - */ - Ilp ilp; - }; -}; - -struct Filsys -{ - char* name; /* name of filsys */ - char* conf; /* symbolic configuration */ - Device* dev; /* device that filsys is on */ - int flags; - #define FREAM (1<<0) /* mkfs */ - #define FRECOVER (1<<1) /* install last dump */ - #define FEDIT (1<<2) /* modified */ -}; - -struct Startsb -{ - char* name; - long startsb; -}; - -struct Time -{ - ulong lasttoy; - long bias; - long offset; -}; - -/* - * array of qids that are locked - */ -struct Tlock -{ - Device* dev; - ulong time; - long qpath; - File* file; -}; - -struct Cons -{ - ulong flags; /* overall flags for all channels */ - QLock; /* generic qlock for mutex */ - int uid; /* botch -- used to get uid on cons_create */ - int gid; /* botch -- used to get gid on cons_create */ - int nuid; /* number of uids */ - int ngid; /* number of gids */ - long offset; /* used to read files, c.f. fchar */ - int chano; /* generator for channel numbers */ - Chan* chan; /* console channel */ - Filsys* curfs; /* current filesystem */ - - int profile; /* are we profiling? */ - long* profbuf; - ulong minpc; - ulong maxpc; - ulong nprofbuf; - - long nlarge; /* number of large message buffers */ - long nsmall; /* ... small ... */ - long nwormre; /* worm read errors */ - long nwormwe; /* worm write errors */ - long nwormhit; /* worm read cache hits */ - long nwormmiss; /* worm read cache non-hits */ - int noage; /* dont update cache age, dump and check */ - long nwrenre; /* disk read errors */ - long nwrenwe; /* disk write errors */ - long nreseq; /* cache bucket resequence */ - - Filter work[3]; /* thruput in messages */ - Filter rate[3]; /* thruput in bytes */ - Filter bhit[3]; /* getbufs that hit */ - Filter bread[3]; /* getbufs that miss and read */ - Filter brahead[3]; /* messages to readahead */ - Filter binit[3]; /* getbufs that miss and dont read */ -}; - -struct File -{ - QLock; - Qid qid; - Wpath* wpath; - Chan* cp; /* null means a free slot */ - Tlock* tlock; /* if file is locked */ - File* next; /* in cp->flist */ - Filsys* fs; - long addr; - long slot; - long lastra; /* read ahead address */ - ushort fid; - short uid; - char open; - #define FREAD 1 - #define FWRITE 2 - #define FREMOV 4 -}; - -struct Wpath -{ - Wpath* up; /* pointer upwards in path */ - long addr; /* directory entry addr */ - long slot; /* directory entry slot */ - short refs; /* number of files using this structure */ -}; - -struct Iobuf -{ - QLock; - Device* dev; - Iobuf* next; /* for hash */ - Iobuf* fore; /* for lru */ - Iobuf* back; /* for lru */ - char* iobuf; /* only active while locked */ - char* xiobuf; /* "real" buffer pointer */ - long addr; - int flags; -}; - -struct Uid -{ - short uid; /* user id */ - short lead; /* leader of group */ - short *gtab; /* group table */ - int ngrp; /* number of group entries */ - char name[NAMELEN]; /* user name */ -}; - -/* DONT TOUCH, this is the disk structure */ -struct Dentry -{ - char name[NAMELEN]; - short uid; - short gid; - ushort mode; - #define DALLOC 0x8000 - #define DDIR 0x4000 - #define DAPND 0x2000 - #define DLOCK 0x1000 - #define DREAD 0x4 - #define DWRITE 0x2 - #define DEXEC 0x1 - short wuid; - Qid qid; - long size; - long dblock[NDBLOCK]; - long iblock; - long diblock; - long atime; - long mtime; -}; - -/* DONT TOUCH, this is the disk structure */ -struct Super1 -{ - long fstart; - long fsize; - long tfree; - long qidgen; /* generator for unique ids */ - /* - * Stuff for WWC device - */ - long cwraddr; /* cfs root addr */ - long roraddr; /* dump root addr */ - long last; /* last super block addr */ - long next; /* next super block addr */ -}; - -/* DONT TOUCH, this is the disk structure */ -struct Fbuf -{ - long nfree; - long free[FEPERBUF]; -}; - -/* DONT TOUCH, this is the disk structure */ -struct Superb -{ - Fbuf fbuf; - Super1; -}; - -struct Fcall -{ - char type; - ushort fid; - short err; - short tag; - union - { - struct - { - short uid; /* T-Userstr */ - short oldtag; /* T-nFlush */ - Qid qid; /* R-Attach, R-Clwalk, R-Walk, - * R-Open, R-Create */ - char rauth[AUTHENTLEN]; /* R-attach */ - }; - struct - { - char uname[NAMELEN]; /* T-nAttach */ - char aname[NAMELEN]; /* T-nAttach */ - char ticket[TICKETLEN]; /* T-attach */ - char auth[AUTHENTLEN]; /* T-attach */ - }; - struct - { - char ename[ERRREC]; /* R-nError */ - char chal[CHALLEN]; /* T-session, R-session */ - char authid[NAMELEN]; /* R-session */ - char authdom[DOMLEN]; /* R-session */ - }; - struct - { - char name[NAMELEN]; /* T-Walk, T-Clwalk, T-Create, T-Remove */ - long perm; /* T-Create */ - ushort newfid; /* T-Clone, T-Clwalk */ - char mode; /* T-Create, T-Open */ - }; - struct - { - long offset; /* T-Read, T-Write */ - long count; /* T-Read, T-Write, R-Read */ - char* data; /* T-Write, R-Read */ - }; - struct - { - char stat[DIRREC]; /* T-Wstat, R-Stat */ - }; - }; -}; - -struct Label -{ - ulong pc; - ulong sp; -}; - -struct Alarm -{ - Lock; - Alarm* next; - int busy; - int dt; /* in ticks */ - void (*f)(Alarm*, void*); - void* arg; -}; - -struct Talarm -{ - Lock; - User *list; -}; - -struct Conf -{ - ulong nmach; /* processors */ - ulong nproc; /* processes */ - ulong mem; /* total physical bytes of memory */ - ulong sparemem; /* memory left for check/dump and chans */ - ulong nalarm; /* alarms */ - ulong nuid; /* distinct uids */ - ulong nserve; /* server processes */ - ulong nfile; /* number of fid -- system wide */ - ulong nwpath; /* number of active paths, derrived from nfile */ - ulong gidspace; /* space for gid names -- derrived from nuid */ - ulong nlgmsg; /* number of large message buffers */ - ulong nsmmsg; /* number of small message buffers */ - ulong wcpsize; /* memory for worm copies */ - ulong recovcw; /* recover addresses */ - ulong recovro; - ulong firstsb; - ulong recovsb; - uchar nodump; /* no periodic dumps */ - uchar ripoff; - uchar dumpreread; /* read and compare in dump copy */ - - ulong npage0; /* total physical pages of memory */ - ulong npage1; /* total physical pages of memory */ - ulong base0; /* base of bank 0 */ - ulong base1; /* base of bank 1 */ -}; - -/* - * message buffers - * 2 types, large and small - */ -struct Msgbuf -{ - short count; - short flags; - #define LARGE (1<<0) - #define FREE (1<<1) - #define BFREE (1<<2) - Chan* chan; - Msgbuf* next; - ulong param; - int category; - char* data; - char* xdata; -}; - -/* - * message buffer categories - */ -enum -{ - Mxxx = 0, - Mbreply1, - Mbreply2, - Mbreply3, - Mbreply4, - Mbarp1, - Mbarp2, - Mbip1, - Mbip2, - Mbip3, - Mbil1, - Mbil2, - Mbil3, - Mbil4, - Mbilauth, - Maeth1, - Maeth2, - Maeth3, - Mbeth1, - Mbeth2, - Mbeth3, - Mbeth4, - Mbsntp, - MAXCAT, -}; - -struct Mach -{ - int machno; /* physical id of processor */ - int mmask; /* 1<machno */ - ulong ticks; /* of the clock since boot time */ - int lights; /* light lights, this processor */ - User* proc; /* current process on this processor */ - Label sched; /* scheduler wakeup */ - Lock alarmlock; /* access to alarm list */ - void* alarm; /* alarms bound to this clock */ - void (*intr)(Ureg*, ulong); /* pending interrupt */ - User* intrp; /* process that was interrupted */ - ulong cause; /* arg to intr */ - Ureg* ureg; /* arg to intr */ - uchar stack[1]; -}; - -#define MAXSTACK 4000 -#define NHAS 100 -struct User -{ - Label sched; - Mach* mach; /* machine running this proc */ - User* rnext; /* next process in run queue */ - User* qnext; /* next process on queue for a QLock */ - void (*start)(void); /* startup function */ - char* text; /* name of this process */ - void* arg; - Filter time[3]; /* cpu time used */ - int exiting; - int pid; - int state; - Rendez tsleep; - - ulong twhen; - Rendez *trend; - User *tlink; - int (*tfn)(void*); - - struct - { - QLock* q[NHAS];/* list of locks this process has */ - QLock* want; /* lock waiting */ - } has; - uchar stack[MAXSTACK]; -}; - -#define PRINTSIZE 256 -struct -{ - Lock; - int machs; - int exiting; -} active; - -struct Command -{ - char* arg0; - char* help; - void (*func)(int, char*[]); -}; - -struct Flag -{ - char* arg0; - char* help; - ulong flag; -}; - -struct Tm -{ - /* see ctime(3) */ - int sec; - int min; - int hour; - int mday; - int mon; - int year; - int wday; - int yday; - int isdst; -}; - -struct Rtc -{ - int sec; - int min; - int hour; - int mday; - int mon; - int year; -}; - -/* - * cw device - */ - -/* DONT TOUCH, this is the disk structure */ -struct Cache -{ - long maddr; /* cache map addr */ - long msize; /* cache map size in buckets */ - long caddr; /* cache addr */ - long csize; /* cache size */ - long fsize; /* current size of worm */ - long wsize; /* max size of the worm */ - long wmax; /* highwater write */ - - long sbaddr; /* super block addr */ - long cwraddr; /* cw root addr */ - long roraddr; /* dump root addr */ - - long toytime; /* somewhere convienent */ - long time; -}; - -/* DONT TOUCH, this is the disk structure */ -struct Centry -{ - ushort age; - short state; - long waddr; /* worm addr */ -}; - -/* DONT TOUCH, this is the disk structure */ -struct Bucket -{ - long agegen; /* generator for ages in this bkt */ - Centry entry[CEPERBK]; -}; - -/* - * scsi i/o - */ -enum -{ - SCSIread = 0, - SCSIwrite = 1, -}; - -/* - * Process states - */ -enum -{ - Dead = 0, - Moribund, - Zombie, - Ready, - Scheding, - Running, - Queueing, - Sending, - Recving, - MMUing, - Exiting, - Inwait, - Wakeme, - Broken, -}; - -/* - * Lights - */ -enum -{ - Lreal = 0, /* blink in clock interrupt */ - Lintr, /* on while in interrupt */ - Lpanic, /* in panic */ - Lcwmap, /* in cw lookup */ -}; - -/* - * devnone block numbers - */ -enum -{ - Cwio1 = 1, - Cwio2, - Cwxx1, - Cwxx2, - Cwxx3, - Cwxx4, - Cwdump1, - Cwdump2, - Cuidbuf, - Cckbuf, -}; - -#define MAXFDATA 8192 -/* - * P9 protocol message types - */ -/* DONT TOUCH, this the 9P protocol */ -enum -{ - Tnop = 50, - Rnop, - Tosession = 52, - Rosession, - Terror = 54, /* illegal */ - Rerror, - Tflush = 56, - Rflush, - Toattach = 58, - Roattach, - Tclone = 60, - Rclone, - Twalk = 62, - Rwalk, - Topen = 64, - Ropen, - Tcreate = 66, - Rcreate, - Tread = 68, - Rread, - Twrite = 70, - Rwrite, - Tclunk = 72, - Rclunk, - Tremove = 74, - Rremove, - Tstat = 76, - Rstat, - Twstat = 78, - Rwstat, - Tclwalk = 80, - Rclwalk, - Tauth = 82, /* illegal */ - Rauth, /* illegal */ - Tsession = 84, - Rsession, - Tattach = 86, - Rattach, - - MAXSYSCALL -}; - -/* - * error codes generated from the file server - */ -enum -{ - Ebadspc = 1, - Efid, - Echar, - Eopen, - Ecount, - Ealloc, - Eqid, - Eaccess, - Eentry, - Emode, - Edir1, - Edir2, - Ephase, - Eexist, - Edot, - Eempty, - Ebadu, - Enotu, - Enotg, - Ename, - Ewalk, - Eronly, - Efull, - Eoffset, - Elocked, - Ebroken, - Eauth, - Enoattach, - MAXERR -}; - -/* - * device types - */ -enum -{ - Devnone = 0, - Devcon, /* console */ - Devwren, /* scsi disk drive */ - Devworm, /* scsi video drive */ - Devlworm, /* scsi video drive (labeled) */ - Devfworm, /* fake read-only device */ - Devjuke, /* jukebox */ - Devcw, /* cache with worm */ - Devro, /* readonly worm */ - Devcycl, /* cyclone fiber uart */ - Devmcat, /* multiple cat devices */ - Devmlev, /* multiple interleave devices */ - Devil, /* internet link */ - Devpart, /* partition */ - Devfloppy, /* floppy drive */ - Devide, /* IDE drive */ - Devswab, /* swab data between mem and device */ - Devdup, /* Dup drive */ - MAXDEV -}; - -/* - * tags on block - */ -/* DONT TOUCH, this is in disk structures */ -enum -{ - Tnone = 0, - Tsuper, /* the super block */ - Tdir, /* directory contents */ - Tind1, /* points to blocks */ - Tind2, /* points to Tind1 */ - Tfile, /* file contents */ - Tfree, /* in free list */ - Tbuck, /* cache fs bucket */ - Tvirgo, /* fake worm virgin bits */ - Tcache, /* cw cache things */ - Tconfig, /* configuration block */ - MAXTAG -}; - -/* - * flags to getbuf - */ -enum -{ - Bread = (1<<0), /* read the block if miss */ - Bprobe = (1<<1), /* return null if miss */ - Bmod = (1<<2), /* buffer is dirty, needs writing */ - Bimm = (1<<3), /* write immediately on putbuf */ - Bres = (1<<4), /* reserved, never renammed */ -}; - -/* - * open modes passed into P9 open/create - */ -/* DONT TOUCH, this the P9 protocol */ -enum -{ - MREAD = 0, - MWRITE, - MBOTH, - MEXEC, - MTRUNC = (1<<4), /* truncate on open */ - MCEXEC = (1<<5), /* close on exec (host) */ - MRCLOSE = (1<<6), /* remove on close */ -}; - - -/* - * Ethernet header - */ -enum -{ - ETHERMINTU = 60, /* minimum transmit size */ - ETHERMAXTU = 1514, /* maximum transmit size */ - - Arptype = 0x0806, - Iptype = 0x0800, - - Icmpproto = 1, - Igmpproto = 2, - Tcpproto = 6, - Udpproto = 17, - Ilproto = 40, - - Nqueue = 20, - Nfrag = 6, /* max number of non-contig ip fragments */ - Nrock = 20, /* number of partial ip assembly stations */ - Nb = 211, /* number of arp hash buckets */ - Ne = 10, /* number of entries in each arp hash bucket */ - - Ensize = 14, /* ether header size */ - Ipsize = 20, /* ip header size -- doesnt include Ensize */ - Arpsize = 28, /* arp header size -- doesnt include Ensize */ - Ilsize = 18, /* il header size -- doesnt include Ipsize/Ensize */ - Udpsize = 8, /* il header size -- doesnt include Ipsize/Ensize */ - Udpphsize = 12, /* udp pseudo ip header size */ - - IP_VER = 0x40, /* Using IP version 4 */ - IP_HLEN = Ipsize/4, /* Header length in longs */ - IP_DF = 0x4000, /* Don't fragment */ - IP_MF = 0x2000, /* More fragments */ - - Arprequest = 1, - Arpreply, - - Ilfsport = 17008, - Ilauthport = 17020, - Ilfsout = 5000, - SNTP = 123, - SNTP_LOCAL = 6001, -}; - -struct Enpkt -{ - uchar d[Easize]; /* destination address */ - uchar s[Easize]; /* source address */ - uchar type[2]; /* packet type */ - - uchar data[ETHERMAXTU-(6+6+2)]; - uchar crc[4]; -}; - -struct Arppkt -{ - uchar d[Easize]; /* ether header */ - uchar s[Easize]; - uchar type[2]; - - uchar hrd[2]; /* hardware type, must be ether==1 */ - uchar pro[2]; /* protocol, must be ip */ - uchar hln; /* hardware address len, must be Easize */ - uchar pln; /* protocol address len, must be Pasize */ - uchar op[2]; - uchar sha[Easize]; - uchar spa[Pasize]; - uchar tha[Easize]; - uchar tpa[Pasize]; -}; - -struct Ippkt -{ - uchar d[Easize]; /* ether header */ - uchar s[Easize]; - uchar type[2]; - - 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 cksum[2]; /* Header checksum */ - uchar src[Pasize]; /* Ip source */ - uchar dst[Pasize]; /* Ip destination */ -}; - -struct Ilpkt -{ - uchar d[Easize]; /* ether header */ - uchar s[Easize]; - uchar type[2]; - - uchar vihl; /* ip header */ - uchar tos; - uchar length[2]; - uchar id[2]; - uchar frag[2]; - uchar ttl; - uchar proto; - uchar cksum[2]; - uchar src[Pasize]; - uchar dst[Pasize]; - - uchar ilsum[2]; /* Checksum including header */ - uchar illen[2]; /* Packet length */ - uchar iltype; /* Packet type */ - uchar ilspec; /* Special */ - uchar ilsrc[2]; /* Src port */ - uchar ildst[2]; /* Dst port */ - uchar ilid[4]; /* Sequence id */ - uchar ilack[4]; /* Acked sequence */ -}; - -struct Udppkt -{ - uchar d[Easize]; /* ether header */ - uchar s[Easize]; - uchar type[2]; - - uchar vihl; /* ip header */ - uchar tos; - uchar length[2]; - uchar id[2]; - uchar frag[2]; - uchar ttl; - uchar proto; - uchar cksum[2]; - uchar src[Pasize]; - uchar dst[Pasize]; - - uchar udpsrc[2]; /* Src port */ - uchar udpdst[2]; /* Dst port */ - uchar udplen[2]; /* Packet length */ - uchar udpsum[2]; /* Checksum including header */ -}; - -struct Icmppkt -{ - uchar d[Easize]; /* ether header */ - uchar s[Easize]; - uchar type[2]; - - uchar vihl; /* ip header */ - uchar tos; - uchar length[2]; - uchar id[2]; - uchar frag[2]; - uchar ttl; - uchar proto; - uchar cksum[2]; - uchar src[Pasize]; - uchar dst[Pasize]; - - uchar icmptype; /* Src port */ - uchar icmpcode; /* Dst port */ - uchar icmpsum[2]; /* Checksum including header */ - - uchar icmpbody[10]; /* Depends on type */ -}; - -struct Ifc -{ - Lock; - Queue* reply; - Filter work[3]; - Filter rate[3]; - ulong rcverr; - ulong txerr; - ulong sumerr; - ulong rxpkt; - ulong txpkt; - uchar ea[Easize]; /* my ether address */ - uchar ipa[Pasize]; /* my ip address, pulled from netdb */ - uchar netgate[Pasize]; /* my ip gateway, pulled from netdb */ - ulong ipaddr; - ulong mask; - ulong cmask; - Ifc *next; /* List of configured interfaces */ -}; - -extern register Mach* m; -extern register User* u; -extern Talarm talarm; - -Conf conf; -Cons cons; -#define MACHP(n) ((Mach*)(MACHADDR+n*BY2PG)) - -#pragma varargck type "D" Device* -#pragma varargck type "T" ulong -#pragma varargck type "I" uchar* -#pragma varargck type "E" uchar* -#pragma varargck type "F" Filter* -#pragma varargck type "G" int //GO.SYSIN DD port/portdat.h echo port/sub.c sed 's/.//' >port/sub.c <<'//GO.SYSIN DD port/sub.c' -#include "all.h" -#include "io.h" - -Filsys* -fsstr(char *p) -{ - Filsys *fs; - - for(fs=filsys; fs->name; fs++) - if(strcmp(fs->name, p) == 0) - return fs; - return 0; -} - -/* - * allocate 'count' contiguous channels - * of type 'type' and return pointer to base - */ -Chan* -chaninit(int type, int count) -{ - Chan *cp, *icp; - int i; - - icp = ialloc(count * sizeof(*icp), 0); - cp = icp; - for(i=0; inext = chans; - chans = cp; - cp->type = type; - cp->chan = cons.chano; - cons.chano++; - strncpy(cp->whoname, "", sizeof(cp->whoname)); - dofilter(&cp->work, C0a, C0b, 1); - dofilter(&cp->rate, C0a, C0b, 1000); - fileinit(cp); - wlock(&cp->reflock); - wunlock(&cp->reflock); - rlock(&cp->reflock); - runlock(&cp->reflock); - cp++; - } - return icp; -} - -void -fileinit(Chan *cp) -{ - File *f, *prev; - Tlock *t; - int h; - -loop: - lock(&flock); - for(h=0; hnext) { - if(f->cp != cp) - continue; - if(prev) { - prev->next = f->next; - f->next = flist[h]; - flist[h] = f; - } - goto out; - } - } - unlock(&flock); - return; - -out: - flist[h] = f->next; - unlock(&flock); - - qlock(f); - if(t = f->tlock) { - t->time = 0; - f->tlock = 0; - } - if(f->open & FREMOV) - doremove(f, 0); - freewp(f->wpath); - f->open = 0; - f->cp = 0; - qunlock(f); - - goto loop; -} - -/* - * returns a locked file structure - */ -File* -filep(Chan *cp, int fid, int flag) -{ - File *f; - int h; - - if(fid == NOF) - return 0; - - h = (long)cp + fid; - if(h < 0) - h = ~h; - h = h % nelem(flist); - -loop: - lock(&flock); - for(f=flist[h]; f; f=f->next) - if(f->fid == fid && f->cp == cp) - goto out; - - if(flag) { - f = newfp(); - if(f) { - f->fid = fid; - f->cp = cp; - f->wpath = 0; - f->tlock = 0; - f->next = flist[h]; - flist[h] = f; - goto out; - } - } - unlock(&flock); - return 0; - -out: - unlock(&flock); - qlock(f); - if(f->fid == fid && f->cp == cp) - return f; - qunlock(f); - goto loop; -} - -/* - * always called with flock locked - */ -File* -newfp(void) -{ - static first; - File *f; - int start, i; - - i = first; - start = i; - do { - f = &files[i]; - i++; - if(i >= conf.nfile) - i = 0; - if(f->cp) - continue; - - first = i; - - return f; - } while(i != start); - - print("out of files\n"); - return 0; -} - -void -freefp(File *fp) -{ - Chan *cp; - File *f, *prev; - int h; - - if(!fp || !(cp = fp->cp)) - return; - - h = (long)cp + fp->fid; - if(h < 0) - h = ~h; - h = h % nelem(flist); - - lock(&flock); - for(prev=0,f=flist[h]; f; prev=f,f=f->next) - if(f == fp) { - if(prev) - prev->next = f->next; - else - flist[h] = f->next; - break; - } - fp->cp = 0; - unlock(&flock); -} - -int -iaccess(File *f, Dentry *d, int m) -{ - - /* uid none gets only other permissions */ - if(f->uid == 0) - goto doother; - - /* - * owner - */ - if(f->uid == d->uid) - if((m<<6) & d->mode) - return 0; - /* - * group membership - */ - if(ingroup(f->uid, d->gid)) - if((m<<3) & d->mode) - return 0; - -doother: - /* - * other - */ - if(m & d->mode) { - if((d->mode & DDIR) && (m == DEXEC)) - return 0; - if(!ingroup(f->uid, 9999)) - return 0; - } - - /* - * various forms of superuser - */ - if(wstatallow) - return 0; - if(duallow != 0 && duallow == f->uid) - if((d->mode & DDIR) && (m == DREAD || m == DEXEC)) - return 0; - - return 1; -} - -Tlock* -tlocked(Iobuf *p, Dentry *d) -{ - Tlock *t, *t1; - long qpath, tim; - Device *dev; - - tim = toytime(); - qpath = d->qid.path; - dev = p->dev; - -again: - t1 = 0; - for(t=tlocks+NTLOCK-1; t>=tlocks; t--) { - if(t->qpath == qpath) - if(t->time >= tim) - if(t->dev == dev) - return nil; /* its locked */ - if(t1 != nil && t->time == 0) - t1 = t; /* remember free lock */ - } - if(t1 == 0) { - // reclaim old locks - lock(&tlocklock); - for(t=tlocks+NTLOCK-1; t>=tlocks; t--) - if(t->time < tim) { - t->time = 0; - t1 = t; - } - unlock(&tlocklock); - } - if(t1) { - lock(&tlocklock); - if(t1->time != 0) { - unlock(&tlocklock); - goto again; - } - t1->dev = dev; - t1->qpath = qpath; - t1->time = tim + TLOCK; - unlock(&tlocklock); - } - /* botch - * out of tlock nodes simulates - * a locked file - */ - return t1; -} - -Wpath* -newwp(void) -{ - static int si = 0; - int i; - Wpath *w, *sw, *ew; - - i = si + 1; - if(i < 0 || i >= conf.nwpath) - i = 0; - si = i; - sw = &wpaths[i]; - ew = &wpaths[conf.nwpath]; - for(w=sw;;) { - w++; - if(w >= ew) - w = &wpaths[0]; - if(w == sw) { - print("out of wpaths\n"); - return 0; - } - if(w->refs) - continue; - lock(&wpathlock); - if(w->refs) { - unlock(&wpathlock); - continue; - } - w->refs = 1; - w->up = 0; - unlock(&wpathlock); - return w; - } - -} - -void -freewp(Wpath *w) -{ - lock(&wpathlock); - for(; w; w=w->up) - w->refs--; - unlock(&wpathlock); -} - -Qid -newqid(Device *dev) -{ - Iobuf *p; - Superb *sb; - Qid qid; - - p = getbuf(dev, superaddr(dev), Bread|Bmod); - if(!p || checktag(p, Tsuper, QPSUPER)) - panic("newqid: super block"); - sb = (Superb*)p->iobuf; - sb->qidgen++; - qid.path = sb->qidgen; - qid.version = 0; - putbuf(p); - return qid; -} - -void -buffree(Device *dev, long addr, int d) -{ - Iobuf *p; - long a; - int i; - - if(!addr) - return; - if(d > 0) { - d--; - p = getbuf(dev, addr, Bread); - if(p) { - for(i=INDPERBUF-1; i>=0; i--) { - a = ((long*)p->iobuf)[i]; - buffree(dev, a, d); - } - putbuf(p); - } - } - /* - * stop outstanding i/o - */ - p = getbuf(dev, addr, Bprobe); - if(p) { - p->flags &= ~(Bmod|Bimm); - putbuf(p); - } - /* - * dont put written worm - * blocks into free list - */ - if(dev->type == Devcw) { - i = cwfree(dev, addr); - if(i) - return; - } - p = getbuf(dev, superaddr(dev), Bread|Bmod); - if(!p || checktag(p, Tsuper, QPSUPER)) - panic("buffree: super block"); - addfree(dev, addr, (Superb*)p->iobuf); - putbuf(p); -} - -long -bufalloc(Device *dev, int tag, long qid, int uid) -{ - Iobuf *bp, *p; - Superb *sb; - long a; - int n; - - p = getbuf(dev, superaddr(dev), Bread|Bmod); - if(!p || checktag(p, Tsuper, QPSUPER)) { - print("bufalloc: super block\n"); - if(p) - putbuf(p); - return 0; - } - sb = (Superb*)p->iobuf; - -loop: - n = --sb->fbuf.nfree; - sb->tfree--; - if(n < 0 || n >= FEPERBUF) { - print("bufalloc: bad freelist\n"); - n = 0; - sb->fbuf.free[0] = 0; - } - a = sb->fbuf.free[n]; - if(n <= 0) { - if(a == 0) { - sb->tfree = 0; - sb->fbuf.nfree = 1; - if(dev->type == Devcw) { - n = uid; - if(n < 0 || n >= nelem(growacct)) - n = 0; - growacct[n]++; - if(cwgrow(dev, sb, uid)) - goto loop; - } - putbuf(p); - print("fs full uid=%d\n", uid); - return 0; - } - bp = getbuf(dev, a, Bread); - if(!bp || checktag(bp, Tfree, QPNONE)) { - if(bp) - putbuf(bp); - putbuf(p); - return 0; - } - sb->fbuf = *(Fbuf*)bp->iobuf; - putbuf(bp); - } - - bp = getbuf(dev, a, Bmod); - memset(bp->iobuf, 0, RBUFSIZE); - settag(bp, tag, qid); - if(tag == Tind1 || tag == Tind2 || tag == Tdir) - bp->flags |= Bimm; - putbuf(bp); - putbuf(p); - return a; -} - -/* - * what are legal characters in a name? - * only disallow control characters. - * a) utf avoids control characters. - * b) '/' may not be the separator - */ -int -checkname(char *n) -{ - int i, c; - - for(i=0; ifbuf.nfree; - if(n < 0 || n > FEPERBUF) - panic("addfree: bad freelist"); - if(n >= FEPERBUF) { - p = getbuf(dev, addr, Bmod|Bimm); - if(p == 0) - panic("addfree: getbuf"); - *(Fbuf*)p->iobuf = sb->fbuf; - settag(p, Tfree, QPNONE); - putbuf(p); - n = 0; - } - sb->fbuf.free[n++] = addr; - sb->fbuf.nfree = n; - sb->tfree++; - if(addr >= sb->fsize) - sb->fsize = addr+1; -} - -int -Cconv(Op *o) -{ - Chan *cp; - char s[20]; - - cp = *(Chan**)o->argp; - sprint(s, "C%d.%.3d", cp->type, cp->chan); - strconv(s, o, o->f1, o->f2); - return sizeof(cp); -} - -int -Dconv(Op *o) -{ - Device *d; - int c, c1; - char s[100]; - - d = *(Device**)o->argp; - if(d == 0) { - sprint(s, "D***"); - goto out; - } - switch(d->type) { - default: - sprint(s, "D%d", d->type); - break; - case Devwren: - c = 'w'; - goto d1; - case Devworm: - c = 'r'; - goto d1; - case Devlworm: - c = 'l'; - goto d1; - d1: - if(d->wren.ctrl == 0 && d->wren.lun == 0) - sprint(s, "%c%d", c, d->wren.targ); - else - sprint(s, "%c%d.%d.%d", c, d->wren.ctrl, d->wren.targ, d->wren.lun); - break; - case Devmcat: - c = '('; - c1 = ')'; - goto d2; - case Devmlev: - c = '['; - c1 = ']'; - d2: - if(d->cat.first == d->cat.last) - sprint(s, "%c%D%c", c, d->cat.first, c1); - else - if(d->cat.first->link == d->cat.last) - sprint(s, "%c%D%D%c", c, d->cat.first, d->cat.last, c1); - else - sprint(s, "%c%D-%D%c", c, d->cat.first, d->cat.last, c1); - break; - case Devro: - sprint(s, "o%D%D", d->ro.parent->cw.c, d->ro.parent->cw.w); - break; - case Devcw: - sprint(s, "c%D%D", d->cw.c, d->cw.w); - break; - case Devjuke: - sprint(s, "j%D%D", d->j.j, d->j.m); - break; - case Devpart: - sprint(s, "p%ld.%ld", d->part.base, d->part.size); - break; - case Devswab: - sprint(s, "x%D", d->swab.d); - break; - } -out: - strconv(s, o, o->f1, o->f2); - return sizeof(d); -} - -int -Fconv(Op *o) -{ - Filter* a; - char s[30]; - - a = *(Filter**)o->argp; - - sprint(s, "%lud", fdf(a->filter, a->c3*a->c1)); - strconv(s, o, o->f1, o->f2); - return sizeof(a); -} - -int -Gconv(Op *o) -{ - int t; - char s[20]; - - t = *(int*)o->argp; - strcpy(s, ""); - if(t >= 0 && t < MAXTAG) - sprint(s, "%s", tagnames[t]); - strconv(s, o, o->f1, o->f2); - return sizeof(t); -} - -int -Econv(Op *o) -{ - char s[64]; - uchar *p; - - p = *((uchar**)o->argp); - sprint(s, "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux", - p[0], p[1], p[2], p[3], p[4], p[5]); - strconv(s, o, o->f1, o->f2); - return sizeof(uchar*); -} - -int -Iconv(Op *o) -{ - char s[64]; - uchar *p; - - p = *((uchar**)o->argp); - sprint(s, "%d.%d.%d.%d", - p[0], p[1], p[2], p[3]); - strconv(s, o, o->f1, o->f2); - return sizeof(uchar*); -} - -int -Nconv(Op *o) -{ - char s[64]; - uchar *p; - long n; - - p = *((uchar**)o->argp); - n = (p[0]<<8) | p[1]; - if(!(o->f3 & FSHORT)) - n = (n<<16) | (p[2]<<8) | p[3]; - sprint(s, "%lud", n); - strconv(s, o, o->f1, o->f2); - return sizeof(uchar*); -} - -void -formatinit(void) -{ - - fmtinstall('C', Cconv); /* print channels */ - fmtinstall('D', Dconv); /* print devices */ - fmtinstall('F', Fconv); /* print filters */ - fmtinstall('G', Gconv); /* print tags */ - fmtinstall('T', Tconv); /* print times */ - fmtinstall('E', Econv); /* print ether addresses */ - fmtinstall('I', Iconv); /* print ip addresses */ - fmtinstall('N', Nconv); /* print network order integers */ -} - -int -nzip(uchar ip[Pasize]) -{ - if(ip[0] || ip[1] || ip[2] || ip[3]) - return 1; - return 0; -} - -void -rootream(Device *dev, long addr) -{ - Iobuf *p; - Dentry *d; - - p = getbuf(dev, addr, Bmod|Bimm); - memset(p->iobuf, 0, RBUFSIZE); - settag(p, Tdir, QPROOT); - d = getdir(p, 0); - strcpy(d->name, "/"); - d->uid = -1; - d->gid = -1; - d->mode = DALLOC | DDIR | - ((DREAD|DEXEC) << 6) | - ((DREAD|DEXEC) << 3) | - ((DREAD|DEXEC) << 0); - d->qid = QID(QPROOT|QPDIR,0); - d->atime = time(); - d->mtime = d->atime; - d->wuid = 0; - putbuf(p); -} - -void -superream(Device *dev, long addr) -{ - Iobuf *p; - Superb *s; - long i; - - p = getbuf(dev, addr, Bmod|Bimm); - memset(p->iobuf, 0, RBUFSIZE); - settag(p, Tsuper, QPSUPER); - - s = (Superb*)p->iobuf; - s->fstart = 2; - s->fsize = devsize(dev); - s->fbuf.nfree = 1; - s->qidgen = 10; - for(i=s->fsize-1; i>=addr+2; i--) - addfree(dev, i, s); - putbuf(p); -} - -struct -{ - Lock; - Msgbuf *smsgbuf; - Msgbuf *lmsgbuf; -} msgalloc; - -void -mbinit(void) -{ - Msgbuf *mb; - Rabuf *rb; - int i; - - lock(&msgalloc); - unlock(&msgalloc); - msgalloc.lmsgbuf = 0; - msgalloc.smsgbuf = 0; - for(i=0; ixdata = ialloc(LARGEBUF+256, 256); - else - mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE); - mb->flags = LARGE; - mbfree(mb); - cons.nlarge++; - } - for(i=0; ixdata = ialloc(SMALLBUF+256, 256); - else - mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE); - mb->flags = 0; - mbfree(mb); - cons.nsmall++; - } - memset(mballocs, 0, sizeof(mballocs)); - - lock(&rabuflock); - unlock(&rabuflock); - rabuffree = 0; - for(i=0; i<1000; i++) { - rb = ialloc(sizeof(*rb), 0); - rb->link = rabuffree; - rabuffree = rb; - } -} - -Msgbuf* -mballoc(int count, Chan *cp, int category) -{ - Msgbuf *mb; - - ilock(&msgalloc); - if(count > SMALLBUF) { - if(count > LARGEBUF) - panic("msgbuf count"); - mb = msgalloc.lmsgbuf; - if(mb == 0) { - mb = ialloc(sizeof(Msgbuf), 0); - if(1) - mb->xdata = ialloc(LARGEBUF+256, 256); - else - mb->xdata = ialloc(LARGEBUF+OFFMSG, LINESIZE); - cons.nlarge++; - } else - msgalloc.lmsgbuf = mb->next; - mb->flags = LARGE; - } else { - mb = msgalloc.smsgbuf; - if(mb == 0) { - mb = ialloc(sizeof(Msgbuf), 0); - if(1) - mb->xdata = ialloc(SMALLBUF+256, 256); - else - mb->xdata = ialloc(SMALLBUF+OFFMSG, LINESIZE); - cons.nsmall++; - } else - msgalloc.smsgbuf = mb->next; - mb->flags = 0; - } - mballocs[category]++; - iunlock(&msgalloc); - mb->count = count; - mb->chan = cp; - mb->next = 0; - mb->param = 0; - mb->category = category; - if(1) - mb->data = mb->xdata+256; - else - mb->data = mb->xdata+OFFMSG; - return mb; -} - -void -mbfree(Msgbuf *mb) -{ - if(mb->flags & FREE) - panic("mbfree already free"); - - ilock(&msgalloc); - mballocs[mb->category]--; - mb->flags |= FREE; - if(mb->flags & LARGE) { - mb->next = msgalloc.lmsgbuf; - msgalloc.lmsgbuf = mb; - } else { - mb->next = msgalloc.smsgbuf; - msgalloc.smsgbuf = mb; - } - mb->data = 0; - iunlock(&msgalloc); -} - -/* - * returns 1 if n is prime - * used for adjusting lengths - * of hashing things. - * there is no need to be clever - */ -int -prime(long n) -{ - long i; - - if((n%2) == 0) - return 0; - for(i=3;; i+=2) { - if((n%i) == 0) - return 0; - if(i*i >= n) - return 1; - } -} - -char* -getwd(char *word, char *line) -{ - int c, n; - - while(*line == ' ') - line++; - for(n=0; n<80; n++) { - c = *line; - if(c == ' ' || c == 0 || c == '\n') - break; - line++; - *word++ = c; - } - *word = 0; - return line; -} - -void -hexdump(void *a, int n) -{ - char s1[30], s2[4]; - uchar *p; - int i; - - p = a; - s1[0] = 0; - for(i=0; icount; - if(c > 0) { - i = q->loc; - a = q->args[i]; - i++; - if(i >= q->size) - i = 0; - q->loc = i; - q->count = c-1; - p = q->whead; - if(p) { - q->whead = p->qnext; - if(q->whead == 0) - q->wtail = 0; - ready(p); - } - unlock(q); - return a; - } - p = q->rtail; - if(p == 0) - q->rhead = u; - else - p->qnext = u; - q->rtail = u; - u->qnext = 0; - s = splhi(); - u->state = Recving; - unlock(q); - sched(); - splx(s); - } - return 0; -} - -void -send(Queue *q, void *a) -{ - User *p; - int i, c; - long s; - - if(q == 0) - panic("send null q"); - for(;;) { - lock(q); - c = q->count; - if(c < q->size) { - i = q->loc + c; - if(i >= q->size) - i -= q->size; - q->args[i] = a; - q->count = c+1; - p = q->rhead; - if(p) { - q->rhead = p->qnext; - if(q->rhead == 0) - q->rtail = 0; - ready(p); - } - unlock(q); - return; - } - p = q->wtail; - if(p == 0) - q->whead = u; - else - p->qnext = u; - q->wtail = u; - u->qnext = 0; - s = splhi(); - u->state = Sending; - unlock(q); - sched(); - splx(s); - } -} - -Queue* -newqueue(int size) -{ - Queue *q; - - q = ialloc(sizeof(Queue) + (size-1)*sizeof(void*), 0); - q->size = size; - lock(q); - unlock(q); - return q; -} - -no(void*) -{ - return 0; -} - -int -devread(Device *d, long b, void *c) -{ - int e; - -loop: - switch(d->type) - { - case Devcw: - return cwread(d, b, c); - - case Devjuke: - d = d->j.m; - goto loop; - - case Devro: - return roread(d, b, c); - - case Devwren: - return wrenread(d, b, c); - case Devide: - return ideread(d, b, c); - - case Devworm: - case Devlworm: - return wormread(d, b, c); - - case Devfworm: - return fwormread(d, b, c); - - case Devmcat: - return mcatread(d, b, c); - - case Devmlev: - return mlevread(d, b, c); - - case Devpart: - return partread(d, b, c); - - case Devswab: - e = devread(d->swab.d, b, c); - if(e == 0) - swab(c, 0); - return e; - } - panic("illegal device in read: %D %ld", d, b); - return 1; -} - -int -devwrite(Device *d, long b, void *c) -{ - int e; - -loop: - switch(d->type) - { - case Devcw: - return cwwrite(d, b, c); - - case Devjuke: - d = d->j.m; - goto loop; - - case Devro: - print("write to ro device %D(%ld)\n", d, b); - return 1; - - case Devwren: - return wrenwrite(d, b, c); - case Devide: - return idewrite(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 Devpart: - return partwrite(d, b, c); - - case Devswab: - swab(c, 1); - e = devwrite(d->swab.d, b, c); - swab(c, 0); - return e; - } - panic("illegal device in write: %D %ld", d, b); - return 1; -} - -long -devsize(Device *d) -{ - -loop: - switch(d->type) - { - case Devcw: - case Devro: - return cwsize(d); - - case Devjuke: - d = d->j.m; - goto loop; - - case Devwren: - return wrensize(d); - case Devide: - return atasize(d); - - case Devworm: - case Devlworm: - return wormsize(d); - - case Devfworm: - return fwormsize(d); - - case Devmcat: - return mcatsize(d); - - case Devmlev: - return mlevsize(d); - - case Devpart: - return partsize(d); - - case Devswab: - d = d->swab.d; - goto loop; - } - panic("illegal device in dev_size: %D", d); - return 0; -} - -long -superaddr(Device *d) -{ - -loop: - switch(d->type) { - default: - return SUPER_ADDR; - - case Devcw: - case Devro: - return cwsaddr(d); - - case Devswab: - d = d->swab.d; - goto loop; - } -} - -long -getraddr(Device *d) -{ - -loop: - switch(d->type) { - default: - return ROOT_ADDR; - - case Devcw: - case Devro: - return cwraddr(d); - - case Devswab: - d = d->swab.d; - goto loop; - } -} - -void -devream(Device *d, int top) -{ - Device *l; - -loop: - print(" devream: %D %d\n", d, top); - switch(d->type) { - default: - print("ream: unknown dev type %D\n", d); - return; - - case Devcw: - devream(d->cw.w, 0); - devream(d->cw.c, 0); - if(top) { - wlock(&mainlock); - cwream(d); - wunlock(&mainlock); - } - devinit(d); - return; - - case Devfworm: - devream(d->fw.fw, 0); - fwormream(d); - break; - - case Devpart: - devream(d->part.d, 0); - break; - - case Devmlev: - case Devmcat: - for(l=d->cat.first; l; l=l->link) - devream(l, 0); - break; - - case Devjuke: - case Devworm: - case Devlworm: - case Devwren: - break; - - case Devswab: - d = d->swab.d; - goto loop; - } - devinit(d); - if(top) { - wlock(&mainlock); - rootream(d, ROOT_ADDR); - superream(d, SUPER_ADDR); - wunlock(&mainlock); - } -} - -void -devrecover(Device *d) -{ - -loop: - print("recover: %D\n", d); - switch(d->type) { - default: - print("recover: unknown dev type %D\n", d); - return; - - case Devcw: - wlock(&mainlock); /* recover */ - cwrecover(d); - wunlock(&mainlock); - break; - - case Devswab: - d = d->swab.d; - goto loop; - } -} - -void -devinit(Device *d) -{ - -loop: - if(d->init) - return; - d->init = 1; - print(" devinit %D\n", d); - switch(d->type) { - default: - print("devinit unknown device %D\n", d); - return; - - case Devro: - cwinit(d->ro.parent); - break; - - case Devcw: - cwinit(d); - break; - - case Devjuke: - jukeinit(d); - break; - - case Devwren: - wreninit(d); - break; - - case Devide: - ideinit(d); - case Devworm: - case Devlworm: - break; - - case Devfworm: - fworminit(d); - break; - - case Devmcat: - mcatinit(d); - break; - - case Devmlev: - mlevinit(d); - break; - - case Devpart: - partinit(d); - break; - - case Devswab: - d = d->swab.d; - goto loop; - } -} - -void -swab2(void *c) -{ - uchar *p; - int t; - - p = c; - - t = p[0]; - p[0] = p[1]; - p[1] = t; -} - -void -swab4(void *c) -{ - uchar *p; - int t; - - p = c; - - t = p[0]; - p[0] = p[3]; - p[3] = t; - - t = p[1]; - p[1] = p[2]; - p[2] = t; -} - -/* - * swab a block - * flag = 0 -- convert from foreign to native - * flag = 1 -- convert from native to foreign - */ -void -swab(void *c, int flag) -{ - uchar *p; - Tag *t; - int i, j; - Dentry *d; - Cache *h; - Bucket *b; - Superb *s; - Fbuf *f; - long *l; - - /* swab the tag */ - p = (uchar*)c; - t = (Tag*)(p + BUFSIZE); - if(!flag) { - swab2(&t->pad); - swab2(&t->tag); - swab4(&t->path); - } - - /* swab each block type */ - switch(t->tag) { - - default: - print("no swab for tag=%G rw=%d\n", t->tag, flag); - for(j=0; j<16; j++) - print(" %.2x", p[BUFSIZE+j]); - print("\n"); - for(i=0; i<16; i++) { - print("%.4x", i*16); - for(j=0; j<16; j++) - print(" %.2x", p[i*16+j]); - print("\n"); - } - break; - - case Tsuper: - s = (Superb*)p; - swab4(&s->fbuf.nfree); - for(i=0; ifbuf.free[i]); - swab4(&s->fstart); - swab4(&s->fsize); - swab4(&s->tfree); - swab4(&s->qidgen); - swab4(&s->cwraddr); - swab4(&s->roraddr); - swab4(&s->last); - swab4(&s->next); - break; - - case Tdir: - for(i=0; iuid); - swab2(&d->gid); - swab2(&d->mode); - swab2(&d->wuid); - swab4(&d->qid.path); - swab4(&d->qid.version); - swab4(&d->size); - for(j=0; jdblock[j]); - swab4(&d->iblock); - swab4(&d->diblock); - swab4(&d->atime); - swab4(&d->mtime); - } - break; - - case Tind1: - case Tind2: - l = (long*)p; - for(i=0; infree); - for(i=0; ifree[i]); - break; - - case Tbuck: - for(i=0; iagegen); - for(j=0; jentry[j].age); - swab2(&b->entry[j].state); - swab4(&b->entry[j].waddr); - } - } - break; - - case Tcache: - h = (Cache*)p; - swab4(&h->maddr); - swab4(&h->msize); - swab4(&h->caddr); - swab4(&h->csize); - swab4(&h->fsize); - swab4(&h->wsize); - swab4(&h->wmax); - swab4(&h->sbaddr); - swab4(&h->cwraddr); - swab4(&h->roraddr); - swab4(&h->toytime); - swab4(&h->time); - break; - - case Tnone: // unitialized - case Tfile: // someone elses problem - case Tvirgo: // bit map -- all bytes - case Tconfig: // configuration string -- all bytes - break; - } - - /* swab the tag */ - if(flag) { - swab2(&t->pad); - swab2(&t->tag); - swab4(&t->path); - } -} //GO.SYSIN DD port/sub.c --upas-aucgxwhjpzzokbfwaidrjufnxa--