linux/drivers/scsi/aic94xx/aic94xx_scb.c

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Aic94xx SAS/SATA driver SCB management.
 *
 * Copyright (C) 2005 Adaptec, Inc.  All rights reserved.
 * Copyright (C) 2005 Luben Tuikov <[email protected]>
 */

#include <linux/gfp.h>
#include <scsi/scsi_host.h>

#include "aic94xx.h"
#include "aic94xx_reg.h"
#include "aic94xx_hwi.h"
#include "aic94xx_seq.h"

#include "aic94xx_dump.h"

/* ---------- EMPTY SCB ---------- */

#define DL_PHY_MASK
#define BYTES_DMAED
#define PRIMITIVE_RECVD
#define PHY_EVENT
#define LINK_RESET_ERROR
#define TIMER_EVENT
#define REQ_TASK_ABORT
#define REQ_DEVICE_RESET
#define SIGNAL_NCQ_ERROR
#define CLEAR_NCQ_ERROR

#define PHY_EVENTS_STATUS

static void get_lrate_mode(struct asd_phy *phy, u8 oob_mode)
{}

static void asd_phy_event_tasklet(struct asd_ascb *ascb,
					 struct done_list_struct *dl)
{}

/* If phys are enabled sparsely, this will do the right thing. */
static unsigned ord_phy(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
{}

/**
 * asd_get_attached_sas_addr -- extract/generate attached SAS address
 * @phy: pointer to asd_phy
 * @sas_addr: pointer to buffer where the SAS address is to be written
 *
 * This function extracts the SAS address from an IDENTIFY frame
 * received.  If OOB is SATA, then a SAS address is generated from the
 * HA tables.
 *
 * LOCKING: the frame_rcvd_lock needs to be held since this parses the frame
 * buffer.
 */
static void asd_get_attached_sas_addr(struct asd_phy *phy, u8 *sas_addr)
{}

static void asd_form_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
{}

static void asd_deform_port(struct asd_ha_struct *asd_ha, struct asd_phy *phy)
{}

static void asd_bytes_dmaed_tasklet(struct asd_ascb *ascb,
				    struct done_list_struct *dl,
				    int edb_id, int phy_id)
{}

static void asd_link_reset_err_tasklet(struct asd_ascb *ascb,
				       struct done_list_struct *dl,
				       int phy_id)
{}

static void asd_primitive_rcvd_tasklet(struct asd_ascb *ascb,
				       struct done_list_struct *dl,
				       int phy_id)
{}

/**
 * asd_invalidate_edb -- invalidate an EDB and if necessary post the ESCB
 * @ascb: pointer to Empty SCB
 * @edb_id: index [0,6] to the empty data buffer which is to be invalidated
 *
 * After an EDB has been invalidated, if all EDBs in this ESCB have been
 * invalidated, the ESCB is posted back to the sequencer.
 * Context is tasklet/IRQ.
 */
void asd_invalidate_edb(struct asd_ascb *ascb, int edb_id)
{}

static void escb_tasklet_complete(struct asd_ascb *ascb,
				  struct done_list_struct *dl)
{}

int asd_init_post_escbs(struct asd_ha_struct *asd_ha)
{}

/* ---------- CONTROL PHY ---------- */

#define CONTROL_PHY_STATUS

/**
 * control_phy_tasklet_complete -- tasklet complete for CONTROL PHY ascb
 * @ascb: pointer to an ascb
 * @dl: pointer to the done list entry
 *
 * This function completes a CONTROL PHY scb and frees the ascb.
 * A note on LEDs:
 *  - an LED blinks if there is IO though it,
 *  - if a device is connected to the LED, it is lit,
 *  - if no device is connected to the LED, is is dimmed (off).
 */
static void control_phy_tasklet_complete(struct asd_ascb *ascb,
					 struct done_list_struct *dl)
{}

static void set_speed_mask(u8 *speed_mask, struct asd_phy_desc *pd)
{}

/**
 * asd_build_control_phy -- build a CONTROL PHY SCB
 * @ascb: pointer to an ascb
 * @phy_id: phy id to control, integer
 * @subfunc: subfunction, what to actually to do the phy
 *
 * This function builds a CONTROL PHY scb.  No allocation of any kind
 * is performed. @ascb is allocated with the list function.
 * The caller can override the ascb->tasklet_complete to point
 * to its own callback function.  It must call asd_ascb_free()
 * at its tasklet complete function.
 * See the default implementation.
 */
void asd_build_control_phy(struct asd_ascb *ascb, int phy_id, u8 subfunc)
{}

/* ---------- INITIATE LINK ADM TASK ---------- */

#if 0

static void link_adm_tasklet_complete(struct asd_ascb *ascb,
				      struct done_list_struct *dl)
{
	u8 opcode = dl->opcode;
	struct initiate_link_adm *link_adm = &ascb->scb->link_adm;
	u8 phy_id = link_adm->phy_id;

	if (opcode != TC_NO_ERROR) {
		asd_printk("phy%d: link adm task 0x%x completed with error "
			   "0x%x\n", phy_id, link_adm->sub_func, opcode);
	}
	ASD_DPRINTK("phy%d: link adm task 0x%x: 0x%x\n",
		    phy_id, link_adm->sub_func, opcode);

	asd_ascb_free(ascb);
}

void asd_build_initiate_link_adm_task(struct asd_ascb *ascb, int phy_id,
				      u8 subfunc)
{
	struct scb *scb = ascb->scb;
	struct initiate_link_adm *link_adm = &scb->link_adm;

	scb->header.opcode = INITIATE_LINK_ADM_TASK;

	link_adm->phy_id = phy_id;
	link_adm->sub_func = subfunc;
	link_adm->conn_handle = cpu_to_le16(0xFFFF);

	ascb->tasklet_complete = link_adm_tasklet_complete;
}

#endif  /*  0  */

/* ---------- SCB timer ---------- */

/**
 * asd_ascb_timedout -- called when a pending SCB's timer has expired
 * @t: Timer context used to fetch the SCB
 *
 * This is the default timeout function which does the most necessary.
 * Upper layers can implement their own timeout function, say to free
 * resources they have with this SCB, and then call this one at the
 * end of their timeout function.  To do this, one should initialize
 * the ascb->timer.{function, expires} prior to calling the post
 * function. The timer is started by the post function.
 */
void asd_ascb_timedout(struct timer_list *t)
{}

/* ---------- CONTROL PHY ---------- */

/* Given the spec value, return a driver value. */
static const int phy_func_table[] =;

int asd_control_phy(struct asd_sas_phy *phy, enum phy_func func, void *arg)
{}