#pragma once #include struct vim { uint32_t irqindex; uint32_t fiqindex; uint32_t padding0[2]; uint32_t firqpr[4]; uint32_t intreq[4]; uint32_t reqenaset[4]; uint32_t reqenaclr[4]; uint32_t wakeenaset[4]; uint32_t wakeenaclr[4]; void (*irqvecreg)(void); void (*fiqvecreg)(void); uint32_t capevt; uint32_t : 32; uint32_t chanctrl[32]; }; struct vim_parity { uint32_t padding0[59]; uint32_t parflg; uint32_t parctl; uint32_t adderr; void (*fbparerr)(void); }; #define VIM_NUM_CHANNELS 127 struct vim_table { void (*phantom)(void); void (*channel[VIM_NUM_CHANNELS])(void); }; #define VIM_BASE 0xFFFFFE00UL static volatile struct vim *const VIM = (volatile struct vim *)VIM_BASE; static volatile struct vim_parity *const VIM_PARITY = (volatile struct vim_parity *)0xFFFFFD00UL; static volatile struct vim_table *const VIM_TABLE = (volatile struct vim_table *)0xFFF82000UL; #define VIM_PARCTL_ENABLE (UINT32_C(0xA)) static inline void vim_enable(uint32_t channel) { VIM->reqenaset[channel / 32] = UINT32_C(1) << (channel % 32); } static inline void vim_disable(uint32_t channel) { VIM->reqenaclr[channel / 32] = UINT32_C(1) << (channel % 32); } static inline void vim_clear(uint32_t channel) { VIM->intreq[channel / 32] = UINT32_C(1) << (channel % 32); } static inline void vim_set_req(uint32_t channel, uint32_t req) { const uint32_t reg = channel / 4; const uint32_t shift = (3 - (channel % 4)) * 8; const uint32_t mask = UINT32_C(0xFF) << shift; VIM->chanctrl[reg] = ((VIM->chanctrl[reg] & ~mask) | (req << shift)); } static inline void vim_set_is_fiq(uint32_t channel) { VIM->firqpr[channel / 32] |= UINT32_C(1) << (channel % 32); } static inline void vim_clear_is_fiq(uint32_t channel) { VIM->firqpr[channel / 32] &= ~(UINT32_C(1) << (channel % 32)); } static inline void vim_set_phantom_handler(void (*handler)(void)) { VIM_TABLE->phantom = handler; } static inline void vim_set_handler(uint32_t channel, void (*handler)(void)) { VIM_TABLE->channel[channel] = handler; } static inline void vim_channel_init(uint32_t channel, uint32_t req, void (*handler)(void)) { vim_set_req(channel, req); vim_set_handler(channel, handler); vim_enable(channel); }