/*
 * Elmo data-structure definitions
 */

#include <linux/list.h>

#define ELMO_MAJOR 247

enum elmo_worker_state {
  ELMO_WORKER_SETUP = 0,
  ELMO_WORKER_DONE,
  ELMO_WORKER_AWAIT_RESET,
  ELMO_WORKER_SETUP_RESET,
  ELMO_WORKER_RESET_DONE,
  ELMO_WORKER_SERVICE_WRITE_FIFO,
  ELMO_WORKER_SERVICE_READ_FIFO,
  ELMO_WORKER_GATE_WRITER,
  ELMO_WORKER_BECOME_WRITER,
  ELMO_WORKER_WRITER,
  ELMO_WORKER_BECOME_READER,
  ELMO_WORKER_READER,
  ELMO_WORKER_READER_POST,
  ELMO_WORKER_GET_BULK_INTERFACE,
  ELMO_WORKER_GET_ESS_COMMAND,
  ELMO_WORKER_SETUP_DMA,
  ELMO_WORKER_AWAIT_FIFO,
  ELMO_WORKER_FINISH_DMA,
};

enum elmo_dma_activity {
  ELMO_DMA_IDLE = 0,
  ELMO_DMA_READING,
  ELMO_DMA_WRITING,
};

struct elmo_worker
{
  struct list_head link;
  unsigned long elmoResourcesUsed;      /* mask of ELMO_RESOURCE_* */
  unsigned long elmoResourcesNeeded;    /* mask of ELMO_RESOURCE_* */
  unsigned long elmoInterruptsPending;  /* mask of ELMO_INT_* */
  unsigned long elmoInterruptsFired;    /* mask of ELMO_INT_* */
  int sn;
  enum elmo_worker_state state;
  int sc_data_direction;
  int reportError;
  int reportHang;
  int go;
  int retries;
  int aborting;
  int timeout;
  int potentialDeadman;
  int deadman;
  int dwell;
  int holdingSemaphore;
  int signalATA;
  int errorATA;
  enum elmo_dma_activity dmaRunning;
  unsigned int transferSize;
  unsigned int transferBurst;
  unsigned int transferRemaining;
  unsigned int consuming;
  unsigned int residual;
  unsigned char sense_buffer[SCSI_SENSE_BUFFERSIZE];
  Scsi_Cmnd *scsiRequest;
  unsigned char *dataBuffer;
  unsigned int dataBufferSize;
  unsigned int dataBufferCount;
  unsigned int readCompleted;
  unsigned short ataCommandReg;
  unsigned short ataCylinderReg;
};

#define ELMO_RESOURCE_WRITEBUFFER_SPACE 0x00000001
#define ELMO_RESOURCE_WRITEBUFFER_DATA  0x00000002
#define ELMO_RESOURCE_WRITER_GATE       0x00000004
#define ELMO_RESOURCE_WRITER            0x00000008
#define ELMO_RESOURCE_READER            0x00000010
#define ELMO_RESOURCE_READBUFFER_DATA   0x00000020
#define ELMO_RESOURCE_READBUFFER_SPACE  0x00000040
#define ELMO_RESOURCE_BULK_INTERFACE    0x00000080
#define ELMO_RESOURCE_ATA_COMMAND       0x00000100

#define ELMO_READBUFFER_SIZE            (PAGE_SIZE)
#define ELMO_WRITEBUFFER_SIZE           (PAGE_SIZE)

/*
  Elmo hardware registers - addresses and definitions
*/

#define EBI_BASE 0x1E000000


#define ELMO_CONTROL_REG            EBI_BASE+0x00
#define ELMO_INT_STATUS_REG         EBI_BASE+0x02
#define ELMO_INT_ENABLE_REG         EBI_BASE+0x04
#define ELMO_FIFO_STATUS_REG        EBI_BASE+0x06
#define ELMO_FIFO_ENABLE_REG        EBI_BASE+0x08
#define ELMO_EBI_STALL_REG          EBI_BASE+0x0A
#define ELMO_LL_WATERLINE_REG       EBI_BASE+0x0C
#define ELMO_IDE_WATERLINE_REG      EBI_BASE+0x0E

#define ELMO_CMD_SECTOR_REG         EBI_BASE+0x10
#define ELMO_CYL_REG                EBI_BASE+0x12
#define ELMO_DMA_EN                 EBI_BASE+0x16

#define ELMO_CHIP_REVISION_REG      EBI_BASE+0x1C

struct elmo_bridge 
{
  volatile unsigned short control;
  volatile unsigned short isr;
  volatile unsigned short imr;
  volatile unsigned short fsr;
  volatile unsigned short fmr;
  volatile unsigned short stall;
  volatile unsigned short ll_waterline;
  volatile unsigned short ide_waterline;
  volatile unsigned short command;
  volatile unsigned short cylinder;
  volatile unsigned short error;
  volatile unsigned short rfu2[3]; /* 0x16 0x18 0x1A */
  volatile unsigned short revision;
};

