Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenpcnet.c
Go to the documentation of this file.
00001 /* 00002 * ReactOS AMD PCNet Driver 00003 * 00004 * Copyright (C) 2003 Vizzini <vizzini@plasmic.com> 00005 * Copyright (C) 2004 Filip Navara <navaraf@reactos.com> 00006 * 00007 * This program is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 2 of the License, or 00010 * (at your option) any later version. 00011 * 00012 * This program is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License along 00018 * with this program; if not, write to the Free Software Foundation, Inc., 00019 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00020 * 00021 * REVISIONS: 00022 * 09-Sep-2003 vizzini - Created 00023 * 10-Oct-2004 navaraf - Fix receive to work on VMware adapters ( 00024 * need to set busmaster bit on PCI). 00025 * - Indicate receive completition. 00026 * - Implement packet transmitting. 00027 * - Don't read slot number from registry and 00028 * report itself as NDIS 5.0 miniport. 00029 * 11-Oct-2004 navaraf - Fix nasty bugs in halt code path. 00030 * 17-Oct-2004 navaraf - Add multicast support. 00031 * - Add media state detection support. 00032 * - Protect the adapter context with spinlock 00033 * and move code talking to card to inside 00034 * NdisMSynchronizeWithInterrupt calls where 00035 * necessary. 00036 * 00037 * NOTES: 00038 * - this assumes a 32-bit machine 00039 */ 00040 00041 #include "pcnet.h" 00042 00043 #define NDEBUG 00044 #include <debug.h> 00045 00046 NTSTATUS 00047 NTAPI 00048 DriverEntry( 00049 IN PDRIVER_OBJECT DriverObject, 00050 IN PUNICODE_STRING RegistryPath); 00051 00052 static VOID 00053 NTAPI 00054 MiniportHandleInterrupt( 00055 IN NDIS_HANDLE MiniportAdapterContext) 00056 /* 00057 * FUNCTION: Handle an interrupt if told to by MiniportISR 00058 * ARGUMENTS: 00059 * MiniportAdapterContext: context specified to NdisMSetAttributes 00060 * NOTES: 00061 * - Called by NDIS at DISPATCH_LEVEL 00062 */ 00063 { 00064 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; 00065 USHORT Data; 00066 UINT i = 0; 00067 00068 DPRINT("Called\n"); 00069 00070 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL); 00071 00072 NdisDprAcquireSpinLock(&Adapter->Lock); 00073 00074 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00075 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00076 00077 DPRINT("CSR0 is 0x%x\n", Data); 00078 00079 while((Data & CSR0_INTR) && i++ < INTERRUPT_LIMIT) 00080 { 00081 /* Clear interrupt flags early to avoid race conditions. */ 00082 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data); 00083 00084 if(Data & CSR0_ERR) 00085 { 00086 DPRINT("error: %x\n", Data & (CSR0_MERR|CSR0_BABL|CSR0_CERR|CSR0_MISS)); 00087 if (Data & CSR0_CERR) 00088 Adapter->Statistics.XmtCollisions++; 00089 } 00090 if(Data & CSR0_IDON) 00091 { 00092 DPRINT("IDON\n"); 00093 } 00094 if(Data & CSR0_RINT) 00095 { 00096 BOOLEAN IndicatedData = FALSE; 00097 00098 DPRINT("receive interrupt\n"); 00099 00100 while(1) 00101 { 00102 PRECEIVE_DESCRIPTOR Descriptor = Adapter->ReceiveDescriptorRingVirt + Adapter->CurrentReceiveDescriptorIndex; 00103 PCHAR Buffer; 00104 ULONG ByteCount; 00105 00106 if(Descriptor->FLAGS & RD_OWN) 00107 { 00108 DPRINT("no more receive descriptors to process\n"); 00109 break; 00110 } 00111 00112 if(Descriptor->FLAGS & RD_ERR) 00113 { 00114 DPRINT("receive descriptor error: 0x%x\n", Descriptor->FLAGS); 00115 if (Descriptor->FLAGS & RD_BUFF) 00116 Adapter->Statistics.RcvBufferErrors++; 00117 if (Descriptor->FLAGS & RD_CRC) 00118 Adapter->Statistics.RcvCrcErrors++; 00119 if (Descriptor->FLAGS & RD_OFLO) 00120 Adapter->Statistics.RcvOverflowErrors++; 00121 if (Descriptor->FLAGS & RD_FRAM) 00122 Adapter->Statistics.RcvFramingErrors++; 00123 break; 00124 } 00125 00126 if(!((Descriptor->FLAGS & RD_STP) && (Descriptor->FLAGS & RD_ENP))) 00127 { 00128 DPRINT("receive descriptor not start&end: 0x%x\n", Descriptor->FLAGS); 00129 break; 00130 } 00131 00132 Buffer = Adapter->ReceiveBufferPtrVirt + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE; 00133 ByteCount = Descriptor->MCNT & 0xfff; 00134 00135 DPRINT("Indicating a %d-byte packet (index %d)\n", ByteCount, Adapter->CurrentReceiveDescriptorIndex); 00136 00137 NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, 0, Buffer, 14, Buffer+14, ByteCount-14, ByteCount-14); 00138 00139 IndicatedData = TRUE; 00140 00141 RtlZeroMemory(Descriptor, sizeof(RECEIVE_DESCRIPTOR)); 00142 Descriptor->RBADR = 00143 (ULONG)(Adapter->ReceiveBufferPtrPhys + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE); 00144 Descriptor->BCNT = (-BUFFER_SIZE) | 0xf000; 00145 Descriptor->FLAGS |= RD_OWN; 00146 00147 Adapter->CurrentReceiveDescriptorIndex++; 00148 Adapter->CurrentReceiveDescriptorIndex %= Adapter->BufferCount; 00149 00150 Adapter->Statistics.RcvGoodFrames++; 00151 } 00152 00153 if (IndicatedData) 00154 NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle); 00155 } 00156 if(Data & CSR0_TINT) 00157 { 00158 PTRANSMIT_DESCRIPTOR Descriptor; 00159 00160 DPRINT("transmit interrupt\n"); 00161 00162 while (Adapter->CurrentTransmitStartIndex != 00163 Adapter->CurrentTransmitEndIndex) 00164 { 00165 Descriptor = Adapter->TransmitDescriptorRingVirt + Adapter->CurrentTransmitStartIndex; 00166 00167 DPRINT("buffer %d flags %x flags2 %x\n", 00168 Adapter->CurrentTransmitStartIndex, 00169 Descriptor->FLAGS, Descriptor->FLAGS2); 00170 00171 if (Descriptor->FLAGS & TD1_OWN) 00172 { 00173 DPRINT("non-TXed buffer\n"); 00174 break; 00175 } 00176 00177 if (Descriptor->FLAGS & TD1_STP) 00178 { 00179 if (Descriptor->FLAGS & TD1_ONE) 00180 Adapter->Statistics.XmtOneRetry++; 00181 else if (Descriptor->FLAGS & TD1_MORE) 00182 Adapter->Statistics.XmtMoreThanOneRetry++; 00183 } 00184 00185 if (Descriptor->FLAGS & TD1_ERR) 00186 { 00187 DPRINT("major error: %x\n", Descriptor->FLAGS2); 00188 if (Descriptor->FLAGS2 & TD2_RTRY) 00189 Adapter->Statistics.XmtRetryErrors++; 00190 if (Descriptor->FLAGS2 & TD2_LCAR) 00191 Adapter->Statistics.XmtLossesOfCarrier++; 00192 if (Descriptor->FLAGS2 & TD2_LCOL) 00193 Adapter->Statistics.XmtLateCollisions++; 00194 if (Descriptor->FLAGS2 & TD2_EXDEF) 00195 Adapter->Statistics.XmtExcessiveDefferals++; 00196 if (Descriptor->FLAGS2 & TD2_UFLO) 00197 Adapter->Statistics.XmtBufferUnderflows++; 00198 if (Descriptor->FLAGS2 & TD2_BUFF) 00199 Adapter->Statistics.XmtBufferErrors++; 00200 break; 00201 } 00202 00203 Adapter->CurrentTransmitStartIndex++; 00204 Adapter->CurrentTransmitStartIndex %= Adapter->BufferCount; 00205 00206 Adapter->Statistics.XmtGoodFrames++; 00207 } 00208 NdisMSendResourcesAvailable(Adapter->MiniportAdapterHandle); 00209 } 00210 if(Data & ~(CSR0_ERR | CSR0_IDON | CSR0_RINT | CSR0_TINT)) 00211 { 00212 DPRINT("UNHANDLED INTERRUPT CSR0 0x%x\n", Data); 00213 } 00214 00215 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00216 } 00217 00218 /* re-enable interrupts */ 00219 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA); 00220 00221 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00222 DPRINT("CSR0 is now 0x%x\n", Data); 00223 00224 NdisDprReleaseSpinLock(&Adapter->Lock); 00225 } 00226 00227 static NDIS_STATUS 00228 MiQueryCard( 00229 IN PADAPTER Adapter) 00230 /* 00231 * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector 00232 * ARGUMENTS: 00233 * MiniportAdapterContext: context supplied to NdisMSetAttributes 00234 * RETURNS: 00235 * NDIS_STATUS_FAILURE on a general error 00236 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter 00237 * NDIS_STATUS_SUCCESS on succes 00238 */ 00239 { 00240 ULONG buf32 = 0; 00241 UCHAR buf8 = 0; 00242 NDIS_STATUS Status; 00243 00244 /* Detect the card in the configured slot */ 00245 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, 0, PCI_PCIID, &buf32, 4); 00246 if(Status != 4) 00247 { 00248 Status = NDIS_STATUS_FAILURE; 00249 DPRINT1("NdisReadPciSlotInformation failed\n"); 00250 return Status; 00251 } 00252 00253 if(buf32 != PCI_ID) 00254 { 00255 Status = NDIS_STATUS_ADAPTER_NOT_FOUND; 00256 DPRINT1("card in slot isn't our: 0x%x\n", 0, buf32); 00257 return Status; 00258 } 00259 00260 /* set busmaster and io space enable bits */ 00261 buf32 = PCI_BMEN | PCI_IOEN; 00262 NdisWritePciSlotInformation(Adapter->MiniportAdapterHandle, 0, PCI_COMMAND, &buf32, 4); 00263 00264 /* get IO base physical address */ 00265 buf32 = 0; 00266 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, 0, PCI_IOBAR, &buf32, 4); 00267 if(Status != 4) 00268 { 00269 Status = NDIS_STATUS_FAILURE; 00270 DPRINT1("NdisReadPciSlotInformation failed\n"); 00271 return Status; 00272 } 00273 00274 if(!buf32) 00275 { 00276 DPRINT1("No base i/o address set\n"); 00277 return NDIS_STATUS_FAILURE; 00278 } 00279 00280 buf32 &= ~1; /* even up address - comes out odd for some reason */ 00281 00282 DPRINT("detected io address 0x%x\n", buf32); 00283 Adapter->IoBaseAddress = buf32; 00284 00285 /* get interrupt vector */ 00286 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, 0, PCI_ILR, &buf8, 1); 00287 if(Status != 1) 00288 { 00289 Status = NDIS_STATUS_FAILURE; 00290 DPRINT1("NdisReadPciSlotInformation failed\n"); 00291 return Status; 00292 } 00293 00294 DPRINT("interrupt: 0x%x\n", buf8); 00295 Adapter->InterruptVector = buf8; 00296 00297 return NDIS_STATUS_SUCCESS; 00298 } 00299 00300 static VOID 00301 MiFreeSharedMemory( 00302 PADAPTER Adapter) 00303 /* 00304 * FUNCTION: Free all allocated shared memory 00305 * ARGUMENTS: 00306 * Adapter: pointer to the miniport's adapter struct 00307 */ 00308 { 00309 NDIS_PHYSICAL_ADDRESS PhysicalAddress; 00310 00311 PhysicalAddress.u.HighPart = 0; 00312 00313 if(Adapter->InitializationBlockVirt) 00314 { 00315 PhysicalAddress.u.LowPart = (ULONG)Adapter->InitializationBlockPhys; 00316 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength, 00317 FALSE, Adapter->InitializationBlockVirt, PhysicalAddress); 00318 Adapter->InitializationBlockVirt = NULL; 00319 } 00320 00321 if(Adapter->TransmitDescriptorRingVirt) 00322 { 00323 PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitDescriptorRingPhys; 00324 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength, 00325 FALSE, Adapter->TransmitDescriptorRingVirt, PhysicalAddress); 00326 Adapter->TransmitDescriptorRingVirt = NULL; 00327 } 00328 00329 if(Adapter->ReceiveDescriptorRingVirt) 00330 { 00331 PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveDescriptorRingPhys; 00332 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength, 00333 FALSE, Adapter->ReceiveDescriptorRingVirt, PhysicalAddress); 00334 Adapter->ReceiveDescriptorRingVirt = NULL; 00335 } 00336 00337 if(Adapter->TransmitBufferPtrVirt) 00338 { 00339 PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitBufferPtrPhys; 00340 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength, 00341 TRUE, Adapter->TransmitBufferPtrVirt, PhysicalAddress); 00342 Adapter->TransmitBufferPtrVirt = NULL; 00343 } 00344 00345 if(Adapter->ReceiveBufferPtrVirt) 00346 { 00347 PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveBufferPtrPhys; 00348 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength, 00349 TRUE, Adapter->ReceiveBufferPtrVirt, PhysicalAddress); 00350 Adapter->ReceiveBufferPtrVirt = NULL; 00351 } 00352 } 00353 00354 static NDIS_STATUS 00355 MiAllocateSharedMemory( 00356 PADAPTER Adapter) 00357 /* 00358 * FUNCTION: Allocate all shared memory used by the miniport 00359 * ARGUMENTS: 00360 * Adapter: Pointer to the miniport's adapter object 00361 * RETURNS: 00362 * NDIS_STATUS_RESOURCES on insufficient memory 00363 * NDIS_STATUS_SUCCESS on success 00364 */ 00365 { 00366 PTRANSMIT_DESCRIPTOR TransmitDescriptor; 00367 PRECEIVE_DESCRIPTOR ReceiveDescriptor; 00368 NDIS_PHYSICAL_ADDRESS PhysicalAddress; 00369 ULONG i; 00370 ULONG BufferCount = NUMBER_OF_BUFFERS; 00371 ULONG LogBufferCount = LOG_NUMBER_OF_BUFFERS; 00372 00373 while (BufferCount != 0) 00374 { 00375 /* allocate the initialization block (we have this in the loop so we can use MiFreeSharedMemory) */ 00376 Adapter->InitializationBlockLength = sizeof(INITIALIZATION_BLOCK); 00377 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength, 00378 FALSE, (PVOID *)&Adapter->InitializationBlockVirt, &PhysicalAddress); 00379 if(!Adapter->InitializationBlockVirt) 00380 { 00381 /* Buffer backoff won't help us here */ 00382 DPRINT1("insufficient resources\n"); 00383 return NDIS_STATUS_RESOURCES; 00384 } 00385 00386 if(((ULONG)Adapter->InitializationBlockVirt & 0x00000003) != 0) 00387 { 00388 DPRINT1("address 0x%x not dword-aligned\n", Adapter->InitializationBlockVirt); 00389 return NDIS_STATUS_RESOURCES; 00390 } 00391 00392 Adapter->InitializationBlockPhys = (PINITIALIZATION_BLOCK)NdisGetPhysicalAddressLow(PhysicalAddress); 00393 00394 /* allocate the transport descriptor ring */ 00395 Adapter->TransmitDescriptorRingLength = sizeof(TRANSMIT_DESCRIPTOR) * BufferCount; 00396 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength, 00397 FALSE, (PVOID *)&Adapter->TransmitDescriptorRingVirt, &PhysicalAddress); 00398 if (!Adapter->TransmitDescriptorRingVirt) 00399 { 00400 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount >> 1)); 00401 BufferCount = BufferCount >> 1; 00402 LogBufferCount--; 00403 MiFreeSharedMemory(Adapter); 00404 continue; 00405 } 00406 00407 if (((ULONG)Adapter->TransmitDescriptorRingVirt & 0x00000003) != 0) 00408 { 00409 DPRINT1("address 0x%x not dword-aligned\n", Adapter->TransmitDescriptorRingVirt); 00410 return NDIS_STATUS_RESOURCES; 00411 } 00412 00413 Adapter->TransmitDescriptorRingPhys = (PTRANSMIT_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress); 00414 RtlZeroMemory(Adapter->TransmitDescriptorRingVirt, sizeof(TRANSMIT_DESCRIPTOR) * BufferCount); 00415 00416 /* allocate the receive descriptor ring */ 00417 Adapter->ReceiveDescriptorRingLength = sizeof(RECEIVE_DESCRIPTOR) * BufferCount; 00418 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength, 00419 FALSE, (PVOID *)&Adapter->ReceiveDescriptorRingVirt, &PhysicalAddress); 00420 if (!Adapter->ReceiveDescriptorRingVirt) 00421 { 00422 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount >> 1)); 00423 BufferCount = BufferCount >> 1; 00424 LogBufferCount--; 00425 MiFreeSharedMemory(Adapter); 00426 continue; 00427 } 00428 00429 if (((ULONG)Adapter->ReceiveDescriptorRingVirt & 0x00000003) != 0) 00430 { 00431 DPRINT1("address 0x%x not dword-aligned\n", Adapter->ReceiveDescriptorRingVirt); 00432 return NDIS_STATUS_RESOURCES; 00433 } 00434 00435 Adapter->ReceiveDescriptorRingPhys = (PRECEIVE_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress); 00436 RtlZeroMemory(Adapter->ReceiveDescriptorRingVirt, sizeof(RECEIVE_DESCRIPTOR) * BufferCount); 00437 00438 /* allocate transmit buffers */ 00439 Adapter->TransmitBufferLength = BUFFER_SIZE * BufferCount; 00440 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength, 00441 TRUE, (PVOID *)&Adapter->TransmitBufferPtrVirt, &PhysicalAddress); 00442 if(!Adapter->TransmitBufferPtrVirt) 00443 { 00444 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount >> 1)); 00445 BufferCount = BufferCount >> 1; 00446 LogBufferCount--; 00447 MiFreeSharedMemory(Adapter); 00448 continue; 00449 } 00450 00451 if (((ULONG)Adapter->TransmitBufferPtrVirt & 0x00000003) != 0) 00452 { 00453 DPRINT1("address 0x%x not dword-aligned\n", Adapter->TransmitBufferPtrVirt); 00454 return NDIS_STATUS_RESOURCES; 00455 } 00456 00457 Adapter->TransmitBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress); 00458 RtlZeroMemory(Adapter->TransmitBufferPtrVirt, BUFFER_SIZE * BufferCount); 00459 00460 /* allocate receive buffers */ 00461 Adapter->ReceiveBufferLength = BUFFER_SIZE * BufferCount; 00462 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength, 00463 TRUE, (PVOID *)&Adapter->ReceiveBufferPtrVirt, &PhysicalAddress); 00464 if(!Adapter->ReceiveBufferPtrVirt) 00465 { 00466 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount >> 1)); 00467 BufferCount = BufferCount >> 1; 00468 LogBufferCount--; 00469 MiFreeSharedMemory(Adapter); 00470 continue; 00471 } 00472 00473 if (((ULONG)Adapter->ReceiveBufferPtrVirt & 0x00000003) != 0) 00474 { 00475 DPRINT1("address 0x%x not dword-aligned\n", Adapter->ReceiveBufferPtrVirt); 00476 return NDIS_STATUS_RESOURCES; 00477 } 00478 00479 Adapter->ReceiveBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress); 00480 RtlZeroMemory(Adapter->ReceiveBufferPtrVirt, BUFFER_SIZE * BufferCount); 00481 00482 break; 00483 } 00484 00485 if (!BufferCount) 00486 { 00487 DPRINT1("Failed to allocate adapter buffers\n"); 00488 return NDIS_STATUS_RESOURCES; 00489 } 00490 00491 Adapter->BufferCount = BufferCount; 00492 Adapter->LogBufferCount = LogBufferCount; 00493 00494 /* initialize tx descriptors */ 00495 TransmitDescriptor = Adapter->TransmitDescriptorRingVirt; 00496 for(i = 0; i < BufferCount; i++) 00497 { 00498 (TransmitDescriptor+i)->TBADR = (ULONG)Adapter->TransmitBufferPtrPhys + i * BUFFER_SIZE; 00499 (TransmitDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */ 00500 (TransmitDescriptor+i)->FLAGS = TD1_STP | TD1_ENP; 00501 } 00502 00503 DPRINT("transmit ring initialized\n"); 00504 00505 /* initialize rx */ 00506 ReceiveDescriptor = Adapter->ReceiveDescriptorRingVirt; 00507 for(i = 0; i < BufferCount; i++) 00508 { 00509 (ReceiveDescriptor+i)->RBADR = (ULONG)Adapter->ReceiveBufferPtrPhys + i * BUFFER_SIZE; 00510 (ReceiveDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */ 00511 (ReceiveDescriptor+i)->FLAGS = RD_OWN; 00512 } 00513 00514 DPRINT("receive ring initialized\n"); 00515 00516 return NDIS_STATUS_SUCCESS; 00517 } 00518 00519 static VOID 00520 MiPrepareInitializationBlock( 00521 PADAPTER Adapter) 00522 /* 00523 * FUNCTION: Initialize the initialization block 00524 * ARGUMENTS: 00525 * Adapter: pointer to the miniport's adapter object 00526 */ 00527 { 00528 ULONG i = 0; 00529 00530 RtlZeroMemory(Adapter->InitializationBlockVirt, sizeof(INITIALIZATION_BLOCK)); 00531 00532 /* read burned-in address from card */ 00533 for(i = 0; i < 6; i++) 00534 NdisRawReadPortUchar(Adapter->PortOffset + i, Adapter->InitializationBlockVirt->PADR + i); 00535 DPRINT("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n", 00536 Adapter->InitializationBlockVirt->PADR[0], 00537 Adapter->InitializationBlockVirt->PADR[1], 00538 Adapter->InitializationBlockVirt->PADR[2], 00539 Adapter->InitializationBlockVirt->PADR[3], 00540 Adapter->InitializationBlockVirt->PADR[4], 00541 Adapter->InitializationBlockVirt->PADR[5]); 00542 00543 /* set up receive ring */ 00544 DPRINT("Receive ring physical address: 0x%x\n", Adapter->ReceiveDescriptorRingPhys); 00545 Adapter->InitializationBlockVirt->RDRA = (ULONG)Adapter->ReceiveDescriptorRingPhys; 00546 Adapter->InitializationBlockVirt->RLEN = (Adapter->LogBufferCount << 4) & 0xf0; 00547 00548 /* set up transmit ring */ 00549 DPRINT("Transmit ring physical address: 0x%x\n", Adapter->TransmitDescriptorRingPhys); 00550 Adapter->InitializationBlockVirt->TDRA = (ULONG)Adapter->TransmitDescriptorRingPhys; 00551 Adapter->InitializationBlockVirt->TLEN = (Adapter->LogBufferCount << 4) & 0xf0; 00552 } 00553 00554 static BOOLEAN 00555 NTAPI 00556 MiSyncStop( 00557 IN PVOID SynchronizeContext) 00558 /* 00559 * FUNCTION: Stop the adapter 00560 * ARGUMENTS: 00561 * SynchronizeContext: Adapter context 00562 */ 00563 { 00564 PADAPTER Adapter = (PADAPTER)SynchronizeContext; 00565 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00566 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP); 00567 return TRUE; 00568 } 00569 00570 static VOID 00571 NTAPI 00572 MiniportHalt( 00573 IN NDIS_HANDLE MiniportAdapterContext) 00574 /* 00575 * FUNCTION: Stop the adapter and release any per-adapter resources 00576 * ARGUMENTS: 00577 * MiniportAdapterContext: context specified to NdisMSetAttributes 00578 * NOTES: 00579 * - Called by NDIS at PASSIVE_LEVEL 00580 */ 00581 { 00582 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; 00583 BOOLEAN TimerCancelled; 00584 00585 DPRINT("Called\n"); 00586 ASSERT(Adapter); 00587 00588 /* stop the media detection timer */ 00589 NdisMCancelTimer(&Adapter->MediaDetectionTimer, &TimerCancelled); 00590 00591 /* stop the chip */ 00592 NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStop, Adapter); 00593 00594 /* deregister the interrupt */ 00595 NdisMDeregisterInterrupt(&Adapter->InterruptObject); 00596 00597 /* deregister i/o port range */ 00598 NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, (PVOID)Adapter->PortOffset); 00599 00600 /* deregister the shutdown routine */ 00601 NdisMDeregisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle); 00602 00603 /* free shared memory */ 00604 MiFreeSharedMemory(Adapter); 00605 00606 /* free map registers */ 00607 NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); 00608 00609 /* free the lock */ 00610 NdisFreeSpinLock(&Adapter->Lock); 00611 00612 /* free the adapter */ 00613 NdisFreeMemory(Adapter, 0, 0); 00614 } 00615 00616 static BOOLEAN 00617 NTAPI 00618 MiSyncMediaDetection( 00619 IN PVOID SynchronizeContext) 00620 /* 00621 * FUNCTION: Stop the adapter 00622 * ARGUMENTS: 00623 * SynchronizeContext: Adapter context 00624 */ 00625 { 00626 PADAPTER Adapter = (PADAPTER)SynchronizeContext; 00627 NDIS_MEDIA_STATE MediaState = MiGetMediaState(Adapter); 00628 UINT MediaSpeed = MiGetMediaSpeed(Adapter); 00629 BOOLEAN FullDuplex = MiGetMediaDuplex(Adapter); 00630 00631 DPRINT("Called\n"); 00632 DPRINT("MediaState: %d\n", MediaState); 00633 if (MediaState != Adapter->MediaState || 00634 MediaSpeed != Adapter->MediaSpeed || 00635 FullDuplex != Adapter->FullDuplex) 00636 { 00637 Adapter->MediaState = MediaState; 00638 Adapter->MediaSpeed = MediaSpeed; 00639 Adapter->FullDuplex = FullDuplex; 00640 return TRUE; 00641 } 00642 return FALSE; 00643 } 00644 00645 static VOID 00646 NTAPI 00647 MiniportMediaDetectionTimer( 00648 IN PVOID SystemSpecific1, 00649 IN PVOID FunctionContext, 00650 IN PVOID SystemSpecific2, 00651 IN PVOID SystemSpecific3) 00652 /* 00653 * FUNCTION: Periodially query media state 00654 * ARGUMENTS: 00655 * FunctionContext: Adapter context 00656 * NOTES: 00657 * - Called by NDIS at DISPATCH_LEVEL 00658 */ 00659 { 00660 PADAPTER Adapter = (PADAPTER)FunctionContext; 00661 00662 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL); 00663 00664 if (NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, 00665 MiSyncMediaDetection, 00666 FunctionContext)) 00667 { 00668 NdisMIndicateStatus(Adapter->MiniportAdapterHandle, 00669 Adapter->MediaState == NdisMediaStateConnected ? 00670 NDIS_STATUS_MEDIA_CONNECT : NDIS_STATUS_MEDIA_DISCONNECT, 00671 (PVOID)0, 0); 00672 NdisMIndicateStatusComplete(Adapter->MiniportAdapterHandle); 00673 } 00674 } 00675 00676 static VOID 00677 MiInitChip( 00678 PADAPTER Adapter) 00679 /* 00680 * FUNCTION: Initialize and start the PCNET chip 00681 * ARGUMENTS: 00682 * Adapter: pointer to the miniport's adapter struct 00683 * NOTES: 00684 * - should be coded to detect failure and return an error 00685 * - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that. 00686 */ 00687 { 00688 USHORT Data = 0; 00689 00690 DPRINT("Called\n"); 00691 00692 /* 00693 * first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset 00694 * twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the 00695 * card is reset by reading from the reset register. on reset it's in 16-bit i/o mode. 00696 */ 00697 NdisRawReadPortUshort(Adapter->PortOffset + RESET32, &Data); 00698 NdisRawReadPortUshort(Adapter->PortOffset + RESET16, &Data); 00699 00700 /* stop the chip */ 00701 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00702 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP); 00703 00704 /* pause for 1ms so the chip will have time to reset */ 00705 NdisStallExecution(1); 00706 00707 DPRINT("chip stopped\n"); 00708 00709 /* set the software style to 2 (32 bits) */ 00710 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR58); 00711 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00712 00713 Data |= SW_STYLE_2; 00714 00715 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data); 00716 00717 /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */ 00718 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4); 00719 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00720 00721 Data |= CSR4_APAD_XMT | /* CSR4_DPOLL |*/ CSR4_TXSTRTM | CSR4_DMAPLUS; 00722 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data); 00723 00724 /* set up bcr18: burst read/write enable */ 00725 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR18); 00726 NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data); 00727 00728 Data |= BCR18_BREADE | BCR18_BWRITE ; 00729 NdisRawWritePortUshort(Adapter->PortOffset + BDP, Data); 00730 00731 /* set up csr1 and csr2 with init block */ 00732 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR1); 00733 NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys & 0xffff)); 00734 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR2); 00735 NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys >> 16) & 0xffff); 00736 00737 DPRINT("programmed with init block\n"); 00738 00739 /* Set mode to 0 */ 00740 Data = 0; 00741 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR15); 00742 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data); 00743 00744 /* load init block and start the card */ 00745 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00746 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA); 00747 00748 /* Allow LED programming */ 00749 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR2); 00750 NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR2_LEDPE); 00751 00752 /* LED0 is configured for link status (on = up, off = down) */ 00753 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4); 00754 NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR4_LNKSTE | BCR4_PSE); 00755 00756 /* LED1 is configured for link duplex (on = full, off = half) */ 00757 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR5); 00758 NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR5_FDLSE | BCR5_PSE); 00759 00760 /* LED2 is configured for link speed (on = 100M, off = 10M) */ 00761 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR6); 00762 NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR6_E100 | BCR6_PSE); 00763 00764 /* LED3 is configured for trasmit/receive activity */ 00765 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR7); 00766 NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR7_XMTE | BCR7_RCVE | BCR7_PSE); 00767 00768 Adapter->MediaState = MiGetMediaState(Adapter); 00769 Adapter->FullDuplex = MiGetMediaDuplex(Adapter); 00770 Adapter->MediaSpeed = MiGetMediaSpeed(Adapter); 00771 00772 DPRINT("card started\n"); 00773 00774 Adapter->Flags &= ~RESET_IN_PROGRESS; 00775 } 00776 00777 #if DBG 00778 static BOOLEAN 00779 MiTestCard( 00780 PADAPTER Adapter) 00781 /* 00782 * FUNCTION: Test the NIC 00783 * ARGUMENTS: 00784 * Adapter: pointer to the miniport's adapter struct 00785 * RETURNS: 00786 * TRUE if the test succeeds 00787 * FALSE otherwise 00788 * NOTES: 00789 * - this is where to add diagnostics. This is called 00790 * at the very end of initialization. 00791 */ 00792 { 00793 int i = 0; 00794 UCHAR address[6]; 00795 USHORT Data = 0; 00796 00797 /* see if we can read/write now */ 00798 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00799 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00800 DPRINT("Port 0x%x RAP 0x%x CSR0 0x%x RDP 0x%x, Interupt status register is 0x%x\n", Adapter->PortOffset, RAP, CSR0, RDP, Data); 00801 00802 /* read the BIA */ 00803 for(i = 0; i < 6; i++) 00804 NdisRawReadPortUchar(Adapter->PortOffset + i, &address[i]); 00805 00806 DPRINT("burned-in address: %x:%x:%x:%x:%x:%x\n", address[0], address[1], address[2], address[3], address[4], address[5]); 00807 /* Read status flags from CSR0 */ 00808 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00809 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00810 DPRINT("CSR0: 0x%x\n", Data); 00811 00812 /* Read status flags from CSR3 */ 00813 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR3); 00814 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00815 00816 DPRINT("CSR3: 0x%x\n", Data); 00817 /* Read status flags from CSR4 */ 00818 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4); 00819 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00820 DPRINT("CSR4: 0x%x\n", Data); 00821 00822 /* Read status flags from CSR5 */ 00823 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR5); 00824 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00825 DPRINT("CSR5: 0x%x\n", Data); 00826 00827 /* Read status flags from CSR6 */ 00828 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR6); 00829 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 00830 DPRINT("CSR6: 0x%x\n", Data); 00831 00832 return TRUE; 00833 } 00834 #endif 00835 00836 VOID 00837 NTAPI 00838 MiniportShutdown( PVOID Context ) 00839 { 00840 PADAPTER Adapter = Context; 00841 00842 DPRINT("Stopping the chip\n"); 00843 00844 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 00845 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP); 00846 } 00847 00848 static NDIS_STATUS 00849 NTAPI 00850 MiniportInitialize( 00851 OUT PNDIS_STATUS OpenErrorStatus, 00852 OUT PUINT SelectedMediumIndex, 00853 IN PNDIS_MEDIUM MediumArray, 00854 IN UINT MediumArraySize, 00855 IN NDIS_HANDLE MiniportAdapterHandle, 00856 IN NDIS_HANDLE WrapperConfigurationContext) 00857 /* 00858 * FUNCTION: Initialize a new miniport 00859 * ARGUMENTS: 00860 * OpenErrorStatus: pointer to a var to return status info in 00861 * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3) 00862 * MediumArray: array of media that we can pick from 00863 * MediumArraySize: size of MediumArray 00864 * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance 00865 * WrapperConfigurationContext: temporary NDIS-assigned handle for passing 00866 * to configuration APIs 00867 * RETURNS: 00868 * NDIS_STATUS_SUCCESS on success 00869 * NDIS_STATUS_FAILURE on general failure 00870 * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray 00871 * NDIS_STATUS_RESOURCES on insufficient system resources 00872 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter 00873 * NOTES: 00874 * - Called by NDIS at PASSIVE_LEVEL, once per detected card 00875 * - Will int 3 on failure of MiTestCard if DBG=1 00876 */ 00877 { 00878 UINT i = 0; 00879 PADAPTER Adapter = 0; 00880 NDIS_STATUS Status = NDIS_STATUS_FAILURE; 00881 BOOLEAN InterruptRegistered = FALSE, MapRegistersAllocated = FALSE; 00882 NDIS_HANDLE ConfigurationHandle; 00883 UINT *RegNetworkAddress = 0; 00884 UINT RegNetworkAddressLength = 0; 00885 00886 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL); 00887 00888 /* Pick a medium */ 00889 for(i = 0; i < MediumArraySize; i++) 00890 if(MediumArray[i] == NdisMedium802_3) 00891 break; 00892 00893 if(i == MediumArraySize) 00894 { 00895 Status = NDIS_STATUS_UNSUPPORTED_MEDIA; 00896 DPRINT1("unsupported media\n"); 00897 *OpenErrorStatus = Status; 00898 return Status; 00899 } 00900 00901 *SelectedMediumIndex = i; 00902 00903 /* allocate our adapter struct */ 00904 Status = NdisAllocateMemoryWithTag((PVOID *)&Adapter, sizeof(ADAPTER), PCNET_TAG); 00905 if(Status != NDIS_STATUS_SUCCESS) 00906 { 00907 Status = NDIS_STATUS_RESOURCES; 00908 DPRINT1("Insufficient resources\n"); 00909 *OpenErrorStatus = Status; 00910 return Status; 00911 } 00912 00913 RtlZeroMemory(Adapter, sizeof(ADAPTER)); 00914 00915 Adapter->MiniportAdapterHandle = MiniportAdapterHandle; 00916 00917 /* register our adapter structwith ndis */ 00918 NdisMSetAttributesEx(Adapter->MiniportAdapterHandle, Adapter, 0, NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci); 00919 00920 do 00921 { 00922 /* Card-specific detection and setup */ 00923 Status = MiQueryCard(Adapter); 00924 if(Status != NDIS_STATUS_SUCCESS) 00925 { 00926 DPRINT1("MiQueryCard failed\n"); 00927 Status = NDIS_STATUS_ADAPTER_NOT_FOUND; 00928 break; 00929 } 00930 00931 /* register an IO port range */ 00932 Status = NdisMRegisterIoPortRange((PVOID*)&Adapter->PortOffset, Adapter->MiniportAdapterHandle, 00933 (UINT)Adapter->IoBaseAddress, NUMBER_OF_PORTS); 00934 if(Status != NDIS_STATUS_SUCCESS) 00935 { 00936 DPRINT1("NdisMRegisterIoPortRange failed: 0x%x\n", Status); 00937 break; 00938 } 00939 00940 /* Allocate map registers */ 00941 Status = NdisMAllocateMapRegisters(Adapter->MiniportAdapterHandle, 0, 00942 NDIS_DMA_32BITS, 8, BUFFER_SIZE); 00943 if(Status != NDIS_STATUS_SUCCESS) 00944 { 00945 DPRINT1("NdisMAllocateMapRegisters failed: 0x%x\n", Status); 00946 break; 00947 } 00948 00949 MapRegistersAllocated = TRUE; 00950 00951 /* set up the interrupt */ 00952 Status = NdisMRegisterInterrupt(&Adapter->InterruptObject, Adapter->MiniportAdapterHandle, Adapter->InterruptVector, 00953 Adapter->InterruptVector, TRUE, TRUE, NdisInterruptLevelSensitive); 00954 if(Status != NDIS_STATUS_SUCCESS) 00955 { 00956 DPRINT1("NdisMRegisterInterrupt failed: 0x%x\n", Status); 00957 break; 00958 } 00959 00960 InterruptRegistered = TRUE; 00961 00962 /* Allocate and initialize shared data structures */ 00963 Status = MiAllocateSharedMemory(Adapter); 00964 if(Status != NDIS_STATUS_SUCCESS) 00965 { 00966 Status = NDIS_STATUS_RESOURCES; 00967 DPRINT1("MiAllocateSharedMemory failed\n", Status); 00968 break; 00969 } 00970 00971 /* set up the initialization block */ 00972 MiPrepareInitializationBlock(Adapter); 00973 00974 /* see if someone set a network address manually */ 00975 NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext); 00976 if (Status == NDIS_STATUS_SUCCESS) 00977 { 00978 NdisReadNetworkAddress(&Status, (PVOID *)&RegNetworkAddress, &RegNetworkAddressLength, ConfigurationHandle); 00979 if(Status == NDIS_STATUS_SUCCESS && RegNetworkAddressLength == 6) 00980 { 00981 int i; 00982 DPRINT("NdisReadNetworkAddress returned successfully, address %x:%x:%x:%x:%x:%x\n", 00983 RegNetworkAddress[0], RegNetworkAddress[1], RegNetworkAddress[2], RegNetworkAddress[3], 00984 RegNetworkAddress[4], RegNetworkAddress[5]); 00985 00986 for(i = 0; i < 6; i++) 00987 Adapter->InitializationBlockVirt->PADR[i] = RegNetworkAddress[i]; 00988 } 00989 00990 NdisCloseConfiguration(ConfigurationHandle); 00991 } 00992 00993 DPRINT("Interrupt registered successfully\n"); 00994 00995 /* Initialize and start the chip */ 00996 MiInitChip(Adapter); 00997 00998 NdisAllocateSpinLock(&Adapter->Lock); 00999 01000 Status = NDIS_STATUS_SUCCESS; 01001 } 01002 while(0); 01003 01004 if(Status != NDIS_STATUS_SUCCESS && Adapter) 01005 { 01006 DPRINT("Error; freeing stuff\n"); 01007 01008 MiFreeSharedMemory(Adapter); 01009 01010 if(MapRegistersAllocated) 01011 NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); 01012 01013 if(Adapter->PortOffset) 01014 NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, (PVOID)Adapter->PortOffset); 01015 01016 if(InterruptRegistered) 01017 NdisMDeregisterInterrupt(&Adapter->InterruptObject); 01018 01019 NdisFreeMemory(Adapter, 0, 0); 01020 } 01021 01022 if(Status == NDIS_STATUS_SUCCESS) 01023 { 01024 NdisMInitializeTimer(&Adapter->MediaDetectionTimer, 01025 Adapter->MiniportAdapterHandle, 01026 MiniportMediaDetectionTimer, 01027 Adapter); 01028 NdisMSetPeriodicTimer(&Adapter->MediaDetectionTimer, 01029 MEDIA_DETECTION_INTERVAL); 01030 NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle, 01031 Adapter, 01032 MiniportShutdown); 01033 } 01034 01035 #if DBG 01036 if(!MiTestCard(Adapter)) 01037 ASSERT(0); 01038 #endif 01039 01040 DPRINT("returning 0x%x\n", Status); 01041 *OpenErrorStatus = Status; 01042 return Status; 01043 } 01044 01045 static VOID 01046 NTAPI 01047 MiniportISR( 01048 OUT PBOOLEAN InterruptRecognized, 01049 OUT PBOOLEAN QueueMiniportHandleInterrupt, 01050 IN NDIS_HANDLE MiniportAdapterContext) 01051 /* 01052 * FUNCTION: Miniport interrupt service routine 01053 * ARGUMENTS: 01054 * InterruptRecognized: the interrupt was ours 01055 * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt 01056 * MiniportAdapterContext: the context originally passed to NdisMSetAttributes 01057 * NOTES: 01058 * - called by NDIS at DIRQL 01059 * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt 01060 * will be called 01061 */ 01062 { 01063 USHORT Data; 01064 USHORT Rap; 01065 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; 01066 01067 DPRINT("Called\n"); 01068 01069 /* save the old RAP value */ 01070 NdisRawReadPortUshort(Adapter->PortOffset + RAP, &Rap); 01071 01072 /* is this ours? */ 01073 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 01074 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data); 01075 01076 if(!(Data & CSR0_INTR)) 01077 { 01078 DPRINT("not our interrupt.\n"); 01079 *InterruptRecognized = FALSE; 01080 *QueueMiniportHandleInterrupt = FALSE; 01081 } 01082 else 01083 { 01084 DPRINT("detected our interrupt\n"); 01085 01086 /* disable interrupts */ 01087 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 01088 NdisRawWritePortUshort(Adapter->PortOffset + RDP, 0); 01089 01090 *InterruptRecognized = TRUE; 01091 *QueueMiniportHandleInterrupt = TRUE; 01092 } 01093 01094 /* restore the rap */ 01095 NdisRawWritePortUshort(Adapter->PortOffset + RAP, Rap); 01096 } 01097 01098 static NDIS_STATUS 01099 NTAPI 01100 MiniportReset( 01101 OUT PBOOLEAN AddressingReset, 01102 IN NDIS_HANDLE MiniportAdapterContext) 01103 /* 01104 * FUNCTION: Reset the miniport 01105 * ARGUMENTS: 01106 * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation 01107 * to reset our addresses and filters 01108 * MiniportAdapterContext: context originally passed to NdisMSetAttributes 01109 * RETURNS: 01110 * NDIS_STATUS_SUCCESS on all requests 01111 * Notes: 01112 * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset 01113 */ 01114 { 01115 DPRINT("Called\n"); 01116 01117 /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */ 01118 01119 *AddressingReset = FALSE; 01120 return NDIS_STATUS_SUCCESS; 01121 } 01122 01123 static BOOLEAN 01124 NTAPI 01125 MiSyncStartTransmit( 01126 IN PVOID SynchronizeContext) 01127 /* 01128 * FUNCTION: Stop the adapter 01129 * ARGUMENTS: 01130 * SynchronizeContext: Adapter context 01131 */ 01132 { 01133 PADAPTER Adapter = (PADAPTER)SynchronizeContext; 01134 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0); 01135 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA | CSR0_TDMD); 01136 return TRUE; 01137 } 01138 01139 static NDIS_STATUS 01140 NTAPI 01141 MiniportSend( 01142 IN NDIS_HANDLE MiniportAdapterContext, 01143 IN PNDIS_PACKET Packet, 01144 IN UINT Flags) 01145 /* 01146 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out 01147 * ARGUMENTS: 01148 * MiniportAdapterContext: context originally input to NdisMSetAttributes 01149 * Packet: The NDIS_PACKET to be sent 01150 * Flags: Flags associated with Packet 01151 * RETURNS: 01152 * NDIS_STATUS_SUCCESS on processed requests 01153 * NDIS_STATUS_RESOURCES if there's no place in buffer ring 01154 * NOTES: 01155 * - Called by NDIS at DISPATCH_LEVEL 01156 */ 01157 { 01158 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; 01159 PTRANSMIT_DESCRIPTOR Desc; 01160 PNDIS_BUFFER NdisBuffer; 01161 PVOID SourceBuffer; 01162 UINT TotalPacketLength, SourceLength, Position = 0; 01163 01164 DPRINT("Called\n"); 01165 01166 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL); 01167 01168 NdisDprAcquireSpinLock(&Adapter->Lock); 01169 01170 /* Check if we have free entry in our circular buffer. */ 01171 if ((Adapter->CurrentTransmitEndIndex + 1 == 01172 Adapter->CurrentTransmitStartIndex) || 01173 (Adapter->CurrentTransmitEndIndex == Adapter->BufferCount - 1 && 01174 Adapter->CurrentTransmitStartIndex == 0)) 01175 { 01176 DPRINT1("No free space in circular buffer\n"); 01177 NdisDprReleaseSpinLock(&Adapter->Lock); 01178 return NDIS_STATUS_RESOURCES; 01179 } 01180 01181 Desc = Adapter->TransmitDescriptorRingVirt + Adapter->CurrentTransmitEndIndex; 01182 01183 NdisQueryPacket(Packet, NULL, NULL, &NdisBuffer, &TotalPacketLength); 01184 ASSERT(TotalPacketLength <= BUFFER_SIZE); 01185 01186 DPRINT("TotalPacketLength: %x\n", TotalPacketLength); 01187 01188 while (NdisBuffer) 01189 { 01190 NdisQueryBuffer(NdisBuffer, &SourceBuffer, &SourceLength); 01191 01192 DPRINT("Buffer: %x Length: %x\n", SourceBuffer, SourceLength); 01193 01194 RtlCopyMemory(Adapter->TransmitBufferPtrVirt + 01195 Adapter->CurrentTransmitEndIndex * BUFFER_SIZE + Position, 01196 SourceBuffer, SourceLength); 01197 01198 Position += SourceLength; 01199 01200 NdisGetNextBuffer(NdisBuffer, &NdisBuffer); 01201 } 01202 01203 #if DBG && 0 01204 { 01205 PUCHAR Ptr = Adapter->TransmitBufferPtrVirt + 01206 Adapter->CurrentTransmitEndIndex * BUFFER_SIZE; 01207 for (Position = 0; Position < TotalPacketLength; Position++) 01208 { 01209 if (Position % 16 == 0) 01210 DbgPrint("\n"); 01211 DbgPrint("%x ", *Ptr++); 01212 } 01213 } 01214 DbgPrint("\n"); 01215 #endif 01216 01217 Adapter->CurrentTransmitEndIndex++; 01218 Adapter->CurrentTransmitEndIndex %= Adapter->BufferCount; 01219 01220 Desc->FLAGS = TD1_OWN | TD1_STP | TD1_ENP; 01221 Desc->BCNT = 0xf000 | -TotalPacketLength; 01222 01223 NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject, MiSyncStartTransmit, Adapter); 01224 01225 NdisDprReleaseSpinLock(&Adapter->Lock); 01226 01227 return NDIS_STATUS_SUCCESS; 01228 } 01229 01230 static ULONG 01231 NTAPI 01232 MiEthernetCrc(UCHAR *Address) 01233 /* 01234 * FUNCTION: Calculate Ethernet CRC32 01235 * ARGUMENTS: 01236 * Address: 6-byte ethernet address 01237 * RETURNS: 01238 * The calculated CRC32 value. 01239 */ 01240 { 01241 UINT Counter, Length; 01242 ULONG Value = ~0; 01243 01244 for (Length = 0; Length < 6; Length++) 01245 { 01246 Value ^= *Address++; 01247 for (Counter = 0; Counter < 8; Counter++) 01248 { 01249 Value >>= 1; 01250 Value ^= (Value & 1) * 0xedb88320; 01251 } 01252 } 01253 01254 return Value; 01255 } 01256 01257 NDIS_STATUS 01258 NTAPI 01259 MiSetMulticast( 01260 PADAPTER Adapter, 01261 UCHAR *Addresses, 01262 UINT AddressCount) 01263 { 01264 UINT Index; 01265 ULONG CrcIndex; 01266 01267 NdisZeroMemory(Adapter->InitializationBlockVirt->LADR, 8); 01268 for (Index = 0; Index < AddressCount; Index++) 01269 { 01270 CrcIndex = MiEthernetCrc(Addresses) >> 26; 01271 Adapter->InitializationBlockVirt->LADR[CrcIndex >> 3] |= 1 << (CrcIndex & 15); 01272 Addresses += 6; 01273 } 01274 01275 /* FIXME: The specification mentions we need to reload the init block here. */ 01276 01277 return NDIS_STATUS_SUCCESS; 01278 } 01279 01280 BOOLEAN 01281 NTAPI 01282 MiGetMediaDuplex(PADAPTER Adapter) 01283 { 01284 ULONG Data; 01285 01286 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR5); 01287 NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data); 01288 01289 return (Data & BCR5_LEDOUT) != 0; 01290 } 01291 01292 UINT 01293 NTAPI 01294 MiGetMediaSpeed(PADAPTER Adapter) 01295 { 01296 ULONG Data; 01297 01298 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR6); 01299 NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data); 01300 01301 return Data & BCR6_LEDOUT ? 100 : 10; 01302 } 01303 01304 NDIS_MEDIA_STATE 01305 NTAPI 01306 MiGetMediaState(PADAPTER Adapter) 01307 /* 01308 * FUNCTION: Determine the link state 01309 * ARGUMENTS: 01310 * Adapter: Adapter context 01311 * RETURNS: 01312 * NdisMediaStateConnected if the cable is connected 01313 * NdisMediaStateDisconnected if the cable is disconnected 01314 */ 01315 { 01316 ULONG Data; 01317 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4); 01318 NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data); 01319 return Data & BCR4_LEDOUT ? NdisMediaStateConnected : NdisMediaStateDisconnected; 01320 } 01321 01322 NTSTATUS 01323 NTAPI 01324 DriverEntry( 01325 IN PDRIVER_OBJECT DriverObject, 01326 IN PUNICODE_STRING RegistryPath) 01327 /* 01328 * FUNCTION: Start this driver 01329 * ARGUMENTS: 01330 * DriverObject: Pointer to the system-allocated driver object 01331 * RegistryPath: Pointer to our SCM database entry 01332 * RETURNS: 01333 * NDIS_STATUS_SUCCESS on success 01334 * NDIS_STATUS_FAILURE on failure 01335 * NOTES: 01336 * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL 01337 * - TODO: convert this to NTSTATUS return values 01338 */ 01339 { 01340 NDIS_HANDLE WrapperHandle; 01341 NDIS_MINIPORT_CHARACTERISTICS Characteristics; 01342 NDIS_STATUS Status; 01343 01344 RtlZeroMemory(&Characteristics, sizeof(Characteristics)); 01345 Characteristics.MajorNdisVersion = NDIS_MINIPORT_MAJOR_VERSION; 01346 Characteristics.MinorNdisVersion = NDIS_MINIPORT_MINOR_VERSION; 01347 Characteristics.HaltHandler = MiniportHalt; 01348 Characteristics.HandleInterruptHandler = MiniportHandleInterrupt; 01349 Characteristics.InitializeHandler = MiniportInitialize; 01350 Characteristics.ISRHandler = MiniportISR; 01351 Characteristics.QueryInformationHandler = MiniportQueryInformation; 01352 Characteristics.ResetHandler = MiniportReset; 01353 Characteristics.SetInformationHandler = MiniportSetInformation; 01354 Characteristics.SendHandler = MiniportSend; 01355 01356 NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0); 01357 if (!WrapperHandle) return NDIS_STATUS_FAILURE; 01358 01359 Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics)); 01360 if(Status != NDIS_STATUS_SUCCESS) 01361 { 01362 NdisTerminateWrapper(WrapperHandle, 0); 01363 return NDIS_STATUS_FAILURE; 01364 } 01365 01366 return NDIS_STATUS_SUCCESS; 01367 } 01368 Generated on Sun May 27 2012 04:28:04 for ReactOS by
1.7.6.1
|