/* returns a free command struct if one is available. * It also blanks out anything that may be a wild pointer/value. * Also, command buffers are not freed. They are * small so they are saved and kept dmamapped and loaded. */ int ips_get_free_cmd(ips_softc_t *sc, ips_command_t **cmd, unsigned long flags) { ips_command_t *command; if(sc->state & IPS_OFFLINE){ return EIO; } if ((flags & IPS_STATIC_FLAG) == 0) { command = SLIST_FIRST(&sc->free_cmd_list); if(!command || (sc->state & IPS_TIMEOUT)){ return EBUSY; } SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); (sc->used_commands)++; } else { if (sc->state & IPS_STATIC_BUSY) return EAGAIN; command = sc->staticcmd; sc->state |= IPS_STATIC_BUSY; } clear_ips_command(command); bzero(command->command_buffer, IPS_COMMAND_LEN); *cmd = command; return 0; }
static void ips_run_waiting_command(ips_softc_t *sc) { ips_wait_list_t *waiter; ips_command_t *command; int (*callback)(ips_command_t*); intrmask_t mask; mask = splbio(); waiter = STAILQ_FIRST(&sc->cmd_wait_list); command = SLIST_FIRST(&sc->free_cmd_list); if(!waiter || !command){ splx(mask); return; } DEVICE_PRINTF(1, sc->dev, "removing command from wait queue\n"); SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); STAILQ_REMOVE_HEAD(&sc->cmd_wait_list, next); (sc->used_commands)++; splx(mask); clear_ips_command(command); bzero(command->command_buffer, IPS_COMMAND_LEN); command->arg = waiter->data; callback = waiter->callback; free(waiter, M_DEVBUF); callback(command); return; }
/* returns a free command struct if one is available. * It also blanks out anything that may be a wild pointer/value. * Also, command buffers are not freed. They are * small so they are saved and kept dmamapped and loaded. */ int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags) { intrmask_t mask; ips_command_t *command; mask = splbio(); if(sc->state & IPS_OFFLINE){ splx(mask); return EIO; } command = SLIST_FIRST(&sc->free_cmd_list); if(!command || (sc->state & IPS_TIMEOUT)){ splx(mask); if(flags & IPS_NOWAIT_FLAG) return EAGAIN; return ips_add_waiting_command(sc, callback, data, flags); } SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); (sc->used_commands)++; splx(mask); clear_ips_command(command); bzero(command->command_buffer, IPS_COMMAND_LEN); command->arg = data; return callback(command); }
static int ips_add_waiting_command(ips_softc_t *sc, int (*callback)(ips_command_t *), void *data, unsigned long flags) { intrmask_t mask; ips_command_t *command; ips_wait_list_t *waiter; unsigned long memflags = 0; if(IPS_NOWAIT_FLAG & flags) memflags = M_NOWAIT; waiter = malloc(sizeof(ips_wait_list_t), M_DEVBUF, memflags); if(!waiter) return ENOMEM; mask = splbio(); if(sc->state & IPS_OFFLINE){ splx(mask); return EIO; } command = SLIST_FIRST(&sc->free_cmd_list); if(command && !(sc->state & IPS_TIMEOUT)){ SLIST_REMOVE_HEAD(&sc->free_cmd_list, next); (sc->used_commands)++; splx(mask); clear_ips_command(command); bzero(command->command_buffer, IPS_COMMAND_LEN); free(waiter, M_DEVBUF); command->arg = data; return callback(command); } DEVICE_PRINTF(1, sc->dev, "adding command to the wait queue\n"); waiter->callback = callback; waiter->data = data; STAILQ_INSERT_TAIL(&sc->cmd_wait_list, waiter, next); splx(mask); return 0; }