* 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:
Axel Dörfler 2006-04-01 11:53:07 +00:00
parent 262a2483e2
commit c9fc73fc8e
5 changed files with 131 additions and 40 deletions

View File

@ -1,13 +1,13 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
#ifndef __SCSI_BUSMANAGER_H__
#define __SCSI_BUSMANAGER_H__
#ifndef _SCSI_BUSMANAGER_H_
#define _SCSI_BUSMANAGER_H_
/*
Part of Open SCSI bus manager
SCSI bus manager interface
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);
// terminate request
uchar (*term_io)(scsi_ccb *ccb_to_terminate);
status_t (*ioctl)(scsi_device device, uint32 op, void *buffer, size_t length);
} scsi_device_interface;
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
@ -439,8 +441,8 @@ typedef struct scsi_sim_interface {
// get restrictions of one device
// (used for non-SCSI transport protocols and bug fixes)
void (*get_restrictions)(
scsi_sim_cookie cookie,
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
@ -450,7 +452,9 @@ typedef struct scsi_sim_interface {
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;
#endif /* __SCSI_BUSMANAGER_H__ */
#endif /* _SCSI_BUSMANAGER_H_ */

View File

@ -1,24 +1,29 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the OpenBeOS License.
*/
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* 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
IDE_CMD_IDENTIFY_PACKET_DEVICE
When a new entry is inserted, add its offset in hex
and its index in decimal as a remark. Without that, you
have a rough time when you messed up the offsets.
*/
#ifndef __IDE_DEVICE_INFOBLOCK_H__
#define __IDE_DEVICE_INFOBLOCK_H__
#include <lendian_bitfield.h>
#define IDE_GET_INFO_BLOCK 0x2710
#define IDE_GET_STATUS 0x2711
// must be 512 bytes!!!
typedef struct tagdevice_infoblock {
union { // 0 general configuration
@ -181,5 +186,11 @@ typedef struct tagdevice_infoblock {
uint16 dummy14[128]; // 100 (128)
} 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_ */

View File

@ -1,5 +1,5 @@
/*
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
@ -26,6 +26,8 @@
#include "ide_sim.h"
#include <bus/scsi/scsi_cmds.h>
#include <safemode.h>
#include <string.h>
#include <malloc.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;
ide_bus_info *bus;
int res;
bool dmaDisabled = false;
status_t status;
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->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;
bus->active_device = NULL;
bus->sync_wait_sem = create_sem(0, "ide_sync_wait");
if (bus->sync_wait_sem < 0) {
res = bus->sync_wait_sem;
status = bus->sync_wait_sem;
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");
if (bus->scan_device_sem < 0) {
res = bus->scan_device_sem;
status = bus->scan_device_sem;
goto err3;
}
res = INIT_BEN(&bus->status_report_ben, "ide_status_report");
if (res < 0)
status = INIT_BEN(&bus->status_report_ben, "ide_status_report");
if (status < B_OK)
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;
// read restrictions of controller
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
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
bus->can_DMA = false;
}
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);
res = pnp->init_driver(parent, bus,
(driver_module_info **)&bus->controller,
(void **)&bus->channel);
status = pnp->init_driver(parent, bus, (driver_module_info **)&bus->controller,
(void **)&bus->channel);
pnp->put_device_node(parent);
if (res != B_OK)
if (status != B_OK)
goto err5;
*cookie = bus;
// detect devices
sim_scan_bus(bus);
return B_OK;
err5:
@ -675,7 +689,7 @@ err:
#endif
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
std_ops(int32 op, ...)
{
@ -801,7 +856,7 @@ scsi_sim_interface ide_sim_module = {
(status_t (*)(void *) ) ide_sim_uninit_bus,
(void (*)(device_node_handle, void *)) ide_sim_bus_removed
},
(void (*)(scsi_sim_cookie, scsi_ccb *)) sim_scsi_io,
(uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_abort,
(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,
(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,
};

View File

@ -1,11 +1,11 @@
/*
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI bus manager
Device node layer.
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
std_ops(int32 op, ...)
{
@ -559,5 +571,6 @@ scsi_device_interface scsi_device_module = {
scsi_sync_io,
scsi_abort,
scsi_reset_device,
scsi_term_io
scsi_term_io,
scsi_ioctl,
};

View File

@ -1,11 +1,12 @@
/*
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
** Distributed under the terms of the Haiku License.
*/
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
*
* Distributed under the terms of the MIT License.
*/
/*
Part of Open SCSI Disk Driver
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);
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);
return B_BAD_VALUE;
}