assert(hba != NULL);
assert(port != NULL);
- assert(port_index >= 0 && port_index < MAX_SATA_DEVICES);
+ assert(port_index >= 0 && port_index < AHCI_PORT_COUNT);
assert(index >= 0 && index < MAX_SATA_DEVICES);
sata_device_t* sata = sata_devices + index;
sata->index = index;
sata->port_index = port_index;
+ init_completion(&sata->completion);
+
printk("ahci port clb %08x fb %08x sata_status 0x%08X signature %08X\n", port->cmd_list_base, port->fis_base,
port->sata_status, port->signature);
sata->cmd_table_vaddr = (ahci_cmd_table_t*)ioremap(sata->cmd_table_paddr, PAGE_SIZE);
memset((void*)sata->cmd_table_vaddr, 0, PAGE_SIZE);
- sata->data_paddr = (paddr_t)page2pa(alloc_one_page(0));
- sata->data_vaddr = (vaddr_t)ioremap(sata->data_paddr, PAGE_SIZE);
- memset((void*)sata->data_vaddr, 0, PAGE_SIZE);
-
memset((void*)cmd_list, 0, sizeof(ahci_cmd_header_t));
cmd_list[0].cfl = 0;
cmd_list[0].a = 0;
max_sata_devices += 1;
- memset(sector, 0xCC, 512);
- sata_dma_read(sata, 0, 1, (paddr_t)va2pa(sector));
- printk("sector %08x\n", (uint32_t*)sector);
+ // memset(sector, 0xCC, 512);
+ // sata_dma_read(sata, 0, 1, (paddr_t)va2pa(sector));
+ // printk("sector %08x\n", (uint32_t*)sector);
}
void sata_irq_handler(unsigned int irq, pt_regs_t* regs, void* dev_id) {
//
}
+ complete(&sata->completion);
+
port->interrupt_status = interrupt_status;
}
return -1;
}
-int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, paddr_t paddr) {
+int sata_dma_read(sata_device_t* sata, uint64_t lba, uint32_t sectors, vaddr_t vaddr) {
assert(sata != NULL);
assert(sectors <= 4);
assert(lba + sectors <= sata->max_lba);
}
//
- sata->prdte0->data_base = paddr;
+ sata->prdte0->data_base = va2pa(vaddr);
sata->prdte0->data_byte_count = (bytes - 1) | 1;
sata->prdte0->ioc = 1;
void sata_identify(sata_device_t* sata) {
assert(sata != NULL);
- sata->prdte0->data_base = sata->data_paddr;
+
+ paddr_t data_paddr = (paddr_t)page2pa(alloc_one_page(0));
+ vaddr_t data_vaddr = (vaddr_t)ioremap(data_paddr, PAGE_SIZE);
+ memset((void*)data_vaddr, 0, PAGE_SIZE);
+
+ sata->prdte0->data_base = data_paddr;
sata->prdte0->data_byte_count = (512 - 1) | 1;
sata->prdte0->ioc = 0;
sata->cmd_list0->prdtl = 1;
sata->cmd_list0->w = 0; // read
sata->cmd_list0->a = 0; // ata device
- sata->cmd_list0->c = 1;
+ sata->cmd_list0->c = 1; // 自动清除BSY位
sata->cmd_list0->prd_byte_count = 0;
// 清除中断状态
assert(port != NULL);
port->interrupt_status = port->interrupt_status;
+#if 0
//
port->interrupt_enable = AHCI_INTERRUPT_ENABLE_DHRS;
+#endif
//
port->cmd_issue = 1 << 0;
uint32_t timeout = 1000000;
while (timeout--) {
+ if ((port->cmd_issue) & (1 << 0) == 0) {
+ break;
+ }
+ // 不启用中断也仍然会设置
if (port->interrupt_status & 1) {
printk("SATA INTERRUPT STATUS: %08x\n", port->interrupt_status);
// 清除本次请求产生的中断
- port->interrupt_status = 1;
+ port->interrupt_status = port->interrupt_status;
break;
}
if (port->sata_error) {
printk("SATA ERROR: %08x\n", port->sata_error);
- return;
+ goto end;
}
asm("pause");
}
if (timeout == 0) {
printk("SATA TIMEOUT\n");
- return;
+ goto end;
}
if (sata->cmd_list0->prd_byte_count != 512) {
printk("SATA PRD BYTE COUNT: %08x\n", sata->cmd_list0->prd_byte_count);
- return;
+ goto end;
}
- printk("identify data %08x\n", sata->data_vaddr);
- uint16_t* identify = (uint16_t*)sata->data_vaddr;
+ printk("identify data %08x\n", data_vaddr);
+ uint16_t* identify = (uint16_t*)data_vaddr;
// 第49个word的第8个bit位表示是否支持DMA
// 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
sata_read_identify_string(identify, 27, 46, s);
printk("HD Model: %s\n", s);
+
+end:
+ iounmap(data_vaddr);
+ free_pages((unsigned long)pa2va(data_paddr));
}
void sata_read_identify_string(const uint16_t* identify, int bgn, int end, char* buf) {
* ------------------------------------------------------------------------
* File Name: task_disk.c
* Author: Zhao Yanbai
- * 2021-11-15 12:19:00 Monday CST
+ * 2026-01-25 09:53:51 Sunday CST
* Description: none
* ------------------------------------------------------------------------
*/
-#include <completion.h>
#include <disk.h>
-#include <ide.h>
-#include <sched.h>
-
-void ata_read_identify(int drv, int disable_intr);
-void ata_pio_read_data(int drvid, int sect_cnt, void* dst);
-void ata_dma_read_ext(int drv, uint64_t pos, uint16_t count, void* dest);
-
-int send_disk_request(disk_request_t* r) {
-#if DISABLE_IDE
- return 0;
-#endif
- if (NULL == r) {
- panic("null disk request");
- }
-
- ide_drive_t* drv = ide_get_drive(r->dev);
-
- assert(drv->present == 1);
-
- // 这个用来让task_disk唤醒自己
- semaphore_init(&r->sem, 0);
+#include <completion.h>
+#include <sata.h>
+// #include
- r->ret = 0;
+disk_request_queue_t disk_request_queue;
- // 校验pos,和pos+count是否大于硬盘返回的最大LBA48
- // ...
+void init_disk_request_queue() {
+ INIT_LIST_HEAD(&disk_request_queue.list);
+ mutex_init(&disk_request_queue.mutex);
+ semaphore_init(&disk_request_queue.sem, 0);
+}
- // 校验buffer是否跨64K
- // 先不处理
+int send_disk_request(disk_request_t* req) {
+ assert(req != NULL);
+ assert(req->count != 0);
+ assert(req->buf != NULL);
-#if 1
{
- const uint32_t size = r->count * 512;
+ const uint32_t size = req->count * 512;
const uint32_t _64K = 1 << 16;
- assert(((((uint32_t)r->buf) & (_64K - 1)) + size) <= _64K);
+ assert(((((uint32_t)req->buf) & (_64K - 1)) + size) <= _64K);
}
-#else
- if (((uint32_t)r->buf & 0xFFFF0000) != (((uint32_t)(r->buf + r->count * 512 - 1)) & 0xFFFF0000)) {
- printk("dma read addr %08x count %d\n", r->buf, r->count);
- panic("disk DMA read cross 64K");
- }
-#endif
- mutex_lock(&drv->ide_pci_controller->request_mutex);
- atomic_inc(&drv->ide_pci_controller->request_cnt);
- list_add_tail(&r->list, &drv->ide_pci_controller->request_queue.list);
- mutex_unlock(&drv->ide_pci_controller->request_mutex);
+ init_completion(&req->completion);
- // 唤醒task_disk
- up(&drv->ide_pci_controller->request_queue.sem);
+ //
+ mutex_lock(&disk_request_queue.mutex);
+ list_add_tail(&req->list, &disk_request_queue.list);
+ disk_request_queue.req_count++;
+ disk_request_queue.pending_count++;
+ mutex_unlock(&disk_request_queue.mutex);
- // 等待被task_disk唤醒
- down(&r->sem);
+ //
+ up(&disk_request_queue.sem);
- return r->ret;
-}
+ //
+ wait_completion(&req->completion);
-void disk_task_entry(void* arg) {
- int r_cnt = 0;
- while (1) {
- int channel = (int)arg;
- ide_pci_controller_t* ide_ctrl = ide_pci_controller + channel;
-
-#if 1
- // 为了在DEBUG时看到RUN
- int cnt = 2;
- for (int i = 0; i < cnt; i++) {
- asm("hlt;");
- }
-#endif
+ return 0;
+}
- // printk("wait request for hard disk channel %d\n", channel);
- down(&ide_ctrl->request_queue.sem);
- // printk("hard disk channel %d\n", channel);
+void disk_request(disk_request_t* req) {
+ int minor = DEV_MINOR(req->dev);
+ printk("disk_request dev %x minor %d\n", req->dev, minor);
+ assert(minor == 0); // 先简单支持
+ assert(req->command == DISK_REQ_READ);
- mutex_lock(&ide_ctrl->request_mutex);
- disk_request_t* r;
- r = list_first_entry(&ide_ctrl->request_queue.list, disk_request_t, list);
- if (NULL == r) {
- panic("no disk request");
- }
+ sata_device_t* sata = &sata_devices[0];
- list_del(&r->list);
- atomic_inc(&ide_ctrl->consumed_cnt);
- mutex_unlock(&ide_ctrl->request_mutex);
+ //
+ init_completion(&sata->completion);
- ide_drive_t* drv = ide_get_drive(r->dev);
- int drvid = drv->drvid;
- if (drv->present == 0) {
- panic("disk not present");
- }
- assert(drv->present == 1);
-
- int part_id = DEV_MINOR((r->dev)) & 0xFF;
- assert(part_id < MAX_DISK_PARTIONS);
- assert(MAKE_DISK_DEV(drvid, part_id) == r->dev);
-
- uint64_t pos = r->pos + drv->partions[part_id].lba_start;
- // printk("pos %lu partid %d lba end %lu\n", pos, part_id, drv->partions[part_id].lba_end);
- // assert(pos < drv->partions[part_id].lba_end);
- if ((pos >= drv->partions[part_id].lba_end)) {
- printk("pos %lu partid %d lba %lu %lu\n", pos, part_id, drv->partions[part_id].lba_start,
- drv->partions[part_id].lba_end);
- panic("INVARG");
- }
+ sata_dma_read(sata, req->pos, req->count, (vaddr_t)req->buf);
- const bool pio_mode = false;
- init_completion(&ide_ctrl->intr_complete);
-
- switch (r->command) {
- case DISK_REQ_IDENTIFY:
- printk("try to read disk drive %u identify\n", drvid);
- assert(r->count == 1);
- ata_read_identify(drvid, 0);
- break;
- case DISK_REQ_READ:
- assert(r->count > 0);
- assert(r->buf != NULL || r->bb->data != NULL);
- // printk("DISK READ drvid %u pos %u count %u bb %x\n", drvid, (uint32_t)pos, r->count, r->bb);
- if (pio_mode) {
- int ata_pio_read_ext(int drvid, uint64_t pos, uint16_t count, int timeout, void* dest);
- if (r->bb != 0) {
- ata_pio_read_ext(drvid, pos, r->count, 100, r->bb->data);
- } else {
- ata_pio_read_ext(drvid, pos, r->count, 100, r->buf);
- }
- } else {
- if (r->bb != 0) {
- ata_dma_read_ext(drvid, pos, r->count, r->bb->data);
- } else {
- ata_dma_read_ext(drvid, pos, r->count, r->buf);
- }
- }
- break;
- default:
- panic("invalid disk request command");
- break;
- }
+ wait_completion(&sata->completion);
+}
- int ret = 0;
- if (!pio_mode) {
- // 等待硬盘中断
- wait_completion(&ide_ctrl->intr_complete);
+void disk_task_entry() {
+ while (1) {
+ down(&disk_request_queue.sem);
- if ((ide_ctrl->status & (ATA_STATUS_BSY | ATA_STATUS_BSY | ATA_STATUS_WF)) != 0) {
- printk("IDE status %02X error for drv %u pos %lu count %u\n", ide_ctrl->status, drvid, pos, r->count);
- ret = -1;
- }
- }
+ mutex_lock(&disk_request_queue.mutex);
+ assert(!list_empty(&disk_request_queue.list));
+ disk_request_t* req = list_first_entry(&disk_request_queue.list, disk_request_t, list);
+ list_del(&req->list);
+ disk_request_queue.pending_count--;
+ mutex_unlock(&disk_request_queue.mutex);
- // 读数据
- if (DISK_REQ_IDENTIFY == r->command) {
- ata_pio_read_data(drvid, 1, r->buf);
- }
+ //
+ disk_request(req);
- if (r->bb != 0) {
- r->bb->uptodate = 1;
- complete(&r->bb->io_done);
- }
+ //
+ complete(&req->completion);
- r->ret = ret;
+ disk_request_queue.completed_count++; // 不需要保护
- // 唤醒等待该请求的进程
- up(&(r->sem));
+ for (int i = 0; i < 123; i++) {
+ asm("hlt");
+ }
}
}