+#include <dprintf.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define RETRY_COUNT 6
-static uint16_t MaxTransfer = 1 << (16 - 9);
-
static int chs_rdwr_sectors(struct disk *disk, void *buf,
sector_t lba, size_t count, bool is_write)
{
while (count) {
chunk = count;
- if (chunk > MaxTransfer)
- chunk = MaxTransfer;
+ if (chunk > disk->maxtransfer)
+ chunk = disk->maxtransfer;
freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
/* For any starting value, this will always end with ..., 1, 0 */
chunk >>= 1;
if (chunk) {
- MaxTransfer = chunk;
+ disk->maxtransfer = chunk;
retry = RETRY_COUNT;
ireg.eax.b[0] = chunk;
continue;
lba += disk->part_start;
while (count) {
chunk = count;
- if (chunk > MaxTransfer)
- chunk = MaxTransfer;
+ if (chunk > disk->maxtransfer)
+ chunk = disk->maxtransfer;
freeseg = (0x10000 - ((size_t)ptr & 0xffff)) >> sector_shift;
if (tptr != ptr && is_write)
memcpy(tptr, ptr, bytes);
- pkt.size = sizeof pkt;
- pkt.blocks = chunk;
- pkt.buf = FAR_PTR(tptr);
- pkt.lba = lba;
-
retry = RETRY_COUNT;
for (;;) {
+ pkt.size = sizeof pkt;
+ pkt.blocks = chunk;
+ pkt.buf = FAR_PTR(tptr);
+ pkt.lba = lba;
+
__intcall(0x13, &ireg, &oreg);
if (!(oreg.eflags.l & EFLAGS_CF))
break;
/* For any starting value, this will always end with ..., 1, 0 */
chunk >>= 1;
if (chunk) {
- MaxTransfer = chunk;
+ disk->maxtransfer = chunk;
retry = RETRY_COUNT;
- pkt.blocks = chunk;
continue;
}
struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start,
- uint16_t bsHeads, uint16_t bsSecPerTrack)
+ uint16_t bsHeads, uint16_t bsSecPerTrack,
+ uint32_t MaxTransfer)
{
static struct disk disk;
static __lowmem struct edd_disk_params edd_params;
com32sys_t ireg, oreg;
bool ebios = cdrom;
int sector_size = cdrom ? 2048 : 512;
+ unsigned int hard_max_transfer = ebios ? 127 : 63;
memset(&ireg, 0, sizeof ireg);
if (cdrom || (!(oreg.eflags.l & EFLAGS_CF) &&
oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1))) {
ebios = true;
+ hard_max_transfer = 127;
/* Query EBIOS parameters */
edd_params.len = sizeof edd_params;
disk.part_start = part_start;
disk.rdwr_sectors = ebios ? edd_rdwr_sectors : chs_rdwr_sectors;
+ if (!MaxTransfer || MaxTransfer > hard_max_transfer)
+ MaxTransfer = hard_max_transfer;
+
+ disk.maxtransfer = MaxTransfer;
+
return &disk;
}
* NOTE: the disk cache needs to be revamped to support multiple devices...
*/
struct device * device_init(uint8_t devno, bool cdrom, sector_t part_start,
- uint16_t bsHeads, uint16_t bsSecPerTrack)
+ uint16_t bsHeads, uint16_t bsSecPerTrack,
+ uint32_t MaxTransfer)
{
static struct device dev;
static __hugebss char diskcache[128*1024];
- dev.disk = disk_init(devno, cdrom, part_start, bsHeads, bsSecPerTrack);
+ dev.disk = disk_init(devno, cdrom, part_start,
+ bsHeads, bsSecPerTrack, MaxTransfer);
dev.cache_data = diskcache;
dev.cache_size = sizeof diskcache;
sector_t disk_offset = regs->ecx.l | ((sector_t)regs->ebx.l << 32);
uint16_t disk_heads = regs->esi.w[0];
uint16_t disk_sectors = regs->edi.w[0];
+ uint32_t maxtransfer = regs->ebp.l;
int blk_shift = -1;
struct device *dev = NULL;
/* ops is a ptr list for several fs_ops */
} else {
if (!dev)
dev = device_init(disk_devno, disk_cdrom, disk_offset,
- disk_heads, disk_sectors);
+ disk_heads, disk_sectors, maxtransfer);
fs.fs_dev = dev;
}
/* invoke the fs-specific init code */
sector_t part_start; /* the start address of this partition(in sectors) */
+ uint32_t maxtransfer; /* Max sectors per transfer */
+
int (*rdwr_sectors)(struct disk *, void *, sector_t, size_t, bool);
};
extern void getoneblk(struct disk *, char *, block_t, int);
/* diskio.c */
-struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t);
-struct device *device_init(uint8_t, bool, sector_t, uint16_t, uint16_t);
+struct disk *disk_init(uint8_t, bool, sector_t, uint16_t, uint16_t, uint32_t);
+struct device *device_init(uint8_t, bool, sector_t, uint16_t, uint16_t, uint32_t);
#endif /* DISK_H */