cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

bebob_command.c (7793B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * bebob_command.c - driver for BeBoB based devices
      4 *
      5 * Copyright (c) 2013-2014 Takashi Sakamoto
      6 */
      7
      8#include "./bebob.h"
      9
     10int avc_audio_set_selector(struct fw_unit *unit, unsigned int subunit_id,
     11			   unsigned int fb_id, unsigned int num)
     12{
     13	u8 *buf;
     14	int err;
     15
     16	buf = kzalloc(12, GFP_KERNEL);
     17	if (buf == NULL)
     18		return -ENOMEM;
     19
     20	buf[0]  = 0x00;		/* AV/C CONTROL */
     21	buf[1]  = 0x08 | (0x07 & subunit_id);	/* AUDIO SUBUNIT ID */
     22	buf[2]  = 0xb8;		/* FUNCTION BLOCK  */
     23	buf[3]  = 0x80;		/* type is 'selector'*/
     24	buf[4]  = 0xff & fb_id;	/* function block id */
     25	buf[5]  = 0x10;		/* control attribute is CURRENT */
     26	buf[6]  = 0x02;		/* selector length is 2 */
     27	buf[7]  = 0xff & num;	/* input function block plug number */
     28	buf[8]  = 0x01;		/* control selector is SELECTOR_CONTROL */
     29
     30	err = fcp_avc_transaction(unit, buf, 12, buf, 12,
     31				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
     32				  BIT(6) | BIT(7) | BIT(8));
     33	if (err < 0)
     34		;
     35	else if (err < 9)
     36		err = -EIO;
     37	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
     38		err = -ENOSYS;
     39	else if (buf[0] == 0x0a) /* REJECTED */
     40		err = -EINVAL;
     41	else
     42		err = 0;
     43
     44	kfree(buf);
     45	return err;
     46}
     47
     48int avc_audio_get_selector(struct fw_unit *unit, unsigned int subunit_id,
     49			   unsigned int fb_id, unsigned int *num)
     50{
     51	u8 *buf;
     52	int err;
     53
     54	buf = kzalloc(12, GFP_KERNEL);
     55	if (buf == NULL)
     56		return -ENOMEM;
     57
     58	buf[0]  = 0x01;		/* AV/C STATUS */
     59	buf[1]  = 0x08 | (0x07 & subunit_id);	/* AUDIO SUBUNIT ID */
     60	buf[2]  = 0xb8;		/* FUNCTION BLOCK */
     61	buf[3]  = 0x80;		/* type is 'selector'*/
     62	buf[4]  = 0xff & fb_id;	/* function block id */
     63	buf[5]  = 0x10;		/* control attribute is CURRENT */
     64	buf[6]  = 0x02;		/* selector length is 2 */
     65	buf[7]  = 0xff;		/* input function block plug number */
     66	buf[8]  = 0x01;		/* control selector is SELECTOR_CONTROL */
     67
     68	err = fcp_avc_transaction(unit, buf, 12, buf, 12,
     69				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
     70				  BIT(6) | BIT(8));
     71	if (err < 0)
     72		;
     73	else if (err < 9)
     74		err = -EIO;
     75	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
     76		err = -ENOSYS;
     77	else if (buf[0] == 0x0a) /* REJECTED */
     78		err = -EINVAL;
     79	else if (buf[0] == 0x0b) /* IN TRANSITION */
     80		err = -EAGAIN;
     81	if (err < 0)
     82		goto end;
     83
     84	*num = buf[7];
     85	err = 0;
     86end:
     87	kfree(buf);
     88	return err;
     89}
     90
     91static inline void
     92avc_bridgeco_fill_extension_addr(u8 *buf, u8 *addr)
     93{
     94	buf[1] = addr[0];
     95	memcpy(buf + 4, addr + 1, 5);
     96}
     97
     98static inline void
     99avc_bridgeco_fill_plug_info_extension_command(u8 *buf, u8 *addr,
    100					      unsigned int itype)
    101{
    102	buf[0] = 0x01;	/* AV/C STATUS */
    103	buf[2] = 0x02;	/* AV/C GENERAL PLUG INFO */
    104	buf[3] = 0xc0;	/* BridgeCo extension */
    105	avc_bridgeco_fill_extension_addr(buf, addr);
    106	buf[9] = itype;	/* info type */
    107}
    108
    109int avc_bridgeco_get_plug_type(struct fw_unit *unit,
    110			       u8 addr[AVC_BRIDGECO_ADDR_BYTES],
    111			       enum avc_bridgeco_plug_type *type)
    112{
    113	u8 *buf;
    114	int err;
    115
    116	buf = kzalloc(12, GFP_KERNEL);
    117	if (buf == NULL)
    118		return -ENOMEM;
    119
    120	/* Info type is 'plug type'. */
    121	avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x00);
    122
    123	err = fcp_avc_transaction(unit, buf, 12, buf, 12,
    124				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
    125				  BIT(6) | BIT(7) | BIT(9));
    126	if (err < 0)
    127		;
    128	else if (err < 11)
    129		err = -EIO;
    130	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
    131		err = -ENOSYS;
    132	else if (buf[0] == 0x0a) /* REJECTED */
    133		err = -EINVAL;
    134	else if (buf[0] == 0x0b) /* IN TRANSITION */
    135		err = -EAGAIN;
    136	if (err < 0)
    137		goto end;
    138
    139	*type = buf[10];
    140	err = 0;
    141end:
    142	kfree(buf);
    143	return err;
    144}
    145
    146int avc_bridgeco_get_plug_ch_count(struct fw_unit *unit, u8 addr[AVC_BRIDGECO_ADDR_BYTES],
    147				   unsigned int *ch_count)
    148{
    149	u8 *buf;
    150	int err;
    151
    152	buf = kzalloc(12, GFP_KERNEL);
    153	if (buf == NULL)
    154		return -ENOMEM;
    155
    156	// Info type is 'plug type'.
    157	avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x02);
    158
    159	err = fcp_avc_transaction(unit, buf, 12, buf, 12,
    160				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
    161				  BIT(6) | BIT(7) | BIT(9));
    162	if (err < 0)
    163		;
    164	else if (err < 11)
    165		err = -EIO;
    166	else if (buf[0] == 0x08) // NOT IMPLEMENTED
    167		err = -ENOSYS;
    168	else if (buf[0] == 0x0a) // REJECTED
    169		err = -EINVAL;
    170	else if (buf[0] == 0x0b) // IN TRANSITION
    171		err = -EAGAIN;
    172	if (err < 0)
    173		goto end;
    174
    175	*ch_count = buf[10];
    176	err = 0;
    177end:
    178	kfree(buf);
    179	return err;
    180}
    181
    182int avc_bridgeco_get_plug_ch_pos(struct fw_unit *unit,
    183				 u8 addr[AVC_BRIDGECO_ADDR_BYTES],
    184				 u8 *buf, unsigned int len)
    185{
    186	int err;
    187
    188	/* Info type is 'channel position'. */
    189	avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x03);
    190
    191	err = fcp_avc_transaction(unit, buf, 12, buf, 256,
    192				  BIT(1) | BIT(2) | BIT(3) | BIT(4) |
    193				  BIT(5) | BIT(6) | BIT(7) | BIT(9));
    194	if (err < 0)
    195		;
    196	else if (err < 11)
    197		err = -EIO;
    198	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
    199		err = -ENOSYS;
    200	else if (buf[0] == 0x0a) /* REJECTED */
    201		err = -EINVAL;
    202	else if (buf[0] == 0x0b) /* IN TRANSITION */
    203		err = -EAGAIN;
    204	if (err < 0)
    205		goto end;
    206
    207	/* Pick up specific data. */
    208	memmove(buf, buf + 10, err - 10);
    209	err = 0;
    210end:
    211	return err;
    212}
    213
    214int avc_bridgeco_get_plug_section_type(struct fw_unit *unit,
    215				       u8 addr[AVC_BRIDGECO_ADDR_BYTES],
    216				       unsigned int id, u8 *type)
    217{
    218	u8 *buf;
    219	int err;
    220
    221	/* section info includes charactors but this module don't need it */
    222	buf = kzalloc(12, GFP_KERNEL);
    223	if (buf == NULL)
    224		return -ENOMEM;
    225
    226	/* Info type is 'section info'. */
    227	avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x07);
    228	buf[10] = 0xff & ++id;	/* section id */
    229
    230	err = fcp_avc_transaction(unit, buf, 12, buf, 12,
    231				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
    232				  BIT(6) | BIT(7) | BIT(9) | BIT(10));
    233	if (err < 0)
    234		;
    235	else if (err < 12)
    236		err = -EIO;
    237	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
    238		err = -ENOSYS;
    239	else if (buf[0] == 0x0a) /* REJECTED */
    240		err = -EINVAL;
    241	else if (buf[0] == 0x0b) /* IN TRANSITION */
    242		err = -EAGAIN;
    243	if (err < 0)
    244		goto end;
    245
    246	*type = buf[11];
    247	err = 0;
    248end:
    249	kfree(buf);
    250	return err;
    251}
    252
    253int avc_bridgeco_get_plug_input(struct fw_unit *unit,
    254				u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 input[7])
    255{
    256	int err;
    257	u8 *buf;
    258
    259	buf = kzalloc(18, GFP_KERNEL);
    260	if (buf == NULL)
    261		return -ENOMEM;
    262
    263	/* Info type is 'plug input'. */
    264	avc_bridgeco_fill_plug_info_extension_command(buf, addr, 0x05);
    265
    266	err = fcp_avc_transaction(unit, buf, 16, buf, 16,
    267				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
    268				  BIT(6) | BIT(7));
    269	if (err < 0)
    270		;
    271	else if (err < 16)
    272		err = -EIO;
    273	else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
    274		err = -ENOSYS;
    275	else if (buf[0] == 0x0a) /* REJECTED */
    276		err = -EINVAL;
    277	else if (buf[0] == 0x0b) /* IN TRANSITION */
    278		err = -EAGAIN;
    279	if (err < 0)
    280		goto end;
    281
    282	memcpy(input, buf + 10, 5);
    283	err = 0;
    284end:
    285	kfree(buf);
    286	return err;
    287}
    288
    289int avc_bridgeco_get_plug_strm_fmt(struct fw_unit *unit,
    290				   u8 addr[AVC_BRIDGECO_ADDR_BYTES], u8 *buf,
    291				   unsigned int *len, unsigned int eid)
    292{
    293	int err;
    294
    295	/* check given buffer */
    296	if ((buf == NULL) || (*len < 12)) {
    297		err = -EINVAL;
    298		goto end;
    299	}
    300
    301	buf[0] = 0x01;	/* AV/C STATUS */
    302	buf[2] = 0x2f;	/* AV/C STREAM FORMAT SUPPORT */
    303	buf[3] = 0xc1;	/* Bridgeco extension - List Request */
    304	avc_bridgeco_fill_extension_addr(buf, addr);
    305	buf[10] = 0xff & eid;	/* Entry ID */
    306
    307	err = fcp_avc_transaction(unit, buf, 12, buf, *len,
    308				  BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) |
    309				  BIT(6) | BIT(7) | BIT(10));
    310	if (err < 0)
    311		;
    312	else if (err < 12)
    313		err = -EIO;
    314	else if (buf[0] == 0x08)        /* NOT IMPLEMENTED */
    315		err = -ENOSYS;
    316	else if (buf[0] == 0x0a)        /* REJECTED */
    317		err = -EINVAL;
    318	else if (buf[0] == 0x0b)        /* IN TRANSITION */
    319		err = -EAGAIN;
    320	else if (buf[10] != eid)
    321		err = -EIO;
    322	if (err < 0)
    323		goto end;
    324
    325	/* Pick up 'stream format info'. */
    326	memmove(buf, buf + 11, err - 11);
    327	*len = err - 11;
    328	err = 0;
    329end:
    330	return err;
    331}