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