* Ported scsi_cd, too, still untested.
* This should have been part of r26828, although it did not break the build :-) git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@26829 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_cd ;
|
SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_cd ;
|
||||||
|
|
||||||
UsePrivateHeaders drivers kernel ;
|
UsePrivateHeaders drivers kernel ;
|
||||||
|
SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ;
|
||||||
|
|
||||||
KernelAddon scsi_cd :
|
KernelAddon scsi_cd :
|
||||||
scsi_cd.cpp
|
scsi_cd.cpp
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
/*! Peripheral driver to handle CD-ROM drives. To be more
|
/*! Peripheral driver to handle CD-ROM drives. To be more
|
||||||
precisely, it supports CD-ROM and WORM drives (well -
|
precisely, it supports CD-ROM and WORM drives (well -
|
||||||
I've never _seen_ a WORM driver).
|
I've never _seen_ a WORM driver).
|
||||||
|
|
||||||
Much work is done by scsi_periph and block_io.
|
Much work is done by scsi_periph and block_io.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -29,49 +29,48 @@
|
|||||||
|
|
||||||
static scsi_periph_interface *sSCSIPeripheral;
|
static scsi_periph_interface *sSCSIPeripheral;
|
||||||
static device_manager_info *sDeviceManager;
|
static device_manager_info *sDeviceManager;
|
||||||
static block_io_for_driver_interface *sBlockIO;
|
|
||||||
|
|
||||||
|
|
||||||
#define SCSI_CD_STD_TIMEOUT 10
|
#define SCSI_CD_STD_TIMEOUT 10
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
update_capacity(cd_device_info *device)
|
update_capacity(cd_driver_info *info)
|
||||||
{
|
{
|
||||||
TRACE("update_capacity()\n");
|
TRACE("update_capacity()\n");
|
||||||
|
|
||||||
scsi_ccb *ccb = device->scsi->alloc_ccb(device->scsi_device);
|
scsi_ccb *ccb = info->scsi->alloc_ccb(info->scsi_device);
|
||||||
if (ccb == NULL)
|
if (ccb == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
status_t status = sSCSIPeripheral->check_capacity(
|
status_t status = sSCSIPeripheral->check_capacity(
|
||||||
device->scsi_periph_device, ccb);
|
info->scsi_periph_device, ccb);
|
||||||
|
|
||||||
device->scsi->free_ccb(ccb);
|
info->scsi->free_ccb(ccb);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_geometry(cd_handle_info *handle, device_geometry *geometry)
|
get_geometry(cd_handle *handle, device_geometry *geometry)
|
||||||
{
|
{
|
||||||
cd_device_info *device = handle->device;
|
cd_driver_info *info = handle->info;
|
||||||
|
|
||||||
status_t status = update_capacity(device);
|
status_t status = update_capacity(info);
|
||||||
|
|
||||||
// it seems that Be expects B_GET_GEOMETRY to always succeed unless
|
// it seems that Be expects B_GET_GEOMETRY to always succeed unless
|
||||||
// the medium has been changed; e.g. if we report B_DEV_NO_MEDIA, the
|
// the medium has been changed; e.g. if we report B_DEV_NO_MEDIA, the
|
||||||
// device is ignored by the CDPlayer and CDBurner
|
// info is ignored by the CDPlayer and CDBurner
|
||||||
if (status == B_DEV_MEDIA_CHANGED)
|
if (status == B_DEV_MEDIA_CHANGED)
|
||||||
return B_DEV_MEDIA_CHANGED;
|
return B_DEV_MEDIA_CHANGED;
|
||||||
|
|
||||||
geometry->bytes_per_sector = device->block_size;
|
geometry->bytes_per_sector = info->block_size;
|
||||||
geometry->sectors_per_track = 1;
|
geometry->sectors_per_track = 1;
|
||||||
geometry->cylinder_count = device->capacity;
|
geometry->cylinder_count = info->capacity;
|
||||||
geometry->head_count = 1;
|
geometry->head_count = 1;
|
||||||
geometry->device_type = device->device_type;
|
geometry->device_type = info->device_type;
|
||||||
geometry->removable = device->removable;
|
geometry->removable = info->removable;
|
||||||
|
|
||||||
// TBD: for all but CD-ROMs, read mode sense - medium type
|
// TBD: for all but CD-ROMs, read mode sense - medium type
|
||||||
// (bit 7 of block device specific parameter for Optical Memory Block Device)
|
// (bit 7 of block device specific parameter for Optical Memory Block Device)
|
||||||
@@ -79,7 +78,7 @@ get_geometry(cd_handle_info *handle, device_geometry *geometry)
|
|||||||
// (same for write-once block devices)
|
// (same for write-once block devices)
|
||||||
// (same for optical memory block devices)
|
// (same for optical memory block devices)
|
||||||
geometry->read_only = true;
|
geometry->read_only = true;
|
||||||
geometry->write_once = device->device_type == scsi_dev_WORM;
|
geometry->write_once = info->device_type == scsi_dev_WORM;
|
||||||
|
|
||||||
TRACE("scsi_disk: get_geometry(): %ld, %ld, %ld, %ld, %d, %d, %d, %d\n",
|
TRACE("scsi_disk: get_geometry(): %ld, %ld, %ld, %ld, %d, %d, %d, %d\n",
|
||||||
geometry->bytes_per_sector, geometry->sectors_per_track,
|
geometry->bytes_per_sector, geometry->sectors_per_track,
|
||||||
@@ -91,7 +90,7 @@ get_geometry(cd_handle_info *handle, device_geometry *geometry)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_toc(cd_device_info *device, scsi_toc *toc)
|
get_toc(cd_driver_info *info, scsi_toc *toc)
|
||||||
{
|
{
|
||||||
scsi_ccb *ccb;
|
scsi_ccb *ccb;
|
||||||
status_t res;
|
status_t res;
|
||||||
@@ -101,11 +100,11 @@ get_toc(cd_device_info *device, scsi_toc *toc)
|
|||||||
|
|
||||||
TRACE("get_toc()\n");
|
TRACE("get_toc()\n");
|
||||||
|
|
||||||
ccb = device->scsi->alloc_ccb(device->scsi_device);
|
ccb = info->scsi->alloc_ccb(info->scsi_device);
|
||||||
if (ccb == NULL)
|
if (ccb == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
// first read number of tracks only
|
// first read number of tracks only
|
||||||
ccb->flags = SCSI_DIR_IN;
|
ccb->flags = SCSI_DIR_IN;
|
||||||
|
|
||||||
cmd = (scsi_cmd_read_toc *)ccb->cdb;
|
cmd = (scsi_cmd_read_toc *)ccb->cdb;
|
||||||
@@ -126,16 +125,16 @@ get_toc(cd_device_info *device, scsi_toc *toc)
|
|||||||
ccb->sg_list = NULL;
|
ccb->sg_list = NULL;
|
||||||
ccb->data_length = sizeof(toc->toc_data);
|
ccb->data_length = sizeof(toc->toc_data);
|
||||||
|
|
||||||
res = sSCSIPeripheral->safe_exec(device->scsi_periph_device, ccb);
|
res = sSCSIPeripheral->safe_exec(info->scsi_periph_device, ccb);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
// then read all track infos
|
// then read all track infos
|
||||||
// (little hint: number of tracks is last - first + 1;
|
// (little hint: number of tracks is last - first + 1;
|
||||||
// but scsi_toc_toc has already one track, so we get
|
// but scsi_toc_toc has already one track, so we get
|
||||||
// last - first extra tracks; finally, we want the lead-out as
|
// last - first extra tracks; finally, we want the lead-out as
|
||||||
// well, so we add an extra track)
|
// well, so we add an extra track)
|
||||||
dataLength = (short_response->last - short_response->first + 1)
|
dataLength = (short_response->last - short_response->first + 1)
|
||||||
* sizeof(scsi_toc_track) + sizeof(scsi_toc_toc);
|
* sizeof(scsi_toc_track) + sizeof(scsi_toc_toc);
|
||||||
dataLength = min_c(dataLength, sizeof(toc->toc_data));
|
dataLength = min_c(dataLength, sizeof(toc->toc_data));
|
||||||
|
|
||||||
@@ -144,35 +143,35 @@ get_toc(cd_device_info *device, scsi_toc *toc)
|
|||||||
|
|
||||||
cmd->allocation_length = B_HOST_TO_BENDIAN_INT16(dataLength);
|
cmd->allocation_length = B_HOST_TO_BENDIAN_INT16(dataLength);
|
||||||
|
|
||||||
res = sSCSIPeripheral->safe_exec(device->scsi_periph_device, ccb);
|
res = sSCSIPeripheral->safe_exec(info->scsi_periph_device, ccb);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
device->scsi->free_ccb(ccb);
|
info->scsi->free_ccb(ccb);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
load_eject(cd_device_info *device, bool load)
|
load_eject(cd_driver_info *info, bool load)
|
||||||
{
|
{
|
||||||
TRACE("load_eject()\n");
|
TRACE("load_eject()\n");
|
||||||
|
|
||||||
scsi_ccb *ccb = device->scsi->alloc_ccb(device->scsi_device);
|
scsi_ccb *ccb = info->scsi->alloc_ccb(info->scsi_device);
|
||||||
if (ccb == NULL)
|
if (ccb == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
err_res result = sSCSIPeripheral->send_start_stop(
|
err_res result = sSCSIPeripheral->send_start_stop(
|
||||||
device->scsi_periph_device, ccb, load, true);
|
info->scsi_periph_device, ccb, load, true);
|
||||||
|
|
||||||
device->scsi->free_ccb(ccb);
|
info->scsi->free_ccb(ccb);
|
||||||
|
|
||||||
return result.error_code;
|
return result.error_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_position(cd_device_info *device, scsi_position *position)
|
get_position(cd_driver_info *info, scsi_position *position)
|
||||||
{
|
{
|
||||||
scsi_cmd_read_subchannel cmd;
|
scsi_cmd_read_subchannel cmd;
|
||||||
|
|
||||||
@@ -186,13 +185,13 @@ get_position(cd_device_info *device, scsi_position *position)
|
|||||||
cmd.track = 0;
|
cmd.track = 0;
|
||||||
cmd.allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_position));
|
cmd.allocation_length = B_HOST_TO_BENDIAN_INT16(sizeof(scsi_position));
|
||||||
|
|
||||||
return sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
return sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), position, sizeof(*position), SCSI_DIR_IN);
|
&cmd, sizeof(cmd), position, sizeof(*position), SCSI_DIR_IN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
|
get_set_volume(cd_driver_info *info, scsi_volume *volume, bool set)
|
||||||
{
|
{
|
||||||
scsi_cmd_mode_sense_6 cmd;
|
scsi_cmd_mode_sense_6 cmd;
|
||||||
scsi_mode_param_header_6 header;
|
scsi_mode_param_header_6 header;
|
||||||
@@ -212,7 +211,7 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
|
|||||||
|
|
||||||
memset(&header, -2, sizeof(header));
|
memset(&header, -2, sizeof(header));
|
||||||
|
|
||||||
res = sSCSIPeripheral->simple_exec(device->scsi_periph_device, &cmd,
|
res = sSCSIPeripheral->simple_exec(info->scsi_periph_device, &cmd,
|
||||||
sizeof(cmd), &header, sizeof(header), SCSI_DIR_IN);
|
sizeof(cmd), &header, sizeof(header), SCSI_DIR_IN);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
@@ -235,14 +234,14 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
|
|||||||
|
|
||||||
cmd.allocation_length = len;
|
cmd.allocation_length = len;
|
||||||
|
|
||||||
res = sSCSIPeripheral->simple_exec(device->scsi_periph_device, &cmd,
|
res = sSCSIPeripheral->simple_exec(info->scsi_periph_device, &cmd,
|
||||||
sizeof(cmd), buffer, len, SCSI_DIR_IN);
|
sizeof(cmd), buffer, len, SCSI_DIR_IN);
|
||||||
if (res != B_OK) {
|
if (res != B_OK) {
|
||||||
free(buffer);
|
free(buffer);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE(" mode_data_len=%d, block_desc_len=%d",
|
TRACE(" mode_data_len=%d, block_desc_len=%d",
|
||||||
((scsi_mode_param_header_6 *)buffer)->mode_data_length,
|
((scsi_mode_param_header_6 *)buffer)->mode_data_length,
|
||||||
((scsi_mode_param_header_6 *)buffer)->block_desc_length);
|
((scsi_mode_param_header_6 *)buffer)->block_desc_length);
|
||||||
|
|
||||||
@@ -295,7 +294,7 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
|
|||||||
cmd.param_list_length = sizeof(header) + header.block_desc_length
|
cmd.param_list_length = sizeof(header) + header.block_desc_length
|
||||||
+ sizeof(*page);
|
+ sizeof(*page);
|
||||||
|
|
||||||
res = sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
res = sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), buffer, len, SCSI_DIR_OUT);
|
&cmd, sizeof(cmd), buffer, len, SCSI_DIR_OUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -306,7 +305,7 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set)
|
|||||||
|
|
||||||
/*! Play audio cd; time is in MSF */
|
/*! Play audio cd; time is in MSF */
|
||||||
static status_t
|
static status_t
|
||||||
play_msf(cd_device_info *device, const scsi_play_position *position)
|
play_msf(cd_driver_info *info, const scsi_play_position *position)
|
||||||
{
|
{
|
||||||
scsi_cmd_play_msf cmd;
|
scsi_cmd_play_msf cmd;
|
||||||
|
|
||||||
@@ -324,14 +323,14 @@ play_msf(cd_device_info *device, const scsi_play_position *position)
|
|||||||
cmd.end_second = position->end_s;
|
cmd.end_second = position->end_s;
|
||||||
cmd.end_frame = position->end_f;
|
cmd.end_frame = position->end_f;
|
||||||
|
|
||||||
return sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
return sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), NULL, 0, 0);
|
&cmd, sizeof(cmd), NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Play audio cd; time is in track/index */
|
/*! Play audio cd; time is in track/index */
|
||||||
static status_t
|
static status_t
|
||||||
play_track_index(cd_device_info *device, const scsi_play_track *buf)
|
play_track_index(cd_driver_info *info, const scsi_play_track *buf)
|
||||||
{
|
{
|
||||||
scsi_toc generic_toc;
|
scsi_toc generic_toc;
|
||||||
scsi_toc_toc *toc;
|
scsi_toc_toc *toc;
|
||||||
@@ -343,7 +342,7 @@ play_track_index(cd_device_info *device, const scsi_play_track *buf)
|
|||||||
|
|
||||||
// the corresponding command PLAY AUDIO TRACK/INDEX is deprecated,
|
// the corresponding command PLAY AUDIO TRACK/INDEX is deprecated,
|
||||||
// so we have to simulate it by converting track to time via TOC
|
// so we have to simulate it by converting track to time via TOC
|
||||||
res = get_toc(device, &generic_toc);
|
res = get_toc(info, &generic_toc);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
@@ -357,7 +356,7 @@ play_track_index(cd_device_info *device, const scsi_play_track *buf)
|
|||||||
|
|
||||||
if (end_track > toc->last_track)
|
if (end_track > toc->last_track)
|
||||||
end_track = toc->last_track + 1;
|
end_track = toc->last_track + 1;
|
||||||
|
|
||||||
if (end_track < toc->last_track + 1)
|
if (end_track < toc->last_track + 1)
|
||||||
++end_track;
|
++end_track;
|
||||||
|
|
||||||
@@ -375,12 +374,12 @@ play_track_index(cd_device_info *device, const scsi_play_track *buf)
|
|||||||
position.end_s = toc->tracks[end_track].start.time.second;
|
position.end_s = toc->tracks[end_track].start.time.second;
|
||||||
position.end_f = toc->tracks[end_track].start.time.frame;
|
position.end_f = toc->tracks[end_track].start.time.frame;
|
||||||
|
|
||||||
return play_msf(device, &position);
|
return play_msf(info, &position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
stop_audio(cd_device_info *device)
|
stop_audio(cd_driver_info *info)
|
||||||
{
|
{
|
||||||
scsi_cmd_stop_play cmd;
|
scsi_cmd_stop_play cmd;
|
||||||
|
|
||||||
@@ -389,13 +388,13 @@ stop_audio(cd_device_info *device)
|
|||||||
memset( &cmd, 0, sizeof( cmd ));
|
memset( &cmd, 0, sizeof( cmd ));
|
||||||
cmd.opcode = SCSI_OP_STOP_PLAY;
|
cmd.opcode = SCSI_OP_STOP_PLAY;
|
||||||
|
|
||||||
return sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
return sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), NULL, 0, 0);
|
&cmd, sizeof(cmd), NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
pause_resume(cd_device_info *device, bool resume)
|
pause_resume(cd_driver_info *info, bool resume)
|
||||||
{
|
{
|
||||||
scsi_cmd_pause_resume cmd;
|
scsi_cmd_pause_resume cmd;
|
||||||
|
|
||||||
@@ -405,13 +404,13 @@ pause_resume(cd_device_info *device, bool resume)
|
|||||||
cmd.opcode = SCSI_OP_PAUSE_RESUME;
|
cmd.opcode = SCSI_OP_PAUSE_RESUME;
|
||||||
cmd.resume = resume;
|
cmd.resume = resume;
|
||||||
|
|
||||||
return sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
return sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), NULL, 0, 0);
|
&cmd, sizeof(cmd), NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
scan(cd_device_info *device, const scsi_scan *buf)
|
scan(cd_driver_info *info, const scsi_scan *buf)
|
||||||
{
|
{
|
||||||
scsi_cmd_scan cmd;
|
scsi_cmd_scan cmd;
|
||||||
scsi_position curPos;
|
scsi_position curPos;
|
||||||
@@ -419,11 +418,11 @@ scan(cd_device_info *device, const scsi_scan *buf)
|
|||||||
|
|
||||||
TRACE("scan(direction =% d)\n", buf->direction);
|
TRACE("scan(direction =% d)\n", buf->direction);
|
||||||
|
|
||||||
status_t res = get_position(device, &curPos);
|
status_t res = get_position(info, &curPos);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
cdPos = (scsi_cd_current_position *)((char *)&curPos
|
cdPos = (scsi_cd_current_position *)((char *)&curPos
|
||||||
+ sizeof(scsi_subchannel_data_header));
|
+ sizeof(scsi_subchannel_data_header));
|
||||||
|
|
||||||
if (buf->direction == 0) {
|
if (buf->direction == 0) {
|
||||||
@@ -437,7 +436,7 @@ scan(cd_device_info *device, const scsi_scan *buf)
|
|||||||
playPos.end_s = 59;
|
playPos.end_s = 59;
|
||||||
playPos.end_f = 24;
|
playPos.end_f = 24;
|
||||||
|
|
||||||
return play_msf(device, &playPos);
|
return play_msf(info, &playPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&cmd, 0, sizeof(cmd));
|
memset(&cmd, 0, sizeof(cmd));
|
||||||
@@ -450,32 +449,32 @@ scan(cd_device_info *device, const scsi_scan *buf)
|
|||||||
/*
|
/*
|
||||||
tmp = (uint8 *)&cmd;
|
tmp = (uint8 *)&cmd;
|
||||||
dprintf("%d %d %d %d %d %d %d %d %d %d %d %d\n",
|
dprintf("%d %d %d %d %d %d %d %d %d %d %d %d\n",
|
||||||
tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5],
|
tmp[0], tmp[1], tmp[2], tmp[3], tmp[4], tmp[5],
|
||||||
tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11]);
|
tmp[6], tmp[7], tmp[8], tmp[9], tmp[10], tmp[11]);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return sSCSIPeripheral->simple_exec(device->scsi_periph_device,
|
return sSCSIPeripheral->simple_exec(info->scsi_periph_device,
|
||||||
&cmd, sizeof(cmd), NULL, 0, 0);
|
&cmd, sizeof(cmd), NULL, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
read_cd(cd_device_info *device, const scsi_read_cd *readCD)
|
read_cd(cd_driver_info *info, const scsi_read_cd *readCD)
|
||||||
{
|
{
|
||||||
scsi_cmd_read_cd *cmd;
|
scsi_cmd_read_cd *cmd;
|
||||||
uint32 lba, length;
|
uint32 lba, length;
|
||||||
scsi_ccb *ccb;
|
scsi_ccb *ccb;
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
// we use safe_exec instead of simple_exec as we want to set
|
// we use safe_exec instead of simple_exec as we want to set
|
||||||
// the sorting order manually (only makes much sense if you grab
|
// the sorting order manually (only makes much sense if you grab
|
||||||
// multiple tracks at once, but we are prepared)
|
// multiple tracks at once, but we are prepared)
|
||||||
ccb = device->scsi->alloc_ccb(device->scsi_device);
|
ccb = info->scsi->alloc_ccb(info->scsi_device);
|
||||||
|
|
||||||
if (ccb == NULL)
|
if (ccb == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
cmd = (scsi_cmd_read_cd *)ccb->cdb;
|
cmd = (scsi_cmd_read_cd *)ccb->cdb;
|
||||||
memset(cmd, 0, sizeof(*cmd));
|
memset(cmd, 0, sizeof(*cmd));
|
||||||
cmd->opcode = SCSI_OP_READ_CD;
|
cmd->opcode = SCSI_OP_READ_CD;
|
||||||
cmd->sector_type = 1;
|
cmd->sector_type = 1;
|
||||||
@@ -509,9 +508,9 @@ read_cd(cd_device_info *device, const scsi_read_cd *readCD)
|
|||||||
ccb->sg_list = NULL;
|
ccb->sg_list = NULL;
|
||||||
ccb->data_length = readCD->buffer_length;
|
ccb->data_length = readCD->buffer_length;
|
||||||
|
|
||||||
res = sSCSIPeripheral->safe_exec(device->scsi_periph_device, ccb);
|
res = sSCSIPeripheral->safe_exec(info->scsi_periph_device, ccb);
|
||||||
|
|
||||||
device->scsi->free_ccb(ccb);
|
info->scsi->free_ccb(ccb);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -526,56 +525,85 @@ log2(uint32 x)
|
|||||||
if (x == (1UL << y))
|
if (x == (1UL << y))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark - block_io API
|
static status_t
|
||||||
|
do_io(void* cookie, IOOperation* operation)
|
||||||
|
{
|
||||||
|
cd_driver_info* info = (cd_driver_info*)cookie;
|
||||||
|
|
||||||
|
// TODO: this can go away as soon as we pushed the IOOperation to the upper
|
||||||
|
// layers - we can then set scsi_periph::io() as callback for the scheduler
|
||||||
|
size_t bytesTransferred;
|
||||||
|
status_t status = sSCSIPeripheral->io(info->scsi_periph_device, operation,
|
||||||
|
&bytesTransferred);
|
||||||
|
|
||||||
|
info->io_scheduler->OperationCompleted(operation, status, bytesTransferred);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// #pragma mark - device module API
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
cd_init_device(void* _info, void** _cookie)
|
||||||
|
{
|
||||||
|
cd_driver_info* info = (cd_driver_info*)_info;
|
||||||
|
|
||||||
|
// and get (initial) capacity
|
||||||
|
scsi_ccb *request = info->scsi->alloc_ccb(info->scsi_device);
|
||||||
|
if (request == NULL)
|
||||||
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
|
sSCSIPeripheral->check_capacity(info->scsi_periph_device, request);
|
||||||
|
info->scsi->free_ccb(request);
|
||||||
|
|
||||||
|
*_cookie = info;
|
||||||
|
return B_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cd_set_device(cd_device_info *info, block_io_device device)
|
cd_uninit_device(void* _cookie)
|
||||||
{
|
{
|
||||||
info->block_io_device = device;
|
cd_driver_info* info = (cd_driver_info*)_cookie;
|
||||||
|
|
||||||
|
delete info->io_scheduler;
|
||||||
|
delete info->dma_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_open(cd_device_info *device, cd_handle_info **_cookie)
|
cd_open(void* _info, const char* path, int openMode, void** _cookie)
|
||||||
{
|
{
|
||||||
TRACE("open()\n");
|
cd_driver_info* info = (cd_driver_info*)_info;
|
||||||
|
|
||||||
cd_handle_info *handle = (cd_handle_info *)malloc(sizeof(*handle));
|
cd_handle* handle = (cd_handle*)malloc(sizeof(cd_handle));
|
||||||
if (handle == NULL)
|
if (handle == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
handle->device = device;
|
handle->info = info;
|
||||||
|
|
||||||
status_t status = sSCSIPeripheral->handle_open(device->scsi_periph_device,
|
status_t status = sSCSIPeripheral->handle_open(info->scsi_periph_device,
|
||||||
(periph_handle_cookie)handle, &handle->scsi_periph_handle);
|
(periph_handle_cookie)handle, &handle->scsi_periph_handle);
|
||||||
if (status < B_OK) {
|
if (status < B_OK) {
|
||||||
free(handle);
|
free(handle);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (device->block_size == 0 || device->capacity == 0) {
|
|
||||||
scsi_ccb *request = device->scsi->alloc_ccb(device->scsi_device);
|
|
||||||
if (request != NULL) {
|
|
||||||
// don't care if no test was possible
|
|
||||||
sSCSIPeripheral->check_capacity(device->scsi_periph_device, request);
|
|
||||||
device->scsi->free_ccb(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*_cookie = handle;
|
*_cookie = handle;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_close(cd_handle_info *handle)
|
cd_close(void* cookie)
|
||||||
{
|
{
|
||||||
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
TRACE("close()\n");
|
TRACE("close()\n");
|
||||||
|
|
||||||
sSCSIPeripheral->handle_close(handle->scsi_periph_handle);
|
sSCSIPeripheral->handle_close(handle->scsi_periph_handle);
|
||||||
@@ -584,8 +612,9 @@ cd_close(cd_handle_info *handle)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_free(cd_handle_info *handle)
|
cd_free(void* cookie)
|
||||||
{
|
{
|
||||||
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
TRACE("free()\n");
|
TRACE("free()\n");
|
||||||
|
|
||||||
sSCSIPeripheral->handle_free(handle->scsi_periph_handle);
|
sSCSIPeripheral->handle_free(handle->scsi_periph_handle);
|
||||||
@@ -595,38 +624,80 @@ cd_free(cd_handle_info *handle)
|
|||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_read(cd_handle_info *handle, const phys_vecs *vecs, off_t pos,
|
cd_read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
||||||
size_t num_blocks, uint32 block_size, size_t *bytes_transferred)
|
|
||||||
{
|
{
|
||||||
return sSCSIPeripheral->read(handle->scsi_periph_handle, vecs, pos,
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
num_blocks, block_size, bytes_transferred, 10);
|
size_t length = *_length;
|
||||||
|
|
||||||
|
IORequest request;
|
||||||
|
status_t status = request.Init(pos, buffer, length, false, 0);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = handle->info->io_scheduler->ScheduleRequest(&request);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = request.Wait(0, 0);
|
||||||
|
if (status == B_OK)
|
||||||
|
*_length = length;
|
||||||
|
else
|
||||||
|
dprintf("cd_read(): request.Wait() returned: %s\n", strerror(status));
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_write(cd_handle_info *handle, const phys_vecs *vecs, off_t pos,
|
cd_write(void* cookie, off_t pos, const void* buffer, size_t* _length)
|
||||||
size_t num_blocks, uint32 block_size, size_t *bytes_transferred)
|
|
||||||
{
|
{
|
||||||
return sSCSIPeripheral->write(handle->scsi_periph_handle, vecs, pos,
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
num_blocks, block_size, bytes_transferred, 10);
|
size_t length = *_length;
|
||||||
|
|
||||||
|
IORequest request;
|
||||||
|
status_t status = request.Init(pos, (void*)buffer, length, true, 0);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = handle->info->io_scheduler->ScheduleRequest(&request);
|
||||||
|
if (status != B_OK)
|
||||||
|
return status;
|
||||||
|
|
||||||
|
status = request.Wait(0, 0);
|
||||||
|
if (status == B_OK)
|
||||||
|
*_length = length;
|
||||||
|
else
|
||||||
|
dprintf("cd_write(): request.Wait() returned: %s\n", strerror(status));
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
cd_io(void *cookie, io_request *request)
|
||||||
{
|
{
|
||||||
cd_device_info *device = handle->device;
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
|
|
||||||
|
return handle->info->io_scheduler->ScheduleRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static status_t
|
||||||
|
cd_ioctl(void* cookie, uint32 op, void* buffer, size_t length)
|
||||||
|
{
|
||||||
|
cd_handle* handle = (cd_handle*)cookie;
|
||||||
|
cd_driver_info *info = handle->info;
|
||||||
|
|
||||||
TRACE("ioctl(op = %d)\n", op);
|
TRACE("ioctl(op = %d)\n", op);
|
||||||
|
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case B_GET_DEVICE_SIZE:
|
case B_GET_DEVICE_SIZE:
|
||||||
{
|
{
|
||||||
status_t status = update_capacity(device);
|
status_t status = update_capacity(info);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
size_t size = device->capacity * device->block_size;
|
size_t size = info->capacity * info->block_size;
|
||||||
return user_memcpy(buffer, &size, sizeof(size_t));
|
return user_memcpy(buffer, &size, sizeof(size_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,7 +710,7 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
status_t status = get_geometry(handle, &geometry);
|
status_t status = get_geometry(handle, &geometry);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
|
return user_memcpy(buffer, &geometry, sizeof(device_geometry));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -649,22 +720,22 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
|
|
||||||
case B_SCSI_GET_TOC:
|
case B_SCSI_GET_TOC:
|
||||||
// TODO: we pass a user buffer here!
|
// TODO: we pass a user buffer here!
|
||||||
return get_toc(device, (scsi_toc *)buffer);
|
return get_toc(info, (scsi_toc *)buffer);
|
||||||
|
|
||||||
case B_EJECT_DEVICE:
|
case B_EJECT_DEVICE:
|
||||||
case B_SCSI_EJECT:
|
case B_SCSI_EJECT:
|
||||||
return load_eject(device, false);
|
return load_eject(info, false);
|
||||||
|
|
||||||
case B_LOAD_MEDIA:
|
case B_LOAD_MEDIA:
|
||||||
return load_eject(device, true);
|
return load_eject(info, true);
|
||||||
|
|
||||||
case B_SCSI_GET_POSITION:
|
case B_SCSI_GET_POSITION:
|
||||||
{
|
{
|
||||||
if (buffer == NULL)
|
if (buffer == NULL)
|
||||||
return B_BAD_VALUE;
|
return B_BAD_VALUE;
|
||||||
|
|
||||||
scsi_position position;
|
scsi_position position;
|
||||||
status_t status = get_position(device, &position);
|
status_t status = get_position(info, &position);
|
||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
@@ -673,10 +744,10 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
|
|
||||||
case B_SCSI_GET_VOLUME:
|
case B_SCSI_GET_VOLUME:
|
||||||
// TODO: we pass a user buffer here!
|
// TODO: we pass a user buffer here!
|
||||||
return get_set_volume(device, (scsi_volume *)buffer, false);
|
return get_set_volume(info, (scsi_volume *)buffer, false);
|
||||||
case B_SCSI_SET_VOLUME:
|
case B_SCSI_SET_VOLUME:
|
||||||
// TODO: we pass a user buffer here!
|
// TODO: we pass a user buffer here!
|
||||||
return get_set_volume(device, (scsi_volume *)buffer, true);
|
return get_set_volume(info, (scsi_volume *)buffer, true);
|
||||||
|
|
||||||
case B_SCSI_PLAY_TRACK:
|
case B_SCSI_PLAY_TRACK:
|
||||||
{
|
{
|
||||||
@@ -684,7 +755,7 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
if (user_memcpy(&track, buffer, sizeof(scsi_play_track)) != B_OK)
|
if (user_memcpy(&track, buffer, sizeof(scsi_play_track)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return play_track_index(device, &track);
|
return play_track_index(info, &track);
|
||||||
}
|
}
|
||||||
case B_SCSI_PLAY_POSITION:
|
case B_SCSI_PLAY_POSITION:
|
||||||
{
|
{
|
||||||
@@ -693,27 +764,27 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
!= B_OK)
|
!= B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return play_msf(device, &position);
|
return play_msf(info, &position);
|
||||||
}
|
}
|
||||||
|
|
||||||
case B_SCSI_STOP_AUDIO:
|
case B_SCSI_STOP_AUDIO:
|
||||||
return stop_audio(device);
|
return stop_audio(info);
|
||||||
case B_SCSI_PAUSE_AUDIO:
|
case B_SCSI_PAUSE_AUDIO:
|
||||||
return pause_resume(device, false);
|
return pause_resume(info, false);
|
||||||
case B_SCSI_RESUME_AUDIO:
|
case B_SCSI_RESUME_AUDIO:
|
||||||
return pause_resume(device, true);
|
return pause_resume(info, true);
|
||||||
|
|
||||||
case B_SCSI_SCAN:
|
case B_SCSI_SCAN:
|
||||||
{
|
{
|
||||||
scsi_scan scanBuffer;
|
scsi_scan scanBuffer;
|
||||||
if (user_memcpy(&scanBuffer, buffer, sizeof(scsi_scan)) != B_OK)
|
if (user_memcpy(&scanBuffer, buffer, sizeof(scsi_scan)) != B_OK)
|
||||||
return B_BAD_ADDRESS;
|
return B_BAD_ADDRESS;
|
||||||
|
|
||||||
return scan(device, &scanBuffer);
|
return scan(info, &scanBuffer);
|
||||||
}
|
}
|
||||||
case B_SCSI_READ_CD:
|
case B_SCSI_READ_CD:
|
||||||
// TODO: we pass a user buffer here!
|
// TODO: we pass a user buffer here!
|
||||||
return read_cd(device, (scsi_read_cd *)buffer);
|
return read_cd(info, (scsi_read_cd *)buffer);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return sSCSIPeripheral->ioctl(handle->scsi_periph_handle, op,
|
return sSCSIPeripheral->ioctl(handle->scsi_periph_handle, op,
|
||||||
@@ -726,10 +797,10 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length)
|
|||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cd_set_capacity(cd_device_info *device, uint64 capacity, uint32 blockSize)
|
cd_set_capacity(cd_driver_info *info, uint64 capacity, uint32 blockSize)
|
||||||
{
|
{
|
||||||
TRACE("das_set_capacity(device = %p, capacity = %Ld, blockSize = %ld)\n",
|
TRACE("cd_set_capacity(info = %p, capacity = %Ld, blockSize = %ld)\n",
|
||||||
device, capacity, blockSize);
|
info, capacity, blockSize);
|
||||||
|
|
||||||
// get log2, if possible
|
// get log2, if possible
|
||||||
uint32 blockShift = log2(blockSize);
|
uint32 blockShift = log2(blockSize);
|
||||||
@@ -737,20 +808,41 @@ cd_set_capacity(cd_device_info *device, uint64 capacity, uint32 blockSize)
|
|||||||
if ((1UL << blockShift) != blockSize)
|
if ((1UL << blockShift) != blockSize)
|
||||||
blockShift = 0;
|
blockShift = 0;
|
||||||
|
|
||||||
device->capacity = capacity;
|
info->capacity = capacity;
|
||||||
device->block_size = blockSize;
|
|
||||||
|
|
||||||
sBlockIO->set_media_params(device->block_io_device, blockSize,
|
if (info->block_size != blockSize) {
|
||||||
blockShift, capacity);
|
if (info->block_size != 0) {
|
||||||
|
dprintf("old %ld, new %ld\n", info->block_size, blockSize);
|
||||||
|
panic("updating DMAResource not yet implemented...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: we need to replace the DMAResource in our IOScheduler
|
||||||
|
status_t status = info->dma_resource->Init(info->node, blockSize);
|
||||||
|
if (status != B_OK)
|
||||||
|
panic("initializing DMAResource failed: %s", strerror(status));
|
||||||
|
|
||||||
|
info->io_scheduler = new(std::nothrow) IOScheduler(info->dma_resource);
|
||||||
|
if (info->io_scheduler == NULL)
|
||||||
|
panic("allocating IOScheduler failed.");
|
||||||
|
|
||||||
|
// TODO: use whole device name here
|
||||||
|
status = info->io_scheduler->Init("scsi");
|
||||||
|
if (status != B_OK)
|
||||||
|
panic("initializing IOScheduler failed: %s", strerror(status));
|
||||||
|
|
||||||
|
info->io_scheduler->SetCallback(do_io, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
info->block_size = blockSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cd_media_changed(cd_device_info *device, scsi_ccb *request)
|
cd_media_changed(cd_driver_info *info, scsi_ccb *request)
|
||||||
{
|
{
|
||||||
// do a capacity check
|
// do a capacity check
|
||||||
// TBD: is this a good idea (e.g. if this is an empty CD)?
|
// TBD: is this a good idea (e.g. if this is an empty CD)?
|
||||||
sSCSIPeripheral->check_capacity(device->scsi_periph_device, request);
|
sSCSIPeripheral->check_capacity(info->scsi_periph_device, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -822,15 +914,15 @@ cd_register_device(device_node *node)
|
|||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
return sDeviceManager->register_node(node, SCSI_CD_MODULE_NAME, attrs,
|
return sDeviceManager->register_node(node, SCSI_CD_DRIVER_MODULE_NAME,
|
||||||
NULL, NULL);
|
attrs, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_init_driver(device_node *node, void **cookie)
|
cd_init_driver(device_node *node, void **cookie)
|
||||||
{
|
{
|
||||||
cd_device_info *device;
|
cd_driver_info *info;
|
||||||
status_t status;
|
status_t status;
|
||||||
uint8 removable;
|
uint8 removable;
|
||||||
|
|
||||||
@@ -841,36 +933,36 @@ cd_init_driver(device_node *node, void **cookie)
|
|||||||
if (status != B_OK)
|
if (status != B_OK)
|
||||||
return status;
|
return status;
|
||||||
|
|
||||||
device = (cd_device_info *)malloc(sizeof(*device));
|
info = (cd_driver_info *)malloc(sizeof(*info));
|
||||||
if (device == NULL)
|
if (info == NULL)
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
|
|
||||||
memset(device, 0, sizeof(*device));
|
memset(info, 0, sizeof(*info));
|
||||||
|
|
||||||
device->node = node;
|
info->node = node;
|
||||||
device->removable = removable;
|
info->removable = removable;
|
||||||
|
|
||||||
// set capacity to zero, so it get checked on first opened handle
|
// set capacity to zero, so it get checked on first opened handle
|
||||||
device->capacity = 0;
|
info->capacity = 0;
|
||||||
device->block_size = 0;
|
info->block_size = 0;
|
||||||
|
|
||||||
sDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM,
|
sDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM,
|
||||||
&device->device_type, true);
|
&info->device_type, true);
|
||||||
|
|
||||||
device_node *parent = sDeviceManager->get_parent_node(node);
|
device_node *parent = sDeviceManager->get_parent_node(node);
|
||||||
sDeviceManager->get_driver(parent, (driver_module_info **)&device->scsi,
|
sDeviceManager->get_driver(parent, (driver_module_info **)&info->scsi,
|
||||||
(void **)&device->scsi_device);
|
(void **)&info->scsi_device);
|
||||||
sDeviceManager->put_node(parent);
|
sDeviceManager->put_node(parent);
|
||||||
|
|
||||||
status = sSCSIPeripheral->register_device((periph_device_cookie)device,
|
status = sSCSIPeripheral->register_device((periph_device_cookie)info,
|
||||||
&callbacks, device->scsi_device, device->scsi, device->node,
|
&callbacks, info->scsi_device, info->scsi, info->node,
|
||||||
device->removable, &device->scsi_periph_device);
|
info->removable, 10, &info->scsi_periph_device);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
free(device);
|
free(info);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
*cookie = device;
|
*cookie = info;
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -878,26 +970,26 @@ cd_init_driver(device_node *node, void **cookie)
|
|||||||
static void
|
static void
|
||||||
cd_uninit_driver(void *_cookie)
|
cd_uninit_driver(void *_cookie)
|
||||||
{
|
{
|
||||||
cd_device_info *device = (cd_device_info *)_cookie;
|
cd_driver_info *info = (cd_driver_info *)_cookie;
|
||||||
|
|
||||||
sSCSIPeripheral->unregister_device(device->scsi_periph_device);
|
sSCSIPeripheral->unregister_device(info->scsi_periph_device);
|
||||||
free(device);
|
free(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static status_t
|
static status_t
|
||||||
cd_register_child_devices(void *_cookie)
|
cd_register_child_devices(void *_cookie)
|
||||||
{
|
{
|
||||||
cd_device_info *device = (cd_device_info *)_cookie;
|
cd_driver_info *info = (cd_driver_info *)_cookie;
|
||||||
status_t status;
|
status_t status;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
name = sSCSIPeripheral->compose_device_name(device->node, "disk/scsi");
|
name = sSCSIPeripheral->compose_device_name(info->node, "disk/scsi");
|
||||||
if (name == NULL)
|
if (name == NULL)
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
|
|
||||||
status = sDeviceManager->publish_device(device->node, name,
|
status = sDeviceManager->publish_device(info->node, name,
|
||||||
B_BLOCK_IO_DEVICE_MODULE_NAME);
|
SCSI_CD_DEVICE_MODULE_NAME);
|
||||||
|
|
||||||
free(name);
|
free(name);
|
||||||
return status;
|
return status;
|
||||||
@@ -905,43 +997,52 @@ cd_register_child_devices(void *_cookie)
|
|||||||
|
|
||||||
|
|
||||||
module_dependency module_dependencies[] = {
|
module_dependency module_dependencies[] = {
|
||||||
{SCSI_PERIPH_MODULE_NAME, (module_info **)&sSCSIPeripheral},
|
{SCSI_PERIPH_MODULE_NAME, (module_info**)&sSCSIPeripheral},
|
||||||
{B_BLOCK_IO_FOR_DRIVER_MODULE_NAME, (module_info **)&sBlockIO},
|
{B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager},
|
||||||
{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&sDeviceManager},
|
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
block_device_interface sSCSICDModule = {
|
struct device_module_info sSCSICDDevice = {
|
||||||
{
|
{
|
||||||
{
|
SCSI_CD_DEVICE_MODULE_NAME,
|
||||||
SCSI_CD_MODULE_NAME,
|
0,
|
||||||
0,
|
NULL
|
||||||
NULL
|
|
||||||
},
|
|
||||||
|
|
||||||
cd_supports_device,
|
|
||||||
cd_register_device,
|
|
||||||
cd_init_driver,
|
|
||||||
cd_uninit_driver,
|
|
||||||
cd_register_child_devices,
|
|
||||||
NULL, // rescan
|
|
||||||
NULL, // removed
|
|
||||||
},
|
},
|
||||||
|
|
||||||
(void (*)(block_device_cookie *, block_io_device)) &cd_set_device,
|
cd_init_device,
|
||||||
(status_t (*)(block_device_cookie *, block_device_handle_cookie **))&cd_open,
|
cd_uninit_device,
|
||||||
(status_t (*)(block_device_handle_cookie *)) &cd_close,
|
NULL, // remove,
|
||||||
(status_t (*)(block_device_handle_cookie *)) &cd_free,
|
|
||||||
|
|
||||||
(status_t (*)(block_device_handle_cookie *, const phys_vecs *,
|
cd_open,
|
||||||
off_t, size_t, uint32, size_t *)) &cd_read,
|
cd_close,
|
||||||
(status_t (*)(block_device_handle_cookie *, const phys_vecs *,
|
cd_free,
|
||||||
off_t, size_t, uint32, size_t *)) &cd_write,
|
cd_read,
|
||||||
|
cd_write,
|
||||||
|
cd_io,
|
||||||
|
cd_ioctl,
|
||||||
|
|
||||||
(status_t (*)(block_device_handle_cookie *, int, void *, size_t))&cd_ioctl,
|
NULL, // select
|
||||||
|
NULL, // deselect
|
||||||
};
|
};
|
||||||
|
|
||||||
module_info *modules[] = {
|
struct driver_module_info sSCSICDDriver = {
|
||||||
(module_info *)&sSCSICDModule,
|
{
|
||||||
|
SCSI_CD_DRIVER_MODULE_NAME,
|
||||||
|
0,
|
||||||
|
NULL
|
||||||
|
},
|
||||||
|
|
||||||
|
cd_supports_device,
|
||||||
|
cd_register_device,
|
||||||
|
cd_init_driver,
|
||||||
|
cd_uninit_driver,
|
||||||
|
cd_register_child_devices,
|
||||||
|
NULL, // rescan
|
||||||
|
NULL, // removed
|
||||||
|
};
|
||||||
|
|
||||||
|
module_info* modules[] = {
|
||||||
|
(module_info*)&sSCSICDDriver,
|
||||||
|
(module_info*)&sSCSICDDevice,
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,28 +12,33 @@
|
|||||||
#include <scsi_periph.h>
|
#include <scsi_periph.h>
|
||||||
#include <scsi.h>
|
#include <scsi.h>
|
||||||
|
|
||||||
|
#include "dma_resources.h"
|
||||||
#define SCSI_CD_MODULE_NAME "drivers/disk/scsi/scsi_cd/driver_v1"
|
#include "io_requests.h"
|
||||||
|
#include "IOScheduler.h"
|
||||||
|
|
||||||
|
|
||||||
// must start as block_device_cookie
|
#define SCSI_CD_DRIVER_MODULE_NAME "drivers/disk/scsi/scsi_cd/driver_v1"
|
||||||
typedef struct cd_device_info {
|
#define SCSI_CD_DEVICE_MODULE_NAME "drivers/disk/scsi/scsi_cd/device_v1"
|
||||||
device_node *node;
|
|
||||||
::scsi_periph_device scsi_periph_device;
|
|
||||||
::scsi_device scsi_device;
|
|
||||||
scsi_device_interface *scsi;
|
|
||||||
::block_io_device block_io_device;
|
|
||||||
|
|
||||||
uint64 capacity;
|
|
||||||
uint32 block_size;
|
|
||||||
|
|
||||||
bool removable;
|
struct cd_driver_info {
|
||||||
uint8 device_type;
|
device_node* node;
|
||||||
} cd_device_info;
|
::scsi_periph_device scsi_periph_device;
|
||||||
|
::scsi_device scsi_device;
|
||||||
typedef struct cd_handle_info {
|
scsi_device_interface* scsi;
|
||||||
::scsi_periph_handle scsi_periph_handle;
|
IOScheduler* io_scheduler;
|
||||||
cd_device_info *device;
|
DMAResource* dma_resource;
|
||||||
} cd_handle_info;
|
|
||||||
|
uint64 capacity;
|
||||||
|
uint32 block_size;
|
||||||
|
|
||||||
|
bool removable;
|
||||||
|
uint8 device_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cd_handle {
|
||||||
|
::scsi_periph_handle scsi_periph_handle;
|
||||||
|
cd_driver_info* info;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _SCSI_CD_H
|
#endif // _SCSI_CD_H
|
||||||
|
|||||||
Reference in New Issue
Block a user