root/sound/firewire/fireface/ff-transaction.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. finish_transmit_midi_msg
  2. finish_transmit_midi0_msg
  3. finish_transmit_midi1_msg
  4. transmit_midi_msg
  5. transmit_midi0_msg
  6. transmit_midi1_msg
  7. handle_midi_msg
  8. allocate_own_address
  9. snd_ff_transaction_reregister
  10. snd_ff_transaction_register
  11. snd_ff_transaction_unregister

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * ff-transaction.c - a part of driver for RME Fireface series
   4  *
   5  * Copyright (c) 2015-2017 Takashi Sakamoto
   6  */
   7 
   8 #include "ff.h"
   9 
  10 static void finish_transmit_midi_msg(struct snd_ff *ff, unsigned int port,
  11                                      int rcode)
  12 {
  13         struct snd_rawmidi_substream *substream =
  14                                 READ_ONCE(ff->rx_midi_substreams[port]);
  15 
  16         if (rcode_is_permanent_error(rcode)) {
  17                 ff->rx_midi_error[port] = true;
  18                 return;
  19         }
  20 
  21         if (rcode != RCODE_COMPLETE) {
  22                 /* Transfer the message again, immediately. */
  23                 ff->next_ktime[port] = 0;
  24                 schedule_work(&ff->rx_midi_work[port]);
  25                 return;
  26         }
  27 
  28         snd_rawmidi_transmit_ack(substream, ff->rx_bytes[port]);
  29         ff->rx_bytes[port] = 0;
  30 
  31         if (!snd_rawmidi_transmit_empty(substream))
  32                 schedule_work(&ff->rx_midi_work[port]);
  33 }
  34 
  35 static void finish_transmit_midi0_msg(struct fw_card *card, int rcode,
  36                                       void *data, size_t length,
  37                                       void *callback_data)
  38 {
  39         struct snd_ff *ff =
  40                 container_of(callback_data, struct snd_ff, transactions[0]);
  41         finish_transmit_midi_msg(ff, 0, rcode);
  42 }
  43 
  44 static void finish_transmit_midi1_msg(struct fw_card *card, int rcode,
  45                                       void *data, size_t length,
  46                                       void *callback_data)
  47 {
  48         struct snd_ff *ff =
  49                 container_of(callback_data, struct snd_ff, transactions[1]);
  50         finish_transmit_midi_msg(ff, 1, rcode);
  51 }
  52 
  53 static void transmit_midi_msg(struct snd_ff *ff, unsigned int port)
  54 {
  55         struct snd_rawmidi_substream *substream =
  56                         READ_ONCE(ff->rx_midi_substreams[port]);
  57         int quad_count;
  58 
  59         struct fw_device *fw_dev = fw_parent_device(ff->unit);
  60         unsigned long long addr;
  61         int generation;
  62         fw_transaction_callback_t callback;
  63         int tcode;
  64 
  65         if (substream == NULL || snd_rawmidi_transmit_empty(substream))
  66                 return;
  67 
  68         if (ff->rx_bytes[port] > 0 || ff->rx_midi_error[port])
  69                 return;
  70 
  71         /* Do it in next chance. */
  72         if (ktime_after(ff->next_ktime[port], ktime_get())) {
  73                 schedule_work(&ff->rx_midi_work[port]);
  74                 return;
  75         }
  76 
  77         quad_count = ff->spec->protocol->fill_midi_msg(ff, substream, port);
  78         if (quad_count <= 0)
  79                 return;
  80 
  81         if (port == 0) {
  82                 addr = ff->spec->midi_rx_addrs[0];
  83                 callback = finish_transmit_midi0_msg;
  84         } else {
  85                 addr = ff->spec->midi_rx_addrs[1];
  86                 callback = finish_transmit_midi1_msg;
  87         }
  88 
  89         /* Set interval to next transaction. */
  90         ff->next_ktime[port] = ktime_add_ns(ktime_get(),
  91                                 ff->rx_bytes[port] * 8 * NSEC_PER_SEC / 31250);
  92 
  93         if (quad_count == 1)
  94                 tcode = TCODE_WRITE_QUADLET_REQUEST;
  95         else
  96                 tcode = TCODE_WRITE_BLOCK_REQUEST;
  97 
  98         /*
  99          * In Linux FireWire core, when generation is updated with memory
 100          * barrier, node id has already been updated. In this module, After
 101          * this smp_rmb(), load/store instructions to memory are completed.
 102          * Thus, both of generation and node id are available with recent
 103          * values. This is a light-serialization solution to handle bus reset
 104          * events on IEEE 1394 bus.
 105          */
 106         generation = fw_dev->generation;
 107         smp_rmb();
 108         fw_send_request(fw_dev->card, &ff->transactions[port], tcode,
 109                         fw_dev->node_id, generation, fw_dev->max_speed,
 110                         addr, &ff->msg_buf[port], quad_count * 4,
 111                         callback, &ff->transactions[port]);
 112 }
 113 
 114 static void transmit_midi0_msg(struct work_struct *work)
 115 {
 116         struct snd_ff *ff = container_of(work, struct snd_ff, rx_midi_work[0]);
 117 
 118         transmit_midi_msg(ff, 0);
 119 }
 120 
 121 static void transmit_midi1_msg(struct work_struct *work)
 122 {
 123         struct snd_ff *ff = container_of(work, struct snd_ff, rx_midi_work[1]);
 124 
 125         transmit_midi_msg(ff, 1);
 126 }
 127 
 128 static void handle_midi_msg(struct fw_card *card, struct fw_request *request,
 129                             int tcode, int destination, int source,
 130                             int generation, unsigned long long offset,
 131                             void *data, size_t length, void *callback_data)
 132 {
 133         struct snd_ff *ff = callback_data;
 134         __le32 *buf = data;
 135 
 136         fw_send_response(card, request, RCODE_COMPLETE);
 137 
 138         offset -= ff->async_handler.offset;
 139         ff->spec->protocol->handle_midi_msg(ff, (unsigned int)offset, buf,
 140                                             length);
 141 }
 142 
 143 static int allocate_own_address(struct snd_ff *ff, int i)
 144 {
 145         struct fw_address_region midi_msg_region;
 146         int err;
 147 
 148         ff->async_handler.length = ff->spec->midi_addr_range;
 149         ff->async_handler.address_callback = handle_midi_msg;
 150         ff->async_handler.callback_data = ff;
 151 
 152         midi_msg_region.start = 0x000100000000ull * i;
 153         midi_msg_region.end = midi_msg_region.start + ff->async_handler.length;
 154 
 155         err = fw_core_add_address_handler(&ff->async_handler, &midi_msg_region);
 156         if (err >= 0) {
 157                 /* Controllers are allowed to register this region. */
 158                 if (ff->async_handler.offset & 0x0000ffffffff) {
 159                         fw_core_remove_address_handler(&ff->async_handler);
 160                         err = -EAGAIN;
 161                 }
 162         }
 163 
 164         return err;
 165 }
 166 
 167 // Controllers are allowed to register higher 4 bytes of destination address to
 168 // receive asynchronous transactions for MIDI messages, while the way to
 169 // register lower 4 bytes of address is different depending on protocols. For
 170 // details, please refer to comments in protocol implementations.
 171 //
 172 // This driver expects userspace applications to configure registers for the
 173 // lower address because in most cases such registers has the other settings.
 174 int snd_ff_transaction_reregister(struct snd_ff *ff)
 175 {
 176         struct fw_card *fw_card = fw_parent_device(ff->unit)->card;
 177         u32 addr;
 178         __le32 reg;
 179 
 180         /*
 181          * Controllers are allowed to register its node ID and upper 2 byte of
 182          * local address to listen asynchronous transactions.
 183          */
 184         addr = (fw_card->node_id << 16) | (ff->async_handler.offset >> 32);
 185         reg = cpu_to_le32(addr);
 186         return snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 187                                   ff->spec->midi_high_addr,
 188                                   &reg, sizeof(reg), 0);
 189 }
 190 
 191 int snd_ff_transaction_register(struct snd_ff *ff)
 192 {
 193         int i, err;
 194 
 195         /*
 196          * Allocate in Memory Space of IEC 13213, but lower 4 byte in LSB should
 197          * be zero due to device specification.
 198          */
 199         for (i = 0; i < 0xffff; i++) {
 200                 err = allocate_own_address(ff, i);
 201                 if (err != -EBUSY && err != -EAGAIN)
 202                         break;
 203         }
 204         if (err < 0)
 205                 return err;
 206 
 207         err = snd_ff_transaction_reregister(ff);
 208         if (err < 0)
 209                 return err;
 210 
 211         INIT_WORK(&ff->rx_midi_work[0], transmit_midi0_msg);
 212         INIT_WORK(&ff->rx_midi_work[1], transmit_midi1_msg);
 213 
 214         return 0;
 215 }
 216 
 217 void snd_ff_transaction_unregister(struct snd_ff *ff)
 218 {
 219         __le32 reg;
 220 
 221         if (ff->async_handler.callback_data == NULL)
 222                 return;
 223         ff->async_handler.callback_data = NULL;
 224 
 225         /* Release higher 4 bytes of address. */
 226         reg = cpu_to_le32(0x00000000);
 227         snd_fw_transaction(ff->unit, TCODE_WRITE_QUADLET_REQUEST,
 228                            ff->spec->midi_high_addr,
 229                            &reg, sizeof(reg), 0);
 230 
 231         fw_core_remove_address_handler(&ff->async_handler);
 232 }

/* [<][>][^][v][top][bottom][index][help] */