From: acevest Date: Mon, 13 May 2024 11:11:27 +0000 (+0800) Subject: 硬盘PIO_EXT读支持一次读多个扇区 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=refs%2Fheads%2Fdev%2F202405%2Fdisk_pio_ext;p=kernel.git 硬盘PIO_EXT读支持一次读多个扇区 --- diff --git a/drivers/ata.c b/drivers/ata.c index fca0bba..3e22617 100644 --- a/drivers/ata.c +++ b/drivers/ata.c @@ -71,6 +71,7 @@ void ata_read_identity_string(const uint16_t *identify, int bgn, int end, char * buf[i] = 0; } +uint16_t max_sectors_per_transfer = 0; // 《AT Attachment 8 - ATA/ATAPI Command Set》 void ide_ata_init() { for (int i = 0; i < MAX_IDE_DRIVE_CNT; i++) { @@ -205,6 +206,8 @@ void ide_ata_init() { // 低8位0x00代表Reserved,0x01~0xFF代表每次最大传输扇区数 printk("A: %04x\n", identify[47]); // 高 8 位保留,低 8 位表示最大扇区数 + max_sectors_per_transfer = identify[47]; + // 第8位为1表示多扇区设置有效 // 当前设置的一次传送的扇区数 printk("B: %04x\n", identify[59]); @@ -473,6 +476,8 @@ int ata_dma_stop(int channel) { // ATA_CMD_READ_PIO_EXT int ata_pio_read_ext(int drv, uint64_t pos, uint16_t count) { + assert(count <= max_sectors_per_transfer); + // 不再设置nIEN,需要中断 outb(0x00, REG_CTL(drv)); @@ -504,7 +509,7 @@ int ata_pio_read_ext(int drv, uint64_t pos, uint16_t count) { nop(); } - outb(ATA_CMD_READ_PIO_EXT, REG_CMD(drv)); + outb(ATA_CMD_READ_MULTIPLE_EXT, REG_CMD(drv)); return 0; } diff --git a/drivers/ata.h b/drivers/ata.h index e62aee3..9cec84a 100644 --- a/drivers/ata.h +++ b/drivers/ata.h @@ -71,21 +71,27 @@ extern unsigned int IDE_CHL1_CTL_BASE; #define ATA_STATUS_ERR 0x01 /* error */ #define ATA_CMD_IDLE 0x00 +#define ATA_CMD_DEVICE_RESET 0x08 #define ATA_CMD_RECALIBRATE 0x10 #define ATA_CMD_READ_PIO 0x20 /* read data */ #define ATA_CMD_READ_PIO_EXT 0x24 /* read data (LBA-48 bit)*/ #define ATA_CMD_READ_DMA 0xC8 #define ATA_CMD_READ_DMA_EXT 0x25 /* read data DMA LBA48 */ +#define ATA_CMD_READ_MULTIPLE_EXT 0x29 #define ATA_CMD_WRITE_PIO 0x30 #define ATA_CMD_WRITE_PIO_EXT 0x34 #define ATA_CMD_WRITE_DMA 0xCA #define ATA_CMD_WRITE_DMA_EXT 0X35 +#define ATA_CMD_WRITE_MULTIPLE_EXT 0x37 #define ATA_CMD_READ_VERIFY 0x40 #define ATA_CMD_FORMAT 0x50 #define ATA_CMD_SEEK 0x70 #define ATA_CMD_DIAG 0x90 #define ATA_CMD_SPECIFY 0x91 #define ATA_CMD_IDENTIFY_PACKET 0xA1 +#define ATA_CMD_READ_MULTIPLE 0xC4 +#define ATA_CMD_WRITE_MULTIPLE 0xC5 +#define ATA_CMD_SET_MULTIPLE_MODE 0xC6 #define ATA_CMD_IDENTIFY 0xEC #define ATA_CTL 0 diff --git a/gdbscript b/gdbscript index d5fe482..89fe90e 100644 --- a/gdbscript +++ b/gdbscript @@ -18,6 +18,8 @@ target remote localhost:1234 set pagination off +#b task_disk.c:97 + #b init_serial #b init_system_info diff --git a/kernel/task_disk.c b/kernel/task_disk.c index 59bde4a..0cdb866 100644 --- a/kernel/task_disk.c +++ b/kernel/task_disk.c @@ -101,6 +101,7 @@ void disk_task_entry(void *arg) { #if !DISK_DMA_MODE // 对于PIO的方式来说,一次只能操作一个扇区,所以有几个扇区就要重试几次 send_cmd_times = r->count; + send_cmd_times = 1; #endif for (int count = 0; count < send_cmd_times; count++) { switch (r->command) { @@ -114,9 +115,9 @@ void disk_task_entry(void *arg) { assert(r->buf != NULL || r->bb->data != NULL); #if !DISK_DMA_MODE if (r->bb != 0) { - ata_pio_read_ext(drv_no, pos + count, 1); + ata_pio_read_ext(drv_no, pos + count, r->count); } else { - ata_pio_read_ext(drv_no, pos + count, 1); + ata_pio_read_ext(drv_no, pos + count, r->count); } #else if (r->bb != 0) { @@ -141,9 +142,9 @@ void disk_task_entry(void *arg) { if (DISK_REQ_READ == r->command || DISK_REQ_IDENTIFY == r->command) { uint32_t offset = SECT_SIZE * count; if (r->bb != 0) { - ata_pio_read_data(drv_no, 1, r->bb->data + offset); + ata_pio_read_data(drv_no, r->count, r->bb->data + offset); } else { - ata_pio_read_data(drv_no, 1, r->buf + offset); + ata_pio_read_data(drv_no, r->count, r->buf + offset); } }