From af29aba8a60cdcc0393246b30730e26752e16213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 30 Mar 2006 20:43:13 +0000 Subject: [PATCH] Cleanup. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@16938 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/add-ons/kernel/bus_managers/ide/atapi.c | 413 ++++++++++---------- 1 file changed, 207 insertions(+), 206 deletions(-) diff --git a/src/add-ons/kernel/bus_managers/ide/atapi.c b/src/add-ons/kernel/bus_managers/ide/atapi.c index c0becb10af..363bfdc471 100644 --- a/src/add-ons/kernel/bus_managers/ide/atapi.c +++ b/src/add-ons/kernel/bus_managers/ide/atapi.c @@ -1,7 +1,9 @@ /* -** 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. + */ /* Part of Open IDE bus manager @@ -24,38 +26,40 @@ #define IDE_ATAPI_BUFFER_SIZE 512 -// set sense according to error reported by device -// return: true - device reported error -static bool check_packet_error( ide_device_info *device, ide_qrequest *qrequest ) +/** Set sense according to error reported by device + * return: true - device reported error + */ + +static bool +check_packet_error(ide_device_info *device, ide_qrequest *qrequest) { ide_bus_info *bus = device->bus; int status; - - status = bus->controller->get_altstatus( bus->channel ); - if( (status & (ide_status_err | ide_status_df)) != 0 ) { + status = bus->controller->get_altstatus(bus->channel); + + if ((status & (ide_status_err | ide_status_df)) != 0) { int error; - - SHOW_FLOW( 3, "packet error, status=%02x", status ); - - if( bus->controller->read_command_block_regs( bus->channel, - &device->tf, ide_mask_error ) != B_OK ) - { + + SHOW_FLOW(3, "packet error, status=%02x", status); + + if (bus->controller->read_command_block_regs(bus->channel, + &device->tf, ide_mask_error) != B_OK) { device->subsys_status = SCSI_HBA_ERR; return true; } - + // the upper 4 bits contain sense key // we don't want to clutter syslog with "not ready" and UA messages, // so use FLOW messages for them error = device->tf.read.error; - if( (error >> 4) == SCSIS_KEY_NOT_READY || - (error >> 4) == SCSIS_KEY_UNIT_ATTENTION ) - SHOW_FLOW( 3, "error=%x", error ); + if ((error >> 4) == SCSIS_KEY_NOT_READY + || (error >> 4) == SCSIS_KEY_UNIT_ATTENTION) + SHOW_FLOW(3, "error=%x", error); else - SHOW_ERROR( 3, "error=%x", error ); + SHOW_ERROR(3, "error=%x", error); - // ATAPI says that + // ATAPI says that: // "ABRT shall be set to one if the requested command has been command // aborted because the command code or a command parameter is invalid. // ABRT may be set to one if the device is not able to complete the @@ -64,9 +68,9 @@ static bool check_packet_error( ide_device_info *device, ide_qrequest *qrequest // if the medium got changed. Therefore, we currently ignore the bit // and rely on auto-sense information /* - if( (error & ide_error_abrt) != 0 ) { + if ((error & ide_error_abrt) != 0) { // if command got aborted, there's no point in reading sense - set_sense( device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE ); + set_sense(device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE); return false; } */ @@ -79,241 +83,240 @@ static bool check_packet_error( ide_device_info *device, ide_qrequest *qrequest device->combined_sense = 0; return true; } - + return false; } -// IRQ handler of packet transfer (executed as DPC) -void packet_dpc( ide_qrequest *qrequest ) +/** IRQ handler of packet transfer (executed as DPC) */ + +void +packet_dpc(ide_qrequest *qrequest) { ide_device_info *device = qrequest->device; ide_bus_info *bus = device->bus; int status; uint32 timeout = qrequest->request->timeout > 0 ? qrequest->request->timeout : IDE_STD_TIMEOUT; - - SHOW_FLOW0( 3, "" ); - - bus->controller->read_command_block_regs( bus->channel, - &device->tf, ide_mask_error | ide_mask_ireason ); - - status = bus->controller->get_altstatus( bus->channel ); - if( qrequest->packet_irq ) { + SHOW_FLOW0(3, ""); + + bus->controller->read_command_block_regs(bus->channel, + &device->tf, ide_mask_error | ide_mask_ireason); + + status = bus->controller->get_altstatus(bus->channel); + + if (qrequest->packet_irq) { // device requests packet qrequest->packet_irq = false; - - if( !device->tf.packet_res.cmd_or_data || - device->tf.packet_res.input_or_output || - (status & ide_status_drq) == 0 ) - { + + if (!device->tf.packet_res.cmd_or_data + || device->tf.packet_res.input_or_output + || (status & ide_status_drq) == 0) { device->subsys_status = SCSI_SEQUENCE_FAIL; goto err; } - - start_waiting_nolock( device->bus, timeout, ide_state_async_waiting ); - + + start_waiting_nolock(device->bus, timeout, ide_state_async_waiting); + // send packet - if( bus->controller->write_pio( bus->channel, - (uint16 *)device->packet, sizeof( device->packet ) / sizeof( uint16 ), - true ) != B_OK ) - { + if (bus->controller->write_pio(bus->channel, + (uint16 *)device->packet, sizeof(device->packet) / sizeof(uint16), + true) != B_OK) { SHOW_ERROR0( 1, "Error sending command packet" ); - + device->subsys_status = SCSI_HBA_ERR; goto err_cancel_timer; } - + return; } - - if( qrequest->uses_dma ) { + + if (qrequest->uses_dma) { // DMA transmission finished bool dma_err, dev_err; // don't check drq - if there is some data left, we cannot handle // it anyway // XXX does the device throw remaining data away on DMA overflow? - SHOW_FLOW0( 3, "DMA done" ); - - dma_err = !finish_dma( device ); - dev_err = check_packet_error( device, qrequest ); - + SHOW_FLOW0(3, "DMA done"); + + dma_err = !finish_dma(device); + dev_err = check_packet_error(device, qrequest); + // what to do if both the DMA controller and the device reports an error? // let's assume that the DMA controller got problems because there was a // device error, so we ignore the dma error and use the device error instead - if( dev_err ) { - finish_checksense( qrequest ); + if (dev_err) { + finish_checksense(qrequest); return; } // device is happy, let's see what the controller says - if( !dma_err ) { + if (!dma_err) { // if DMA works, reset error counter so we don't disable // DMA only because it didn't work once in a while device->DMA_failures = 0; // this is a lie, but there is no way to find out // how much has been transmitted qrequest->request->data_resid = 0; - finish_checksense( qrequest ); - + finish_checksense(qrequest); } else { // DMA transmission went wrong - set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE ); - - if( ++device->DMA_failures >= MAX_DMA_FAILURES ) { - SHOW_ERROR0( 1, "Disabling DMA because of too many errors" ); - + set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE); + + if (++device->DMA_failures >= MAX_DMA_FAILURES) { + SHOW_ERROR0(1, "Disabling DMA because of too many errors"); + device->DMA_enabled = false; } - - finish_checksense( qrequest ); + + finish_checksense(qrequest); } return; } // PIO mode - if( (status & ide_status_drq) != 0 ) { + if ((status & ide_status_drq) != 0) { // device wants to transmit data int length; status_t err; - - SHOW_FLOW0( 3, "data transmission" ); - - if( device->tf.packet_res.cmd_or_data ) { + + SHOW_FLOW0(3, "data transmission"); + + if (device->tf.packet_res.cmd_or_data) { device->subsys_status = SCSI_SEQUENCE_FAIL; goto err; } - + // check whether transmission direction matches - if( (device->tf.packet_res.input_or_output ^ qrequest->is_write) == 0 ) { - SHOW_ERROR0( 2, "data transmission in wrong way!?" ); - - // XXX hm, either the device is broken or the caller has specified + if ((device->tf.packet_res.input_or_output ^ qrequest->is_write) == 0) { + SHOW_ERROR0(2, "data transmission in wrong way!?"); + + // TODO: hm, either the device is broken or the caller has specified // the wrong direction - what is the proper handling? - set_sense( device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE ); + set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE); // reset device to make it alive - // TBD: the device will abort next command with a reset condition + // TODO: the device will abort next command with a reset condition // perhaps we should hide that by reading sense? - SHOW_FLOW0( 3, "Reset" ); - reset_device( device, qrequest ); - - finish_checksense( qrequest ); + SHOW_FLOW0(3, "Reset"); + reset_device(device, qrequest); + finish_checksense(qrequest); return; } - + // ask device how much data it wants to transmit - bus->controller->read_command_block_regs( bus->channel, - &device->tf, ide_mask_byte_count ); - - length = device->tf.packet_res.byte_count_0_7 | - ((int)device->tf.packet_res.byte_count_8_15 << 8); - - SHOW_FLOW( 3, "device transmittes %d bytes", length ); - + bus->controller->read_command_block_regs(bus->channel, + &device->tf, ide_mask_byte_count); + + length = device->tf.packet_res.byte_count_0_7 + | ((int)device->tf.packet_res.byte_count_8_15 << 8); + + SHOW_FLOW(3, "device transmittes %d bytes", length); + // start waiting before starting transmission, else we // could start waiting too late; // don't mind getting overtaken by IRQ handler - as it will // issue a DPC for the thread context we are in, we are save - start_waiting_nolock( device->bus, timeout, ide_state_async_waiting ); - - if( device->tf.packet_res.input_or_output ) - err = read_PIO_block( qrequest, length ); + start_waiting_nolock(device->bus, timeout, ide_state_async_waiting); + + if (device->tf.packet_res.input_or_output) + err = read_PIO_block(qrequest, length); else - err = write_PIO_block( qrequest, length ); - + err = write_PIO_block(qrequest, length); + // only report "real" errors; // discarding data (ERR_TOO_BIG) can happen but is OK - if( err == B_ERROR ) { - SHOW_ERROR0( 2, "Error during PIO transmission" ); - + if (err == B_ERROR) { + SHOW_ERROR0(2, "Error during PIO transmission"); + device->subsys_status = SCSI_HBA_ERR; goto err_cancel_timer; } - - SHOW_FLOW0( 3, "7" ); - + + SHOW_FLOW0(3, "7"); return; - } else { // device has done job and doesn't want to transmit data anymore // -> finish request - SHOW_FLOW0( 3, "no data" ); - - check_packet_error( device, qrequest ); + SHOW_FLOW0(3, "no data"); - SHOW_FLOW( 3, "finished: %d of %d left", + check_packet_error(device, qrequest); + + SHOW_FLOW(3, "finished: %d of %d left", (int)qrequest->request->data_resid, - (int)qrequest->request->data_len ); - - finish_checksense( qrequest ); + (int)qrequest->request->data_len); + + finish_checksense(qrequest); return; } - + return; err_cancel_timer: - cancel_irq_timeout( device->bus ); - + cancel_irq_timeout(device->bus); err: - finish_checksense( qrequest ); + finish_checksense(qrequest); } -// create taskfile for ATAPI packet -static bool create_packet_taskfile( ide_device_info *device, ide_qrequest *qrequest, - bool write ) +/** Create taskfile for ATAPI packet */ + +static bool +create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest, + bool write) { scsi_ccb *request = qrequest->request; - - SHOW_FLOW( 3, "DMA enabled=%d, uses_dma=%d, scsi_cmd=%x", - device->DMA_enabled, qrequest->uses_dma, device->packet[0] ); - + + SHOW_FLOW(3, "DMA enabled=%d, uses_dma=%d, scsi_cmd=%x", + device->DMA_enabled, qrequest->uses_dma, device->packet[0]); + device->tf_param_mask = ide_mask_features | ide_mask_byte_count; - + device->tf.packet.dma = qrequest->uses_dma; device->tf.packet.ovl = 0; device->tf.packet.byte_count_0_7 = request->data_len & 0xff; device->tf.packet.byte_count_8_15 = request->data_len >> 8; device->tf.packet.command = IDE_CMD_PACKET; - + return true; } -// send ATAPI packet -void send_packet( ide_device_info *device, ide_qrequest *qrequest, bool write ) +/** Send ATAPI packet */ + +void +send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write) { ide_bus_info *bus = device->bus; bool packet_irq = device->atapi.packet_irq; uint8 scsi_cmd = device->packet[0]; - + SHOW_FLOW( 3, "qrequest=%p, command=%x", qrequest, scsi_cmd ); - + /*{ unsigned int i; for( i = 0; i < sizeof( device->packet ); ++i ) dprintf( "%x ", device->packet[i] ); }*/ - + SHOW_FLOW( 3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len=%d)", device->packet[0], device->packet[1], device->packet[2], device->packet[3], device->packet[4], device->packet[5], device->packet[6], device->packet[7], device->packet[8], device->packet[9], device->packet[10], device->packet[11], qrequest->request->cdb_len ); - + //snooze( 1000000 ); - + qrequest->is_write = write; // if needed, mark first IRQ as being packet request IRQ qrequest->packet_irq = packet_irq; - + // only READ/WRITE commands can use DMA // (the device may support it always, but IDE controllers don't // report how much data is transmitted, and this information is @@ -326,61 +329,61 @@ void send_packet( ide_device_info *device, ide_qrequest *qrequest, bool write ) scsi_cmd == SCSI_OP_READ_CD ); // try preparing DMA, if that fails, fall back to PIO - if( qrequest->uses_dma ) { - SHOW_FLOW0( 3, "0" ); - if( !prepare_dma( device, qrequest )) + if (qrequest->uses_dma) { + SHOW_FLOW0(3, "0"); + if (!prepare_dma( device, qrequest)) qrequest->uses_dma = false; - - SHOW_FLOW( 3, "0->%d", qrequest->uses_dma ); + + SHOW_FLOW(3, "0->%d", qrequest->uses_dma); } - - SHOW_FLOW0( 3, "1" ); - - if( !qrequest->uses_dma ) - prep_PIO_transfer( device, qrequest ); - - SHOW_FLOW0( 3, "2" ); - if( !create_packet_taskfile( device, qrequest, write )) + SHOW_FLOW0(3, "1"); + + if (!qrequest->uses_dma) + prep_PIO_transfer(device, qrequest); + + SHOW_FLOW0(3, "2"); + + if (!create_packet_taskfile(device, qrequest, write)) goto err_setup; - SHOW_FLOW0( 3, "3" ); - - if( !send_command( device, qrequest, false, - device->atapi.packet_irq_timeout, - device->atapi.packet_irq ? ide_state_async_waiting : ide_state_accessing )) + SHOW_FLOW0(3, "3"); + + if (!send_command(device, qrequest, false, + device->atapi.packet_irq_timeout, + device->atapi.packet_irq ? ide_state_async_waiting : ide_state_accessing)) goto err_setup; - - SHOW_FLOW0( 3, "4" ); - - if( packet_irq ) + + SHOW_FLOW0(3, "4"); + + if (packet_irq) { // device asks for packet via IRQ; // timeout and stuff is already set by send_command return; - - SHOW_FLOW0( 3, "5" ); + } + SHOW_FLOW0(3, "5"); + // wait for device to get ready for packet transmission - if( !ide_wait( device, ide_status_drq, ide_status_bsy, false, 100000 )) + if (!ide_wait(device, ide_status_drq, ide_status_bsy, false, 100000)) goto err_setup; - - SHOW_FLOW0( 3, "6" ); + + SHOW_FLOW0(3, "6"); // make sure device really asks for command packet - bus->controller->read_command_block_regs( bus->channel, &device->tf, - ide_mask_ireason ); - - if( !device->tf.packet_res.cmd_or_data || - device->tf.packet_res.input_or_output ) - { + bus->controller->read_command_block_regs(bus->channel, &device->tf, + ide_mask_ireason); + + if (!device->tf.packet_res.cmd_or_data + || device->tf.packet_res.input_or_output) { device->subsys_status = SCSI_SEQUENCE_FAIL; goto err_setup; } - - SHOW_FLOW0( 3, "7" ); - + + SHOW_FLOW0(3, "7"); + // some old drives need a delay before submitting the packet - spin( 10 ); + spin(10); // locking is evil here: as soon as the packet is transmitted, the device // may raise an IRQ (which actually happens if the device reports an Check @@ -388,79 +391,77 @@ void send_packet( ide_device_info *device, ide_qrequest *qrequest, bool write ) // start packet transmission, which forbids all kind of interrupts for some // time; to reduce this period, blocking is done just before last dword is // sent (avoid sending 16 bits as controller may transmit 32 bit chunks) - + // write packet - if( bus->controller->write_pio( bus->channel, - (uint16 *)device->packet, sizeof( device->packet ) / sizeof( uint16 ) - 2, - true ) != B_OK ) - { + if (bus->controller->write_pio(bus->channel, + (uint16 *)device->packet, sizeof(device->packet) / sizeof(uint16) - 2, + true) != B_OK) { goto err_packet; } - IDE_LOCK( bus ); + IDE_LOCK(bus); - if( bus->controller->write_pio( bus->channel, - (uint16 *)device->packet + sizeof( device->packet ) / sizeof( uint16 ) - 2, - 2, true ) != B_OK ) - { + if (bus->controller->write_pio(bus->channel, + (uint16 *)device->packet + sizeof(device->packet) / sizeof(uint16) - 2, + 2, true) != B_OK) { goto err_packet2; } - if( qrequest->uses_dma ) { + if (qrequest->uses_dma) { SHOW_FLOW0( 3, "ready for DMA" ); // S/G table must already be setup - we hold the bus lock, so // we really have to hurry up - start_dma_wait( device, qrequest ); + start_dma_wait(device, qrequest); } else { uint32 timeout = qrequest->request->timeout > 0 ? qrequest->request->timeout : IDE_STD_TIMEOUT; - - start_waiting( bus, timeout, ide_state_async_waiting ); + + start_waiting(bus, timeout, ide_state_async_waiting); } - - SHOW_FLOW0( 3, "8" ); - + + SHOW_FLOW0(3, "8"); return; err_packet2: - IDE_UNLOCK( bus ); + IDE_UNLOCK(bus); -err_packet: +err_packet: device->subsys_status = SCSI_HBA_ERR; err_setup: - if( qrequest->uses_dma ) - abort_dma( device, qrequest ); + if (qrequest->uses_dma) + abort_dma(device, qrequest); - finish_checksense( qrequest ); + finish_checksense(qrequest); } -// execute SCSI I/O for atapi devices -void atapi_exec_io( ide_device_info *device, ide_qrequest *qrequest ) +/** Execute SCSI I/O for atapi devices */ + +void +atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest) { scsi_ccb *request = qrequest->request; - - SHOW_FLOW( 3, "command=%x", qrequest->request->cdb[0] ); + + SHOW_FLOW(3, "command=%x", qrequest->request->cdb[0]); // ATAPI command packets are 12 bytes long; // if the command is shorter, remaining bytes must be padded with zeros - memset( device->packet, 0, sizeof( device->packet )); - memcpy( device->packet, request->cdb, request->cdb_len ); + memset(device->packet, 0, sizeof(device->packet)); + memcpy(device->packet, request->cdb, request->cdb_len); - if( request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense ) { + if (request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) { // we have a pending emulated sense - return it on REQUEST SENSE - ide_request_sense( device, qrequest ); - finish_checksense( qrequest ); - + ide_request_sense(device, qrequest); + finish_checksense(qrequest); } else { // reset all error codes for new request - start_request( device, qrequest ); + start_request(device, qrequest); // now we have an IDE packet - send_packet( device, qrequest, - (request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT ); + send_packet(device, qrequest, + (request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT); } } @@ -472,7 +473,7 @@ prep_atapi(ide_device_info *device) { ide_device_infoblock *infoblock = &device->infoblock; - SHOW_FLOW0( 3, "" ); + SHOW_FLOW0(3, ""); device->is_atapi = true; device->exec_io = atapi_exec_io;