feat: disk read/write support for both ATA and ATAPI device
authorMinep <zelong56@gmail.com>
Tue, 5 Jul 2022 16:23:10 +0000 (17:23 +0100)
committerMinep <zelong56@gmail.com>
Tue, 5 Jul 2022 16:23:10 +0000 (17:23 +0100)
feat: vcalloc and vcalloc_dma wrapper
refactor: no need tranverse down partial list when grabing a cake!

12 files changed:
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/ata.c [new file with mode: 0644]
lunaix-os/hal/ahci/atapi.c
lunaix-os/hal/ahci/utils.c
lunaix-os/includes/hal/ahci/ahci.h
lunaix-os/includes/hal/ahci/hba.h
lunaix-os/includes/hal/ahci/sata.h
lunaix-os/includes/hal/ahci/scsi.h
lunaix-os/includes/hal/ahci/utils.h
lunaix-os/includes/lunaix/mm/valloc.h
lunaix-os/kernel/mm/cake.c
lunaix-os/kernel/mm/valloc.c

index 6771bb690248412bfc1d9455551ed5d7af2e4898..a723c204ace1b34bc7c2e0a385e889375c0e9dff 100644 (file)
@@ -36,6 +36,24 @@ __ahci_hba_isr(isr_param param);
 int
 ahci_init_device(struct hba_port* port);
 
 int
 ahci_init_device(struct hba_port* port);
 
+void
+achi_register_ops(struct hba_port* port);
+
+unsigned int
+ahci_get_port_usage()
+{
+    return hba.ports_bmp;
+}
+
+struct hba_port*
+ahci_get_port(unsigned int index)
+{
+    if (index >= 32) {
+        return 0;
+    }
+    return hba.ports[index];
+}
+
 void
 ahci_init()
 {
 void
 ahci_init()
 {
@@ -70,12 +88,14 @@ ahci_init()
 
     // As per section 3.1.1, this is 0 based value.
     hba_reg_t cap = hba.base[HBA_RCAP];
 
     // As per section 3.1.1, this is 0 based value.
     hba_reg_t cap = hba.base[HBA_RCAP];
+    hba_reg_t pmap = hba.base[HBA_RPI];
+
     hba.ports_num = (cap & 0x1f) + 1;  // CAP.PI
     hba.cmd_slots = (cap >> 8) & 0x1f; // CAP.NCS
     hba.version = hba.base[HBA_RVER];
     hba.ports_num = (cap & 0x1f) + 1;  // CAP.PI
     hba.cmd_slots = (cap >> 8) & 0x1f; // CAP.NCS
     hba.version = hba.base[HBA_RVER];
+    hba.ports_bmp = pmap;
 
     /* ------ HBA端口配置 ------ */
 
     /* ------ HBA端口配置 ------ */
-    hba_reg_t pmap = hba.base[HBA_RPI];
     uintptr_t clb_pg_addr, fis_pg_addr, clb_pa, fis_pa;
     for (size_t i = 0, fisp = 0, clbp = 0; i < 32;
          i++, pmap >>= 1, fisp = (fisp + 1) % 16, clbp = (clbp + 1) % 4) {
     uintptr_t clb_pg_addr, fis_pg_addr, clb_pa, fis_pa;
     for (size_t i = 0, fisp = 0, clbp = 0; i < 32;
          i++, pmap >>= 1, fisp = (fisp + 1) % 16, clbp = (clbp + 1) % 4) {
@@ -176,7 +196,7 @@ ahci_list_device()
         }
         kprintf("\t\t capacity: %d KiB\n",
                 (dev_info->max_lba * dev_info->block_size) >> 10);
         }
         kprintf("\t\t capacity: %d KiB\n",
                 (dev_info->max_lba * dev_info->block_size) >> 10);
-        kprintf("\t\t sector size: %dB\n", dev_info->block_size);
+        kprintf("\t\t block size: %dB\n", dev_info->block_size);
         kprintf("\t\t model: %s\n", &dev_info->model);
         kprintf("\t\t serial: %s\n", &dev_info->serial_num);
     }
         kprintf("\t\t model: %s\n", &dev_info->model);
         kprintf("\t\t serial: %s\n", &dev_info->serial_num);
     }
