kexts: ahci: implement read support for ATA devices

This commit is contained in:
2023-07-09 22:02:30 +01:00
parent 3233169f25
commit c696bdf122
6 changed files with 107 additions and 5 deletions

View File

@@ -47,6 +47,11 @@ static void free_cmd_table(struct hba_cmd_table *table)
} }
kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct iovec *vec, size_t nvec) kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct iovec *vec, size_t nvec)
{
return send_ata_command_ex(dev, NULL, cmd, vec, nvec);
}
kern_status_t send_ata_command_ex(struct ahci_device *dev, struct fis_reg_h2d *fis, unsigned int cmd, struct iovec *vec, size_t nvec)
{ {
if (nvec == 0) { if (nvec == 0) {
return KERN_OK; return KERN_OK;
@@ -73,6 +78,12 @@ kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct
struct fis_reg_h2d *cmdfis = (struct fis_reg_h2d*)(&cmdtbl->cfis); struct fis_reg_h2d *cmdfis = (struct fis_reg_h2d*)(&cmdtbl->cfis);
if (fis) {
memcpy(cmdfis, fis, sizeof *cmdfis);
} else {
memset(cmdfis, 0x00, sizeof *cmdfis);
}
cmdfis->fis_type = FIS_TYPE_REG_H2D; cmdfis->fis_type = FIS_TYPE_REG_H2D;
cmdfis->c = 1; cmdfis->c = 1;
cmdfis->command = cmd; cmdfis->command = cmd;
@@ -96,12 +107,14 @@ kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct
if (port->is & HBA_PxIS_TFES) { if (port->is & HBA_PxIS_TFES) {
free_cmd_table(cmdtbl); free_cmd_table(cmdtbl);
printk("ahci: command failed");
return KERN_IO_ERROR; return KERN_IO_ERROR;
} }
} }
free_cmd_table(cmdtbl); free_cmd_table(cmdtbl);
if (port->is & HBA_PxIS_TFES) { if (port->is & HBA_PxIS_TFES) {
printk("ahci: command failed");
return KERN_IO_ERROR; return KERN_IO_ERROR;
} }
@@ -109,6 +122,11 @@ kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct
} }
kern_status_t send_atapi_command(struct ahci_device *dev, struct scsi_command *cmd, struct iovec *vec, size_t nvec) kern_status_t send_atapi_command(struct ahci_device *dev, struct scsi_command *cmd, struct iovec *vec, size_t nvec)
{
return send_atapi_command_ex(dev, NULL, cmd, vec, nvec);
}
kern_status_t send_atapi_command_ex(struct ahci_device *dev, struct fis_reg_h2d *fis, struct scsi_command *cmd, struct iovec *vec, size_t nvec)
{ {
if (nvec == 0) { if (nvec == 0) {
return KERN_OK; return KERN_OK;
@@ -136,7 +154,11 @@ kern_status_t send_atapi_command(struct ahci_device *dev, struct scsi_command *c
memcpy(&cmdtbl->acmd, cmd, sizeof *cmd); memcpy(&cmdtbl->acmd, cmd, sizeof *cmd);
struct fis_reg_h2d *cmdfis = (struct fis_reg_h2d *)(&cmdtbl->cfis); struct fis_reg_h2d *cmdfis = (struct fis_reg_h2d *)(&cmdtbl->cfis);
if (fis) {
memcpy(cmdfis, fis, sizeof *cmdfis);
} else {
memset(cmdfis, 0x0, sizeof *cmdfis); memset(cmdfis, 0x0, sizeof *cmdfis);
}
cmdfis->fis_type = FIS_TYPE_REG_H2D; cmdfis->fis_type = FIS_TYPE_REG_H2D;
cmdfis->c = 1; cmdfis->c = 1;

View File

@@ -716,7 +716,9 @@ extern struct driver *ahci_driver(void);
extern kern_status_t identify_ata_device(struct ahci_device *dev, struct identify_device_data *out); extern kern_status_t identify_ata_device(struct ahci_device *dev, struct identify_device_data *out);
extern kern_status_t identify_atapi_device(struct ahci_device *dev, struct identify_device_data *out); extern kern_status_t identify_atapi_device(struct ahci_device *dev, struct identify_device_data *out);
extern kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct iovec *vec, size_t nvec); extern kern_status_t send_ata_command(struct ahci_device *dev, unsigned int cmd, struct iovec *vec, size_t nvec);
extern kern_status_t send_ata_command_ex(struct ahci_device *dev, struct fis_reg_h2d *fis, unsigned int cmd, struct iovec *vec, size_t nvec);
extern kern_status_t send_atapi_command(struct ahci_device *dev, struct scsi_command *cmd, struct iovec *vec, size_t nvec); extern kern_status_t send_atapi_command(struct ahci_device *dev, struct scsi_command *cmd, struct iovec *vec, size_t nvec);
extern kern_status_t send_atapi_command_ex(struct ahci_device *dev, struct fis_reg_h2d *fis, struct scsi_command *cmd, struct iovec *vec, size_t nvec);
extern void rebase_ahci_port(struct ahci_device *dev); extern void rebase_ahci_port(struct ahci_device *dev);
extern void probe_ahci_ports(struct driver *driver, struct device *controller, volatile struct hba_config *abar, extern void probe_ahci_ports(struct driver *driver, struct device *controller, volatile struct hba_config *abar,

View File

@@ -0,0 +1,49 @@
#include <socks/device.h>
#include "ahci.h"
kern_status_t ata_read_blocks(struct device *dev, sectors_t offset, size_t *count, struct iovec *vec, size_t nvec, socks_flags_t flags)
{
struct fis_reg_h2d fis = {0};
size_t c = *count;
c &= 0xFFFF;
fis.fis_type = FIS_TYPE_REG_H2D;
fis.count_l = (c & 0xFFu);
fis.count_h = (c >> 8) & 0xFFu;
fis.lba0 = offset & 0xFFu;
fis.lba1 = (offset >> 8) & 0xFFu;
fis.lba2 = (offset >> 16) & 0xFFu;
fis.lba3 = (offset >> 24) & 0xFFu;
fis.lba4 = (offset >> 32) & 0xFFu;
fis.lba5 = (offset >> 40) & 0xFFu;
fis.device = 1 << 6;
struct ahci_device *ahci_dev = dev->dev_priv;
kern_status_t status = send_ata_command_ex(ahci_dev, &fis, ATA_CMD_READ_DMA_EX, vec, nvec);
if (status == KERN_OK) {
*count = c;
} else {
*count = 0;
}
return status;
}
kern_status_t ata_write_blocks(struct device *dev, sectors_t offset, size_t *count, struct iovec *vec, size_t nvec, socks_flags_t flags)
{
return KERN_UNSUPPORTED;
}
kern_status_t ata_ioctl(struct device *dev, unsigned int req, void *argp)
{
return KERN_UNSUPPORTED;
}
struct block_device_ops ata_device_ops = {
.read_blocks = ata_read_blocks,
.write_blocks = ata_write_blocks,
.ioctl = ata_ioctl,
};

View File

@@ -0,0 +1,22 @@
#include <socks/device.h>
kern_status_t atapi_read_blocks(struct device *dev, sectors_t offset, size_t *count, struct iovec *vec, size_t nvec, socks_flags_t flags)
{
return KERN_UNSUPPORTED;
}
kern_status_t atapi_write_blocks(struct device *dev, sectors_t offset, size_t *count, struct iovec *vec, size_t nvec, socks_flags_t flags)
{
return KERN_UNSUPPORTED;
}
kern_status_t atapi_ioctl(struct device *dev, unsigned int req, void *argp)
{
return KERN_UNSUPPORTED;
}
struct block_device_ops atapi_device_ops = {
.read_blocks = atapi_read_blocks,
.write_blocks = atapi_write_blocks,
.ioctl = atapi_ioctl,
};

View File

@@ -4,6 +4,9 @@
#include <socks/libc/stdio.h> #include <socks/libc/stdio.h>
#include "ahci.h" #include "ahci.h"
extern struct block_device_ops ata_device_ops;
extern struct block_device_ops atapi_device_ops;
extern void create_device_from_ahci_port(int port_no, struct device *controller, volatile struct hba_port *port, int type) extern void create_device_from_ahci_port(int port_no, struct device *controller, volatile struct hba_port *port, int type)
{ {
struct block_device *bdev = block_device_create(); struct block_device *bdev = block_device_create();
@@ -37,8 +40,9 @@ extern void create_device_from_ahci_port(int port_no, struct device *controller,
} }
/* TODO read IDENTIFY DEVICE log to support non-512 sector sizes */ /* TODO read IDENTIFY DEVICE log to support non-512 sector sizes */
bdev->sector_size = 512; bdev->b_ops = &ata_device_ops;
bdev->capacity = identity_data.user_addressable_sectors; bdev->b_sector_size = 512;
bdev->b_capacity = identity_data.user_addressable_sectors;
snprintf(bdev_base->dev_model_name, sizeof bdev_base->dev_model_name, "%s", identity_data.model_number); snprintf(bdev_base->dev_model_name, sizeof bdev_base->dev_model_name, "%s", identity_data.model_number);
} else if (type == AHCI_DEV_SATAPI) { } else if (type == AHCI_DEV_SATAPI) {
@@ -62,8 +66,9 @@ extern void create_device_from_ahci_port(int port_no, struct device *controller,
return; return;
} }
bdev->sector_size = big_to_host_u32(cmd_result.block_size); bdev->b_ops = &atapi_device_ops;
bdev->capacity = big_to_host_u32(cmd_result.last_sector) + 1; bdev->b_sector_size = big_to_host_u32(cmd_result.block_size);
bdev->b_capacity = big_to_host_u32(cmd_result.last_sector) + 1;
snprintf(bdev_base->dev_model_name, sizeof bdev_base->dev_model_name, "%s", identity_data.model_number); snprintf(bdev_base->dev_model_name, sizeof bdev_base->dev_model_name, "%s", identity_data.model_number);
} }

View File

@@ -8,4 +8,6 @@ sources:
- main.c - main.c
- device.c - device.c
- ahci.c - ahci.c
- ata.c
- atapi.c
- ahci.h - ahci.h