Commit 11b9153d authored by Wesley W. Terpstra's avatar Wesley W. Terpstra

api: include an API call to request MSI access

parent d905e360
......@@ -435,6 +435,21 @@ eb_status_t eb_device_open_nb(eb_socket_t socket,
eb_user_data_t user_data,
eb_callback_t callback);
/* Enable MSI delivery for this master.
* If successful, the msi_first and msi_last range will be filled with a range
* of addresses on which MSI accesses can be received.
*
* Return codes:
* OK - MSI enabled
* BUSY - No more MSI resources were available
* ABI - No MSI supported by hardware
* FAIL - Failed due to hardware-specific error
*/
EB_PUBLIC
eb_status_t eb_device_enable_msi(eb_device_t device,
eb_address_t *msi_first,
eb_address_t *msi_last);
/* Open a remote Etherbone device at 'address' (default port 0xEBD0) passively.
* The channel is opened and the remote device should initiate the EB exchange.
* This is useful for stream protocols where the master cannot be the initiator.
......@@ -754,6 +769,8 @@ class Device {
width_t width() const;
EB_STATUS_OR_VOID_T enable_msi(eb_address_t* msi_first, eb_address_t* msi_last);
template <typename T>
EB_STATUS_OR_VOID_T sdb_scan_bus(const struct sdb_bridge* bridge, T* user, sdb_callback_t);
template <typename T>
......@@ -959,6 +976,10 @@ inline width_t Device::width() const {
return eb_device_width(device);
}
inline EB_STATUS_OR_VOID_T Device::enable_msi(eb_address_t* msi_first, eb_address_t* msi_last) {
EB_RETURN_OR_THROW("Device::enable_msi", eb_device_enable_msi(device, msi_first, msi_last));
}
template <typename T>
inline EB_STATUS_OR_VOID_T Device::sdb_scan_bus(const struct sdb_bridge* bridge, T* user, sdb_callback_t cb) {
EB_RETURN_OR_THROW("Device::sdb_scan_bus", eb_sdb_scan_bus(device, bridge, user, cb));
......
......@@ -166,6 +166,44 @@ eb_status_t eb_device_open(eb_socket_t socketp, const char* address, eb_width_t
return EB_OK;
}
eb_status_t eb_device_enable_msi(eb_device_t device, eb_address_t *msi_first, eb_address_t *msi_last) {
eb_status_t status;
eb_cycle_t cycle;
eb_data_t code, low[8], high[8];
eb_address_t first, last;
int stride, i;
/* How big is the largest access we can make? */
stride = eb_device_width(device) & EB_DATAX;
if ((status = eb_cycle_open(device, 0, 0, &cycle)) != EB_OK) return status;
/* Config space is always bigendian */
eb_cycle_write_config(cycle, 40-stride, EB_BIG_ENDIAN|stride, 1);
eb_cycle_read_config (cycle, 48-stride, EB_BIG_ENDIAN|stride, &code);
for (i = 0; i < 8; i += stride)
eb_cycle_read_config(cycle, 48+i, EB_BIG_ENDIAN|stride, &low[i]);
for (i = 0; i < 8; i += stride)
eb_cycle_read_config(cycle, 56+i, EB_BIG_ENDIAN|stride, &high[i]);
if ((status = eb_cycle_close_silently(cycle)) != EB_OK) return status;
/* Combine the read words */
first = 0; for (i = 0; i < 8; i += stride) first = (first << (8*stride)) | low[i];
last = 0; for (i = 0; i < 8; i += stride) last = (last << (8*stride)) | high[i];
*msi_first = first;
*msi_last = last;
switch (code) {
case 1: return EB_OK;
case 2: return EB_ABI;
case 3: return EB_BUSY;
default: return EB_FAIL;
}
}
eb_status_t eb_socket_passive(eb_socket_t socketp, const char* address) {
eb_device_t devicep;
eb_transport_t transportp;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment