//------------------------------------------------------------------- // nicstudy.cpp (An enhancement of our 'nicregs.cpp' deno) // // This program utilizes our 'user8139.c' device-driver to map // the RealTek 8139 network interface registers to user-space; // also to do read(), write(), and lseek() on a kernel buffer. // // It is assumed that the System Administrator has created the // required character-mode device-node in the '/dev' directory // before the user attempts to execute this program: // // root# mknod /dev/nic c 98 0 // root# chmod a+rw /dev/nic // // programmer: ALLAN CRUSE // written on: 06 APR 2005 //------------------------------------------------------------------- #include // for printf(), perror() #include // for open() #include // for exit() #include // for mmap(), munmap() #include // for memset(), strncpy() #include // for sleep() char nicname[] = "/dev/nic"; void show_nic_registers( void *vm ) { // display the contents of io-memory in hexadecimal format printf( "\n\nRealTek 8139 Registers mapped at %p \n", vm ); unsigned long *lp = (unsigned long *)vm; for (int i = 0; i < 64; i++) { if ( ( i % 8 ) == 0 ) printf( "\n%02X: ", i*4 ); printf( "%08lX ", lp[ i ] ); } printf( "\n" ); } int main( int argc, char **argv ) { // open the device-file int fd = open( nicname, O_RDWR ); if ( fd < 0 ) { perror( nicname ); exit(1); } // map the device's io-memory to user-space int prot = PROT_READ | PROT_WRITE; int flag = MAP_SHARED; int size = 0x1000; int base = 0; void *vm = mmap( NULL, size, prot, flag, fd, base ); if ( vm == MAP_FAILED ) { perror( "mmap" ); exit(1); } // display the contents of io-memory in hexadecimal format show_nic_registers( vm ); //----------------------------------------- // OK, now let's study packet transmission //----------------------------------------- int io = (int)vm; unsigned char *RTCommand = (unsigned char *)(io+0x37); unsigned long *TxStatus0 = (unsigned long *)(io+0x10); unsigned long *Tx_Config = (unsigned long *)(io+0x40); // reset the network controller *RTCommand = 0x10; sleep(1); // place our network packet into the kernel buffer area char packet[ 64 ] = {0}; memset( packet+0, 0xFF, 6 ); // broadcast address memset( packet+6, 0x00, 6 ); // unspecified source strncpy( packet+16, "Hello", 5 ); lseek( fd, 0, SEEK_SET ); // point to TxBuffer0 int nbytes = write( fd, packet, sizeof(packet) ); printf( "\n%d bytes written to kernel buffer \n", nbytes ); // now try to transmit the packet *RTCommand = 0x04; // enable TX *Tx_Config = 0; // configure TX *TxStatus0 = 64; // transmit TxBuffer0 sleep( 1 ); show_nic_registers( vm ); }