@@ -197,8 +217,7 @@ __get_free_slot(struct hba_port* port)
 void
 sata_create_fis(struct sata_reg_fis* cmd_fis,
                 uint8_t command,
 void
 sata_create_fis(struct sata_reg_fis* cmd_fis,
                 uint8_t command,
-                uint32_t lba_lo,
-                uint32_t lba_hi,
+                uint64_t lba,
                 uint16_t sector_count)
 {
     cmd_fis->head.type = SATA_REG_FIS_H2D;
                 uint16_t sector_count)
 {
     cmd_fis->head.type = SATA_REG_FIS_H2D;
@@ -206,13 +225,13 @@ sata_create_fis(struct sata_reg_fis* cmd_fis,
     cmd_fis->head.status_cmd = command;
     cmd_fis->dev = 0;
 
     cmd_fis->head.status_cmd = command;
     cmd_fis->dev = 0;
 
-    cmd_fis->lba0 = SATA_LBA_COMPONENT(lba_lo, 0);
-    cmd_fis->lba8 = SATA_LBA_COMPONENT(lba_lo, 8);
-    cmd_fis->lba16 = SATA_LBA_COMPONENT(lba_lo, 16);
-    cmd_fis->lba24 = SATA_LBA_COMPONENT(lba_lo, 24);
+    cmd_fis->lba0 = SATA_LBA_COMPONENT(lba, 0);
+    cmd_fis->lba8 = SATA_LBA_COMPONENT(lba, 8);
+    cmd_fis->lba16 = SATA_LBA_COMPONENT(lba, 16);
+    cmd_fis->lba24 = SATA_LBA_COMPONENT(lba, 24);
 
 
-    cmd_fis->lba32 = SATA_LBA_COMPONENT(lba_hi, 0);
-    cmd_fis->lba40 = SATA_LBA_COMPONENT(lba_hi, 8);
+    cmd_fis->lba32 = SATA_LBA_COMPONENT(lba, 32);
+    cmd_fis->lba40 = SATA_LBA_COMPONENT(lba, 40);
 
     cmd_fis->count = sector_count;
 }
 
     cmd_fis->count = sector_count;
 }
@@ -234,7 +253,6 @@ hba_alloc_slot(struct hba_port* port,
     memset(cmd_table, 0, sizeof(*cmd_table));
 
     // 将命令表挂到命令头上
     memset(cmd_table, 0, sizeof(*cmd_table));
 
     // 将命令表挂到命令头上
-    cmd_header->prdt_len = 1;
     cmd_header->cmd_table_base = vmm_v2p(cmd_table);
     cmd_header->options = HBA_CMDH_FIS_LEN(sizeof(struct sata_reg_fis)) |
                           HBA_CMDH_CLR_BUSY | (header_options & ~0x1f);
     cmd_header->cmd_table_base = vmm_v2p(cmd_table);
     cmd_header->options = HBA_CMDH_FIS_LEN(sizeof(struct sata_reg_fis)) |
                           HBA_CMDH_CLR_BUSY | (header_options & ~0x1f);
@@ -252,12 +270,14 @@ ahci_init_device(struct hba_port* port)
     struct hba_cmdt* cmd_table;
     struct hba_cmdh* cmd_header;
 
     struct hba_cmdt* cmd_table;
     struct hba_cmdh* cmd_header;
 
+    // 确保端口是空闲的
+    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY)));
+
     int slot = hba_alloc_slot(port, &cmd_table, &cmd_header, 0);
 
     // 清空任何待响应的中断
     port->regs[HBA_RPxIS] = 0;
     int slot = hba_alloc_slot(port, &cmd_table, &cmd_header, 0);
 
     // 清空任何待响应的中断
     port->regs[HBA_RPxIS] = 0;
-    port->device = valloc(sizeof(struct hba_device));
-    port->device->signature = port->regs[HBA_RPxSIG];
+    port->device = vcalloc(sizeof(struct hba_device));
 
     // 预备DMA接收缓存,用于存放HBA传回的数据
     uint16_t* data_in = (uint16_t*)valloc_dma(512);
 
     // 预备DMA接收缓存,用于存放HBA传回的数据
     uint16_t* data_in = (uint16_t*)valloc_dma(512);
@@ -271,12 +291,13 @@ ahci_init_device(struct hba_port* port)
     struct sata_reg_fis* cmd_fis = (struct sata_reg_fis*)cmd_table->command_fis;
 
     // 根据设备类型使用合适的命令
     struct sata_reg_fis* cmd_fis = (struct sata_reg_fis*)cmd_table->command_fis;
 
     // 根据设备类型使用合适的命令
