Commit | Line | Data |
---|---|---|
19174295 TS |
1 | /* |
2 | * ff-transaction.c - a part of driver for RME Fireface series | |
3 | * | |
4 | * Copyright (c) 2015-2017 Takashi Sakamoto | |
5 | * | |
6 | * Licensed under the terms of the GNU General Public License, version 2. | |
7 | */ | |
8 | ||
9 | #include "ff.h" | |
10 | ||
11 | static void finish_transmit_midi_msg(struct snd_ff *ff, unsigned int port, | |
12 | int rcode) | |
13 | { | |
14 | struct snd_rawmidi_substream *substream = | |
6aa7de05 | 15 | READ_ONCE(ff->rx_midi_substreams[port]); |
19174295 TS |
16 | |
17 | if (rcode_is_permanent_error(rcode)) { | |
18 | ff->rx_midi_error[port] = true; | |
19 | return; | |
20 | } | |
21 | ||
22 | if (rcode != RCODE_COMPLETE) { | |
23 | /* Transfer the message again, immediately. */ | |
e3a973c6 | 24 | ff->next_ktime[port] = 0; |
19174295 TS |
25 | schedule_work(&ff->rx_midi_work[port]); |
26 | return; | |
27 | } | |
28 | ||
29 | snd_rawmidi_transmit_ack(substream, ff->rx_bytes[port]); | |
30 | ff->rx_bytes[port] = 0; | |
31 | ||
32 | if (!snd_rawmidi_transmit_empty(substream)) | |
33 | schedule_work(&ff->rx_midi_work[port]); | |
34 | } | |
35 | ||
36 | static void finish_transmit_midi0_msg(struct fw_card *card, int rcode, | |
37 | void *data, size_t length, | |
38 | void *callback_data) | |
39 | { | |
40 | struct snd_ff *ff = | |
41 | container_of(callback_data, struct snd_ff, transactions[0]); | |
42 | finish_transmit_midi_msg(ff, 0, rcode); | |
43 | } | |
44 | ||
45 | static void finish_transmit_midi1_msg(struct fw_card *card, int rcode, | |
46 | void *data, size_t length, | |
47 | void *callback_data) | |
48 | { | |
49 | struct snd_ff *ff = | |
50 | container_of(callback_data, struct snd_ff, transactions[1]); | |
51 | finish_transmit_midi_msg(ff, 1, rcode); | |
52 | } | |
53 | ||
54 | static inline void fill_midi_buf(struct snd_ff *ff, unsigned int port, | |
55 | unsigned int index, u8 byte) | |
56 | { | |
57 | ff->msg_buf[port][index] = cpu_to_le32(byte); | |
58 | } | |
59 | ||
60 | static void transmit_midi_msg(struct snd_ff *ff, unsigned int port) | |
61 | { | |
62 | struct snd_rawmidi_substream *substream = | |
6aa7de05 | 63 | READ_ONCE(ff->rx_midi_substreams[port]); |
19174295 TS |
64 | u8 *buf = (u8 *)ff->msg_buf[port]; |
65 | int i, len; | |
66 | ||
67 | struct fw_device *fw_dev = fw_parent_device(ff->unit); | |
68 | unsigned long long addr; | |
69 | int generation; | |
70 | fw_transaction_callback_t callback; | |
71 | ||
72 | if (substream == NULL || snd_rawmidi_transmit_empty(substream)) | |
73 | return; | |
74 | ||
75 | if (ff->rx_bytes[port] > 0 || ff->rx_midi_error[port]) | |
76 | return; | |
77 | ||
78 | /* Do it in next chance. */ | |
79 | if (ktime_after(ff->next_ktime[port], ktime_get())) { | |
80 | schedule_work(&ff->rx_midi_work[port]); | |
81 | return; | |
82 | } | |
83 | ||
84 | len = snd_rawmidi_transmit_peek(substream, buf, | |
85 | SND_FF_MAXIMIM_MIDI_QUADS); | |
86 | if (len <= 0) | |
87 | return; | |
88 | ||
89 | for (i = len - 1; i >= 0; i--) | |
90 | fill_midi_buf(ff, port, i, buf[i]); | |
91 | ||
92 | if (port == 0) { | |
93 | addr = ff->spec->protocol->midi_rx_port_0_reg; | |
94 | callback = finish_transmit_midi0_msg; | |
95 | } else { | |
96 | addr = ff->spec->protocol->midi_rx_port_1_reg; | |
97 | callback = finish_transmit_midi1_msg; | |
98 | } | |
99 | ||
100 | /* Set interval to next transaction. */ | |
101 | ff->next_ktime[port] = ktime_add_ns(ktime_get(), | |
102 | len * 8 * NSEC_PER_SEC / 31250); | |
103 | ff->rx_bytes[port] = len; | |
104 | ||
105 | /* | |
106 | * In Linux FireWire core, when generation is updated with memory | |
107 | * barrier, node id has already been updated. In this module, After | |
108 | * this smp_rmb(), load/store instructions to memory are completed. | |
109 | * Thus, both of generation and node id are available with recent | |
110 | * values. This is a light-serialization solution to handle bus reset | |
111 | * events on IEEE 1394 bus. | |
112 | */ | |
113 | generation = fw_dev->generation; | |
114 | smp_rmb(); | |
115 | fw_send_request(fw_dev->card, &ff->transactions[port], | |
116 | TCODE_WRITE_BLOCK_REQUEST, | |
117 | fw_dev->node_id, generation, fw_dev->max_speed, | |
118 | addr, &ff->msg_buf[port], len * 4, | |
119 | callback, &ff->transactions[port]); | |
120 | } | |
121 | ||
122 | static void transmit_midi0_msg(struct work_struct *work) | |
123 | { | |
124 | struct snd_ff *ff = container_of(work, struct snd_ff, rx_midi_work[0]); | |
125 | ||
126 | transmit_midi_msg(ff, 0); | |
127 | } | |
128 | ||
129 | static void transmit_midi1_msg(struct work_struct *work) | |
130 | { | |
131 | struct snd_ff *ff = container_of(work, struct snd_ff, rx_midi_work[1]); | |
132 | ||
133 | transmit_midi_msg(ff, 1); | |
134 | } | |
135 | ||
136 | static void handle_midi_msg(struct fw_card *card, struct fw_request *request, | |
137 | int tcode, int destination, int source, | |
138 | int generation, unsigned long long offset, | |
139 | void *data, size_t length, void *callback_data) | |
140 | { | |
141 | struct snd_ff *ff = callback_data; | |
142 | __le32 *buf = data; | |
143 | u32 quad; | |
144 | u8 byte; | |
145 | unsigned int index; | |
146 | struct snd_rawmidi_substream *substream; | |
147 | int i; | |
148 | ||
149 | fw_send_response(card, request, RCODE_COMPLETE); | |
150 | ||
151 | for (i = 0; i < length / 4; i++) { | |
152 | quad = le32_to_cpu(buf[i]); | |
153 | ||
154 | /* Message in first port. */ | |
155 | /* | |
156 | * This value may represent the index of this unit when the same | |
157 | * units are on the same IEEE 1394 bus. This driver doesn't use | |
158 | * it. | |
159 | */ | |
160 | index = (quad >> 8) & 0xff; | |
161 | if (index > 0) { | |
6aa7de05 | 162 | substream = READ_ONCE(ff->tx_midi_substreams[0]); |
19174295 TS |
163 | if (substream != NULL) { |
164 | byte = quad & 0xff; | |
165 | snd_rawmidi_receive(substream, &byte, 1); | |
166 | } | |
167 | } | |
168 | ||
169 | /* Message in second port. */ | |
170 | index = (quad >> 24) & 0xff; | |
171 | if (index > 0) { | |
6aa7de05 | 172 | substream = READ_ONCE(ff->tx_midi_substreams[1]); |
19174295 TS |
173 | if (substream != NULL) { |
174 | byte = (quad >> 16) & 0xff; | |
175 | snd_rawmidi_receive(substream, &byte, 1); | |
176 | } | |
177 | } | |
178 | } | |
179 | } | |
180 | ||
181 | static int allocate_own_address(struct snd_ff *ff, int i) | |
182 | { | |
183 | struct fw_address_region midi_msg_region; | |
184 | int err; | |
185 | ||
186 | ff->async_handler.length = SND_FF_MAXIMIM_MIDI_QUADS * 4; | |
187 | ff->async_handler.address_callback = handle_midi_msg; | |
188 | ff->async_handler.callback_data = ff; | |
189 | ||
190 | midi_msg_region.start = 0x000100000000ull * i; | |
191 | midi_msg_region.end = midi_msg_region.start + ff->async_handler.length; | |
192 | ||
193 | err = fw_core_add_address_handler(&ff->async_handler, &midi_msg_region); | |
194 | if (err >= 0) { | |
195 | /* Controllers are allowed to register this region. */ | |
196 | if (ff->async_handler.offset & 0x0000ffffffff) { | |
197 | fw_core_remove_address_handler(&ff->async_handler); | |
198 | err = -EAGAIN; | |
199 | } | |
200 | } | |
201 | ||
202 | return err; | |
203 | } | |
204 | ||
205 | /* | |
206 | * The configuration to start asynchronous transactions for MIDI messages is in | |
207 | * 0x'0000'8010'051c. This register includes the other options, thus this driver | |
208 | * doesn't touch it and leaves the decision to userspace. The userspace MUST add | |
209 | * 0x04000000 to write transactions to the register to receive any MIDI | |
210 | * messages. | |
211 | * | |
212 | * Here, I just describe MIDI-related offsets of the register, in little-endian | |
213 | * order. | |
214 | * | |
215 | * Controllers are allowed to register higher 4 bytes of address to receive | |
216 | * the transactions. The register is 0x'0000'8010'03f4. On the other hand, the | |
217 | * controllers are not allowed to register lower 4 bytes of the address. They | |
218 | * are forced to select from 4 options by writing corresponding bits to | |
219 | * 0x'0000'8010'051c. | |
220 | * | |
221 | * The 3rd-6th bits in MSB of this register are used to indicate lower 4 bytes | |
222 | * of address to which the device transferrs the transactions. | |
223 | * - 6th: 0x'....'....'0000'0180 | |
224 | * - 5th: 0x'....'....'0000'0100 | |
225 | * - 4th: 0x'....'....'0000'0080 | |
226 | * - 3rd: 0x'....'....'0000'0000 | |
227 | * | |
228 | * This driver configure 0x'....'....'0000'0000 for units to receive MIDI | |
229 | * messages. 3rd bit of the register should be configured, however this driver | |
230 | * deligates this task to user space applications due to a restriction that | |
231 | * this register is write-only and the other bits have own effects. | |
232 | * | |
233 | * The 1st and 2nd bits in LSB of this register are used to cancel transferring | |
234 | * asynchronous transactions. These two bits have the same effect. | |
235 | * - 1st/2nd: cancel transferring | |
236 | */ | |
237 | int snd_ff_transaction_reregister(struct snd_ff *ff) | |
238 | { | |
239 | struct fw_card *fw_card = fw_parent_device(ff->unit)->card; | |
240 | u32 addr; | |
241 | __le32 reg; | |
242 | ||
243 | /* | |
244 | * Controllers are allowed to register its node ID and upper 2 byte of | |
245 | * local address to listen asynchronous transactions. | |
246 | */ | |
247 | addr = (fw_card->node_id << 16) | (ff->async_handler.offset >> 32); | |
248 | reg = cpu_to_le32(addr); | |
249 | return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, | |
250 | ff->spec->protocol->midi_high_addr_reg, | |
251 | ®, sizeof(reg), 0); | |
252 | } | |
253 | ||
254 | int snd_ff_transaction_register(struct snd_ff *ff) | |
255 | { | |
256 | int i, err; | |
257 | ||
258 | /* | |
259 | * Allocate in Memory Space of IEC 13213, but lower 4 byte in LSB should | |
260 | * be zero due to device specification. | |
261 | */ | |
262 | for (i = 0; i < 0xffff; i++) { | |
263 | err = allocate_own_address(ff, i); | |
264 | if (err != -EBUSY && err != -EAGAIN) | |
265 | break; | |
266 | } | |
267 | if (err < 0) | |
268 | return err; | |
269 | ||
270 | err = snd_ff_transaction_reregister(ff); | |
271 | if (err < 0) | |
272 | return err; | |
273 | ||
274 | INIT_WORK(&ff->rx_midi_work[0], transmit_midi0_msg); | |
275 | INIT_WORK(&ff->rx_midi_work[1], transmit_midi1_msg); | |
276 | ||
277 | return 0; | |
278 | } | |
279 | ||
280 | void snd_ff_transaction_unregister(struct snd_ff *ff) | |
281 | { | |
282 | __le32 reg; | |
283 | ||
284 | if (ff->async_handler.callback_data == NULL) | |
285 | return; | |
286 | ff->async_handler.callback_data = NULL; | |
287 | ||
288 | /* Release higher 4 bytes of address. */ | |
289 | reg = cpu_to_le32(0x00000000); | |
290 | snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST, | |
291 | ff->spec->protocol->midi_high_addr_reg, | |
292 | ®, sizeof(reg), 0); | |
293 | ||
294 | fw_core_remove_address_handler(&ff->async_handler); | |
295 | } |