FreeBSD/sys/dev/mrsas/mrsas.c
/*
 *  mrsas_register_aen:		Register for asynchronous event notification
 *  @sc:			Adapter soft state
 *  @seq_num:			Starting sequence number
 *  @class_locale:		Class of the event
 *
 *  This function subscribes for events beyond the @seq_num
 *  and type @class_locale.
 *
 */
Register for asynchronous event notification
@sc:                        Adapter soft state
@seq_num:                   Starting sequence number
@class_locale:              Class of the event

This function subscribes for events beyond the @seq_num
and type @class_locale.
Register for asynchronous event notification @sc : Adapter soft state @seq_num : Starting sequence number @class_locale : Class of the event This function subscribes for events beyond the @seq_num and type @class_locale .
static int
mrsas_register_aen(struct mrsas_softc *sc, u_int32_t seq_num,
    u_int32_t class_locale_word)
{
	int ret_val;
	struct mrsas_mfi_cmd *cmd;
	struct mrsas_dcmd_frame *dcmd;
	union mrsas_evt_class_locale curr_aen;
	union mrsas_evt_class_locale prev_aen;
	curr_aen.word = class_locale_word;
	if (sc->aen_cmd) {
		prev_aen.word = sc->aen_cmd->frame->dcmd.mbox.w[1];
		if ((prev_aen.members.class <= curr_aen.members.class) &&
		    !((prev_aen.members.locale & curr_aen.members.locale) ^
		    curr_aen.members.locale)) {
			return 0;
		} else {
			curr_aen.members.locale |= prev_aen.members.locale;
			if (prev_aen.members.class < curr_aen.members.class)
				curr_aen.members.class = prev_aen.members.class;
			sc->aen_cmd->abort_aen = 1;
			ret_val = mrsas_issue_blocked_abort_cmd(sc,
			    sc->aen_cmd);
			if (ret_val) {
				printf("mrsas: Failed to abort "
				    "previous AEN command\n");
				return ret_val;
			}
		}
	}
	cmd = mrsas_get_mfi_cmd(sc);
	if (!cmd)
		return -ENOMEM;
	dcmd = &cmd->frame->dcmd;
	memset(sc->evt_detail_mem, 0, sizeof(struct mrsas_evt_detail));
	memset(dcmd->mbox.b, 0, MFI_MBOX_SIZE);
	dcmd->cmd = MFI_CMD_DCMD;
	dcmd->cmd_status = 0x0;
	dcmd->sge_count = 1;
	dcmd->flags = MFI_FRAME_DIR_READ;
	dcmd->timeout = 0;
	dcmd->pad_0 = 0;
	dcmd->data_xfer_len = sizeof(struct mrsas_evt_detail);
	dcmd->opcode = MR_DCMD_CTRL_EVENT_WAIT;
	dcmd->mbox.w[0] = seq_num;
	sc->last_seq_num = seq_num;
	dcmd->mbox.w[1] = curr_aen.word;
	dcmd->sgl.sge32[0].phys_addr = (u_int32_t)sc->evt_detail_phys_addr;
	dcmd->sgl.sge32[0].length = sizeof(struct mrsas_evt_detail);
	if (sc->aen_cmd != NULL) {
		mrsas_release_mfi_cmd(cmd);
		return 0;
	}
	sc->aen_cmd = cmd;
	if (mrsas_issue_dcmd(sc, cmd)) {
		device_printf(sc->mrsas_dev, "Cannot issue AEN DCMD command.\n");
		return (1);
	}
	return 0;
}
static int mrsas_register_aen ( struct mrsas_softc * sc , u_int32_t seq_num , u_int32_t class_locale_word ) { int ret_val ; struct mrsas_mfi_cmd * cmd ; struct mrsas_dcmd_frame * dcmd ; union mrsas_evt_class_locale curr_aen ; union mrsas_evt_class_locale prev_aen ; curr_aen . word = class_locale_word ; if ( sc -> aen_cmd ) { prev_aen . word = sc -> aen_cmd -> frame -> dcmd . mbox . w [ 1 ] ; if ( ( prev_aen . members . class <= curr_aen . members . class ) && ! ( ( prev_aen . members . locale & curr_aen . members . locale ) ^ curr_aen . members . locale ) ) { return 0 ; } else { curr_aen . members . locale |= prev_aen . members . locale ; if ( prev_aen . members . class < curr_aen . members . class ) curr_aen . members . class = prev_aen . members . class ; sc -> aen_cmd -> abort_aen = 1 ; ret_val = mrsas_issue_blocked_abort_cmd ( sc , sc -> aen_cmd ) ; if ( ret_val ) { printf ( " " " \n " ) ; return ret_val ; } } } cmd = mrsas_get_mfi_cmd ( sc ) ; if ( ! cmd ) return - ENOMEM ; dcmd = & cmd -> frame -> dcmd ; memset ( sc -> evt_detail_mem , 0 , sizeof ( struct mrsas_evt_detail ) ) ; memset ( dcmd -> mbox . b , 0 , MFI_MBOX_SIZE ) ; dcmd -> cmd = MFI_CMD_DCMD ; dcmd -> cmd_status = 0x0 ; dcmd -> sge_count = 1 ; dcmd -> flags = MFI_FRAME_DIR_READ ; dcmd -> timeout = 0 ; dcmd -> pad_0 = 0 ; dcmd -> data_xfer_len = sizeof ( struct mrsas_evt_detail ) ; dcmd -> opcode = MR_DCMD_CTRL_EVENT_WAIT ; dcmd -> mbox . w [ 0 ] = seq_num ; sc -> last_seq_num = seq_num ; dcmd -> mbox . w [ 1 ] = curr_aen . word ; dcmd -> sgl . sge32 [ 0 ] . phys_addr = ( u_int32_t ) sc -> evt_detail_phys_addr ; dcmd -> sgl . sge32 [ 0 ] . length = sizeof ( struct mrsas_evt_detail ) ; if ( sc -> aen_cmd != NULL ) { mrsas_release_mfi_cmd ( cmd ) ; return 0 ; } sc -> aen_cmd = cmd ; if ( mrsas_issue_dcmd ( sc , cmd ) ) { device_printf ( sc -> mrsas_dev , " \n " ) ; return ( 1 ) ; } return 0 ; }
mrsas_register_aen:         Register for asynchronous event notification
  @sc:                        Adapter soft state
  @seq_num:                   Starting sequence number
  @class_locale:              Class of the event