-    if (port->device->signature == HBA_DEV_SIG_ATA) {
+    if (port->regs[HBA_RPxSIG] == HBA_DEV_SIG_ATA) {
         // ATA 一般为硬盘
         // ATA 一般为硬盘
-        sata_create_fis(cmd_fis, ATA_IDENTIFY_DEVICE, 0, 0, 0);
+        sata_create_fis(cmd_fis, ATA_IDENTIFY_DEVICE, 0, 0);
     } else {
         // ATAPI 一般为光驱,软驱,或者磁带机
     } else {
         // ATAPI 一般为光驱,软驱,或者磁带机
-        sata_create_fis(cmd_fis, ATA_IDENTIFY_PAKCET_DEVICE, 0, 0, 0);
+        port->device->flags |= HBA_DEV_FATAPI;
+        sata_create_fis(cmd_fis, ATA_IDENTIFY_PAKCET_DEVICE, 0, 0);
     }
 
     // PxCI寄存器置位,告诉HBA这儿有个数据需要发送到SATA端口
     }
 
     // PxCI寄存器置位,告诉HBA这儿有个数据需要发送到SATA端口
@@ -284,6 +305,12 @@ ahci_init_device(struct hba_port* port)
 
     wait_until(!(port->regs[HBA_RPxCI] & (1 << slot)));
 
 
     wait_until(!(port->regs[HBA_RPxCI] & (1 << slot)));
 
+    if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
+        // 有错误
+        sata_read_error(port);
+        goto fail;
+    }
+
     /*
         等待数据到达内存
         解析IDENTIFY DEVICE传回来的数据。
     /*
         等待数据到达内存
         解析IDENTIFY DEVICE传回来的数据。
@@ -292,7 +319,7 @@ ahci_init_device(struct hba_port* port)
     */
     ahci_parse_dev_info(port->device, data_in);
 
     */
     ahci_parse_dev_info(port->device, data_in);
 
-    if (port->device->signature == HBA_DEV_SIG_ATA) {
+    if (!(port->device->flags & HBA_DEV_FATAPI)) {
         goto done;
     }
 
         goto done;
     }
 
@@ -319,9 +346,11 @@ ahci_init_device(struct hba_port* port)
             * SATA AHCI HBA Spec, Section 5.3.7
             * SCSI Command Reference Manual, Section 3.26
     */
             * SATA AHCI HBA Spec, Section 5.3.7
             * SCSI Command Reference Manual, Section 3.26
     */
-    sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0, 0);
     struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd;
     struct scsi_cdb16* cdb16 = (struct scsi_cdb16*)cmd_table->atapi_cmd;
-    scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 0, 512);
+
+    sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0);
+    scsi_create_packet16(cdb16, SCSI_READ_CAPACITY_16, 0, 512);
+
     cdb16->misc1 = 0x10; // service action
     cmd_header->transferred_size = 0;
     cmd_header->options |= HBA_CMDH_ATAPI;
     cdb16->misc1 = 0x10; // service action
     cmd_header->transferred_size = 0;
     cmd_header->options |= HBA_CMDH_ATAPI;
@@ -329,13 +358,46 @@ ahci_init_device(struct hba_port* port)
     port->regs[HBA_RPxCI] = (1 << slot);
     wait_until(!(port->regs[HBA_RPxCI] & (1 << slot)));
 
     port->regs[HBA_RPxCI] = (1 << slot);
     wait_until(!(port->regs[HBA_RPxCI] & (1 << slot)));
 
+    if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
+        // 有错误
+        sata_read_error(port);
+        goto fail;
+    }
+
     scsi_parse_capacity(port->device, (uint32_t*)data_in);
 
 done:
     scsi_parse_capacity(port->device, (uint32_t*)data_in);
 
 done:
+    achi_register_ops(port);
+
     vfree_dma(data_in);
     vfree_dma(cmd_table);
 
     return 1;
     vfree_dma(data_in);
     vfree_dma(cmd_table);
 
     return 1;
+
+fail:
+    vfree_dma(data_in);
+    vfree_dma(cmd_table);
+
+    return 0;
 }
 
 }
 
