Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygen8390.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS Novell Eagle 2000 driver 00004 * FILE: ne2000/8390.c 00005 * PURPOSE: DP8390 NIC specific routines 00006 * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net) 00007 * REVISIONS: 00008 * CSH 27/08-2000 Created 00009 */ 00010 #include <ne2000.h> 00011 00012 /* Null-terminated array of ports to probe. This is "semi-risky" (Don Becker). */ 00013 ULONG_PTR ProbeAddressList[] = { 0x280, 0x300, 0x320, 0x340, 0x360, 0x380, 0 }; 00014 00015 static BOOLEAN ProbeAddressForNIC( 00016 ULONG_PTR address) 00017 /* 00018 * FUNCTION: Probes an address for a NIC 00019 * ARGUMENTS: 00020 * address = Base address to probe 00021 * RETURNS: 00022 * TRUE if an NIC is found at the address 00023 * FALSE otherwise 00024 * NOTES: 00025 * If the adapter responds correctly to a 00026 * stop command we assume it is present 00027 */ 00028 { 00029 UCHAR Tmp; 00030 00031 NDIS_DbgPrint(MID_TRACE, ("Probing address 0x%x\n", address)); 00032 00033 /* Disable interrupts */ 00034 NdisRawWritePortUchar(address + PG0_IMR, 0); 00035 00036 /* Stop the NIC */ 00037 NdisRawWritePortUchar(address + PG0_CR, CR_STP | CR_RD2); 00038 00039 /* Pause for 1.6ms */ 00040 NdisStallExecution(1600); 00041 00042 /* Read NIC response */ 00043 NdisRawReadPortUchar(address + PG0_CR, &Tmp); 00044 00045 if ((Tmp == (CR_RD2 | CR_STP)) || (Tmp == (CR_RD2 | CR_STP | CR_STA))) 00046 return TRUE; 00047 else 00048 return FALSE; 00049 } 00050 00051 00052 BOOLEAN NICCheck( 00053 PNIC_ADAPTER Adapter) 00054 /* 00055 * FUNCTION: Tests for a NIC 00056 * ARGUMENTS: 00057 * Adapter = Pointer to adapter information 00058 * RETURNS: 00059 * TRUE if NIC is believed to be present, FALSE if not 00060 */ 00061 { 00062 int i; 00063 00064 NDIS_DbgPrint(MAX_TRACE, ("Called\n")); 00065 00066 /* first try the supplied value */ 00067 if(ProbeAddressForNIC(Adapter->IoBaseAddress)) 00068 { 00069 NDIS_DbgPrint(MID_TRACE, ("Found adapter at 0x%x\n", Adapter->IoBaseAddress)); 00070 return TRUE; 00071 } 00072 00073 /* ok, no dice, time to probe */ 00074 for(i = 0; ProbeAddressList[i]; i++) 00075 { 00076 if(ProbeAddressForNIC(ProbeAddressList[i])) 00077 { 00078 NDIS_DbgPrint(MID_TRACE, ("Found adapter at address 0x%x\n", ProbeAddressList[i])); 00079 Adapter->IoBaseAddress = ProbeAddressList[i]; 00080 return TRUE; 00081 } 00082 } 00083 00084 NDIS_DbgPrint(MIN_TRACE,("Adapter NOT found!\n")); 00085 return FALSE; 00086 } 00087 00088 00089 static BOOLEAN NICTestAddress( 00090 PNIC_ADAPTER Adapter, 00091 ULONG Address) 00092 /* 00093 * FUNCTION: Tests if an address is writable 00094 * ARGUMENTS: 00095 * Adapter = Pointer to adapter information 00096 * RETURNS: 00097 * TRUE if the address is writable, FALSE if not 00098 */ 00099 { 00100 USHORT Data; 00101 USHORT Tmp; 00102 00103 /* Read one word */ 00104 NICReadDataAlign(Adapter, &Data, Address, 0x02); 00105 00106 /* Alter it */ 00107 Data ^= 0xFFFF; 00108 00109 /* Write it back */ 00110 NICWriteDataAlign(Adapter, Address, &Data, 0x02); 00111 00112 /* Check if it has changed on the NIC */ 00113 NICReadDataAlign(Adapter, &Tmp, Address, 0x02); 00114 00115 return (Data == Tmp); 00116 } 00117 00118 00119 static BOOLEAN NICTestRAM( 00120 PNIC_ADAPTER Adapter) 00121 /* 00122 * FUNCTION: Finds out how much RAM a NIC has 00123 * ARGUMENTS: 00124 * Adapter = Pointer to adapter information 00125 * RETURNS: 00126 * TRUE if the RAM size was found, FALSE if not 00127 * NOTES: 00128 * Start at 1KB and test for every 1KB up to 64KB 00129 */ 00130 { 00131 ULONG_PTR Base; 00132 00133 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00134 00135 /* Locate RAM base address */ 00136 for (Base = 0x0400; Base < 0x10000; Base += 0x0400) { 00137 if (NICTestAddress(Adapter, Base)) 00138 break; 00139 } 00140 00141 if (Base == 0x10000) { 00142 /* No RAM on this board */ 00143 NDIS_DbgPrint(MIN_TRACE, ("No RAM found on board.\n")); 00144 return FALSE; 00145 } 00146 00147 Adapter->RamBase = (PUCHAR)Base; 00148 00149 /* Find RAM size */ 00150 for (; Base < 0x10000; Base += 0x0400) { 00151 if (!NICTestAddress(Adapter, Base)) 00152 break; 00153 } 00154 00155 Adapter->RamSize = (UINT)(Base - (ULONG_PTR)Adapter->RamBase); 00156 00157 NDIS_DbgPrint(MID_TRACE, ("RAM is at (0x%X). Size is (0x%X).\n", 00158 Adapter->RamBase, Adapter->RamSize)); 00159 00160 return TRUE; 00161 } 00162 00163 00164 static VOID NICSetPhysicalAddress( 00165 PNIC_ADAPTER Adapter) 00166 /* 00167 * FUNCTION: Initializes the physical address on the NIC 00168 * ARGUMENTS: 00169 * Adapter = Pointer to adapter information 00170 * NOTES: 00171 * The physical address is taken from Adapter. 00172 * The NIC is stopped by this operation 00173 */ 00174 { 00175 UINT i; 00176 00177 /* Select page 1 */ 00178 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); 00179 00180 /* Initialize PAR - Physical Address Registers */ 00181 for (i = 0; i < 0x06; i++) 00182 NdisRawWritePortUchar(Adapter->IOBase + PG1_PAR + i, Adapter->StationAddress[i]); 00183 00184 /* Go back to page 0 */ 00185 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 00186 } 00187 00188 00189 static VOID NICSetMulticastAddressMask( 00190 PNIC_ADAPTER Adapter) 00191 /* 00192 * FUNCTION: Initializes the multicast address mask on the NIC 00193 * ARGUMENTS: 00194 * Adapter = Pointer to adapter information 00195 * NOTES: 00196 * The multicast address mask is taken from Adapter. 00197 * The NIC is stopped by this operation 00198 */ 00199 { 00200 UINT i; 00201 00202 /* Select page 1 */ 00203 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); 00204 00205 /* Initialize MAR - Multicast Address Registers */ 00206 for (i = 0; i < 0x08; i++) 00207 NdisRawWritePortUchar(Adapter->IOBase + PG1_MAR + i, Adapter->MulticastAddressMask[i]); 00208 00209 /* Go back to page 0 */ 00210 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 00211 } 00212 00213 00214 static BOOLEAN NICReadSAPROM( 00215 PNIC_ADAPTER Adapter) 00216 /* 00217 * FUNCTION: Reads the Station Address PROM data from the NIC 00218 * ARGUMENTS: 00219 * Adapter = Pointer to adapter information 00220 * RETURNS: 00221 * TRUE if a the NIC is an NE2000 00222 * NOTES: 00223 * This routine also determines if the NIC can support word mode transfers 00224 * and if it does initializes the NIC for word mode. 00225 * The station address in the adapter structure is initialized with 00226 * the address from the SAPROM 00227 */ 00228 { 00229 UINT i; 00230 UCHAR Buffer[32]; 00231 UCHAR WordLength; 00232 00233 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00234 00235 /* Read Station Address PROM (SAPROM) which is 16 bytes at remote DMA address 0. 00236 Some cards double the data read which we must compensate for */ 00237 00238 /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ 00239 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x20); 00240 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); 00241 00242 /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ 00243 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, 0x00); 00244 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, 0x00); 00245 00246 /* Select page 0, read and start the NIC */ 00247 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); 00248 00249 /* Read one byte at a time */ 00250 WordLength = 2; /* Assume a word is two bytes */ 00251 for (i = 0; i < 32; i += 2) { 00252 NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i]); 00253 NdisRawReadPortUchar(Adapter->IOBase + NIC_DATA, &Buffer[i + 1]); 00254 if (Buffer[i] != Buffer[i + 1]) 00255 WordLength = 1; /* A word is one byte long */ 00256 } 00257 00258 /* If WordLength is 2 the data read before was doubled. We must compensate for this */ 00259 if (WordLength == 2) { 00260 NDIS_DbgPrint(MAX_TRACE,("NE2000 or compatible network adapter found.\n")); 00261 00262 Adapter->WordMode = TRUE; 00263 00264 /* Move the SAPROM data to the adapter object */ 00265 for (i = 0; i < 16; i++) 00266 Adapter->SAPROM[i] = Buffer[i * 2]; 00267 00268 /* Copy the permanent address */ 00269 NdisMoveMemory( 00270 (PVOID)&Adapter->PermanentAddress, 00271 (PVOID)&Adapter->SAPROM, 00272 DRIVER_LENGTH_OF_ADDRESS); 00273 00274 /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */ 00275 NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10); 00276 00277 return TRUE; 00278 } else { 00279 NDIS_DbgPrint(MAX_TRACE, ("NE1000 or compatible network adapter found.\n")); 00280 00281 Adapter->WordMode = FALSE; 00282 00283 return FALSE; 00284 } 00285 } 00286 00287 00288 NDIS_STATUS NICInitialize( 00289 PNIC_ADAPTER Adapter) 00290 /* 00291 * FUNCTION: Initializes a NIC 00292 * ARGUMENTS: 00293 * Adapter = Pointer to adapter information 00294 * RETURNS: 00295 * Status of NIC initialization 00296 * NOTES: 00297 * The NIC is put into loopback mode 00298 */ 00299 { 00300 UCHAR Tmp; 00301 00302 NDIS_DbgPrint(MID_TRACE, ("Called.\n")); 00303 00304 /* Reset the NIC */ 00305 NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp); 00306 00307 /* Wait for 1.6ms */ 00308 NdisStallExecution(1600); 00309 00310 /* Write the value back */ 00311 NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp); 00312 00313 /* Select page 0 and stop NIC */ 00314 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 00315 00316 /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */ 00317 NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10); 00318 00319 /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */ 00320 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); 00321 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); 00322 00323 /* Initialize RCR - Receive Configuration Register (monitor mode) */ 00324 NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); 00325 00326 /* Enter loopback mode (internal NIC module loopback) */ 00327 NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); 00328 00329 /* Read the Station Address PROM */ 00330 if (!NICReadSAPROM(Adapter)) 00331 return NDIS_STATUS_ADAPTER_NOT_FOUND; 00332 00333 NDIS_DbgPrint(MID_TRACE, ("Station address is (%02X %02X %02X %02X %02X %02X).\n", 00334 Adapter->StationAddress[0], Adapter->StationAddress[1], 00335 Adapter->StationAddress[2], Adapter->StationAddress[3], 00336 Adapter->StationAddress[4], Adapter->StationAddress[5])); 00337 00338 /* Select page 0 and start NIC */ 00339 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); 00340 00341 /* Clear ISR - Interrupt Status Register */ 00342 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF); 00343 00344 /* Find NIC RAM size */ 00345 NICTestRAM(Adapter); 00346 00347 return NDIS_STATUS_SUCCESS; 00348 } 00349 00350 00351 NDIS_STATUS NICSetup( 00352 PNIC_ADAPTER Adapter) 00353 /* 00354 * FUNCTION: Sets up a NIC 00355 * ARGUMENTS: 00356 * Adapter = Pointer to adapter information 00357 * RETURNS: 00358 * Status of operation 00359 * NOTES: 00360 * The NIC is put into loopback mode 00361 */ 00362 { 00363 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00364 00365 if (Adapter->WordMode ) { 00366 /* Initialize DCR - Data Configuration Register (word mode/4 words FIFO) */ 00367 NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_WTS | DCR_LS | DCR_FT10); 00368 } else { 00369 /* Initialize DCR - Data Configuration Register (byte mode/8 bytes FIFO) */ 00370 NdisRawWritePortUchar(Adapter->IOBase + PG0_DCR, DCR_LS | DCR_FT10); 00371 } 00372 00373 /* Clear RBCR0 and RBCR1 - Remote Byte Count Registers */ 00374 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); 00375 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); 00376 00377 /* Initialize RCR - Receive Configuration Register (monitor mode) */ 00378 NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); 00379 00380 /* Enter loopback mode (internal NIC module loopback) */ 00381 NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); 00382 00383 /* Set boundary page */ 00384 NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, Adapter->NextPacket); 00385 00386 /* Set start page */ 00387 NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTART, Adapter->PageStart); 00388 00389 /* Set stop page */ 00390 NdisRawWritePortUchar(Adapter->IOBase + PG0_PSTOP, Adapter->PageStop); 00391 00392 /* Program our address on the NIC */ 00393 NICSetPhysicalAddress(Adapter); 00394 00395 /* Program the multicast address mask on the NIC */ 00396 NICSetMulticastAddressMask(Adapter); 00397 00398 /* Select page 1 and stop NIC */ 00399 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE1); 00400 00401 /* Initialize current page register */ 00402 NdisRawWritePortUchar(Adapter->IOBase + PG1_CURR, Adapter->PageStart + 1); 00403 00404 /* Select page 0 and stop NIC */ 00405 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 00406 00407 /* Clear ISR - Interrupt Status Register */ 00408 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, 0xFF); 00409 00410 /* Initialize IMR - Interrupt Mask Register */ 00411 NdisRawWritePortUchar(Adapter->IOBase + PG0_IMR, Adapter->InterruptMask); 00412 00413 /* Select page 0 and start NIC */ 00414 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); 00415 00416 Adapter->CurrentPage = Adapter->PageStart + 1; 00417 Adapter->NextPacket = Adapter->PageStart + 1; 00418 Adapter->BufferOverflow = FALSE; 00419 Adapter->ReceiveError = FALSE; 00420 Adapter->TransmitError = FALSE; 00421 00422 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n")); 00423 00424 return NDIS_STATUS_SUCCESS; 00425 } 00426 00427 00428 NDIS_STATUS NICStart( 00429 PNIC_ADAPTER Adapter) 00430 /* 00431 * FUNCTION: Starts a NIC 00432 * ARGUMENTS: 00433 * Adapter = Pointer to adapter information 00434 * RETURNS: 00435 * Status of operation 00436 */ 00437 { 00438 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00439 00440 /* Take NIC out of loopback mode */ 00441 NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, 0x00); 00442 00443 /* Initialize RCR - Receive Configuration Register (accept all) */ 00444 NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_AB | RCR_AM | RCR_PRO); 00445 00446 return NDIS_STATUS_SUCCESS; 00447 } 00448 00449 00450 NDIS_STATUS NICStop( 00451 PNIC_ADAPTER Adapter) 00452 /* 00453 * FUNCTION: Stops a NIC 00454 * ARGUMENTS: 00455 * Adapter = Pointer to adapter information 00456 * RETURNS: 00457 * Status of operation 00458 */ 00459 { 00460 UCHAR Tmp; 00461 UINT i; 00462 00463 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00464 00465 /* Select page 0 and stop NIC */ 00466 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 00467 00468 /* Clear Remote Byte Count Register so ISR_RST will be set */ 00469 NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00); 00470 NdisRawWritePortUchar( Adapter->IOBase + PG0_RBCR0, 0x00); 00471 00472 /* Wait for ISR_RST to be set, but timeout after 2ms */ 00473 for (i = 0; i < 4; i++) { 00474 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); 00475 if (Tmp & ISR_RST) 00476 break; 00477 00478 NdisStallExecution(500); 00479 } 00480 00481 #if DBG 00482 if (i == 4) 00483 NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n")); 00484 #endif 00485 00486 /* Initialize RCR - Receive Configuration Register (monitor mode) */ 00487 NdisRawWritePortUchar(Adapter->IOBase + PG0_RCR, RCR_MON); 00488 00489 /* Initialize TCR - Transmit Configuration Register (loopback mode) */ 00490 NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); 00491 00492 /* Start NIC */ 00493 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2); 00494 00495 return NDIS_STATUS_SUCCESS; 00496 } 00497 00498 00499 NDIS_STATUS NICReset( 00500 PNIC_ADAPTER Adapter) 00501 /* 00502 * FUNCTION: Resets a NIC 00503 * ARGUMENTS: 00504 * Adapter = Pointer to adapter information 00505 * RETURNS: 00506 * Status of operation 00507 */ 00508 { 00509 UCHAR Tmp; 00510 00511 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00512 00513 /* Stop the NIC */ 00514 NICStop(Adapter); 00515 00516 /* Reset the NIC */ 00517 NdisRawReadPortUchar(Adapter->IOBase + NIC_RESET, &Tmp); 00518 00519 /* Wait for 1.6ms */ 00520 NdisStallExecution(1600); 00521 00522 /* Write the value back */ 00523 NdisRawWritePortUchar(Adapter->IOBase + NIC_RESET, Tmp); 00524 00525 /* Restart the NIC */ 00526 NICStart(Adapter); 00527 00528 return NDIS_STATUS_SUCCESS; 00529 } 00530 00531 00532 static VOID NICStartTransmit( 00533 PNIC_ADAPTER Adapter) 00534 /* 00535 * FUNCTION: Starts transmitting a packet 00536 * ARGUMENTS: 00537 * Adapter = Pointer to adapter information 00538 */ 00539 { 00540 UINT Length; 00541 UCHAR FrameStart; 00542 UCHAR Tmp; 00543 00544 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00545 00546 if (Adapter->TXCurrent < 0) return; 00547 00548 //FrameStart = Adapter->TXStart + Adapter->TXCurrent * DRIVER_BLOCK_SIZE; 00549 //FrameStart = Adapter->TXStart; 00550 FrameStart = (UCHAR)(Adapter->TXStart + (UCHAR)(Adapter->TXCurrent * BUFFERS_PER_TX_BUF)); 00551 00552 /* Set start of frame */ 00553 NdisRawReadPortUchar(Adapter->IOBase + PG0_TPSR, &Tmp); 00554 // NdisRawWritePortUchar(Adapter->IOBase + PG0_TPSR, 00555 // Adapter->TXStart + Adapter->TXCurrent * DRIVER_BLOCK_SIZE); 00556 00557 NdisRawWritePortUchar(Adapter->IOBase + PG0_TPSR, FrameStart); 00558 //NDIS_DbgPrint(MID_TRACE, ("Setting start of frame to (%d).\n", FrameStart)); 00559 00560 /* Set length of frame */ 00561 Length = Adapter->TXSize[Adapter->TXCurrent]; 00562 NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR0, Length & 0xFF); 00563 NdisRawWritePortUchar(Adapter->IOBase + PG0_TBCR1, Length >> 8); 00564 00565 /* Start transmitting */ 00566 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_TXP | CR_RD2); 00567 00568 NDIS_DbgPrint(MID_TRACE, ("Transmitting. FrameStart (%d) TXCurrent (%d) TXStart (%d) Length (%d).\n\n", 00569 FrameStart, 00570 Adapter->TXCurrent, 00571 Adapter->TXStart, 00572 Length)); 00573 00574 } 00575 00576 00577 static VOID NICSetBoundaryPage( 00578 PNIC_ADAPTER Adapter) 00579 /* 00580 * FUNCTION: Sets the boundary page on the adapter to be one less than NextPacket 00581 * ARGUMENTS: 00582 * Adapter = Pointer to adapter information 00583 */ 00584 { 00585 if (Adapter->NextPacket == Adapter->PageStart) { 00586 NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, 00587 (UCHAR)(Adapter->PageStop - 1)); 00588 } else { 00589 NdisRawWritePortUchar(Adapter->IOBase + PG0_BNRY, 00590 (UCHAR)(Adapter->NextPacket - 1)); 00591 } 00592 } 00593 00594 00595 static VOID NICGetCurrentPage( 00596 PNIC_ADAPTER Adapter) 00597 /* 00598 * FUNCTION: Retrieves the current page from the adapter 00599 * ARGUMENTS: 00600 * Adapter = Pointer to adapter information 00601 */ 00602 { 00603 UCHAR Current; 00604 00605 /* Select page 1 */ 00606 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE1); 00607 00608 /* Read current page */ 00609 NdisRawReadPortUchar(Adapter->IOBase + PG1_CURR, &Current); 00610 00611 /* Select page 0 */ 00612 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); 00613 00614 Adapter->CurrentPage = Current; 00615 } 00616 00617 00618 VOID NICUpdateCounters( 00619 PNIC_ADAPTER Adapter) 00620 /* 00621 * FUNCTION: Updates counters 00622 * ARGUMENTS: 00623 * Adapter = Pointer to adapter information 00624 */ 00625 { 00626 UCHAR Tmp; 00627 00628 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00629 00630 NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR0, &Tmp); 00631 Adapter->FrameAlignmentErrors += Tmp; 00632 00633 NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR1, &Tmp); 00634 Adapter->CrcErrors += Tmp; 00635 00636 NdisRawReadPortUchar(Adapter->IOBase + PG0_CNTR2, &Tmp); 00637 Adapter->MissedPackets += Tmp; 00638 } 00639 00640 00641 VOID NICReadDataAlign( 00642 PNIC_ADAPTER Adapter, 00643 PUSHORT Target, 00644 ULONG_PTR Source, 00645 USHORT Length) 00646 /* 00647 * FUNCTION: Copies data from a NIC's RAM into a buffer 00648 * ARGUMENTS: 00649 * Adapter = Pointer to adapter information 00650 * Target = Pointer to buffer to copy data into (in host memory) 00651 * Source = Offset into NIC's RAM (must be an even number) 00652 * Length = Number of bytes to copy from NIC's RAM (must be an even number) 00653 */ 00654 { 00655 UCHAR Tmp; 00656 USHORT Count; 00657 00658 Count = Length; 00659 00660 /* Select page 0 and start the NIC */ 00661 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); 00662 00663 /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ 00664 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Source & 0xFF)); 00665 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Source >> 8)); 00666 00667 /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ 00668 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF)); 00669 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8)); 00670 00671 /* Select page 0, read and start the NIC */ 00672 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); 00673 00674 if (Adapter->WordMode) 00675 NdisRawReadPortBufferUshort(Adapter->IOBase + NIC_DATA, Target, Count >> 1); 00676 else 00677 NdisRawReadPortBufferUchar(Adapter->IOBase + NIC_DATA, Target, Count); 00678 00679 /* Wait for remote DMA to complete, but timeout after some time */ 00680 for (Count = 0; Count < 0xFFFF; Count++) { 00681 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); 00682 if (Tmp & ISR_RDC) 00683 break; 00684 00685 NdisStallExecution(4); 00686 } 00687 00688 #if DBG 00689 if (Count == 0xFFFF) 00690 NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); 00691 #endif 00692 00693 /* Clear remote DMA bit in ISR - Interrupt Status Register */ 00694 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); 00695 } 00696 00697 00698 VOID NICWriteDataAlign( 00699 PNIC_ADAPTER Adapter, 00700 ULONG_PTR Target, 00701 PUSHORT Source, 00702 USHORT Length) 00703 /* 00704 * FUNCTION: Copies data from a buffer into the NIC's RAM 00705 * ARGUMENTS: 00706 * Adapter = Pointer to adapter information 00707 * Target = Offset into NIC's RAM (must be an even number) 00708 * Source = Pointer to buffer to copy data from (in host memory) 00709 * Length = Number of bytes to copy from the buffer (must be an even number) 00710 */ 00711 { 00712 UCHAR Tmp; 00713 USHORT Count; 00714 00715 /* Select page 0 and start the NIC */ 00716 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2 | CR_PAGE0); 00717 00718 /* Handle read-before-write bug */ 00719 00720 /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ 00721 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF)); 00722 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8)); 00723 00724 /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ 00725 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x02); 00726 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); 00727 00728 /* Read and start the NIC */ 00729 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD0 | CR_PAGE0); 00730 00731 /* Read data */ 00732 NdisRawReadPortUshort(Adapter->IOBase + NIC_DATA, &Count); 00733 00734 /* Wait for remote DMA to complete, but timeout after some time */ 00735 for (Count = 0; Count < 0xFFFF; Count++) { 00736 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); 00737 if (Tmp & ISR_RDC) 00738 break; 00739 00740 NdisStallExecution(4); 00741 } 00742 00743 #if DBG 00744 if (Count == 0xFFFF) 00745 NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); 00746 #endif 00747 00748 /* Clear remote DMA bit in ISR - Interrupt Status Register */ 00749 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); 00750 00751 00752 /* Now output some data */ 00753 Count = Length; 00754 00755 /* Initialize RSAR0 and RSAR1 - Remote Start Address Registers */ 00756 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR0, (UCHAR)(Target & 0xFF)); 00757 NdisRawWritePortUchar(Adapter->IOBase + PG0_RSAR1, (UCHAR)(Target >> 8)); 00758 00759 /* Initialize RBCR0 and RBCR1 - Remote Byte Count Registers */ 00760 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, (UCHAR)(Count & 0xFF)); 00761 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, (UCHAR)(Count >> 8)); 00762 00763 /* Write and start the NIC */ 00764 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD1 | CR_PAGE0); 00765 00766 if (Adapter->WordMode) 00767 NdisRawWritePortBufferUshort(Adapter->IOBase + NIC_DATA, Source, Count >> 1); 00768 else 00769 NdisRawWritePortBufferUchar(Adapter->IOBase + NIC_DATA, Source, Count); 00770 00771 /* Wait for remote DMA to complete, but timeout after some time */ 00772 for (Count = 0; Count < 0xFFFF; Count++) { 00773 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); 00774 if (Tmp & ISR_RDC) 00775 break; 00776 00777 NdisStallExecution(4); 00778 } 00779 00780 #if DBG 00781 if (Count == 0xFFFF) 00782 NDIS_DbgPrint(MIN_TRACE, ("Remote DMA did not complete.\n")); 00783 #endif 00784 00785 /* Clear remote DMA bit in ISR - Interrupt Status Register */ 00786 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISR_RDC); 00787 } 00788 00789 00790 VOID NICReadData( 00791 PNIC_ADAPTER Adapter, 00792 PUCHAR Target, 00793 ULONG_PTR Source, 00794 USHORT Length) 00795 /* 00796 * FUNCTION: Copies data from a NIC's RAM into a buffer 00797 * ARGUMENTS: 00798 * Adapter = Pointer to adapter information 00799 * Target = Pointer to buffer to copy data into (in host memory) 00800 * Source = Offset into NIC's RAM 00801 * Length = Number of bytes to copy from NIC's RAM 00802 */ 00803 { 00804 USHORT Tmp; 00805 00806 /* Avoid transfers to odd addresses */ 00807 if (Source & 0x01) { 00808 /* Transfer one word and use the MSB */ 00809 NICReadDataAlign(Adapter, &Tmp, Source - 1, 0x02); 00810 *Target = (UCHAR)(Tmp >> 8); 00811 Source++; 00812 Target++; 00813 Length--; 00814 } 00815 00816 if (Length & 0x01) { 00817 /* Transfer as many words as we can without exceeding the buffer length */ 00818 Tmp = Length & 0xFFFE; 00819 NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Tmp); 00820 Source += Tmp; 00821 Target = (PUCHAR)((ULONG_PTR) Target + Tmp); 00822 00823 /* Read one word and keep the LSB */ 00824 NICReadDataAlign(Adapter, &Tmp, Source, 0x02); 00825 *Target = (UCHAR)(Tmp & 0x00FF); 00826 } else 00827 /* Transfer the rest of the data */ 00828 NICReadDataAlign(Adapter, (PUSHORT)Target, Source, Length); 00829 } 00830 00831 00832 VOID NICWriteData( 00833 PNIC_ADAPTER Adapter, 00834 ULONG_PTR Target, 00835 PUCHAR Source, 00836 USHORT Length) 00837 /* 00838 * FUNCTION: Copies data from a buffer into NIC's RAM 00839 * ARGUMENTS: 00840 * Adapter = Pointer to adapter information 00841 * Target = Offset into NIC's RAM to store data 00842 * Source = Pointer to buffer to copy data from (in host memory) 00843 * Length = Number of bytes to copy from buffer 00844 */ 00845 { 00846 USHORT Tmp; 00847 00848 /* Avoid transfers to odd addresses */ 00849 if (Target & 0x01) { 00850 /* Read one word */ 00851 NICReadDataAlign(Adapter, &Tmp, Target - 1, 0x02); 00852 00853 /* Merge LSB with the new byte which become the new MSB */ 00854 Tmp = (Tmp & 0x00FF) | (*Source << 8); 00855 00856 /* Finally write the value back */ 00857 NICWriteDataAlign(Adapter, Target - 1, &Tmp, 0x02); 00858 00859 /* Update pointers */ 00860 Source = (PUCHAR) ((ULONG_PTR) Source + 1); 00861 Target += 1; 00862 Length--; 00863 } 00864 00865 if (Length & 0x01) { 00866 /* Transfer as many words as we can without exceeding the transfer length */ 00867 Tmp = Length & 0xFFFE; 00868 NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Tmp); 00869 Source += Tmp; 00870 Target += Tmp; 00871 00872 /* Read one word */ 00873 NICReadDataAlign(Adapter, &Tmp, Target, 0x02); 00874 00875 /* Merge MSB with the new byte which become the new LSB */ 00876 Tmp = (Tmp & 0xFF00) | (*Source); 00877 00878 /* Finally write the value back */ 00879 NICWriteDataAlign(Adapter, Target, &Tmp, 0x02); 00880 } else 00881 /* Transfer the rest of the data */ 00882 NICWriteDataAlign(Adapter, Target, (PUSHORT)Source, Length); 00883 } 00884 00885 00886 static VOID NICIndicatePacket( 00887 PNIC_ADAPTER Adapter) 00888 /* 00889 * FUNCTION: Indicates a packet to the wrapper 00890 * ARGUMENTS: 00891 * Adapter = Pointer to adapter information 00892 */ 00893 { 00894 UINT IndicateLength; 00895 00896 IndicateLength = (Adapter->PacketHeader.PacketLength < 00897 (Adapter->LookaheadSize + DRIVER_HEADER_SIZE))? 00898 (Adapter->PacketHeader.PacketLength) : 00899 (Adapter->LookaheadSize + DRIVER_HEADER_SIZE); 00900 00901 /* Fill the lookahead buffer */ 00902 NICReadData(Adapter, 00903 (PUCHAR)&Adapter->Lookahead, 00904 Adapter->PacketOffset + sizeof(PACKET_HEADER), 00905 IndicateLength + DRIVER_HEADER_SIZE); 00906 00907 NDIS_DbgPrint(MID_TRACE, ("Indicating (%d) bytes.\n", IndicateLength)); 00908 NDIS_DbgPrint(MID_TRACE, ("ne2000!NICIndicatePacket: Indicating (%d) bytes.\n", IndicateLength)); 00909 00910 #if 0 00911 NDIS_DbgPrint(MAX_TRACE, ("FRAME:\n")); 00912 for (i = 0; i < (IndicateLength + 7) / 8; i++) { 00913 NDIS_DbgPrint(MAX_TRACE, ("%02X %02X %02X %02X %02X %02X %02X %02X\n", 00914 Adapter->Lookahead[i*8+0], 00915 Adapter->Lookahead[i*8+1], 00916 Adapter->Lookahead[i*8+2], 00917 Adapter->Lookahead[i*8+3], 00918 Adapter->Lookahead[i*8+4], 00919 Adapter->Lookahead[i*8+5], 00920 Adapter->Lookahead[i*8+6], 00921 Adapter->Lookahead[i*8+7])); 00922 } 00923 #endif 00924 00925 if (IndicateLength >= DRIVER_HEADER_SIZE) { 00926 NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n", 00927 Adapter->MiniportAdapterHandle)); 00928 NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, 00929 NULL, 00930 (PVOID)&Adapter->Lookahead, 00931 DRIVER_HEADER_SIZE, 00932 (PVOID)&Adapter->Lookahead[DRIVER_HEADER_SIZE], 00933 IndicateLength - DRIVER_HEADER_SIZE, 00934 Adapter->PacketHeader.PacketLength - DRIVER_HEADER_SIZE); 00935 } else { 00936 NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, 00937 NULL, 00938 (PVOID)&Adapter->Lookahead, 00939 IndicateLength, 00940 NULL, 00941 0, 00942 0); 00943 } 00944 } 00945 00946 00947 static VOID NICReadPacket( 00948 PNIC_ADAPTER Adapter) 00949 /* 00950 * FUNCTION: Reads a full packet from the receive buffer ring 00951 * ARGUMENTS: 00952 * Adapter = Pointer to adapter information 00953 */ 00954 { 00955 BOOLEAN SkipPacket = FALSE; 00956 00957 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 00958 00959 /* Get the header of the next packet in the receive ring */ 00960 Adapter->PacketOffset = Adapter->NextPacket << 8; 00961 NICReadData(Adapter, 00962 (PUCHAR)&Adapter->PacketHeader, 00963 Adapter->PacketOffset, 00964 sizeof(PACKET_HEADER)); 00965 00966 NDIS_DbgPrint(MAX_TRACE, ("HEADER: (Status) (0x%X)\n", Adapter->PacketHeader.Status)); 00967 NDIS_DbgPrint(MAX_TRACE, ("HEADER: (NextPacket) (0x%X)\n", Adapter->PacketHeader.NextPacket)); 00968 NDIS_DbgPrint(MAX_TRACE, ("HEADER: (PacketLength) (0x%X)\n", Adapter->PacketHeader.PacketLength)); 00969 00970 if (Adapter->PacketHeader.PacketLength < 64 || 00971 Adapter->PacketHeader.PacketLength > 1518) { /* XXX I don't think the CRC will show up... should be 1514 */ 00972 NDIS_DbgPrint(MAX_TRACE, ("Bogus packet size (%d).\n", 00973 Adapter->PacketHeader.PacketLength)); 00974 SkipPacket = TRUE; 00975 } 00976 00977 if (SkipPacket) { 00978 /* Skip packet */ 00979 Adapter->NextPacket = Adapter->CurrentPage; 00980 } else { 00981 NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n", 00982 Adapter->MiniportAdapterHandle)); 00983 NICIndicatePacket(Adapter); 00984 00985 /* Go to the next free buffer in receive ring */ 00986 Adapter->NextPacket = Adapter->PacketHeader.NextPacket; 00987 } 00988 00989 /* Update boundary page */ 00990 NICSetBoundaryPage(Adapter); 00991 } 00992 00993 00994 static VOID NICWritePacket( 00995 PNIC_ADAPTER Adapter) 00996 /* 00997 * FUNCTION: Writes a full packet to the transmit buffer ring 00998 * ARGUMENTS: 00999 * Adapter = Pointer to adapter information 01000 * NOTES: 01001 * There must be enough free buffers available in the transmit buffer ring. 01002 * The packet is taken from the head of the transmit queue and the position 01003 * into the transmit buffer ring is taken from TXNext 01004 */ 01005 { 01006 PNDIS_BUFFER SrcBuffer; 01007 UINT BytesToCopy, SrcSize, DstSize; 01008 PUCHAR SrcData; 01009 ULONG DstData; 01010 UINT TXStart; 01011 UINT TXStop; 01012 01013 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01014 01015 TXStart = Adapter->TXStart * DRIVER_BLOCK_SIZE; 01016 TXStop = (Adapter->TXStart + Adapter->TXCount) * DRIVER_BLOCK_SIZE; 01017 01018 NdisQueryPacket(Adapter->TXQueueHead, 01019 NULL, 01020 NULL, 01021 &SrcBuffer, 01022 &Adapter->TXSize[Adapter->TXNext]); 01023 01024 NDIS_DbgPrint(MID_TRACE, ("Packet (%d) is now size (%d).\n", 01025 Adapter->TXNext, 01026 Adapter->TXSize[Adapter->TXNext])); 01027 01028 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 01029 01030 DstData = TXStart + Adapter->TXNext * DRIVER_BLOCK_SIZE; 01031 DstSize = TXStop - DstData; 01032 01033 /* Start copying the data */ 01034 for (;;) { 01035 BytesToCopy = (SrcSize < DstSize)? SrcSize : DstSize; 01036 01037 NICWriteData(Adapter, DstData, SrcData, BytesToCopy); 01038 01039 SrcData = (PUCHAR)((ULONG_PTR) SrcData + BytesToCopy); 01040 SrcSize -= BytesToCopy; 01041 DstData += BytesToCopy; 01042 DstSize -= BytesToCopy; 01043 01044 if (SrcSize == 0) { 01045 /* No more bytes in source buffer. Proceed to 01046 the next buffer in the source buffer chain */ 01047 NdisGetNextBuffer(SrcBuffer, &SrcBuffer); 01048 if (!SrcBuffer) 01049 break; 01050 01051 NdisQueryBuffer(SrcBuffer, (PVOID)&SrcData, &SrcSize); 01052 } 01053 01054 if (DstSize == 0) { 01055 /* Wrap around the end of the transmit buffer ring */ 01056 DstData = TXStart; 01057 DstSize = Adapter->TXCount * DRIVER_BLOCK_SIZE; 01058 } 01059 } 01060 } 01061 01062 01063 static BOOLEAN NICPrepareForTransmit( 01064 PNIC_ADAPTER Adapter) 01065 /* 01066 * FUNCTION: Prepares a packet for transmission 01067 * ARGUMENTS: 01068 * Adapter = Pointer to adapter information 01069 * NOTES: 01070 * There must be at least one packet in the transmit queue 01071 * RETURNS: 01072 * TRUE if a packet was prepared, FALSE if not 01073 */ 01074 { 01075 UINT Length; 01076 UINT BufferCount; 01077 PNDIS_PACKET Packet; 01078 01079 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01080 01081 /* Calculate number of buffers needed to transmit packet */ 01082 NdisQueryPacket(Adapter->TXQueueHead, 01083 NULL, 01084 NULL, 01085 NULL, 01086 &Length); 01087 01088 BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE; 01089 01090 if (BufferCount > Adapter->TXFree) { 01091 NDIS_DbgPrint(MID_TRACE, ("No transmit resources. Have (%d) buffers, need (%d).\n", 01092 Adapter->TXFree, BufferCount)); 01093 /* We don't have the resources to transmit this packet right now */ 01094 return FALSE; 01095 } 01096 01097 /* Write the packet to the card */ 01098 NICWritePacket(Adapter); 01099 01100 /* If the NIC is not transmitting, reset the current transmit pointer */ 01101 if (Adapter->TXCurrent == -1) 01102 Adapter->TXCurrent = Adapter->TXNext; 01103 01104 Adapter->TXNext = (Adapter->TXNext + BufferCount) % Adapter->TXCount; 01105 Adapter->TXFree -= BufferCount; 01106 01107 /* Remove the packet from the queue */ 01108 Packet = Adapter->TXQueueHead; 01109 Adapter->TXQueueHead = RESERVED(Packet)->Next; 01110 01111 if (Packet == Adapter->TXQueueTail) 01112 Adapter->TXQueueTail = NULL; 01113 01114 /* Assume the transmit went well */ 01115 NdisMSendComplete(Adapter->MiniportAdapterHandle, 01116 Packet, 01117 NDIS_STATUS_SUCCESS); 01118 01119 return TRUE; 01120 } 01121 01122 01123 VOID NICTransmit( 01124 PNIC_ADAPTER Adapter) 01125 /* 01126 * FUNCTION: Starts transmitting packets in the transmit queue 01127 * ARGUMENTS: 01128 * Adapter = Pointer to adapter information 01129 * NOTES: 01130 * There must be at least one packet in the transmit queue 01131 */ 01132 { 01133 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01134 01135 if (Adapter->TXCurrent == -1) { 01136 /* NIC is not transmitting, so start transmitting now */ 01137 01138 /* Load next packet onto the card, and start transmitting */ 01139 if (NICPrepareForTransmit(Adapter)) 01140 NICStartTransmit(Adapter); 01141 } 01142 } 01143 01144 01145 static VOID HandleReceive( 01146 PNIC_ADAPTER Adapter) 01147 /* 01148 * FUNCTION: Handles reception of a packet 01149 * ARGUMENTS: 01150 * Adapter = Pointer to adapter information 01151 * NOTES: 01152 * Buffer overflows are also handled here 01153 */ 01154 { 01155 UINT i; 01156 UCHAR Tmp; 01157 UINT PacketCount; 01158 01159 NDIS_DbgPrint(MAX_TRACE, ("Called.\n")); 01160 01161 Adapter->DoneIndicating = FALSE; 01162 PacketCount = 0; 01163 01164 NICGetCurrentPage(Adapter); 01165 01166 if (Adapter->BufferOverflow) { 01167 01168 NDIS_DbgPrint(MID_TRACE, ("Receive ring overflow.\n")); 01169 01170 /* Select page 0 and stop the NIC */ 01171 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STP | CR_RD2 | CR_PAGE0); 01172 01173 /* Clear RBCR0,RBCR1 - Remote Byte Count Registers */ 01174 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR0, 0x00); 01175 NdisRawWritePortUchar(Adapter->IOBase + PG0_RBCR1, 0x00); 01176 01177 /* Wait for ISR_RST to be set, but timeout after 2ms */ 01178 for (i = 0; i < 4; i++) { 01179 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &Tmp); 01180 if (Tmp & ISR_RST) 01181 break; 01182 01183 NdisStallExecution(500); 01184 } 01185 01186 #if DBG 01187 if (i == 4) 01188 NDIS_DbgPrint(MIN_TRACE, ("NIC was not reset after 2ms.\n")); 01189 #endif 01190 01191 if ((Adapter->InterruptStatus & (ISR_PTX | ISR_TXE)) == 0) { 01192 /* We may need to restart the transmitter */ 01193 Adapter->TransmitPending = TRUE; 01194 } 01195 01196 /* Initialize TCR - Transmit Configuration Register to loopback mode 1 */ 01197 NdisRawWritePortUchar(Adapter->IOBase + PG0_TCR, TCR_LOOP); 01198 01199 /* Start NIC */ 01200 NdisRawWritePortUchar(Adapter->IOBase + PG0_CR, CR_STA | CR_RD2); 01201 01202 NICStart(Adapter); 01203 01204 Adapter->BufferOverflow = FALSE; 01205 } 01206 01207 if (Adapter->ReceiveError) { 01208 NDIS_DbgPrint(MID_TRACE, ("Receive error.\n")); 01209 01210 /* Skip this packet */ 01211 Adapter->NextPacket = Adapter->CurrentPage; 01212 NICSetBoundaryPage(Adapter); 01213 01214 Adapter->ReceiveError = FALSE; 01215 } 01216 01217 for (;;) { 01218 NICGetCurrentPage(Adapter); 01219 01220 NDIS_DbgPrint(MID_TRACE, ("Current page (0x%X) NextPacket (0x%X).\n", 01221 Adapter->CurrentPage, 01222 Adapter->NextPacket)); 01223 01224 if (Adapter->CurrentPage == Adapter->NextPacket) { 01225 NDIS_DbgPrint(MID_TRACE, ("No more packets.\n")); 01226 break; 01227 } else { 01228 NDIS_DbgPrint(MID_TRACE, ("Got a packet in the receive ring.\n")); 01229 01230 NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n", 01231 Adapter->MiniportAdapterHandle)); 01232 /* Read packet from receive buffer ring */ 01233 NICReadPacket(Adapter); 01234 01235 Adapter->DoneIndicating = TRUE; 01236 01237 PacketCount++; 01238 if (PacketCount == 10) { 01239 /* Don't starve transmit interrupts */ 01240 break; 01241 } 01242 } 01243 } 01244 01245 if ((Adapter->TransmitPending) && (Adapter->TXCurrent != -1)) { 01246 NDIS_DbgPrint(MID_TRACE, ("Retransmitting current packet at (%d).\n", Adapter->TXCurrent)); 01247 /* Retransmit packet */ 01248 NICStartTransmit(Adapter); 01249 Adapter->TransmitPending = FALSE; 01250 } 01251 01252 if (Adapter->DoneIndicating) 01253 NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle); 01254 } 01255 01256 01257 static VOID HandleTransmit( 01258 PNIC_ADAPTER Adapter) 01259 /* 01260 * FUNCTION: Handles transmission of a packet 01261 * ARGUMENTS: 01262 * Adapter = Pointer to adapter information 01263 */ 01264 { 01265 UINT Length; 01266 UINT BufferCount; 01267 01268 // PIP_PACKET pIPPacket; 01269 // pIPPacket = (PIP_PACKET) 01270 // DisplayIPPacket(pIPPacket); 01271 01272 if (Adapter->TransmitError) { 01273 /* FIXME: Retransmit now or let upper layer protocols handle retransmit? */ 01274 Adapter->TransmitError = FALSE; 01275 } 01276 01277 /* Free transmit buffers */ 01278 Length = Adapter->TXSize[Adapter->TXCurrent]; 01279 BufferCount = (Length + DRIVER_BLOCK_SIZE - 1) / DRIVER_BLOCK_SIZE; 01280 01281 NDIS_DbgPrint(MID_TRACE, ("Freeing (%d) buffers at (%d).\n", 01282 BufferCount, 01283 Adapter->TXCurrent)); 01284 01285 Adapter->TXFree += BufferCount; 01286 Adapter->TXSize[Adapter->TXCurrent] = 0; 01287 Adapter->TXCurrent = (Adapter->TXCurrent + BufferCount) % Adapter->TXCount; 01288 01289 if (Adapter->TXSize[Adapter->TXCurrent] == 0) { 01290 NDIS_DbgPrint(MID_TRACE, ("No more packets in transmit buffer.\n")); 01291 01292 Adapter->TXCurrent = -1; 01293 } 01294 01295 if (Adapter->TXQueueTail) { 01296 if (NICPrepareForTransmit(Adapter)) 01297 NICStartTransmit(Adapter); 01298 } 01299 } 01300 01301 01302 VOID NTAPI MiniportHandleInterrupt( 01303 IN NDIS_HANDLE MiniportAdapterContext) 01304 /* 01305 * FUNCTION: Handler for deferred processing of interrupts 01306 * ARGUMENTS: 01307 * MiniportAdapterContext = Pointer to adapter context area 01308 * NOTES: 01309 * Interrupt Service Register is read to determine which interrupts 01310 * are pending. All pending interrupts are handled 01311 */ 01312 { 01313 UCHAR ISRValue; 01314 UCHAR ISRMask; 01315 UCHAR Mask; 01316 PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext; 01317 UINT i = 0; 01318 01319 ISRMask = Adapter->InterruptMask; 01320 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue); 01321 01322 NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue)); 01323 01324 Adapter->InterruptStatus |= (ISRValue & ISRMask); 01325 01326 Mask = 0x01; 01327 while (Adapter->InterruptStatus != 0x00 && i++ < INTERRUPT_LIMIT) { 01328 01329 if (ISRValue != 0x00) { 01330 /* Acknowledge interrupts */ 01331 NdisRawWritePortUchar(Adapter->IOBase + PG0_ISR, ISRValue); 01332 Mask = 0x01; 01333 } 01334 01335 NDIS_DbgPrint(MID_TRACE, ("Adapter->InterruptStatus (0x%X) Mask (0x%X).\n", 01336 Adapter->InterruptStatus, Mask)); 01337 01338 /* Find next interrupt type */ 01339 while (((Adapter->InterruptStatus & Mask) == 0) && (Mask < ISRMask)) 01340 Mask = (Mask << 1); 01341 01342 switch (Adapter->InterruptStatus & Mask) { 01343 case ISR_OVW: 01344 NDIS_DbgPrint(MID_TRACE, ("Overflow interrupt.\n")); 01345 /* Overflow. Handled almost the same way as a receive interrupt */ 01346 Adapter->BufferOverflow = TRUE; 01347 01348 NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n", 01349 Adapter->MiniportAdapterHandle)); 01350 if(Adapter->MiniportAdapterHandle) 01351 HandleReceive(Adapter); 01352 else 01353 NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n")); 01354 01355 Adapter->InterruptStatus &= ~ISR_OVW; 01356 break; 01357 01358 case ISR_RXE: 01359 NDIS_DbgPrint(MID_TRACE, ("Receive error interrupt.\n")); 01360 NICUpdateCounters(Adapter); 01361 01362 Adapter->ReceiveError = TRUE; 01363 break; 01364 case ISR_PRX: 01365 NDIS_DbgPrint(MID_TRACE, ("Receive interrupt.\n")); 01366 01367 NDIS_DbgPrint(MAX_TRACE,("Adapter->MiniportAdapterHandle: %x\n", 01368 Adapter->MiniportAdapterHandle)); 01369 if(Adapter->MiniportAdapterHandle) 01370 HandleReceive(Adapter); 01371 else 01372 NDIS_DbgPrint(MAX_TRACE,("No miniport adapter yet\n")); 01373 01374 Adapter->InterruptStatus &= ~(ISR_PRX | ISR_RXE); 01375 break; 01376 01377 case ISR_TXE: 01378 NDIS_DbgPrint(MID_TRACE, ("Transmit error interrupt.\n")); 01379 NICUpdateCounters(Adapter); 01380 01381 Adapter->TransmitError = TRUE; 01382 break; 01383 case ISR_PTX: 01384 NDIS_DbgPrint(MID_TRACE, ("Transmit interrupt.\n")); 01385 01386 HandleTransmit(Adapter); 01387 01388 Adapter->InterruptStatus &= ~(ISR_PTX | ISR_TXE); 01389 break; 01390 01391 case ISR_CNT: 01392 NDIS_DbgPrint(MID_TRACE, ("Counter interrupt.\n")); 01393 /* Counter overflow. Read counters from the NIC */ 01394 NICUpdateCounters(Adapter); 01395 01396 Adapter->InterruptStatus &= ~ISR_CNT; 01397 break; 01398 01399 default: 01400 NDIS_DbgPrint(MID_TRACE, ("Unknown interrupt. Adapter->InterruptStatus (0x%X).\n", Adapter->InterruptStatus)); 01401 Adapter->InterruptStatus &= ~Mask; 01402 break; 01403 } 01404 01405 Mask = (Mask << 1); 01406 01407 /* Check if new interrupts are generated */ 01408 01409 NdisRawReadPortUchar(Adapter->IOBase + PG0_ISR, &ISRValue); 01410 01411 NDIS_DbgPrint(MID_TRACE, ("ISRValue (0x%X).\n", ISRValue)); 01412 01413 Adapter->InterruptStatus |= (ISRValue & ISRMask); 01414 } 01415 01416 NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext); 01417 } 01418 01419 /* EOF */ Generated on Sat May 26 2012 04:26:36 for ReactOS by
1.7.6.1
|