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
22char *
23periph_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
55status_t
56periph_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
100err1:
101	mutex_destroy(&device->mutex);
102	free(device);
103	return status;
104}
105
106
107status_t
108periph_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