1/* 2 * Copyright 2007-2009, Marcus Overhagen. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6#include "ahci_controller.h" 7 8#include <KernelExport.h> 9#include <string.h> 10#include <new> 11 12#define TRACE(a...) dprintf("ahci: " a) 13//#define FLOW(a...) dprintf("ahci: " a) 14#define FLOW(a...) 15 16 17// #pragma mark - SIM module interface 18 19 20static void 21ahci_set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus) 22{ 23} 24 25 26//! execute request 27static void 28ahci_scsi_io(scsi_sim_cookie cookie, scsi_ccb *request) 29{ 30 FLOW("ahci_scsi_io, cookie %p, path_id %u, target_id %u, target_lun %u\n", 31 cookie, request->path_id, request->target_id, request->target_lun); 32 static_cast<AHCIController *>(cookie)->ExecuteRequest(request); 33} 34 35 36//! abort request 37static uchar 38ahci_abort_io(scsi_sim_cookie cookie, scsi_ccb *request) 39{ 40 TRACE("ahci_abort_io, cookie %p\n", cookie); 41 return static_cast<AHCIController *>(cookie)->AbortRequest(request); 42} 43 44 45static uchar 46ahci_reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN) 47{ 48 TRACE("ahci_reset_device, cookie %p\n", cookie); 49 return static_cast<AHCIController *>(cookie)->ResetDevice(targetID, targetLUN); 50} 51 52 53//! terminate request 54static uchar 55ahci_terminate_io(scsi_sim_cookie cookie, scsi_ccb *request) 56{ 57 TRACE("ahci_terminate_io, cookie %p\n", cookie); 58 return static_cast<AHCIController *>(cookie)->TerminateRequest(request); 59} 60 61 62//! get information about bus 63static uchar 64ahci_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info) 65{ 66 TRACE("ahci_path_inquiry, cookie %p\n", cookie); 67 68 memset(info, 0, sizeof(*info)); 69 info->version_num = 1; 70 // supports tagged requests and soft reset 71 info->hba_inquiry = 0; // SCSI_PI_TAG_ABLE | SCSI_PI_SOFT_RST; 72 // controller is 32, devices are 0 to 31 73 info->initiator_id = 32; 74 // adapter command queue size 75 info->hba_queue_size = 1; 76 77 return SCSI_REQ_CMP; 78} 79 80 81//! this is called immediately before the SCSI bus manager scans the bus 82static uchar 83ahci_scan_bus(scsi_sim_cookie cookie) 84{ 85 TRACE("ahci_scan_bus, cookie %p\n", cookie); 86 87 return SCSI_REQ_CMP; 88} 89 90 91static uchar 92ahci_reset_bus(scsi_sim_cookie cookie) 93{ 94 TRACE("ahci_reset_bus, cookie %p\n", cookie); 95 96 return SCSI_REQ_CMP; 97} 98 99 100/*! Get restrictions of one device 101 (used for non-SCSI transport protocols and bug fixes) 102*/ 103static void 104ahci_get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI, 105 bool *noAutoSense, uint32 *maxBlocks) 106{ 107 TRACE("ahci_get_restrictions, cookie %p\n", cookie); 108 109 static_cast<AHCIController *>(cookie)->GetRestrictions(targetID, isATAPI, noAutoSense, maxBlocks); 110} 111 112 113static status_t 114ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer, 115 size_t length) 116{ 117 TRACE("ahci_ioctl, cookie %p\n", cookie); 118 return B_DEV_INVALID_IOCTL; 119} 120 121 122// #pragma mark - 123 124 125static status_t 126ahci_sim_init_bus(device_node *node, void **_cookie) 127{ 128 TRACE("ahci_sim_init_bus\n"); 129 130 // get the PCI device from our parent's parent 131 device_node *parent = gDeviceManager->get_parent_node(node); 132 device_node *pciParent = gDeviceManager->get_parent_node(parent); 133 gDeviceManager->put_node(parent); 134 135 pci_device_module_info *pci; 136 pci_device *pciDevice; 137 gDeviceManager->get_driver(pciParent, (driver_module_info **)&pci, 138 (void **)&pciDevice); 139 gDeviceManager->put_node(pciParent); 140 141 TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice); 142 143 AHCIController *controller = new(std::nothrow) AHCIController(node, pci, 144 pciDevice); 145 if (!controller) 146 return B_NO_MEMORY; 147 status_t status = controller->Init(); 148 if (status < B_OK) { 149 delete controller; 150 return status; 151 } 152 153 *_cookie = controller; 154 TRACE("cookie = %p\n", *_cookie); 155 return B_OK; 156} 157 158 159static void 160ahci_sim_uninit_bus(void *cookie) 161{ 162 TRACE("ahci_sim_uninit_bus, cookie %p\n", cookie); 163 AHCIController *controller = static_cast<AHCIController *>(cookie); 164 165 controller->Uninit(); 166 delete controller; 167} 168 169 170static void 171ahci_sim_bus_removed(void *cookie) 172{ 173 TRACE("ahci_sim_bus_removed, cookie %p\n", cookie); 174} 175 176 177static status_t 178std_ops(int32 op, ...) 179{ 180 switch (op) { 181 case B_MODULE_INIT: 182 case B_MODULE_UNINIT: 183 return B_OK; 184 185 default: 186 return B_ERROR; 187 } 188} 189 190 191scsi_sim_interface gAHCISimInterface = { 192 { 193 { 194 AHCI_SIM_MODULE_NAME, 195 0, 196 std_ops 197 }, 198 NULL, // supported devices 199 NULL, // register node 200 ahci_sim_init_bus, 201 ahci_sim_uninit_bus, 202 NULL, // register child devices 203 NULL, // rescan 204 ahci_sim_bus_removed 205 }, 206 ahci_set_scsi_bus, 207 ahci_scsi_io, 208 ahci_abort_io, 209 ahci_reset_device, 210 ahci_terminate_io, 211 ahci_path_inquiry, 212 ahci_scan_bus, 213 ahci_reset_bus, 214 ahci_get_restrictions, 215 ahci_ioctl 216}; 217