xref: /haiku/src/add-ons/kernel/bus_managers/scsi/dpc.cpp (revision cbe0a0c436162d78cc3f92a305b64918c839d079)
1 /*
2 ** Copyright 2002/03, Thomas Kurschel. All rights reserved.
3 ** Distributed under the terms of the MIT License.
4 */
5 
6 /*
7 	Part of Open SCSI bus manager
8 
9 	DPC handling (deferred procedure calls).
10 
11 	DPC are executed by the service thread of the bus
12 	(see busses.c).
13 */
14 
15 #include "scsi_internal.h"
16 
17 #include <string.h>
18 #include <stdlib.h>
19 
20 
21 status_t
22 scsi_alloc_dpc(scsi_dpc_info **dpc)
23 {
24 	SHOW_FLOW0(3, "");
25 
26 	*dpc = (scsi_dpc_info *)malloc(sizeof(scsi_dpc_info));
27 	if (*dpc == NULL)
28 		return B_NO_MEMORY;
29 
30 	memset(*dpc, 0, sizeof(scsi_dpc_info));
31 	return B_OK;
32 }
33 
34 
35 status_t
36 scsi_free_dpc(scsi_dpc_info *dpc)
37 {
38 	SHOW_FLOW0(3, "");
39 
40 	free(dpc);
41 	return B_OK;
42 }
43 
44 
45 status_t
46 scsi_schedule_dpc(scsi_bus_info *bus, scsi_dpc_info *dpc, /*int flags,*/
47 	void (*func)(void *arg), void *arg)
48 {
49 	SHOW_FLOW(3, "bus=%p, dpc=%p", bus, dpc);
50 	acquire_spinlock_irq(&bus->dpc_lock);
51 
52 	dpc->func = func;
53 	dpc->arg = arg;
54 
55 	if (!dpc->registered) {
56 		dpc->registered = true;
57 		dpc->next = bus->dpc_list;
58 		bus->dpc_list = dpc;
59 	} else
60 		SHOW_FLOW0(3, "already registered - ignored");
61 
62 	release_spinlock_irq(&bus->dpc_lock);
63 
64 	// this is called in IRQ context, so scheduler is not allowed
65 	release_sem_etc(bus->start_service, 1, B_DO_NOT_RESCHEDULE);
66 	return B_OK;
67 }
68 
69 
70 /** execute pending DPCs */
71 
72 bool
73 scsi_check_exec_dpc(scsi_bus_info *bus)
74 {
75 	SHOW_FLOW(3, "bus=%p, dpc_list=%p", bus, bus->dpc_list);
76 	acquire_spinlock_irq(&bus->dpc_lock);
77 
78 	if (bus->dpc_list) {
79 		scsi_dpc_info *dpc;
80 		void (*dpc_func)(void *);
81 		void *dpc_arg;
82 
83 		dpc = bus->dpc_list;
84 		bus->dpc_list = dpc->next;
85 
86 		dpc_func = dpc->func;
87 		dpc_arg = dpc->arg;
88 		dpc->registered = false;
89 
90 		release_spinlock_irq(&bus->dpc_lock);
91 
92 		dpc_func(dpc_arg);
93 		return true;
94 	}
95 
96 	release_spinlock_irq(&bus->dpc_lock);
97 	return false;
98 }
99 
100