Listing 1Here is all the application-specific code I need for the Ethernet device. The rest of the system implements the TCP/IP stack.
#include <sys/wait.h>
#include <netinet/in.h>
#include <stdio.h>
#include <asm/io.h>
#define LPTDAT 0x278
#define LPTSTAT 0x279
#define LPTCTL 0x27a
#define MyPort 4321
main(){
int s,ns;
struct sockaddr_in sin;
int slen;
/* establish command port using TCP/IP */
s = socket(AF_INET, SOCK_STREAM, 0);
sin.sin_addr.s_addr = htonl(0);
sin.sin_port = htons(MyPort);
bind(s,(struct sockaddr *)&sin,sizeof(sin));
listen(s,1);
while(1){
slen = sizeof(sin); /* wait for connection */
ns = accept(s,(struct sockaddr *)&sin,&slen);
if(ns < 0)
continue;
if(!fork()){ /* spawn off process to deal with connection */
process(ns);
exit(0);
}
close(ns); /* close off socket in parent */
}
}
#define CMDLEN 5
process(fd)
int fd;{
char buf[128];
int n,l;
char req;
int port, data;
iopl(3);
while ( 1 ){
l = 0;
while ( l < CMDLEN ){
n = read(fd,&buf[l],(CMDLEN-l));
if(n < 0) goto done_err;
l += n;
}
buf[CMDLEN] = '\0';
sscanf(buf,"%c%02x%02x",&req,&port,&data);
switch(req){
case 'q':
goto done_normal;
case 'w':
le_write(port,data);
break;
case 'r':
data = le_read(port);
break;
}
sprintf(buf,"%02x",data);
if(write(fd,buf,2)<0)
goto done_err;
}
done_normal:
close(fd);
return(0);
done_err:
close(fd);
return(-1);
}
le_read(p)
int p;{
int x;
outb(p,LPTDAT); /* address */
outb(0x01,LPTCTL); /* address strobe */
outb(0x00,LPTCTL); /* reset address strobe */
outb(0x02,LPTCTL); /* read high nibble */
x = inb(LPTSTAT)>>4;
outb(0x0a,LPTCTL); /* read strobe lower nibble */
x |= (inb(LPTSTAT) & 0xf0);
outb(0x00,LPTCTL); /* reset read strobe */
return(x);
}
le_write(p,x)
int p,x;{
outb(p,LPTDAT); /* address */
outb(0x01,LPTCTL); /* address strobe */
outb(0x00,LPTCTL); /* reset address strobe */
outb(x,LPTDAT); /* data */
outb(0x04,LPTCTL); /* write strobe */
outb(0x00,LPTCTL); /* reset write strobe */
}