1 /*
2  * tascam-transaction.c - a part of driver for TASCAM FireWire series
3  *
4  * Copyright (c) 2015 Takashi Sakamoto
5  *
6  * Licensed under the terms of the GNU General Public License, version 2.
7  */
8 
9 #include "tascam.h"
10 
11 /*
12  * When return minus value, given argument is not MIDI status.
13  * When return 0, given argument is a beginning of system exclusive.
14  * When return the others, given argument is MIDI data.
15  */
16 static inline int calculate_message_bytes(u8 status)
17 {
18 	switch (status) {
19 	case 0xf6:	/* Tune request. */
20 	case 0xf8:	/* Timing clock. */
21 	case 0xfa:	/* Start. */
22 	case 0xfb:	/* Continue. */
23 	case 0xfc:	/* Stop. */
24 	case 0xfe:	/* Active sensing. */
25 	case 0xff:	/* System reset. */
26 		return 1;
27 	case 0xf1:	/* MIDI time code quarter frame. */
28 	case 0xf3:	/* Song select. */
29 		return 2;
30 	case 0xf2:	/* Song position pointer. */
31 		return 3;
32 	case 0xf0:	/* Exclusive. */
33 		return 0;
34 	case 0xf7:	/* End of exclusive. */
35 		break;
36 	case 0xf4:	/* Undefined. */
37 	case 0xf5:	/* Undefined. */
38 	case 0xf9:	/* Undefined. */
39 	case 0xfd:	/* Undefined. */
40 		break;
41 	default:
42 		switch (status & 0xf0) {
43 		case 0x80:	/* Note on. */
44 		case 0x90:	/* Note off. */
45 		case 0xa0:	/* Polyphonic key pressure. */
46 		case 0xb0:	/* Control change and Mode change. */
47 		case 0xe0:	/* Pitch bend change. */
48 			return 3;
49 		case 0xc0:	/* Program change. */
50 		case 0xd0:	/* Channel pressure. */
51 			return 2;
52 		default:
53 		break;
54 		}
55 	break;
56 	}
57 
58 	return -EINVAL;
59 }
60 
61 static int fill_message(struct snd_fw_async_midi_port *port,
62 			struct snd_rawmidi_substream *substream)
63 {
64 	int i, len, consume;
65 	u8 *label, *msg;
66 	u8 status;
67 
68 	/* The first byte is used for label, the rest for MIDI bytes. */
69 	label = port->buf;
70 	msg = port->buf + 1;
71 
72 	consume = snd_rawmidi_transmit_peek(substream, msg, 3);
73 	if (consume == 0)
74 		return 0;
75 
76 	/* On exclusive message. */
77 	if (port->on_sysex) {
78 		/* Seek the end of exclusives. */
79 		for (i = 0; i < consume; ++i) {
80 			if (msg[i] == 0xf7) {
81 				port->on_sysex = false;
82 				break;
83 			}
84 		}
85 
86 		/* At the end of exclusive message, use label 0x07. */
87 		if (!port->on_sysex) {
88 			consume = i + 1;
89 			*label = (substream->number << 4) | 0x07;
90 		/* During exclusive message, use label 0x04. */
91 		} else if (consume == 3) {
92 			*label = (substream->number << 4) | 0x04;
93 		/* We need to fill whole 3 bytes. Go to next change. */
94 		} else {
95 			return 0;
96 		}
97 
98 		len = consume;
99 	} else {
100 		/* The beginning of exclusives. */
101 		if (msg[0] == 0xf0) {
102 			/* Transfer it in next chance in another condition. */
103 			port->on_sysex = true;
104 			return 0;
105 		} else {
106 			/* On running-status. */
107 			if ((msg[0] & 0x80) != 0x80)
108 				status = port->running_status;
109 			else
110 				status = msg[0];
111 
112 			/* Calculate consume bytes. */
113 			len = calculate_message_bytes(status);
114 			if (len <= 0)
115 				return 0;
116 
117 			/* On running-status. */
118 			if ((msg[0] & 0x80) != 0x80) {
119 				/* Enough MIDI bytes were not retrieved. */
120 				if (consume < len - 1)
121 					return 0;
122 				consume = len - 1;
123 
124 				msg[2] = msg[1];
125 				msg[1] = msg[0];
126 				msg[0] = port->running_status;
127 			} else {
128 				/* Enough MIDI bytes were not retrieved. */
129 				if (consume < len)
130 					return 0;
131 				consume = len;
132 
133 				port->running_status = msg[0];
134 			}
135 		}
136 
137 		*label = (substream->number << 4) | (msg[0] >> 4);
138 	}
139 
140 	if (len > 0 && len < 3)
141 		memset(msg + len, 0, 3 - len);
142 
143 	return consume;
144 }
145 
146 static void async_midi_port_callback(struct fw_card *card, int rcode,
147 				     void *data, size_t length,
148 				     void *callback_data)
149 {
150 	struct snd_fw_async_midi_port *port = callback_data;
151 	struct snd_rawmidi_substream *substream = READ_ONCE(port->substream);
152 
153 	/* This port is closed. */
154 	if (substream == NULL)
155 		return;
156 
157 	if (rcode == RCODE_COMPLETE)
158 		snd_rawmidi_transmit_ack(substream, port->consume_bytes);
159 	else if (!rcode_is_permanent_error(rcode))
160 		/* To start next transaction immediately for recovery. */
161 		port->next_ktime = 0;
162 	else
163 		/* Don't continue processing. */
164 		port->error = true;
165 
166 	port->idling = true;
167 
168 	if (!snd_rawmidi_transmit_empty(substream))
169 		schedule_work(&port->work);
170 }
171 
172 static void midi_port_work(struct work_struct *work)
173 {
174 	struct snd_fw_async_midi_port *port =
175 			container_of(work, struct snd_fw_async_midi_port, work);
176 	struct snd_rawmidi_substream *substream = READ_ONCE(port->substream);
177 	int generation;
178 
179 	/* Under transacting or error state. */
180 	if (!port->idling || port->error)
181 		return;
182 
183 	/* Nothing to do. */
184 	if (substream == NULL || snd_rawmidi_transmit_empty(substream))
185 		return;
186 
187 	/* Do it in next chance. */
188 	if (ktime_after(port->next_ktime, ktime_get())) {
189 		schedule_work(&port->work);
190 		return;
191 	}
192 
193 	/*
194 	 * Fill the buffer. The callee must use snd_rawmidi_transmit_peek().
195 	 * Later, snd_rawmidi_transmit_ack() is called.
196 	 */
197 	memset(port->buf, 0, 4);
198 	port->consume_bytes = fill_message(port, substream);
199 	if (port->consume_bytes <= 0) {
200 		/* Do it in next chance, immediately. */
201 		if (port->consume_bytes == 0) {
202 			port->next_ktime = 0;
203 			schedule_work(&port->work);
204 		} else {
205 			/* Fatal error. */
206 			port->error = true;
207 		}
208 		return;
209 	}
210 
211 	/* Set interval to next transaction. */
212 	port->next_ktime = ktime_add_ns(ktime_get(),
213 				port->consume_bytes * 8 * NSEC_PER_SEC / 31250);
214 
215 	/* Start this transaction. */
216 	port->idling = false;
217 
218 	/*
219 	 * In Linux FireWire core, when generation is updated with memory
220 	 * barrier, node id has already been updated. In this module, After
221 	 * this smp_rmb(), load/store instructions to memory are completed.
222 	 * Thus, both of generation and node id are available with recent
223 	 * values. This is a light-serialization solution to handle bus reset
224 	 * events on IEEE 1394 bus.
225 	 */
226 	generation = port->parent->generation;
227 	smp_rmb();
228 
229 	fw_send_request(port->parent->card, &port->transaction,
230 			TCODE_WRITE_QUADLET_REQUEST,
231 			port->parent->node_id, generation,
232 			port->parent->max_speed,
233 			TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_RX_QUAD,
234 			port->buf, 4, async_midi_port_callback,
235 			port);
236 }
237 
238 void snd_fw_async_midi_port_init(struct snd_fw_async_midi_port *port)
239 {
240 	port->idling = true;
241 	port->error = false;
242 	port->running_status = 0;
243 	port->on_sysex = false;
244 }
245 
246 static void handle_midi_tx(struct fw_card *card, struct fw_request *request,
247 			   int tcode, int destination, int source,
248 			   int generation, unsigned long long offset,
249 			   void *data, size_t length, void *callback_data)
250 {
251 	struct snd_tscm *tscm = callback_data;
252 	u32 *buf = (u32 *)data;
253 	unsigned int messages;
254 	unsigned int i;
255 	unsigned int port;
256 	struct snd_rawmidi_substream *substream;
257 	u8 *b;
258 	int bytes;
259 
260 	if (offset != tscm->async_handler.offset)
261 		goto end;
262 
263 	messages = length / 8;
264 	for (i = 0; i < messages; i++) {
265 		b = (u8 *)(buf + i * 2);
266 
267 		port = b[0] >> 4;
268 		/* TODO: support virtual MIDI ports. */
269 		if (port >= tscm->spec->midi_capture_ports)
270 			goto end;
271 
272 		/* Assume the message length. */
273 		bytes = calculate_message_bytes(b[1]);
274 		/* On MIDI data or exclusives. */
275 		if (bytes <= 0) {
276 			/* Seek the end of exclusives. */
277 			for (bytes = 1; bytes < 4; bytes++) {
278 				if (b[bytes] == 0xf7)
279 					break;
280 			}
281 			if (bytes == 4)
282 				bytes = 3;
283 		}
284 
285 		substream = READ_ONCE(tscm->tx_midi_substreams[port]);
286 		if (substream != NULL)
287 			snd_rawmidi_receive(substream, b + 1, bytes);
288 	}
289 end:
290 	fw_send_response(card, request, RCODE_COMPLETE);
291 }
292 
293 int snd_tscm_transaction_register(struct snd_tscm *tscm)
294 {
295 	static const struct fw_address_region resp_register_region = {
296 		.start	= 0xffffe0000000ull,
297 		.end	= 0xffffe000ffffull,
298 	};
299 	unsigned int i;
300 	int err;
301 
302 	/*
303 	 * Usually, two quadlets are transferred by one transaction. The first
304 	 * quadlet has MIDI messages, the rest includes timestamp.
305 	 * Sometimes, 8 set of the data is transferred by a block transaction.
306 	 */
307 	tscm->async_handler.length = 8 * 8;
308 	tscm->async_handler.address_callback = handle_midi_tx;
309 	tscm->async_handler.callback_data = tscm;
310 
311 	err = fw_core_add_address_handler(&tscm->async_handler,
312 					  &resp_register_region);
313 	if (err < 0)
314 		return err;
315 
316 	err = snd_tscm_transaction_reregister(tscm);
317 	if (err < 0)
318 		goto error;
319 
320 	for (i = 0; i < TSCM_MIDI_OUT_PORT_MAX; i++) {
321 		tscm->out_ports[i].parent = fw_parent_device(tscm->unit);
322 		tscm->out_ports[i].next_ktime = 0;
323 		INIT_WORK(&tscm->out_ports[i].work, midi_port_work);
324 	}
325 
326 	return err;
327 error:
328 	fw_core_remove_address_handler(&tscm->async_handler);
329 	tscm->async_handler.callback_data = NULL;
330 	return err;
331 }
332 
333 /* At bus reset, these registers are cleared. */
334 int snd_tscm_transaction_reregister(struct snd_tscm *tscm)
335 {
336 	struct fw_device *device = fw_parent_device(tscm->unit);
337 	__be32 reg;
338 	int err;
339 
340 	/* Register messaging address. Block transaction is not allowed. */
341 	reg = cpu_to_be32((device->card->node_id << 16) |
342 			  (tscm->async_handler.offset >> 32));
343 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
344 				 TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ADDR_HI,
345 				 &reg, sizeof(reg), 0);
346 	if (err < 0)
347 		return err;
348 
349 	reg = cpu_to_be32(tscm->async_handler.offset);
350 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
351 				 TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ADDR_LO,
352 				 &reg, sizeof(reg), 0);
353 	if (err < 0)
354 		return err;
355 
356 	/* Turn on messaging. */
357 	reg = cpu_to_be32(0x00000001);
358 	err = snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
359 				  TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ON,
360 				  &reg, sizeof(reg), 0);
361 	if (err < 0)
362 		return err;
363 
364 	/* Turn on FireWire LED. */
365 	reg = cpu_to_be32(0x0001008e);
366 	return snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
367 				  TSCM_ADDR_BASE + TSCM_OFFSET_LED_POWER,
368 				  &reg, sizeof(reg), 0);
369 }
370 
371 void snd_tscm_transaction_unregister(struct snd_tscm *tscm)
372 {
373 	__be32 reg;
374 
375 	if (tscm->async_handler.callback_data == NULL)
376 		return;
377 
378 	/* Turn off FireWire LED. */
379 	reg = cpu_to_be32(0x0000008e);
380 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
381 			   TSCM_ADDR_BASE + TSCM_OFFSET_LED_POWER,
382 			   &reg, sizeof(reg), 0);
383 
384 	/* Turn off messaging. */
385 	reg = cpu_to_be32(0x00000000);
386 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
387 			   TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ON,
388 			   &reg, sizeof(reg), 0);
389 
390 	/* Unregister the address. */
391 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
392 			   TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ADDR_HI,
393 			   &reg, sizeof(reg), 0);
394 	snd_fw_transaction(tscm->unit, TCODE_WRITE_QUADLET_REQUEST,
395 			   TSCM_ADDR_BASE + TSCM_OFFSET_MIDI_TX_ADDR_LO,
396 			   &reg, sizeof(reg), 0);
397 
398 	fw_core_remove_address_handler(&tscm->async_handler);
399 	tscm->async_handler.callback_data = NULL;
400 }
401