#ifndef ABCIO_H #define ABCIO_H #include "common.h" #include "config.h" #define DEVSEL_NONE 64 /* No device at all selected */ struct abc_dev; /* Called from an interrupt handler, so hot */ #define ABC_CALLBACK_DECL(func) \ void func(struct abc_dev *dev __unused, \ uint8_t data __unused, \ uint8_t addr __unused) #define ABC_CALLBACK(func) \ __hot ABC_CALLBACK_DECL(func) typedef ABC_CALLBACK_DECL((*abc_callback_t)); struct abc_dev { uint8_t *out_buf; size_t out_cnt; const uint8_t *inp_buf; size_t inp_cnt; uint16_t callback_mask; uint16_t event_mask; /* Can be a superset of callback_mask */ uint8_t status_first_out_mask; uint8_t status_first_inp_mask; uint8_t out_data[6]; /* [1] is devsel, all 8 bits */ union { struct { uint8_t inp_data[2]; uint8_t inp_en; uint8_t inp_data_def; /* inp_data[0] when no queue active */ }; uint32_t inp_data_w; }; abc_callback_t callback_out[6]; abc_callback_t callback_inp[2]; abc_callback_t callback_rst; unsigned int devsel; const char *name; }; extern struct abc_dev *_abc_selected_dev; static inline struct abc_dev *abc_selected_dev(void) { return _abc_selected_dev; } void abc_setup_out_queue(struct abc_dev *dev, void *buf, size_t len, uint8_t status); void abc_setup_inp_queue(struct abc_dev *dev, const void *buf, size_t len, uint8_t status); void abc_set_inp_default(struct abc_dev *dev, uint8_t val); void abc_set_inp_status(struct abc_dev *dev, uint8_t val); /* * The _ versions can be used from interrupt handlers or when ABC_IRQ * is known to be masked already; for the _inp_data() functions this ALSO * requires that dev->inp_cnt is known to be zero (no currently configured * queue.) * * The __ versions can be used when it is *also* known that the device * in question is already selected (e.g. inside a callback.) */ static inline void _abc_set_inp_data(struct abc_dev *dev, uint8_t val) { dev->inp_data[0] = dev->inp_data_def = val; if (dev == abc_selected_dev()) ABC_INP0_DATA = val; } static inline void _abc_set_inp_status(struct abc_dev *dev, uint8_t val) { dev->inp_data[1] = val; if (dev == abc_selected_dev()) ABC_INP1_DATA = val; } static inline void __abc_set_inp_data(struct abc_dev *dev, uint8_t val) { ABC_INP0_DATA = dev->inp_data[0] = dev->inp_data_def = val; } static inline void __abc_set_inp_status(struct abc_dev *dev, uint8_t val) { ABC_INP1_DATA = dev->inp_data[1] = val; } static inline bool is_abc800(void) { unsigned long int host = getvar_uint(config_abc_hosttype); if (host) return host >= ABC_ABC800CM; else return !!(ABC_STATUS & ABC_STATUS_800); } void abc_register(struct abc_dev *dev, unsigned int devsel); void abc_init(void); void abcdisk_init(void); void abcdisk_config(void); void abcdisk_io_poll(void); void abcdisk_shutdown(void); void rtc_abc_init(void); void rtc_abc_config(void); void rtc_abc_io_poll(void); void pun80_init(void); void pun80_config(void); void abc_init_memmap(void); #endif /* ABCIO_H */