refactor: send the command with retry and error detection
authorMinep <zelong56@gmail.com>
Thu, 18 Aug 2022 15:31:23 +0000 (16:31 +0100)
committerMinep <zelong56@gmail.com>
Thu, 18 Aug 2022 15:31:23 +0000 (16:31 +0100)
chore: other refactorings

lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/ata.c
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 [deleted file]
lunaix-os/includes/klibc/string.h
lunaix-os/libs/klibc/string/trim.c [new file with mode: 0644]

index 21eaa1df12aeeef891e6011e853c4591cf8cdd85..41ebc8669ef57b5d88b0bbf598584c35bfae3d63 100644 (file)
@@ -12,7 +12,6 @@
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 #include <hal/ahci/scsi.h>
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 #include <hal/ahci/scsi.h>
-#include <hal/ahci/utils.h>
 
 #include <hal/pci.h>
 #include <klibc/string.h>
 
 #include <hal/pci.h>
 #include <klibc/string.h>
@@ -158,8 +157,7 @@ ahci_init()
         /* 初始化端口,并置于就绪状态 */
         port_regs[HBA_RPxCI] = 0;
 
         /* 初始化端口,并置于就绪状态 */
         port_regs[HBA_RPxCI] = 0;
 
-        // 需要通过全部置位去清空这些寄存器(相当的奇怪……)
-        port_regs[HBA_RPxSERR] = -1;
+        hba_clear_reg(port_regs[HBA_RPxSERR]);
 
         hba.ports[i] = port;
 
 
         hba.ports[i] = port;
 
@@ -176,6 +174,11 @@ ahci_init()
             continue;
         }
 
             continue;
         }
 
+        kprintf(KINFO "sata%d: %s (%s)\n",
+                i,
+                port->device->model,
+                port->device->serial_num);
+
         block_mount_disk(port->device);
     }
 }
         block_mount_disk(port->device);
     }
 }
@@ -312,16 +315,11 @@ ahci_init_device(struct hba_port* port)
     // mask DHR interrupt
     port->regs[HBA_RPxIE] &= ~HBA_PxINTR_DHR;
 
     // mask DHR interrupt
     port->regs[HBA_RPxIE] &= ~HBA_PxINTR_DHR;
 
-    // 确保端口是空闲的
-    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY)));
-
     // 预备DMA接收缓存,用于存放HBA传回的数据
     uint16_t* data_in = (uint16_t*)valloc_dma(512);
 
     int slot = hba_prepare_cmd(port, &cmd_table, &cmd_header, data_in, 512);
 
     // 预备DMA接收缓存,用于存放HBA传回的数据
     uint16_t* data_in = (uint16_t*)valloc_dma(512);
 
     int slot = hba_prepare_cmd(port, &cmd_table, &cmd_header, data_in, 512);
 
-    // 清空任何待响应的中断
-    port->regs[HBA_RPxIS] = 0;
     port->device = vzalloc(sizeof(struct hba_device));
     port->device->port = port;
 
     port->device = vzalloc(sizeof(struct hba_device));
     port->device->port = port;
 
@@ -338,14 +336,7 @@ ahci_init_device(struct hba_port* port)
         sata_create_fis(cmd_fis, ATA_IDENTIFY_PAKCET_DEVICE, 0, 0);
     }
 
         sata_create_fis(cmd_fis, ATA_IDENTIFY_PAKCET_DEVICE, 0, 0);
     }
 
-    // PxCI寄存器置位,告诉HBA这儿有个数据需要发送到SATA端口
-    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);
+    if (!ahci_try_send(port, slot)) {
         goto fail;
     }
 
         goto fail;
     }
 
@@ -388,7 +379,7 @@ ahci_init_device(struct hba_port* port)
     sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0);
 
     // for dev use 12 bytes cdb, READ_CAPACITY must use the 10 bytes variation.
     sata_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0);
 
     // for dev use 12 bytes cdb, READ_CAPACITY must use the 10 bytes variation.
