tascam-transaction.c 10 KB

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