DRESULT disk_write ( BYTE pdrv, /* Physical drive nmuber (0) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector number (LBA) */ UINT count /* Sector count (1..128) */ ) { if (pdrv || !count) return RES_PARERR; if (Stat & STA_NOINIT) return RES_NOTRDY; /* Issue Write Setor(s) command */ if (!issue_rwcmd(CMD_WRITE, sector, count)) return RES_ERROR; /* Send data blocks */ do { if (!wait_stat(2000, DRQ)) return RES_ERROR; write_block(buff); buff += 512; } while (--count); /* Wait for end of write process */ if (!wait_stat(1000, 0)) return RES_ERROR; read_ata(REG_ALTSTAT); read_ata(REG_STATUS); return RES_OK; }
DRESULT disk_ioctl ( BYTE pdrv, /* Physical drive nmuber (0) */ BYTE cmd, /* Control code */ void *buff /* Buffer to send/receive data block */ ) { BYTE n, w, ofs, dl, dh, *ptr = (BYTE*)buff; if (pdrv) return RES_PARERR; if (Stat & STA_NOINIT) return RES_NOTRDY; switch (cmd) { case GET_BLOCK_SIZE : /* Get erase block size in sectors (DWORD) */ *(DWORD*)buff = 128; return RES_OK; case CTRL_SYNC : /* Nothing to do */ return RES_OK; } switch (cmd) { case GET_SECTOR_COUNT : ofs = 60; w = 2; n = 0; break; case ATA_GET_REV : /* Get firmware revision (8 chars) */ ofs = 23; w = 4; n = 4; break; case ATA_GET_MODEL : /* Get model name (40 chars) */ ofs = 27; w = 20; n = 20; break; case ATA_GET_SN : /* Get serial number (20 chars) */ ofs = 10; w = 10; n = 10; break; default: return RES_PARERR; } if (!wait_stat(1000, DRDY)) return RES_ERROR; write_ata(REG_COMMAND, CMD_IDENTIFY); /* Get device ID data block */ if (!wait_stat(1000, DRQ)) return RES_ERROR; /* Wait for data ready */ read_block_part(ptr, ofs, w); /* Get a part of data block */ while (n--) { /* Swap byte order */ dl = *ptr++; dh = *ptr--; *ptr++ = dh; *ptr++ = dl; } read_ata(REG_ALTSTAT); read_ata(REG_STATUS); return RES_OK; }
static struct fat_dir_entry *get_dir_entry(struct fat32_fs *fs, unsigned int rel_cluster) { struct fat_dir_entry *dir = kmalloc(sizeof(struct fat_dir_entry)); if (!read_ata(fs->d, abs_cluster(fs, rel_cluster), dir, //if (!read_ata(fs->d, rel_cluster, dir, sizeof(struct fat_dir_entry))) { kfree(dir); kprintf("Could not find on disk\n"); return NULL; } /* The root entry will have VOLUME_ID and not DIRECTORY set */ if (dir->attr & ATTR_VOLUME_ID) { return dir; } else { if (dir->dirname[0] == 0x00 || dir->dirname[0] == 0xE5) { kprintf("Unused entry\n"); return NULL; } else if (!(dir->attr & ATTR_DIRECTORY)) { kprintf("Entry exists, but isn't a dir\n"); return NULL; } else { return dir; } } }
static unsigned char *read_fat(struct fat32_fs *fs, unsigned int start_sector) { unsigned char *table = kmalloc(FAT32_CLUSTER_SIZE); if (!read_ata(fs->d, start_sector, table, FAT32_CLUSTER_SIZE)) { kprintf("Couldn't read file allocation table\n"); return NULL; } return table; }
static int wait_stat ( /* 0:Timeout or or ERR goes 1 */ UINT ms, BYTE bit ) { BYTE s; set_timer(ms); do { s = read_ata(REG_STATUS); /* Get status */ if (!get_timer() || (s & ERR)) return 0; /* Abort when timeout or error occured */ } while ((s & BSY) || (bit && !(bit & s))); /* Wait for BSY goes 0 and the bit goes 1 */ read_ata(REG_ALTSTAT); return 1; }
DRESULT disk_read ( BYTE pdrv, /* Physical drive nmuber (0) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector number (LBA) */ UINT count /* Sector count (1..128) */ ) { if (pdrv || !count) return RES_PARERR; if (Stat & STA_NOINIT) return RES_NOTRDY; /* Issue Read Setor(s) command */ if (!issue_rwcmd(CMD_READ, sector, count)) return RES_ERROR; /* Receive data blocks */ do { if (!wait_stat(2000, DRQ)) return RES_ERROR; read_block(buff); buff += 512; } while (--count); read_ata(REG_ALTSTAT); read_ata(REG_STATUS); return RES_OK; }
struct fat32_fs *mount_fat32(struct drive *d) { struct fat_boot_sector *bs = kmalloc(512); if (!read_ata(d, 0, bs, 512)) { kprintf("Failed to read sector 0\n"); kfree(bs); return NULL; } /* Treat bootjmp as magic */ if (bs->bootjmp[0] != 0xEB && bs->bootjmp[0] != 0xE9) { kprintf("There is no FAT32 file system here\n"); kfree(bs); return NULL; } /* null-terminate all of the string fields */ bs->oem_name[7] = '\0'; bs->fat32.volume_label[10] = '\0'; bs->fat32.fat_type_label[5] = '\0'; /* Verify this is FAT32 */ if (strcmp((char *)bs->fat32.fat_type_label, "FAT32") != 0) { kprintf("There is a FAT file system here, but it's not FAT32: `%s`\n", bs->fat32.fat_type_label); return NULL; } /* Populate the file system struct */ struct fat32_fs *fs = kmalloc(sizeof(struct fat32_fs)); fs->d = d; fs->bs = bs; fs->first_data_sector = bs->reserved_sector_count + (bs->table_count * bs->table_size_16); fs->table = read_fat(fs, fs->first_data_sector); kprintf("Mounted FAT32 file system with label `%s`\n", bs->fat32.volume_label); return fs; }