-    if (port->device->cbd_size == 12) {
+    if (port->device->cbd_size == SCSI_CDB12) {
         struct scsi_cdb12* cdb12 = (struct scsi_cdb12*)cmd_table->atapi_cmd;
         // ugly tricks to construct 10 byte cdb from 12 byte cdb
         scsi_create_packet12(cdb12, SCSI_READ_CAPACITY_10, 0, 512 << 8);
         struct scsi_cdb12* cdb12 = (struct scsi_cdb12*)cmd_table->atapi_cmd;
         // ugly tricks to construct 10 byte cdb from 12 byte cdb
         scsi_create_packet12(cdb12, SCSI_READ_CAPACITY_10, 0, 512 << 8);
@@ -401,12 +392,7 @@ ahci_init_device(struct hba_port* port)
     cmd_header->transferred_size = 0;
     cmd_header->options |= HBA_CMDH_ATAPI;
 
     cmd_header->transferred_size = 0;
     cmd_header->options |= HBA_CMDH_ATAPI;
 
-    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);
+    if (!ahci_try_send(port, slot)) {
         goto fail;
     }
 
         goto fail;
     }
 
@@ -414,7 +400,6 @@ ahci_init_device(struct hba_port* port)
 
 done:
     // reset interrupt status and unmask D2HR interrupt
 
 done:
     // reset interrupt status and unmask D2HR interrupt
-    port->regs[HBA_RPxIS] = -1;
     port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
     achi_register_ops(port);
 
     port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
     achi_register_ops(port);
 
@@ -424,7 +409,6 @@ done:
     return 1;
 
 fail:
     return 1;
 
 fail:
-    port->regs[HBA_RPxIS] = -1;
     port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
     vfree_dma(data_in);
     vfree_dma(cmd_table);
     port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
     vfree_dma(data_in);
     vfree_dma(cmd_table);
index 118bf1196a8697b6e4a001f66c2196d9e900a3d3..845f4202bfdcbb59bded40c9bbf0e6fd0996cae2 100644 (file)
@@ -1,3 +1,4 @@
+#include <hal/ahci/ahci.h>
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 
@@ -27,12 +28,6 @@ __sata_buffer_io(struct hba_device* dev,
     struct hba_cmdh* header;
     struct hba_cmdt* table;
     int slot = hba_prepare_cmd(port, &table, &header, buffer, size);
     struct hba_cmdh* header;
     struct hba_cmdt* table;
     int slot = hba_prepare_cmd(port, &table, &header, buffer, size);
-    int bitmask = 1 << slot;
-
-    // 确保端口是空闲的
-    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ)));
-
-    port->regs[HBA_RPxIS] = 0;
 
     header->options |= HBA_CMDH_WRITE * (write == 1);
 
 
     header->options |= HBA_CMDH_WRITE * (write == 1);
 
@@ -57,26 +52,10 @@ __sata_buffer_io(struct hba_device* dev,
     */
     fis->dev = (1 << 6);
 
     */
     fis->dev = (1 << 6);
 
-    int retries = 0;
-
-    while (retries < MAX_RETRY) {
-        port->regs[HBA_RPxCI] = bitmask;
-
-        wait_until(!(port->regs[HBA_RPxCI] & bitmask));
-
-        if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
-            // 有错误
-            sata_read_error(port);
-            retries++;
-        } else {
-            vfree_dma(table);
-            return 1;
-        }
-    }
+    int is_ok = ahci_try_send(port, slot);
 
 
-fail:
     vfree_dma(table);
     vfree_dma(table);
-    return 0;
+    return is_ok;
 }
 
 int
 }
 
 int
index 76c379571e538424d41754c46d479655fb62331b..f75c1bec6cb59ed463907c8c1a104d2e2c2ba946 100644 (file)
@@ -1,7 +1,7 @@
+#include <hal/ahci/ahci.h>
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 #include <hal/ahci/scsi.h>
 #include <hal/ahci/hba.h>
 #include <hal/ahci/sata.h>
 #include <hal/ahci/scsi.h>
-#include <hal/ahci/utils.h>
 
 #include <klibc/string.h>
 #include <lunaix/mm/valloc.h>
 
 #include <klibc/string.h>
 #include <lunaix/mm/valloc.h>
