1: /* 2: * Do full cylinder buffered writes to slow devices. Uses a simple 3: * buffered read/delayed write algorithm 4: */ 5: 6: #include <stdio.h> 7: #include "msdos.h" 8: 9: extern int fd, disk_size, disk_dirty, dir_start, dir_len; 10: extern int clus_size; 11: extern long disk_offset, disk_current; 12: extern unsigned char *disk_buf; 13: static int blank_cyl(); 14: 15: void 16: disk_write(start, buf, len) 17: long start; 18: unsigned char *buf; 19: int len; 20: { 21: register long i; 22: int length; 23: unsigned char *buf_ptr, *disk_ptr; 24: char *memcpy(); 25: void perror(), exit(), disk_flush(); 26: long where, tail, lseek(); 27: 28: /* don't use cache? */ 29: if (disk_size == 1) { 30: where = (start * MSECTOR_SIZE) + disk_offset; 31: if (lseek(fd, where, 0) < 0) { 32: perror("disk_write: lseek"); 33: exit(1); 34: } 35: /* write it! */ 36: if (write(fd, (char *) buf, (unsigned int) len) != len) { 37: perror("disk_write: write"); 38: exit(1); 39: } 40: return; 41: } 42: 43: tail = start + (len / MSECTOR_SIZE) - 1; 44: for (i = start; i <= tail; i++) { 45: /* a cache miss... */ 46: if (i < disk_current || i >= disk_current + disk_size) { 47: 48: if (disk_dirty) 49: disk_flush(); 50: 51: /* 52: * If there is something on the new cylinder that 53: * you want to keep, you'll have to read it first 54: * before writing. 55: */ 56: if (blank_cyl(i)) 57: disk_current = (i / disk_size) * disk_size; 58: else { 59: disk_current = (i / disk_size) * disk_size; 60: where = (disk_current * MSECTOR_SIZE) + disk_offset; 61: length = disk_size * MSECTOR_SIZE; 62: 63: /* move to next location */ 64: if (lseek(fd, where, 0) < 0) { 65: perror("disk_write: lseek"); 66: exit(1); 67: } 68: /* read it! */ 69: if (read(fd, (char *) disk_buf, (unsigned int) length) != length) { 70: perror("disk_write: read"); 71: exit(1); 72: } 73: } 74: } 75: /* a cache hit ... */ 76: buf_ptr = buf + ((i - start) * MSECTOR_SIZE); 77: disk_ptr = disk_buf + ((i - disk_current) * MSECTOR_SIZE); 78: memcpy((char *) disk_ptr, (char *) buf_ptr, MSECTOR_SIZE); 79: disk_dirty = 1; 80: } 81: return; 82: } 83: 84: /* 85: * Flush a dirty buffer to disk. Resets disk_dirty to zero. 86: * All errors are fatal. 87: */ 88: 89: void 90: disk_flush() 91: { 92: int len; 93: long where, lseek(); 94: void perror(), exit(); 95: 96: if (fd < 0 || disk_current < 0L || !disk_dirty) 97: return; 98: 99: where = (disk_current * MSECTOR_SIZE) + disk_offset; 100: if (lseek(fd, where, 0) < 0) { 101: perror("disk_flush: lseek"); 102: exit(1); 103: } 104: /* write it! */ 105: len = disk_size * MSECTOR_SIZE; 106: if (write(fd, (char *) disk_buf, (unsigned int) len) != len) { 107: perror("disk_flush: write"); 108: exit(1); 109: } 110: disk_dirty = 0; 111: return; 112: } 113: 114: /* 115: * Determine if the cylinder has some useful information on it. Returns a 1 116: * if it is blank. 117: */ 118: 119: static int 120: blank_cyl(num) 121: long num; 122: { 123: register unsigned int i; 124: unsigned int start, end, fat_decode(); 125: long sector; 126: 127: sector = (num / disk_size) * disk_size; 128: if (!sector) 129: return(0); 130: 131: start = ((sector - dir_start - dir_len) / clus_size) + 2; 132: end = ((sector + disk_size - dir_start - dir_len) / clus_size) + 2; 133: 134: for (i = start; i < end; i++) { 135: /* if fat_decode returns non-zero */ 136: if (fat_decode(i)) 137: return(0); 138: } 139: return(1); 140: }