* SCSI SIM module driver shell for the AHCI driver for Marcus.

It is loaded on boot, and the SCSI bus manager tries to scan its bus which
  of course fails at the moment. Hope that helps :-)
* Moved the driver to its new location; it's a SCSI bus controller, so it
  should be placed in busses/scsi.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@22048 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2007-08-23 23:29:08 +00:00
parent d570f3bf79
commit 8be13cd585
10 changed files with 449 additions and 201 deletions

View File

@ -130,6 +130,8 @@ AddFilesToHaikuImage beos system add-ons kernel bus_managers
: $(BEOS_ADD_ONS_BUS_MANAGERS) ;
AddFilesToHaikuImage beos system add-ons kernel busses ide
: generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata ;
AddFilesToHaikuImage beos system add-ons kernel busses scsi
: ahci ;
AddFilesToHaikuImage beos system add-ons kernel busses usb
: <usb>uhci <usb>ohci <usb>ehci ;
AddFilesToHaikuImage beos system add-ons kernel console : vga_text ;
@ -153,7 +155,6 @@ AddDriversToHaikuImage : console dprintf $(X86_ONLY)keyboard null
AddDriversToHaikuImage audio hmulti : $(BEOS_ADD_ONS_DRIVERS_AUDIO) ;
AddDriversToHaikuImage midi : $(BEOS_ADD_ONS_DRIVERS_MIDI) ;
AddDriversToHaikuImage bus : usb_raw ;
AddDriversToHaikuImage disk : ahci ;
AddDriversToHaikuImage disk scsi : scsi_cd scsi_dsk ;
AddDriversToHaikuImage disk virtual : nbd ;
AddDriversToHaikuImage dvb : cx23882 ;

View File

@ -1,5 +1,6 @@
SubDir HAIKU_TOP src add-ons kernel busses scsi ;
SubInclude HAIKU_TOP src add-ons kernel busses scsi ahci ;
SubInclude HAIKU_TOP src add-ons kernel busses scsi 53c8xx ;
SubInclude HAIKU_TOP src add-ons kernel busses scsi buslogic ;
SubInclude HAIKU_TOP src add-ons kernel busses scsi usb ;

View File

@ -0,0 +1,6 @@
SubDir HAIKU_TOP src add-ons kernel busses scsi ahci ;
KernelAddon ahci :
ahci.c
ahci_sim.c
;

View File