@@ -61,12 +61,6 @@ __scsi_buffer_io(struct hba_device* dev,
     struct hba_cmdh* header;
     struct hba_cmdt* table;
     int slot = hba_prepare_cmd(port, &table, &header, buffer, size);
     struct hba_cmdh* header;
     struct hba_cmdt* table;
     int slot = hba_prepare_cmd(port, &table, &header, buffer, size);
-    int bitmask = 1 << slot;
-
-    // 确保端口是空闲的
-    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ)));
-
-    port->regs[HBA_RPxIS] = 0;
 
     header->options |= (HBA_CMDH_WRITE * (write == 1)) | HBA_CMDH_ATAPI;
 
 
     header->options |= (HBA_CMDH_WRITE * (write == 1)) | HBA_CMDH_ATAPI;
 
@@ -77,7 +71,7 @@ __scsi_buffer_io(struct hba_device* dev,
     sata_create_fis(fis, ATA_PACKET, (size << 8), 0);
     fis->feature = 1 | ((!write) << 2);
 
     sata_create_fis(fis, ATA_PACKET, (size << 8), 0);
     fis->feature = 1 | ((!write) << 2);
 
-    if (port->device->cbd_size == 16) {
+    if (port->device->cbd_size == SCSI_CDB16) {
         scsi_create_packet16((struct scsi_cdb16*)cdb,
                              write ? SCSI_WRITE_BLOCKS_16 : SCSI_READ_BLOCKS_16,
                              lba,
         scsi_create_packet16((struct scsi_cdb16*)cdb,
                              write ? SCSI_WRITE_BLOCKS_16 : SCSI_READ_BLOCKS_16,
                              lba,
@@ -92,26 +86,10 @@ __scsi_buffer_io(struct hba_device* dev,
     // field: cdb->misc1
     *((uint8_t*)cdb + 1) = 3 << 5; // RPROTECT=011b 禁用保护检查
 
     // field: cdb->misc1
     *((uint8_t*)cdb + 1) = 3 << 5; // RPROTECT=011b 禁用保护检查
 
-    int retries = 0;
-
-    while (retries < MAX_RETRY) {
-        port->regs[HBA_RPxCI] = bitmask;
-
-        wait_until_expire(!(port->regs[HBA_RPxCI] & bitmask), 1000000);
-
-        if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
-            // 有错误
-            sata_read_error(port);
-            retries++;
-        } else {
-            vfree_dma(table);
-            return 1;
-        }
-    }
-
-fail:
+    int is_ok = ahci_try_send(port, slot);
     vfree_dma(table);
     vfree_dma(table);
-    return 0;
+
+    return is_ok;
 }
 
 int
 }
 
 int
index 664488dbe3f0a1b5969516533b2c598ef36242b0..96d163b93585ed8a0f7a273e25506f07a4d2b631 100644 (file)
@@ -1,7 +1,11 @@
+#include <hal/ahci/ahci.h>
 #include <hal/ahci/hba.h>
 #include <hal/ahci/hba.h>
-#include <hal/ahci/utils.h>
+#include <hal/ahci/sata.h>
+#include <hal/ahci/scsi.h>
 #include <klibc/string.h>
 
 #include <klibc/string.h>
 
+#include <lunaix/spike.h>
+
 #define IDDEV_OFFMAXLBA 60
 #define IDDEV_OFFMAXLBA_EXT 230
 #define IDDEV_OFFLSECSIZE 117
 #define IDDEV_OFFMAXLBA 60
 #define IDDEV_OFFMAXLBA_EXT 230
 #define IDDEV_OFFLSECSIZE 117
 #define IDDEV_OFFLPP 106
 #define IDDEV_OFFCAPABILITIES 49
 
 #define IDDEV_OFFLPP 106
 #define IDDEV_OFFCAPABILITIES 49
 
+static uint32_t cdb_size[] = { SCSI_CDB12, SCSI_CDB16, 0, 0 };
+
 void
 ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data)
 {
     dev_info->max_lba = *((uint32_t*)(data + IDDEV_OFFMAXLBA));
     dev_info->block_size = *((uint32_t*)(data + IDDEV_OFFLSECSIZE));
 void
 ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data)
 {
     dev_info->max_lba = *((uint32_t*)(data + IDDEV_OFFMAXLBA));
     dev_info->block_size = *((uint32_t*)(data + IDDEV_OFFLSECSIZE));
-    dev_info->cbd_size = (*data & 0x3) ? 16 : 12;
+    dev_info->cbd_size = cdb_size[(*data & 0x3)];
     dev_info->wwn = *(uint64_t*)(data + IDDEV_OFFWWN);
     dev_info->block_per_sec = 1 << (*(data + IDDEV_OFFLPP) & 0xf);
     dev_info->alignment_offset = *(data + IDDEV_OFFALIGN) & 0x3fff;
     dev_info->wwn = *(uint64_t*)(data + IDDEV_OFFWWN);
     dev_info->block_per_sec = 1 << (*(data + IDDEV_OFFLPP) & 0xf);
     dev_info->alignment_offset = *(data + IDDEV_OFFALIGN) & 0x3fff;
@@ -47,4 +53,36 @@ ahci_parsestr(char* str, uint16_t* reg_start, int size_word)
         str[j + 1] = (char)(reg & 0xff);
     }
     str[j - 1] = '\0';
         str[j + 1] = (char)(reg & 0xff);
     }
     str[j - 1] = '\0';
+    strrtrim(str);
+}
+
+int
+ahci_try_send(struct hba_port* port, int slot)
+{
+    int retries = 0, bitmask = 1 << slot;
+
+    // 确保端口是空闲的
+    wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ)));
+
+    hba_clear_reg(port->regs[HBA_RPxIS]);
+
+    while (retries < MAX_RETRY) {
+        // PxCI寄存器置位,告诉HBA这儿有个数据需要发送到SATA端口
+        port->regs[HBA_RPxCI] = bitmask;
+
+        wait_until_expire(!(port->regs[HBA_RPxCI] & bitmask), 1000000);
+
+        port->regs[HBA_RPxCI] &= ~bitmask; // ensure CI bit is cleared
+        if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) {
+            // 有错误
+            sata_read_error(port);
+            retries++;
+        } else {
+            break;
+        }
+    }
+
+    hba_clear_reg(port->regs[HBA_RPxIS]);
+
+    return retries < MAX_RETRY;
 }