-// TODO: Support ATAPI Device.
\ No newline at end of file
+int
+ahci_identify_device(struct hba_port* port)
+{
+    // 用于重新识别设备(比如在热插拔的情况下)
+    vfree(port->device);
+    return ahci_init_device(port);
+}
+
+void
+achi_register_ops(struct hba_port* port)
+{
+    port->device->ops.identify = ahci_identify_device;
+    if (!(port->device->flags & HBA_DEV_FATAPI)) {
+        port->device->ops.read_buffer = sata_read_buffer;
+        port->device->ops.write_buffer = sata_write_buffer;
+    } else {
+        port->device->ops.read_buffer = scsi_read_buffer;
+        port->device->ops.write_buffer = scsi_write_buffer;
+    }
+}
\ No newline at end of file
diff --git a/lunaix-os/hal/ahci/ata.c b/lunaix-os/hal/ahci/ata.c
new file mode 100644 (file)
index 0000000..ea2e5f3
--- /dev/null
@@ -0,0 +1,88 @@
+#include <hal/ahci/hba.h>
+#include <hal/ahci/sata.h>
+
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+int
+__sata_buffer_io(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size,
+                 int write)
+{
+    assert_msg(((uintptr_t)buffer & 0x3) == 0, "HBA: Bad buffer alignment");
+
+    struct hba_cmdh* header;
+    struct hba_cmdt* table;
+    int slot = hba_alloc_slot(port, &table, &header, 0);
+    int bitmask = 1 << slot;
+
+    // 确保端口是空闲的
+    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY)));
+
+    port->regs[HBA_RPxIS] = 0;
+
+    table->entries[0] =
+      (struct hba_prdte){ .byte_count = size - 1, .data_base = buffer };
+    header->prdt_len = 1;
+    header->options |= HBA_CMDH_WRITE * (write == 1);
+
+    uint16_t count = size / port->device->block_size;
+    if (count == 0 && size < port->device->block_size) {
+        // 一个special case: 当count=0的时候,表示的是65536个区块会被传输
+        // 如果这个0是因为不够除而导致的,那么说明size太小了
+        goto fail;
+    }
+
+    struct sata_reg_fis* fis = table->command_fis;
+    if ((port->device->flags & HBA_DEV_FEXTLBA)) {
+        // 如果该设备支持48位LBA寻址
+        sata_create_fis(
+          fis, write ? ATA_WRITE_DMA_EXT : ATA_READ_DMA_EXT, lba, count);
+    } else {
+        sata_create_fis(fis, write ? ATA_WRITE_DMA : ATA_READ_DMA, lba, count);
+    }
+
+    port->regs[HBA_RPxCI] = bitmask;
+
+    wait_until(!(port->regs[HBA_RPxCI] & bitmask));
+
+    if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
+        // 有错误
+        sata_read_error(port);
+        goto fail;
+    }
+
+    vfree_dma(table);
+    return 1;
+
+fail:
+    vfree_dma(table);
+    return 0;
+}
+
+int
+sata_read_buffer(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size)
+{
+    return __sata_buffer_io(port, lba, buffer, size, 0);
+}
+
+int
+sata_write_buffer(struct hba_port* port,
+                  uint64_t lba,
+                  void* buffer,
+                  uint32_t size)
+{
+    return __sata_buffer_io(port, lba, buffer, size, 1);
+}
+
+void
+sata_read_error(struct hba_port* port)
+{
+    uint32_t tfd = port->regs[HBA_RPxTFD];
+    port->device->last_error = (tfd >> 8) & 0xff;
+}
\ No newline at end of file
index 193f8f30774a5bc65246286c99323ed26b6c7413..c245c0a060ac599529232205a5fc63751bffdb6d 100644 (file)
@@ -1,4 +1,5 @@
 #include <hal/ahci/hba.h>
 #include <hal/ahci/hba.h>
+#include <hal/ahci/sata.h>
 #include <hal/ahci/scsi.h>
 #include <hal/ahci/utils.h>
 
 #include <hal/ahci/scsi.h>
 #include <hal/ahci/utils.h>
 
