1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
| int raid4_valid(u_int diskno) { int ret; int offset = 0, read = 0; ret = syscall_write_dev(&diskno, 0x13000010, 4); if(ret < 0) user_panic("raid4_valid error!");
ret = syscall_write_dev(&offset, 0x13000000, 4); if(ret < 0) user_panic("raid4_valid error!");
ret = syscall_write_dev(&read, 0x13000020, 4); if(ret < 0) user_panic("raid4_valid error!");
if(syscall_read_dev(&ret, 0x13000030, 4) < 0) user_panic("raid4_valid error!");
return ret; }
int raid4_write(u_int blockno, void *src) { int res = 0; int offset = 0, diskno = 1, halfpg = 0x800; int check[2][128], i; while (diskno <= 4) { if(raid4_valid(diskno)) { ide_write(diskno, 2 * blockno, src + offset, 1); ide_write(diskno, 2 * blockno + 1, src + offset + halfpg, 1); } else res++; diskno++; offset += 0x200; } if(raid4_valid(diskno)) { user_bzero(check, 1024); for(i = 0; i < 128; i++) { check[0][i] = *(int *)(src + 4 * i); check[1][i] = *(int *)(src + halfpg + 4 * i); for(offset = 0x200; offset < 0x800; offset += 0x200) { check[0][i] ^= *(int *)(src + offset + 4 * i); check[1][i] ^= *(int *)(src + offset + halfpg + 4 * i); } } ide_write(diskno, 2 * blockno, (void *)check[0], 1); ide_write(diskno, 2 * blockno + 1, (void *)check[1], 1); } else res++; return res; }
int raid4_read(u_int blockno, void *dst) { int res = 0; int invalid = 0; int offset = 0, diskno = 1, halfpg = 0x800; int check[2][128], i; int check0, check1; while (diskno <= 5) { if(!raid4_valid(diskno)) res++; diskno++; } if(res > 1) return res; else { diskno = 1; while (diskno <= 4) { if(raid4_valid(diskno)) { ide_read(diskno, 2 * blockno, dst + offset, 1); ide_read(diskno, 2 * blockno + 1, dst + offset + halfpg, 1); } else invalid = diskno; diskno++; offset += 0x200; } if(res == 1 && invalid == 0) return 1; else { user_bzero(check, 1024); ide_read(diskno, 2 * blockno, (void *)check[0], 1); ide_read(diskno, 2 * blockno + 1, (void *)check[1], 1); if(res == 0) { for(i = 0; i < 128; i++) { check0 = *(int *)(dst + 4 * i); check1 = *(int *)(dst + halfpg + 4 * i); for(offset = 0x200; offset < 0x800; offset += 0x200) { check0 ^= *(int *)(dst + offset + 4 * i); check1 ^= *(int *)(dst + offset + halfpg + 4 * i); } if(check0 != check[0][i] || check1 != check[1][i]) return -1; } return 0; } else { for(i = 0; i < 128; i++) { check0 = check[0][i]; check1 = check[1][i]; for(offset = 0; offset < 0x800; offset += 0x200) { check0 ^= *(int *)(dst + offset + 4 * i); check1 ^= *(int *)(dst + offset + halfpg + 4 * i); } check0 ^= *(int *)(dst + (invalid - 1) * 0x200 + 4 * i); check1 ^= *(int *)(dst + (invalid - 1) * 0x200 + halfpg + 4 * i); *(int *)(dst + (invalid - 1) * 0x200 + 4 * i) = check0; *(int *)(dst + (invalid - 1) * 0x200 + halfpg + 4 * i) = check1; } return 1; } } } }
|