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