00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030 #include <isa/ne2k.h>
00031 #include <isa/8259.h>
00032 #include <sys/device.old.h>
00033 #include <sys/io.h>
00034 #include <sys/idt.h>
00035 #include <lib/kmalloc.h>
00036 #include <lib/kprintf.h>
00037 #include <string.h>
00038 #include <ubixos/kpanic.h>
00039 #include <ubixos/vitals.h>
00040 #include <ubixos/spinlock.h>
00041 #include <assert.h>
00042
00043
00044 static spinLock_t ne2k_spinLock = SPIN_LOCK_INITIALIZER;
00045
00046 static int dp_pkt2user(struct device *dev,int page,int length);
00047 static void getblock(struct device *dev,int page,size_t offset,size_t size,void *dst);
00048 static int dp_recv(struct device *);
00049
00050 static struct nicBuffer *ne2kBuffer = 0x0;
00051 static struct device *mDev = 0x0;
00052
00053 asm(
00054 ".globl ne2kISR \n"
00055 "ne2kISR: \n"
00056 " pusha \n"
00057 " call ne2kHandler \n"
00058 " popa \n"
00059 " iret \n"
00060 );
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 int ne2k_init() {
00071 mDev = (struct device *)kmalloc(sizeof(struct device));
00072 mDev->ioAddr = 0x280;
00073 mDev->irq = 10;
00074 setVector(&ne2kISR, mVec+10, dPresent + dInt + dDpl0);
00075 irqEnable(10);
00076
00077
00078 outportByte(mDev->ioAddr + NE_CMD, 0x21);
00079 outportByte(mDev->ioAddr + NE_DCR,0x29);
00080 outportByte(mDev->ioAddr + NE_RBCR0,0x00);
00081 outportByte(mDev->ioAddr + NE_RBCR1,0x00);
00082 outportByte(mDev->ioAddr + NE_RCR,0x3C);
00083 outportByte(mDev->ioAddr + NE_TCR,0x02);
00084 outportByte(mDev->ioAddr + NE_PSTART,startPage);
00085 outportByte(mDev->ioAddr + NE_BNRY,startPage);
00086 outportByte(mDev->ioAddr + NE_PSTOP,stopPage);
00087 outportByte(mDev->ioAddr + NE_ISR,0xFF);
00088 outportByte(mDev->ioAddr + NE_IMR,0x0B);
00089 outportByte(mDev->ioAddr + NE_CMD,0x61);
00090
00091 outportByte(mDev->ioAddr + DP_MAR0, 0xFF);
00092 outportByte(mDev->ioAddr + DP_MAR1, 0xFF);
00093 outportByte(mDev->ioAddr + DP_MAR2, 0xFF);
00094 outportByte(mDev->ioAddr + DP_MAR3, 0xFF);
00095 outportByte(mDev->ioAddr + DP_MAR4, 0xFF);
00096 outportByte(mDev->ioAddr + DP_MAR5, 0xFF);
00097 outportByte(mDev->ioAddr + DP_MAR6, 0xFF);
00098 outportByte(mDev->ioAddr + DP_MAR7, 0xFF);
00099 outportByte(mDev->ioAddr + DP_CURR, startPage + 1);
00100 outportByte(mDev->ioAddr + NE_CMD, 0x20);
00101 inportByte(mDev->ioAddr + DP_CNTR0);
00102 inportByte(mDev->ioAddr + DP_CNTR1);
00103 inportByte(mDev->ioAddr + DP_CNTR2);
00104
00105 outportByte(mDev->ioAddr + NE_TCR, 0x00);
00106
00107 outportByte(mDev->ioAddr + NE_CMD, 0x0);
00108 outportByte(mDev->ioAddr + NE_DCR, 0x29);
00109
00110 kprintf("Initialized");
00111
00112 return(0x0);
00113 }
00114
00115 int PCtoNIC(struct device *dev,void *packet,int length) {
00116 int i = 0x0;
00117 uInt16 *packet16 = (uInt16 *)packet;
00118 uInt8 *packet8 = (uInt8 *)packet;
00119 uInt8 word16 = 0x1;
00120
00121 if ((inportByte(dev->ioAddr) & 0x04) == 0x04) {
00122 kpanic("Device Not Ready\n");
00123 }
00124
00125 assert(length);
00126 if ((word16 == 1) && (length & 0x01)) {
00127 length++;
00128 }
00129
00130 outportByte(dev->ioAddr+EN0_RCNTLO,(length & 0xFF));
00131 outportByte(dev->ioAddr+EN0_RCNTHI,(length >> 8));
00132
00133 outportByte(dev->ioAddr+EN0_RSARLO,0x0);
00134 outportByte(dev->ioAddr+EN0_RSARHI,0x41);
00135
00136 outportByte(dev->ioAddr,E8390_RWRITE+E8390_START);
00137
00138 if (word16 != 0x0) {
00139 for(i=0;i<length/2;i++){
00140 outportWord(dev->ioAddr + NE_DATAPORT,packet16[i]);
00141 }
00142 }
00143 else {
00144 for(i=0;i<length;i++){
00145 outportByte(dev->ioAddr + NE_DATAPORT,packet8[i]);
00146 }
00147 }
00148
00149 for (i = 0;i<=100;i++) {
00150 if ((inportByte(dev->ioAddr+EN0_ISR) & 0x40) == 0x40) {
00151 break;
00152 }
00153 }
00154
00155 outportByte(dev->ioAddr+EN0_ISR,0x40);
00156 outportByte(dev->ioAddr+EN0_TPSR,0x41);
00157 outportByte(dev->ioAddr+0x05,(length & 0xFF));
00158 outportByte(dev->ioAddr+0x06,(length >> 8));
00159 outportByteP(dev->ioAddr,0x26);
00160
00161 return(length);
00162 }
00163
00164 int NICtoPC(struct device *dev,void *packet,int length,int nic_addr) {
00165 int i = 0x0;
00166 uInt16 *packet16 = (uInt16 *)packet;
00167
00168 assert(length);
00169
00170 if (length & 0x01)
00171 length++;
00172
00173
00174
00175 outportByte(dev->ioAddr+EN0_RCNTLO,(length & 0xFF));
00176 outportByte(dev->ioAddr+EN0_RCNTHI,(length >> 8));
00177
00178 outportByte(dev->ioAddr+EN0_RSARLO,nic_addr & 0xFF);
00179 outportByte(dev->ioAddr+EN0_RSARHI,nic_addr >> 8);
00180
00181 outportByte(dev->ioAddr,0x0A);
00182
00183 for(i=0;i<length/2;i++){
00184 packet16[i] = inportWord(dev->ioAddr + NE_DATAPORT);
00185 }
00186
00187 outportByte(dev->ioAddr+EN0_ISR,0x40);
00188 return(length);
00189 }
00190
00191 void ne2kHandler() {
00192 uInt16 isr = 0x0;
00193 uInt16 status = 0x0;
00194
00195 irqDisable(10);
00196 outportByte(mPic, eoi);
00197 outportByte(sPic, eoi);
00198
00199 asm("sti");
00200
00201 isr = inportByte(mDev->ioAddr + NE_ISR);
00202
00203 if ((isr & 0x02) == 0x02) {
00204 outportByte(mDev->ioAddr + NE_ISR, 0x0A);
00205 status = inportByte(0x280 + NE_TPSR);
00206 }
00207 if ((isr & 0x01) == 0x01) {
00208 if (dp_recv(mDev)) {
00209 kprintf("Error Getting Packet\n");
00210 }
00211 outportByte(mDev->ioAddr + NE_ISR, 0x05);
00212 }
00213
00214 outportByte(mDev->ioAddr + NE_IMR,0x0);
00215 outportByte(mDev->ioAddr + NE_IMR,0x0B);
00216
00217 asm("cli");
00218 irqEnable(10);
00219
00220 return;
00221 }
00222
00223 static int dp_recv(struct device *dev) {
00224 dp_rcvhdr_t header;
00225 unsigned int pageno = 0x0, curr = 0x0, next = 0x0;
00226 int packet_processed = 0x0, r = 0x0;
00227 uInt16 eth_type = 0x0;
00228
00229 uInt32 length = 0x0;
00230
00231 pageno = inportByte(dev->ioAddr + NE_BNRY) + 1;
00232 if (pageno == stopPage) pageno = startPage;
00233
00234 do {
00235 outportByte(dev->ioAddr + NE_CMD, 0x40);
00236 curr = inportByte(dev->ioAddr + NE_CURRENT);
00237 outportByte(dev->ioAddr, 0x0);
00238 if (curr == pageno) break;
00239 getblock(dev, pageno, (size_t)0, sizeof(header), &header);
00240 getblock(dev, pageno, sizeof(header) + 2*sizeof(ether_addr_t), sizeof(eth_type), ð_type);
00241
00242 length = (header.dr_rbcl | (header.dr_rbch << 8)) - sizeof(dp_rcvhdr_t);
00243 next = header.dr_next;
00244
00245
00246
00247 if (length < 60 || length > 1514) {
00248 kprintf("dp8390: packet with strange length arrived: %d\n",length);
00249 next= curr;
00250 }
00251 else if (next < startPage || next >= stopPage) {
00252 kprintf("dp8390: strange next page\n");
00253 next= curr;
00254 }
00255 else if (header.dr_status & RSR_FO) {
00256 kpanic("dp8390: fifo overrun, resetting receive buffer\n");
00257 next = curr;
00258 }
00259 else if (header.dr_status & RSR_PRX) {
00260 r = dp_pkt2user(dev, pageno, length);
00261 if (r != OK) {
00262 kprintf("FRUIT");
00263 return(0x0);
00264 }
00265
00266 packet_processed = 0x1;
00267 }
00268 if (next == startPage)
00269 outportByte(dev->ioAddr + NE_BNRY, stopPage - 1);
00270 else
00271 outportByte(dev->ioAddr + NE_BNRY, next - 1);
00272
00273 pageno = next;
00274
00275 } while (packet_processed == 0x0);
00276 return(0x0);
00277 }
00278
00279 static void getblock(struct device *dev,int page,size_t offset,size_t size,void *dst) {
00280 uInt16 *ha = 0x0;
00281 int i = 0x0;
00282
00283 ha = (uInt16 *) dst;
00284 offset = page * DP_PAGESIZE + offset;
00285 outportByte(dev->ioAddr + NE_RBCR0, size & 0xFF);
00286 outportByte(dev->ioAddr + NE_RBCR1, size >> 8);
00287 outportByte(dev->ioAddr + EN0_RSARLO, offset & 0xFF);
00288 outportByte(dev->ioAddr + EN0_RSARHI, offset >> 8);
00289 outportByte(dev->ioAddr + NE_CMD, E8390_RREAD | E8390_START);
00290
00291 size /= 2;
00292 for (i= 0; i<size; i++)
00293 ha[i]= inportWord(dev->ioAddr + NE_DATAPORT);
00294 outportByte(dev->ioAddr+EN0_ISR,0x40);
00295 }
00296
00297 static int dp_pkt2user(struct device *dev,int page,int length) {
00298 int last = 0x0;
00299 struct nicBuffer *tmpBuf = 0x0;
00300
00301 last = page + (length - 1) / DP_PAGESIZE;
00302
00303 if (last >= stopPage) {
00304 kprintf("FOOK STOP PAGE!!!");
00305 }
00306 else {
00307 tmpBuf = ne2kAllocBuffer(length);
00308 NICtoPC(dev,tmpBuf->buffer,length,page * DP_PAGESIZE + sizeof(dp_rcvhdr_t));
00309 }
00310 return(OK);
00311 }
00312
00313 struct nicBuffer *ne2kAllocBuffer(int length) {
00314 struct nicBuffer *tmpBuf = 0x0;
00315
00316 spinLock(&ne2k_spinLock);
00317
00318 if (ne2kBuffer == 0x0) {
00319 ne2kBuffer = (struct nicBuffer *)kmalloc(sizeof(struct nicBuffer));
00320 ne2kBuffer->next = 0x0;
00321 ne2kBuffer->length = length;
00322 ne2kBuffer->buffer = (char *)kmalloc(length);
00323 spinUnlock(&ne2k_spinLock);
00324 return(ne2kBuffer);
00325 }
00326 else {
00327 for (tmpBuf = ne2kBuffer;tmpBuf->next != 0x0;tmpBuf = tmpBuf->next);
00328
00329 tmpBuf->next = (struct nicBuffer *)kmalloc(sizeof(struct nicBuffer));
00330 tmpBuf = tmpBuf->next;
00331 tmpBuf->next = 0x0;
00332 tmpBuf->length = length;
00333 tmpBuf->buffer = (char *)kmalloc(length);
00334 spinUnlock(&ne2k_spinLock);
00335 return(tmpBuf);
00336 }
00337 spinUnlock(&ne2k_spinLock);
00338 return(0x0);
00339 }
00340
00341 struct nicBuffer *ne2kGetBuffer() {
00342 struct nicBuffer *tmpBuf = 0x0;
00343
00344 if (ne2k_spinLock == 0x1)
00345 return(0x0);
00346
00347 tmpBuf = ne2kBuffer;
00348 if (ne2kBuffer != 0x0)
00349 ne2kBuffer = ne2kBuffer->next;
00350 return(tmpBuf);
00351 }
00352
00353 void ne2kFreeBuffer(struct nicBuffer *buf) {
00354 kfree(buf->buffer);
00355 kfree(buf);
00356 return;
00357 }
00358
00359
00360
00361