/*
  Copyright 2004, 2005 Jean-Baptiste Note

  This file is part of prism54usb.

  prism54usb is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 2 of the License, or
  (at your option) any later version.

  prism54usb is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with prism54usb; if not, write to the Free Software Foundation,
  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

*/

/* this file contains definitions for protocol communication with the
 * ROM of the ISL devices */

#ifndef _HAVE_ISL_ROM_H_
#define _HAVE_ISL_ROM_H_

#define X2_SIGNATURE "x2  "
#define X2_SIGNATURE_SIZE 4
#define X2_LEN (sizeof(struct x2_header))

#include <linux/firmware.h>
#include <linux/types.h>
#include <linux/crc32.h>

/* Rom communication primitives */
int islrom_send_data(char* data, unsigned data_len);

struct x2_cmd {
	uint32_t                fw_load_addr;
	uint32_t                fw_length;
} __attribute__((packed));

struct x2_header {
	char                    signature[X2_SIGNATURE_SIZE];
	struct x2_cmd           cmd;
	uint32_t                crc;
} __attribute__((packed));

/* X2 header, used to send the firmware to the 3887 rom */

#define islrom_crc32(data, length) ~crc32_le(~0, (unsigned char const *)(data), (length));


/* int                     islrom_build_x2(struct x2_header *header, */
/* 					uint32_t fw_load_addr, */
/* 					uint32_t fw_length); */
/* Firmware checksum */
void islrom_build_fwtail(uint32_t *tail, char *fw, unsigned fw_len);

/******
 * DATA SENDING COMMANDS
 ******/

/* you can readily load the data without x2 header as outlined in the
 * help. You have no checksum on length and desination address, though,
 * but you need to provide a checksum on data at the end of the payload
 */
int                     islrom_load_fw(struct islsm *device,
				       unsigned dest_addr,
				       char *fw, unsigned length);

/* when you send the load command without arguments,
 * the firmware expects a x2 header to describe the load in the 3887
 * case.
 *
 * In the PCI case, i guess the length is an implied
 * parameter. Triggering error is not easy by just playing on the
 * keyboard: the length of the default firmware must be quite long
 */
int                     islrom_load_fw_x2(struct islsm *device,
					  unsigned dest_addr,
					  char *fw, unsigned length);

/* the firmware responds with (ERROR or OK) + prompt once these commands
 * have been completed (or aborted by a checksum error, as may be the
 * case) */

/* once done, jump. implied address is ? */
int                     islrom_boot_fw(struct islsm *device, int addr);

#endif				/* _HAVE_ISL_ROM_H_ */
