Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/firewire/fcp.c
26378 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Function Control Protocol (IEC 61883-1) helper functions
4
*
5
* Copyright (c) Clemens Ladisch <[email protected]>
6
*/
7
8
#include <linux/device.h>
9
#include <linux/firewire.h>
10
#include <linux/firewire-constants.h>
11
#include <linux/list.h>
12
#include <linux/module.h>
13
#include <linux/slab.h>
14
#include <linux/sched.h>
15
#include <linux/spinlock.h>
16
#include <linux/wait.h>
17
#include <linux/delay.h>
18
#include "fcp.h"
19
#include "lib.h"
20
#include "amdtp-stream.h"
21
22
#define CTS_AVC 0x00
23
24
#define ERROR_RETRIES 3
25
#define ERROR_DELAY_MS 5
26
#define FCP_TIMEOUT_MS 125
27
28
int avc_general_set_sig_fmt(struct fw_unit *unit, unsigned int rate,
29
enum avc_general_plug_dir dir,
30
unsigned short pid)
31
{
32
unsigned int sfc;
33
u8 *buf;
34
bool flag;
35
int err;
36
37
flag = false;
38
for (sfc = 0; sfc < CIP_SFC_COUNT; sfc++) {
39
if (amdtp_rate_table[sfc] == rate) {
40
flag = true;
41
break;
42
}
43
}
44
if (!flag)
45
return -EINVAL;
46
47
buf = kzalloc(8, GFP_KERNEL);
48
if (buf == NULL)
49
return -ENOMEM;
50
51
buf[0] = 0x00; /* AV/C CONTROL */
52
buf[1] = 0xff; /* UNIT */
53
if (dir == AVC_GENERAL_PLUG_DIR_IN)
54
buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */
55
else
56
buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */
57
buf[3] = 0xff & pid; /* plug id */
58
buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */
59
buf[5] = 0x07 & sfc; /* FDF-hi. AM824, frequency */
60
buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used)*/
61
buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */
62
63
/* do transaction and check buf[1-5] are the same against command */
64
err = fcp_avc_transaction(unit, buf, 8, buf, 8,
65
BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5));
66
if (err < 0)
67
;
68
else if (err < 8)
69
err = -EIO;
70
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
71
err = -ENOSYS;
72
else if (buf[0] == 0x0a) /* REJECTED */
73
err = -EINVAL;
74
if (err < 0)
75
goto end;
76
77
err = 0;
78
end:
79
kfree(buf);
80
return err;
81
}
82
EXPORT_SYMBOL(avc_general_set_sig_fmt);
83
84
int avc_general_get_sig_fmt(struct fw_unit *unit, unsigned int *rate,
85
enum avc_general_plug_dir dir,
86
unsigned short pid)
87
{
88
unsigned int sfc;
89
u8 *buf;
90
int err;
91
92
buf = kzalloc(8, GFP_KERNEL);
93
if (buf == NULL)
94
return -ENOMEM;
95
96
buf[0] = 0x01; /* AV/C STATUS */
97
buf[1] = 0xff; /* Unit */
98
if (dir == AVC_GENERAL_PLUG_DIR_IN)
99
buf[2] = 0x19; /* INPUT PLUG SIGNAL FORMAT */
100
else
101
buf[2] = 0x18; /* OUTPUT PLUG SIGNAL FORMAT */
102
buf[3] = 0xff & pid; /* plug id */
103
buf[4] = 0x90; /* EOH_1, Form_1, FMT. AM824 */
104
buf[5] = 0xff; /* FDF-hi. AM824, frequency */
105
buf[6] = 0xff; /* FDF-mid. AM824, SYT hi (not used) */
106
buf[7] = 0xff; /* FDF-low. AM824, SYT lo (not used) */
107
108
/* do transaction and check buf[1-4] are the same against command */
109
err = fcp_avc_transaction(unit, buf, 8, buf, 8,
110
BIT(1) | BIT(2) | BIT(3) | BIT(4));
111
if (err < 0)
112
;
113
else if (err < 8)
114
err = -EIO;
115
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
116
err = -ENOSYS;
117
else if (buf[0] == 0x0a) /* REJECTED */
118
err = -EINVAL;
119
else if (buf[0] == 0x0b) /* IN TRANSITION */
120
err = -EAGAIN;
121
if (err < 0)
122
goto end;
123
124
/* check sfc field and pick up rate */
125
sfc = 0x07 & buf[5];
126
if (sfc >= CIP_SFC_COUNT) {
127
err = -EAGAIN; /* also in transition */
128
goto end;
129
}
130
131
*rate = amdtp_rate_table[sfc];
132
err = 0;
133
end:
134
kfree(buf);
135
return err;
136
}
137
EXPORT_SYMBOL(avc_general_get_sig_fmt);
138
139
int avc_general_get_plug_info(struct fw_unit *unit, unsigned int subunit_type,
140
unsigned int subunit_id, unsigned int subfunction,
141
u8 info[AVC_PLUG_INFO_BUF_BYTES])
142
{
143
u8 *buf;
144
int err;
145
146
/* extended subunit in spec.4.2 is not supported */
147
if ((subunit_type == 0x1E) || (subunit_id == 5))
148
return -EINVAL;
149
150
buf = kzalloc(8, GFP_KERNEL);
151
if (buf == NULL)
152
return -ENOMEM;
153
154
buf[0] = 0x01; /* AV/C STATUS */
155
/* UNIT or Subunit, Functionblock */
156
buf[1] = ((subunit_type & 0x1f) << 3) | (subunit_id & 0x7);
157
buf[2] = 0x02; /* PLUG INFO */
158
buf[3] = 0xff & subfunction;
159
160
err = fcp_avc_transaction(unit, buf, 8, buf, 8, BIT(1) | BIT(2));
161
if (err < 0)
162
;
163
else if (err < 8)
164
err = -EIO;
165
else if (buf[0] == 0x08) /* NOT IMPLEMENTED */
166
err = -ENOSYS;
167
else if (buf[0] == 0x0a) /* REJECTED */
168
err = -EINVAL;
169
else if (buf[0] == 0x0b) /* IN TRANSITION */
170
err = -EAGAIN;
171
if (err < 0)
172
goto end;
173
174
info[0] = buf[4];
175
info[1] = buf[5];
176
info[2] = buf[6];
177
info[3] = buf[7];
178
179
err = 0;
180
end:
181
kfree(buf);
182
return err;
183
}
184
EXPORT_SYMBOL(avc_general_get_plug_info);
185
186
static DEFINE_SPINLOCK(transactions_lock);
187
static LIST_HEAD(transactions);
188
189
enum fcp_state {
190
STATE_PENDING,
191
STATE_BUS_RESET,
192
STATE_COMPLETE,
193
STATE_DEFERRED,
194
};
195
196
struct fcp_transaction {
197
struct list_head list;
198
struct fw_unit *unit;
199
void *response_buffer;
200
unsigned int response_size;
201
unsigned int response_match_bytes;
202
enum fcp_state state;
203
wait_queue_head_t wait;
204
bool deferrable;
205
};
206
207
/**
208
* fcp_avc_transaction - send an AV/C command and wait for its response
209
* @unit: a unit on the target device
210
* @command: a buffer containing the command frame; must be DMA-able
211
* @command_size: the size of @command
212
* @response: a buffer for the response frame
213
* @response_size: the maximum size of @response
214
* @response_match_bytes: a bitmap specifying the bytes used to detect the
215
* correct response frame
216
*
217
* This function sends a FCP command frame to the target and waits for the
218
* corresponding response frame to be returned.
219
*
220
* Because it is possible for multiple FCP transactions to be active at the
221
* same time, the correct response frame is detected by the value of certain
222
* bytes. These bytes must be set in @response before calling this function,
223
* and the corresponding bits must be set in @response_match_bytes.
224
*
225
* @command and @response can point to the same buffer.
226
*
227
* Returns the actual size of the response frame, or a negative error code.
228
*/
229
int fcp_avc_transaction(struct fw_unit *unit,
230
const void *command, unsigned int command_size,
231
void *response, unsigned int response_size,
232
unsigned int response_match_bytes)
233
{
234
struct fcp_transaction t;
235
int tcode, ret, tries = 0;
236
237
t.unit = unit;
238
t.response_buffer = response;
239
t.response_size = response_size;
240
t.response_match_bytes = response_match_bytes;
241
t.state = STATE_PENDING;
242
init_waitqueue_head(&t.wait);
243
t.deferrable = (*(const u8 *)command == 0x00 || *(const u8 *)command == 0x03);
244
245
spin_lock_irq(&transactions_lock);
246
list_add_tail(&t.list, &transactions);
247
spin_unlock_irq(&transactions_lock);
248
249
for (;;) {
250
tcode = command_size == 4 ? TCODE_WRITE_QUADLET_REQUEST
251
: TCODE_WRITE_BLOCK_REQUEST;
252
ret = snd_fw_transaction(t.unit, tcode,
253
CSR_REGISTER_BASE + CSR_FCP_COMMAND,
254
(void *)command, command_size, 0);
255
if (ret < 0)
256
break;
257
deferred:
258
wait_event_timeout(t.wait, t.state != STATE_PENDING,
259
msecs_to_jiffies(FCP_TIMEOUT_MS));
260
261
if (t.state == STATE_DEFERRED) {
262
/*
263
* 'AV/C General Specification' define no time limit
264
* on command completion once an INTERIM response has
265
* been sent. but we promise to finish this function
266
* for a caller. Here we use FCP_TIMEOUT_MS for next
267
* interval. This is not in the specification.
268
*/
269
t.state = STATE_PENDING;
270
goto deferred;
271
} else if (t.state == STATE_COMPLETE) {
272
ret = t.response_size;
273
break;
274
} else if (t.state == STATE_BUS_RESET) {
275
msleep(ERROR_DELAY_MS);
276
} else if (++tries >= ERROR_RETRIES) {
277
dev_err(&t.unit->device, "FCP command timed out\n");
278
ret = -EIO;
279
break;
280
}
281
}
282
283
spin_lock_irq(&transactions_lock);
284
list_del(&t.list);
285
spin_unlock_irq(&transactions_lock);
286
287
return ret;
288
}
289
EXPORT_SYMBOL(fcp_avc_transaction);
290
291
/**
292
* fcp_bus_reset - inform the target handler about a bus reset
293
* @unit: the unit that might be used by fcp_avc_transaction()
294
*
295
* This function must be called from the driver's .update handler to inform
296
* the FCP transaction handler that a bus reset has happened. Any pending FCP
297
* transactions are retried.
298
*/
299
void fcp_bus_reset(struct fw_unit *unit)
300
{
301
struct fcp_transaction *t;
302
303
spin_lock_irq(&transactions_lock);
304
list_for_each_entry(t, &transactions, list) {
305
if (t->unit == unit &&
306
(t->state == STATE_PENDING ||
307
t->state == STATE_DEFERRED)) {
308
t->state = STATE_BUS_RESET;
309
wake_up(&t->wait);
310
}
311
}
312
spin_unlock_irq(&transactions_lock);
313
}
314
EXPORT_SYMBOL(fcp_bus_reset);
315
316
/* checks whether the response matches the masked bytes in response_buffer */
317
static bool is_matching_response(struct fcp_transaction *transaction,
318
const void *response, size_t length)
319
{
320
const u8 *p1, *p2;
321
unsigned int mask, i;
322
323
p1 = response;
324
p2 = transaction->response_buffer;
325
mask = transaction->response_match_bytes;
326
327
for (i = 0; ; ++i) {
328
if ((mask & 1) && p1[i] != p2[i])
329
return false;
330
mask >>= 1;
331
if (!mask)
332
return true;
333
if (--length == 0)
334
return false;
335
}
336
}
337
338
static void fcp_response(struct fw_card *card, struct fw_request *request,
339
int tcode, int destination, int source,
340
int generation, unsigned long long offset,
341
void *data, size_t length, void *callback_data)
342
{
343
struct fcp_transaction *t;
344
unsigned long flags;
345
346
if (length < 1 || (*(const u8 *)data & 0xf0) != CTS_AVC)
347
return;
348
349
spin_lock_irqsave(&transactions_lock, flags);
350
list_for_each_entry(t, &transactions, list) {
351
struct fw_device *device = fw_parent_device(t->unit);
352
if (device->card != card ||
353
device->generation != generation)
354
continue;
355
smp_rmb(); /* node_id vs. generation */
356
if (device->node_id != source)
357
continue;
358
359
if (t->state == STATE_PENDING &&
360
is_matching_response(t, data, length)) {
361
if (t->deferrable && *(const u8 *)data == 0x0f) {
362
t->state = STATE_DEFERRED;
363
} else {
364
t->state = STATE_COMPLETE;
365
t->response_size = min_t(unsigned int, length,
366
t->response_size);
367
memcpy(t->response_buffer, data,
368
t->response_size);
369
}
370
wake_up(&t->wait);
371
}
372
}
373
spin_unlock_irqrestore(&transactions_lock, flags);
374
}
375
376
static struct fw_address_handler response_register_handler = {
377
.length = 0x200,
378
.address_callback = fcp_response,
379
};
380
381
static int __init fcp_module_init(void)
382
{
383
static const struct fw_address_region response_register_region = {
384
.start = CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
385
.end = CSR_REGISTER_BASE + CSR_FCP_END,
386
};
387
388
fw_core_add_address_handler(&response_register_handler,
389
&response_register_region);
390
391
return 0;
392
}
393
394
static void __exit fcp_module_exit(void)
395
{
396
WARN_ON(!list_empty(&transactions));
397
fw_core_remove_address_handler(&response_register_handler);
398
}
399
400
module_init(fcp_module_init);
401
module_exit(fcp_module_exit);
402
403