4700: # 4701: /* 4702: */ 4703: 4704: #include "../param.h" 4705: #include "../user.h" 4706: #include "../buf.h" 4707: #include "../conf.h" 4708: #include "../systm.h" 4709: #include "../proc.h" 4710: #include "../seg.h" 4711: 4712: /* 4713: * This is the set of buffers proper, whose heads 4714: * were declared in buf.h. There can exist buffer 4715: * headers not pointing here that are used purely 4716: * as arguments to the I/O routines to describe 4717: * I/O to be done-- e.g. swbuf, just below, for 4718: * swapping. 4719: */ 4720: char buffers[NBUF][514]; 4721: struct buf swbuf; 4722: 4723: /* 4724: * Declarations of the tables for the magtape devices; 4725: * see bdwrite. 4726: */ 4727: int tmtab; 4728: int httab; 4729: 4730: /* 4731: * The following several routines allocate and free 4732: * buffers with various side effects. In general the 4733: * arguments to an allocate routine are a device and 4734: * a block number, and the value is a pointer to 4735: * to the buffer header; the buffer is marked "busy" 4736: * so that no on else can touch it. If the block was 4737: * already in core, no I/O need be done; if it is 4738: * already busy, the process waits until it becomes free. 4739: * The following routines allocate a buffer: 4740: * getblk 4741: * bread 4742: * breada 4743: * Eventually the buffer must be released, possibly with the 4744: * side effect of writing it out, by using one of 4745: * bwrite 4746: * bdwrite 4747: * bawrite 4748: * brelse 4749: */ 4750: 4751: /* 4752: * Read in (if necessary) the block and return a buffer pointer. 4753: */ 4754: bread(dev, blkno) 4755: { 4756: register struct buf *rbp; 4757: 4758: rbp = getblk(dev, blkno); 4759: if (rbp->b_flags&B_DONE) 4760: return(rbp); 4761: rbp->b_flags =| B_READ; 4762: rbp->b_wcount = -256; 4763: (*bdevsw[dev.d_major].d_strategy)(rbp); 4764: iowait(rbp); 4765: return(rbp); 4766: } 4767: /* --------------------------- */ 4768: 4769: /* 4770: * Read in the block, like bread, but also start I/O on the 4771: * read-ahead block (which is not allocated to the caller) 4772: */ 4773: breada(adev, blkno, rablkno) 4774: { 4775: register struct buf *rbp, *rabp; 4776: register int dev; 4777: 4778: dev = adev; 4779: rbp = 0; 4780: if (!incore(dev, blkno)) { 4781: rbp = getblk(dev, blkno); 4782: if ((rbp->b_flags&B_DONE) == 0) { 4783: rbp->b_flags =| B_READ; 4784: rbp->b_wcount = -256; 4785: (*bdevsw[adev.d_major].d_strategy)(rbp); 4786: } 4787: } 4788: if (rablkno && !incore(dev, rablkno)) { 4789: rabp = getblk(dev, rablkno); 4790: if (rabp->b_flags & B_DONE) 4791: brelse(rabp); 4792: else { 4793: rabp->b_flags =| B_READ|B_ASYNC; 4794: rabp->b_wcount = -256; 4795: (*bdevsw[adev.d_major].d_strategy)(rabp); 4796: } 4797: } 4798: if (rbp==0) 4799: return(bread(dev, blkno)); 4800: iowait(rbp); 4801: return(rbp); 4802: } 4803: /* --------------------------- */ 4804: 4805: /* 4806: * Write the buffer, waiting for completion. 4807: * Then release the buffer. 4808: */ 4809: bwrite(bp) 4810: struct buf *bp; 4811: { 4812: register struct buf *rbp; 4813: register flag; 4814: 4815: rbp = bp; 4816: flag = rbp->b_flags; 4817: rbp->b_flags =& ~(B_READ | B_DONE | B_ERROR | B_DELWRI); 4818: rbp->b_wcount = -256; 4819: (*bdevsw[rbp->b_dev.d_major].d_strategy)(rbp); 4820: if ((flag&B_ASYNC) == 0) { 4821: iowait(rbp); 4822: brelse(rbp); 4823: } else if ((flag&B_DELWRI)==0) 4824: geterror(rbp); 4825: } 4826: /* --------------------------- */ 4827: 4828: /* 4829: * Release the buffer, marking it so that if it is grabbed 4830: * for another purpose it will be written out before being 4831: * given up (e.g. when writing a partial block where it is 4832: * assumed that another write for the same block will soon follow). 4833: * This can't be done for magtape, since writes must be done 4834: * in the same order as requested. 4835: */ 4836: bdwrite(bp) 4837: struct buf *bp; 4838: { 4839: register struct buf *rbp; 4840: register struct devtab *dp; 4841: 4842: rbp = bp; 4843: dp = bdevsw[rbp->b_dev.d_major].d_tab; 4844: if (dp == &tmtab || dp == &httab) 4845: bawrite(rbp); 4846: else { 4847: rbp->b_flags =| B_DELWRI | B_DONE; 4848: brelse(rbp); 4849: } 4850: } 4851: /* --------------------------- */ 4852: 4853: /* 4854: * Release the buffer, start I/O on it, but don't wait for completion. 4855: */ 4856: bawrite(bp) 4857: struct buf *bp; 4858: { 4859: register struct buf *rbp; 4860: 4861: rbp = bp; 4862: rbp->b_flags =| B_ASYNC; 4863: bwrite(rbp); 4864: } 4865: /* --------------------------- */ 4866: 4867: /* release the buffer, with no I/O implied. 4868: */ 4869: brelse(bp) 4870: struct buf *bp; 4871: { 4872: register struct buf *rbp, **backp; 4873: register int sps; 4874: 4875: rbp = bp; 4876: if (rbp->b_flags&B_WANTED) 4877: wakeup(rbp); 4878: if (bfreelist.b_flags&B_WANTED) { 4879: bfreelist.b_flags =& ~B_WANTED; 4880: wakeup(&bfreelist); 4881: } 4882: if (rbp->b_flags&B_ERROR) 4883: rbp->b_dev.d_minor = -1; /* no assoc. on error */ 4884: backp = &bfreelist.av_back; 4885: sps = PS->integ; 4886: spl6(); 4887: rbp->b_flags =& ~(B_WANTED|B_BUSY|B_ASYNC); 4888: (*backp)->av_forw = rbp; 4889: rbp->av_back = *backp; 4890: *backp = rbp; 4891: rbp->av_forw = &bfreelist; 4892: PS->integ = sps; 4893: } 4894: /* --------------------------- */ 4895: 4896: /* See if the block is associated with some buffer 4897: * (mainly to avoid getting hung up on a wait in breada) 4898: */ 4899: incore(adev, blkno) 4900: { 4901: register int dev; 4902: register struct buf *bp; 4903: register struct devtab *dp; 4904: 4905: dev = adev; 4906: dp = bdevsw[adev.d_major].d_tab; 4907: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) 4908: if (bp->b_blkno==blkno && bp->b_dev==dev) 4909: return(bp); 4910: return(0); 4911: } 4912: /* --------------------------- */ 4913: 4914: /* Assign a buffer for the given block. If the appropriate 4915: * block is already associated, return it; otherwise search 4916: * for the oldest non-busy buffer and reassign it. 4917: * When a 512-byte area is wanted for some random reason 4918: * (e.g. during exec, for the user arglist) getblk can be called 4919: * with device NODEV to avoid unwanted associativity. 4920: */ 4921: getblk(dev, blkno) 4922: { 4923: register struct buf *bp; 4924: register struct devtab *dp; 4925: extern lbolt; 4926: 4927: if(dev.d_major >= nblkdev) 4928: panic("blkdev"); 4929: 4930: loop: 4931: if (dev < 0) 4932: dp = &bfreelist; 4933: else { 4934: dp = bdevsw[dev.d_major].d_tab; 4935: if(dp == NULL) 4936: panic("devtab"); 4937: for (bp=dp->b_forw; bp != dp; bp = bp->b_forw) { 4938: if (bp->b_blkno!=blkno || bp->b_dev!=dev) 4939: continue; 4940: spl6(); 4941: if (bp->b_flags&B_BUSY) { 4942: bp->b_flags =| B_WANTED; 4943: sleep(bp, PRIBIO); 4944: spl0(); 4945: goto loop; 4946: } 4947: spl0(); 4948: notavail(bp); 4949: return(bp); 4950: } 4951: } 4952: spl6(); 4953: if (bfreelist.av_forw == &bfreelist) { 4954: bfreelist.b_flags =| B_WANTED; 4955: sleep(&bfreelist, PRIBIO); 4956: spl0(); 4957: goto loop; 4958: } 4959: spl0(); 4960: notavail(bp = bfreelist.av_forw); 4961: if (bp->b_flags & B_DELWRI) { 4962: bp->b_flags =| B_ASYNC; 4963: bwrite(bp); 4964: goto loop; 4965: } 4966: bp->b_flags = B_BUSY | B_RELOC; 4967: bp->b_back->b_forw = bp->b_forw; 4968: bp->b_forw->b_back = bp->b_back; 4969: bp->b_forw = dp->b_forw; 4970: bp->b_back = dp; 4971: dp->b_forw->b_back = bp; 4972: dp->b_forw = bp; 4973: bp->b_dev = dev; 4974: bp->b_blkno = blkno; 4975: return(bp); 4976: } 4977: /* --------------------------- */ 4978: 4979: /* Wait for I/O completion on the buffer; return errors 4980: * to the user. 4981: */ 4982: iowait(bp) 4983: struct buf *bp; 4984: { 4985: register struct buf *rbp; 4986: 4987: rbp = bp; 4988: spl6(); 4989: while ((rbp->b_flags&B_DONE)==0) 4990: sleep(rbp, PRIBIO); 4991: spl0(); 4992: geterror(rbp); 4993: } 4994: /* --------------------------- */ 4995: 4996: /* Unlink a buffer from the available list and mark it busy. 4997: * (internal interface) 4998: */ 4999: notavail(bp) 5000: struct buf *bp; 5001: { 5002: register struct buf *rbp; 5003: register int sps; 5004: 5005: rbp = bp; 5006: sps = PS->integ; 5007: spl6(); 5008: rbp->av_back->av_forw = rbp->av_forw; 5009: rbp->av_forw->av_back = rbp->av_back; 5010: rbp->b_flags =| B_BUSY; 5011: PS->integ = sps; 5012: } 5013: /* --------------------------- */ 5014: 5015: /* Mark I/O complete on a buffer, release it if I/O is asynchronous, 5016: * and wake up anyone waiting for it. 5017: */ 5018: iodone(bp) 5019: struct buf *bp; 5020: { 5021: register struct buf *rbp; 5022: 5023: rbp = bp; 5024: if(rbp->b_flags&B_MAP) 5025: mapfree(rbp); 5026: rbp->b_flags =| B_DONE; 5027: if (rbp->b_flags&B_ASYNC) 5028: brelse(rbp); 5029: else { 5030: rbp->b_flags =& ~B_WANTED; 5031: wakeup(rbp); 5032: } 5033: } 5034: /* --------------------------- */ 5035: 5036: /* Zero the core associated with a buffer. 5037: */ 5038: clrbuf(bp) 5039: int *bp; 5040: { 5041: register *p; 5042: register c; 5043: 5044: p = bp->b_addr; 5045: c = 256; 5046: do 5047: *p++ = 0; 5048: while (--c); 5049: } 5050: /* --------------------------- */ 5051: 5052: /* Initialize the buffer I/O system by freeing 5053: * all buffers and setting all device buffer lists to empty. 5054: */ 5055: binit() 5056: { 5057: register struct buf *bp; 5058: register struct devtab *dp; 5059: register int i; 5060: struct bdevsw *bdp; 5061: 5062: bfreelist.b_forw = bfreelist.b_back = 5063: bfreelist.av_forw = bfreelist.av_back = &bfreelist; 5064: for (i=0; i<NBUF; i++) { 5065: bp = &buf[i]; 5066: bp->b_dev = -1; 5067: bp->b_addr = buffers[i]; 5068: bp->b_back = &bfreelist; 5069: bp->b_forw = bfreelist.b_forw; 5070: bfreelist.b_forw->b_back = bp; 5071: bfreelist.b_forw = bp; 5072: bp->b_flags = B_BUSY; 5073: brelse(bp); 5074: } 5075: i = 0; 5076: for (bdp = bdevsw; bdp->d_open; bdp++) { 5077: dp = bdp->d_tab; 5078: if(dp) { 5079: dp->b_forw = dp; 5080: dp->b_back = dp; 5081: } 5082: i++; 5083: } 5084: nblkdev = i; 5085: } 5086: /* --------------------------- */ 5087: 5088: /* Device start routine for disks 5089: * and other devices that have the register 5090: * layout of the older DEC controllers (RF, RK, RP, TM) 5091: */ 5092: #define IENABLE 0100 5093: #define WCOM 02 5094: #define RCOM 04 5095: #define GO 01 5096: devstart(bp, devloc, devblk, hbcom) 5097: struct buf *bp; 5098: int *devloc; 5099: { 5100: register int *dp; 5101: register struct buf *rbp; 5102: register int com; 5103: 5104: dp = devloc; 5105: rbp = bp; 5106: *dp = devblk; /* block address */ 5107: *--dp = rbp->b_addr; /* buffer address */ 5108: *--dp = rbp->b_wcount; /* word count */ 5109: com = (hbcom<<8) | IENABLE | GO | 5110: ((rbp->b_xmem & 03) << 4); 5111: if (rbp->b_flags&B_READ) /* command + x-mem */ 5112: com =| RCOM; 5113: else 5114: com =| WCOM; 5115: *--dp = com; 5116: } 5117: /* --------------------------- */ 5118: 5119: /* startup routine for RH controllers. */ 5120: #define RHWCOM 060 5121: #define RHRCOM 070 5122: 5123: rhstart(bp, devloc, devblk, abae) 5124: struct buf *bp; 5125: int *devloc, *abae; 5126: { 5127: register int *dp; 5128: register struct buf *rbp; 5129: register int com; 5130: 5131: dp = devloc; 5132: rbp = bp; 5133: if(cputype == 70) 5134: *abae = rbp->b_xmem; 5135: *dp = devblk; /* block address */ 5136: *--dp = rbp->b_addr; /* buffer address */ 5137: *--dp = rbp->b_wcount; /* word count */ 5138: com = IENABLE | GO | 5139: ((rbp->b_xmem & 03) << 8); 5140: if (rbp->b_flags&B_READ) /* command + x-mem */ 5141: com =| RHRCOM; else 5142: com =| RHWCOM; 5143: *--dp = com; 5144: } 5145: /* --------------------------- */ 5146: 5147: /* 5148: * 11/70 routine to allocate the 5149: * UNIBUS map and initialize for 5150: * a unibus device. 5151: * The code here and in 5152: * rhstart assumes that an rh on an 11/70 5153: * is an rh70 and contains 22 bit addressing. 5154: */ 5155: int maplock; 5156: mapalloc(abp) 5157: struct buf *abp; 5158: { 5159: register i, a; 5160: register struct buf *bp; 5161: 5162: if(cputype != 70) 5163: return; 5164: spl6(); 5165: while(maplock&B_BUSY) { 5166: maplock =| B_WANTED; 5167: sleep(&maplock, PSWP); 5168: } 5169: maplock =| B_BUSY; 5170: spl0(); 5171: bp = abp; 5172: bp->b_flags =| B_MAP; 5173: a = bp->b_xmem; 5174: for(i=16; i<32; i=+2) 5175: UBMAP->r[i+1] = a; 5176: for(a++; i<48; i=+2) 5177: UBMAP->r[i+1] = a; 5178: bp->b_xmem = 1; 5179: } 5180: /* --------------------------- */ 5181: 5182: mapfree(bp) 5183: struct buf *bp; 5184: { 5185: 5186: bp->b_flags =& ~B_MAP; 5187: if(maplock&B_WANTED) 5188: wakeup(&maplock); 5189: maplock = 0; 5190: } 5191: /* --------------------------- */ 5192: 5193: /* 5194: * swap I/O 5195: */ 5196: swap(blkno, coreaddr, count, rdflg) 5197: { 5198: register int *fp; 5199: 5200: fp = &swbuf.b_flags; 5201: spl6(); 5202: while (*fp&B_BUSY) { 5203: *fp =| B_WANTED; 5204: sleep(fp, PSWP); 5205: } 5206: *fp = B_BUSY | B_PHYS | rdflg; 5207: swbuf.b_dev = swapdev; 5208: swbuf.b_wcount = - (count<<5); /* 32 w/block */ 5209: swbuf.b_blkno = blkno; 5210: swbuf.b_addr = coreaddr<<6; /* 64 b/block */ 5211: swbuf.b_xmem = (coreaddr>>10) & 077; 5212: (*bdevsw[swapdev>>8].d_strategy)(&swbuf); 5213: spl6(); 5214: while((*fp&B_DONE)==0) 5215: sleep(fp, PSWP); 5216: if (*fp&B_WANTED) 5217: wakeup(fp); 5218: spl0(); 5219: *fp =& ~(B_BUSY|B_WANTED); 5220: return(*fp&B_ERROR); 5221: } 5222: /* --------------------------- */ 5223: 5224: /* 5225: * make sure all write-behind blocks 5226: * on dev (or NODEV for all) 5227: * are flushed out. 5228: * (from umount and update) 5229: */ 5230: bflush(dev) 5231: { 5232: register struct buf *bp; 5233: 5234: loop: 5235: spl6(); 5236: for (bp = bfreelist.av_forw; bp != &bfreelist; bp = bp->av_forw) { 5237: 5238: if (bp->b_flags&B_DELWRI && (dev == NODEV||dev==bp->b_dev)) { 5239: bp->b_flags =| B_ASYNC; 5240: notavail(bp); 5241: bwrite(bp); 5242: goto loop; 5243: } 5244: } 5245: spl0(); 5246: } 5247: /* --------------------------- */ 5248: 5249: /* 5250: * Raw I/O. The arguments are 5251: * The strategy routine for the device 5252: * A buffer, which will always be a special buffer 5253: * header owned exclusively by the device for this purpose 5254: * The device number 5255: * Read/write flag 5256: * Essentially all the work is computing physical addresses and 5257: * validating them. 5258: */ 5259: physio(strat, abp, dev, rw) 5260: struct buf *abp; 5261: int (*strat)(); 5262: { 5263: register struct buf *bp; 5264: register char *base; 5265: register int nb; 5266: int ts; 5267: 5268: bp = abp; 5269: base = u.u_base; 5270: /* 5271: * Check odd base, odd count, and address wraparound 5272: */ 5273: if (base&01 || u.u_count&01 || base>=base+u.u_count) 5274: goto bad; 5275: ts = (u.u_tsize+127) & ~0177; 5276: if (u.u_sep) 5277: ts = 0; 5278: nb = (base>>6) & 01777; 5279: /* 5280: * Check overlap with text. (ts and nb now 5281: * in 64-byte clicks) 5282: */ 5283: if (nb < ts) 5284: goto bad; 5285: /* 5286: * Check that transfer is either entirely in the 5287: * data or in the stack: that is, either 5288: * the end is in the data or the start is in the stack 5289: * (remember wraparound was already checked). 5290: */ 5291: if ((((base+u.u_count)>>6)&01777) >= ts+u.u_dsize 5292: && nb < 1024-u.u_ssize) 5293: goto bad; 5294: spl6(); 5295: while (bp->b_flags&B_BUSY) { 5296: bp->b_flags =| B_WANTED; 5297: sleep(bp, PRIBIO); 5298: } 5299: bp->b_flags = B_BUSY | B_PHYS | rw; 5300: bp->b_dev = dev; 5301: /* 5302: * Compute physical address by simulating 5303: * the segmentation hardware. 5304: */ 5305: bp->b_addr = base&077; 5306: base = (u.u_sep? UDSA: UISA)->r[nb>>7] + (nb&0177); 5307: bp->b_addr =+ base<<6; 5308: bp->b_xmem = (base>>10) & 077; 5309: bp->b_blkno = lshift(u.u_offset, -9); 5310: bp->b_wcount = -((u.u_count>>1) & 077777); 5311: bp->b_error = 0; 5312: u.u_procp->p_flag =| SLOCK; 5313: (*strat)(bp); 5314: spl6(); 5315: while ((bp->b_flags&B_DONE) == 0) 5316: sleep(bp, PRIBIO); 5317: u.u_procp->p_flag =& ~SLOCK; 5318: if (bp->b_flags&B_WANTED) 5319: wakeup(bp); 5320: spl0(); 5321: bp->b_flags =& ~(B_BUSY|B_WANTED); 5322: u.u_count = (-bp->b_resid)<<1; 5323: geterror(bp); 5324: return; 5325: bad: 5326: u.u_error = EFAULT; 5327: } 5328: /* --------------------------- */ 5329: 5330: /* 5331: * Pick up the device's error number and pass it to the user; 5332: * if there is an error but the number is 0 set a generalized 5333: * code. Actually the latter is always true because devices 5334: * don't yet return specific errors. 5335: */ 5336: geterror(abp) 5337: struct buf *abp; 5338: { 5339: register struct buf *bp; 5340: 5341: bp = abp; 5342: if (bp->b_flags&B_ERROR) 5343: if ((u.u_error = bp->b_error)==0) 5344: u.u_error = EIO; 5345: } 5346: /* --------------------------- */