#ifndef ABCIO_H
#define ABCIO_H

#include <stddef.h>
#include <stdint.h>

#define DEVSEL_NONE 64		/* No device at all selected */

struct abc_dev;

#define ABC_CALLBACK(func)					\
    void func(struct abc_dev *dev __attribute__((unused)),	\
	      uint8_t data __attribute__((unused)),		\
	      uint8_t addr __attribute__((unused)))
typedef ABC_CALLBACK((*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;
};

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);

void abc_register(struct abc_dev *dev, unsigned int devsel);
void abc_init(void);

void abcdisk_init(void);
void abcdisk_io_poll(void);

void abc_init_memmap(void);

#endif /* ABCIO_H */
