xref: /haiku/src/add-ons/kernel/generic/scsi_periph/block.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
1 /*
2  * Copyright 2004-2008, Haiku, Inc. All RightsReserved.
3  * Copyright 2002-2003, Thomas Kurschel. All rights reserved.
4  *
5  * Distributed under the terms of the MIT License.
6  */
7 
8 //!	Handling of block device (currently, only a capacity check is provided)
9 
10 
11 #include "scsi_periph_int.h"
12 #include <string.h>
13 
14 
15 status_t
16 periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *request)
17 {
18 	scsi_res_read_capacity capacityResult;
19 	scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
20 	uint64 capacity;
21 	uint32 blockSize;
22 	status_t res;
23 
24 	SHOW_FLOW(3, "%p, %p", device, request);
25 
26 	// driver doesn't support capacity callback - seems to be no block
27 	// device driver, so ignore
28 	if (device->callbacks->set_capacity == NULL)
29 		return B_OK;
30 
31 	request->flags = SCSI_DIR_IN;
32 
33 	request->data = (uint8*)&capacityResult;
34 	request->data_length = sizeof(capacityResult);
35 	request->cdb_length = sizeof(scsi_cmd_read_capacity);
36 	request->timeout = device->std_timeout;
37 	request->sort = -1;
38 	request->sg_list = NULL;
39 
40 	memset(cmd, 0, sizeof(*cmd));
41 	cmd->opcode = SCSI_OP_READ_CAPACITY;
42 	// we don't set PMI (partial medium indicator) as we want the whole capacity;
43 	// in this case, all other parameters must be zero
44 
45 	res = periph_safe_exec(device, request);
46 
47 	if (res == B_DEV_MEDIA_CHANGED) {
48 		// in this case, the error handler has already called check_capacity
49 		// recursively, so we ignore our (invalid) result
50 		SHOW_FLOW0( 3, "ignore result because medium change" );
51 		return B_DEV_MEDIA_CHANGED;
52 	}
53 
54 	ACQUIRE_BEN(&device->mutex);
55 
56 	if (res == B_OK && request->data_resid == 0) {
57 		capacity = B_BENDIAN_TO_HOST_INT32(capacityResult.lba);
58 
59 		// the command returns the index of the _last_ block,
60 		// i.e. the size is one larger
61 		++capacity;
62 
63 		blockSize = B_BENDIAN_TO_HOST_INT32(capacityResult.block_size);
64 	} else {
65 		capacity = 0;
66 		blockSize = 0;
67 	}
68 
69 	SHOW_FLOW(3, "capacity = %Ld, block_size = %ld", capacity, blockSize);
70 
71 	device->block_size = blockSize;
72 
73 	device->callbacks->set_capacity(device->periph_device,
74 		capacity, blockSize);
75 
76 /*	device->byte2blk_shift = log2( device->block_size );
77 	if( device->byte2blk_shift < 0 ) {
78 		// this may be too restrictive...
79 		device->capacity = -1;
80 		return ERR_DEV_GENERAL;
81 	}*/
82 
83 	RELEASE_BEN(&device->mutex);
84 
85 	SHOW_FLOW(3, "done (%s)", strerror(res));
86 
87 	return res;
88 }
89 
90