From eb037efe9f30ae166684e99146024abf8740984d Mon Sep 17 00:00:00 2001 From: Minep Date: Tue, 5 Jul 2022 17:23:10 +0100 Subject: [PATCH] feat: disk read/write support for both ATA and ATAPI device feat: vcalloc and vcalloc_dma wrapper refactor: no need tranverse down partial list when grabing a cake! --- lunaix-os/hal/ahci/ahci.c | 102 +++++++++++++++++++++----- lunaix-os/hal/ahci/ata.c | 88 ++++++++++++++++++++++ lunaix-os/hal/ahci/atapi.c | 91 ++++++++++++++++++++++- lunaix-os/hal/ahci/utils.c | 29 +++++--- lunaix-os/includes/hal/ahci/ahci.h | 10 ++- lunaix-os/includes/hal/ahci/hba.h | 32 +++++++- lunaix-os/includes/hal/ahci/sata.h | 25 ++++++- lunaix-os/includes/hal/ahci/scsi.h | 15 +++- lunaix-os/includes/hal/ahci/utils.h | 3 + lunaix-os/includes/lunaix/mm/valloc.h | 6 ++ lunaix-os/kernel/mm/cake.c | 13 +--- lunaix-os/kernel/mm/valloc.c | 18 +++++ 12 files changed, 376 insertions(+), 56 deletions(-) create mode 100644 lunaix-os/hal/ahci/ata.c diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index 6771bb6..a723c20 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -36,6 +36,24 @@ __ahci_hba_isr(isr_param param); 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() { @@ -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]; + 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_bmp = pmap; /* ------ 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) { @@ -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 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); } @@ -197,8 +217,7 @@ __get_free_slot(struct hba_port* port) 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; @@ -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->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; } @@ -234,7 +253,6 @@ hba_alloc_slot(struct hba_port* port, 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); @@ -252,12 +270,14 @@ ahci_init_device(struct hba_port* port) 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; - 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); @@ -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; // 根据设备类型使用合适的命令 - if (port->device->signature == HBA_DEV_SIG_ATA) { + if (port->regs[HBA_RPxSIG] == HBA_DEV_SIG_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 一般为光驱,软驱,或者磁带机 - 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端口 @@ -284,6 +305,12 @@ ahci_init_device(struct hba_port* port) wait_until(!(port->regs[HBA_RPxCI] & (1 << slot))); + if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { + // 有错误 + sata_read_error(port); + goto fail; + } + /* 等待数据到达内存 解析IDENTIFY DEVICE传回来的数据。 @@ -292,7 +319,7 @@ ahci_init_device(struct hba_port* port) */ 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; } @@ -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_create_fis(cmd_fis, ATA_PACKET, 512 << 8, 0, 0); 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; @@ -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))); + if ((port->regs[HBA_RPxTFD] & HBA_PxTFD_ERR)) { + // 有错误 + sata_read_error(port); + goto fail; + } + scsi_parse_capacity(port->device, (uint32_t*)data_in); done: + achi_register_ops(port); + 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 index 0000000..ea2e5f3 --- /dev/null +++ b/lunaix-os/hal/ahci/ata.c @@ -0,0 +1,88 @@ +#include +#include + +#include +#include + +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 diff --git a/lunaix-os/hal/ahci/atapi.c b/lunaix-os/hal/ahci/atapi.c index 193f8f3..c245c0a 100644 --- a/lunaix-os/hal/ahci/atapi.c +++ b/lunaix-os/hal/ahci/atapi.c @@ -1,4 +1,5 @@ #include +#include #include #include @@ -20,14 +21,13 @@ scsi_create_packet12(struct scsi_cdb12* cdb, 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; - 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; } @@ -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)); +} + +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 diff --git a/lunaix-os/hal/ahci/utils.c b/lunaix-os/hal/ahci/utils.c index 9af9cfe..23541ee 100644 --- a/lunaix-os/hal/ahci/utils.c +++ b/lunaix-os/hal/ahci/utils.c @@ -2,24 +2,33 @@ #include #include -#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) { - 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; - 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; } - 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 diff --git a/lunaix-os/includes/hal/ahci/ahci.h b/lunaix-os/includes/hal/ahci/ahci.h index 0494181..acd779b 100644 --- a/lunaix-os/includes/hal/ahci/ahci.h +++ b/lunaix-os/includes/hal/ahci/ahci.h @@ -12,10 +12,6 @@ #define AHCI_HBA_CLASS 0x10601 -#define ATA_IDENTIFY_DEVICE 0xec -#define ATA_IDENTIFY_PAKCET_DEVICE 0xa1 -#define ATA_PACKET 0xa0 - /** * @brief 初始化AHCI与HBA * @@ -26,4 +22,10 @@ ahci_init(); void ahci_list_device(); +unsigned int +ahci_get_port_usage(); + +struct hba_port* +ahci_get_port(unsigned int index); + #endif /* __LUNAIX_AHCI_H */ diff --git a/lunaix-os/includes/hal/ahci/hba.h b/lunaix-os/includes/hal/ahci/hba.h index d836a78..19f76cd 100644 --- a/lunaix-os/includes/hal/ahci/hba.h +++ b/lunaix-os/includes/hal/ahci/hba.h @@ -32,6 +32,9 @@ #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) @@ -82,15 +85,35 @@ struct hba_cmdt 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]; - uint32_t signature; - uint32_t max_lba; + uint32_t flags; + uint64_t max_lba; uint32_t block_size; - uint8_t wwn[8]; + uint64_t wwn; 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 @@ -98,7 +121,7 @@ struct hba_port volatile hba_reg_t* regs; unsigned int ssts; struct hba_cmdh* cmdlst; - struct sata_fis_head* fis; + void* fis; struct hba_device* device; }; @@ -106,6 +129,7 @@ struct ahci_hba { 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]; diff --git a/lunaix-os/includes/hal/ahci/sata.h b/lunaix-os/includes/hal/ahci/sata.h index 135f3eb..f898d32 100644 --- a/lunaix-os/includes/hal/ahci/sata.h +++ b/lunaix-os/includes/hal/ahci/sata.h @@ -6,7 +6,15 @@ #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 { @@ -40,8 +48,19 @@ struct sata_data_fis 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); +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 */ diff --git a/lunaix-os/includes/hal/ahci/scsi.h b/lunaix-os/includes/hal/ahci/scsi.h index 5015641..cce9af4 100644 --- a/lunaix-os/includes/hal/ahci/scsi.h +++ b/lunaix-os/includes/hal/ahci/scsi.h @@ -44,8 +44,19 @@ scsi_create_packet12(struct scsi_cdb12* cdb, 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); +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 */ diff --git a/lunaix-os/includes/hal/ahci/utils.h b/lunaix-os/includes/hal/ahci/utils.h index 119ec39..e22a280 100644 --- a/lunaix-os/includes/hal/ahci/utils.h +++ b/lunaix-os/includes/hal/ahci/utils.h @@ -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); +int +sata_read_error(struct hba_port* port); + #endif /* __LUNAIX_UTILS_H */ diff --git a/lunaix-os/includes/lunaix/mm/valloc.h b/lunaix-os/includes/lunaix/mm/valloc.h index 076503f..d5d0c75 100644 --- a/lunaix-os/includes/lunaix/mm/valloc.h +++ b/lunaix-os/includes/lunaix/mm/valloc.h @@ -4,12 +4,18 @@ void* valloc(unsigned int size); +void* +vcalloc(unsigned int size); + void vfree(void* ptr); void* valloc_dma(unsigned int size); +void* +vcalloc_dma(unsigned int size); + void vfree_dma(void* ptr); diff --git a/lunaix-os/kernel/mm/cake.c b/lunaix-os/kernel/mm/cake.c index fad5bc2..7e3142b 100644 --- a/lunaix-os/kernel/mm/cake.c +++ b/lunaix-os/kernel/mm/cake.c @@ -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. :) @@ -112,14 +112,9 @@ void* 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); diff --git a/lunaix-os/kernel/mm/valloc.c b/lunaix-os/kernel/mm/valloc.c index 0c4d4d4..4ff4794 100644 --- a/lunaix-os/kernel/mm/valloc.c +++ b/lunaix-os/kernel/mm/valloc.c @@ -1,4 +1,6 @@ +#include #include +#include #define MAX_CLASS 6 @@ -64,6 +66,14 @@ valloc(unsigned int size) return __valloc(size, &piles); } +void* +vcalloc(unsigned int size) +{ + void* ptr = __valloc(size, &piles); + memset(ptr, 0, size); + return ptr; +} + void vfree(void* ptr) { @@ -76,6 +86,14 @@ valloc_dma(unsigned int size) 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) { -- 2.27.0