#define ELMO_LOW_LATENCY_FIFO_ADDR  (EBI_BASE+0x80000)
#define ELMO_IDE_FIFO_ADDR          (EBI_BASE+0xC0000)


#define ELMO_CONTROL_SW_RST         0x0001
#define ELMO_CONTROL_LL_FIFO_RST    0x0002
#define ELMO_CONTROL_IDE_FIFO_RST   0x0004
#define ELMO_CONTROL_ATA_INT_RST    0x0008 
#define ELMO_CONTROL_EBI_TIMEOUT_EN 0x0010
#define ELMO_CONTROL_DSK_RST_ACK    0x0020
#define ELMO_CONTROL_DSK_CMD_ACK    0x0040
#define ELMO_CONTROL_INT_ESS        0x0080
#define ELMO_CONTROL_ESS_RST        0x0100
#define ELMO_CONTROL_NTSC_DVO_SEL   0x0200
#define ELMO_CONTROL_ACLK_SEL0      0x0400
#define ELMO_CONTROL_ACLK_SEL1      0x0800
#define ELMO_CONTROL_EBI_ESS_DMA_EN 0x1000
#define ELMO_CONTROL_ESS_EBI_DMA_EN 0x2000
#define ELMO_CONTROL_EBI_IDE_DMA_EN 0x4000
#define ELMO_CONTROL_IDE_EBI_DMA_EN 0x8000

/*
  The Elmo interrupts are defined here twice, for convenience.

  The ELMO_ISR_ and ELMO_FIFO_ definitions match up with the
  interrupt bit positions in the 16-bit status and enable
  registers in the hardware.

  The ELMO_INT_... definitions assume that these two 16-
  bit interrupt sets are combined into a single 32-bit
  entity (ELMO_ISR_ in the high halfword and ELMO_FIFO_
  in the low halfword).  These become the "virtual interrupt"
  bits used to manage the workers.

  Several of the "reserved, will always be zero" bits in the real
  hardware is stolen away, to be "virtual" interruptindicator bits
  for "broadcom DMA is done", "timer expired" etc.
*/

#define ELMO_ISR_BUS_TIMEOUT        0x0001
#define ELMO_ISR_DMA_RD_IRQ         0x0002
#define ELMO_ISR_DMA_WR_IRQ         0x0004
#define ELMO_ISR_RFU_BIT_3          0x0008
#define ELMO_ISR_RFU_BIT_4          0x0010
#define ELMO_ISR_DSK_RST_REQ        0x0020
#define ELMO_ISR_DSK_CMD_REQ        0x0040
#define ELMO_ISR_INT_FROM_ESS       0x0080
#define ELMO_ISR_EBI_TO_ESS_OVR     0x0100
#define ELMO_ISR_EBI_TO_ESS_UDR     0x0200
#define ELMO_ISR_ESS_TO_EBI_OVR     0x0400
#define ELMO_ISR_ESS_TO_EBI_UDR     0x0800
#define ELMO_ISR_EBI_TO_IDE_OVR     0x1000
#define ELMO_ISR_EBI_TO_IDE_UDR     0x2000
#define ELMO_ISR_IDE_TO_EBI_OVR     0x4000
#define ELMO_ISR_IDE_TO_EBI_UDR     0x8000

#define ELMO_FIFO_EBI_TO_ESS_NE     0x0001
#define ELMO_FIFO_EBI_TO_ESS_LWM    0x0002
#define ELMO_FIFO_EBI_TO_ESS_FF     0x0004
#define ELMO_FIFO_RFU_BIT_3         0x0008
#define ELMO_FIFO_ESS_TO_EBI_NE     0x0010
#define ELMO_FIFO_ESS_TO_EBI_HWM    0x0020
#define ELMO_FIFO_RFU_BIT_6         0x0040
#define ELMO_FIFO_RFU_BIT_7         0x0080
#define ELMO_FIFO_EBI_TO_IDE_NE     0x0100
#define ELMO_FIFO_EBI_TO_IDE_LWM    0x0200
#define ELMO_FIFO_EBI_TO_IDE_FF     0x0400
#define ELMO_FIFO_RFU_BIT_11        0x0800
#define ELMO_FIFO_IDE_TO_EBI_NE     0x1000
#define ELMO_FIFO_IDE_TO_EBI_HWM    0x2000
#define ELMO_FIFO_RFU_BIT_14        0x4000
#define ELMO_FIFO_RFU_BIT_14        0x8000