@@ -20,14 +21,13 @@ scsi_create_packet12(struct scsi_cdb12* cdb,
 void
 scsi_create_packet16(struct scsi_cdb16* cdb,
                      uint8_t opcode,
 void
 scsi_create_packet16(struct scsi_cdb16* cdb,
                      uint8_t opcode,
-                     uint32_t lba_hi,
-                     uint32_t lba_lo,
+                     uint64_t lba,
                      uint32_t alloc_size)
 {
     memset(cdb, 0, sizeof(*cdb));
     cdb->opcode = opcode;
                      uint32_t alloc_size)
 {
     memset(cdb, 0, sizeof(*cdb));
     cdb->opcode = opcode;
-    cdb->lba_be_hi = SCSI_FLIP(lba_hi);
-    cdb->lba_be_lo = SCSI_FLIP(lba_lo);
+    cdb->lba_be_hi = SCSI_FLIP(lba >> 32);
+    cdb->lba_be_lo = SCSI_FLIP((uint32_t)lba);
     cdb->length = alloc_size;
 }
 
     cdb->length = alloc_size;
 }
 
@@ -36,4 +36,87 @@ scsi_parse_capacity(struct hba_device* device, uint32_t* parameter)
 {
     device->max_lba = SCSI_FLIP(*(parameter + 1));
     device->block_size = SCSI_FLIP(*(parameter + 2));
 {
     device->max_lba = SCSI_FLIP(*(parameter + 1));
     device->block_size = SCSI_FLIP(*(parameter + 2));
+}
+
+void
+__scsi_buffer_io(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size,
+                 int write)
+{
+    assert_msg(((uintptr_t)buffer & 0x3) == 0, "HBA: Bad buffer alignment");
+
+    struct hba_cmdh* header;
+    struct hba_cmdt* table;
+    int slot = hba_alloc_slot(port, &table, &header, 0);
+    int bitmask = 1 << slot;
+
+    // 确保端口是空闲的
+    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY)));
+
+    port->regs[HBA_RPxIS] = 0;
+
+    table->entries[0] =
+      (struct hba_prdte){ .byte_count = size - 1, .data_base = buffer };
+    header->prdt_len = 1;
+    header->options |= (HBA_CMDH_WRITE * (write == 1)) | HBA_CMDH_ATAPI;
+
+    uint32_t count = size / port->device->block_size;
+    if (count == 0) {
+        // 对ATAPI设备来说,READ/WRITE (16/12) 没有这个count=0的 special case
+        //  但是对于READ/WRITE (6),就存在这个special case
+        goto fail;
+    }
+
+    struct sata_reg_fis* fis = table->command_fis;
+    void* cdb = table->atapi_cmd;
+    sata_create_fis(fis, ATA_PACKET, (size << 8) & 0xffffff, 0);
+
+    if (port->device->cbd_size == 16) {
+        scsi_create_packet16((struct scsi_cdb16*)cdb,
+                             write ? SCSI_WRITE_BLOCKS_16 : SCSI_READ_BLOCKS_16,
+                             lba,
+                             count);
+    } else {
+        scsi_create_packet12((struct scsi_cdb12*)cdb,
+                             write ? SCSI_WRITE_BLOCKS_12 : SCSI_READ_BLOCKS_12,
+                             lba,
+                             count);
+    }
+
+    port->regs[HBA_RPxCI] = bitmask;
+
+    wait_until(!(port->regs[HBA_RPxCI] & bitmask));
+
+    if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
+        // 有错误
+        sata_read_error(port);
+        goto fail;
+    }
+
+    vfree_dma(table);
+    return 1;
+
+fail:
+    vfree_dma(table);
+    return 0;
+}
+
+void
+scsi_read_buffer(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size)
+{
+    __scsi_buffer_io(port, lba, buffer, size, 0);
+}
+
+void
+scsi_write_buffer(struct hba_port* port,
+                  uint64_t lba,
+                  void* buffer,
+                  uint32_t size)
+{
+    __scsi_buffer_io(port, lba, buffer, size, 1);
 }
\ No newline at end of file
 }
\ No newline at end of file
index 9af9cfee25ada3189cbffb1b4a5463dc75c1e7e4..23541ee9fe541aa9bacf85690df4babbd4e921d1 100644 (file)
@@ -2,24 +2,33 @@
 #include <hal/ahci/utils.h>
 #include <klibc/string.h>
 
 #include <hal/ahci/utils.h>
 #include <klibc/string.h>
 
