2 * motu-transaction.c - a part of driver for MOTU FireWire series
4 * Copyright (c) 2015-2017 Takashi Sakamoto <o-takashi@sakamocchi.jp>
6 * Licensed under the terms of the GNU General Public License, version 2.
12 #define SND_MOTU_ADDR_BASE 0xfffff0000000ULL
13 #define ASYNC_ADDR_HI 0x0b04
14 #define ASYNC_ADDR_LO 0x0b08
16 int snd_motu_transaction_read(struct snd_motu
*motu
, u32 offset
, __be32
*reg
,
21 if (size
% sizeof(__be32
) > 0 || size
<= 0)
23 if (size
== sizeof(__be32
))
24 tcode
= TCODE_READ_QUADLET_REQUEST
;
26 tcode
= TCODE_READ_BLOCK_REQUEST
;
28 return snd_fw_transaction(motu
->unit
, tcode
,
29 SND_MOTU_ADDR_BASE
+ offset
, reg
, size
, 0);
32 int snd_motu_transaction_write(struct snd_motu
*motu
, u32 offset
, __be32
*reg
,
37 if (size
% sizeof(__be32
) > 0 || size
<= 0)
39 if (size
== sizeof(__be32
))
40 tcode
= TCODE_WRITE_QUADLET_REQUEST
;
42 tcode
= TCODE_WRITE_BLOCK_REQUEST
;
44 return snd_fw_transaction(motu
->unit
, tcode
,
45 SND_MOTU_ADDR_BASE
+ offset
, reg
, size
, 0);
48 static void handle_message(struct fw_card
*card
, struct fw_request
*request
,
49 int tcode
, int destination
, int source
,
50 int generation
, unsigned long long offset
,
51 void *data
, size_t length
, void *callback_data
)
53 struct snd_motu
*motu
= callback_data
;
54 __be32
*buf
= (__be32
*)data
;
57 if (tcode
!= TCODE_WRITE_QUADLET_REQUEST
) {
58 fw_send_response(card
, request
, RCODE_COMPLETE
);
62 if (offset
!= motu
->async_handler
.offset
|| length
!= 4) {
63 fw_send_response(card
, request
, RCODE_ADDRESS_ERROR
);
67 spin_lock_irqsave(&motu
->lock
, flags
);
68 motu
->msg
= be32_to_cpu(*buf
);
69 spin_unlock_irqrestore(&motu
->lock
, flags
);
71 fw_send_response(card
, request
, RCODE_COMPLETE
);
73 wake_up(&motu
->hwdep_wait
);
76 int snd_motu_transaction_reregister(struct snd_motu
*motu
)
78 struct fw_device
*device
= fw_parent_device(motu
->unit
);
82 if (motu
->async_handler
.callback_data
== NULL
)
85 /* Register messaging address. Block transaction is not allowed. */
86 data
= cpu_to_be32((device
->card
->node_id
<< 16) |
87 (motu
->async_handler
.offset
>> 32));
88 err
= snd_motu_transaction_write(motu
, ASYNC_ADDR_HI
, &data
,
93 data
= cpu_to_be32(motu
->async_handler
.offset
);
94 return snd_motu_transaction_write(motu
, ASYNC_ADDR_LO
, &data
,
98 int snd_motu_transaction_register(struct snd_motu
*motu
)
100 static const struct fw_address_region resp_register_region
= {
101 .start
= 0xffffe0000000ull
,
102 .end
= 0xffffe000ffffull
,
106 /* Perhaps, 4 byte messages are transferred. */
107 motu
->async_handler
.length
= 4;
108 motu
->async_handler
.address_callback
= handle_message
;
109 motu
->async_handler
.callback_data
= motu
;
111 err
= fw_core_add_address_handler(&motu
->async_handler
,
112 &resp_register_region
);
116 err
= snd_motu_transaction_reregister(motu
);
118 fw_core_remove_address_handler(&motu
->async_handler
);
119 motu
->async_handler
.address_callback
= NULL
;
125 void snd_motu_transaction_unregister(struct snd_motu
*motu
)
129 if (motu
->async_handler
.address_callback
!= NULL
)
130 fw_core_remove_address_handler(&motu
->async_handler
);
131 motu
->async_handler
.address_callback
= NULL
;
133 /* Unregister the address. */
134 data
= cpu_to_be32(0x00000000);
135 snd_motu_transaction_write(motu
, ASYNC_ADDR_HI
, &data
, sizeof(data
));
136 snd_motu_transaction_write(motu
, ASYNC_ADDR_LO
, &data
, sizeof(data
));