#define ELMO_INT_EBI_TO_ESS_NE      0x00000001
#define ELMO_INT_EBI_TO_ESS_LWM     0x00000002
#define ELMO_INT_EBI_TO_ESS_FF      0x00000004
#define ELMO_INT_ISB_DMA            0x00000008  /* stolen bit */
#define ELMO_INT_ESS_TO_EBI_NE      0x00000010
#define ELMO_INT_ESS_TO_EBI_HWM     0x00000020
#define ELMO_INT_TIMER              0x00000040  /* stolen bit */
#define ELMO_INT_RFU_BIT_7          0x00000080
#define ELMO_INT_EBI_TO_IDE_NE      0x00000100
#define ELMO_INT_EBI_TO_IDE_LWM     0x00000200
#define ELMO_INT_EBI_TO_IDE_FF      0x00000400
#define ELMO_INT_RFU_BIT_11         0x00000800
#define ELMO_INT_IDE_TO_EBI_NE      0x00001000
#define ELMO_INT_IDE_TO_EBI_HWM     0x00002000
#define ELMO_INT_EBI_TX_DMA         0x00004000 /* stolen bit */
#define ELMO_INT_EBI_RX_DMA         0x00008000 /* stolen bit */
#define ELMO_INT_BUS_TIMEOUT        0x00010000
#define ELMO_INT_DMA_RD_IRQ         0x00020000
#define ELMO_INT_DMA_WR_IRQ         0x00040000
#define ELMO_INT_RFU_BIT_3          0x00080000
#define ELMO_INT_RFU_BIT_4          0x00100000
#define ELMO_INT_DSK_RST_REQ        0x00200000
#define ELMO_INT_DSK_CMD_REQ        0x00400000
#define ELMO_INT_INT_FROM_ESS       0x00800000
#define ELMO_INT_EBI_TO_ESS_OVR     0x01000000
#define ELMO_INT_EBI_TO_ESS_UDR     0x02000000
#define ELMO_INT_ESS_TO_EBI_OVR     0x04000000
#define ELMO_INT_ESS_TO_EBI_UDR     0x08000000
#define ELMO_INT_EBI_TO_IDE_OVR     0x10000000
#define ELMO_INT_EBI_TO_IDE_UDR     0x20000000
#define ELMO_INT_IDE_TO_EBI_OVR     0x40000000
#define ELMO_INT_IDE_TO_EBI_UDR     0x80000000
  
#define ELMO_BRIDGE_BASE 0x1e000000

#define ELMO_BRIDGE ((volatile struct elmo_bridge *) KSEG1ADDR(ELMO_BRIDGE_BASE))

#define ELMO_LOW_LATENCY_FIFO       ((volatile unsigned short *) KSEG1ADDR(ELMO_LOW_LATENCY_FIFO_ADDR))
#define ELMO_IDE_FIFO       ((volatile unsigned short *) KSEG1ADDR(ELMO_IDE_FIFO_ADDR))

#define ELMO_IRQ BCM_LINUX_GIOX_IRQ(34)
#define DMA_IRQ BCM_LINUX_DMA_IRQ

#define GetELMOBridgeAddress( addr ) ((volatile short *)KSEG1ADDR((addr)+ELMO_BRIDGE_BASE))

/*
  ATAPI register definitions
*/

#define ELMO_OFFSET_ATA_PRIMARY_COMMAND ELMO_OFFSET_CS2+0x1000000
#define ELMO_OFFSET_ATA_PRIMARY_CONTROL ELMO_OFFSET_CS2+0x1200000

#define ELMO_ATAPI_DATA_REGISTER      ELMO_OFFSET_ATA_PRIMARY_COMMAND+0
#define ELMO_ATAPI_ERROR_REGISTER     ELMO_OFFSET_ATA_PRIMARY_COMMAND+2
#define ELMO_ATAPI_FEATURE_REGISTER     ELMO_ATAPI_ERROR_REGISTER
#define ELMO_ATAPI_IREASON_REGISTER   ELMO_OFFSET_ATA_PRIMARY_COMMAND+4
/* no use of                        ELMO_OFFSET_ATA_PRIMARY_COMMAND+6 */
#define ELMO_ATAPI_BCOUNTL_REGISTER   ELMO_OFFSET_ATA_PRIMARY_COMMAND+8
#define ELMO_ATAPI_BCOUNTH_REGISTER   ELMO_OFFSET_ATA_PRIMARY_COMMAND+10
#define ELMO_ATAPI_SELECT_REGISTER    ELMO_OFFSET_ATA_PRIMARY_COMMAND+12
#define ELMO_ATAPI_COMMAND_REGISTER   ELMO_OFFSET_ATA_PRIMARY_COMMAND+14
#define ELMO_ATAPI_STATUS_REGISTER      ELMO_ATAPI_COMMAND_REGISTER

#define ELMO_ATAPI_CONTROL_REGISTER   ELMO_OFFSET_ATA_PRIMARY_CONTROL+12
#define ELMO_ATAPI_ALTSTATUS_REGISTER   ELMO_ATAPI_CONTROL_REGISTER

/*
 *	Bits of the interrupt reason register.
 */

#define ELMO_ATAPI_IREASON_COD	0x1 /* Information transferred is command */
#define ELMO_ATAPI_IREASON_IO	0x2 /* The device requests us to read */
