Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  Functions for assembling fcx enabled I/O control blocks.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *    Copyright IBM Corp. 2008
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *    Author(s): Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/types.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/string.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/err.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <asm/fcx.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include "cio.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  * tcw_get_intrg - return pointer to associated interrogate tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @tcw: pointer to the original tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  * Return a pointer to the interrogate tcw associated with the specified tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23)  * or %NULL if there is no associated interrogate tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) struct tcw *tcw_get_intrg(struct tcw *tcw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	return (struct tcw *) ((addr_t) tcw->intrg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) EXPORT_SYMBOL(tcw_get_intrg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * tcw_get_data - return pointer to input/output data associated with tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  * @tcw: pointer to the tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35)  * Return the input or output data address specified in the tcw depending
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36)  * on whether the r-bit or the w-bit is set. If neither bit is set, return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37)  * %NULL.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) void *tcw_get_data(struct tcw *tcw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	if (tcw->r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		return (void *) ((addr_t) tcw->input);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 	if (tcw->w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 		return (void *) ((addr_t) tcw->output);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 	return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) EXPORT_SYMBOL(tcw_get_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * tcw_get_tccb - return pointer to tccb associated with tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  * @tcw: pointer to the tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53)  * Return pointer to the tccb associated with this tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) struct tccb *tcw_get_tccb(struct tcw *tcw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	return (struct tccb *) ((addr_t) tcw->tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) EXPORT_SYMBOL(tcw_get_tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * tcw_get_tsb - return pointer to tsb associated with tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * @tcw: pointer to the tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * Return pointer to the tsb associated with this tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) struct tsb *tcw_get_tsb(struct tcw *tcw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	return (struct tsb *) ((addr_t) tcw->tsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) EXPORT_SYMBOL(tcw_get_tsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74)  * tcw_init - initialize tcw data structure
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75)  * @tcw: pointer to the tcw to be initialized
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * @r: initial value of the r-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  * @w: initial value of the w-bit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * Initialize all fields of the specified tcw data structure with zero and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * fill in the format, flags, r and w fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) void tcw_init(struct tcw *tcw, int r, int w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 	memset(tcw, 0, sizeof(struct tcw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	tcw->format = TCW_FORMAT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 	tcw->flags = TCW_FLAGS_TIDAW_FORMAT(TCW_TIDAW_FORMAT_DEFAULT);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 	if (r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		tcw->r = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	if (w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 		tcw->w = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) EXPORT_SYMBOL(tcw_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) static inline size_t tca_size(struct tccb *tccb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	return tccb->tcah.tcal - 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) static u32 calc_dcw_count(struct tccb *tccb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	int offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	struct dcw *dcw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 	u32 count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	size_t size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 	size = tca_size(tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	for (offset = 0; offset < size;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 		dcw = (struct dcw *) &tccb->tca[offset];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 		count += dcw->count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 		if (!(dcw->flags & DCW_FLAGS_CC))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 		offset += sizeof(struct dcw) + ALIGN((int) dcw->cd_count, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	return count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static u32 calc_cbc_size(struct tidaw *tidaw, int num)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	u32 cbc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	u32 cbc_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	u64 data_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	for (i = 0; i < num; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 		if (tidaw[i].flags & TIDAW_FLAGS_LAST)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 		/* TODO: find out if padding applies to total of data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		 * transferred or data transferred by this tidaw. Assumption:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 		 * applies to total. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 		data_count += tidaw[i].count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		if (tidaw[i].flags & TIDAW_FLAGS_INSERT_CBC) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 			cbc_data = 4 + ALIGN(data_count, 4) - data_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 			cbc_count += cbc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 			data_count += cbc_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 	return cbc_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  * tcw_finalize - finalize tcw length fields and tidaw list
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * @tcw: pointer to the tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * @num_tidaws: the number of tidaws used to address input/output data or zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * if no tida is used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * Calculate the input-/output-count and tccbl field in the tcw, add a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  * tcat the tccb and terminate the data tidaw list if used.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  * Note: in case input- or output-tida is used, the tidaw-list must be stored
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * in contiguous storage (no ttic). The tcal field in the tccb must be
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  * up-to-date.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) void tcw_finalize(struct tcw *tcw, int num_tidaws)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	struct tidaw *tidaw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 	struct tccb *tccb;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	struct tccb_tcat *tcat;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 	u32 count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 	/* Terminate tidaw list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	tidaw = tcw_get_data(tcw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	if (num_tidaws > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 		tidaw[num_tidaws - 1].flags |= TIDAW_FLAGS_LAST;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	/* Add tcat to tccb. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	tccb = tcw_get_tccb(tcw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	tcat = (struct tccb_tcat *) &tccb->tca[tca_size(tccb)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	memset(tcat, 0, sizeof(*tcat));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	/* Calculate tcw input/output count and tcat transport count. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	count = calc_dcw_count(tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	if (tcw->w && (tcw->flags & TCW_FLAGS_OUTPUT_TIDA))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 		count += calc_cbc_size(tidaw, num_tidaws);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if (tcw->r)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		tcw->input_count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 	else if (tcw->w)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		tcw->output_count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 	tcat->count = ALIGN(count, 4) + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 	/* Calculate tccbl. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 	tcw->tccbl = (sizeof(struct tccb) + tca_size(tccb) +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		      sizeof(struct tccb_tcat) - 20) >> 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) EXPORT_SYMBOL(tcw_finalize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)  * tcw_set_intrg - set the interrogate tcw address of a tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)  * @tcw: the tcw address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186)  * @intrg_tcw: the address of the interrogate tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188)  * Set the address of the interrogate tcw in the specified tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) void tcw_set_intrg(struct tcw *tcw, struct tcw *intrg_tcw)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 	tcw->intrg = (u32) ((addr_t) intrg_tcw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) EXPORT_SYMBOL(tcw_set_intrg);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197)  * tcw_set_data - set data address and tida flag of a tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)  * @tcw: the tcw address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)  * @data: the data address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200)  * @use_tidal: zero of the data address specifies a contiguous block of data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201)  * non-zero if it specifies a list if tidaws.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203)  * Set the input/output data address of a tcw (depending on the value of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204)  * r-flag and w-flag). If @use_tidal is non-zero, the corresponding tida flag
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * is set as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) void tcw_set_data(struct tcw *tcw, void *data, int use_tidal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 	if (tcw->r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		tcw->input = (u64) ((addr_t) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 		if (use_tidal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 			tcw->flags |= TCW_FLAGS_INPUT_TIDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 	} else if (tcw->w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 		tcw->output = (u64) ((addr_t) data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		if (use_tidal)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			tcw->flags |= TCW_FLAGS_OUTPUT_TIDA;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) EXPORT_SYMBOL(tcw_set_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)  * tcw_set_tccb - set tccb address of a tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)  * @tcw: the tcw address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224)  * @tccb: the tccb address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)  * Set the address of the tccb in the specified tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) void tcw_set_tccb(struct tcw *tcw, struct tccb *tccb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	tcw->tccb = (u64) ((addr_t) tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) EXPORT_SYMBOL(tcw_set_tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)  * tcw_set_tsb - set tsb address of a tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)  * @tcw: the tcw address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)  * @tsb: the tsb address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)  * Set the address of the tsb in the specified tcw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) void tcw_set_tsb(struct tcw *tcw, struct tsb *tsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 	tcw->tsb = (u64) ((addr_t) tsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) EXPORT_SYMBOL(tcw_set_tsb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248)  * tccb_init - initialize tccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249)  * @tccb: the tccb address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)  * @size: the maximum size of the tccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)  * @sac: the service-action-code to be user
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)  * Initialize the header of the specified tccb by resetting all values to zero
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)  * and filling in defaults for format, sac and initial tcal fields.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) void tccb_init(struct tccb *tccb, size_t size, u32 sac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 	memset(tccb, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 	tccb->tcah.format = TCCB_FORMAT_DEFAULT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 	tccb->tcah.sac = sac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 	tccb->tcah.tcal = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) EXPORT_SYMBOL(tccb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266)  * tsb_init - initialize tsb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267)  * @tsb: the tsb address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269)  * Initialize the specified tsb by resetting all values to zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) void tsb_init(struct tsb *tsb)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 	memset(tsb, 0, sizeof(*tsb));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) EXPORT_SYMBOL(tsb_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278)  * tccb_add_dcw - add a dcw to the tccb
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279)  * @tccb: the tccb address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280)  * @tccb_size: the maximum tccb size
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281)  * @cmd: the dcw command
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282)  * @flags: flags for the dcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283)  * @cd: pointer to control data for this dcw or NULL if none is required
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284)  * @cd_count: number of control data bytes for this dcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285)  * @count: number of data bytes for this dcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287)  * Add a new dcw to the specified tccb by writing the dcw information specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288)  * by @cmd, @flags, @cd, @cd_count and @count to the tca of the tccb. Return
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289)  * a pointer to the newly added dcw on success or -%ENOSPC if the new dcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)  * would exceed the available space as defined by @tccb_size.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292)  * Note: the tcal field of the tccb header will be updates to reflect added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293)  * content.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) struct dcw *tccb_add_dcw(struct tccb *tccb, size_t tccb_size, u8 cmd, u8 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 			 void *cd, u8 cd_count, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 	struct dcw *dcw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	int size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	int tca_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	/* Check for space. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	tca_offset = tca_size(tccb);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	size = ALIGN(sizeof(struct dcw) + cd_count, 4);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	if (sizeof(struct tccb_tcah) + tca_offset + size +
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	    sizeof(struct tccb_tcat) > tccb_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 		return ERR_PTR(-ENOSPC);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	/* Add dcw to tca. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	dcw = (struct dcw *) &tccb->tca[tca_offset];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	memset(dcw, 0, size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	dcw->cmd = cmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	dcw->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	dcw->count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	dcw->cd_count = cd_count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 	if (cd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 		memcpy(&dcw->cd[0], cd, cd_count);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	tccb->tcah.tcal += size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	return dcw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) EXPORT_SYMBOL(tccb_add_dcw);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)  * tcw_add_tidaw - add a tidaw to a tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324)  * @tcw: the tcw address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325)  * @num_tidaws: the current number of tidaws
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326)  * @flags: flags for the new tidaw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327)  * @addr: address value for the new tidaw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)  * @count: count value for the new tidaw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330)  * Add a new tidaw to the input/output data tidaw-list of the specified tcw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331)  * (depending on the value of the r-flag and w-flag) and return a pointer to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)  * the new tidaw.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334)  * Note: the tidaw-list is assumed to be contiguous with no ttics. The caller
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335)  * must ensure that there is enough space for the new tidaw. The last-tidaw
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)  * flag for the last tidaw in the list will be set by tcw_finalize.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) struct tidaw *tcw_add_tidaw(struct tcw *tcw, int num_tidaws, u8 flags,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 			    void *addr, u32 count)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	struct tidaw *tidaw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	/* Add tidaw to tidaw-list. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	tidaw = ((struct tidaw *) tcw_get_data(tcw)) + num_tidaws;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 	memset(tidaw, 0, sizeof(struct tidaw));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 	tidaw->flags = flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 	tidaw->count = count;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 	tidaw->addr = (u64) ((addr_t) addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	return tidaw;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) EXPORT_SYMBOL(tcw_add_tidaw);