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/*
9	Controllers use this interface to interact with bus manager.
10*/
11
12
13#include "scsi_internal.h"
14#include "queuing.h"
15
16#include <stdio.h>
17#include <stdlib.h>
18#include <string.h>
19
20
21/**	new scsi controller added
22 *	in return, we register a new scsi bus node and let its fixed
23 *	consumer (the SCSI device layer) automatically scan it for devices
24 */
25
26static status_t
27scsi_controller_added(device_node *parent)
28{
29	const char *controller_name;
30	int32 pathID;
31
32	SHOW_FLOW0(4, "");
33
34	if (pnp->get_attr_string(parent, SCSI_DESCRIPTION_CONTROLLER_NAME,
35			&controller_name, false) != B_OK) {
36		dprintf("scsi: ignored controller - controller name missing\n");
37		return B_ERROR;
38	}
39
40	pathID = pnp->create_id(SCSI_PATHID_GENERATOR);
41	if (pathID < 0) {
42		dprintf("scsi: Cannot register SCSI controller %s - out of path IDs\n",
43			controller_name);
44		return B_ERROR;
45	}
46
47	{
48		device_attr attrs[] = {
49			{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE,
50				{ .string = "SCSI Controller" }},
51
52			// remember who we are
53			// (could use the controller name, but probably some software would choke)
54			// TODO create_id() generates a 32 bit ranged integer but we need only 8 bits
55			{ SCSI_BUS_PATH_ID_ITEM, B_UINT8_TYPE, { .ui8 = (uint8)pathID }},
56
57			// tell PnP manager to clean up ID
58//			{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { .string = SCSI_PATHID_GENERATOR }},
59//			{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { .ui32 = path_id }},
60			{}
61		};
62
63		return pnp->register_node(parent, SCSI_BUS_MODULE_NAME, attrs, NULL,
64			NULL);
65	}
66}
67
68
69static status_t
70scsi_controller_init(device_node *node, void **_cookie)
71{
72	*_cookie = node;
73	return B_OK;
74}
75
76
77static status_t
78scsi_controller_register_raw_device(void *_cookie)
79{
80	device_node *node = (device_node *)_cookie;
81	uint32 channel;
82	uint8 pathID;
83	char *name;
84
85#if 1
86// TODO: this seems to cause a crash in some configurations, and needs to be investigated!
87//		see bug #389 and #393.
88// TODO: check if the above is still true
89	if (pnp->get_attr_uint32(node, "ide/channel_id", &channel, true) == B_OK) {
90		// this is actually an IDE device, we don't need to publish
91		// a bus device for those
92		return B_OK;
93	}
94#endif
95	pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &pathID, false);
96
97	// put that on heap to not overflow the limited kernel stack
98	name = (char*)malloc(PATH_MAX + 1);
99	if (name == NULL)
100		return B_NO_MEMORY;
101
102	snprintf(name, PATH_MAX + 1, "bus/scsi/%d/bus_raw", pathID);
103
104	return pnp->publish_device(node, name, SCSI_BUS_RAW_MODULE_NAME);
105}
106
107
108static status_t
109std_ops(int32 op, ...)
110{
111	switch (op) {
112		case B_MODULE_INIT:
113		case B_MODULE_UNINIT:
114			return B_OK;
115
116		default:
117			return B_ERROR;
118	}
119}
120
121
122scsi_for_sim_interface scsi_for_sim_module =
123{
124	{
125		{
126			SCSI_FOR_SIM_MODULE_NAME,
127			0,
128			std_ops
129		},
130
131		NULL,	// supported devices
132		scsi_controller_added,
133		scsi_controller_init,
134		NULL,	// uninit
135		scsi_controller_register_raw_device,
136		NULL,	// rescan
137		NULL,	// removed
138	},
139
140	scsi_requeue_request,
141	scsi_resubmit_request,
142	scsi_request_finished,
143
144	scsi_alloc_dpc,
145	scsi_free_dpc,
146	scsi_schedule_dpc,
147
148	scsi_block_bus,
149	scsi_unblock_bus,
150	scsi_block_device,
151	scsi_unblock_device,
152
153	scsi_cont_send_bus,
154	scsi_cont_send_device
155};
156