//------------------------------------------------------------------- // ajayinit.cpp // // Our initial prototype for initializing and configuring the // Debug Port after our Hi-Speed USB Debug Cable is connected // (and our 'ajay.c' module has been compiled and installed). // // compile using: $ g++ ajayinit.cpp -o ajayinit // execute using: $ ./ajayinit // // NOTE: Before executing this program, preparation by a user // who possesses 'root' privileges will be needed, namely: // // root# mknod /dev/ajay c 79 0 // root# chmod a+rw /dev/ajay // root# /sbin/insmod ajay.ko // // programmer: ALLAN CRUSE // written on: 24 JAN 2010 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for lseek(), usleep() #include // for mmap() #define AJAYBASE 0x80000 // suitable address for io-mapping char devname[] = "/dev/ajay"; // name for our driver device-node int main( int argc, char **argv ) { // open the device-file for reading and writing int fd = open( devname, O_RDWR ); if ( fd < 0 ) { perror( devname ); exit(1); } // map the EHCI registers to user-space int size = lseek( fd, 0, SEEK_END ); int prot = PROT_READ | PROT_WRITE; int flag = MAP_FIXED | MAP_SHARED; void *mm = (void*)AJAYBASE; if ( mmap( mm, size, prot, flag, fd, 0 ) == MAP_FAILED ) { perror( "mmap" ); exit(1); } // show state of the relevant EHCI controller registers unsigned int *lp = (unsigned int *)mm; printf( "\n Detecting... \n" ); printf( " CONFIGFLAG=%X ", lp[ 0x60 >> 2 ] ); printf( " USB2INTR=%08X ", lp[ 0x28 >> 2 ] ); printf( "\n" ); printf( " USB2CMD=%08X ", lp[ 0x20 >> 2 ] ); printf( " USB2STS=%08X ", lp[ 0x24 >> 2 ] ); printf( " PORT0SC=%08X ", lp[ 0x64 >> 2 ] ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( "\n" ); // interpret readiness of the EHCI for Debug Port usage unsigned int port0sc = lp[ 0x64 >> 2 ]; unsigned int cfgflag = lp[ 0x60 >> 2 ]; unsigned int dbgcmd = lp[ 0xA0 >> 2 ]; unsigned int usbpid = lp[ 0xA4 >> 2 ]; if ( cfgflag == 1 ) printf( " EHCI initialized" ); else { printf( "\n EHCI controller is uninitialized " ); goto quit; } if ( (port0sc & 1)==1 ) printf( ", Port 0 connected" ); else { printf( "\n Port 0 is not connected " ); goto quit; } if ( ( (port0sc >> 13)&1 )==0 ) printf( ", but not owned" ); else { printf( "\n Port 0 is already owned " ); goto quit; } if ( ( (dbgcmd >> 30)&1 )==0 ) printf( ", Debug Port available" ); else { printf( "\n Debug Port is already owned " ); goto quit; } printf( "\n\n" ); // initiate Port 0 reset port0sc = lp[ 0x64 >> 2 ]; // read current PORT0SC bits port0sc &= ~(1 << 13); // clear Port0 'owned' bit port0sc &= ~(1 << 2); // clear Port0 'enabled' bit port0sc |= (1 << 8 ); // set the Port0 'reset' bit lp[ 0x64 >> 2 ] = port0sc; // write revised PORT0SC bits usleep( 50000 ); // delay for 50 milliseconds // terminate Port 0 reset port0sc = lp[ 0x64 >> 2 ]; // read current PORT0SC bits port0sc &= ~(1 << 8 ); // clear the Port0 'reset' bit lp[ 0x64 >> 2 ] = port0sc; // write revised PORT0SC bits usleep( 2000 ); // delay for 2 milliseconds // configure the Debug Port printf( " Configuring... \n" ); lp[ 0xA0 >> 2 ] = 0x50010000; printf( " USB2CMD=%08X ", lp[ 0x20 >> 2 ] ); printf( " USB2STS=%08X ", lp[ 0x24 >> 2 ] ); printf( " PORT0SC=%08X ", lp[ 0x64 >> 2 ] ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( "\n" ); // implement the 'Get_Descriptor' control-transfer printf( "\n Initiating our 'GET_DESCRIPTOR' control-transfer: \n" ); // 1. the SETUP stage lp[ 0xB0 >> 2 ] = 0x00000000; // CONFIG: device=0, endpoint=0 lp[ 0xA8 >> 2 ] = 0x0A000680; // DATA_31: bRequest=6, wValue=10 lp[ 0xAC >> 2 ] = 0x00080000; // DATA_74: wIndex=0, wLength=8 lp[ 0xA4 >> 2 ] = 0x0000C32D; // USBPID: SETUP, DATA0 lp[ 0xA0 >> 2 ] = 0x50010018; // CNTL_STS: transmit 8 bytes lp[ 0xA0 >> 2 ] = lp[ 0xA0 >> 2 ] | (1 << 5); // set the GO bit while ( ( lp[ 0xA0 >> 2 ] & (1 << 16)) == 0 ); // await DONE bit printf( " SETUP: " ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( " USBPID=%06X ", lp[ 0xA4 >> 2 ] ); printf( " DATABUF=%08X-%08X ", lp[ 0xA8 >> 2 ], lp[ 0xAC >> 2 ] ); printf( "\n"); // 2. the DATA stage lp[ 0xA8 >> 2 ] = 0x00000000; // DATABUF_31: all zeros lp[ 0xAC >> 2 ] = 0x00000000; // DATABUF_74: all zeros lp[ 0xA4 >> 2 ] = 0x0000C369; // USBPID: IN, DATA0 lp[ 0xA0 >> 2 ] = 0x50010008; // CNTL_STS: receive 8 bytes lp[ 0xA0 >> 2 ] = lp[ 0xA0 >> 2 ] | (1 << 5); // set the GO bit while ( ( lp[ 0xA0 >> 2 ] & (1 << 16)) == 0 ); // await DONE bit printf( " IN: " ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( " USBPID=%06X ", lp[ 0xA4 >> 2 ] ); printf( " DATABUF=%08X-%08X ", lp[ 0xA8 >> 2 ], lp[ 0xAC >> 2 ] ); printf( "\n"); // 3. the HANDSHAKE stage lp[ 0xA4 >> 2 ] = 0x0000C3E1; // USBPID: OUT, DATA0 lp[ 0xA0 >> 2 ] = 0x50010010; // CNTL_STS: transmit 0 bytes lp[ 0xA0 >> 2 ] = lp[ 0xA0 >> 2 ] | (1 << 5); // set the GO bit while ( ( lp[ 0xA0 >> 2 ] & (1 << 16)) == 0 ); // await DONE bit printf( " OUT: " ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( " USBPID=%06X ", lp[ 0xA4 >> 2 ] ); printf( " DATABUF=%08X-%08X ", lp[ 0xA8 >> 2 ], lp[ 0xAC >> 2 ] ); printf( "\n"); // check for an unexpected peripheral attached to Port 0 usbpid = lp[ 0xA4 >> 2 ]; if ( (usbpid >> 16) != 0xD2 ) { printf( " Handshake was not 'ACK' " ); printf( "(i.e., Port 0 not attached to Debug Peripheral) " ); goto quit; } // show the Debug Descriptor unsigned char descriptor[ 8 ]; *(unsigned int *)( descriptor+0 ) = lp[ 0xA8 >> 2 ]; *(unsigned int *)( descriptor+4 ) = lp[ 0xAC >> 2 ]; printf( "\n Debug Descriptor: " ); for (int i = 0; i < 4; i++) printf( " %02X", descriptor[ i ] ); printf( "\n" ); // Now implement the 'Set_Feature' control-transfer printf( "\n Initiating our 'SET_FEATURE' control-transfer: \n" ); // 1. the SETUP stage lp[ 0xA8 >> 2 ] = 0x00060300; // DATABUF_30: bRequest=3, wValue=6 lp[ 0xAC >> 2 ] = 0x00000000; // DATABUF_73: wIndex=0, wLength=0 lp[ 0xB0 >> 2 ] = 0x00000000; // CONFIG: address=0, endpoint=0 lp[ 0xA4 >> 2 ] = 0x0000C32D; // USBPID: SETUP, DATA0 lp[ 0xA0 >> 2 ] = 0x50010018; // CNTL_STS: transmit 8 bytes lp[ 0xA0 >> 2 ] = lp[ 0xA0 >> 2 ] | (1 << 5); // set the GO bit while ( ( lp[ 0xA0 >> 2 ] & (1 << 16)) == 0 ); // await DONE bit printf( " SETUP: " ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( " USBPID=%06X ", lp[ 0xA4 >> 2 ] ); printf( " DATABUF=%08X-%08X ", lp[ 0xA8 >> 2 ], lp[ 0xAC >> 2 ] ); printf( "\n"); // 2. the HANDSHAKE phase lp[ 0xA4 >> 2 ] = 0x0000C369; // USBPID: IN, DATA0 lp[ 0xA0 >> 2 ] = 0x50010000; // CNTL_STS: receive 0 bytes lp[ 0xA0 >> 2 ] = lp[ 0xA0 >> 2 ] | (1 << 5); // set the GO bit while ( ( lp[ 0xA0 >> 2 ] & (1 << 16)) == 0 ); // await DONE bit printf( " IN: " ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( " USBPID=%06X ", lp[ 0xA4 >> 2 ] ); printf( " DATABUF=%08X-%08X ", lp[ 0xA8 >> 2 ], lp[ 0xAC >> 2 ] ); // release ownership of the Debug Port quit: printf( "\n\n Quitting... \n" ); lp[ 0xA0 >> 2 ] = 0x00010000; printf( " USB2CMD=%08X ", lp[ 0x20 >> 2 ] ); printf( " USB2STS=%08X ", lp[ 0x24 >> 2 ] ); printf( " PORT0SC=%08X ", lp[ 0x64 >> 2 ] ); printf( " CNTL_STS=%08X ", lp[ 0xA0 >> 2 ] ); printf( "\n\n" ); }