kexts: ahci: implement read support for ATA devices
This commit is contained in:
@@ -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)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
|
||||
if (fis) {
|
||||
memcpy(cmdfis, fis, sizeof *cmdfis);
|
||||
} else {
|
||||
memset(cmdfis, 0x00, sizeof *cmdfis);
|
||||
}
|
||||
|
||||
cmdfis->fis_type = FIS_TYPE_REG_H2D;
|
||||
cmdfis->c = 1;
|
||||
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) {
|
||||
free_cmd_table(cmdtbl);
|
||||
printk("ahci: command failed");
|
||||
return KERN_IO_ERROR;
|
||||
}
|
||||
}
|
||||
free_cmd_table(cmdtbl);
|
||||
|
||||
if (port->is & HBA_PxIS_TFES) {
|
||||
printk("ahci: command failed");
|
||||
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)
|
||||
{
|
||||
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) {
|
||||
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);
|
||||
|
||||
struct fis_reg_h2d *cmdfis = (struct fis_reg_h2d *)(&cmdtbl->cfis);
|
||||
memset(cmdfis, 0x0, sizeof *cmdfis);
|
||||
if (fis) {
|
||||
memcpy(cmdfis, fis, sizeof *cmdfis);
|
||||
} else {
|
||||
memset(cmdfis, 0x0, sizeof *cmdfis);
|
||||
}
|
||||
|
||||
cmdfis->fis_type = FIS_TYPE_REG_H2D;
|
||||
cmdfis->c = 1;
|
||||
|
||||
@@ -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_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_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_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 probe_ahci_ports(struct driver *driver, struct device *controller, volatile struct hba_config *abar,
|
||||
|
||||
49
kexts/drivers/block/ahci/ata.c
Normal file
49
kexts/drivers/block/ahci/ata.c
Normal 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,
|
||||
};
|
||||
22
kexts/drivers/block/ahci/atapi.c
Normal file
22
kexts/drivers/block/ahci/atapi.c
Normal 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,
|
||||
};
|
||||
@@ -4,6 +4,9 @@
|
||||
#include <socks/libc/stdio.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)
|
||||
{
|
||||
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 */
|
||||
bdev->sector_size = 512;
|
||||
bdev->capacity = identity_data.user_addressable_sectors;
|
||||
bdev->b_ops = &ata_device_ops;
|
||||
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);
|
||||
} else if (type == AHCI_DEV_SATAPI) {
|
||||
@@ -62,8 +66,9 @@ extern void create_device_from_ahci_port(int port_no, struct device *controller,
|
||||
return;
|
||||
}
|
||||
|
||||
bdev->sector_size = big_to_host_u32(cmd_result.block_size);
|
||||
bdev->capacity = big_to_host_u32(cmd_result.last_sector) + 1;
|
||||
bdev->b_ops = &atapi_device_ops;
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -8,4 +8,6 @@ sources:
|
||||
- main.c
|
||||
- device.c
|
||||
- ahci.c
|
||||
- ata.c
|
||||
- atapi.c
|
||||
- ahci.h
|
||||
|
||||
Reference in New Issue
Block a user