From: Minep Date: Wed, 6 Jul 2022 22:28:18 +0000 (+0100) Subject: feat: sector rwm ops test code X-Git-Url: https://scm.lunaixsky.com/lunaix-os.git/commitdiff_plain/88e668538d6c0d394e6ea34516052f010ca6e8d2?hp=eb037efe9f30ae166684e99146024abf8740984d feat: sector rwm ops test code feat: retry sending of command if failed feat: hex dump fix: wrong CDB sizing and ensure big-endian on scsi command. chore: correct some comments and segregated class name --- diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index a723c20..31e9725 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -188,7 +188,7 @@ ahci_list_device() kprintf("\t Port %d: %s (%x)\n", i, &sata_ifs[device_state], - port->regs[HBA_RPxSIG]); + port->device->flags); struct hba_device* dev_info = port->device; if (!device_state || !dev_info) { @@ -247,10 +247,9 @@ hba_alloc_slot(struct hba_port* port, // 构建命令头(Command Header)和命令表(Command Table) struct hba_cmdh* cmd_header = &port->cmdlst[slot]; - struct hba_cmdt* cmd_table = valloc_dma(sizeof(struct hba_cmdt)); + struct hba_cmdt* cmd_table = vcalloc_dma(sizeof(struct hba_cmdt)); memset(cmd_header, 0, sizeof(*cmd_header)); - memset(cmd_table, 0, sizeof(*cmd_table)); // 将命令表挂到命令头上 cmd_header->cmd_table_base = vmm_v2p(cmd_table); diff --git a/lunaix-os/hal/ahci/ata.c b/lunaix-os/hal/ahci/ata.c index ea2e5f3..91863fd 100644 --- a/lunaix-os/hal/ahci/ata.c +++ b/lunaix-os/hal/ahci/ata.c @@ -2,6 +2,7 @@ #include #include +#include #include int @@ -19,43 +20,43 @@ __sata_buffer_io(struct hba_port* port, int bitmask = 1 << slot; // 确保端口是空闲的 - wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY))); + wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ))); port->regs[HBA_RPxIS] = 0; - table->entries[0] = - (struct hba_prdte){ .byte_count = size - 1, .data_base = buffer }; + table->entries[0] = (struct hba_prdte){ .byte_count = size - 1, + .data_base = vmm_v2p(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; - } - + uint16_t count = ICEIL(size, port->device->block_size); 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); + fis->dev = (1 << 6) * (!write); } else { sata_create_fis(fis, write ? ATA_WRITE_DMA : ATA_READ_DMA, lba, count); } - port->regs[HBA_RPxCI] = bitmask; + int retries = 0; - wait_until(!(port->regs[HBA_RPxCI] & bitmask)); + while (retries < MAX_RETRY) { + port->regs[HBA_RPxCI] = bitmask; - if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { - // 有错误 - sata_read_error(port); - goto fail; - } + wait_until(!(port->regs[HBA_RPxCI] & bitmask)); - vfree_dma(table); - return 1; + if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { + // 有错误 + sata_read_error(port); + retries++; + } else { + vfree_dma(table); + return 1; + } + } fail: vfree_dma(table); diff --git a/lunaix-os/hal/ahci/atapi.c b/lunaix-os/hal/ahci/atapi.c index c245c0a..32ec5df 100644 --- a/lunaix-os/hal/ahci/atapi.c +++ b/lunaix-os/hal/ahci/atapi.c @@ -4,7 +4,10 @@ #include #include +#include +#include #include +#include void scsi_create_packet12(struct scsi_cdb12* cdb, @@ -15,7 +18,7 @@ scsi_create_packet12(struct scsi_cdb12* cdb, memset(cdb, 0, sizeof(*cdb)); cdb->opcode = opcode; cdb->lba_be = SCSI_FLIP(lba); - cdb->length = alloc_size; + cdb->length = SCSI_FLIP(alloc_size); } void @@ -26,9 +29,9 @@ scsi_create_packet16(struct scsi_cdb16* cdb, { memset(cdb, 0, sizeof(*cdb)); cdb->opcode = opcode; - cdb->lba_be_hi = SCSI_FLIP(lba >> 32); + cdb->lba_be_hi = SCSI_FLIP((uint32_t)(lba >> 32)); cdb->lba_be_lo = SCSI_FLIP((uint32_t)lba); - cdb->length = alloc_size; + cdb->length = SCSI_FLIP(alloc_size); } void @@ -53,50 +56,52 @@ __scsi_buffer_io(struct hba_port* port, int bitmask = 1 << slot; // 确保端口是空闲的 - wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY))); + wait_until(!(port->regs[HBA_RPxTFD] & (HBA_PxTFD_BSY | HBA_PxTFD_DRQ))); port->regs[HBA_RPxIS] = 0; - table->entries[0] = - (struct hba_prdte){ .byte_count = size - 1, .data_base = buffer }; + table->entries[0] = (struct hba_prdte){ .byte_count = size - 1, + .data_base = vmm_v2p(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; - } + uint32_t count = ICEIL(size, port->device->block_size); struct sata_reg_fis* fis = table->command_fis; void* cdb = table->atapi_cmd; - sata_create_fis(fis, ATA_PACKET, (size << 8) & 0xffffff, 0); + sata_create_fis(fis, ATA_PACKET, (size << 8), 0); + fis->feature = 1 | ((!write) << 2); if (port->device->cbd_size == 16) { scsi_create_packet16((struct scsi_cdb16*)cdb, write ? SCSI_WRITE_BLOCKS_16 : SCSI_READ_BLOCKS_16, lba, count); + ((struct scsi_cdb16*)cdb)->misc1 = 3 << 5; // 禁用保护检查 } else { scsi_create_packet12((struct scsi_cdb12*)cdb, write ? SCSI_WRITE_BLOCKS_12 : SCSI_READ_BLOCKS_12, lba, count); + ((struct scsi_cdb12*)cdb)->misc1 = 3 << 5; // 禁用保护检查 } - port->regs[HBA_RPxCI] = bitmask; + int retries = 0; - wait_until(!(port->regs[HBA_RPxCI] & bitmask)); + while (retries < MAX_RETRY) { + port->regs[HBA_RPxCI] = bitmask; - if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { - // 有错误 - sata_read_error(port); - goto fail; - } + wait_until(!(port->regs[HBA_RPxCI] & bitmask)); - vfree_dma(table); - return 1; + if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { + // 有错误 + sata_read_error(port); + retries++; + } else { + vfree_dma(table); + return 1; + } + } fail: vfree_dma(table); diff --git a/lunaix-os/hal/ahci/utils.c b/lunaix-os/hal/ahci/utils.c index 23541ee..3b1fbcb 100644 --- a/lunaix-os/hal/ahci/utils.c +++ b/lunaix-os/hal/ahci/utils.c @@ -15,7 +15,7 @@ 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) ? 12 : 16; + dev_info->cbd_size = (*data & 0x3) ? 16 : 12; dev_info->wwn = *(uint64_t*)(data + IDDEV_OFFWWN); if (!dev_info->block_size) { diff --git a/lunaix-os/includes/hal/ahci/ahci.h b/lunaix-os/includes/hal/ahci/ahci.h index acd779b..ec9a64f 100644 --- a/lunaix-os/includes/hal/ahci/ahci.h +++ b/lunaix-os/includes/hal/ahci/ahci.h @@ -1,6 +1,8 @@ #ifndef __LUNAIX_AHCI_H #define __LUNAIX_AHCI_H +#include "hba.h" + /* * Macro naming rule: * HBA_R[xxx] diff --git a/lunaix-os/includes/hal/ahci/sata.h b/lunaix-os/includes/hal/ahci/sata.h index f898d32..99a45bc 100644 --- a/lunaix-os/includes/hal/ahci/sata.h +++ b/lunaix-os/includes/hal/ahci/sata.h @@ -11,10 +11,12 @@ #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 +#define ATA_READ_DMA_EXT 0x25 +#define ATA_READ_DMA 0xc8 +#define ATA_WRITE_DMA_EXT 0x35 +#define ATA_WRITE_DMA 0xca + +#define MAX_RETRY 2 struct sata_fis_head { @@ -31,7 +33,7 @@ struct sata_reg_fis uint8_t lba0, lba8, lba16; uint8_t dev; uint8_t lba24, lba32, lba40; - uint8_t reserved1; + uint8_t feature; uint16_t count; diff --git a/lunaix-os/includes/lunaix/spike.h b/lunaix-os/includes/lunaix/spike.h index cbdadfb..6f91924 100644 --- a/lunaix-os/includes/lunaix/spike.h +++ b/lunaix-os/includes/lunaix/spike.h @@ -6,6 +6,8 @@ // 除法向上取整 #define CEIL(v, k) (((v) + (1 << (k)) - 1) >> (k)) +#define ICEIL(x, y) ((x) / (y) + ((x) % (y) != 0)) + // 除法向下取整 #define FLOOR(v, k) ((v) >> (k)) diff --git a/lunaix-os/includes/lunaix/syslog.h b/lunaix-os/includes/lunaix/syslog.h index 545a803..f5fc8db 100644 --- a/lunaix-os/includes/lunaix/syslog.h +++ b/lunaix-os/includes/lunaix/syslog.h @@ -3,27 +3,30 @@ #include -#define _LEVEL_INFO "0" -#define _LEVEL_WARN "1" +#define _LEVEL_INFO "0" +#define _LEVEL_WARN "1" #define _LEVEL_ERROR "2" #define _LEVEL_DEBUG "3" -#define KINFO "\x1b" _LEVEL_INFO -#define KWARN "\x1b" _LEVEL_WARN -#define KERROR "\x1b" _LEVEL_ERROR -#define KDEBUG "\x1b" _LEVEL_DEBUG - -#define LOG_MODULE(module) \ - static void kprintf(const char* fmt, ...) { \ - va_list args; \ - va_start(args, fmt); \ - __kprintf(module, fmt, args); \ - va_end(args); \ +#define KINFO "\x1b" _LEVEL_INFO +#define KWARN "\x1b" _LEVEL_WARN +#define KERROR "\x1b" _LEVEL_ERROR +#define KDEBUG "\x1b" _LEVEL_DEBUG + +#define LOG_MODULE(module) \ + static void kprintf(const char* fmt, ...) \ + { \ + va_list args; \ + va_start(args, fmt); \ + __kprintf(module, fmt, args); \ + va_end(args); \ } void __kprintf(const char* component, const char* fmt, va_list args); +void +kprint_hex(const void* buffer, unsigned int size); void kprint_panic(const char* fmt, ...); diff --git a/lunaix-os/kernel/kprintf.c b/lunaix-os/kernel/kprintf.c index af47a8a..d18691a 100644 --- a/lunaix-os/kernel/kprintf.c +++ b/lunaix-os/kernel/kprintf.c @@ -84,4 +84,30 @@ kprint_panic(const char* fmt, ...) tty_put_str_at(buf, 0, 24); va_end(args); +} + +void +kprint_hex(const void* buffer, unsigned int size) +{ + unsigned char* data = (unsigned char*)buffer; + char buf[16]; + char ch_cache[16]; + unsigned int ptr = 0; + int i; + + ch_cache[0] = '|'; + ch_cache[1] = ' '; + while (size) { + snprintf(buf, 64, " %.4p: ", ptr); + console_write_str(buf); + for (i = 0; i < 8 && size; i++, size--, ptr++) { + unsigned char c = *(data + ptr) & 0xff; + ch_cache[2 + i] = (32 <= c && c < 127) ? c : '.'; + snprintf(buf, 64, "%.2x ", c); + console_write_str(buf); + } + ch_cache[2 + i] = '\0'; + console_write_str(ch_cache); + console_write_char('\n'); + } } \ No newline at end of file diff --git a/lunaix-os/kernel/mm/valloc.c b/lunaix-os/kernel/mm/valloc.c index 4ff4794..631f39e 100644 --- a/lunaix-os/kernel/mm/valloc.c +++ b/lunaix-os/kernel/mm/valloc.c @@ -10,7 +10,7 @@ static char piles_names[MAX_CLASS][PILE_NAME_MAXLEN] = { }; static char piles_names_dma[MAX_CLASS][PILE_NAME_MAXLEN] = { - "valloc_dma_128", "valloc_dma_512", "valloc_dma_512", + "valloc_dma_128", "valloc_dma_256", "valloc_dma_512", "valloc_dma_1k", "valloc_dma_2k", "valloc_dma_4k" }; diff --git a/lunaix-os/kernel/proc0.c b/lunaix-os/kernel/proc0.c index dcd6bf4..b9a2470 100644 --- a/lunaix-os/kernel/proc0.c +++ b/lunaix-os/kernel/proc0.c @@ -19,6 +19,8 @@ #include #include +#include + LOG_MODULE("PROC0") extern void @@ -109,6 +111,39 @@ extern uint8_t __kernel_end; /* link/linker.ld */ extern uint8_t __init_hhk_end; /* link/linker.ld */ extern multiboot_info_t* _k_init_mb_info; /* k_init.c */ +char test_sequence[] = "Once upon a time, in a magical land of Equestria. " + "There were two regal sisters who ruled together " + "and created harmony for all the land."; + +void +__test_disk_io() +{ + struct hba_port* port = ahci_get_port(0); + char* buffer = valloc_dma(port->device->block_size); + strcpy(buffer, test_sequence); + kprintf("WRITE: %s\n", buffer); + int result; + + // 写入第一扇区 + result = + port->device->ops.write_buffer(port, 1, buffer, port->device->block_size); + if (!result) { + kprintf(KWARN "fail to write: %x\n", port->device->last_error); + } + + memset(buffer, 0, port->device->block_size); + + // 读出我们刚刚写的内容! + result = + port->device->ops.read_buffer(port, 1, buffer, port->device->block_size); + kprintf(KDEBUG "%x, %x\n", port->regs[HBA_RPxIS], port->regs[HBA_RPxTFD]); + if (!result) { + kprintf(KWARN "fail to read: %x\n", port->device->last_error); + } else { + kprint_hex(buffer, 256); + } +} + void init_platform() { @@ -130,6 +165,8 @@ init_platform() ahci_init(); ahci_list_device(); + __test_disk_io(); + cake_stats(); syscall_install();