--- /dev/null
+/*
+ * jtag.c - basic jtag stuff (good excercise!)
+ *
+ * author: hackbard@hackdaworld.org
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/io.h>
+#include <string.h>
+
+// variables
+
+#define u16 unsigned short
+#define u8 unsigned char
+#define u32 unsigned int
+
+// max devices and ir chain len
+#define MAXDEV 64
+#define MAXIRLEN 32
+
+typedef struct s_jtdrv {
+ unsigned long ppaddr;
+ //int *init(t_jtag *jtag);
+} t_jtdrv;
+
+typedef struct s_part {
+ int irlen;
+ u32 idcode;
+} t_part;
+
+typedef struct s_jtag {
+ int nod;
+ int tot_ir_len;
+ t_part part[MAXDEV];
+} t_jtag;
+
+// only parallel III cable by now
+
+#define TDI 0x01
+#define TMS 0x04
+#define TCK 0x02
+#define TDO 0x10
+
+// parport functions
+
+int parport_init(unsigned long ppaddr) {
+
+ if(ioperm(ppaddr,1,1)||ioperm(ppaddr+1,1,1)) {
+ perror("parport init");
+ return -1;
+ }
+
+ return 0;
+
+}
+
+int parport_out(u8 data) {
+
+ outb(data,0x378);
+
+ return 0;
+
+}
+
+int parport_in(u8 *data) {
+
+ *data=inb(0x379);
+
+ return 0;
+
+}
+
+// jtag low level functions
+
+u8 jtag_clock(u8 tms,u8 tdi) {
+
+ u8 in;
+ u8 out;
+ u8 tdo;
+
+ out=0;
+ if(tms) out|=TMS;
+ if(tdi) out|=TDI;
+ parport_out(out);
+
+ parport_in(&in);
+
+ tdo=in&TDO?1:0;
+
+ // clock cycle
+ parport_out(out|TCK);
+ parport_out(out);
+
+ return tdo;
+
+}
+
+// jtag mid level functions
+
+int jtag_reset() {
+
+ // 5 times TMS
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+
+ // go to idle mode
+ jtag_clock(0,0);
+
+ return 0;
+}
+
+int jtag_enter_shift_ir() {
+
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(0,0);
+ jtag_clock(0,0);
+
+ return 0;
+
+}
+
+int jtag_leave_shift_ir() {
+
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(0,0);
+
+ return 0;
+
+}
+
+int jtag_enter_shift_dr() {
+
+ jtag_clock(1,0);
+ jtag_clock(0,0);
+ jtag_clock(0,0);
+
+ return 0;
+
+}
+
+int jtag_leave_shift_dr() {
+
+ jtag_clock(1,0);
+ jtag_clock(1,0);
+ jtag_clock(0,0);
+
+ return 0;
+
+}
+
+int jtag_read_data(u8 *p,int bitlen) {
+
+ u8 in;
+ int count;
+
+ memset(p,0,bitlen+7/8);
+ count=0;
+
+ while(bitlen) {
+ in=jtag_clock(0,0);
+ p[count/8]|=((in&1)<<(count%8));
+ count+=1;
+ bitlen-=1;
+ }
+
+ return 0;
+
+}
+
+int jtag_chain_init(t_jtag *jtag) {
+
+ int i;
+ u8 tdo;
+
+ jtag_enter_shift_ir();
+ for(i=0;i<MAXIRLEN*MAXDEV;i++) jtag_clock(0,0);
+ for(i=0;i<MAXIRLEN*MAXDEV;i++) {
+ tdo=jtag_clock(0,1);
+ if(tdo)
+ break;
+ }
+ printf("ir len: %d\n",i);
+ jtag->tot_ir_len=i;
+ jtag_leave_shift_ir();
+
+ jtag_enter_shift_dr();
+ for(i=0;i<MAXIRLEN*MAXDEV;i++) jtag_clock(0,0);
+ for(i=0;i<MAXIRLEN*MAXDEV;i++)
+ if(jtag_clock(0,1))
+ break;
+ printf("number of devices: %d\n",i);
+ jtag->nod=i;
+ jtag_leave_shift_dr();
+
+ jtag_reset();
+ jtag_enter_shift_dr();
+ for(i=1;i<=jtag->nod;i++) {
+ jtag_read_data((u8 *)&(jtag->part[jtag->nod-i].idcode),32);
+ printf("idcode of part %d: %x\n",i,jtag->part[jtag->nod-i].idcode);
+ }
+ jtag_leave_shift_dr();
+
+ return i;
+
+}
+
+int main(int argc,char **argv) {
+
+ t_jtag jtag;
+
+ memset(&jtag,0,sizeof(t_jtag));
+
+ printf("parport init ...\n");
+ parport_init(0x378);
+ printf("done\n\n");
+
+ printf("reset test logic ...\n");
+ jtag_reset();
+ printf("done\n\n");
+
+ printf("jtag chain init ...\n");
+ jtag_chain_init(&jtag);
+ printf("done\n\n");
+
+ return 0;
+
+}
+