mrsas_register_aen : Register for asynchronous event notification @sc : Adapter soft state @seq_num : Starting sequence number @class_locale : Class of the event
/*
	 * If there an AEN pending already (aen_cmd), check if the
	 * class_locale of that pending AEN is inclusive of the new AEN
	 * request we currently have. If it is, then we don't have to do
	 * anything. In other words, whichever events the current AEN request
	 * is subscribing to, have already been subscribed to. If the old_cmd
	 * is _not_ inclusive, then we have to abort that command, form a
	 * class_locale that is superset of both old and current and re-issue
	 * to the FW
	 */ /*
		 * A class whose enum value is smaller is inclusive of all
		 * higher values. If a PROGRESS (= -1) was previously
		 * registered, then a new registration requests for higher
		 * classes need not be sent to FW. They are automatically
		 * included. Locale numbers don't have such hierarchy. They
		 * are bitmap values
		 */ /*
			 * Previously issued event registration includes
			 * current request. Nothing to do.
			 */ /*
	 * Prepare DCMD for aen registration
	 */ /*
	 * Store reference to the cmd used to register for AEN. When an
	 * application wants us to register for AEN, we have to abort this
	 * cmd and re-register with a new EVENT LOCALE supplied by that app
	 */ /*
	 * Issue the aen registration frame
	 */