@ -0,0 +1,248 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ahci_defs.h"
#include <stdlib.h>
#include <string.h>
#include <block_io.h>
#define TRACE(a...) dprintf("\33[35mahci:\33[30m " a)
#define FLOW(a...) dprintf("ahci: " a)
#define AHCI_ID_GENERATOR "ahci/id"
#define AHCI_ID_ITEM "ahci/id"
static device_manager_info *sDeviceManager;
static pci_device *sPCIDevice;
static status_t
register_sim(device_node_handle parent)
{
int32 id = sDeviceManager->create_id(AHCI_ID_GENERATOR);
if (id < 0)
return id;
{
device_attr attrs[] = {
{ B_DRIVER_MODULE, B_STRING_TYPE,
{ string: AHCI_SIM_MODULE_NAME }},
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE,
{ string: SCSI_FOR_SIM_MODULE_NAME }},
{ SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
{ string: AHCI_DEVICE_MODULE_NAME }},
{ B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: 255 }},
{ AHCI_ID_ITEM, B_UINT32_TYPE, { ui32: id }},
{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE,
{ string: AHCI_ID_GENERATOR }},
{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }},
{ NULL }
};
device_node_handle node;
status_t status = sDeviceManager->register_device(parent, attrs, NULL,
&node);
if (status < B_OK)
sDeviceManager->free_id(AHCI_ID_GENERATOR, id);
return status;
}
}
// #pragma mark -
static float
ahci_supports_device(device_node_handle parent, bool *_noConnection)
{
uint8 baseClass, subClass, classAPI;
uint16 vendorID;
uint16 deviceID;
char *bus;
TRACE("ahci_supports_device\n");
// make sure parent is an PCI IDE mass storage host adapter device node
if (sDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus,
false) != B_OK
|| sDeviceManager->get_attr_uint8(parent,
PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) != B_OK
|| sDeviceManager->get_attr_uint8(parent,
PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) != B_OK
|| sDeviceManager->get_attr_uint8(parent,
PCI_DEVICE_API_ID_ITEM, &classAPI, false) != B_OK
|| sDeviceManager->get_attr_uint16(parent,
PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) != B_OK
|| sDeviceManager->get_attr_uint16(parent,
PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) != B_OK)
return B_ERROR;
#if 1
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage
|| subClass != PCI_sata || classAPI != PCI_sata_ahci) {
free(bus);
return 0.0f;
}
#else
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage
|| subClass != PCI_ide) {
free(bus);
return 0.0;
}
#endif
TRACE("controller found! vendor 0x%04x, device 0x%04x\n",
vendorID, deviceID);
#if 0
res = pci->find_pci_capability(device, PCI_cap_id_sata, &cap_ofs);
if (res == B_OK) {
uint32 satacr0;
uint32 satacr1;
TRACE("PCI SATA capability found at offset 0x%x\n", cap_ofs);
satacr0 = pci->read_pci_config(device, cap_ofs, 4);
satacr1 = pci->read_pci_config(device, cap_ofs + 4, 4);
TRACE("satacr0 = 0x%08x, satacr1 = 0x%08x\n", satacr0, satacr1);
}
#endif
free(bus);
return 0.5;
}
static status_t
ahci_register_device(device_node_handle parent)
{
device_node_handle node;
status_t status;
device_attr attrs[] = {
// info about ourself and our consumer
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: AHCI_DEVICE_MODULE_NAME }},
// DMA properties
// data must be word-aligned;
{ B_BLOCK_DEVICE_DMA_ALIGNMENT, B_UINT32_TYPE,
{ ui32: 1 }},
// one S/G block must not cross 64K boundary
{ B_BLOCK_DEVICE_DMA_BOUNDARY, B_UINT32_TYPE,
{ ui32: 0xffff }},
// max size of S/G block is 16 bits with zero being 64K
{ B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, B_UINT32_TYPE,
{ ui32: 0x10000 }},
// see definition of MAX_SG_COUNT
{ B_BLOCK_DEVICE_MAX_SG_BLOCKS, B_UINT32_TYPE,
{ ui32: 32 /* whatever... */ }},
{ NULL }
};
TRACE("ahci_register_device\n");
// initialize parent (the bus) to get the PCI interface and device
status = sDeviceManager->init_driver(parent, NULL,
(driver_module_info **)&gPCI, (void **)&sPCIDevice);
if (status != B_OK)
return status;
status = sDeviceManager->register_device(parent, attrs,
NULL, &node);
if (status < B_OK)
return status;
// TODO: register SIM for every controller we find!
return register_sim(node);
}
static status_t
ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie)
{
TRACE("ahci_init_driver\n");
return B_OK;
}
static status_t
ahci_uninit_driver(void *cookie)
{
TRACE("ahci_uninit_driver\n");
return B_OK;
}
static void
ahci_device_removed(device_node_handle node, void *cookie)
{
TRACE("ahci_device_removed\n");
}
static void
ahci_device_cleanup(device_node_handle node)
{
TRACE("ahci_device_cleanup\n");
}
static void
ahci_get_supported_paths(const char ***_busses, const char ***_devices)
{
static const char *kBus[] = { "pci", NULL };
static const char *kDevice[] = { "drivers/dev/disk/sata", NULL };
TRACE("ahci_get_supported_paths\n");
*_busses = kBus;
*_devices = kDevice;
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
driver_module_info sAHCIDevice = {
{
AHCI_DEVICE_MODULE_NAME,
0,
std_ops
},
ahci_supports_device,
ahci_register_device,
ahci_init_driver,
ahci_uninit_driver,
ahci_device_removed,
ahci_device_cleanup,
ahci_get_supported_paths,
};
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager },
{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI },
{}
};
module_info *modules[] = {
(module_info *)&sAHCIDevice,
(module_info *)&gAHCISimInterface,
NULL
};

View File

