* Added an optional ioctl() function to the modules up to the SIM interface.
* Implemented the functions needed by ideinfo/idestatus using this one. * The IDE bus manager now disables DMA if the safemode settings ask for this. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16944 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
|
||||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef __SCSI_BUSMANAGER_H__
|
#ifndef _SCSI_BUSMANAGER_H_
|
||||||
#define __SCSI_BUSMANAGER_H__
|
#define _SCSI_BUSMANAGER_H_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
SCSI bus manager interface
|
SCSI bus manager interface
|
||||||
|
|
||||||
The bus manager interface is _based_ on CAM, but I've modified it because :-
|
The bus manager interface is _based_ on CAM, but I've modified it because :-
|
||||||
@@ -315,6 +315,8 @@ typedef struct scsi_device_interface {
|
|||||||
uchar (*reset_device)(scsi_device device);
|
uchar (*reset_device)(scsi_device device);
|
||||||
// terminate request
|
// terminate request
|
||||||
uchar (*term_io)(scsi_ccb *ccb_to_terminate);
|
uchar (*term_io)(scsi_ccb *ccb_to_terminate);
|
||||||
|
|
||||||
|
status_t (*ioctl)(scsi_device device, uint32 op, void *buffer, size_t length);
|
||||||
} scsi_device_interface;
|
} scsi_device_interface;
|
||||||
|
|
||||||
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
|
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
|
||||||
@@ -439,8 +441,8 @@ typedef struct scsi_sim_interface {
|
|||||||
|
|
||||||
// get restrictions of one device
|
// get restrictions of one device
|
||||||
// (used for non-SCSI transport protocols and bug fixes)
|
// (used for non-SCSI transport protocols and bug fixes)
|
||||||
void (*get_restrictions)(
|
void (*get_restrictions)(
|
||||||
scsi_sim_cookie cookie,
|
scsi_sim_cookie cookie,
|
||||||
uchar target_id, // target id
|
uchar target_id, // target id
|
||||||
bool *is_atapi, // set to true if this is an ATAPI device that
|
bool *is_atapi, // set to true if this is an ATAPI device that
|
||||||
// needs some commands emulated
|
// needs some commands emulated
|
||||||
@@ -450,7 +452,9 @@ typedef struct scsi_sim_interface {
|
|||||||
uint32 *max_blocks ); // maximum number of blocks per transfer if > 0;
|
uint32 *max_blocks ); // maximum number of blocks per transfer if > 0;
|
||||||
// used for buggy devices that cannot handle
|
// used for buggy devices that cannot handle
|
||||||
// large transfers (read: ATAPI ZIP drives)
|
// large transfers (read: ATAPI ZIP drives)
|
||||||
|
|
||||||
|
status_t (*ioctl)(scsi_sim_cookie, uint8 targetID, uint32 op, void *buffer, size_t length);
|
||||||
} scsi_sim_interface;
|
} scsi_sim_interface;
|
||||||
|
|
||||||
|
|
||||||
#endif /* __SCSI_BUSMANAGER_H__ */
|
#endif /* _SCSI_BUSMANAGER_H_ */
|
||||||
|
|||||||
@@ -1,24 +1,29 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the OpenBeOS License.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
#ifndef _IDE_DEVICE_INFOBLOCK_H_
|
||||||
|
#define _IDE_DEVICE_INFOBLOCK_H_
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Part of Open IDE bus manager
|
|
||||||
|
|
||||||
Definition of response to IDE_CMD_IDENTIFY_DEVICE or
|
Definition of response to IDE_CMD_IDENTIFY_DEVICE or
|
||||||
IDE_CMD_IDENTIFY_PACKET_DEVICE
|
IDE_CMD_IDENTIFY_PACKET_DEVICE
|
||||||
|
|
||||||
When a new entry is inserted, add its offset in hex
|
When a new entry is inserted, add its offset in hex
|
||||||
and its index in decimal as a remark. Without that, you
|
and its index in decimal as a remark. Without that, you
|
||||||
have a rough time when you messed up the offsets.
|
have a rough time when you messed up the offsets.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __IDE_DEVICE_INFOBLOCK_H__
|
|
||||||
#define __IDE_DEVICE_INFOBLOCK_H__
|
|
||||||
|
|
||||||
#include <lendian_bitfield.h>
|
#include <lendian_bitfield.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define IDE_GET_INFO_BLOCK 0x2710
|
||||||
|
#define IDE_GET_STATUS 0x2711
|
||||||
|
|
||||||
|
|
||||||
// must be 512 bytes!!!
|
// must be 512 bytes!!!
|
||||||
typedef struct tagdevice_infoblock {
|
typedef struct tagdevice_infoblock {
|
||||||
union { // 0 general configuration
|
union { // 0 general configuration
|
||||||
@@ -181,5 +186,11 @@ typedef struct tagdevice_infoblock {
|
|||||||
uint16 dummy14[128]; // 100 (128)
|
uint16 dummy14[128]; // 100 (128)
|
||||||
} ide_device_infoblock;
|
} ide_device_infoblock;
|
||||||
|
|
||||||
|
typedef struct ide_status {
|
||||||
|
uint8 _reserved;
|
||||||
|
uint8 dma_status;
|
||||||
|
uint8 pio_mode;
|
||||||
|
uint8 dma_mode;
|
||||||
|
} ide_status;
|
||||||
|
|
||||||
#endif
|
#endif /* _IDE_DEVICE_INFOBLOCK_H_ */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
* Copyright 2004-2006, Axel Dörfler, [email protected]. All rights reserved.
|
||||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
@@ -26,6 +26,8 @@
|
|||||||
#include "ide_sim.h"
|
#include "ide_sim.h"
|
||||||
|
|
||||||
#include <bus/scsi/scsi_cmds.h>
|
#include <bus/scsi/scsi_cmds.h>
|
||||||
|
#include <safemode.h>
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -546,7 +548,8 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
{
|
{
|
||||||
device_node_handle parent;
|
device_node_handle parent;
|
||||||
ide_bus_info *bus;
|
ide_bus_info *bus;
|
||||||
int res;
|
bool dmaDisabled = false;
|
||||||
|
status_t status;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
@@ -586,13 +589,13 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
bus->timer.bus = bus;
|
bus->timer.bus = bus;
|
||||||
bus->synced_pc_list = NULL;
|
bus->synced_pc_list = NULL;
|
||||||
|
|
||||||
if ((res = scsi->alloc_dpc(&bus->irq_dpc)) < 0)
|
if ((status = scsi->alloc_dpc(&bus->irq_dpc)) < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
|
|
||||||
bus->active_device = NULL;
|
bus->active_device = NULL;
|
||||||
bus->sync_wait_sem = create_sem(0, "ide_sync_wait");
|
bus->sync_wait_sem = create_sem(0, "ide_sync_wait");
|
||||||
if (bus->sync_wait_sem < 0) {
|
if (bus->sync_wait_sem < 0) {
|
||||||
res = bus->sync_wait_sem;
|
status = bus->sync_wait_sem;
|
||||||
goto err2;
|
goto err2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,28 +603,41 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
|
|
||||||
bus->scan_device_sem = create_sem(0, "ide_scan_finished");
|
bus->scan_device_sem = create_sem(0, "ide_scan_finished");
|
||||||
if (bus->scan_device_sem < 0) {
|
if (bus->scan_device_sem < 0) {
|
||||||
res = bus->scan_device_sem;
|
status = bus->scan_device_sem;
|
||||||
goto err3;
|
goto err3;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = INIT_BEN(&bus->status_report_ben, "ide_status_report");
|
status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
|
||||||
if (res < 0)
|
if (status < B_OK)
|
||||||
goto err4;
|
goto err4;
|
||||||
|
|
||||||
|
{
|
||||||
|
// check if safemode settings disable DMA
|
||||||
|
void *settings = load_driver_settings(B_SAFEMODE_DRIVER_SETTINGS);
|
||||||
|
if (settings != NULL) {
|
||||||
|
dmaDisabled = get_driver_boolean_parameter(settings, B_SAFEMODE_DISABLE_IDE_DMA,
|
||||||
|
false, false);
|
||||||
|
unload_driver_settings(settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bus->first_device = NULL;
|
bus->first_device = NULL;
|
||||||
|
|
||||||
// read restrictions of controller
|
// read restrictions of controller
|
||||||
|
|
||||||
if (pnp->get_attr_uint8(node, IDE_CONTROLLER_MAX_DEVICES_ITEM,
|
if (pnp->get_attr_uint8(node, IDE_CONTROLLER_MAX_DEVICES_ITEM,
|
||||||
&bus->max_devices, true) != B_OK)
|
&bus->max_devices, true) != B_OK) {
|
||||||
// per default, 2 devices are supported per node
|
// per default, 2 devices are supported per node
|
||||||
bus->max_devices = 2;
|
bus->max_devices = 2;
|
||||||
|
}
|
||||||
|
|
||||||
bus->max_devices = min(bus->max_devices, 2);
|
bus->max_devices = min(bus->max_devices, 2);
|
||||||
|
|
||||||
if (pnp->get_attr_uint8(node, IDE_CONTROLLER_CAN_DMA_ITEM, &bus->can_DMA, true) != B_OK)
|
if (dmaDisabled
|
||||||
|
|| pnp->get_attr_uint8(node, IDE_CONTROLLER_CAN_DMA_ITEM, &bus->can_DMA, true) != B_OK) {
|
||||||
// per default, no dma support
|
// per default, no dma support
|
||||||
bus->can_DMA = false;
|
bus->can_DMA = false;
|
||||||
|
}
|
||||||
|
|
||||||
SHOW_FLOW(2, "can_dma: %d", bus->can_DMA);
|
SHOW_FLOW(2, "can_dma: %d", bus->can_DMA);
|
||||||
|
|
||||||
@@ -643,19 +659,17 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
|
|
||||||
parent = pnp->get_parent(node);
|
parent = pnp->get_parent(node);
|
||||||
|
|
||||||
res = pnp->init_driver(parent, bus,
|
status = pnp->init_driver(parent, bus, (driver_module_info **)&bus->controller,
|
||||||
(driver_module_info **)&bus->controller,
|
(void **)&bus->channel);
|
||||||
(void **)&bus->channel);
|
|
||||||
|
|
||||||
pnp->put_device_node(parent);
|
pnp->put_device_node(parent);
|
||||||
if (res != B_OK)
|
if (status != B_OK)
|
||||||
goto err5;
|
goto err5;
|
||||||
|
|
||||||
*cookie = bus;
|
*cookie = bus;
|
||||||
|
|
||||||
// detect devices
|
// detect devices
|
||||||
sim_scan_bus(bus);
|
sim_scan_bus(bus);
|
||||||
|
|
||||||
return B_OK;
|
return B_OK;
|
||||||
|
|
||||||
err5:
|
err5:
|
||||||
@@ -675,7 +689,7 @@ err:
|
|||||||
#endif
|
#endif
|
||||||
free(bus);
|
free(bus);
|
||||||
|
|
||||||
return res;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -766,6 +780,47 @@ ide_sim_get_restrictions(ide_bus_info *bus, uchar target_id,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
ide_sim_ioctl(ide_bus_info *bus, uint8 targetID, uint32 op, void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
ide_device_info *device = bus->devices[targetID];
|
||||||
|
|
||||||
|
// We currently only support IDE_GET_INFO_BLOCK
|
||||||
|
switch (op) {
|
||||||
|
case IDE_GET_INFO_BLOCK:
|
||||||
|
// we already have the info block, just copy it
|
||||||
|
memcpy(buffer, &device->infoblock,
|
||||||
|
min(sizeof(device->infoblock), length));
|
||||||
|
return B_OK;
|
||||||
|
|
||||||
|
case IDE_GET_STATUS:
|
||||||
|
{
|
||||||
|
// TODO: have our own structure and fill it with some useful stuff
|
||||||
|
ide_status status;
|
||||||
|
if (device->DMA_enabled)
|
||||||
|
status.dma_status = 1;
|
||||||
|
else if (device->DMA_supported) {
|
||||||
|
if (device->DMA_failures > 0)
|
||||||
|
status.dma_status = 6;
|
||||||
|
else if (device->bus->can_DMA)
|
||||||
|
status.dma_status = 2;
|
||||||
|
else
|
||||||
|
status.dma_status = 4;
|
||||||
|
} else
|
||||||
|
status.dma_status = 2;
|
||||||
|
|
||||||
|
status.pio_mode = 0;
|
||||||
|
status.dma_mode = 0;
|
||||||
|
|
||||||
|
memcpy(buffer, &status, min(sizeof(status), length));
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
std_ops(int32 op, ...)
|
std_ops(int32 op, ...)
|
||||||
{
|
{
|
||||||
@@ -801,7 +856,7 @@ scsi_sim_interface ide_sim_module = {
|
|||||||
(status_t (*)(void *) ) ide_sim_uninit_bus,
|
(status_t (*)(void *) ) ide_sim_uninit_bus,
|
||||||
(void (*)(device_node_handle, void *)) ide_sim_bus_removed
|
(void (*)(device_node_handle, void *)) ide_sim_bus_removed
|
||||||
},
|
},
|
||||||
|
|
||||||
(void (*)(scsi_sim_cookie, scsi_ccb *)) sim_scsi_io,
|
(void (*)(scsi_sim_cookie, scsi_ccb *)) sim_scsi_io,
|
||||||
(uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_abort,
|
(uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_abort,
|
||||||
(uchar (*)(scsi_sim_cookie, uchar, uchar)) sim_reset_device,
|
(uchar (*)(scsi_sim_cookie, uchar, uchar)) sim_reset_device,
|
||||||
@@ -812,5 +867,7 @@ scsi_sim_interface ide_sim_module = {
|
|||||||
(uchar (*)(scsi_sim_cookie)) sim_reset_bus,
|
(uchar (*)(scsi_sim_cookie)) sim_reset_bus,
|
||||||
|
|
||||||
(void (*)(scsi_sim_cookie, uchar,
|
(void (*)(scsi_sim_cookie, uchar,
|
||||||
bool*, bool *, uint32 *)) ide_sim_get_restrictions
|
bool*, bool *, uint32 *)) ide_sim_get_restrictions,
|
||||||
|
|
||||||
|
(status_t (*)(scsi_sim_cookie, uint8, uint32, void *, size_t))ide_sim_ioctl,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
|
||||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
|
*
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Part of Open SCSI bus manager
|
|
||||||
|
|
||||||
Device node layer.
|
Device node layer.
|
||||||
|
|
||||||
When a SCSI bus is registered, this layer scans for SCSI devices
|
When a SCSI bus is registered, this layer scans for SCSI devices
|
||||||
@@ -516,6 +516,18 @@ scsi_reset_device(scsi_device_info *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
scsi_ioctl(scsi_device_info *device, uint32 op, void *buffer, size_t length)
|
||||||
|
{
|
||||||
|
if (device->bus->interface->ioctl != NULL) {
|
||||||
|
return device->bus->interface->ioctl(device->bus->sim_cookie,
|
||||||
|
device->target_id, op, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
return B_BAD_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
std_ops(int32 op, ...)
|
std_ops(int32 op, ...)
|
||||||
{
|
{
|
||||||
@@ -559,5 +571,6 @@ scsi_device_interface scsi_device_module = {
|
|||||||
scsi_sync_io,
|
scsi_sync_io,
|
||||||
scsi_abort,
|
scsi_abort,
|
||||||
scsi_reset_device,
|
scsi_reset_device,
|
||||||
scsi_term_io
|
scsi_term_io,
|
||||||
|
scsi_ioctl,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
|
||||||
** Distributed under the terms of the Haiku License.
|
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||||
*/
|
*
|
||||||
|
* Distributed under the terms of the MIT License.
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Part of Open SCSI Disk Driver
|
Part of Open SCSI Disk Driver
|
||||||
|
|
||||||
Everything doing the real input/output stuff.
|
Everything doing the real input/output stuff.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -301,6 +302,11 @@ periph_ioctl(scsi_periph_handle_info *handle, int op, void *buffer, size_t lengt
|
|||||||
return raw_command(handle->device, buffer);
|
return raw_command(handle->device, buffer);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
if (handle->device->scsi->ioctl != NULL) {
|
||||||
|
return handle->device->scsi->ioctl(handle->device->scsi_device,
|
||||||
|
op, buffer, length);
|
||||||
|
}
|
||||||
|
|
||||||
SHOW_ERROR(4, "Unknown ioctl: %x", op);
|
SHOW_ERROR(4, "Unknown ioctl: %x", op);
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user