#ifndef ETHFCORE_H
#define ETHFCORE_H

#include <stdio.h>

/* this is a non-standard declaration but apparently it works in clang, gcc
 * and openwatcom. it instructs the compiler to pack struct tightly
 * (necessary to avoid "holes" in structs below) */
#pragma pack(push, 1)

struct FRAME {
  unsigned char dmac[6];
  unsigned char smac[6];
  unsigned short etype;
  unsigned char protover;
  unsigned char reqid;
  char flopid[8];
  unsigned short ax;
  unsigned short bx;
  unsigned short cx;
  unsigned short dx;
  unsigned char sectnum;
  unsigned char driveid;  /* 0=A, 1=B */
  unsigned char data[512];
  unsigned short csum;
};

/* restore the default (compiler/system) struct packing */
#pragma pack(pop)


struct cliententry {
  unsigned char mac[6];
  char curflopid[9];
  unsigned char ro;          /* read-only flag */
  int fd;                    /* open file handle to floppy img (-1 = NONE) */
  struct cliententry *next;
  unsigned short sectcount;  /* total count of sectors on floppy */
  unsigned short lastimgsector; /* last sector actually in img (thin provisionning) */
  unsigned char chs_sectspertrack;
  unsigned char chs_totheads;
  unsigned char diskchangeflag; /* 0=disk not changed, 1=new disk in drive */
  unsigned char driveid;        /* client's local drive letter (0=A 1=B) */

  /* below fields are used to cache answers so ethflopd does not have to
   * recompute (re-read or re-write) data in case of a client retransmission */
  unsigned char last_frame_recvd_reqid; /* reqid of last query answered */
  unsigned short last_frame_recvd_csum; /* csum of last query answered */
  struct FRAME last_frame_sent; /* last answer sent */
};


/* before anything you need to init the ethflop server with the local MAC */
void ethflop_init(const unsigned char *mymac);

/* returns a pointer to of frame to send back, or NULL if nothing. log may be
 * filled with a feedback message.  */
const struct FRAME *ethflop_process(const void *frameptr, unsigned short framelen, char *log);


/*****************************************************************************
 * convenience functions useful for user interfaces                          *
 *****************************************************************************/

/* returns a ptr to a linked list with all currently connected ethflop clients
 * returns NULL if no client is connected */
struct cliententry *ethflop_getclients(void);

/* insert floppy "arg" to client "ce", readonly if roflag non zero.
 * msg may be filled with a feedback message
 * returns 0 on sucess, non-zero otherwise */
int ethflop_insert(struct cliententry *ce, const char *arg, char *msg, unsigned char roflag);

/* ejects floppy inserted in client ce and fills msg with a feedback message.
 * returns 0 on success, non-zero otherwise */
int ethflop_eject(struct cliententry *ce, char *msg);

/* fills s with the list of available floppy images, returns the number of
 * images. image names are written sequentially as 10-bytes fields. sorted. */
unsigned short ethflop_imgfilelist(char *s, unsigned short sz);

#endif
