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)
|
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);
|
||||||
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->fis_type = FIS_TYPE_REG_H2D;
|
||||||
cmdfis->c = 1;
|
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_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,
|
||||||
|
|||||||
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 <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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user