-#define IDDEV_MAXLBA_OFFSET 60
-#define IDDEV_LSECSIZE_OFFSET 117
-#define IDDEV_WWN_OFFSET 108
-#define IDDEV_SERIALNUM_OFFSET 10
-#define IDDEV_MODELNUM_OFFSET 27
+#define IDDEV_OFFMAXLBA 60
+#define IDDEV_OFFMAXLBA_EXT 230
+#define IDDEV_OFFLSECSIZE 117
+#define IDDEV_OFFWWN 108
+#define IDDEV_OFFSERIALNUM 10
+#define IDDEV_OFFMODELNUM 27
+#define IDDEV_OFFADDSUPPORT 69
 
 void
 ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data)
 {
 
 void
 ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data)
 {
-    dev_info->max_lba = *((uint32_t*)(data + IDDEV_MAXLBA_OFFSET));
-    dev_info->block_size = *((uint32_t*)(data + IDDEV_LSECSIZE_OFFSET));
+    dev_info->max_lba = *((uint32_t*)(data + IDDEV_OFFMAXLBA));
+    dev_info->block_size = *((uint32_t*)(data + IDDEV_OFFLSECSIZE));
     dev_info->cbd_size = (*data & 0x3) ? 12 : 16;
     dev_info->cbd_size = (*data & 0x3) ? 12 : 16;
-    memcpy(&dev_info->wwn, (uint8_t*)(data + IDDEV_WWN_OFFSET), 8);
+    dev_info->wwn = *(uint64_t*)(data + IDDEV_OFFWWN);
+
     if (!dev_info->block_size) {
         dev_info->block_size = 512;
     }
     if (!dev_info->block_size) {
         dev_info->block_size = 512;
     }
-    ahci_parsestr(&dev_info->serial_num, data + IDDEV_SERIALNUM_OFFSET, 10);
-    ahci_parsestr(&dev_info->model, data + IDDEV_MODELNUM_OFFSET, 20);
+
+    if ((*(data + IDDEV_OFFADDSUPPORT) & 0x8)) {
+        dev_info->max_lba = *((uint64_t*)(data + IDDEV_OFFMAXLBA_EXT));
+        dev_info->flags |= HBA_DEV_FEXTLBA;
+    }
+
+    ahci_parsestr(&dev_info->serial_num, data + IDDEV_OFFSERIALNUM, 10);
+    ahci_parsestr(&dev_info->model, data + IDDEV_OFFMODELNUM, 20);
 }
 
 void
 }
 
 void
index 0494181d03efc7ecda592091b63cb69a9eefbc89..acd779b7152646c3aa09d815e58e6ebd13bffce0 100644 (file)
 
 #define AHCI_HBA_CLASS 0x10601
 
 
 #define AHCI_HBA_CLASS 0x10601
 
-#define ATA_IDENTIFY_DEVICE 0xec
-#define ATA_IDENTIFY_PAKCET_DEVICE 0xa1
-#define ATA_PACKET 0xa0
-
 /**
  * @brief 初始化AHCI与HBA
  *
 /**
  * @brief 初始化AHCI与HBA
  *
@@ -26,4 +22,10 @@ ahci_init();
 void
 ahci_list_device();
 
 void
 ahci_list_device();
 
+unsigned int
+ahci_get_port_usage();
+
+struct hba_port*
+ahci_get_port(unsigned int index);
+
 #endif /* __LUNAIX_AHCI_H */
 #endif /* __LUNAIX_AHCI_H */
index d836a78a423967ecd7349ec9360b805d71b9061b..19f76cd08603f8e57272d57685a7e01a586c0c43 100644 (file)
@@ -32,6 +32,9 @@
 #define HBA_PxCMD_ST (1)
 #define HBA_PxINTR_DMA (1 << 2)
 #define HBA_PxINTR_D2HR (1)
 #define HBA_PxCMD_ST (1)
 #define HBA_PxINTR_DMA (1 << 2)
 #define HBA_PxINTR_D2HR (1)
+#define HBA_PxTFD_ERR (1)
+#define HBA_PxTFD_BSY (1 << 7)
+#define HBA_PxTFD_DRQ (1 << 3)
 
 #define HBA_RGHC_ACHI_ENABLE (1 << 31)
 #define HBA_RGHC_INTR_ENABLE (1 << 1)
 
 #define HBA_RGHC_ACHI_ENABLE (1 << 31)
 #define HBA_RGHC_INTR_ENABLE (1 << 1)
@@ -82,15 +85,35 @@ struct hba_cmdt
     struct hba_prdte entries[3];
 } __HBA_PACKED__;
 
     struct hba_prdte entries[3];
 } __HBA_PACKED__;
 
