From 65f1e8eceb585263436db23748f6207bea0e3a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 5 Aug 2008 21:15:28 +0000 Subject: [PATCH] * 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 --- .../kernel/drivers/disk/scsi/scsi_cd/Jamfile | 1 + .../drivers/disk/scsi/scsi_cd/scsi_cd.cpp | 439 +++++++++++------- .../drivers/disk/scsi/scsi_cd/scsi_cd.h | 43 +- 3 files changed, 295 insertions(+), 188 deletions(-) diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile index 9340ffc904..971734a587 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/Jamfile @@ -1,6 +1,7 @@ SubDir HAIKU_TOP src add-ons kernel drivers disk scsi scsi_cd ; UsePrivateHeaders drivers kernel ; +SubDirHdrs $(HAIKU_TOP) src system kernel device_manager ; KernelAddon scsi_cd : scsi_cd.cpp diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp index 17ca2e5c0b..c7c408ac1d 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.cpp @@ -7,8 +7,8 @@ /*! Peripheral driver to handle CD-ROM drives. To be more 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. */ @@ -29,49 +29,48 @@ static scsi_periph_interface *sSCSIPeripheral; static device_manager_info *sDeviceManager; -static block_io_for_driver_interface *sBlockIO; #define SCSI_CD_STD_TIMEOUT 10 static status_t -update_capacity(cd_device_info *device) +update_capacity(cd_driver_info *info) { 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) return B_NO_MEMORY; 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; } 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 // 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) 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->cylinder_count = device->capacity; + geometry->cylinder_count = info->capacity; geometry->head_count = 1; - geometry->device_type = device->device_type; - geometry->removable = device->removable; + geometry->device_type = info->device_type; + geometry->removable = info->removable; // TBD: for all but CD-ROMs, read mode sense - medium type // (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 optical memory block devices) 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", geometry->bytes_per_sector, geometry->sectors_per_track, @@ -91,7 +90,7 @@ get_geometry(cd_handle_info *handle, device_geometry *geometry) static status_t -get_toc(cd_device_info *device, scsi_toc *toc) +get_toc(cd_driver_info *info, scsi_toc *toc) { scsi_ccb *ccb; status_t res; @@ -101,11 +100,11 @@ get_toc(cd_device_info *device, scsi_toc *toc) TRACE("get_toc()\n"); - ccb = device->scsi->alloc_ccb(device->scsi_device); + ccb = info->scsi->alloc_ccb(info->scsi_device); if (ccb == NULL) return B_NO_MEMORY; - // first read number of tracks only + // first read number of tracks only ccb->flags = SCSI_DIR_IN; 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->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) goto err; // then read all track infos - // (little hint: number of tracks is last - first + 1; - // but scsi_toc_toc has already one track, so we get + // (little hint: number of tracks is last - first + 1; + // but scsi_toc_toc has already one track, so we get // last - first extra tracks; finally, we want the lead-out as // 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); 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); - res = sSCSIPeripheral->safe_exec(device->scsi_periph_device, ccb); + res = sSCSIPeripheral->safe_exec(info->scsi_periph_device, ccb); err: - device->scsi->free_ccb(ccb); + info->scsi->free_ccb(ccb); return res; } static status_t -load_eject(cd_device_info *device, bool load) +load_eject(cd_driver_info *info, bool load) { 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) return B_NO_MEMORY; 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; } 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; @@ -186,13 +185,13 @@ get_position(cd_device_info *device, scsi_position *position) cmd.track = 0; 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); } 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_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)); - 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); if (res != B_OK) return res; @@ -235,14 +234,14 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set) 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); if (res != B_OK) { free(buffer); 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)->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 + 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); } @@ -306,7 +305,7 @@ get_set_volume(cd_device_info *device, scsi_volume *volume, bool set) /*! Play audio cd; time is in MSF */ 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; @@ -324,14 +323,14 @@ play_msf(cd_device_info *device, const scsi_play_position *position) cmd.end_second = position->end_s; 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); } /*! Play audio cd; time is in track/index */ 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_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, // 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) return res; @@ -357,7 +356,7 @@ play_track_index(cd_device_info *device, const scsi_play_track *buf) if (end_track > toc->last_track) end_track = toc->last_track + 1; - + if (end_track < toc->last_track + 1) ++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_f = toc->tracks[end_track].start.time.frame; - return play_msf(device, &position); + return play_msf(info, &position); } static status_t -stop_audio(cd_device_info *device) +stop_audio(cd_driver_info *info) { scsi_cmd_stop_play cmd; @@ -389,13 +388,13 @@ stop_audio(cd_device_info *device) memset( &cmd, 0, sizeof( cmd )); 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); } static status_t -pause_resume(cd_device_info *device, bool resume) +pause_resume(cd_driver_info *info, bool resume) { scsi_cmd_pause_resume cmd; @@ -405,13 +404,13 @@ pause_resume(cd_device_info *device, bool resume) cmd.opcode = SCSI_OP_PAUSE_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); } 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_position curPos; @@ -419,11 +418,11 @@ scan(cd_device_info *device, const scsi_scan *buf) 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) return res; - cdPos = (scsi_cd_current_position *)((char *)&curPos + cdPos = (scsi_cd_current_position *)((char *)&curPos + sizeof(scsi_subchannel_data_header)); if (buf->direction == 0) { @@ -437,7 +436,7 @@ scan(cd_device_info *device, const scsi_scan *buf) playPos.end_s = 59; playPos.end_f = 24; - return play_msf(device, &playPos); + return play_msf(info, &playPos); } memset(&cmd, 0, sizeof(cmd)); @@ -450,32 +449,32 @@ scan(cd_device_info *device, const scsi_scan *buf) /* tmp = (uint8 *)&cmd; 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]); */ - return sSCSIPeripheral->simple_exec(device->scsi_periph_device, + return sSCSIPeripheral->simple_exec(info->scsi_periph_device, &cmd, sizeof(cmd), NULL, 0, 0); } 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; - uint32 lba, length; + uint32 lba, length; scsi_ccb *ccb; status_t res; // we use safe_exec instead of simple_exec as we want to set // the sorting order manually (only makes much sense if you grab // 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) return B_NO_MEMORY; - cmd = (scsi_cmd_read_cd *)ccb->cdb; + cmd = (scsi_cmd_read_cd *)ccb->cdb; memset(cmd, 0, sizeof(*cmd)); cmd->opcode = SCSI_OP_READ_CD; cmd->sector_type = 1; @@ -509,9 +508,9 @@ read_cd(cd_device_info *device, const scsi_read_cd *readCD) ccb->sg_list = NULL; 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; } @@ -526,56 +525,85 @@ log2(uint32 x) if (x == (1UL << y)) break; } - + 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 -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 -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) 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); if (status < B_OK) { free(handle); 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; return B_OK; } static status_t -cd_close(cd_handle_info *handle) +cd_close(void* cookie) { + cd_handle* handle = (cd_handle*)cookie; TRACE("close()\n"); sSCSIPeripheral->handle_close(handle->scsi_periph_handle); @@ -584,8 +612,9 @@ cd_close(cd_handle_info *handle) static status_t -cd_free(cd_handle_info *handle) +cd_free(void* cookie) { + cd_handle* handle = (cd_handle*)cookie; TRACE("free()\n"); sSCSIPeripheral->handle_free(handle->scsi_periph_handle); @@ -595,38 +624,80 @@ cd_free(cd_handle_info *handle) static status_t -cd_read(cd_handle_info *handle, const phys_vecs *vecs, off_t pos, - size_t num_blocks, uint32 block_size, size_t *bytes_transferred) +cd_read(void* cookie, off_t pos, void* buffer, size_t* _length) { - return sSCSIPeripheral->read(handle->scsi_periph_handle, vecs, pos, - num_blocks, block_size, bytes_transferred, 10); + cd_handle* handle = (cd_handle*)cookie; + 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 -cd_write(cd_handle_info *handle, const phys_vecs *vecs, off_t pos, - size_t num_blocks, uint32 block_size, size_t *bytes_transferred) +cd_write(void* cookie, off_t pos, const void* buffer, size_t* _length) { - return sSCSIPeripheral->write(handle->scsi_periph_handle, vecs, pos, - num_blocks, block_size, bytes_transferred, 10); + cd_handle* handle = (cd_handle*)cookie; + 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 -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); switch (op) { case B_GET_DEVICE_SIZE: { - status_t status = update_capacity(device); + status_t status = update_capacity(info); if (status != B_OK) 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)); } @@ -639,7 +710,7 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length) status_t status = get_geometry(handle, &geometry); if (status != B_OK) return status; - + 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: // 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_SCSI_EJECT: - return load_eject(device, false); + return load_eject(info, false); case B_LOAD_MEDIA: - return load_eject(device, true); + return load_eject(info, true); case B_SCSI_GET_POSITION: { if (buffer == NULL) return B_BAD_VALUE; - + scsi_position position; - status_t status = get_position(device, &position); + status_t status = get_position(info, &position); if (status != B_OK) return status; @@ -673,10 +744,10 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length) case B_SCSI_GET_VOLUME: // 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: // 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: { @@ -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) return B_BAD_ADDRESS; - return play_track_index(device, &track); + return play_track_index(info, &track); } case B_SCSI_PLAY_POSITION: { @@ -693,27 +764,27 @@ cd_ioctl(cd_handle_info *handle, int op, void *buffer, size_t length) != B_OK) return B_BAD_ADDRESS; - return play_msf(device, &position); + return play_msf(info, &position); } case B_SCSI_STOP_AUDIO: - return stop_audio(device); + return stop_audio(info); case B_SCSI_PAUSE_AUDIO: - return pause_resume(device, false); + return pause_resume(info, false); case B_SCSI_RESUME_AUDIO: - return pause_resume(device, true); + return pause_resume(info, true); case B_SCSI_SCAN: { scsi_scan scanBuffer; if (user_memcpy(&scanBuffer, buffer, sizeof(scsi_scan)) != B_OK) return B_BAD_ADDRESS; - - return scan(device, &scanBuffer); + + return scan(info, &scanBuffer); } case B_SCSI_READ_CD: // TODO: we pass a user buffer here! - return read_cd(device, (scsi_read_cd *)buffer); + return read_cd(info, (scsi_read_cd *)buffer); default: 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 -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", - device, capacity, blockSize); + TRACE("cd_set_capacity(info = %p, capacity = %Ld, blockSize = %ld)\n", + info, capacity, blockSize); // get log2, if possible uint32 blockShift = log2(blockSize); @@ -737,20 +808,41 @@ cd_set_capacity(cd_device_info *device, uint64 capacity, uint32 blockSize) if ((1UL << blockShift) != blockSize) blockShift = 0; - device->capacity = capacity; - device->block_size = blockSize; + info->capacity = capacity; - sBlockIO->set_media_params(device->block_io_device, blockSize, - blockShift, capacity); + if (info->block_size != blockSize) { + 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 -cd_media_changed(cd_device_info *device, scsi_ccb *request) +cd_media_changed(cd_driver_info *info, scsi_ccb *request) { // do a capacity check // 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 } }; - return sDeviceManager->register_node(node, SCSI_CD_MODULE_NAME, attrs, - NULL, NULL); + return sDeviceManager->register_node(node, SCSI_CD_DRIVER_MODULE_NAME, + attrs, NULL, NULL); } static status_t cd_init_driver(device_node *node, void **cookie) { - cd_device_info *device; + cd_driver_info *info; status_t status; uint8 removable; @@ -841,36 +933,36 @@ cd_init_driver(device_node *node, void **cookie) if (status != B_OK) return status; - device = (cd_device_info *)malloc(sizeof(*device)); - if (device == NULL) + info = (cd_driver_info *)malloc(sizeof(*info)); + if (info == NULL) return B_NO_MEMORY; - memset(device, 0, sizeof(*device)); + memset(info, 0, sizeof(*info)); - device->node = node; - device->removable = removable; + info->node = node; + info->removable = removable; // set capacity to zero, so it get checked on first opened handle - device->capacity = 0; - device->block_size = 0; + info->capacity = 0; + info->block_size = 0; - sDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM, - &device->device_type, true); + sDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM, + &info->device_type, true); device_node *parent = sDeviceManager->get_parent_node(node); - sDeviceManager->get_driver(parent, (driver_module_info **)&device->scsi, - (void **)&device->scsi_device); + sDeviceManager->get_driver(parent, (driver_module_info **)&info->scsi, + (void **)&info->scsi_device); sDeviceManager->put_node(parent); - status = sSCSIPeripheral->register_device((periph_device_cookie)device, - &callbacks, device->scsi_device, device->scsi, device->node, - device->removable, &device->scsi_periph_device); + status = sSCSIPeripheral->register_device((periph_device_cookie)info, + &callbacks, info->scsi_device, info->scsi, info->node, + info->removable, 10, &info->scsi_periph_device); if (status != B_OK) { - free(device); + free(info); return status; } - *cookie = device; + *cookie = info; return B_OK; } @@ -878,26 +970,26 @@ cd_init_driver(device_node *node, void **cookie) static void 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); - free(device); + sSCSIPeripheral->unregister_device(info->scsi_periph_device); + free(info); } static status_t 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; char *name; - name = sSCSIPeripheral->compose_device_name(device->node, "disk/scsi"); + name = sSCSIPeripheral->compose_device_name(info->node, "disk/scsi"); if (name == NULL) return B_ERROR; - status = sDeviceManager->publish_device(device->node, name, - B_BLOCK_IO_DEVICE_MODULE_NAME); + status = sDeviceManager->publish_device(info->node, name, + SCSI_CD_DEVICE_MODULE_NAME); free(name); return status; @@ -905,43 +997,52 @@ cd_register_child_devices(void *_cookie) module_dependency module_dependencies[] = { - {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}, + {SCSI_PERIPH_MODULE_NAME, (module_info**)&sSCSIPeripheral}, + {B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager}, {} }; -block_device_interface sSCSICDModule = { +struct device_module_info sSCSICDDevice = { { - { - SCSI_CD_MODULE_NAME, - 0, - NULL - }, - - cd_supports_device, - cd_register_device, - cd_init_driver, - cd_uninit_driver, - cd_register_child_devices, - NULL, // rescan - NULL, // removed + SCSI_CD_DEVICE_MODULE_NAME, + 0, + NULL }, - (void (*)(block_device_cookie *, block_io_device)) &cd_set_device, - (status_t (*)(block_device_cookie *, block_device_handle_cookie **))&cd_open, - (status_t (*)(block_device_handle_cookie *)) &cd_close, - (status_t (*)(block_device_handle_cookie *)) &cd_free, + cd_init_device, + cd_uninit_device, + NULL, // remove, - (status_t (*)(block_device_handle_cookie *, const phys_vecs *, - off_t, size_t, uint32, size_t *)) &cd_read, - (status_t (*)(block_device_handle_cookie *, const phys_vecs *, - off_t, size_t, uint32, size_t *)) &cd_write, + cd_open, + cd_close, + cd_free, + 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[] = { - (module_info *)&sSCSICDModule, +struct driver_module_info sSCSICDDriver = { + { + 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 }; diff --git a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h index bf91cf963c..75158a67d3 100644 --- a/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h +++ b/src/add-ons/kernel/drivers/disk/scsi/scsi_cd/scsi_cd.h @@ -12,28 +12,33 @@ #include #include - -#define SCSI_CD_MODULE_NAME "drivers/disk/scsi/scsi_cd/driver_v1" +#include "dma_resources.h" +#include "io_requests.h" +#include "IOScheduler.h" -// must start as block_device_cookie -typedef struct cd_device_info { - device_node *node; - ::scsi_periph_device scsi_periph_device; - ::scsi_device scsi_device; - scsi_device_interface *scsi; - ::block_io_device block_io_device; +#define SCSI_CD_DRIVER_MODULE_NAME "drivers/disk/scsi/scsi_cd/driver_v1" +#define SCSI_CD_DEVICE_MODULE_NAME "drivers/disk/scsi/scsi_cd/device_v1" - uint64 capacity; - uint32 block_size; - bool removable; - uint8 device_type; -} cd_device_info; - -typedef struct cd_handle_info { - ::scsi_periph_handle scsi_periph_handle; - cd_device_info *device; -} cd_handle_info; +struct cd_driver_info { + device_node* node; + ::scsi_periph_device scsi_periph_device; + ::scsi_device scsi_device; + scsi_device_interface* scsi; + IOScheduler* io_scheduler; + DMAResource* dma_resource; + + 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