Files
mango/kexts/drivers/block/ahci/device.c
2023-07-09 09:07:15 +01:00

73 lines
2.1 KiB
C

#include <socks/device.h>
#include <socks/util.h>
#include <socks/printk.h>
#include <socks/libc/stdio.h>
#include "ahci.h"
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();
if (!bdev) {
return;
}
struct device *bdev_base = block_device_base(bdev);
struct ahci_device *ahci_dev = kmalloc(sizeof *ahci_dev, VM_NORMAL);
if (!ahci_dev) {
device_deref(bdev_base);
return;
}
ahci_dev->port = port;
ahci_dev->port_no = port_no;
ahci_dev->type = type;
bdev_base->dev_priv = ahci_dev;
rebase_ahci_port(ahci_dev);
snprintf(bdev_base->dev_name, sizeof bdev_base->dev_name, "ahci%d", port_no);
if (type == AHCI_DEV_SATA) {
struct identify_device_data identity_data = {0};
kern_status_t status = identify_ata_device(ahci_dev, &identity_data);
if (status != KERN_OK) {
kfree(ahci_dev);
device_deref(bdev_base);
return;
}
/* TODO read IDENTIFY DEVICE log to support non-512 sector sizes */
bdev->sector_size = 512;
bdev->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) {
struct identify_device_data identity_data = {0};
kern_status_t status = identify_atapi_device(ahci_dev, &identity_data);
if (status != KERN_OK) {
kfree(ahci_dev);
device_deref(bdev_base);
return;
}
struct scsi_command cmd = {0};
cmd.cmd = SCSI_CMD_READ_CAPACITY;
struct scsi_read_capacity_data cmd_result = {0};
struct iovec vec = { .io_buf = &cmd_result, .io_len = sizeof cmd_result };
status = send_atapi_command(ahci_dev, &cmd, &vec, 1);
if (status != KERN_OK) {
printk("ahci: failed to contact ATAPI device: %s", kern_status_string(status));
return;
}
bdev->sector_size = big_to_host_u32(cmd_result.block_size);
bdev->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);
}
device_register(bdev_base, ahci_driver(), controller);
}