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
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419