@ -2,14 +2,17 @@
* Copyright 2007, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef _AHCI_DEFS_H
#define _AHCI_DEFS_H
#include <SupportDefs.h>
#include <bus/PCI.h>
#include <bus/SCSI.h>
typedef struct
{
#define AHCI_DEVICE_MODULE_NAME "busses/scsi/ahci/device_v1"
#define AHCI_SIM_MODULE_NAME "busses/scsi/ahci/sim/v1"
typedef struct {
uint32 clb; // Command List Base Address
uint32 clbu; // Command List Base Address Upper 32-Bits
uint32 fb; // FIS Base Address
@ -32,8 +35,7 @@ typedef struct
} ahci_port;
typedef struct
{
typedef struct {
uint32 cap; // Host Capabilities
uint32 ghc; // Global Host Control
uint32 is; // Interrupt Status
@ -48,4 +50,8 @@ typedef struct
ahci_port port[32];
} ahci_hba;
#endif
extern scsi_sim_interface gAHCISimInterface;
extern pci_device_module_info *gPCI;
extern scsi_for_sim_interface *gSCSI;
#endif /* _AHCI_DEFS_H */

View File

@ -0,0 +1,179 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include "ahci_defs.h"
#include <KernelExport.h>
#define TRACE(a...) dprintf("\33[34mahci:\33[30m " a)
#define FLOW(a...) dprintf("ahci: " a)
pci_device_module_info *gPCI;
scsi_for_sim_interface *gSCSI;
// #pragma mark - SIM module interface
//! execute request
static void
ahci_scsi_io(scsi_sim_cookie cookie, scsi_ccb *request)
{
TRACE("ahci_scsi_io()\n");
request->subsys_status = SCSI_NO_HBA;
gSCSI->finished(request, 1);
}
//! abort request
static uchar
ahci_abort_io(scsi_sim_cookie cookie, scsi_ccb *request)
{
TRACE("ahci_abort_io()\n");
return SCSI_REQ_CMP;
}
static uchar
ahci_reset_device(scsi_sim_cookie cookie, uchar targetID, uchar targetLUN)
{
TRACE("ahci_reset_device()\n");
return SCSI_REQ_CMP;
}
//! terminate request
static uchar
ahci_terminate_io(scsi_sim_cookie cookie, scsi_ccb *request)
{
TRACE("ahci_terminate_io()\n");
return SCSI_NO_HBA;
}
//! get information about bus
static uchar
ahci_path_inquiry(scsi_sim_cookie cookie, scsi_path_inquiry *info)
{
TRACE("ahci_path_inquiry()\n");
return SCSI_NO_HBA;
}
//! this is called immediately before the SCSI bus manager scans the bus
static uchar
ahci_scan_bus(scsi_sim_cookie cookie)
{
TRACE("ahci_scan_bus()\n");
return SCSI_NO_HBA;
}
static uchar
ahci_reset_bus(scsi_sim_cookie cookie)
{
TRACE("ahci_reset_bus()\n");
return SCSI_NO_HBA;
}
/*! Get restrictions of one device
(used for non-SCSI transport protocols and bug fixes)
*/
static void
ahci_get_restrictions(scsi_sim_cookie cookie, uchar targetID, bool *isATAPI,
bool *noAutoSense, uint32 *maxBlocks)
{
TRACE("ahci_get_restrictions()\n");
*isATAPI = false;
*noAutoSense = false;
*maxBlocks = 255;
}
static status_t
ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
size_t length)
{
TRACE("ahci_ioctl()\n");
return B_BAD_VALUE;
}
// #pragma mark -
static status_t
ahci_sim_init_bus(device_node_handle node, void *user_cookie, void **_cookie)
{
TRACE("ahci_sim_init_bus\n");
return B_OK;
}
static status_t
ahci_sim_uninit_bus(void *cookie)
{
TRACE("ahci_sim_uninit_bus\n");
return B_OK;
}
static void
ahci_sim_bus_removed(device_node_handle node, void *cookie)
{
TRACE("ahci_sim_bus_removed\n");
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
scsi_sim_interface gAHCISimInterface = {
{
{
AHCI_SIM_MODULE_NAME,
0,
std_ops
},
NULL, // supported devices
NULL, // register node
ahci_sim_init_bus,
ahci_sim_uninit_bus,
ahci_sim_bus_removed,
NULL, // device cleanup
NULL, // get supported paths
},
ahci_scsi_io,
ahci_abort_io,
ahci_reset_device,
ahci_terminate_io,
ahci_path_inquiry,
ahci_scan_bus,
ahci_reset_bus,
ahci_get_restrictions,
ahci_ioctl
};

View File

@ -1,6 +1,5 @@
SubDir HAIKU_TOP src add-ons kernel drivers disk ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk acpi_loader ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk ahci ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk scsi ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk virtual ;

View File

@ -1,7 +0,0 @@
SubDir HAIKU_TOP src add-ons kernel drivers disk ahci ;
KernelAddon ahci :
ahci.c
ahci_sim.c
;

View File

@ -1,130 +0,0 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <device_manager.h>
#define TRACE(a...) dprintf("\33[35mahci:\33[30m " a)
#define FLOW(a...) dprintf("ahci: " a)
static float
ahci_supports_device(device_node_handle parent, bool *_noConnection)
{
TRACE("ahci_supports_device\n");
#if 0
uint16 vendor_id;
uint16 device_id;
uint8 base_class;
uint8 sub_class;
uint8 class_api;
status_t res;
if (base_class != PCI_mass_storage || sub_class != PCI_sata || class_api != PCI_sata_ahci)
return 0.0f;
TRACE("controller found! vendor 0x%04x, device 0x%04x\n", vendor_id, device_id);
res = pci->find_pci_capability(device, PCI_cap_id_sata, &cap_ofs);
if (res == B_OK) {
uint32 satacr0;
uint32 satacr1;
TRACE("PCI SATA capability found at offset 0x%x\n", cap_ofs);
satacr0 = pci->read_pci_config(device, cap_ofs, 4);
satacr1 = pci->read_pci_config(device, cap_ofs + 4, 4);
TRACE("satacr0 = 0x%08x, satacr1 = 0x%08x\n", satacr0, satacr1);
}
#endif
return 0.0;
}
static status_t
ahci_register_device(device_node_handle parent)
{
TRACE("ahci_register_device\n");
return B_OK;
}
static status_t
ahci_init_driver(device_node_handle node, void *user_cookie, void **_cookie)
{
TRACE("ahci_init_driver\n");
return B_OK;
}
static status_t
ahci_uninit_driver(void *cookie)
{
TRACE("ahci_uninit_driver\n");
return B_OK;
}
static void
ahci_device_removed(device_node_handle node, void *cookie)
{
TRACE("ahci_device_removed\n");
}
static void
ahci_device_cleanup(device_node_handle node)
{
TRACE("ahci_device_cleanup\n");
}
static void
ahci_get_supported_paths(const char ***_busses, const char ***_devices)
{
static const char *kBus[] = { "pci", NULL };
static const char *kDevice[] = { "drivers/dev/disk/sata", NULL };
TRACE("ahci_get_supported_paths\n");
*_busses = kBus;
*_devices = kDevice;
}
static status_t
std_ops(int32 op, ...)
{
switch (op) {
case B_MODULE_INIT:
case B_MODULE_UNINIT:
return B_OK;
default:
return B_ERROR;
}
}
driver_module_info ahci_driver = {
{
"ahci/device_v1",
0,
std_ops
},
ahci_supports_device,
ahci_register_device,
ahci_init_driver,
ahci_uninit_driver,
ahci_device_removed,
ahci_device_cleanup,
ahci_get_supported_paths,
};
module_info *modules[] = {
(module_info *)&ahci_driver,
NULL
};

View File

@ -1,55 +0,0 @@
/*
* Copyright 2007, Marcus Overhagen. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#include <KernelExport.h>
#include <bus/SCSI.h>
#define TRACE(a...) dprintf("ahci: " a)
#define FLOW(a...) dprintf("ahci: " a)
/*
// SIM interface
// SCSI controller drivers must provide this interface
typedef struct scsi_sim_interface {
driver_module_info info;
// execute request
void (*scsi_io)( scsi_sim_cookie cookie, scsi_ccb *ccb );
// abort request
uchar (*abort)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort );
// reset device
uchar (*reset_device)( scsi_sim_cookie cookie, uchar target_id, uchar target_lun );
// terminate request
uchar (*term_io)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate );
// get information about bus
uchar (*path_inquiry)( scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data );
// scan bus
// this is called immediately before the SCSI bus manager scans the bus
uchar (*scan_bus)( scsi_sim_cookie cookie );
// reset bus
uchar (*reset_bus)( scsi_sim_cookie cookie );
// get restrictions of one device
// (used for non-SCSI transport protocols and bug fixes)
void (*get_restrictions)(
scsi_sim_cookie cookie,
uchar target_id, // target id
bool *is_atapi, // set to true if this is an ATAPI device that
// needs some commands emulated
bool *no_autosense, // set to true if there is no autosense;
// the SCSI bus manager will request sense on
// SCSI_REQ_CMP_ERR/SCSI_DEVICE_CHECK_CONDITION
uint32 *max_blocks ); // maximum number of blocks per transfer if > 0;
// used for buggy devices that cannot handle
// large transfers (read: ATAPI ZIP drives)
status_t (*ioctl)(scsi_sim_cookie, uint8 targetID, uint32 op, void *buffer, size_t length);
} scsi_sim_interface;
*/