\ No newline at end of file
 }
\ No newline at end of file
index ec9a64ffe6461c1b8d12512216bf01fc514b3222..c7685104eebd8c1dd88d72a36926477022178318 100644 (file)
@@ -30,4 +30,13 @@ ahci_get_port_usage();
 struct hba_port*
 ahci_get_port(unsigned int index);
 
 struct hba_port*
 ahci_get_port(unsigned int index);
 
+void
+ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data);
+
+void
+ahci_parsestr(char* str, uint16_t* reg_start, int size_word);
+
+int
+ahci_try_send(struct hba_port* port, int slot);
+
 #endif /* __LUNAIX_AHCI_H */
 #endif /* __LUNAIX_AHCI_H */
index 92a2b5a382518417f423a3f8ecce38416d318dd7..8203ab5e6f902880961f7d3236fecfb99e394cb3 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LUNAIX_HBA_H
 #define __LUNAIX_HBA_H
 
 #ifndef __LUNAIX_HBA_H
 #define __LUNAIX_HBA_H
 
-#include <stdint.h>
+#include <lunaix/types.h>
 
 #define HBA_RCAP 0
 #define HBA_RGHC 1
 
 #define HBA_RCAP 0
 #define HBA_RGHC 1
@@ -47,6 +47,8 @@
 #define HBA_RPxSSTS_IF(x) (((x) >> 4) & 0xf)
 #define HBA_RPxSSTS_PHYSTATE(x) ((x)&0xf)
 
 #define HBA_RPxSSTS_IF(x) (((x) >> 4) & 0xf)
 #define HBA_RPxSSTS_PHYSTATE(x) ((x)&0xf)
 
