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

amdtp-dot.c (10538B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * amdtp-dot.c - a part of driver for Digidesign Digi 002/003 family
      4 *
      5 * Copyright (c) 2014-2015 Takashi Sakamoto
      6 * Copyright (C) 2012 Robin Gareus <robin@gareus.org>
      7 * Copyright (C) 2012 Damien Zammit <damien@zamaudio.com>
      8 */
      9
     10#include <sound/pcm.h>
     11#include "digi00x.h"
     12
     13#define CIP_FMT_AM		0x10
     14
     15/* 'Clock-based rate control mode' is just supported. */
     16#define AMDTP_FDF_AM824		0x00
     17
     18/*
     19 * Nominally 3125 bytes/second, but the MIDI port's clock might be
     20 * 1% too slow, and the bus clock 100 ppm too fast.
     21 */
     22#define MIDI_BYTES_PER_SECOND	3093
     23
     24/*
     25 * Several devices look only at the first eight data blocks.
     26 * In any case, this is more than enough for the MIDI data rate.
     27 */
     28#define MAX_MIDI_RX_BLOCKS	8
     29
     30/* 3 = MAX(DOT_MIDI_IN_PORTS, DOT_MIDI_OUT_PORTS) + 1. */
     31#define MAX_MIDI_PORTS		3
     32
     33/*
     34 * The double-oh-three algorithm was discovered by Robin Gareus and Damien
     35 * Zammit in 2012, with reverse-engineering for Digi 003 Rack.
     36 */
     37struct dot_state {
     38	u8 carry;
     39	u8 idx;
     40	unsigned int off;
     41};
     42
     43struct amdtp_dot {
     44	unsigned int pcm_channels;
     45	struct dot_state state;
     46
     47	struct snd_rawmidi_substream *midi[MAX_MIDI_PORTS];
     48	int midi_fifo_used[MAX_MIDI_PORTS];
     49	int midi_fifo_limit;
     50};
     51
     52/*
     53 * double-oh-three look up table
     54 *
     55 * @param idx index byte (audio-sample data) 0x00..0xff
     56 * @param off channel offset shift
     57 * @return salt to XOR with given data
     58 */
     59#define BYTE_PER_SAMPLE (4)
     60#define MAGIC_DOT_BYTE (2)
     61#define MAGIC_BYTE_OFF(x) (((x) * BYTE_PER_SAMPLE) + MAGIC_DOT_BYTE)
     62static u8 dot_scrt(const u8 idx, const unsigned int off)
     63{
     64	/*
     65	 * the length of the added pattern only depends on the lower nibble
     66	 * of the last non-zero data
     67	 */
     68	static const u8 len[16] = {0, 1, 3, 5, 7, 9, 11, 13, 14,
     69				   12, 10, 8, 6, 4, 2, 0};
     70
     71	/*
     72	 * the lower nibble of the salt. Interleaved sequence.
     73	 * this is walked backwards according to len[]
     74	 */
     75	static const u8 nib[15] = {0x8, 0x7, 0x9, 0x6, 0xa, 0x5, 0xb, 0x4,
     76				   0xc, 0x3, 0xd, 0x2, 0xe, 0x1, 0xf};
     77
     78	/* circular list for the salt's hi nibble. */
     79	static const u8 hir[15] = {0x0, 0x6, 0xf, 0x8, 0x7, 0x5, 0x3, 0x4,
     80				   0xc, 0xd, 0xe, 0x1, 0x2, 0xb, 0xa};
     81
     82	/*
     83	 * start offset for upper nibble mapping.
     84	 * note: 9 is /special/. In the case where the high nibble == 0x9,
     85	 * hir[] is not used and - coincidentally - the salt's hi nibble is
     86	 * 0x09 regardless of the offset.
     87	 */
     88	static const u8 hio[16] = {0, 11, 12, 6, 7, 5, 1, 4,
     89				   3, 0x00, 14, 13, 8, 9, 10, 2};
     90
     91	const u8 ln = idx & 0xf;
     92	const u8 hn = (idx >> 4) & 0xf;
     93	const u8 hr = (hn == 0x9) ? 0x9 : hir[(hio[hn] + off) % 15];
     94
     95	if (len[ln] < off)
     96		return 0x00;
     97
     98	return ((nib[14 + off - len[ln]]) | (hr << 4));
     99}
    100
    101static void dot_encode_step(struct dot_state *state, __be32 *const buffer)
    102{
    103	u8 * const data = (u8 *) buffer;
    104
    105	if (data[MAGIC_DOT_BYTE] != 0x00) {
    106		state->off = 0;
    107		state->idx = data[MAGIC_DOT_BYTE] ^ state->carry;
    108	}
    109	data[MAGIC_DOT_BYTE] ^= state->carry;
    110	state->carry = dot_scrt(state->idx, ++(state->off));
    111}
    112
    113int amdtp_dot_set_parameters(struct amdtp_stream *s, unsigned int rate,
    114			     unsigned int pcm_channels)
    115{
    116	struct amdtp_dot *p = s->protocol;
    117	int err;
    118
    119	if (amdtp_stream_running(s))
    120		return -EBUSY;
    121
    122	/*
    123	 * A first data channel is for MIDI messages, the rest is Multi Bit
    124	 * Linear Audio data channel.
    125	 */
    126	err = amdtp_stream_set_parameters(s, rate, pcm_channels + 1);
    127	if (err < 0)
    128		return err;
    129
    130	s->ctx_data.rx.fdf = AMDTP_FDF_AM824 | s->sfc;
    131
    132	p->pcm_channels = pcm_channels;
    133
    134	/*
    135	 * We do not know the actual MIDI FIFO size of most devices.  Just
    136	 * assume two bytes, i.e., one byte can be received over the bus while
    137	 * the previous one is transmitted over MIDI.
    138	 * (The value here is adjusted for midi_ratelimit_per_packet().)
    139	 */
    140	p->midi_fifo_limit = rate - MIDI_BYTES_PER_SECOND * s->syt_interval + 1;
    141
    142	return 0;
    143}
    144
    145static void write_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
    146			  __be32 *buffer, unsigned int frames,
    147			  unsigned int pcm_frames)
    148{
    149	struct amdtp_dot *p = s->protocol;
    150	unsigned int channels = p->pcm_channels;
    151	struct snd_pcm_runtime *runtime = pcm->runtime;
    152	unsigned int pcm_buffer_pointer;
    153	int remaining_frames;
    154	const u32 *src;
    155	int i, c;
    156
    157	pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
    158	pcm_buffer_pointer %= runtime->buffer_size;
    159
    160	src = (void *)runtime->dma_area +
    161				frames_to_bytes(runtime, pcm_buffer_pointer);
    162	remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
    163
    164	buffer++;
    165	for (i = 0; i < frames; ++i) {
    166		for (c = 0; c < channels; ++c) {
    167			buffer[c] = cpu_to_be32((*src >> 8) | 0x40000000);
    168			dot_encode_step(&p->state, &buffer[c]);
    169			src++;
    170		}
    171		buffer += s->data_block_quadlets;
    172		if (--remaining_frames == 0)
    173			src = (void *)runtime->dma_area;
    174	}
    175}
    176
    177static void read_pcm_s32(struct amdtp_stream *s, struct snd_pcm_substream *pcm,
    178			 __be32 *buffer, unsigned int frames,
    179			 unsigned int pcm_frames)
    180{
    181	struct amdtp_dot *p = s->protocol;
    182	unsigned int channels = p->pcm_channels;
    183	struct snd_pcm_runtime *runtime = pcm->runtime;
    184	unsigned int pcm_buffer_pointer;
    185	int remaining_frames;
    186	u32 *dst;
    187	int i, c;
    188
    189	pcm_buffer_pointer = s->pcm_buffer_pointer + pcm_frames;
    190	pcm_buffer_pointer %= runtime->buffer_size;
    191
    192	dst  = (void *)runtime->dma_area +
    193				frames_to_bytes(runtime, pcm_buffer_pointer);
    194	remaining_frames = runtime->buffer_size - pcm_buffer_pointer;
    195
    196	buffer++;
    197	for (i = 0; i < frames; ++i) {
    198		for (c = 0; c < channels; ++c) {
    199			*dst = be32_to_cpu(buffer[c]) << 8;
    200			dst++;
    201		}
    202		buffer += s->data_block_quadlets;
    203		if (--remaining_frames == 0)
    204			dst = (void *)runtime->dma_area;
    205	}
    206}
    207
    208static void write_pcm_silence(struct amdtp_stream *s, __be32 *buffer,
    209			      unsigned int data_blocks)
    210{
    211	struct amdtp_dot *p = s->protocol;
    212	unsigned int channels, i, c;
    213
    214	channels = p->pcm_channels;
    215
    216	buffer++;
    217	for (i = 0; i < data_blocks; ++i) {
    218		for (c = 0; c < channels; ++c)
    219			buffer[c] = cpu_to_be32(0x40000000);
    220		buffer += s->data_block_quadlets;
    221	}
    222}
    223
    224static bool midi_ratelimit_per_packet(struct amdtp_stream *s, unsigned int port)
    225{
    226	struct amdtp_dot *p = s->protocol;
    227	int used;
    228
    229	used = p->midi_fifo_used[port];
    230	if (used == 0)
    231		return true;
    232
    233	used -= MIDI_BYTES_PER_SECOND * s->syt_interval;
    234	used = max(used, 0);
    235	p->midi_fifo_used[port] = used;
    236
    237	return used < p->midi_fifo_limit;
    238}
    239
    240static inline void midi_use_bytes(struct amdtp_stream *s,
    241				  unsigned int port, unsigned int count)
    242{
    243	struct amdtp_dot *p = s->protocol;
    244
    245	p->midi_fifo_used[port] += amdtp_rate_table[s->sfc] * count;
    246}
    247
    248static void write_midi_messages(struct amdtp_stream *s, __be32 *buffer,
    249		unsigned int data_blocks, unsigned int data_block_counter)
    250{
    251	struct amdtp_dot *p = s->protocol;
    252	unsigned int f, port;
    253	int len;
    254	u8 *b;
    255
    256	for (f = 0; f < data_blocks; f++) {
    257		port = (data_block_counter + f) % 8;
    258		b = (u8 *)&buffer[0];
    259
    260		len = 0;
    261		if (port < MAX_MIDI_PORTS &&
    262		    midi_ratelimit_per_packet(s, port) &&
    263		    p->midi[port] != NULL)
    264			len = snd_rawmidi_transmit(p->midi[port], b + 1, 2);
    265
    266		if (len > 0) {
    267			/*
    268			 * Upper 4 bits of LSB represent port number.
    269			 * - 0000b: physical MIDI port 1.
    270			 * - 0010b: physical MIDI port 2.
    271			 * - 1110b: console MIDI port.
    272			 */
    273			if (port == 2)
    274				b[3] = 0xe0;
    275			else if (port == 1)
    276				b[3] = 0x20;
    277			else
    278				b[3] = 0x00;
    279			b[3] |= len;
    280			midi_use_bytes(s, port, len);
    281		} else {
    282			b[1] = 0;
    283			b[2] = 0;
    284			b[3] = 0;
    285		}
    286		b[0] = 0x80;
    287
    288		buffer += s->data_block_quadlets;
    289	}
    290}
    291
    292static void read_midi_messages(struct amdtp_stream *s, __be32 *buffer,
    293			       unsigned int data_blocks)
    294{
    295	struct amdtp_dot *p = s->protocol;
    296	unsigned int f, port, len;
    297	u8 *b;
    298
    299	for (f = 0; f < data_blocks; f++) {
    300		b = (u8 *)&buffer[0];
    301
    302		len = b[3] & 0x0f;
    303		if (len > 0) {
    304			/*
    305			 * Upper 4 bits of LSB represent port number.
    306			 * - 0000b: physical MIDI port 1. Use port 0.
    307			 * - 1110b: console MIDI port. Use port 2.
    308			 */
    309			if (b[3] >> 4 > 0)
    310				port = 2;
    311			else
    312				port = 0;
    313
    314			if (port < MAX_MIDI_PORTS && p->midi[port])
    315				snd_rawmidi_receive(p->midi[port], b + 1, len);
    316		}
    317
    318		buffer += s->data_block_quadlets;
    319	}
    320}
    321
    322int amdtp_dot_add_pcm_hw_constraints(struct amdtp_stream *s,
    323				     struct snd_pcm_runtime *runtime)
    324{
    325	int err;
    326
    327	/* This protocol delivers 24 bit data in 32bit data channel. */
    328	err = snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
    329	if (err < 0)
    330		return err;
    331
    332	return amdtp_stream_add_pcm_hw_constraints(s, runtime);
    333}
    334
    335void amdtp_dot_midi_trigger(struct amdtp_stream *s, unsigned int port,
    336			  struct snd_rawmidi_substream *midi)
    337{
    338	struct amdtp_dot *p = s->protocol;
    339
    340	if (port < MAX_MIDI_PORTS)
    341		WRITE_ONCE(p->midi[port], midi);
    342}
    343
    344static unsigned int process_ir_ctx_payloads(struct amdtp_stream *s,
    345					    const struct pkt_desc *descs,
    346					    unsigned int packets,
    347					    struct snd_pcm_substream *pcm)
    348{
    349	unsigned int pcm_frames = 0;
    350	int i;
    351
    352	for (i = 0; i < packets; ++i) {
    353		const struct pkt_desc *desc = descs + i;
    354		__be32 *buf = desc->ctx_payload;
    355		unsigned int data_blocks = desc->data_blocks;
    356
    357		if (pcm) {
    358			read_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
    359			pcm_frames += data_blocks;
    360		}
    361
    362		read_midi_messages(s, buf, data_blocks);
    363	}
    364
    365	return pcm_frames;
    366}
    367
    368static unsigned int process_it_ctx_payloads(struct amdtp_stream *s,
    369					    const struct pkt_desc *descs,
    370					    unsigned int packets,
    371					    struct snd_pcm_substream *pcm)
    372{
    373	unsigned int pcm_frames = 0;
    374	int i;
    375
    376	for (i = 0; i < packets; ++i) {
    377		const struct pkt_desc *desc = descs + i;
    378		__be32 *buf = desc->ctx_payload;
    379		unsigned int data_blocks = desc->data_blocks;
    380
    381		if (pcm) {
    382			write_pcm_s32(s, pcm, buf, data_blocks, pcm_frames);
    383			pcm_frames += data_blocks;
    384		} else {
    385			write_pcm_silence(s, buf, data_blocks);
    386		}
    387
    388		write_midi_messages(s, buf, data_blocks,
    389				    desc->data_block_counter);
    390	}
    391
    392	return pcm_frames;
    393}
    394
    395int amdtp_dot_init(struct amdtp_stream *s, struct fw_unit *unit,
    396		 enum amdtp_stream_direction dir)
    397{
    398	amdtp_stream_process_ctx_payloads_t process_ctx_payloads;
    399	unsigned int flags = CIP_NONBLOCKING | CIP_UNAWARE_SYT;
    400
    401	// Use different mode between incoming/outgoing.
    402	if (dir == AMDTP_IN_STREAM)
    403		process_ctx_payloads = process_ir_ctx_payloads;
    404	else
    405		process_ctx_payloads = process_it_ctx_payloads;
    406
    407	return amdtp_stream_init(s, unit, dir, flags, CIP_FMT_AM,
    408				process_ctx_payloads, sizeof(struct amdtp_dot));
    409}
    410
    411void amdtp_dot_reset(struct amdtp_stream *s)
    412{
    413	struct amdtp_dot *p = s->protocol;
    414
    415	p->state.carry = 0x00;
    416	p->state.idx = 0x00;
    417	p->state.off = 0;
    418}