/** write_sectors in write.c has BUG!!! * write_sectors - write several sectors from disk * @drive_info: driveinfo struct describing the disk * @lba: Position to write * @data: Buffer to write * @size: Size of the buffer (number of sectors) * * Return the number of sectors write on success or -1 on failure. * errno_disk contains the error number. **/ static int dwipe_write_sectors(const struct driveinfo *drive_info, const unsigned int lba, const void *data, const int size) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + size * SECTOR; memcpy(buf, data, size * SECTOR); memset(&inreg, 0, sizeof inreg); if (drive_info->ebios) { dapa->len = sizeof(*dapa); dapa->count = size; dapa->off = OFFS(buf); dapa->seg = SEG(buf); dapa->lba = lba; inreg.esi.w[0] = OFFS(dapa); inreg.ds = SEG(dapa); inreg.edx.b[0] = drive_info->disk; inreg.eax.w[0] = 0x4300; /* Extended write */ } else { unsigned int c, h, s; if (!drive_info->cbios) { // XXX errno /* We failed to get the geometry */ if (lba) return -1; /* Can only write MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); // XXX errno if (s > 63 || h > 256 || c > 1023) return -1; inreg.eax.w[0] = 0x0301; /* Write one sector */ inreg.ecx.b[1] = c & 0xff; inreg.ecx.b[0] = s + (c >> 6); inreg.edx.b[1] = h; inreg.edx.b[0] = drive_info->disk; inreg.ebx.w[0] = OFFS(buf); inreg.es = SEG(buf); } /* Perform the write */ if (int13_retry(&inreg, &outreg)) { errno_disk = outreg.eax.b[1]; return -1; /* Give up */ } else return size; }
/** * read_sectors - read several sectors from disk * @drive_info: driveinfo struct describing the disk * @data: Pre-allocated buffer for output * @lba: Position to read * @sectors: Number of sectors to read * * Return the number of sectors read on success or -1 on failure. * errno_disk contains the error number. **/ int read_sectors(struct driveinfo *drive_info, void *data, const unsigned int lba, const int sectors) { com32sys_t inreg, outreg; struct ebios_dapa *dapa = __com32.cs_bounce; void *buf = (char *)__com32.cs_bounce + sectors * SECTOR; char *bufp = data; if (get_drive_parameters(drive_info) == -1) return -1; memset(&inreg, 0, sizeof inreg); if (drive_info->ebios) { dapa->len = sizeof(*dapa); dapa->count = sectors; dapa->off = OFFS(buf); dapa->seg = SEG(buf); dapa->lba = lba; inreg.esi.w[0] = OFFS(dapa); inreg.ds = SEG(dapa); inreg.edx.b[0] = drive_info->disk; inreg.eax.b[1] = 0x42; /* Extended read */ } else { unsigned int c, h, s; if (!drive_info->cbios) { // XXX errno /* We failed to get the geometry */ if (lba) return -1; /* Can only read MBR */ s = 1; h = 0; c = 0; } else lba_to_chs(drive_info, lba, &s, &h, &c); // XXX errno if (s > 63 || h > 256 || c > 1023) return -1; inreg.eax.w[0] = 0x0201; /* Read one sector */ inreg.ecx.b[1] = c & 0xff; inreg.ecx.b[0] = s + (c >> 6); inreg.edx.b[1] = h; inreg.edx.b[0] = drive_info->disk; inreg.ebx.w[0] = OFFS(buf); inreg.es = SEG(buf); } /* Perform the read */ if (int13_retry(&inreg, &outreg)) { errno_disk = outreg.eax.b[1]; return -1; /* Give up */ } memcpy(bufp, buf, sectors * SECTOR); return sectors; }
void add_partition() { int off, noff, poff; int size, psize; int i, partno, type; int cyl, head, sect; int ch; char str[128]; // Get partition number ch = ask("partition number (0-3)? ", "0123\n"); if (ch == '\n') return; partno = ch - '0'; if (mbr.parttab[partno].systid != 0) { printf("error: partition already used\n"); return; } // Get partition size printf("partition size (KB) (*=max size)? "); gets(str); size = *str == '*' ? -1 : atoi(str) * 1024 / geom.sectorsize; // Get partition type printf("partition type (default %x)? ", SANOS_BOOT_PARTITION_ID); gets(str); type = *str ? strtol(str, NULL, 16) : SANOS_BOOT_PARTITION_ID; // Adjust size to be a multiple of the sectors per track if (size > 0) { size = ALIGN(size, geom.spt); if (size < geom.spt) { printf("partition size must be at least %d sectors\n", geom.spt); return; } } // Search for the next partition in the table for (i = partno + 1; i < 4; i++) { if (mbr.parttab[i].systid != 0) break; } if (i >= 4) { noff = -1; } else { noff = mbr.parttab[i].relsect; } // Search for the previous partition in the table for (i = partno - 1; i >= 0; i--) { if (mbr.parttab[i].systid != 0) break; } if (i < 0) { poff = -1; } else { poff = mbr.parttab[i].relsect; psize = mbr.parttab[i].numsect; } // Compute offset of new partition if (poff < 0) { off = geom.spt; } else { off = ALIGN(poff + psize, geom.spt); } // Check whether specified partition will fit, or calculate maximum partition size if (size < 0) { size = (noff < 0 ? geom.sectors : noff) - off; } else { if (off + size > (noff < 0 ? geom.sectors : noff)) { printf("partition size too large\n"); return; } } printf("add partition %d offset %d size %d KB\n", partno, off, size / (1024 / geom.sectorsize)); mbr.parttab[partno].relsect = off; mbr.parttab[partno].numsect = size; mbr.parttab[partno].systid = type; lba_to_chs(off, &cyl, &head, §); mbr.parttab[partno].begcyl = cyl & 0xFF; mbr.parttab[partno].beghead = head; mbr.parttab[partno].begsect = sect | ((cyl >> 8) << 6); lba_to_chs(off + size - 1, &cyl, &head, §); mbr.parttab[partno].endcyl = cyl & 0xFF; mbr.parttab[partno].endhead = head; mbr.parttab[partno].endsect = sect | ((cyl >> 8) << 6); }
/* * And now, it's time to implenent the read or write function, that's * all the floppy driver mean! * * Read/Write one sector once. */ static int floppy_rw(int sector, char *buf, int command) { int head; char *dma_buffer = buf; static char tmp_dma_buffer[512]; //LOG("TMP dma buffer: %p\n", tmp_dma_buffer); lba_to_chs(sector, &head, &track, §or); LOG("head: %d \ttrack: %d \tsector: %d\n", head, track, sector); /* turn it on if not */ motor_on(); if (inb_p(FD_DIR) & 0x80) { changed = TRUE; seek(1, head); /* clear "disk change" status */ recalibrate(); motor_off(); printk("floppy_rw: Disk change detected. You are going to DIE:)\n"); pause(); /* just put it in DIE */ } /* move head to the right track */ if (!seek(track, head)) { motor_off(); printk("floppy_rw: Error seeking to track#%d\n", track); return FALSE; } if ((unsigned long)buf >= 0xff000) { dma_buffer = tmp_dma_buffer; if (command == FD_WRITE) memcpy(dma_buffer, buf, 512); } setup_DMA((unsigned long)dma_buffer, command); send_byte(command); send_byte(head<<2 | 0); send_byte(track); send_byte(head); send_byte(sector); send_byte(2); /* sector size = 125 * 2^(2) */ send_byte(floppy.sector); send_byte(0); send_byte(0xFF); /* sector size(only two valid vaules, 0xff when n!=0*/ if (!wait_fdc(FALSE)) { //LOG("wait fdc failed!\n"); //return 0; /* printk("Time out, trying operation again after reset() \n"); reset(); return floppy_rw(sector, buf, command); */ } motor_off(); if (/*res != 7 || */(ST0 & 0xf8) || (ST1 & 0xbf) || (ST2 & 0x73) ) { if (ST1 & 0x02) LOG("Drive is write protected!\n"); else LOG("floppy_rw: bad interrupt!\n"); return -EIO; } else { LOG("floppy_rw: OK\n"); if ((unsigned long)buf >= 0xff000 && command == FD_READ) memcpy(buf, dma_buffer, 512); return 0; } }