~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/firewire/motu/motu-transaction.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 }
137 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php