xref: /haiku/src/add-ons/kernel/generic/scsi_periph/device.cpp (revision a5061ecec55353a5f394759473f1fd6df04890da)
1 /*
2  * Copyright 2004-2011, 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 //!	Basic handling of device.
10 
11 
12 #include "scsi_periph_int.h"
13 
14 #include <string.h>
15 #include <stdio.h>
16 #include <stdlib.h>
17 
18 
19 #define SCSI_PERIPH_STD_TIMEOUT 10
20 
21 
22 char *
23 periph_compose_device_name(device_node *node, const char *prefix)
24 {
25 	uint8 pathID, targetID, targetLUN, type;
26 	char name[128];
27 	uint32 channel;
28 
29 	if (gDeviceManager->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &pathID, true) != B_OK
30 		|| gDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TARGET_ID_ITEM, &targetID, true) != B_OK
31 		|| gDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TARGET_LUN_ITEM, &targetLUN, true) != B_OK)
32 		return NULL;
33 
34 	// IDE devices have a different naming scheme
35 
36 	if (gDeviceManager->get_attr_uint32(node, "ide/channel_id", &channel, true) == B_OK
37 		&& gDeviceManager->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM, &type, true) == B_OK) {
38 		// this is actually an IDE device, so we ignore the prefix
39 
40 		// a bus device for those
41 		snprintf(name, sizeof(name), "disk/ata%s/%" B_PRId32 "/%s/raw",
42 			type == scsi_dev_CDROM ? "pi" : "", channel,
43 			targetID == 0 ? "master" : "slave");
44 	} else {
45 		// this is a real SCSI device
46 
47 		snprintf(name, sizeof(name), "%s/%d/%d/%d/raw",
48 			prefix, pathID, targetID, targetLUN);
49 	}
50 
51 	return strdup(name);
52 }
53 
54 
55 status_t
56 periph_register_device(periph_device_cookie periph_device,
57 	scsi_periph_callbacks *callbacks, scsi_device scsi_device,
58 	scsi_device_interface *scsi, device_node *node,
59 	bool removable, int preferredCcbSize, scsi_periph_device *driver)
60 {
61 	SHOW_FLOW0(3, "");
62 
63 	scsi_periph_device_info *device
64 		= (scsi_periph_device_info *)malloc(sizeof(*device));
65 	if (device == NULL)
66 		return B_NO_MEMORY;
67 
68 	memset(device, 0, sizeof(*device));
69 
70 	mutex_init(&device->mutex, "SCSI_PERIPH");
71 	device->scsi_device = scsi_device;
72 	device->scsi = scsi;
73 	device->periph_device = periph_device;
74 	device->removal_requested = false;
75 	device->callbacks = callbacks;
76 	device->node = node;
77 	device->removable = removable;
78 	device->std_timeout = SCSI_PERIPH_STD_TIMEOUT;
79 
80 	// set some default options
81 	device->next_tag_action = 0;
82 	device->preferred_ccb_size = preferredCcbSize;
83 	device->rw10_enabled = true;
84 	device->unmap_command = TRIM_NONE;
85 	device->max_unmap_lba_count = 0;
86 	device->max_unmap_descriptor_count = 0;
87 
88 	// launch sync daemon
89 	status_t status = register_kernel_daemon(periph_sync_queue_daemon, device,
90 		60*10);
91 	if (status != B_OK)
92 		goto err1;
93 
94 	*driver = device;
95 
96 	SHOW_FLOW0(3, "done");
97 
98 	return B_OK;
99 
100 err1:
101 	mutex_destroy(&device->mutex);
102 	free(device);
103 	return status;
104 }
105 
106 
107 status_t
108 periph_unregister_device(scsi_periph_device_info *device)
109 {
110 	unregister_kernel_daemon(periph_sync_queue_daemon, device);
111 	free(device);
112 
113 	return B_OK;
114 }
115