+#define HBA_DEV_FEXTLBA 1
+#define HBA_DEV_FATAPI (1 << 1)
+
+struct hba_port;
+
 struct hba_device
 {
     char serial_num[20];
     char model[40];
 struct hba_device
 {
     char serial_num[20];
     char model[40];
-    uint32_t signature;
-    uint32_t max_lba;
+    uint32_t flags;
+    uint64_t max_lba;
     uint32_t block_size;
     uint32_t block_size;
-    uint8_t wwn[8];
+    uint64_t wwn;
     uint8_t cbd_size;
     uint8_t cbd_size;
+    uint8_t last_error;
+    uint8_t last_status;
+
+    struct
+    {
+        int (*identify)(struct hba_port* port);
+        int (*read_buffer)(struct hba_port* port,
+                           uint64_t lba,
+                           void* buffer,
+                           uint32_t size);
+        int (*write_buffer)(struct hba_port* port,
+                            uint64_t lba,
+                            void* buffer,
+                            uint32_t size);
+    } ops;
 };
 
 struct hba_port
 };
 
 struct hba_port
@@ -98,7 +121,7 @@ struct hba_port
     volatile hba_reg_t* regs;
     unsigned int ssts;
     struct hba_cmdh* cmdlst;
     volatile hba_reg_t* regs;
     unsigned int ssts;
     struct hba_cmdh* cmdlst;
-    struct sata_fis_head* fis;
+    void* fis;
     struct hba_device* device;
 };
 
     struct hba_device* device;
 };
 