+#define hba_clear_reg(reg) (reg) = -1
+
 #define HBA_DEV_SIG_ATAPI 0xeb140101
 #define HBA_DEV_SIG_ATA 0x00000101
 
 #define HBA_DEV_SIG_ATAPI 0xeb140101
 #define HBA_DEV_SIG_ATA 0x00000101
 
index dc934482c4e4799d95e95a56f3732f5f4c8ba46b..a08c5f43f497b7a1322577f3974f02af04522bbe 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __LUNAIX_SATA_H
 #define __LUNAIX_SATA_H
 
 #ifndef __LUNAIX_SATA_H
 #define __LUNAIX_SATA_H
 
-#include <stdint.h>
+#include <hal/ahci/hba.h>
 
 #define SATA_REG_FIS_D2H 0x34
 #define SATA_REG_FIS_H2D 0x27
 
 #define SATA_REG_FIS_D2H 0x34
 #define SATA_REG_FIS_H2D 0x27
@@ -65,4 +65,6 @@ sata_write_buffer(struct hba_device* dev,
                   void* buffer,
                   uint32_t size);
 
                   void* buffer,
                   uint32_t size);
 
+void
+sata_read_error(struct hba_port* port);
 #endif /* __LUNAIX_SATA_H */
 #endif /* __LUNAIX_SATA_H */
index fee899fa916ebb72b9b2c347537ce9ebf89ef94c..a3cfe2f3457560f5165f06d1749a021db8800b2d 100644 (file)
@@ -62,4 +62,7 @@ scsi_write_buffer(struct hba_device* dev,
                   void* buffer,
                   uint32_t size);
 
                   void* buffer,
                   uint32_t size);
 
+void
+scsi_parse_capacity(struct hba_device* device, uint32_t* parameter);
+
 #endif /* __LUNAIX_ATAPI_H */
 #endif /* __LUNAIX_ATAPI_H */
diff --git a/lunaix-os/includes/hal/ahci/utils.h b/lunaix-os/includes/hal/ahci/utils.h
deleted file mode 100644 (file)
index e22a280..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef __LUNAIX_AHCI_UTILS_H
-#define __LUNAIX_AHCI_UTILS_H
-
-#include <hal/ahci/hba.h>
-#include <stdint.h>
-
-void
-ahci_parse_dev_info(struct hba_device* dev_info, uint16_t* data);
-
-void
-ahci_parsestr(char* str, uint16_t* reg_start, int size_word);
-
-void
-scsi_parse_capacity(struct hba_device* device, uint32_t* parameter);
-
-int
-sata_read_error(struct hba_port* port);
-
-#endif /* __LUNAIX_UTILS_H */
index 35fd53e76c97e8a79697a7d604038ce1eb930889..fcb0df5286167ebf9a43586efe30da7fa13f6b43 100644 (file)
@@ -33,4 +33,10 @@ strchr(const char* str, int character);
 int
 streq(const char* a, const char* b);
 
 int
 streq(const char* a, const char* b);
 
+void
+strrtrim(char* str);
+
+void*
+strltrim_safe(char* str);
+
 #endif /* __LUNAIX_STRING_H */
 #endif /* __LUNAIX_STRING_H */
diff --git a/lunaix-os/libs/klibc/string/trim.c b/lunaix-os/libs/klibc/string/trim.c
new file mode 100644 (file)
index 0000000..82f29bd
--- /dev/null
@@ -0,0 +1,29 @@
+#include <klibc/string.h>
+
+#define WS_CHAR(c)                                                             \
+    (c == ' ' || c == '\t' || c == '\n' || c == '\f' || c == '\v' || c == '\r')
+
+void
+strrtrim(char* str)
+{
+    size_t l = strlen(str);
+    while (l < (size_t)-1) {
+        char c = str[l];
+        if (!c || WS_CHAR(c)) {
+            l--;
+            continue;
+        }
+        break;
+    }
+    str[l + 1] = '\0';
+}
+
+void*
+strltrim_safe(char* str)
+{
+    size_t l = 0;
+    char c = 0;
+    while ((c = str[l++]) && WS_CHAR(c))
+        ;
+    return strcpy(str, str + l);
+}
\ No newline at end of file