1/*
2 * Copyright 2004-2007, Haiku, Inc. All RightsReserved.
3 * Copyright 2002/03, Thomas Kurschel. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8/*
9	Part of Open IDE bus manager
10
11	ATAPI command protocol
12*/
13
14#include "ide_internal.h"
15
16#include <scsi_cmds.h>
17
18#include "ide_cmds.h"
19#include "ide_sim.h"
20
21#include <string.h>
22
23
24// used for MODE SENSE/SELECT 6 emulation; maximum size is 255 + header,
25// so this is a safe bet
26#define IDE_ATAPI_BUFFER_SIZE 512
27
28
29/*!
30	Set sense according to error reported by device
31	return: true - device reported error
32*/
33static bool
34check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
35{
36	ide_bus_info *bus = device->bus;
37	int status;
38
39	status = bus->controller->get_altstatus(bus->channel_cookie);
40
41	if ((status & (ide_status_err | ide_status_df)) != 0) {
42		int error;
43
44		SHOW_FLOW(3, "packet error, status=%02x", status);
45
46		if (bus->controller->read_command_block_regs(bus->channel_cookie,
47				&device->tf, ide_mask_error) != B_OK) {
48			device->subsys_status = SCSI_HBA_ERR;
49			return true;
50		}
51
52		// the upper 4 bits contain sense key
53		// we don't want to clutter syslog with "not ready" and UA messages,
54		// so use FLOW messages for them
55		error = device->tf.read.error;
56		if ((error >> 4) == SCSIS_KEY_NOT_READY
57			|| (error >> 4) == SCSIS_KEY_UNIT_ATTENTION)
58			SHOW_FLOW(3, "error=%x", error);
59		else
60			SHOW_ERROR(3, "error=%x", error);
61
62		// ATAPI says that:
63		// "ABRT shall be set to one if the requested command has been command
64		//  aborted because the command code or a command parameter is invalid.
65		//  ABRT may be set to one if the device is not able to complete the
66		//  action requested by the command."
67		// Effectively, it can be set if "something goes wrong", including
68		// if the medium got changed. Therefore, we currently ignore the bit
69		// and rely on auto-sense information
70		/*
71		if ((error & ide_error_abrt) != 0) {
72			// if command got aborted, there's no point in reading sense
73			set_sense(device, SCSIS_KEY_ABORTED_COMMAND, SCSIS_ASC_NO_SENSE);
74			return false;
75		}
76		*/
77
78		// tell SCSI layer that sense must be requested
79		// (we don't take care of auto-sense ourselve)
80		device->subsys_status = SCSI_REQ_CMP_ERR;
81		qrequest->request->device_status = SCSI_STATUS_CHECK_CONDITION;
82		// reset pending emulated sense - its overwritten by a real one
83		device->combined_sense = 0;
84		return true;
85	}
86
87	return false;
88}
89
90
91/*! IRQ handler of packet transfer (executed as DPC) */
92void
93packet_dpc(ide_qrequest *qrequest)
94{
95	ide_device_info *device = qrequest->device;
96	ide_bus_info *bus = device->bus;
97	int status;
98	uint32 timeout = qrequest->request->timeout > 0 ?
99		qrequest->request->timeout : IDE_STD_TIMEOUT;
100
101	SHOW_FLOW0(3, "");
102
103	bus->controller->read_command_block_regs(bus->channel_cookie,
104		&device->tf, ide_mask_error | ide_mask_ireason);
105
106	status = bus->controller->get_altstatus(bus->channel_cookie);
107
108	if (qrequest->packet_irq) {
109		// device requests packet
110		qrequest->packet_irq = false;
111
112		if (!device->tf.packet_res.cmd_or_data
113			|| device->tf.packet_res.input_or_output
114			|| (status & ide_status_drq) == 0) {
115			device->subsys_status = SCSI_SEQUENCE_FAIL;
116			goto err;
117		}
118
119		start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);
120
121		// send packet
122		if (bus->controller->write_pio(bus->channel_cookie,
123				(uint16 *)device->packet, sizeof(device->packet) / sizeof(uint16),
124				true) != B_OK) {
125			SHOW_ERROR0( 1, "Error sending command packet" );
126
127			device->subsys_status = SCSI_HBA_ERR;
128			goto err_cancel_timer;
129		}
130
131		return;
132	}
133
134	if (qrequest->uses_dma) {
135		// DMA transmission finished
136		bool dma_err, dev_err;
137
138		// don't check drq - if there is some data left, we cannot handle
139		// it anyway
140		// XXX does the device throw remaining data away on DMA overflow?
141		SHOW_FLOW0(3, "DMA done");
142
143		dma_err = !finish_dma(device);
144		dev_err = check_packet_error(device, qrequest);
145
146		// what to do if both the DMA controller and the device reports an error?
147		// let's assume that the DMA controller got problems because there was a
148		// device error, so we ignore the dma error and use the device error instead
149		if (dev_err) {
150			finish_checksense(qrequest);
151			return;
152		}
153
154		// device is happy, let's see what the controller says
155		if (!dma_err) {
156			// if DMA works, reset error counter so we don't disable
157			// DMA only because it didn't work once in a while
158			device->DMA_failures = 0;
159			// this is a lie, but there is no way to find out
160			// how much has been transmitted
161			qrequest->request->data_resid = 0;
162			finish_checksense(qrequest);
163		} else {
164			// DMA transmission went wrong
165			set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE);
166
167			if (++device->DMA_failures >= MAX_DMA_FAILURES) {
168				SHOW_ERROR0(1, "Disabling DMA because of too many errors");
169
170				device->DMA_enabled = false;
171			}
172
173			finish_checksense(qrequest);
174		}
175
176		return;
177	}
178
179	// PIO mode
180	if ((status & ide_status_drq) != 0) {
181		// device wants to transmit data
182		int length;
183		status_t err;
184
185		SHOW_FLOW0(3, "data transmission");
186
187		if (device->tf.packet_res.cmd_or_data) {
188			device->subsys_status = SCSI_SEQUENCE_FAIL;
189			goto err;
190		}
191
192		// check whether transmission direction matches
193		if ((device->tf.packet_res.input_or_output ^ qrequest->is_write) == 0) {
194			SHOW_ERROR0(2, "data transmission in wrong way!?");
195
196			// TODO: hm, either the device is broken or the caller has specified
197			// the wrong direction - what is the proper handling?
198			set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE);
199
200			// reset device to make it alive
201			// TODO: the device will abort next command with a reset condition
202			// 		perhaps we should hide that by reading sense?
203			SHOW_FLOW0(3, "Reset");
204			reset_device(device, qrequest);
205
206			finish_checksense(qrequest);
207			return;
208		}
209
210		// ask device how much data it wants to transmit
211		bus->controller->read_command_block_regs(bus->channel_cookie,
212			&device->tf, ide_mask_byte_count);
213
214		length = device->tf.packet_res.byte_count_0_7
215			| ((int)device->tf.packet_res.byte_count_8_15 << 8);
216
217		SHOW_FLOW(3, "device transmittes %d bytes", length);
218
219		// start waiting before starting transmission, else we
220		// could start waiting too late;
221		// don't mind getting overtaken by IRQ handler - as it will
222		// issue a DPC for the thread context we are in, we are save
223		start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);
224
225		if (device->tf.packet_res.input_or_output)
226			err = read_PIO_block(qrequest, length);
227		else
228			err = write_PIO_block(qrequest, length);
229
230		// only report "real" errors;
231		// discarding data (ERR_TOO_BIG) can happen but is OK
232		if (err == B_ERROR) {
233			SHOW_ERROR0(2, "Error during PIO transmission");
234
235			device->subsys_status = SCSI_HBA_ERR;
236			goto err_cancel_timer;
237		}
238
239		SHOW_FLOW0(3, "7");
240		return;
241	} else {
242		// device has done job and doesn't want to transmit data anymore
243		// -> finish request
244		SHOW_FLOW0(3, "no data");
245
246		check_packet_error(device, qrequest);
247
248		SHOW_FLOW(3, "finished: %d of %d left",
249			(int)qrequest->request->data_resid,
250			(int)qrequest->request->data_length);
251
252		finish_checksense(qrequest);
253		return;
254	}
255
256	return;
257
258err_cancel_timer:
259	cancel_irq_timeout(device->bus);
260err:
261	finish_checksense(qrequest);
262}
263
264
265/*!	Create taskfile for ATAPI packet */
266static bool
267create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
268	bool write)
269{
270	scsi_ccb *request = qrequest->request;
271
272	SHOW_FLOW(3, "DMA enabled=%d, uses_dma=%d, scsi_cmd=%x",
273		device->DMA_enabled, qrequest->uses_dma, device->packet[0]);
274
275	device->tf_param_mask = ide_mask_features | ide_mask_byte_count;
276
277	device->tf.packet.dma = qrequest->uses_dma;
278	device->tf.packet.ovl = 0;
279	device->tf.packet.byte_count_0_7 = request->data_length & 0xff;
280	device->tf.packet.byte_count_8_15 = request->data_length >> 8;
281	device->tf.packet.command = IDE_CMD_PACKET;
282
283	return true;
284}
285
286
287/*! Send ATAPI packet */
288void
289send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
290{
291	ide_bus_info *bus = device->bus;
292	bool packet_irq = device->atapi.packet_irq;
293	uint8 scsi_cmd = device->packet[0];
294
295	SHOW_FLOW( 3, "qrequest=%p, command=%x", qrequest, scsi_cmd );
296
297	/*{
298		unsigned int i;
299
300		for( i = 0; i < sizeof( device->packet ); ++i )
301			dprintf( "%x ", device->packet[i] );
302	}*/
303
304	SHOW_FLOW(3, "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x (len=%d)",
305		device->packet[0], device->packet[1], device->packet[2],
306		device->packet[3], device->packet[4], device->packet[5],
307		device->packet[6], device->packet[7], device->packet[8],
308		device->packet[9], device->packet[10], device->packet[11],
309		qrequest->request->cdb_length);
310
311	//snooze( 1000000 );
312
313	qrequest->is_write = write;
314	// if needed, mark first IRQ as being packet request IRQ
315	qrequest->packet_irq = packet_irq;
316
317	// only READ/WRITE commands can use DMA
318	// (the device may support it always, but IDE controllers don't
319	// report how much data is transmitted, and this information is
320	// crucial for the SCSI protocol)
321	// special offer: let READ_CD commands use DMA too
322	qrequest->uses_dma = device->DMA_enabled
323		&& (scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6
324		|| scsi_cmd == SCSI_OP_READ_10 || scsi_cmd == SCSI_OP_WRITE_10
325		|| scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12
326		|| scsi_cmd == SCSI_OP_READ_CD);
327
328	// try preparing DMA, if that fails, fall back to PIO
329	if (qrequest->uses_dma) {
330		SHOW_FLOW0(3, "0");
331		if (!prepare_dma( device, qrequest))
332			qrequest->uses_dma = false;
333
334		SHOW_FLOW(3, "0->%d", qrequest->uses_dma);
335	}
336
337	SHOW_FLOW0(3, "1");
338
339	if (!qrequest->uses_dma)
340		prep_PIO_transfer(device, qrequest);
341
342	SHOW_FLOW0(3, "2");
343
344	if (!create_packet_taskfile(device, qrequest, write))
345		goto err_setup;
346
347	SHOW_FLOW0(3, "3");
348
349	if (!send_command(device, qrequest, false,
350			device->atapi.packet_irq_timeout,
351			device->atapi.packet_irq ? ide_state_async_waiting : ide_state_accessing))
352		goto err_setup;
353
354	SHOW_FLOW0(3, "4");
355
356	if (packet_irq) {
357		// device asks for packet via IRQ;
358		// timeout and stuff is already set by send_command
359		return;
360	}
361
362	SHOW_FLOW0(3, "5");
363
364	// wait for device to get ready for packet transmission
365	if (!ide_wait(device, ide_status_drq, ide_status_bsy, false, 100000))
366		goto err_setup;
367
368	SHOW_FLOW0(3, "6");
369
370	// make sure device really asks for command packet
371	bus->controller->read_command_block_regs(bus->channel_cookie, &device->tf,
372		ide_mask_ireason);
373
374	if (!device->tf.packet_res.cmd_or_data
375		|| device->tf.packet_res.input_or_output) {
376		device->subsys_status = SCSI_SEQUENCE_FAIL;
377		goto err_setup;
378	}
379
380	SHOW_FLOW0(3, "7");
381
382	// some old drives need a delay before submitting the packet
383	spin(10);
384
385	// locking is evil here: as soon as the packet is transmitted, the device
386	// may raise an IRQ (which actually happens if the device reports an Check
387	// Condition error). Thus, we have to lock out the IRQ handler _before_ we
388	// start packet transmission, which forbids all kind of interrupts for some
389	// time; to reduce this period, blocking is done just before last dword is
390	// sent (avoid sending 16 bits as controller may transmit 32 bit chunks)
391
392	// write packet
393	if (bus->controller->write_pio(bus->channel_cookie,
394			(uint16 *)device->packet, sizeof(device->packet) / sizeof(uint16) - 2,
395			true) != B_OK) {
396		goto err_packet;
397	}
398
399	IDE_LOCK(bus);
400
401	if (bus->controller->write_pio(bus->channel_cookie,
402			(uint16 *)device->packet + sizeof(device->packet) / sizeof(uint16) - 2,
403			2, true) != B_OK) {
404		goto err_packet2;
405	}
406
407	if (qrequest->uses_dma) {
408		SHOW_FLOW0( 3, "ready for DMA" );
409
410		// S/G table must already be setup - we hold the bus lock, so
411		// we really have to hurry up
412		start_dma_wait(device, qrequest);
413	} else {
414		uint32 timeout = qrequest->request->timeout > 0 ?
415			qrequest->request->timeout : IDE_STD_TIMEOUT;
416
417		start_waiting(bus, timeout, ide_state_async_waiting);
418	}
419
420	SHOW_FLOW0(3, "8");
421	return;
422
423err_packet2:
424	IDE_UNLOCK(bus);
425
426err_packet:
427	device->subsys_status = SCSI_HBA_ERR;
428
429err_setup:
430	if (qrequest->uses_dma)
431		abort_dma(device, qrequest);
432
433	finish_checksense(qrequest);
434}
435
436
437/*! Execute SCSI I/O for atapi devices */
438void
439atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
440{
441	scsi_ccb *request = qrequest->request;
442
443	SHOW_FLOW(3, "command=%x", qrequest->request->cdb[0]);
444
445	// ATAPI command packets are 12 bytes long;
446	// if the command is shorter, remaining bytes must be padded with zeros
447	memset(device->packet, 0, sizeof(device->packet));
448	memcpy(device->packet, request->cdb, request->cdb_length);
449
450	if (request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) {
451		// we have a pending emulated sense - return it on REQUEST SENSE
452		ide_request_sense(device, qrequest);
453		finish_checksense(qrequest);
454	} else {
455		// reset all error codes for new request
456		start_request(device, qrequest);
457
458		// now we have an IDE packet
459		send_packet(device, qrequest,
460			(request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT);
461	}
462}
463
464
465/*!	Prepare device info for ATAPI device */
466bool
467prep_atapi(ide_device_info *device)
468{
469	ide_device_infoblock *infoblock = &device->infoblock;
470
471	SHOW_FLOW0(3, "");
472
473	device->is_atapi = true;
474	device->exec_io = atapi_exec_io;
475
476	if (infoblock->_0.atapi.ATAPI != 2)
477		return false;
478
479	switch(infoblock->_0.atapi.drq_speed) {
480		case 0:
481		case 2:
482			device->atapi.packet_irq = false;
483			break;
484		case 1:
485			device->atapi.packet_irq = true;
486			device->atapi.packet_irq_timeout = IDE_STD_TIMEOUT;
487			break;
488		default:
489			return false;
490	}
491
492	SHOW_FLOW(3, "drq speed: %d", infoblock->_0.atapi.drq_speed);
493
494	/*if( infoblock->_0.atapi.packet_size != 0 )
495		return false;*/
496
497	device->device_type = infoblock->_0.atapi.type;
498	device->last_lun = infoblock->last_lun;
499
500	SHOW_FLOW(3, "device_type=%d, last_lun=%d",
501		device->device_type, device->last_lun);
502
503	// don't use task file to select LUN but command packet
504	// (SCSI bus manager sets LUN there automatically)
505	device->tf.packet.lun = 0;
506
507	if (!initialize_qreq_array(device, 1)
508		|| !configure_dma(device))
509		return false;
510
511	// currently, we don't support queuing, but I haven't found any
512	// ATAPI device that supports queuing anyway, so this is no loss
513	device->CQ_enabled = device->CQ_supported = false;
514
515	return true;
516}
517