BLOCKIO.C
上传用户:dcs7469208
上传日期:2010-01-02
资源大小:443k
文件大小:10k
源码类别:

操作系统开发

开发平台:

DOS

  1. /****************************************************************/
  2. /* */
  3. /*     blockio.c */
  4. /*       DOS-C */
  5. /* */
  6. /* Block cache functions and device driver interface */
  7. /* */
  8. /* Copyright (c) 1995 */
  9. /* Pasquale J. Villani */
  10. /* All Rights Reserved */
  11. /* */
  12. /* This file is part of DOS-C. */
  13. /* */
  14. /* DOS-C is free software; you can redistribute it and/or */
  15. /* modify it under the terms of the GNU General Public License */
  16. /* as published by the Free Software Foundation; either version */
  17. /* 2, or (at your option) any later version. */
  18. /* */
  19. /* DOS-C is distributed in the hope that it will be useful, but */
  20. /* WITHOUT ANY WARRANTY; without even the implied warranty of */
  21. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See */
  22. /* the GNU General Public License for more details. */
  23. /* */
  24. /* You should have received a copy of the GNU General Public */
  25. /* License along with DOS-C; see the file COPYING.  If not, */
  26. /* write to the Free Software Foundation, 675 Mass Ave, */
  27. /* Cambridge, MA 02139, USA. */
  28. /* */
  29. /****************************************************************/
  30. #include "../../hdr/portab.h"
  31. #include "globals.h"
  32. /* $Logfile:   C:/dos-c/src/fs/blockio.c_v  $ */
  33. #ifdef VERSION_STRINGS
  34. static BYTE *blockioRcsId = "$Header:   C:/dos-c/src/fs/blockio.c_v   1.7   22 Jan 1998  4:09:00   patv  $";
  35. #endif
  36. /* $Log:   C:/dos-c/src/fs/blockio.c_v  $
  37.  * 
  38.  *    Rev 1.7   22 Jan 1998  4:09:00   patv
  39.  * Fixed pointer problems affecting SDA
  40.  * 
  41.  *    Rev 1.6   04 Jan 1998 23:14:36   patv
  42.  * Changed Log for strip utility
  43.  * 
  44.  *    Rev 1.5   03 Jan 1998  8:36:02   patv
  45.  * Converted data area to SDA format
  46.  * 
  47.  *    Rev 1.4   16 Jan 1997 12:46:34   patv
  48.  * pre-Release 0.92 feature additions
  49.  * 
  50.  *    Rev 1.3   29 May 1996 21:15:10   patv
  51.  * bug fixes for v0.91a
  52.  * 
  53.  *    Rev 1.2   01 Sep 1995 17:48:46   patv
  54.  * First GPL release.
  55.  * 
  56.  *    Rev 1.1   30 Jul 1995 20:50:28   patv
  57.  * Eliminated version strings in ipl
  58.  * 
  59.  *    Rev 1.0   02 Jul 1995  8:04:06   patv
  60.  * Initial revision.
  61.  */
  62. /* $EndLog$ */
  63. /************************************************************************/
  64. /* */
  65. /* block cache routines */
  66. /* */
  67. /************************************************************************/
  68. #ifdef I86
  69. static BOOL Is64kBoundry(VOID FAR *lpPtr);
  70. /* */
  71. /* Test if buffer will stradle a 64k boundry.  Buffer is assumed to be */
  72. /* BUFFERSIZE long. */
  73. /* */
  74. static BOOL Is64kBoundary(VOID FAR *lpPtr)
  75. {
  76. ULONG lTemp;
  77. /* First, convert the segmented pointer to linear address */
  78. lTemp = FP_SEG(lpPtr);
  79. lTemp = (lTemp << 4) + FP_OFF(lpPtr);
  80. /* Now, clear out the top of the linear address above the 64K */
  81. /* boundary and add BUFFERSIZE to it.  If we get a carry above */
  82. /* the 64k boundary, then return TRUE. */
  83. lTemp &= 0x0000ffffl;
  84. lTemp += BUFFERSIZE;
  85. return (lTemp & 0xffff0000l) != 0 ? TRUE : FALSE;
  86. }
  87. #endif
  88. /* */
  89. /* Initialize the buffer structure */
  90. /* */
  91. VOID 
  92. init_buffers (void)
  93. {
  94. REG WORD i;
  95. for (i = 0; i < Config.cfgBuffers; ++i)
  96. {
  97. buffers[i].b_unit = 0;
  98. buffers[i].b_flag = 0;
  99. buffers[i].b_blkno = 0;
  100. buffers[i].b_copies = 0;
  101. buffers[i].b_offset = 0;
  102. if (i < (Config.cfgBuffers - 1))
  103. buffers[i].b_next = &buffers[i+1];
  104. else
  105. buffers[i].b_next = NULL;
  106. }
  107. firstbuf = &buffers[0];
  108. lastbuf  = &buffers[Config.cfgBuffers-1];
  109. #ifdef I86
  110. /* Eliminate any buffers that straddle 64K boundaries because */
  111. /* DMA can't handle them. */
  112. /* First, search for the first buffer that is safe. */
  113. /* There is an underlying assumption here that BUFFERSIZE is */
  114. /* not 64k.  If it is, this code will fail but then again there */
  115. /* is no way to make it work because it means that every buffer */
  116.         /* is on a 64k boundary! */
  117. i = 0;
  118. while(Is64kBoundary(firstbuf -> b_buffer))
  119. {
  120. firstbuf = &buffers[++i];
  121. }
  122. /* Now start from the (presumably) buffer[1] and link out any */
  123. /* buffer that does straddle a boundary. */
  124. for (; i < Config.cfgBuffers; ++i)
  125. {
  126. if(buffers[i].b_buffer == (struct buffer FAR *)0)
  127. break;
  128. if(Is64kBoundary(buffers[i].b_buffer))
  129. {
  130. buffers[i - 1].b_next = buffers[i].b_next;
  131. ++i;
  132. }
  133. }
  134. #endif
  135. }
  136.  
  137. /* */
  138. /* Return the address of a buffer structure containing the */
  139. /* requested block. */
  140. /* */
  141. /* returns: */
  142. /* requested block with data */
  143. /* failure: */
  144. /* returns NULL */
  145. /* */
  146. struct buffer FAR *
  147. getblock (LONG blkno, COUNT dsk)
  148. {
  149. REG struct buffer FAR *bp;
  150. REG struct buffer FAR *lbp;
  151. REG struct buffer FAR *mbp;
  152. REG WORD imsave;
  153. /* Search through buffers to see if the required block */
  154. /* is already in a buffer */
  155. bp = firstbuf;
  156. lbp = NULL;
  157. mbp = NULL;
  158. while(bp != NULL)
  159. {
  160. if ((bp -> b_flag & BFR_VALID) && (bp -> b_unit == dsk) 
  161.      && (bp -> b_blkno == blkno) )
  162. {
  163. /* found it -- rearrange LRU links */
  164. if(lbp != NULL)
  165. {
  166. lbp -> b_next = bp -> b_next;
  167. bp -> b_next  = firstbuf;
  168. firstbuf = bp;
  169. }
  170. return(bp);
  171. }
  172. else
  173. {
  174. mbp = lbp; /* move along to next buffer */
  175. lbp = bp;
  176. bp  = bp -> b_next;
  177. }
  178. }
  179. /* The block we need is not in a buffer, we must make a buffer */
  180. /* available, and fill it with the desired block */
  181. /* detach lru buffer */
  182. if(mbp != NULL)
  183. mbp -> b_next = NULL;
  184. lbp -> b_next = firstbuf;
  185. firstbuf = lbp;
  186. if(flush1(lbp) && fill(lbp, blkno, dsk)) /* success */
  187. mbp = lbp;
  188. else
  189. mbp = NULL; /* failure */
  190. return (mbp);
  191. }
  192. BOOL
  193. getbuf (struct buffer FAR **pbp, LONG blkno, COUNT dsk)
  194. {
  195. REG struct buffer FAR *bp;
  196. REG struct buffer FAR *lbp;
  197. REG struct buffer FAR *mbp;
  198. REG WORD imsave;
  199. /* Search through buffers to see if the required block */
  200. /* is already in a buffer */
  201. bp = firstbuf;
  202. lbp = NULL;
  203. mbp = NULL;
  204. while(bp != NULL)
  205. {
  206. if ((bp -> b_flag & BFR_VALID) && (bp -> b_unit == dsk) 
  207.      && (bp -> b_blkno == blkno) )
  208. {
  209. /* found it -- rearrange LRU links */
  210. if(lbp != NULL)
  211. {
  212. lbp -> b_next = bp -> b_next;
  213. bp -> b_next  = firstbuf;
  214. firstbuf = bp;
  215. }
  216. *pbp = bp;
  217. return TRUE;
  218. }
  219. else
  220. {
  221. mbp = lbp; /* move along to next buffer */
  222. lbp = bp;
  223. bp  = bp -> b_next;
  224. }
  225. }
  226. /* The block we need is not in a buffer, we must make a buffer */
  227. /* available, and fill it with the desired block */
  228. /* detach lru buffer */
  229. if(mbp != NULL)
  230. mbp -> b_next = NULL;
  231. lbp -> b_next = firstbuf;
  232. firstbuf = lbp;
  233. if(flush1(lbp)) /* success */
  234. {
  235. *pbp = lbp;
  236. return TRUE;
  237. }
  238. else /* failure */
  239. {
  240. *pbp = NULL;
  241. return FALSE;
  242. }
  243. }
  244. /* */
  245. /* Mark all buffers for a disk as not valid */
  246. /* */
  247. VOID 
  248. setinvld (REG COUNT dsk)
  249. {
  250. REG struct buffer FAR *bp;
  251. bp = firstbuf;
  252. while (bp)
  253. {
  254. if(bp -> b_unit == dsk)
  255. bp -> b_flag = 0;
  256. bp = bp -> b_next;
  257. }
  258. }
  259. /* */
  260. /* Flush all buffers for a disk */
  261. /* */
  262. /* returns: */
  263. /* TRUE on success */
  264. /* */
  265. BOOL 
  266. flush_buffers (REG COUNT dsk)
  267. {
  268. REG struct buffer FAR *bp;
  269. REG BOOL ok = TRUE;
  270. bp = firstbuf;
  271. while (bp)
  272. {
  273. if(bp -> b_unit == dsk)
  274. if(!flush1(bp))
  275. ok = FALSE;
  276. bp = bp -> b_next;
  277. }
  278. return ok;
  279. }
  280. /* */
  281. /* Write one disk buffer */
  282. /* */
  283. BOOL 
  284. flush1 (struct buffer FAR *bp)
  285. {
  286. REG WORD ok;
  287. if ((bp -> b_flag & BFR_VALID) && (bp -> b_flag & BFR_DIRTY))
  288. {
  289. ok = dskxfer(bp -> b_unit, bp -> b_blkno,
  290.  (VOID FAR *)bp -> b_buffer, DSKWRITE);
  291. if(bp -> b_flag & BFR_FAT)
  292. {
  293. int i = bp -> b_copies - 1;
  294. do
  295. ok &= dskxfer(bp -> b_unit,
  296.  bp -> b_blkno + i * bp -> b_offset,
  297.  (VOID FAR *)bp -> b_buffer, DSKWRITE);
  298. while (--i > 0);
  299. }
  300. }
  301. else
  302. ok = TRUE;
  303. bp -> b_flag &= ~BFR_DIRTY; /* even if error, mark not dirty */
  304. if(!ok) /* otherwise system has trouble  */
  305. bp -> b_flag &= ~BFR_VALID; /* continuing.  */
  306. return(ok);
  307. }
  308. /* */
  309. /* Write all disk buffers */
  310. /* */
  311. BOOL 
  312. flush (void)
  313. {
  314. REG struct buffer FAR *bp;
  315. REG BOOL ok;
  316. ok = TRUE;
  317. bp = firstbuf;
  318. while(bp)
  319. {
  320. if (!flush1(bp))
  321. ok = FALSE;
  322. bp -> b_flag &= ~BFR_VALID;
  323. bp = bp -> b_next;
  324. }
  325. return(ok);
  326. }
  327. /* */
  328. /* Fill the indicated disk buffer with the current track and sector */
  329. /* */
  330. BOOL 
  331. fill (REG struct buffer FAR *bp, LONG blkno, COUNT dsk)
  332. {
  333. REG WORD ok;
  334. if((bp -> b_flag & BFR_VALID) && (bp -> b_flag & BFR_DIRTY))
  335. ok = flush1(bp);
  336. else
  337. ok = TRUE;
  338. if(ok && (bp -> b_flag & BFR_VALID) && (blkno == bp -> b_blkno))
  339. return OK;
  340. if(ok)
  341. ok = dskxfer(dsk, blkno, (VOID FAR *)bp -> b_buffer, DSKREAD);
  342. bp -> b_flag = BFR_VALID | BFR_DATA;
  343. bp -> b_blkno = blkno;
  344. bp -> b_unit = dsk;
  345. return(ok);
  346. }
  347. /************************************************************************/
  348. /* */
  349. /* Device Driver Interface Functions */
  350. /* */
  351. /************************************************************************/
  352. /* */
  353. /* Transfer a block to/from disk */
  354. /* */
  355. BOOL 
  356. dskxfer (COUNT dsk, LONG blkno, VOID FAR *buf, COUNT mode)
  357. {
  358. REG struct dpb *dpbp = &blk_devices[dsk];
  359. for(;;)
  360. {
  361. IoReqHdr.r_length = sizeof(request);
  362. IoReqHdr.r_unit = dpbp -> dpb_subunit;
  363. IoReqHdr.r_command =
  364.  mode == DSKWRITE ?
  365.   (verify_ena ? C_OUTVFY : C_OUTPUT)
  366.   : C_INPUT;
  367. IoReqHdr.r_status = 0;
  368. IoReqHdr.r_meddesc = dpbp -> dpb_mdb;
  369. IoReqHdr.r_trans = (BYTE FAR *)buf;
  370. IoReqHdr.r_count = 1;
  371. if(blkno > MAXSHORT)
  372. {
  373. IoReqHdr.r_start = HUGECOUNT;
  374. IoReqHdr.r_huge = blkno - 1;
  375. }
  376. else
  377. IoReqHdr.r_start = blkno - 1;
  378. execrh((request FAR *)&IoReqHdr, dpbp -> dpb_device);
  379. if(!(IoReqHdr.r_status & S_ERROR) && (IoReqHdr.r_status & S_DONE))
  380. break;
  381. else
  382. {
  383. loop:
  384. switch(block_error(&IoReqHdr, dpbp -> dpb_unit))
  385. {
  386. case ABORT:
  387. case FAIL:
  388. return FALSE;
  389. case RETRY:
  390. continue;
  391. case CONTINUE:
  392. break;
  393. default:
  394. goto loop;
  395. }
  396. }
  397. }
  398. return TRUE;
  399. }