tascam-transaction.c 10 KB

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