Example #1
0
static bool
scan_device_int(ide_device_info *device, bool atapi)
{
	ide_bus_info *bus = device->bus;
	int status;

	TRACE("scan_device_int: device %p, atapi %d\n", device, atapi);

	device->tf_param_mask = 0;
	device->tf.write.command = atapi ? IDE_CMD_IDENTIFY_PACKET_DEVICE
		: IDE_CMD_IDENTIFY_DEVICE;

	// initialize device selection flags,
	// this is the only place where this bit gets initialized in the task file
	if (bus->controller->read_command_block_regs(bus->channel_cookie, &device->tf,
			ide_mask_device_head) != B_OK) {
		TRACE("scan_device_int: read_command_block_regs failed\n");
		return false;
	}

	device->tf.lba.device = device->is_device1;

	if (!send_command(device, NULL, atapi ? false : true, 20, ide_state_sync_waiting)) {
		TRACE("scan_device_int: send_command failed\n");
		return false;
	}

	// do a short wait first - if there's no device at all we could wait forever
	// ToDo: have a look at this; if it times out (when the time is too short),
	//		the kernel seems to crash a little later)!
	TRACE("scan_device_int: waiting 100ms...\n");
	if (acquire_sem_etc(bus->sync_wait_sem, 1, B_RELATIVE_TIMEOUT, 100000) == B_TIMED_OUT) {
		bool cont;

		TRACE("scan_device_int: no fast response to inquiry\n");

		// check the busy flag - if it's still set, there's probably no device	
		IDE_LOCK(bus);

		status = bus->controller->get_altstatus(bus->channel_cookie);
		cont = (status & ide_status_bsy) == ide_status_bsy;

		IDE_UNLOCK(bus);

		TRACE("scan_device_int: status %#04x\n", status);

		if (!cont) {
			TRACE("scan_device_int: busy bit not set after 100ms - probably noone there\n");
			// no reaction -> abort waiting
			cancel_irq_timeout(bus);

			// timeout or irq may have been fired, reset semaphore just is case
			acquire_sem_etc(bus->sync_wait_sem, 1, B_RELATIVE_TIMEOUT, 0);

			TRACE("scan_device_int: aborting because busy bit not set\n");
			return false;
		}

		TRACE("scan_device_int: busy bit set, give device more time\n");

		// there is something, so wait for it
		acquire_sem(bus->sync_wait_sem);
	}
	TRACE("scan_device_int: got a fast response\n");

	// cancel the timeout manually; usually this is done by wait_for_sync(), but
	// we've used the wait semaphore directly	
	cancel_irq_timeout(bus);

	if (bus->sync_wait_timeout) {
		TRACE("scan_device_int: aborting on sync_wait_timeout\n");
		return false;
	}

	ide_wait(device, ide_status_drq, ide_status_bsy, true, 1000);

	status = bus->controller->get_altstatus(bus->channel_cookie);

	if ((status & ide_status_err) != 0) {
		// if there's no device, all bits including the error bit are set
		TRACE("scan_device_int: error bit set - no device or wrong type (status: %#04x)\n", status);
		return false;
	}

	// get the infoblock		
	bus->controller->read_pio(bus->channel_cookie, (uint16 *)&device->infoblock, 
		sizeof(device->infoblock) / sizeof(uint16), false);

	if (!wait_for_drqdown(device)) {
		TRACE("scan_device_int: wait_for_drqdown failed\n");
		return false;
	}

	TRACE("scan_device_int: device found\n");

	prep_infoblock(device);
	return true;	
}
Example #2
0
void ata_dpc_PIO( ide_qrequest *qrequest )
{
	ide_device_info *device = qrequest->device;
	bigtime_t timeout = qrequest->request->cam_timeout > 0 ? 
		qrequest->request->cam_timeout : IDE_STD_TIMEOUT;
	
	if( !check_rw_error( device, qrequest ) ||
		!check_rw_status( device, qrequest,
		qrequest->is_write ? device->left_blocks > 1 : true )) 
	{
		/*if( (device->sense.sense_key == SCSIS_KEY_ABORTED_COMMAND ||
			 device->sense.ascq == SCSIS_ASC_UNREC_READ_ERR) &&
			++qrequest->retries < MAX_PIO_RETRIES ) 
		{
			finish_rw_request( qrequest, ide_finish_rw_retry );
		} else*/
			finish_checksense( qrequest );
			
		return;
	}

	if( qrequest->is_write ) {
		if( device->left_blocks == 0 )
			goto finish;
			
		if( !wait_for_drq( device )) 
			goto finish;
			
		start_waiting_nolock( device->bus, timeout, ide_state_async_waiting );
		
		// having a too short data buffer shouldn't happen here
		// anyway - we are prepared
		if( write_PIO_block( qrequest, 512 ) == ERR_GENERAL )
			goto finish_cancel_timeout;
			
		--device->left_blocks;

	} else {
		if( device->left_blocks > 0 )
			start_waiting_nolock( device->bus, timeout, ide_state_async_waiting );
		
		// see write
		if( read_PIO_block( qrequest, 512 ) == ERR_GENERAL ) 
			goto finish_cancel_timeout;
			
		--device->left_blocks;
		
		if( device->left_blocks == 0 ) {
			wait_for_drqdown( device );
			goto finish_cancel_timeout;
		}
	}
	
	//start_waiting( device->bus );
	return;
	
finish_cancel_timeout:
	cancel_irq_timeout( device->bus );
	
finish:
	finish_checksense( qrequest );
	return;
}
Example #3
0
void
ata_dpc_PIO(ide_qrequest *qrequest)
{
	ide_device_info *device = qrequest->device;
	uint32 timeout = qrequest->request->timeout > 0 ?
		qrequest->request->timeout : IDE_STD_TIMEOUT;

	SHOW_FLOW0(3, "");

	if (check_rw_error(device, qrequest)
		|| !check_rw_status(device, qrequest->is_write ? device->left_blocks > 0 : true))
	{
		// failure reported by device
		SHOW_FLOW0( 3, "command finished unsuccessfully" );

		finish_checksense(qrequest);
		return;
	}

	if (qrequest->is_write) {
		if (device->left_blocks == 0) {
			// this was the end-of-transmission IRQ
			SHOW_FLOW0(3, "write access finished");
			if (!wait_for_drqdown(device)) {
				SHOW_ERROR0(3, "device wants to transmit data though command is finished");
				goto finish;
			}
			goto finish;
		}

		// wait until device requests data
		SHOW_FLOW0(3, "Waiting for device ready to transmit");
		if (!wait_for_drq(device)) {
			SHOW_FLOW0(3, "device not ready for data transmission - abort");
			goto finish;
		}

		// start async waiting for next block/end of command
		// we should start that when block is transmitted, but with bad
		// luck the IRQ fires exactly between transmission and start of waiting,
		// so we better start waiting too early; as we are in service thread,
		// a DPC initiated by IRQ cannot overtake us, so there is no need to block
		// IRQs during sent
		start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);

		// having a too short data buffer shouldn't happen here
		// anyway - we are prepared
		SHOW_FLOW0(3, "Writing one block");
		if (write_PIO_block(qrequest, 512) == B_ERROR)
			goto finish_cancel_timeout;

		--device->left_blocks;
	} else {
		if (device->left_blocks > 1) {
			// start async waiting for next command (see above)
			start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);
		}

		// see write
		SHOW_FLOW0( 3, "Reading one block" );
		if (read_PIO_block(qrequest, 512) == B_ERROR)
			goto finish_cancel_timeout;

		--device->left_blocks;

		if (device->left_blocks == 0) {
			// at end of transmission, wait for data request going low
			SHOW_FLOW0( 3, "Waiting for device to finish transmission" );

			if (!wait_for_drqdown(device))
				SHOW_FLOW0( 3, "Device continues data transmission - abort command" );

			// we don't cancel timeout as no timeout is started during last block
			goto finish;
		}
	}

	return;

finish_cancel_timeout:
	cancel_irq_timeout(device->bus);

finish:
	finish_checksense(qrequest);
}