// **************************************************************************
//
//  WRT54G.H - Header file for the WRT54G EJTAG DeBrick Utility  v3.0
//
//  Note:
//  This program is for De-Bricking a WRT54G/GS version 1.x/2.x router.  It 
//  has only been tested (by me) on a WRT54G version 2.0 router.  
//  
//  New for v3.0 - the software has been changed to fully support units with
//                 a larger 8MB flash chip (i.e. - the GS Units).  It now
//                 has a "/8MB" command line switch to support these chips.
//                 Software also now uses Flash Window 2 (0x1C000000) instead
//                 of Flash Window 1 (0x1FC00000) in order to support the
//                 larger 8MB flash chips.
//
// **************************************************************************
//  Written by HairyDairyMaid (a.k.a. - lightbulb)
//  hairydairymaid@yahoo.com
// **************************************************************************
//
//  This program is copyright (C) 2004 HairyDairyMaid (a.k.a. Lightbulb)
//  This program is free software; you can redistribute it and/or modify it
//  under the terms of version 2 the GNU General Public License as published
//  by the Free Software Foundation.
//  This program 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.
//  To view a copy of the license go to:
//  http://www.fsf.org/copyleft/gpl.html
//  To receive a copy of the GNU General Public License write the Free Software
//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
//
// **************************************************************************

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/ppdev.h>

#define true  1
#define false 1

// ------------------------------------------------------
// --- Choose only one cable specific section below
// ------------------------------------------------------
//
// --- Xilinx Type Cable ---
#define TDI     0
#define TCK     1
#define TMS     2
#define TDO     4
#define PROG  TDO
//
// --- Wiggler Type Cable ---
// #define TDI      3
// #define TCK      2
// #define TMS      1
// #define TDO      7
// #define PROG   TDO
//
// ------------------------------------------------------

// --- Support two Chips ---
#define BCM4702_CHIP    0x1
#define BCM4712_CHIP    0x2

// --- Some BCM47XX Instructions ---
#define INSTR_IDCODE    0x01
#define INSTR_EXTEST    0x00
#define INSTR_SAMPLE    0x02
#define INSTR_PRELOAD   0x02
#define INSTR_BYPASS    0xFF
#define INSTR_CONTROL   0x0A
#define INSTR_DATA      0x09
#define INSTR_ADDRESS   0x08

// --- Some EJTAG Bit Masks ---
#define TOF             (1 << 1 )
#define BRKST           (1 << 3 )
#define DRWN            (1 << 9 )
#define DERR            (1 << 10)
#define DSTRT           (1 << 11)
#define SETDEV          (1 << 14)
#define PROBEN          (1 << 15)
#define DMAACC          (1 << 17)
#define PRACC           (1 << 18)
#define PRNW            (1 << 19)
#define DLOCK           (1 << 5 )
#define TIF             (1 << 2 )
#define SYNC            (1 << 23)
#define PRRST           (1 << 16)
#define PERRST          (1 << 20)
#define JTAGBRK         (1 << 12)
#define DNM             (1 << 28)
#define DMA_BYTE        0x00000000  //DMA tranfser size BYTE
#define DMA_HALFWORD    0x00000080  //DMA transfer size HALFWORD
#define DMA_WORD        0x00000100  //DMA transfer size WORD
#define DMA_TRIPLEBYTE  0x00000180  //DMA transfer size TRIPLEBYTE

// --- Some Important Locations, etc. ---
#define  FLASH_MEMORY          0x1C000000  // Changed Start to Alway Use Flash Window 2 (since it supports all size chips)
#define  BLOCK_SIZE_8          0x2000      // 8K Blocks (Boot for Intel)
#define  BLOCK_SIZE            0x10000     // 64K Blocks Default
#define  FLASH_CHIP_UNKNOWN    0x0
#define  FLASH_CHIP_AMD        0x1
#define  FLASH_CHIP_INTEL      0x89

// --- For 4MB Flash Chips ---
#define  CFE_START_4MB         0x1C000000
#define  CFE_LENGTH_4MB        0x40000
#define  KERNEL_START_4MB      0x1C040000
#define  KERNEL_LENGTH_4MB     0x3B0000
#define  NVRAM_START_4MB       0x1C3F0000
#define  NVRAM_LENGTH_4MB      0x10000
#define  WHOLEFLASH_START_4MB  0x1C000000
#define  WHOLEFLASH_LENGTH_4MB 0x400000

// --- For 8MB Flash Chips ---
#define  CFE_START_8MB         0x1C000000
#define  CFE_LENGTH_8MB        0x40000   
#define  KERNEL_START_8MB      0x1C040000
#define  KERNEL_LENGTH_8MB     0x7A0000  
#define  NVRAM_START_8MB       0x1C7E0000
#define  NVRAM_LENGTH_8MB      0x20000   
#define  WHOLEFLASH_START_8MB  0x1C000000
#define  WHOLEFLASH_LENGTH_8MB 0x800000  


// --- Uhh, Just Because I Have To ---
void lpt_openport(void);
void lpt_closeport(void);
void clockin(int tms, int tdi);
unsigned char clockout(void);
void test_reset();
void capture_dr();
void capture_ir();
void set_instr(int instr);
static void chip_detect(void);
static void chip_shutdown(void);
void ReadWriteData(unsigned char* ichain, unsigned char* ochain);
void ReadData(unsigned char *read_chain);
void WriteData(unsigned char *write_chain);
void ShowData(unsigned int value);
static unsigned int ejtag_dma_read(unsigned int addr);
static unsigned int ejtag_dma_read_h(unsigned int addr);
static void ejtag_dma_write(unsigned int addr, unsigned int data);
static void ejtag_dma_write_h(unsigned int addr, unsigned int data);
void setup_Watchdog(void);
void setup_DCR(void);
void setup_memory(void);
void ejtag_issue_reset(void);
static int sflash_probe(void);
static void sflash_erase_area(unsigned int start, unsigned int length);
static int sflash_erase_block(unsigned int block);
static int sflash_write_word(unsigned int addr, unsigned int data);
static void sflash_end(void);
void run_backup(char *filename, unsigned int start, unsigned int length);
void run_erase(char *filename, unsigned int start, unsigned int length);
void run_flash(char *filename, unsigned int start, unsigned int length);
void show_usage(void);
