1/*
2 * Copyright 2008-2023, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 *		Michael Lotz <mmlr@mlotz.ch>
7 *		Augustin Cavalier <waddlesplash>
8 */
9
10
11#include "usb_disk.h"
12
13#include <ByteOrder.h>
14#include <StackOrHeapArray.h>
15#include <Drivers.h>
16#include <bus/USB.h>
17
18#include <stdio.h>
19#include <stdlib.h>
20#include <string.h>
21
22#include <kernel.h>
23#include <fs/devfs.h>
24#include <syscall_restart.h>
25#include <util/AutoLock.h>
26
27#include "IORequest.h"
28
29#include "scsi_sense.h"
30#include "usb_disk_scsi.h"
31#include "icons.h"
32
33
34#define MAX_IO_BLOCKS					(128)
35
36#define USB_DISK_DEVICE_MODULE_NAME		"drivers/disk/usb_disk/device_v1"
37#define USB_DISK_DRIVER_MODULE_NAME		"drivers/disk/usb_disk/driver_v1"
38#define USB_DISK_DEVICE_ID_GENERATOR	"usb_disk/device_id"
39
40#define DRIVER_NAME			"usb_disk"
41#define DEVICE_NAME_BASE	"disk/usb/"
42#define DEVICE_NAME			DEVICE_NAME_BASE "%" B_PRIu32 "/%d/raw"
43
44
45//#define TRACE_USB_DISK
46#ifdef TRACE_USB_DISK
47#define TRACE(x...)			dprintf(DRIVER_NAME ": " x)
48#define TRACE_ALWAYS(x...)	dprintf(DRIVER_NAME ": " x)
49#define CALLED() 			TRACE("CALLED %s\n", __PRETTY_FUNCTION__)
50#else
51#define TRACE(x...)			/* nothing */
52#define CALLED()
53#define TRACE_ALWAYS(x...)	dprintf(DRIVER_NAME ": " x)
54#endif
55
56
57device_manager_info *gDeviceManager;
58static usb_module_info *gUSBModule = NULL;
59
60struct {
61	const char *vendor;
62	const char *product;
63	device_icon *icon;
64	const char *name;
65} kIconMatches[] = {
66	// matches for Hama USB 2.0 Card Reader 35 in 1
67	// vendor: "Transcend Information, Inc."
68	// product: "63-in-1 Multi-Card Reader/Writer" ver. 0100
69	// which report things like "Generic " "USB  CF Reader  "
70//	{ NULL, " CF Reader", &kCFIconData, "devices/drive-removable-media-flash" },
71	{ NULL, " SD Reader", &kSDIconData, "devices/drive-removable-media-flash" },
72	{ NULL, " MS Reader", &kMSIconData, "devices/drive-removable-media-flash" },
73//	{ NULL, " SM Reader", &kSMIconData, "devices/drive-removable-media-flash" },
74	// match for my Kazam mobile phone
75	// stupid thing says "MEDIATEK" " FLASH DISK     " even for internal memory
76	{ "MEDIATEK", NULL, &kMobileIconData,
77		"devices/drive-removable-media-flash" },
78	{ NULL, NULL, NULL, NULL }
79};
80
81
82//
83//#pragma mark - Forward Declarations
84//
85
86
87static void	usb_disk_callback(void *cookie, status_t status, void *data,
88				size_t actualLength);
89
90uint8		usb_disk_get_max_lun(disk_device *device);
91void		usb_disk_reset_recovery(disk_device *device);
92status_t	usb_disk_receive_csw(disk_device *device,
93				usb_massbulk_command_status_wrapper *status);
94
95status_t	usb_disk_send_diagnostic(device_lun *lun);
96status_t	usb_disk_request_sense(device_lun *lun, err_act *action);
97status_t	usb_disk_mode_sense(device_lun *lun);
98status_t	usb_disk_test_unit_ready(device_lun *lun, err_act *action = NULL);
99status_t	usb_disk_inquiry(device_lun *lun);
100status_t	usb_disk_reset_capacity(device_lun *lun);
101status_t	usb_disk_update_capacity(device_lun *lun);
102status_t	usb_disk_synchronize(device_lun *lun, bool force);
103
104
105// #pragma mark - disk_device helper functions
106
107
108disk_device_s::disk_device_s()
109	:
110	notify(-1),
111	interruptLock(-1)
112{
113	recursive_lock_init(&io_lock, "usb_disk i/o lock");
114	mutex_init(&lock, "usb_disk device lock");
115}
116
117
118disk_device_s::~disk_device_s()
119{
120	recursive_lock_destroy(&io_lock);
121	mutex_destroy(&lock);
122
123	if (notify >= 0)
124		delete_sem(notify);
125	if (interruptLock >= 0)
126		delete_sem(interruptLock);
127}
128
129
130static DMAResource*
131get_dma_resource(disk_device *device, uint32 blockSize)
132{
133	for (int32 i = 0; i < device->dma_resources.Count(); i++) {
134		DMAResource* r = device->dma_resources[i];
135		if (r->BlockSize() == blockSize)
136			return r;
137	}
138	return NULL;
139}
140
141
142void
143usb_disk_free_device_and_luns(disk_device *device)
144{
145	ASSERT_LOCKED_MUTEX(&device->lock);
146
147	for (int32 i = 0; i < device->dma_resources.Count(); i++)
148		delete device->dma_resources[i];
149	for (uint8 i = 0; i < device->lun_count; i++)
150		free(device->luns[i]);
151	free(device->luns);
152	delete device;
153}
154
155
156//
157//#pragma mark - Bulk-only Mass Storage Functions
158//
159
160
161static status_t
162usb_disk_mass_storage_reset(disk_device *device)
163{
164	return gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_OUT
165		| USB_REQTYPE_CLASS, USB_MASSBULK_REQUEST_MASS_STORAGE_RESET, 0x0000,
166		device->interface, 0, NULL, NULL);
167}
168
169
170uint8
171usb_disk_get_max_lun(disk_device *device)
172{
173	ASSERT_LOCKED_RECURSIVE(&device->io_lock);
174
175	uint8 result = 0;
176	size_t actualLength = 0;
177
178	// devices that do not support multiple LUNs may stall this request
179	if (gUSBModule->send_request(device->device, USB_REQTYPE_INTERFACE_IN
180		| USB_REQTYPE_CLASS, USB_MASSBULK_REQUEST_GET_MAX_LUN, 0x0000,
181		device->interface, 1, &result, &actualLength) != B_OK
182			|| actualLength != 1) {
183		return 0;
184	}
185
186	if (result > MAX_LOGICAL_UNIT_NUMBER) {
187		// invalid max lun
188		return 0;
189	}
190
191	return result;
192}
193
194
195static void
196usb_disk_clear_halt(usb_pipe pipe)
197{
198	gUSBModule->cancel_queued_transfers(pipe);
199	gUSBModule->clear_feature(pipe, USB_FEATURE_ENDPOINT_HALT);
200}
201
202
203void
204usb_disk_reset_recovery(disk_device *device, err_act *_action)
205{
206	TRACE("reset recovery\n");
207	ASSERT_LOCKED_RECURSIVE(&device->io_lock);
208
209	usb_disk_mass_storage_reset(device);
210	usb_disk_clear_halt(device->bulk_in);
211	usb_disk_clear_halt(device->bulk_out);
212	if (device->is_ufi)
213		usb_disk_clear_halt(device->interrupt);
214
215	if (_action != NULL)
216		*_action = err_act_retry;
217}
218
219
220struct transfer_data {
221	union {
222		physical_entry* phys_vecs;
223		iovec* vecs;
224	};
225	uint32 vec_count = 0;
226	bool physical = false;
227};
228
229
230static status_t
231usb_disk_transfer_data(disk_device *device, bool directionIn, const transfer_data& data)
232{
233	status_t result;
234	if (data.physical) {
235		result = gUSBModule->queue_bulk_v_physical(
236			directionIn ? device->bulk_in : device->bulk_out,
237			data.phys_vecs, data.vec_count, usb_disk_callback, device);
238	} else {
239		result = gUSBModule->queue_bulk_v(
240			directionIn ? device->bulk_in : device->bulk_out,
241			data.vecs, data.vec_count, usb_disk_callback, device);
242	}
243	if (result != B_OK) {
244		TRACE_ALWAYS("failed to queue data transfer: %s\n", strerror(result));
245		return result;
246	}
247
248	mutex_unlock(&device->lock);
249	do {
250		result = acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT,
251			10 * 1000 * 1000);
252		if (result == B_TIMED_OUT) {
253			// Cancel the transfer and collect the sem that should now be
254			// released through the callback on cancel. Handling of device
255			// reset is done in usb_disk_operation() when it detects that
256			// the transfer failed.
257			gUSBModule->cancel_queued_transfers(directionIn ? device->bulk_in
258				: device->bulk_out);
259			acquire_sem_etc(device->notify, 1, B_RELATIVE_TIMEOUT, 0);
260		}
261	} while (result == B_INTERRUPTED);
262	mutex_lock(&device->lock);
263
264	if (result != B_OK) {
265		TRACE_ALWAYS("acquire_sem failed while waiting for data transfer: %s\n",
266			strerror(result));
267		return result;
268	}
269
270	return B_OK;
271}
272
273
274static status_t
275usb_disk_transfer_data(disk_device *device, bool directionIn,
276	void* buffer, size_t dataLength)
277{
278	iovec vec;
279	vec.iov_base = buffer;
280	vec.iov_len = dataLength;
281
282	struct transfer_data data;
283	data.vecs = &vec;
284	data.vec_count = 1;
285
286	return usb_disk_transfer_data(device, directionIn, data);
287}
288
289
290static void
291callback_interrupt(void* cookie, int32 status, void* data, size_t length)
292{
293	disk_device* device = (disk_device*)cookie;
294	// We release the lock even if the interrupt is invalid. This way there
295	// is at least a chance for the driver to terminate properly.
296	release_sem(device->interruptLock);
297
298	if (length != 2) {
299		TRACE_ALWAYS("interrupt of length %" B_PRIuSIZE "! (expected 2)\n",
300			length);
301		// In this case we do not reschedule the interrupt. This means the
302		// driver will be locked. The interrupt should perhaps be scheduled
303		// when starting a transfer instead. But getting there means something
304		// is really broken, so...
305		return;
306	}
307
308	// Reschedule the interrupt for next time
309	gUSBModule->queue_interrupt(device->interrupt, device->interruptBuffer, 2,
310		callback_interrupt, cookie);
311}
312
313
314static status_t
315receive_csw_interrupt(disk_device *device,
316	interrupt_status_wrapper *status)
317{
318	TRACE("Waiting for result...\n");
319
320	gUSBModule->queue_interrupt(device->interrupt,
321			device->interruptBuffer, 2, callback_interrupt, device);
322
323	acquire_sem(device->interruptLock);
324
325	status->status = device->interruptBuffer[0];
326	status->misc = device->interruptBuffer[1];
327
328	return B_OK;
329}
330
331
332static status_t
333receive_csw_bulk(disk_device *device,
334	usb_massbulk_command_status_wrapper *status)
335{
336	status_t result = usb_disk_transfer_data(device, true, status,
337		sizeof(usb_massbulk_command_status_wrapper));
338	if (result != B_OK)
339		return result;
340
341	if (device->status != B_OK
342			|| device->actual_length
343			!= sizeof(usb_massbulk_command_status_wrapper)) {
344		// receiving the command status wrapper failed
345		return B_ERROR;
346	}
347
348	return B_OK;
349}
350
351
352status_t
353usb_disk_operation_interrupt(device_lun *lun, uint8* operation,
354	const transfer_data& data, size_t *dataLength,
355	bool directionIn, err_act *_action)
356{
357	TRACE("operation: lun: %u; op: 0x%x; data: %p; dlen: %p (%lu); in: %c\n",
358		lun->logical_unit_number, operation[0], data.vecs, dataLength,
359		dataLength ? *dataLength : 0, directionIn ? 'y' : 'n');
360	ASSERT_LOCKED_RECURSIVE(&lun->device->io_lock);
361
362	disk_device* device = lun->device;
363
364	// Step 1 : send the SCSI operation as a class specific request
365	size_t actualLength = 12;
366	status_t result = gUSBModule->send_request(device->device,
367		USB_REQTYPE_CLASS | USB_REQTYPE_INTERFACE_OUT, 0 /*request*/,
368		0/*value*/, device->interface/*index*/, 12, operation, &actualLength);
369
370	if (result != B_OK || actualLength != 12) {
371		TRACE("Command stage: wrote %ld bytes (error: %s)\n",
372			actualLength, strerror(result));
373
374		// There was an error, we have to do a request sense to reset the device
375		if (operation[0] != SCSI_REQUEST_SENSE_6) {
376			usb_disk_request_sense(lun, _action);
377		}
378		return result;
379	}
380
381	// Step 2 : data phase : send or receive data
382	size_t transferedData = 0;
383	if (data.vec_count != 0) {
384		// we have data to transfer in a data stage
385		result = usb_disk_transfer_data(device, directionIn, data);
386		if (result != B_OK) {
387			TRACE("Error %s in data phase\n", strerror(result));
388			return result;
389		}
390
391		transferedData = device->actual_length;
392		if (device->status != B_OK || transferedData != *dataLength) {
393			// sending or receiving of the data failed
394			if (device->status == B_DEV_STALLED) {
395				TRACE("stall while transfering data\n");
396				usb_disk_clear_halt(directionIn ? device->bulk_in : device->bulk_out);
397			} else {
398				TRACE_ALWAYS("sending or receiving of the data failed\n");
399				usb_disk_reset_recovery(device, _action);
400				return B_IO_ERROR;
401			}
402		}
403	}
404
405	// step 3 : wait for the device to send the interrupt ACK
406	if (operation[0] != SCSI_REQUEST_SENSE_6) {
407		interrupt_status_wrapper status;
408		result =  receive_csw_interrupt(device, &status);
409		if (result != B_OK) {
410			// in case of a stall or error clear the stall and try again
411			TRACE("Error receiving interrupt: %s. Retrying...\n",
412				strerror(result));
413			usb_disk_clear_halt(device->bulk_in);
414			result = receive_csw_interrupt(device, &status);
415		}
416
417		if (result != B_OK) {
418			TRACE_ALWAYS("receiving the command status interrupt failed\n");
419			usb_disk_reset_recovery(device, _action);
420			return result;
421		}
422
423		// wait for the device to finish the operation.
424		result = usb_disk_request_sense(lun, _action);
425	}
426	return result;
427}
428
429
430status_t
431usb_disk_operation_bulk(device_lun *lun, uint8 *operation, size_t operationLength,
432	const transfer_data& data, size_t *dataLength,
433	bool directionIn, err_act *_action)
434{
435	TRACE("operation: lun: %u; op: %u; data: %p; dlen: %p (%lu); in: %c\n",
436		lun->logical_unit_number, operation[0],
437		data.vecs, dataLength, dataLength ? *dataLength : 0,
438		directionIn ? 'y' : 'n');
439	ASSERT_LOCKED_RECURSIVE(&lun->device->io_lock);
440
441	disk_device *device = lun->device;
442	usb_massbulk_command_block_wrapper command;
443	command.signature = USB_MASSBULK_CBW_SIGNATURE;
444	command.tag = device->current_tag++;
445	command.data_transfer_length = (dataLength != NULL ? *dataLength : 0);
446	command.flags = (directionIn ? USB_MASSBULK_CBW_DATA_INPUT
447		: USB_MASSBULK_CBW_DATA_OUTPUT);
448	command.lun = lun->logical_unit_number;
449	command.command_block_length
450		= device->is_atapi ? ATAPI_COMMAND_LENGTH : operationLength;
451	memset(command.command_block, 0, sizeof(command.command_block));
452	memcpy(command.command_block, operation, operationLength);
453
454	status_t result = usb_disk_transfer_data(device, false, &command,
455		sizeof(usb_massbulk_command_block_wrapper));
456	if (result != B_OK)
457		return result;
458
459	if (device->status != B_OK ||
460		device->actual_length != sizeof(usb_massbulk_command_block_wrapper)) {
461		// sending the command block wrapper failed
462		TRACE_ALWAYS("sending the command block wrapper failed: %s\n",
463			strerror(device->status));
464		usb_disk_reset_recovery(device, _action);
465		return B_IO_ERROR;
466	}
467
468	size_t transferedData = 0;
469	if (data.vec_count != 0) {
470		// we have data to transfer in a data stage
471		result = usb_disk_transfer_data(device, directionIn, data);
472		if (result != B_OK)
473			return result;
474
475		transferedData = device->actual_length;
476		if (device->status != B_OK || transferedData != *dataLength) {
477			// sending or receiving of the data failed
478			if (device->status == B_DEV_STALLED) {
479				TRACE("stall while transfering data\n");
480				usb_disk_clear_halt(directionIn ? device->bulk_in : device->bulk_out);
481			} else {
482				TRACE_ALWAYS("sending or receiving of the data failed: %s\n",
483					strerror(device->status));
484				usb_disk_reset_recovery(device, _action);
485				return B_IO_ERROR;
486			}
487		}
488	}
489
490	usb_massbulk_command_status_wrapper status;
491	result =  receive_csw_bulk(device, &status);
492	if (result != B_OK) {
493		// in case of a stall or error clear the stall and try again
494		usb_disk_clear_halt(device->bulk_in);
495		result = receive_csw_bulk(device, &status);
496	}
497
498	if (result != B_OK) {
499		TRACE_ALWAYS("receiving the command status wrapper failed: %s\n",
500			strerror(result));
501		usb_disk_reset_recovery(device, _action);
502		return result;
503	}
504
505	if (status.signature != USB_MASSBULK_CSW_SIGNATURE
506		|| status.tag != command.tag) {
507		// the command status wrapper is not valid
508		TRACE_ALWAYS("command status wrapper is not valid: %#" B_PRIx32 "\n",
509			status.signature);
510		usb_disk_reset_recovery(device, _action);
511		return B_ERROR;
512	}
513
514	switch (status.status) {
515		case USB_MASSBULK_CSW_STATUS_COMMAND_PASSED:
516		case USB_MASSBULK_CSW_STATUS_COMMAND_FAILED:
517		{
518			// The residue from "status.data_residue" is not maintained
519			// correctly by some devices, so calculate it instead.
520			uint32 residue = command.data_transfer_length - transferedData;
521
522			if (dataLength != NULL) {
523				*dataLength -= residue;
524				if (transferedData < *dataLength) {
525					TRACE_ALWAYS("less data transfered than indicated: %"
526						B_PRIuSIZE " vs. %" B_PRIuSIZE "\n", transferedData,
527						*dataLength);
528					*dataLength = transferedData;
529				}
530			}
531
532			if (status.status == USB_MASSBULK_CSW_STATUS_COMMAND_PASSED) {
533				// the operation is complete and has succeeded
534				return B_OK;
535			} else {
536				if (operation[0] == SCSI_REQUEST_SENSE_6)
537					return B_ERROR;
538
539				// the operation is complete but has failed at the SCSI level
540				if (operation[0] != SCSI_TEST_UNIT_READY_6) {
541					TRACE_ALWAYS("operation %#" B_PRIx8
542						" failed at the SCSI level\n", operation[0]);
543				}
544
545				result = usb_disk_request_sense(lun, _action);
546				return result == B_OK ? B_ERROR : result;
547			}
548		}
549
550		case USB_MASSBULK_CSW_STATUS_PHASE_ERROR:
551		{
552			// a protocol or device error occured
553			TRACE_ALWAYS("phase error in operation %#" B_PRIx8 "\n",
554				operation[0]);
555			usb_disk_reset_recovery(device, _action);
556			return B_ERROR;
557		}
558
559		default:
560		{
561			// command status wrapper is not meaningful
562			TRACE_ALWAYS("command status wrapper has invalid status\n");
563			usb_disk_reset_recovery(device, _action);
564			return B_ERROR;
565		}
566	}
567}
568
569
570static status_t
571usb_disk_operation(device_lun *lun, uint8* operation, size_t opLength,
572	const transfer_data& data, size_t *dataLength,
573	bool directionIn, err_act *_action = NULL)
574{
575	if (lun->device->is_ufi) {
576		return usb_disk_operation_interrupt(lun, operation,
577			data, dataLength, directionIn, _action);
578	} else {
579		return usb_disk_operation_bulk(lun, operation, opLength,
580			data, dataLength, directionIn, _action);
581	}
582}
583
584
585static status_t
586usb_disk_operation(device_lun *lun, uint8* operation, size_t opLength,
587	void *buffer, size_t *dataLength,
588	bool directionIn, err_act *_action = NULL)
589{
590	iovec vec;
591	vec.iov_base = buffer;
592
593	struct transfer_data data;
594	data.vecs = &vec;
595
596	if (dataLength != NULL && *dataLength != 0) {
597		vec.iov_len = *dataLength;
598		data.vec_count = 1;
599	} else {
600		vec.iov_len = 0;
601		data.vec_count = 0;
602	}
603
604	return usb_disk_operation(lun, operation, opLength,
605		data, dataLength, directionIn, _action);
606}
607
608
609//
610//#pragma mark - Helper/Convenience Functions
611//
612
613
614status_t
615usb_disk_send_diagnostic(device_lun *lun)
616{
617	uint8 commandBlock[12];
618	memset(commandBlock, 0, sizeof(commandBlock));
619
620	commandBlock[0] = SCSI_SEND_DIAGNOSTIC;
621	commandBlock[1] = (lun->logical_unit_number << 5) | 4;
622
623	status_t result = usb_disk_operation(lun, commandBlock, 6, NULL, NULL, false);
624
625	int retry = 100;
626	err_act action = err_act_ok;
627	while (result == B_DEV_NO_MEDIA && retry > 0) {
628		snooze(10000);
629		result = usb_disk_request_sense(lun, &action);
630		retry--;
631	}
632
633	if (result != B_OK)
634		TRACE("Send Diagnostic failed: %s\n", strerror(result));
635	return result;
636}
637
638
639status_t
640usb_disk_request_sense(device_lun *lun, err_act *_action)
641{
642	size_t dataLength = sizeof(scsi_request_sense_6_parameter);
643	uint8 commandBlock[12];
644	memset(commandBlock, 0, sizeof(commandBlock));
645
646	commandBlock[0] = SCSI_REQUEST_SENSE_6;
647	commandBlock[1] = lun->logical_unit_number << 5;
648	commandBlock[2] = 0; // page code
649	commandBlock[4] = dataLength;
650
651	scsi_request_sense_6_parameter parameter;
652	status_t result = B_ERROR;
653	for (uint32 tries = 0; tries < 3; tries++) {
654		result = usb_disk_operation(lun, commandBlock, 6, &parameter,
655			&dataLength, true);
656		if (result != B_TIMED_OUT)
657			break;
658		snooze(100000);
659	}
660	if (result != B_OK) {
661		TRACE_ALWAYS("getting request sense data failed: %s\n",
662			strerror(result));
663		return result;
664	}
665
666	const char *label = NULL;
667	err_act action = err_act_fail;
668	status_t status = B_ERROR;
669	scsi_get_sense_asc_info((parameter.additional_sense_code << 8)
670		| parameter.additional_sense_code_qualifier, &label, &action,
671		&status);
672
673	if (parameter.sense_key > SCSI_SENSE_KEY_NOT_READY
674		&& parameter.sense_key != SCSI_SENSE_KEY_UNIT_ATTENTION) {
675		TRACE_ALWAYS("request_sense: key: 0x%02x; asc: 0x%02x; ascq: "
676			"0x%02x; %s\n", parameter.sense_key,
677			parameter.additional_sense_code,
678			parameter.additional_sense_code_qualifier,
679			label ? label : "(unknown)");
680	}
681
682	if ((parameter.additional_sense_code == 0
683			&& parameter.additional_sense_code_qualifier == 0)
684		|| label == NULL) {
685		scsi_get_sense_key_info(parameter.sense_key, &label, &action, &status);
686	}
687
688	if (status == B_DEV_MEDIA_CHANGED) {
689		lun->media_changed = true;
690		lun->media_present = true;
691	} else if (parameter.sense_key == SCSI_SENSE_KEY_UNIT_ATTENTION
692		&& status != B_DEV_NO_MEDIA) {
693		lun->media_present = true;
694	} else if (status == B_DEV_NOT_READY) {
695		lun->media_present = false;
696		usb_disk_reset_capacity(lun);
697	}
698
699	if (_action != NULL)
700		*_action = action;
701
702	return status;
703}
704
705
706status_t
707usb_disk_mode_sense(device_lun *lun)
708{
709	size_t dataLength = sizeof(scsi_mode_sense_6_parameter);
710
711	uint8 commandBlock[12];
712	memset(commandBlock, 0, sizeof(commandBlock));
713
714	commandBlock[0] = SCSI_MODE_SENSE_6;
715	commandBlock[1] = SCSI_MODE_PAGE_DEVICE_CONFIGURATION;
716	commandBlock[2] = 0; // Current values
717	commandBlock[3] = dataLength >> 8;
718	commandBlock[4] = dataLength;
719
720	scsi_mode_sense_6_parameter parameter;
721	status_t result = usb_disk_operation(lun, commandBlock, 6,
722		&parameter, &dataLength, true);
723	if (result != B_OK) {
724		TRACE_ALWAYS("getting mode sense data failed: %s\n", strerror(result));
725		return result;
726	}
727
728	lun->write_protected
729		= (parameter.device_specific & SCSI_DEVICE_SPECIFIC_WRITE_PROTECT)
730			!= 0;
731	TRACE_ALWAYS("write protected: %s\n", lun->write_protected ? "yes" : "no");
732	return B_OK;
733}
734
735
736status_t
737usb_disk_test_unit_ready(device_lun *lun, err_act *_action)
738{
739	// if unsupported we assume the unit is fixed and therefore always ok
740	if (lun->device->is_ufi || !lun->device->tur_supported)
741		return B_OK;
742
743	status_t result = B_OK;
744	uint8 commandBlock[12];
745	memset(commandBlock, 0, sizeof(commandBlock));
746
747	if (lun->device->is_atapi) {
748		commandBlock[0] = SCSI_START_STOP_UNIT_6;
749		commandBlock[1] = lun->logical_unit_number << 5;
750		commandBlock[2] = 0;
751		commandBlock[3] = 0;
752		commandBlock[4] = 1;
753
754		result = usb_disk_operation(lun, commandBlock, 6, NULL, NULL, false,
755			_action);
756	} else {
757		commandBlock[0] = SCSI_TEST_UNIT_READY_6;
758		commandBlock[1] = lun->logical_unit_number << 5;
759		commandBlock[2] = 0;
760		commandBlock[3] = 0;
761		commandBlock[4] = 0;
762		result = usb_disk_operation(lun, commandBlock, 6, NULL, NULL, true,
763			_action);
764	}
765
766	if (result == B_DEV_INVALID_IOCTL) {
767		lun->device->tur_supported = false;
768		return B_OK;
769	}
770
771	return result;
772}
773
774
775status_t
776usb_disk_inquiry(device_lun *lun)
777{
778	size_t dataLength = sizeof(scsi_inquiry_6_parameter);
779
780	uint8 commandBlock[12];
781	memset(commandBlock, 0, sizeof(commandBlock));
782
783	commandBlock[0] = SCSI_INQUIRY_6;
784	commandBlock[1] = lun->logical_unit_number << 5;
785	commandBlock[2] = 0; // page code
786	commandBlock[4] = dataLength;
787
788	scsi_inquiry_6_parameter parameter;
789	status_t result = B_ERROR;
790	err_act action = err_act_ok;
791	for (uint32 tries = 0; tries < 3; tries++) {
792		result = usb_disk_operation(lun, commandBlock, 6, &parameter,
793			&dataLength, true, &action);
794		if (result == B_OK || (action != err_act_retry
795				&& action != err_act_many_retries)) {
796			break;
797		}
798	}
799	if (result != B_OK) {
800		TRACE_ALWAYS("getting inquiry data failed: %s\n", strerror(result));
801		lun->device_type = B_DISK;
802		lun->removable = true;
803		return result;
804	}
805
806	TRACE("peripherial_device_type  0x%02x\n",
807		parameter.peripherial_device_type);
808	TRACE("peripherial_qualifier    0x%02x\n",
809		parameter.peripherial_qualifier);
810	TRACE("removable_medium         %s\n",
811		parameter.removable_medium ? "yes" : "no");
812	TRACE("version                  0x%02x\n", parameter.version);
813	TRACE("response_data_format     0x%02x\n", parameter.response_data_format);
814	TRACE_ALWAYS("vendor_identification    \"%.8s\"\n",
815		parameter.vendor_identification);
816	TRACE_ALWAYS("product_identification   \"%.16s\"\n",
817		parameter.product_identification);
818	TRACE_ALWAYS("product_revision_level   \"%.4s\"\n",
819		parameter.product_revision_level);
820
821	memcpy(lun->vendor_name, parameter.vendor_identification,
822		MIN(sizeof(lun->vendor_name), sizeof(parameter.vendor_identification)));
823	memcpy(lun->product_name, parameter.product_identification,
824		MIN(sizeof(lun->product_name),
825			sizeof(parameter.product_identification)));
826	memcpy(lun->product_revision, parameter.product_revision_level,
827		MIN(sizeof(lun->product_revision),
828			sizeof(parameter.product_revision_level)));
829
830	lun->device_type = parameter.peripherial_device_type; /* 1:1 mapping */
831	lun->removable = (parameter.removable_medium == 1);
832	return B_OK;
833}
834
835
836status_t
837usb_disk_reset_capacity(device_lun *lun)
838{
839	lun->block_size = 512;
840	lun->block_count = 0;
841	return B_OK;
842}
843
844
845static status_t
846usb_disk_update_capacity_16(device_lun *lun)
847{
848	size_t dataLength = sizeof(scsi_read_capacity_16_parameter);
849	scsi_read_capacity_16_parameter parameter;
850	status_t result = B_ERROR;
851	err_act action = err_act_ok;
852
853	uint8 commandBlock[16];
854	memset(commandBlock, 0, sizeof(commandBlock));
855
856	commandBlock[0] = SCSI_SERVICE_ACTION_IN;
857	commandBlock[1] = SCSI_SAI_READ_CAPACITY_16;
858	commandBlock[10] = dataLength >> 24;
859	commandBlock[11] = dataLength >> 16;
860	commandBlock[12] = dataLength >> 8;
861	commandBlock[13] = dataLength;
862
863	// Retry reading the capacity up to three times. The first try might only
864	// yield a unit attention telling us that the device or media status
865	// changed, which is more or less expected if it is the first operation
866	// on the device or the device only clears the unit atention for capacity
867	// reads.
868	for (int32 i = 0; i < 5; i++) {
869		result = usb_disk_operation(lun, commandBlock, 16, &parameter,
870			&dataLength, true, &action);
871
872		if (result == B_OK || (action != err_act_retry
873				&& action != err_act_many_retries)) {
874			break;
875		}
876	}
877
878	if (result != B_OK) {
879		TRACE_ALWAYS("failed to update capacity: %s\n", strerror(result));
880		lun->media_present = false;
881		lun->media_changed = false;
882		usb_disk_reset_capacity(lun);
883		return result;
884	}
885
886	lun->media_present = true;
887	lun->media_changed = false;
888	lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length);
889	lun->physical_block_size = lun->block_size;
890	lun->block_count =
891		B_BENDIAN_TO_HOST_INT64(parameter.last_logical_block_address) + 1;
892	return B_OK;
893}
894
895
896status_t
897usb_disk_update_capacity(device_lun *lun)
898{
899	size_t dataLength = sizeof(scsi_read_capacity_10_parameter);
900	scsi_read_capacity_10_parameter parameter;
901	status_t result = B_ERROR;
902	err_act action = err_act_ok;
903
904	uint8 commandBlock[12];
905	memset(commandBlock, 0, sizeof(commandBlock));
906
907	commandBlock[0] = SCSI_READ_CAPACITY_10;
908	commandBlock[1] = lun->logical_unit_number << 5;
909
910	// Retry reading the capacity up to three times. The first try might only
911	// yield a unit attention telling us that the device or media status
912	// changed, which is more or less expected if it is the first operation
913	// on the device or the device only clears the unit atention for capacity
914	// reads.
915	for (int32 i = 0; i < 5; i++) {
916		result = usb_disk_operation(lun, commandBlock, 10, &parameter,
917			&dataLength, true, &action);
918
919		if (result == B_OK || (action != err_act_retry
920				&& action != err_act_many_retries)) {
921			break;
922		}
923
924		// In some cases, it's best to wait a little for the device to settle
925		// before retrying.
926		if (lun->device->is_ufi && (result == B_DEV_NO_MEDIA
927				|| result == B_TIMED_OUT || result == B_DEV_STALLED))
928			snooze(10000);
929	}
930
931	if (result != B_OK) {
932		TRACE_ALWAYS("failed to update capacity: %s\n", strerror(result));
933		lun->media_present = false;
934		lun->media_changed = false;
935		usb_disk_reset_capacity(lun);
936		return result;
937	}
938
939	lun->media_present = true;
940	lun->media_changed = false;
941	lun->block_size = B_BENDIAN_TO_HOST_INT32(parameter.logical_block_length);
942	lun->physical_block_size = lun->block_size;
943	lun->block_count =
944		B_BENDIAN_TO_HOST_INT32(parameter.last_logical_block_address) + 1;
945	if (lun->block_count == 0) {
946		// try SCSI_READ_CAPACITY_16
947		result = usb_disk_update_capacity_16(lun);
948		if (result != B_OK)
949			return result;
950	}
951
952	// ensure we have a DMAResource for this block_size
953	if (get_dma_resource(lun->device, lun->block_size) == NULL) {
954		dma_restrictions restrictions = {};
955		restrictions.max_transfer_size = (lun->block_size * MAX_IO_BLOCKS);
956
957		DMAResource* dmaResource = new DMAResource;
958		result = dmaResource->Init(restrictions, lun->block_size, 1, 1);
959		if (result != B_OK)
960			return result;
961
962		lun->device->dma_resources.Add(dmaResource);
963	}
964
965	return B_OK;
966}
967
968
969status_t
970usb_disk_synchronize(device_lun *lun, bool force)
971{
972	if (lun->device->is_ufi) {
973		// UFI use interrupt because it runs all commands immediately, and
974		// tells us when its done. There is no cache involved in that case,
975		// so nothing to synchronize.
976		return B_UNSUPPORTED;
977	}
978
979	if (lun->device->sync_support == 0) {
980		// this device reported an illegal request when syncing or repeatedly
981		// returned an other error, it apparently does not support syncing...
982		return B_UNSUPPORTED;
983	}
984
985	if (!lun->should_sync && !force)
986		return B_OK;
987
988	uint8 commandBlock[12];
989	memset(commandBlock, 0, sizeof(commandBlock));
990
991	commandBlock[0] = SCSI_SYNCHRONIZE_CACHE_10;
992	commandBlock[1] = lun->logical_unit_number << 5;
993
994	status_t result = usb_disk_operation(lun, commandBlock, 10,
995		NULL, NULL, false);
996
997	if (result == B_OK) {
998		lun->device->sync_support = SYNC_SUPPORT_RELOAD;
999		lun->should_sync = false;
1000		return B_OK;
1001	}
1002
1003	if (result == B_DEV_INVALID_IOCTL)
1004		lun->device->sync_support = 0;
1005	else
1006		lun->device->sync_support--;
1007
1008	return result;
1009}
1010
1011
1012//
1013//#pragma mark - Device Attach/Detach Notifications and Callback
1014//
1015
1016
1017static void
1018usb_disk_callback(void *cookie, status_t status, void *data,
1019	size_t actualLength)
1020{
1021	//TRACE("callback()\n");
1022	disk_device *device = (disk_device *)cookie;
1023	device->status = status;
1024	device->actual_length = actualLength;
1025	release_sem(device->notify);
1026}
1027
1028
1029static status_t
1030usb_disk_attach(device_node *node, usb_device newDevice, void **cookie)
1031{
1032	TRACE("device_added(0x%08" B_PRIx32 ")\n", newDevice);
1033	disk_device *device = new(std::nothrow) disk_device;
1034	recursive_lock_lock(&device->io_lock);
1035	mutex_lock(&device->lock);
1036
1037	device->node = node;
1038	device->device = newDevice;
1039	device->removed = false;
1040	device->open_count = 0;
1041	device->interface = 0xff;
1042	device->current_tag = 0;
1043	device->sync_support = SYNC_SUPPORT_RELOAD;
1044	device->tur_supported = true;
1045	device->is_atapi = false;
1046	device->is_ufi = false;
1047	device->luns = NULL;
1048
1049	// scan through the interfaces to find our bulk-only data interface
1050	const usb_configuration_info *configuration
1051		= gUSBModule->get_configuration(newDevice);
1052	if (configuration == NULL) {
1053		delete device;
1054		return B_ERROR;
1055	}
1056
1057	for (size_t i = 0; i < configuration->interface_count; i++) {
1058		usb_interface_info *interface = configuration->interface[i].active;
1059		if (interface == NULL)
1060			continue;
1061
1062		if (interface->descr->interface_class == USB_MASS_STORAGE_DEVICE_CLASS
1063			&& (((interface->descr->interface_subclass == 0x06 /* SCSI */
1064					|| interface->descr->interface_subclass == 0x02 /* ATAPI */
1065					|| interface->descr->interface_subclass == 0x05 /* ATAPI */)
1066				&& interface->descr->interface_protocol == 0x50 /* bulk-only */)
1067			|| (interface->descr->interface_subclass == 0x04 /* UFI */
1068				&& interface->descr->interface_protocol == 0x00))) {
1069
1070			bool hasIn = false;
1071			bool hasOut = false;
1072			bool hasInt = false;
1073			for (size_t j = 0; j < interface->endpoint_count; j++) {
1074				usb_endpoint_info *endpoint = &interface->endpoint[j];
1075				if (endpoint == NULL)
1076					continue;
1077
1078				if (!hasIn && (endpoint->descr->endpoint_address
1079					& USB_ENDPOINT_ADDR_DIR_IN) != 0
1080					&& endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
1081					device->bulk_in = endpoint->handle;
1082					hasIn = true;
1083				} else if (!hasOut && (endpoint->descr->endpoint_address
1084					& USB_ENDPOINT_ADDR_DIR_IN) == 0
1085					&& endpoint->descr->attributes == USB_ENDPOINT_ATTR_BULK) {
1086					device->bulk_out = endpoint->handle;
1087					hasOut = true;
1088				} else if (!hasInt && (endpoint->descr->endpoint_address
1089					& USB_ENDPOINT_ADDR_DIR_IN)
1090					&& endpoint->descr->attributes
1091					== USB_ENDPOINT_ATTR_INTERRUPT) {
1092					device->interrupt = endpoint->handle;
1093					hasInt = true;
1094				}
1095
1096				if (hasIn && hasOut && hasInt)
1097					break;
1098			}
1099
1100			if (!(hasIn && hasOut)) {
1101				// Missing one of the required endpoints, try next interface
1102				continue;
1103			}
1104
1105			device->interface = interface->descr->interface_number;
1106			device->is_atapi = interface->descr->interface_subclass != 0x06
1107				&& interface->descr->interface_subclass != 0x04;
1108			device->is_ufi = interface->descr->interface_subclass == 0x04;
1109
1110			if (device->is_ufi && !hasInt) {
1111				// UFI without interrupt endpoint is not possible.
1112				continue;
1113			}
1114			break;
1115		}
1116	}
1117
1118	if (device->interface == 0xff) {
1119		TRACE_ALWAYS("no valid bulk-only or CBI interface found\n");
1120		delete device;
1121		return B_ERROR;
1122	}
1123
1124	device->notify = create_sem(0, "usb_disk callback notify");
1125	if (device->notify < B_OK) {
1126		status_t result = device->notify;
1127		delete device;
1128		return result;
1129	}
1130
1131	if (device->is_ufi) {
1132		device->interruptLock = create_sem(0, "usb_disk interrupt lock");
1133		if (device->interruptLock < B_OK) {
1134			status_t result = device->interruptLock;
1135			delete device;
1136			return result;
1137		}
1138	}
1139
1140	device->lun_count = usb_disk_get_max_lun(device) + 1;
1141	device->luns = (device_lun **)malloc(device->lun_count
1142		* sizeof(device_lun *));
1143	for (uint8 i = 0; i < device->lun_count; i++)
1144		device->luns[i] = NULL;
1145
1146	status_t result = B_OK;
1147
1148	TRACE_ALWAYS("device reports a lun count of %d\n", device->lun_count);
1149	for (uint8 i = 0; i < device->lun_count; i++) {
1150		// create the individual luns present on this device
1151		device_lun *lun = (device_lun *)malloc(sizeof(device_lun));
1152		if (lun == NULL) {
1153			result = B_NO_MEMORY;
1154			break;
1155		}
1156
1157		device->luns[i] = lun;
1158		lun->device = device;
1159		lun->logical_unit_number = i;
1160		lun->should_sync = false;
1161		lun->media_present = true;
1162		lun->media_changed = true;
1163
1164		memset(lun->vendor_name, 0, sizeof(lun->vendor_name));
1165		memset(lun->product_name, 0, sizeof(lun->product_name));
1166		memset(lun->product_revision, 0, sizeof(lun->product_revision));
1167
1168		usb_disk_reset_capacity(lun);
1169
1170		// initialize this lun
1171		result = usb_disk_inquiry(lun);
1172
1173		if (device->is_ufi) {
1174			// Reset the device
1175			// If we don't do it all the other commands except inquiry and send
1176			// diagnostics will be stalled.
1177			result = usb_disk_send_diagnostic(lun);
1178		}
1179
1180		err_act action = err_act_ok;
1181		for (uint32 tries = 0; tries < 8; tries++) {
1182			TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " begin\n",
1183				i, tries);
1184			status_t ready = usb_disk_test_unit_ready(lun, &action);
1185			if (ready == B_OK || ready == B_DEV_NO_MEDIA
1186				|| ready == B_DEV_MEDIA_CHANGED) {
1187				if (lun->device_type == B_CD)
1188					lun->write_protected = true;
1189				// TODO: check for write protection; disabled since some
1190				// devices lock up when getting the mode sense
1191				else if (/*usb_disk_mode_sense(lun) != B_OK*/true)
1192					lun->write_protected = false;
1193
1194				TRACE("usb lun %" B_PRIu8 " ready. write protected = %c%s\n", i,
1195					lun->write_protected ? 'y' : 'n',
1196					ready == B_DEV_NO_MEDIA ? " (no media inserted)" : "");
1197
1198				break;
1199			}
1200			TRACE("usb lun %" B_PRIu8 " inquiry attempt %" B_PRIu32 " failed\n",
1201				i, tries);
1202			if (action != err_act_retry && action != err_act_many_retries)
1203				break;
1204			bigtime_t snoozeTime = 1000000 * tries;
1205			TRACE("snoozing %" B_PRIu64 " microseconds for usb lun\n",
1206				snoozeTime);
1207			snooze(snoozeTime);
1208		}
1209
1210		if (result != B_OK)
1211			break;
1212	}
1213
1214	if (result != B_OK) {
1215		TRACE_ALWAYS("failed to initialize logical units: %s\n",
1216			strerror(result));
1217		usb_disk_free_device_and_luns(device);
1218		return result;
1219	}
1220
1221	mutex_unlock(&device->lock);
1222	recursive_lock_unlock(&device->io_lock);
1223
1224	TRACE("new device: 0x%p\n", device);
1225	*cookie = (void *)device;
1226	return B_OK;
1227}
1228
1229
1230static void
1231usb_disk_device_removed(void *cookie)
1232{
1233	TRACE("device_removed(0x%p)\n", cookie);
1234	disk_device *device = (disk_device *)cookie;
1235	mutex_lock(&device->lock);
1236
1237	for (uint8 i = 0; i < device->lun_count; i++) {
1238		// unpublish_device() can call close().
1239		mutex_unlock(&device->lock);
1240		gDeviceManager->unpublish_device(device->node, device->luns[i]->name);
1241		mutex_lock(&device->lock);
1242	}
1243
1244	device->removed = true;
1245	gUSBModule->cancel_queued_transfers(device->bulk_in);
1246	gUSBModule->cancel_queued_transfers(device->bulk_out);
1247	if (device->is_ufi)
1248		gUSBModule->cancel_queued_transfers(device->interrupt);
1249
1250	// At this point, open_count should always be 0 anyway.
1251	if (device->open_count == 0)
1252		usb_disk_free_device_and_luns(device);
1253	else
1254		mutex_unlock(&device->lock);
1255}
1256
1257
1258static bool
1259usb_disk_needs_bounce(device_lun *lun, io_request *request)
1260{
1261	if (!request->Buffer()->IsVirtual())
1262		return true;
1263	if ((request->Offset() % lun->block_size) != 0)
1264		return true;
1265	if ((request->Length() % lun->block_size) != 0)
1266		return true;
1267	if (request->Length() > (lun->block_size * MAX_IO_BLOCKS))
1268		return true;
1269	return false;
1270}
1271
1272
1273static status_t
1274usb_disk_block_read(device_lun *lun, uint64 blockPosition, size_t blockCount,
1275	struct transfer_data data, size_t *length)
1276{
1277	uint8 commandBlock[16];
1278	memset(commandBlock, 0, sizeof(commandBlock));
1279	if (lun->device->is_ufi) {
1280		commandBlock[0] = SCSI_READ_12;
1281		commandBlock[1] = lun->logical_unit_number << 5;
1282		commandBlock[2] = blockPosition >> 24;
1283		commandBlock[3] = blockPosition >> 16;
1284		commandBlock[4] = blockPosition >> 8;
1285		commandBlock[5] = blockPosition;
1286		commandBlock[6] = blockCount >> 24;
1287		commandBlock[7] = blockCount >> 16;
1288		commandBlock[8] = blockCount >> 8;
1289		commandBlock[9] = blockCount;
1290
1291		status_t result = B_OK;
1292		for (int tries = 0; tries < 5; tries++) {
1293			result = usb_disk_operation(lun, commandBlock, 12, data,
1294				length, true);
1295			if (result == B_OK)
1296				break;
1297			else
1298				snooze(10000);
1299		}
1300		return result;
1301	} else if (blockPosition + blockCount < 0x100000000LL && blockCount <= 0x10000) {
1302		commandBlock[0] = SCSI_READ_10;
1303		commandBlock[1] = 0;
1304		commandBlock[2] = blockPosition >> 24;
1305		commandBlock[3] = blockPosition >> 16;
1306		commandBlock[4] = blockPosition >> 8;
1307		commandBlock[5] = blockPosition;
1308		commandBlock[7] = blockCount >> 8;
1309		commandBlock[8] = blockCount;
1310		status_t result = usb_disk_operation(lun, commandBlock, 10,
1311			data, length, true);
1312		return result;
1313	} else {
1314		commandBlock[0] = SCSI_READ_16;
1315		commandBlock[1] = 0;
1316		commandBlock[2] = blockPosition >> 56;
1317		commandBlock[3] = blockPosition >> 48;
1318		commandBlock[4] = blockPosition >> 40;
1319		commandBlock[5] = blockPosition >> 32;
1320		commandBlock[6] = blockPosition >> 24;
1321		commandBlock[7] = blockPosition >> 16;
1322		commandBlock[8] = blockPosition >> 8;
1323		commandBlock[9] = blockPosition;
1324		commandBlock[10] = blockCount >> 24;
1325		commandBlock[11] = blockCount >> 16;
1326		commandBlock[12] = blockCount >> 8;
1327		commandBlock[13] = blockCount;
1328		status_t result = usb_disk_operation(lun, commandBlock, 16,
1329			data, length, true);
1330		return result;
1331	}
1332}
1333
1334
1335static status_t
1336usb_disk_block_write(device_lun *lun, uint64 blockPosition, size_t blockCount,
1337	struct transfer_data data, size_t *length)
1338{
1339	uint8 commandBlock[16];
1340	memset(commandBlock, 0, sizeof(commandBlock));
1341
1342	if (lun->device->is_ufi) {
1343		commandBlock[0] = SCSI_WRITE_12;
1344		commandBlock[1] = lun->logical_unit_number << 5;
1345		commandBlock[2] = blockPosition >> 24;
1346		commandBlock[3] = blockPosition >> 16;
1347		commandBlock[4] = blockPosition >> 8;
1348		commandBlock[5] = blockPosition;
1349		commandBlock[6] = blockCount >> 24;
1350		commandBlock[7] = blockCount >> 16;
1351		commandBlock[8] = blockCount >> 8;
1352		commandBlock[9] = blockCount;
1353
1354		status_t result;
1355		result = usb_disk_operation(lun, commandBlock, 12,
1356			data, length, false);
1357
1358		int retry = 10;
1359		err_act action = err_act_ok;
1360		while (result == B_DEV_NO_MEDIA && retry > 0) {
1361			snooze(10000);
1362			result = usb_disk_request_sense(lun, &action);
1363			retry--;
1364		}
1365
1366		if (result == B_OK)
1367			lun->should_sync = true;
1368		return result;
1369	} else if (blockPosition + blockCount < 0x100000000LL && blockCount <= 0x10000) {
1370		commandBlock[0] = SCSI_WRITE_10;
1371		commandBlock[2] = blockPosition >> 24;
1372		commandBlock[3] = blockPosition >> 16;
1373		commandBlock[4] = blockPosition >> 8;
1374		commandBlock[5] = blockPosition;
1375		commandBlock[7] = blockCount >> 8;
1376		commandBlock[8] = blockCount;
1377		status_t result = usb_disk_operation(lun, commandBlock, 10,
1378			data, length, false);
1379		if (result == B_OK)
1380			lun->should_sync = true;
1381		return result;
1382	} else {
1383		commandBlock[0] = SCSI_WRITE_16;
1384		commandBlock[1] = 0;
1385		commandBlock[2] = blockPosition >> 56;
1386		commandBlock[3] = blockPosition >> 48;
1387		commandBlock[4] = blockPosition >> 40;
1388		commandBlock[5] = blockPosition >> 32;
1389		commandBlock[6] = blockPosition >> 24;
1390		commandBlock[7] = blockPosition >> 16;
1391		commandBlock[8] = blockPosition >> 8;
1392		commandBlock[9] = blockPosition;
1393		commandBlock[10] = blockCount >> 24;
1394		commandBlock[11] = blockCount >> 16;
1395		commandBlock[12] = blockCount >> 8;
1396		commandBlock[13] = blockCount;
1397		status_t result = usb_disk_operation(lun, commandBlock, 16,
1398			data, length, false);
1399		if (result == B_OK)
1400			lun->should_sync = true;
1401		return result;
1402	}
1403}
1404
1405
1406//
1407//#pragma mark - Driver Hooks
1408//
1409
1410
1411static status_t
1412usb_disk_init_device(void* _info, void** _cookie)
1413{
1414	CALLED();
1415	*_cookie = _info;
1416	return B_OK;
1417}
1418
1419
1420static void
1421usb_disk_uninit_device(void* _cookie)
1422{
1423	// Nothing to do.
1424}
1425
1426
1427static status_t
1428usb_disk_open(void *deviceCookie, const char *path, int flags, void **_cookie)
1429{
1430	TRACE("open(%s)\n", path);
1431	if (strncmp(path, DEVICE_NAME_BASE, strlen(DEVICE_NAME_BASE)) != 0)
1432		return B_NAME_NOT_FOUND;
1433
1434	int32 lastPart = 0;
1435	size_t nameLength = strlen(path);
1436	for (int32 i = nameLength - 1; i >= 0; i--) {
1437		if (path[i] == '/') {
1438			lastPart = i;
1439			break;
1440		}
1441	}
1442
1443	char rawName[nameLength + 4];
1444	strncpy(rawName, path, lastPart + 1);
1445	rawName[lastPart + 1] = 0;
1446	strcat(rawName, "raw");
1447
1448	disk_device *device = (disk_device *)deviceCookie;
1449	MutexLocker locker(device->lock);
1450	for (uint8 i = 0; i < device->lun_count; i++) {
1451		device_lun *lun = device->luns[i];
1452		if (strncmp(rawName, lun->name, 32) == 0) {
1453			// found the matching device/lun
1454			if (device->removed)
1455				return B_ERROR;
1456
1457			device->open_count++;
1458			*_cookie = lun;
1459			return B_OK;
1460		}
1461	}
1462
1463	return B_NAME_NOT_FOUND;
1464}
1465
1466
1467static status_t
1468usb_disk_close(void *cookie)
1469{
1470	TRACE("close()\n");
1471	device_lun *lun = (device_lun *)cookie;
1472	disk_device *device = lun->device;
1473
1474	RecursiveLocker ioLocker(device->io_lock);
1475	MutexLocker deviceLocker(device->lock);
1476
1477	if (!device->removed)
1478		usb_disk_synchronize(lun, false);
1479
1480	return B_OK;
1481}
1482
1483
1484static status_t
1485usb_disk_free(void *cookie)
1486{
1487	TRACE("free()\n");
1488
1489	device_lun *lun = (device_lun *)cookie;
1490	disk_device *device = lun->device;
1491	mutex_lock(&device->lock);
1492
1493	device->open_count--;
1494	if (device->open_count == 0 && device->removed) {
1495		// we can simply free the device here as it has been removed from
1496		// the device list in the device removed notification hook
1497		usb_disk_free_device_and_luns(device);
1498	} else {
1499		mutex_unlock(&device->lock);
1500	}
1501
1502	return B_OK;
1503}
1504
1505
1506static inline void
1507normalize_name(char *name, size_t nameLength)
1508{
1509	bool wasSpace = false;
1510	size_t insertIndex = 0;
1511	for (size_t i = 0; i < nameLength; i++) {
1512		bool isSpace = name[i] == ' ';
1513		if (isSpace && wasSpace)
1514			continue;
1515
1516		name[insertIndex++] = name[i];
1517		wasSpace = isSpace;
1518	}
1519
1520	if (insertIndex > 0 && name[insertIndex - 1] == ' ')
1521		insertIndex--;
1522
1523	name[insertIndex] = 0;
1524}
1525
1526
1527static status_t
1528acquire_io_lock(disk_device *device, MutexLocker& locker, RecursiveLocker& ioLocker)
1529{
1530	locker.Unlock();
1531	ioLocker.SetTo(device->io_lock, false, true);
1532	locker.Lock();
1533
1534	if (!locker.IsLocked() || !ioLocker.IsLocked())
1535		return B_ERROR;
1536
1537	if (device->removed)
1538		return B_DEV_NOT_READY;
1539
1540	return B_OK;
1541}
1542
1543
1544static status_t
1545handle_media_change(device_lun *lun, MutexLocker& locker)
1546{
1547	RecursiveLocker ioLocker;
1548	status_t result = acquire_io_lock(lun->device, locker, ioLocker);
1549	if (result != B_OK)
1550		return result;
1551
1552	// It may have been handled while we were waiting for locks.
1553	if (lun->media_changed) {
1554		result = usb_disk_update_capacity(lun);
1555		if (result != B_OK)
1556			return result;
1557	}
1558
1559	return B_OK;
1560}
1561
1562
1563static status_t
1564usb_disk_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
1565{
1566	device_lun *lun = (device_lun *)cookie;
1567	disk_device *device = lun->device;
1568	MutexLocker locker(&device->lock);
1569	if (device->removed)
1570		return B_DEV_NOT_READY;
1571	RecursiveLocker ioLocker;
1572
1573	switch (op) {
1574		case B_GET_DEVICE_SIZE:
1575		{
1576			if (lun->media_changed) {
1577				status_t result = handle_media_change(lun, locker);
1578				if (result != B_OK)
1579					return result;
1580			}
1581
1582			size_t size = lun->block_size * lun->block_count;
1583			return user_memcpy(buffer, &size, sizeof(size));
1584		}
1585
1586		case B_GET_MEDIA_STATUS:
1587		{
1588			status_t result = acquire_io_lock(lun->device, locker, ioLocker);
1589			if (result != B_OK)
1590				return result;
1591
1592			err_act action = err_act_ok;
1593			status_t ready;
1594			for (uint32 tries = 0; tries < 3; tries++) {
1595				ready = usb_disk_test_unit_ready(lun, &action);
1596				if (ready == B_OK || ready == B_DEV_NO_MEDIA
1597					|| (action != err_act_retry
1598						&& action != err_act_many_retries)) {
1599					if (IS_USER_ADDRESS(buffer)) {
1600						if (user_memcpy(buffer, &ready, sizeof(status_t)) != B_OK)
1601							return B_BAD_ADDRESS;
1602					} else if (is_called_via_syscall()) {
1603						return B_BAD_ADDRESS;
1604					} else
1605						*(status_t *)buffer = ready;
1606					break;
1607				}
1608				snooze(500000);
1609			}
1610			TRACE("B_GET_MEDIA_STATUS: 0x%08" B_PRIx32 "\n", ready);
1611			return B_OK;
1612		}
1613
1614		case B_GET_GEOMETRY:
1615		{
1616			if (buffer == NULL || length > sizeof(device_geometry))
1617				return B_BAD_VALUE;
1618			if (lun->media_changed) {
1619				status_t result = handle_media_change(lun, locker);
1620				if (result != B_OK)
1621					return result;
1622			}
1623
1624			device_geometry geometry;
1625			devfs_compute_geometry_size(&geometry, lun->block_count,
1626				lun->block_size);
1627			geometry.bytes_per_physical_sector = lun->physical_block_size;
1628
1629			geometry.device_type = lun->device_type;
1630			geometry.removable = lun->removable;
1631			geometry.read_only = lun->write_protected;
1632			geometry.write_once = lun->device_type == B_WORM;
1633			TRACE("B_GET_GEOMETRY: %" B_PRId32 " sectors at %" B_PRId32
1634				" bytes per sector\n", geometry.cylinder_count,
1635				geometry.bytes_per_sector);
1636			return user_memcpy(buffer, &geometry, length);
1637		}
1638
1639		case B_FLUSH_DRIVE_CACHE:
1640		{
1641			TRACE("B_FLUSH_DRIVE_CACHE\n");
1642
1643			status_t result = acquire_io_lock(lun->device, locker, ioLocker);
1644			if (result != B_OK)
1645				return result;
1646
1647			return usb_disk_synchronize(lun, true);
1648		}
1649
1650		case B_EJECT_DEVICE:
1651		{
1652			status_t result = acquire_io_lock(lun->device, locker, ioLocker);
1653			if (result != B_OK)
1654				return result;
1655
1656			uint8 commandBlock[12];
1657			memset(commandBlock, 0, sizeof(commandBlock));
1658
1659			commandBlock[0] = SCSI_START_STOP_UNIT_6;
1660			commandBlock[1] = lun->logical_unit_number << 5;
1661			commandBlock[4] = 2;
1662
1663			return usb_disk_operation(lun, commandBlock, 6, NULL, NULL,
1664				false);
1665		}
1666
1667		case B_LOAD_MEDIA:
1668		{
1669			status_t result = acquire_io_lock(lun->device, locker, ioLocker);
1670			if (result != B_OK)
1671				return result;
1672
1673			uint8 commandBlock[12];
1674			memset(commandBlock, 0, sizeof(commandBlock));
1675
1676			commandBlock[0] = SCSI_START_STOP_UNIT_6;
1677			commandBlock[1] = lun->logical_unit_number << 5;
1678			commandBlock[4] = 3;
1679
1680			return usb_disk_operation(lun, commandBlock, 6, NULL, NULL,
1681				false);
1682		}
1683
1684		case B_GET_ICON:
1685			// We don't support this legacy ioctl anymore, but the two other
1686			// icon ioctls below instead.
1687			break;
1688
1689		case B_GET_ICON_NAME:
1690		{
1691			const char *iconName = "devices/drive-removable-media-usb";
1692			char vendor[sizeof(lun->vendor_name)+1];
1693			char product[sizeof(lun->product_name)+1];
1694
1695			if (device->is_ufi) {
1696				iconName = "devices/drive-floppy-usb";
1697			}
1698
1699			switch (lun->device_type) {
1700				case B_CD:
1701				case B_OPTICAL:
1702					iconName = "devices/drive-optical";
1703					break;
1704				case B_TAPE:	// TODO
1705				default:
1706					snprintf(vendor, sizeof(vendor), "%.8s",
1707						lun->vendor_name);
1708					snprintf(product, sizeof(product), "%.16s",
1709						lun->product_name);
1710					for (int i = 0; kIconMatches[i].icon; i++) {
1711						if (kIconMatches[i].vendor != NULL
1712							&& strstr(vendor, kIconMatches[i].vendor) == NULL)
1713							continue;
1714						if (kIconMatches[i].product != NULL
1715							&& strstr(product, kIconMatches[i].product) == NULL)
1716							continue;
1717						iconName = kIconMatches[i].name;
1718					}
1719					break;
1720			}
1721			return user_strlcpy((char *)buffer, iconName,
1722				B_FILE_NAME_LENGTH);
1723		}
1724
1725		case B_GET_VECTOR_ICON:
1726		{
1727			device_icon *icon = &kKeyIconData;
1728			char vendor[sizeof(lun->vendor_name)+1];
1729			char product[sizeof(lun->product_name)+1];
1730
1731			if (length != sizeof(device_icon))
1732				return B_BAD_VALUE;
1733
1734			if (device->is_ufi) {
1735				// UFI is specific for floppy drives
1736				icon = &kFloppyIconData;
1737			} else {
1738				switch (lun->device_type) {
1739					case B_CD:
1740					case B_OPTICAL:
1741						icon = &kCDIconData;
1742						break;
1743					case B_TAPE:	// TODO
1744					default:
1745						snprintf(vendor, sizeof(vendor), "%.8s",
1746								lun->vendor_name);
1747						snprintf(product, sizeof(product), "%.16s",
1748								lun->product_name);
1749						for (int i = 0; kIconMatches[i].icon; i++) {
1750							if (kIconMatches[i].vendor != NULL
1751									&& strstr(vendor,
1752										kIconMatches[i].vendor) == NULL)
1753								continue;
1754							if (kIconMatches[i].product != NULL
1755									&& strstr(product,
1756										kIconMatches[i].product) == NULL)
1757								continue;
1758							icon = kIconMatches[i].icon;
1759						}
1760						break;
1761				}
1762			}
1763
1764			device_icon iconData;
1765			if (user_memcpy(&iconData, buffer, sizeof(device_icon)) != B_OK)
1766				return B_BAD_ADDRESS;
1767
1768			if (iconData.icon_size >= icon->icon_size) {
1769				if (user_memcpy(iconData.icon_data, icon->icon_data,
1770						(size_t)icon->icon_size) != B_OK)
1771					return B_BAD_ADDRESS;
1772			}
1773
1774			iconData.icon_size = icon->icon_size;
1775			return user_memcpy(buffer, &iconData, sizeof(device_icon));
1776		}
1777
1778		case B_GET_DEVICE_NAME:
1779		{
1780			size_t nameLength = sizeof(lun->vendor_name)
1781				+ sizeof(lun->product_name) + sizeof(lun->product_revision) + 3;
1782
1783			char name[nameLength];
1784			snprintf(name, nameLength, "%.8s %.16s %.4s", lun->vendor_name,
1785				lun->product_name, lun->product_revision);
1786
1787			normalize_name(name, nameLength);
1788
1789			status_t result = user_strlcpy((char *)buffer, name, length);
1790			if (result > 0)
1791				result = B_OK;
1792
1793			TRACE_ALWAYS("got device name \"%s\": %s\n", name,
1794				strerror(result));
1795			return result;
1796		}
1797	}
1798
1799	TRACE_ALWAYS("unhandled ioctl %" B_PRId32 "\n", op);
1800	return B_DEV_INVALID_IOCTL;
1801}
1802
1803
1804static status_t
1805usb_disk_bounced_io(device_lun *lun, io_request *request)
1806{
1807	DMAResource* dmaResource = get_dma_resource(lun->device, lun->block_size);
1808	if (dmaResource == NULL)
1809		return B_NO_INIT;
1810
1811	if (!request->Buffer()->IsPhysical()) {
1812		status_t status = request->Buffer()->LockMemory(request->TeamID(), request->IsWrite());
1813		if (status != B_OK) {
1814			TRACE_ALWAYS("failed to lock memory: %s\n", strerror(status));
1815			return status;
1816		}
1817		// SetStatusAndNotify() takes care of unlocking memory if necessary.
1818	}
1819
1820	status_t status = B_OK;
1821	while (request->RemainingBytes() > 0) {
1822		IOOperation operation;
1823		status = dmaResource->TranslateNext(request, &operation, 0);
1824		if (status != B_OK)
1825			break;
1826
1827		do {
1828			TRACE("%p: IOO offset: %" B_PRIdOFF ", length: %" B_PRIuGENADDR
1829				", write: %s\n", request, operation.Offset(),
1830				operation.Length(), operation.IsWrite() ? "yes" : "no");
1831
1832			struct transfer_data data;
1833			data.physical = true;
1834			data.phys_vecs = (physical_entry*)operation.Vecs();
1835			data.vec_count = operation.VecCount();
1836
1837			size_t length = operation.Length();
1838			const uint64 blockPosition = operation.Offset() / lun->block_size;
1839			const size_t blockCount = length / lun->block_size;
1840			if (operation.IsWrite()) {
1841				status = usb_disk_block_write(lun,
1842					blockPosition, blockCount, data, &length);
1843			} else {
1844				status = usb_disk_block_read(lun,
1845					blockPosition, blockCount, data, &length);
1846			}
1847
1848			operation.SetStatus(status, length);
1849		} while (status == B_OK && !operation.Finish());
1850
1851		if (status == B_OK && operation.Status() != B_OK) {
1852			TRACE_ALWAYS("I/O succeeded but IOOperation failed!\n");
1853			status = operation.Status();
1854		}
1855
1856		request->OperationFinished(&operation);
1857		dmaResource->RecycleBuffer(operation.Buffer());
1858
1859		TRACE("%p: status %s, remaining bytes %" B_PRIuGENADDR "\n", request,
1860			strerror(status), request->RemainingBytes());
1861		if (status != B_OK)
1862			break;
1863	}
1864
1865	return status;
1866}
1867
1868
1869static status_t
1870usb_disk_direct_io(device_lun *lun, io_request *request)
1871{
1872	generic_io_vec* genericVecs = request->Buffer()->Vecs();
1873	const uint32 count = request->Buffer()->VecCount();
1874	BStackOrHeapArray<iovec, 16> vecs(count);
1875	for (uint32 i = 0; i < count; i++) {
1876		vecs[i].iov_base = (void*)genericVecs[i].base;
1877		vecs[i].iov_len = genericVecs[i].length;
1878	}
1879	struct transfer_data data;
1880	data.vecs = vecs;
1881	data.vec_count = count;
1882
1883	size_t length = request->Length();
1884	const uint64 blockPosition = request->Offset() / lun->block_size;
1885	const size_t blockCount = length / lun->block_size;
1886
1887	status_t status;
1888	if (request->IsWrite()) {
1889		 status = usb_disk_block_write(lun,
1890			blockPosition, blockCount, data, &length);
1891	} else {
1892		status = usb_disk_block_read(lun,
1893			blockPosition, blockCount, data, &length);
1894	}
1895
1896	request->SetTransferredBytes(length != request->Length(), length);
1897	return status;
1898}
1899
1900
1901static status_t
1902usb_disk_io(void *cookie, io_request *request)
1903{
1904	TRACE("io(%p)\n", request);
1905
1906	device_lun *lun = (device_lun *)cookie;
1907	disk_device *device = lun->device;
1908
1909	RecursiveLocker ioLocker(device->io_lock);
1910	MutexLocker deviceLocker(device->lock);
1911
1912	if (device->removed)
1913		return B_DEV_NOT_READY;
1914
1915	status_t status;
1916	if (!usb_disk_needs_bounce(lun, request)) {
1917		status = usb_disk_direct_io(lun, request);
1918	} else {
1919		status = usb_disk_bounced_io(lun, request);
1920	}
1921
1922	deviceLocker.Unlock();
1923	ioLocker.Unlock();
1924
1925	if (request->Status() > 0)
1926		request->SetStatusAndNotify(status);
1927	else
1928		request->NotifyFinished();
1929	return status;
1930}
1931
1932
1933//	#pragma mark - driver module API
1934
1935
1936static float
1937usb_disk_supports_device(device_node *parent)
1938{
1939	CALLED();
1940	const char *bus;
1941
1942	// make sure parent is really the usb bus manager
1943	if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
1944		return -1;
1945	if (strcmp(bus, "usb") != 0)
1946		return 0.0;
1947
1948	usb_device device;
1949	if (gDeviceManager->get_attr_uint32(parent, USB_DEVICE_ID_ITEM, &device, true) != B_OK)
1950		return -1;
1951
1952	const usb_configuration_info *configuration = gUSBModule->get_configuration(device);
1953	if (configuration == NULL)
1954		return -1;
1955
1956	static usb_support_descriptor supportedDevices[] = {
1957		{ USB_MASS_STORAGE_DEVICE_CLASS, 0x06 /* SCSI */, 0x50 /* bulk */, 0, 0 },
1958		{ USB_MASS_STORAGE_DEVICE_CLASS, 0x02 /* ATAPI */, 0x50 /* bulk */, 0, 0 },
1959		{ USB_MASS_STORAGE_DEVICE_CLASS, 0x05 /* ATAPI */, 0x50 /* bulk */, 0, 0 },
1960		{ USB_MASS_STORAGE_DEVICE_CLASS, 0x04 /* UFI */, 0x00, 0, 0 }
1961	};
1962
1963	for (size_t i = 0; i < configuration->interface_count; i++) {
1964		usb_interface_info *interface = configuration->interface[i].active;
1965		if (interface == NULL)
1966			continue;
1967
1968		for (size_t i = 0; i < B_COUNT_OF(supportedDevices); i++) {
1969			if (interface->descr->interface_class != supportedDevices[i].dev_class)
1970				continue;
1971			if (interface->descr->interface_subclass != supportedDevices[i].dev_subclass)
1972				continue;
1973			if (interface->descr->interface_protocol != supportedDevices[i].dev_protocol)
1974				continue;
1975
1976			TRACE("USB disk device found!\n");
1977			return 0.6;
1978		}
1979	}
1980
1981	return 0.0;
1982}
1983
1984
1985static status_t
1986usb_disk_register_device(device_node *node)
1987{
1988	CALLED();
1989
1990	device_attr attrs[] = {
1991		{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {.string = "USB Disk"} },
1992		{ NULL }
1993	};
1994
1995	return gDeviceManager->register_node(node, USB_DISK_DRIVER_MODULE_NAME,
1996		attrs, NULL, NULL);
1997}
1998
1999
2000static status_t
2001usb_disk_init_driver(device_node *node, void **cookie)
2002{
2003	CALLED();
2004
2005	usb_device usb_device;
2006	if (gDeviceManager->get_attr_uint32(node, USB_DEVICE_ID_ITEM, &usb_device, true) != B_OK)
2007		return B_BAD_VALUE;
2008
2009	return usb_disk_attach(node, usb_device, cookie);
2010}
2011
2012
2013static void
2014usb_disk_uninit_driver(void *_cookie)
2015{
2016	CALLED();
2017	// Nothing to do.
2018}
2019
2020
2021static status_t
2022usb_disk_register_child_devices(void* _cookie)
2023{
2024	CALLED();
2025	disk_device *device = (disk_device *)_cookie;
2026
2027	device->number = gDeviceManager->create_id(USB_DISK_DEVICE_ID_GENERATOR);
2028	if (device->number < 0)
2029		return device->number;
2030
2031	status_t status = B_OK;
2032	for (uint8 i = 0; i < device->lun_count; i++) {
2033		sprintf(device->luns[i]->name, DEVICE_NAME, device->number, i);
2034		status = gDeviceManager->publish_device(device->node, device->luns[i]->name,
2035			USB_DISK_DEVICE_MODULE_NAME);
2036	}
2037
2038	return status;
2039}
2040
2041
2042//	#pragma mark -
2043
2044
2045module_dependency module_dependencies[] = {
2046	{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&gDeviceManager },
2047	{ B_USB_MODULE_NAME, (module_info**)&gUSBModule},
2048	{ NULL }
2049};
2050
2051struct device_module_info sUsbDiskDevice = {
2052	{
2053		USB_DISK_DEVICE_MODULE_NAME,
2054		0,
2055		NULL
2056	},
2057
2058	usb_disk_init_device,
2059	usb_disk_uninit_device,
2060	usb_disk_device_removed,
2061
2062	usb_disk_open,
2063	usb_disk_close,
2064	usb_disk_free,
2065	NULL,	// read
2066	NULL,	// write
2067	usb_disk_io,
2068	usb_disk_ioctl,
2069
2070	NULL,	// select
2071	NULL,	// deselect
2072};
2073
2074struct driver_module_info sUsbDiskDriver = {
2075	{
2076		USB_DISK_DRIVER_MODULE_NAME,
2077		0,
2078		NULL
2079	},
2080
2081	usb_disk_supports_device,
2082	usb_disk_register_device,
2083	usb_disk_init_driver,
2084	usb_disk_uninit_driver,
2085	usb_disk_register_child_devices,
2086	NULL,	// rescan
2087	NULL,	// removed
2088};
2089
2090module_info* modules[] = {
2091	(module_info*)&sUsbDiskDriver,
2092	(module_info*)&sUsbDiskDevice,
2093	NULL
2094};
2095