1 #include "dos.h" /* AN000 */
2 #include "fdisk.h" /* AN000 */
3 #include "extern.h" /* AN000 */
4 #include "subtype.h" /* AN000 */
5 #include "fdiskmsg.h" /* AN000 */
11 /* int printf(char *, ...); */
20 /* Initialize values */
21 number_of_drives = uc(0); /* AC000 */
22 for (i=uc(0); i < uc(2); i++) /* AC000 */
24 total_disk[i] = u(0); /* AC000 */
25 total_mbytes[i] = f(0); /* AC000 */
26 max_sector[i] = uc(0); /* AC000 */
27 max_head[0] = u(0); /* AC004 */
30 /* See how many drives there are */
31 if (get_drive_parameters(uc(0x80))) /* AC000 */
34 /* Get the drive parameters for all drives */
35 for (i = uc(0); i < number_of_drives;i++) /* AC000 */
38 if (get_drive_parameters(uc(0x80)+i)) /* AC000 */
41 /* Save drive parameters */
42 max_sector[i] = ((unsigned char)(regs.h.cl & 0x3F));
43 max_head[i] = ((unsigned)(regs.h.dh +1)); /* AC004 */
45 total_disk[i] = ((((unsigned)(regs.h.cl & 0xC0 )) & 0x00C0) << 2)+ ((unsigned)regs.h.ch) +1;
47 total_disk[i] = ((((unsigned)(regs.h.cl & 0xc0)) << 2) | regs.h.ch) + 1;
49 total_mbytes[i] = cylinders_to_mbytes(total_disk[i],i); /* AN004 */
60 /* No drives present */
62 no_fatal_error = FALSE;
70 char write_boot_record(cylinder,which_disk)
73 unsigned char which_disk;
79 char far *buffer_pointer = boot_record;
81 /* Setup read, always on a cylinder boundary */
82 regs.h.ah = uc(WRITE_DISK); /* AC000 */
83 regs.h.al = uc(1); /* AC000 */
84 regs.h.dh = uc(0); /* AC000 */
85 regs.h.cl = uc(0x01); /* AC000 */
87 /* Specify the disk */
88 regs.h.dl = which_disk + 0x80;
90 /* Need to scramble CX so that sectors and cyl's are in INT 13 format */
92 if (cylinder > u(255)) /* AC000 */
94 regs.h.cl = regs.h.cl | ((unsigned char)((cylinder /256) << 6));
96 regs.h.ch = (unsigned char)(cylinder & 0xFF);
98 /* Point at the place to read the boot record */
99 regs.x.bx = FP_OFF(buffer_pointer);
100 segregs.es = FP_SEG(buffer_pointer);
102 /* write the boot record */
103 DiskIo(®s,®s,&segregs); /* AC000 */
105 /* Check for error reading it */
106 if ((regs.x.cflag & 1) != u(1)) /* AC000 */
112 /* Tell user there was an error */
113 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
115 no_fatal_error = FALSE;
121 unsigned verify_tracks(pointer,type)
129 unsigned sectors_per_fat;
133 unsigned long total_sectors;
136 unsigned char cur_head; /* AC004 */
138 char far *buffer_pointer = boot_record;
143 for (i=u(0); i< u(BYTES_PER_SECTOR);i++) /* AC000 */
145 /* Put something other then 0's so that unformatted FAT looks full */
147 boot_record[i] = uc(0xF6); /* AC000 */
150 /* Get the start cylinder for the sweep */
151 cur_cyl = free_space[pointer].start;
153 /* Also keep track of what it is */
154 verify_cyl = cur_cyl;
156 /* Initialize the start head -assume 0*/
157 cur_head = uc(0); /* AC004 */
158 if ((type == c(PRIMARY)) && (cur_cyl == u(0))) /* AC000 */
161 /* It's head 1 - NOTE: This is convience for PC-DOS because it is */
162 /* always this way - This may have to be beefed up for IFS */
163 cur_head = uc(1); /* AC004 */
166 /* Now go figure out the number of golden sectors needed. Use the */
167 /* allocation equation in the fixed disk section of DOS Tech Ref. */
169 /* TS = Free cyl's * sector/track * track/cyl */
173 /* BPS = BYTES_PER_SECTOR */
179 /* Golden Sectors = RS + 2(SPF) + BPD(D) + (DOSFILES) */
180 /* ÄÄÄÄÄÄ if bootable */
183 total_sectors = ((unsigned long)free_space[pointer].space) * max_head[cur_disk] * max_sector[cur_disk];
185 /* Chop off one track if it starts on head 1 */
186 if (cur_head == uc(1)) /* AC004 */
188 total_sectors = total_sectors - max_sector[cur_disk];
191 /* See if 12 or 16 bit fat */
192 if (total_sectors > (unsigned long)FAT16_SIZE)
195 sectors_per_fat = ((unsigned)((total_sectors -33)/(2 + ((BYTES_PER_SECTOR *4)/2))));
200 sectors_per_fat = ((unsigned)((total_sectors -33)/(2 + ((BYTES_PER_SECTOR *8)/1.5))));
203 /* Round up one just to handle any rounding errors */
206 /* Now see how many tracks */
207 num_tracks = (sectors_per_fat*2) + 33;
209 /* If primary and drive 0, add in enough for system files */
210 if ((type == c(PRIMARY)) && (cur_disk == c(0))) /* AC000 */
212 num_tracks = num_tracks + SYSTEM_FILE_SECTORS;
216 /* Now convert to tracks */
217 num_tracks = num_tracks/max_sector[cur_disk];
219 /* Handle upward rounding */
220 if (num_tracks%max_sector[cur_disk] != u(0)) /* AC000 */
225 /* Handle upward rounding */ /* The problem with the IBM code is */
226 if (num_tracks%max_sector[cur_disk] != u(0)) /* that if num_tracks is < max_sector[cur_disk] */
227 BEGIN /* the num_tracks becomes 0 due to the integer */
228 num_tracks = num_tracks + max_sector[cur_disk]; /* division and num_tracks will not be inc'd . */
229 END /* This section of code overcomes that. */
231 /* Now convert to tracks */
232 num_tracks = num_tracks/max_sector[cur_disk];
236 golden_tracks = FALSE;
237 while (!golden_tracks)
239 for (i = u(0);i < num_tracks; i++) /* AC000 */
241 retry = c(0); /* AC000 */
245 /* Specify the operation */
246 regs.h.ah = uc(WRITE_DISK); /* AC000 */
248 /* Specify number of sectors */
249 regs.h.al = ((unsigned char)max_sector[cur_disk]);
251 /* Specify the start sectors */
252 regs.h.cl = uc(1); /* AC000 */
254 /* Need to scramble CX so that sectors and cyl's are in INT 13 format */
255 if (cur_cyl > u(255)) /* AC000 */
257 regs.h.cl = regs.h.cl | ((unsigned char)((cur_cyl/256) << 6));
259 regs.h.ch = ((unsigned char)cur_cyl) & 0xFF;
261 /* Specify the disk */
262 regs.h.dl = ((unsigned char)cur_disk) + 0x80;
264 /* Specify the head */
265 regs.h.dh = cur_head; /* AC004 */
267 /* Point at the place to write */
268 regs.x.bx = FP_OFF(buffer_pointer);
269 segregs.es = FP_SEG(buffer_pointer);
271 /* write the track */
272 DiskIo(®s,®s,&segregs); /* AC000 */
275 while (((regs.x.cflag & 1) == u(1)) && (retry != c(5))); /* AC000 */
277 /* See if we had a good read */
278 if ((regs.x.cflag & 1) != u(1)) /* AC000 */
280 golden_tracks = TRUE;
281 /* Get the next head */
283 if (cur_head == (uc(max_head[cur_disk] -1))) /* AC004 */
285 /* Up to the next cylinder */
286 cur_head = uc(0); /* AC004 */
289 /* Check to see if we've reached the end of the free_space*/
290 if (cur_cyl > free_space[pointer].end)
292 /* It is, so return with the cyl offset equal to the freespace */
293 return(free_space[pointer].space);
299 /* Get out of the for loop, with a false flag */
300 golden_tracks = FALSE;
302 /* Bump up to the next cylinder boundary */
304 cur_head = uc(0); /* AC004 */
306 /* Save the new verify start point */
307 verify_cyl = cur_cyl;
311 END /* for num_tracks */
312 END /* while !golden_tracks */
314 /* All done, return the offset from original cyl to the new one */
315 return(verify_cyl - free_space[pointer].start);
320 char get_drive_parameters(drive)
325 /* See how many drives there are */
326 regs.h.ah = uc(DISK_INFO); /* AC000 */
328 DiskIo(®s,®s,&segregs); /* AC000 */
330 /* See if any drives exist */
331 if ((regs.h.dl == uc(0)) || ((regs.x.cflag & 1) == u(1))) /* AC000 */
338 /* Save the number of drives */
339 number_of_drives = regs.h.dl;
345 char read_boot_record(cylinder,which_disk,which_head,which_sector) /* AC000 */
348 unsigned char which_disk;
349 unsigned char which_head; /* AN000 */
350 unsigned char which_sector; /* AN000 */
354 char far *buffer_pointer = boot_record;
356 /* Setup read, always on a cylinder boundary */
357 regs.h.ah = uc(READ_DISK); /* AC000 */
358 regs.h.al = uc(1); /* AC000 */
359 regs.h.dh = which_head; /* AC000 */
360 regs.h.cl = which_sector; /* AC000 */
362 /* Specify the disk */
363 regs.h.dl = which_disk + 0x80;
365 /* Need to scramble CX so that sectors and cyl's are in INT 13 format */
367 if (cylinder > u(255)) /* AC000 */
369 regs.h.cl = regs.h.cl | ((char)((cylinder /256) << 6));
371 regs.h.ch = (unsigned char)(cylinder & 0xFF);
373 /* Point at the place to write the boot record */
374 regs.x.bx = FP_OFF(buffer_pointer);
375 segregs.es = FP_SEG(buffer_pointer);
377 /* read in the boot record */
378 DiskIo(®s,®s,&segregs); /* AC000 */
379 /* Check for error reading it */
380 if ((regs.x.cflag & 1) != u(1)) /* AC000 */
386 /* Tell user there was an error */
387 good_disk[which_disk] = FALSE;
388 clear_screen(u(0),u(0),u(24),u(79)); /* AC000 */
394 void DiskIo(InRegs,OutRegs,SegRegs)
397 struct SREGS *SegRegs;
414 int86x((int)DISK,InRegs,OutRegs,SegRegs); /* AC000 */
418 WritePtr = getenv("WRITE");
419 if (strcmpi(WritePtr,"ON") != 0)
421 printf("\nDisallowing Disk I/O Request\n");
422 printf("AX:%04X BX:%04X CX:%04X DX:%04X ES:%04X\n",
423 InRegs->x.ax,InRegs->x.bx,InRegs->x.cx,InRegs->x.dx,SegRegs->es);
425 OutRegs->h.ah = (unsigned char) 0;
426 OutRegs->x.cflag = (unsigned) 0;
428 else int86x((int)DISK,InRegs,OutRegs,SegRegs);
436 int86x((int)DISK,InRegs,OutRegs,SegRegs); /* AC000 */