root/sound/firewire/motu/motu-transaction.c

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

DEFINITIONS

This source file includes following definitions.
  1. snd_motu_transaction_read
  2. snd_motu_transaction_write
  3. handle_message
  4. snd_motu_transaction_reregister
  5. snd_motu_transaction_register
  6. snd_motu_transaction_unregister

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * motu-transaction.c - a part of driver for MOTU FireWire series
   4  *
   5  * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
   6  */
   7 
   8 
   9 #include "motu.h"
  10 
  11 #define SND_MOTU_ADDR_BASE      0xfffff0000000ULL
  12 #define ASYNC_ADDR_HI  0x0b04
  13 #define ASYNC_ADDR_LO  0x0b08
  14 
  15 int snd_motu_transaction_read(struct snd_motu *motu, u32 offset, __be32 *reg,
  16                               size_t size)
  17 {
  18         int tcode;
  19 
  20         if (size % sizeof(__be32) > 0 || size <= 0)
  21                 return -EINVAL;
  22         if (size == sizeof(__be32))
  23                 tcode = TCODE_READ_QUADLET_REQUEST;
  24         else
  25                 tcode = TCODE_READ_BLOCK_REQUEST;
  26 
  27         return snd_fw_transaction(motu->unit, tcode,
  28                                   SND_MOTU_ADDR_BASE + offset, reg, size, 0);
  29 }
  30 
  31 int snd_motu_transaction_write(struct snd_motu *motu, u32 offset, __be32 *reg,
  32                                size_t size)
  33 {
  34         int tcode;
  35 
  36         if (size % sizeof(__be32) > 0 || size <= 0)
  37                 return -EINVAL;
  38         if (size == sizeof(__be32))
  39                 tcode = TCODE_WRITE_QUADLET_REQUEST;
  40         else
  41                 tcode = TCODE_WRITE_BLOCK_REQUEST;
  42 
  43         return snd_fw_transaction(motu->unit, tcode,
  44                                   SND_MOTU_ADDR_BASE + offset, reg, size, 0);
  45 }
  46 
  47 static void handle_message(struct fw_card *card, struct fw_request *request,
  48                            int tcode, int destination, int source,
  49                            int generation, unsigned long long offset,
  50                            void *data, size_t length, void *callback_data)
  51 {
  52         struct snd_motu *motu = callback_data;
  53         __be32 *buf = (__be32 *)data;
  54         unsigned long flags;
  55 
  56         if (tcode != TCODE_WRITE_QUADLET_REQUEST) {
  57                 fw_send_response(card, request, RCODE_COMPLETE);
  58                 return;
  59         }
  60 
  61         if (offset != motu->async_handler.offset || length != 4) {
  62                 fw_send_response(card, request, RCODE_ADDRESS_ERROR);
  63                 return;
  64         }
  65 
  66         spin_lock_irqsave(&motu->lock, flags);
  67         motu->msg = be32_to_cpu(*buf);
  68         spin_unlock_irqrestore(&motu->lock, flags);
  69 
  70         fw_send_response(card, request, RCODE_COMPLETE);
  71 
  72         wake_up(&motu->hwdep_wait);
  73 }
  74 
  75 int snd_motu_transaction_reregister(struct snd_motu *motu)
  76 {
  77         struct fw_device *device = fw_parent_device(motu->unit);
  78         __be32 data;
  79         int err;
  80 
  81         if (motu->async_handler.callback_data == NULL)
  82                 return -EINVAL;
  83 
  84         /* Register messaging address. Block transaction is not allowed. */
  85         data = cpu_to_be32((device->card->node_id << 16) |
  86                            (motu->async_handler.offset >> 32));
  87         err = snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data,
  88                                          sizeof(data));
  89         if (err < 0)
  90                 return err;
  91 
  92         data = cpu_to_be32(motu->async_handler.offset);
  93         return snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data,
  94                                           sizeof(data));
  95 }
  96 
  97 int snd_motu_transaction_register(struct snd_motu *motu)
  98 {
  99         static const struct fw_address_region resp_register_region = {
 100                 .start  = 0xffffe0000000ull,
 101                 .end    = 0xffffe000ffffull,
 102         };
 103         int err;
 104 
 105         /* Perhaps, 4 byte messages are transferred. */
 106         motu->async_handler.length = 4;
 107         motu->async_handler.address_callback = handle_message;
 108         motu->async_handler.callback_data = motu;
 109 
 110         err = fw_core_add_address_handler(&motu->async_handler,
 111                                           &resp_register_region);
 112         if (err < 0)
 113                 return err;
 114 
 115         err = snd_motu_transaction_reregister(motu);
 116         if (err < 0) {
 117                 fw_core_remove_address_handler(&motu->async_handler);
 118                 motu->async_handler.address_callback = NULL;
 119         }
 120 
 121         return err;
 122 }
 123 
 124 void snd_motu_transaction_unregister(struct snd_motu *motu)
 125 {
 126         __be32 data;
 127 
 128         if (motu->async_handler.address_callback != NULL)
 129                 fw_core_remove_address_handler(&motu->async_handler);
 130         motu->async_handler.address_callback = NULL;
 131 
 132         /* Unregister the address. */
 133         data = cpu_to_be32(0x00000000);
 134         snd_motu_transaction_write(motu, ASYNC_ADDR_HI, &data, sizeof(data));
 135         snd_motu_transaction_write(motu, ASYNC_ADDR_LO, &data, sizeof(data));
 136 }

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