@@ -106,6 +129,7 @@ struct ahci_hba
 {
     volatile hba_reg_t* base;
     unsigned int ports_num;
 {
     volatile hba_reg_t* base;
     unsigned int ports_num;
+    unsigned int ports_bmp;
     unsigned int cmd_slots;
     unsigned int version;
     struct hba_port* ports[32];
     unsigned int cmd_slots;
     unsigned int version;
     struct hba_port* ports[32];
index 135f3ebb58ca2819638bbed3d14d3741b846f5d7..f898d322add8afb22ac9065552bce929f9891905 100644 (file)
@@ -6,7 +6,15 @@
 #define SATA_REG_FIS_D2H 0x34
 #define SATA_REG_FIS_H2D 0x27
 #define SATA_REG_FIS_COMMAND 0x80
 #define SATA_REG_FIS_D2H 0x34
 #define SATA_REG_FIS_H2D 0x27
 #define SATA_REG_FIS_COMMAND 0x80
-#define SATA_LBA_COMPONENT(lba, offset) ((((lba_lo) >> (offset)) & 0xff))
+#define SATA_LBA_COMPONENT(lba, offset) ((((lba) >> (offset)) & 0xff))
+
+#define ATA_IDENTIFY_DEVICE 0xec
+#define ATA_IDENTIFY_PAKCET_DEVICE 0xa1
+#define ATA_PACKET 0xa0
+#define ATA_READ_DMA_EXT 0xc8
+#define ATA_READ_DMA 0x25
+#define ATA_WRITE_DMA_EXT 0xca
+#define ATA_WRITE_DMA 0x35
 
 struct sata_fis_head
 {
 
 struct sata_fis_head
 {
@@ -40,8 +48,19 @@ struct sata_data_fis
 void
 sata_create_fis(struct sata_reg_fis* cmd_fis,
                 uint8_t command,
 void
 sata_create_fis(struct sata_reg_fis* cmd_fis,
                 uint8_t command,
-                uint32_t lba_lo,
-                uint32_t lba_hi,
+                uint64_t lba,
                 uint16_t sector_count);
 
                 uint16_t sector_count);
 
+int
+sata_read_buffer(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size);
+
+int
+sata_write_buffer(struct hba_port* port,
+                  uint64_t lba,
+                  void* buffer,
+                  uint32_t size);
+
 #endif /* __LUNAIX_SATA_H */
 #endif /* __LUNAIX_SATA_H */
index 5015641086c5fb3a9103dc1b1cc817c23c7db183..cce9af467725486a33985d09068071db1b7e68e8 100644 (file)
@@ -44,8 +44,19 @@ scsi_create_packet12(struct scsi_cdb12* cdb,
 void
 scsi_create_packet16(struct scsi_cdb16* cdb,
                      uint8_t opcode,
 void
 scsi_create_packet16(struct scsi_cdb16* cdb,
                      uint8_t opcode,
-                     uint32_t lba_hi,
-                     uint32_t lba_lo,
+                     uint64_t lba,
                      uint32_t alloc_size);
 
                      uint32_t alloc_size);
 
+void
+scsi_read_buffer(struct hba_port* port,
+                 uint64_t lba,
+                 void* buffer,
+                 uint32_t size);
+
+void
+scsi_write_buffer(struct hba_port* port,
+                  uint64_t lba,
+                  void* buffer,
+                  uint32_t size);
+
 #endif /* __LUNAIX_ATAPI_H */
 #endif /* __LUNAIX_ATAPI_H */
index 119ec3960eaf362944911d5d44522366326eb593..e22a28007d58b26bd64aa9f496841bbc04d95ebe 100644 (file)
@@ -13,4 +13,7 @@ ahci_parsestr(char* str, uint16_t* reg_start, int size_word);
 void
 scsi_parse_capacity(struct hba_device* device, uint32_t* parameter);
 
 void
 scsi_parse_capacity(struct hba_device* device, uint32_t* parameter);
 
+int
+sata_read_error(struct hba_port* port);
+
 #endif /* __LUNAIX_UTILS_H */
 #endif /* __LUNAIX_UTILS_H */
index 076503f70fa762d647f808de7de9860deff70d15..d5d0c7530b5e97d08e225c33e8141f6164f8ede2 100644 (file)
@@ -4,12 +4,18 @@
 void*
 valloc(unsigned int size);
 
 void*
 valloc(unsigned int size);
 
+void*
+vcalloc(unsigned int size);
+
 void
 vfree(void* ptr);
 
 void*
 valloc_dma(unsigned int size);
 
 void
 vfree(void* ptr);
 
 void*
 valloc_dma(unsigned int size);
 
+void*
+vcalloc_dma(unsigned int size);
+
 void
 vfree_dma(void* ptr);
 
 void
 vfree_dma(void* ptr);
 
index fad5bc2525efa8117dc6d2e169fea3861770850d..7e3142b1fbe6579b3d5dc2351cba4e1dae074c87 100644 (file)
@@ -1,5 +1,5 @@
 /**
 /**
- * @file valloc.c
+ * @file cake.c
  * @author Lunaixsky (zelong56@gmail.com)
  * @brief A simplified cake(slab) allocator.
  *          P.s. I call it cake as slab sounds more 'ridge' to me. :)
  * @author Lunaixsky (zelong56@gmail.com)
  * @brief A simplified cake(slab) allocator.
  *          P.s. I call it cake as slab sounds more 'ridge' to me. :)
@@ -112,14 +112,9 @@ void*
 cake_grab(struct cake_pile* pile)
 {
     struct cake_s *pos, *n;
 cake_grab(struct cake_pile* pile)
 {
     struct cake_s *pos, *n;
-    llist_for_each(pos, n, &pile->partial, cakes)
-    {
-        if (pos->next_free != EO_FREE_PIECE) {
-            goto found;
-        }
-    }
-
-    if (llist_empty(&pile->free)) {
+    if (!llist_empty(&pile->partial)) {
+        pos = list_entry(pile->partial.next, typeof(*pos), cakes);
+    } else if (llist_empty(&pile->free)) {
         pos = __new_cake(pile);
     } else {
         pos = list_entry(pile->free.next, typeof(*pos), cakes);
         pos = __new_cake(pile);
     } else {
         pos = list_entry(pile->free.next, typeof(*pos), cakes);
index 0c4d4d4020e2167cf85c7a5d304812f80abc144a..4ff4794fd3e0da1a9543f07efbbec432ddbb66c6 100644 (file)
@@ -1,4 +1,6 @@
+#include <klibc/string.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/cake.h>
+#include <lunaix/mm/valloc.h>
 
 #define MAX_CLASS 6
 
 
 #define MAX_CLASS 6
 
@@ -64,6 +66,14 @@ valloc(unsigned int size)
     return __valloc(size, &piles);
 }
 
     return __valloc(size, &piles);
 }
 
+void*
+vcalloc(unsigned int size)
+{
+    void* ptr = __valloc(size, &piles);
+    memset(ptr, 0, size);
+    return ptr;
+}
+
 void
 vfree(void* ptr)
 {
 void
 vfree(void* ptr)
 {
@@ -76,6 +86,14 @@ valloc_dma(unsigned int size)
     return __valloc(size, &piles_dma);
 }
 
     return __valloc(size, &piles_dma);
 }
 
+void*
+vcalloc_dma(unsigned int size)
+{
+    void* ptr = __valloc(size, &piles_dma);
+    memset(ptr, 0, size);
+    return ptr;
+}
+
 void
 vfree_dma(void* ptr)
 {
 void
 vfree_dma(void* ptr)
 {