1. Removed #ifdef SNP_DEBUG and used debug lib to output information
[mirror_edk2.git] / EdkModulePkg / Universal / Network / Snp32_64 / Dxe / snp.c
1 /*++
2 Copyright (c) 2006, Intel Corporation
3 All rights reserved. This program and the accompanying materials
4 are licensed and made available under the terms and conditions of the BSD License
5 which accompanies this distribution. The full text of the license may be found at
6 http://opensource.org/licenses/bsd-license.php
7
8 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
9 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
10
11 Module name:
12 snp.c
13
14 Abstract:
15
16 --*/
17
18
19 #include "Snp.h"
20
21 //
22 // Module global variables needed to support undi 3.0 interface
23 //
24 EFI_PCI_IO_PROTOCOL *mPciIoFncs;
25 struct s_v2p *_v2p = NULL; // undi3.0 map_list head
26 // End Global variables
27 //
28
29 STATIC
30 EFI_STATUS
31 issue_hwundi_command (
32 UINT64 cdb
33 )
34 /*++
35
36 Routine Description:
37
38 Arguments:
39
40 Returns:
41
42 --*/
43 {
44 DEBUG ((EFI_D_ERROR, "\nissue_hwundi_command() - This should not be called!"));
45
46 if (cdb == 0) {
47 return EFI_INVALID_PARAMETER;
48
49 }
50 //
51 // %%TBD - For now, nothing is done.
52 //
53 return EFI_UNSUPPORTED;
54 }
55
56 STATIC
57 UINT8
58 calc_8bit_cksum (
59 VOID *ptr,
60 UINTN len
61 )
62 /*++
63
64 Routine Description:
65 Compute 8-bit checksum of a buffer.
66
67 Arguments:
68 ptr - Pointer to buffer.
69 len - Length of buffer in bytes.
70
71 Returns:
72 8-bit checksum of all bytes in buffer.
73 If ptr is NULL or len is zero, zero is returned.
74
75 --*/
76 {
77 UINT8 *bptr;
78 UINT8 cksum;
79
80 bptr = ptr;
81 cksum = 0;
82
83 if (ptr == NULL || len == 0) {
84 return 0;
85 }
86
87 while (len--) {
88 cksum = (UINT8) (cksum +*bptr++);
89 }
90
91 return cksum;
92 }
93
94 STATIC
95 EFI_STATUS
96 EFIAPI
97 SimpleNetworkDriverSupported (
98 IN EFI_DRIVER_BINDING_PROTOCOL *This,
99 IN EFI_HANDLE Controller,
100 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
101 )
102 /*++
103
104 Routine Description:
105 Test to see if this driver supports Controller. Any Controller
106 that contains a Nii protocol can be supported.
107
108 Arguments:
109 This - Protocol instance pointer.
110 Controller - Handle of device to test.
111 RemainingDevicePath - Not used.
112
113 Returns:
114 EFI_SUCCESS - This driver supports this device.
115 EFI_ALREADY_STARTED - This driver is already running on this device.
116 other - This driver does not support this device.
117
118 --*/
119 {
120 EFI_STATUS Status;
121 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;
122 PXE_UNDI *pxe;
123 BOOLEAN IsUndi31;
124
125 IsUndi31 = FALSE;
126 Status = gBS->OpenProtocol (
127 Controller,
128 &gEfiDevicePathProtocolGuid,
129 NULL,
130 This->DriverBindingHandle,
131 Controller,
132 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
133 );
134 if (EFI_ERROR (Status)) {
135 return Status;
136 }
137
138 Status = gBS->OpenProtocol (
139 Controller,
140 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
141 (VOID **) &NiiProtocol,
142 This->DriverBindingHandle,
143 Controller,
144 EFI_OPEN_PROTOCOL_BY_DRIVER
145 );
146 if (Status == EFI_ALREADY_STARTED)
147 {
148 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %x\n", Controller));
149 return EFI_ALREADY_STARTED;
150 }
151
152 if (!EFI_ERROR (Status))
153 {
154 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %x\n", Controller));
155 IsUndi31 = TRUE;
156 } else {
157 //
158 // try the older 3.0 driver
159 //
160 Status = gBS->OpenProtocol (
161 Controller,
162 &gEfiNetworkInterfaceIdentifierProtocolGuid,
163 (VOID **) &NiiProtocol,
164 This->DriverBindingHandle,
165 Controller,
166 EFI_OPEN_PROTOCOL_BY_DRIVER
167 );
168 if (EFI_ERROR (Status)) {
169 return Status;
170 }
171
172 DEBUG ((EFI_D_INFO, "Support(): UNDI3.0 found on handle %x\n", Controller));
173 }
174 //
175 // check the version, we don't want to connect to the undi16
176 //
177 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {
178 Status = EFI_UNSUPPORTED;
179 goto Done;
180 }
181 //
182 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.
183 //
184 if (NiiProtocol->ID & 0x0F) {
185 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));
186 Status = EFI_UNSUPPORTED;
187 goto Done;
188 }
189
190 pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);
191
192 //
193 // Verify !PXE revisions.
194 //
195 if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) {
196 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));
197 Status = EFI_UNSUPPORTED;
198 goto Done;
199 }
200
201 if (pxe->hw.Rev < PXE_ROMID_REV) {
202 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));
203 Status = EFI_UNSUPPORTED;
204 goto Done;
205 }
206
207 if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {
208
209 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));
210 Status = EFI_UNSUPPORTED;
211 goto Done;
212
213 } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) {
214 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));
215 Status = EFI_UNSUPPORTED;
216 goto Done;
217 }
218 //
219 // Do S/W UNDI specific checks.
220 //
221 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {
222 if (pxe->sw.EntryPoint < pxe->sw.Len) {
223 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));
224 Status = EFI_UNSUPPORTED;
225 goto Done;
226 }
227
228 if (pxe->sw.BusCnt == 0) {
229 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));
230 Status = EFI_UNSUPPORTED;
231 goto Done;
232 }
233 }
234
235 Status = EFI_SUCCESS;
236 DEBUG ((EFI_D_INFO, "Support(): supported on %x\n", Controller));
237
238 Done:
239 if (IsUndi31) {
240 gBS->CloseProtocol (
241 Controller,
242 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
243 This->DriverBindingHandle,
244 Controller
245 );
246
247 } else {
248 gBS->CloseProtocol (
249 Controller,
250 &gEfiNetworkInterfaceIdentifierProtocolGuid,
251 This->DriverBindingHandle,
252 Controller
253 );
254 }
255
256 return Status;
257 }
258
259 STATIC
260 EFI_STATUS
261 EFIAPI
262 SimpleNetworkDriverStart (
263 IN EFI_DRIVER_BINDING_PROTOCOL *This,
264 IN EFI_HANDLE Controller,
265 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
266 )
267 /*++
268
269 Routine Description:
270 called for any handle that we said "supported" in the above call!
271
272 Arguments:
273 This - Protocol instance pointer.
274 Controller - Handle of device to start
275 RemainingDevicePath - Not used.
276
277 Returns:
278 EFI_SUCCESS - This driver supports this device.
279 other - This driver failed to start this device.
280
281 --*/
282 {
283 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;
284 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;
285 EFI_STATUS Status;
286 PXE_UNDI *pxe;
287 SNP_DRIVER *snp;
288 VOID *addr;
289 VOID *addrUnmap;
290 EFI_PHYSICAL_ADDRESS paddr;
291 EFI_HANDLE Handle;
292 UINTN Size;
293 BOOLEAN UndiNew;
294 PXE_PCI_CONFIG_INFO ConfigInfo;
295 PCI_TYPE00 *ConfigHeader;
296 UINT32 *TempBar;
297 UINT8 BarIndex;
298 PXE_STATFLAGS InitStatFlags;
299
300 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));
301
302 Status = gBS->OpenProtocol (
303 Controller,
304 &gEfiDevicePathProtocolGuid,
305 (VOID **) &NiiDevicePath,
306 This->DriverBindingHandle,
307 Controller,
308 EFI_OPEN_PROTOCOL_BY_DRIVER
309 );
310
311 if (EFI_ERROR (Status)) {
312 return Status;
313 }
314
315 Status = gBS->LocateDevicePath (
316 &gEfiPciIoProtocolGuid,
317 &NiiDevicePath,
318 &Handle
319 );
320
321 if (EFI_ERROR (Status)) {
322 return Status;
323 }
324
325 Status = gBS->OpenProtocol (
326 Handle,
327 &gEfiPciIoProtocolGuid,
328 (VOID **) &mPciIoFncs,
329 This->DriverBindingHandle,
330 Controller,
331 EFI_OPEN_PROTOCOL_GET_PROTOCOL
332 );
333 if (EFI_ERROR (Status)) {
334 return Status;
335 }
336 //
337 // Get the NII interface. look for 3.1 undi first, if it is not there
338 // then look for 3.0, validate the interface.
339 //
340 Status = gBS->OpenProtocol (
341 Controller,
342 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
343 (VOID **) &Nii,
344 This->DriverBindingHandle,
345 Controller,
346 EFI_OPEN_PROTOCOL_BY_DRIVER
347 );
348 if (Status == EFI_ALREADY_STARTED) {
349 gBS->CloseProtocol (
350 Controller,
351 &gEfiDevicePathProtocolGuid,
352 This->DriverBindingHandle,
353 Controller
354 );
355 return Status;
356 }
357
358 if (!EFI_ERROR (Status)) {
359 //
360 // probably not a 3.1 UNDI
361 //
362 UndiNew = TRUE;
363 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));
364
365 } else {
366 UndiNew = FALSE;
367 Status = gBS->OpenProtocol (
368 Controller,
369 &gEfiNetworkInterfaceIdentifierProtocolGuid,
370 (VOID **) &Nii,
371 This->DriverBindingHandle,
372 Controller,
373 EFI_OPEN_PROTOCOL_BY_DRIVER
374 );
375 if (EFI_ERROR (Status)) {
376 gBS->CloseProtocol (
377 Controller,
378 &gEfiDevicePathProtocolGuid,
379 This->DriverBindingHandle,
380 Controller
381 );
382
383 return Status;
384 }
385
386 DEBUG ((EFI_D_INFO, "Start(): UNDI3.0 found\n"));
387 }
388
389 pxe = (PXE_UNDI *) (UINTN) (Nii->ID);
390
391 if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) {
392 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));
393 goto NiiError;
394 }
395
396 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
397 //
398 // We can get any packets.
399 //
400 } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
401 //
402 // We need to be able to get broadcast packets for DHCP.
403 // If we do not have promiscuous support, we must at least have
404 // broadcast support or we cannot do DHCP!
405 //
406 } else {
407 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));
408 goto NiiError;
409 }
410 //
411 // OK, we like this UNDI, and we know snp is not already there on this handle
412 // Allocate and initialize a new simple network protocol structure.
413 //
414 Status = mPciIoFncs->AllocateBuffer (
415 mPciIoFncs,
416 AllocateAnyPages,
417 EfiBootServicesData,
418 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
419 &addr,
420 0
421 );
422
423 if (Status != EFI_SUCCESS) {
424 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));
425 goto NiiError;
426 }
427
428 snp = (SNP_DRIVER *) (UINTN) addr;
429
430 if (!UndiNew) {
431 Size = SNP_MEM_PAGES (sizeof (SNP_DRIVER));
432
433 Status = mPciIoFncs->Map (
434 mPciIoFncs,
435 EfiPciIoOperationBusMasterCommonBuffer,
436 addr,
437 &Size,
438 &paddr,
439 &addrUnmap
440 );
441
442 ASSERT (paddr);
443
444 DEBUG ((EFI_D_NET, "\nSNP_DRIVER @ %Xh, sizeof(SNP_DRIVER) == %d", addr, sizeof (SNP_DRIVER)));
445 snp = (SNP_DRIVER *) (UINTN) paddr;
446 snp->SnpDriverUnmap = addrUnmap;
447 }
448
449 ZeroMem (snp, sizeof (SNP_DRIVER));
450
451 snp->IoFncs = mPciIoFncs;
452 snp->IsOldUndi = (BOOLEAN) (!UndiNew);
453
454 snp->Signature = SNP_DRIVER_SIGNATURE;
455
456 EfiInitializeLock (&snp->lock, EFI_TPL_NOTIFY);
457
458 snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;
459 snp->snp.Start = snp_undi32_start;
460 snp->snp.Stop = snp_undi32_stop;
461 snp->snp.Initialize = snp_undi32_initialize;
462 snp->snp.Reset = snp_undi32_reset;
463 snp->snp.Shutdown = snp_undi32_shutdown;
464 snp->snp.ReceiveFilters = snp_undi32_receive_filters;
465 snp->snp.StationAddress = snp_undi32_station_address;
466 snp->snp.Statistics = snp_undi32_statistics;
467 snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac;
468 snp->snp.NvData = snp_undi32_nvdata;
469 snp->snp.GetStatus = snp_undi32_get_status;
470 snp->snp.Transmit = snp_undi32_transmit;
471 snp->snp.Receive = snp_undi32_receive;
472 snp->snp.WaitForPacket = NULL;
473
474 snp->snp.Mode = &snp->mode;
475
476 snp->tx_rx_bufsize = 0;
477 snp->tx_rx_buffer = NULL;
478
479 snp->if_num = Nii->IfNum;
480
481 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {
482 snp->is_swundi = FALSE;
483 snp->issue_undi32_command = &issue_hwundi_command;
484 } else {
485 snp->is_swundi = TRUE;
486
487 if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {
488 snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint;
489 } else {
490 snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint);
491 }
492 }
493 //
494 // Allocate a global CPB and DB buffer for this UNDI interface.
495 // we do this because:
496 //
497 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be
498 // within 2GB limit, create them here and map them so that when undi calls
499 // v2p callback to check if the physical address is < 2gb, we will pass.
500 //
501 // -This is not a requirement for 3.1 or later UNDIs but the code looks
502 // simpler if we use the same cpb, db variables for both old and new undi
503 // interfaces from all the SNP interface calls (we don't map the buffers
504 // for the newer undi interfaces though)
505 // .
506 // -it is OK to allocate one global set of CPB, DB pair for each UNDI
507 // interface as EFI does not multi-task and so SNP will not be re-entered!
508 //
509 Status = mPciIoFncs->AllocateBuffer (
510 mPciIoFncs,
511 AllocateAnyPages,
512 EfiBootServicesData,
513 SNP_MEM_PAGES (4096),
514 &addr,
515 0
516 );
517
518 if (Status != EFI_SUCCESS) {
519 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));
520 goto Error_DeleteSNP;
521 }
522
523 if (snp->IsOldUndi) {
524 Size = SNP_MEM_PAGES (4096);
525
526 Status = mPciIoFncs->Map (
527 mPciIoFncs,
528 EfiPciIoOperationBusMasterCommonBuffer,
529 addr,
530 &Size,
531 &paddr,
532 &snp->CpbUnmap
533 );
534
535 ASSERT (paddr);
536
537 snp->cpb = (VOID *) (UINTN) paddr;
538 snp->db = (VOID *) ((UINTN) paddr + 2048);
539 } else {
540 snp->cpb = (VOID *) (UINTN) addr;
541 snp->db = (VOID *) ((UINTN) addr + 2048);
542 }
543 //
544 // pxe_start call is going to give the callback functions to UNDI, these callback
545 // functions use the BarIndex values from the snp structure, so these must be initialized
546 // with default values before doing a pxe_start. The correct values can be obtained after
547 // getting the config information from UNDI
548 //
549 snp->MemoryBarIndex = 0;
550 snp->IoBarIndex = 1;
551
552 //
553 // we need the undi init information many times in this snp code, just get it
554 // once here and store it in the snp driver structure. to get Init Info
555 // from UNDI we have to start undi first.
556 //
557 Status = pxe_start (snp);
558
559 if (Status != EFI_SUCCESS) {
560 goto Error_DeleteCPBDB;
561 }
562
563 snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;
564 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
565
566 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
567 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
568
569 snp->cdb.DBsize = sizeof snp->init_info;
570 snp->cdb.DBaddr = (UINT64) (UINTN) &snp->init_info;
571
572 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
573 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
574
575 snp->cdb.IFnum = snp->if_num;
576 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
577
578 DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() "));
579
580 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
581
582 //
583 // Save the INIT Stat Code...
584 //
585 InitStatFlags = snp->cdb.StatFlags;
586
587 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
588 DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
589 pxe_stop (snp);
590 goto Error_DeleteCPBDB;
591 }
592
593 snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;
594 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;
595
596 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;
597 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;
598
599 snp->cdb.DBsize = sizeof ConfigInfo;
600 snp->cdb.DBaddr = (UINT64) (UINTN) &ConfigInfo;
601
602 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;
603 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;
604
605 snp->cdb.IFnum = snp->if_num;
606 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;
607
608 DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() "));
609
610 (*snp->issue_undi32_command) ((UINT64) (UINTN) &snp->cdb);
611
612 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {
613 DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));
614 pxe_stop (snp);
615 goto Error_DeleteCPBDB;
616 }
617 //
618 // Find the correct BAR to do IO.
619 //
620 //
621 // Enumerate through the PCI BARs for the device to determine which one is
622 // the IO BAR. Save the index of the BAR into the adapter info structure.
623 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped
624 //
625 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];
626 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];
627 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {
628 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {
629 //
630 // This is a 64-bit memory bar, skip this and the
631 // next bar as well.
632 //
633 TempBar++;
634 }
635
636 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {
637 snp->IoBarIndex = BarIndex;
638 break;
639 }
640
641 TempBar++;
642 }
643
644 //
645 // We allocate 2 more global buffers for undi 3.0 interface. We use these
646 // buffers to pass to undi when the user buffers are beyond 4GB.
647 // UNDI 3.0 wants all the addresses passed to it to be
648 // within 2GB limit, create them here and map them so that when undi calls
649 // v2p callback to check if the physical address is < 2gb, we will pass.
650 //
651 // For 3.1 and later UNDIs, we do not do this because undi is
652 // going to call the map() callback if and only if it wants to use the
653 // device address for any address it receives.
654 //
655 if (snp->IsOldUndi) {
656 //
657 // buffer for receive
658 //
659 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
660 Status = mPciIoFncs->AllocateBuffer (
661 mPciIoFncs,
662 AllocateAnyPages,
663 EfiBootServicesData,
664 Size,
665 &addr,
666 0
667 );
668
669 if (Status != EFI_SUCCESS) {
670 DEBUG ((EFI_D_ERROR, "\nCould not allocate receive buffer.\n"));
671 goto Error_DeleteCPBDB;
672 }
673
674 Status = mPciIoFncs->Map (
675 mPciIoFncs,
676 EfiPciIoOperationBusMasterCommonBuffer,
677 addr,
678 &Size,
679 &paddr,
680 &snp->ReceiveBufUnmap
681 );
682
683 ASSERT (paddr);
684
685 snp->receive_buf = (UINT8 *) (UINTN) paddr;
686
687 //
688 // buffer for fill_header
689 //
690 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen);
691 Status = mPciIoFncs->AllocateBuffer (
692 mPciIoFncs,
693 AllocateAnyPages,
694 EfiBootServicesData,
695 Size,
696 &addr,
697 0
698 );
699
700 if (Status != EFI_SUCCESS) {
701 DEBUG ((EFI_D_ERROR, "\nCould not allocate fill_header buffer.\n"));
702 goto Error_DeleteRCVBuf;
703 }
704
705 Status = mPciIoFncs->Map (
706 mPciIoFncs,
707 EfiPciIoOperationBusMasterCommonBuffer,
708 addr,
709 &Size,
710 &paddr,
711 &snp->FillHdrBufUnmap
712 );
713
714 ASSERT (paddr);
715 snp->fill_hdr_buf = (UINT8 *) (UINTN) paddr;
716 }
717 //
718 // Initialize simple network protocol mode structure
719 //
720 snp->mode.State = EfiSimpleNetworkStopped;
721 snp->mode.HwAddressSize = snp->init_info.HWaddrLen;
722 snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen;
723 snp->mode.MaxPacketSize = snp->init_info.FrameDataLen;
724 snp->mode.NvRamAccessSize = snp->init_info.NvWidth;
725 snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize;
726 snp->mode.IfType = snp->init_info.IFtype;
727 snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt;
728 snp->mode.MCastFilterCount = 0;
729
730 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {
731 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:
732 snp->mode.MediaPresentSupported = TRUE;
733 break;
734
735 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:
736 default:
737 snp->mode.MediaPresentSupported = FALSE;
738 }
739
740 if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {
741 snp->mode.MacAddressChangeable = TRUE;
742 } else {
743 snp->mode.MacAddressChangeable = FALSE;
744 }
745
746 if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {
747 snp->mode.MultipleTxSupported = TRUE;
748 } else {
749 snp->mode.MultipleTxSupported = FALSE;
750 }
751
752 snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;
753
754 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {
755 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
756
757 }
758
759 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {
760 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;
761
762 }
763
764 if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {
765 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;
766
767 }
768
769 if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {
770 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;
771
772 }
773
774 if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {
775 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;
776
777 }
778
779 snp->mode.ReceiveFilterSetting = 0;
780
781 //
782 // need to get the station address to save in the mode structure. we need to
783 // initialize the UNDI first for this.
784 //
785 snp->tx_rx_bufsize = snp->init_info.MemoryRequired;
786 Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);
787
788 if (Status) {
789 pxe_stop (snp);
790 goto Error_DeleteHdrBuf;
791 }
792
793 Status = pxe_get_stn_addr (snp);
794
795 if (Status != EFI_SUCCESS) {
796 DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n"));
797 pxe_shutdown (snp);
798 pxe_stop (snp);
799 goto Error_DeleteHdrBuf;
800 }
801
802 snp->mode.MediaPresent = FALSE;
803
804 //
805 // We should not leave UNDI started and initialized here. this DriverStart()
806 // routine must only find and attach the SNP interface to UNDI layer that it
807 // finds on the given handle!
808 // The UNDI layer will be started when upper layers call snp->start.
809 // How ever, this DriverStart() must fill up the snp mode structure which
810 // contains the MAC address of the NIC. For this reason we started and
811 // initialized UNDI here, now we are done, do a shutdown and stop of the
812 // UNDI interface!
813 //
814 pxe_shutdown (snp);
815 pxe_stop (snp);
816
817 //
818 // add SNP to the undi handle
819 //
820 Status = gBS->InstallProtocolInterface (
821 &Controller,
822 &gEfiSimpleNetworkProtocolGuid,
823 EFI_NATIVE_INTERFACE,
824 &(snp->snp)
825 );
826
827 if (!EFI_ERROR (Status)) {
828 return Status;
829 }
830
831 Error_DeleteHdrBuf:
832 if (snp->IsOldUndi) {
833 Status = mPciIoFncs->Unmap (
834 mPciIoFncs,
835 snp->FillHdrBufUnmap
836 );
837 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen);
838 mPciIoFncs->FreeBuffer (
839 mPciIoFncs,
840 Size,
841 snp->fill_hdr_buf
842 );
843 }
844
845 Error_DeleteRCVBuf:
846 if (snp->IsOldUndi) {
847 Status = mPciIoFncs->Unmap (
848 mPciIoFncs,
849 snp->ReceiveBufUnmap
850 );
851 Size = SNP_MEM_PAGES (snp->init_info.MediaHeaderLen + snp->init_info.FrameDataLen);
852 mPciIoFncs->FreeBuffer (
853 mPciIoFncs,
854 Size,
855 snp->receive_buf
856 );
857
858 }
859
860 Error_DeleteCPBDB:
861 if (snp->IsOldUndi) {
862 Status = mPciIoFncs->Unmap (
863 mPciIoFncs,
864 snp->CpbUnmap
865 );
866 }
867
868 Status = mPciIoFncs->FreeBuffer (
869 mPciIoFncs,
870 SNP_MEM_PAGES (4096),
871 snp->cpb
872 );
873
874 Error_DeleteSNP:
875 if (snp->IsOldUndi) {
876 Status = mPciIoFncs->Unmap (
877 mPciIoFncs,
878 snp->SnpDriverUnmap
879 );
880 }
881
882 mPciIoFncs->FreeBuffer (
883 mPciIoFncs,
884 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
885 snp
886 );
887 NiiError:
888 if (!UndiNew) {
889 gBS->CloseProtocol (
890 Controller,
891 &gEfiNetworkInterfaceIdentifierProtocolGuid,
892 This->DriverBindingHandle,
893 Controller
894 );
895 } else {
896 gBS->CloseProtocol (
897 Controller,
898 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
899 This->DriverBindingHandle,
900 Controller
901 );
902 }
903
904 gBS->CloseProtocol (
905 Controller,
906 &gEfiDevicePathProtocolGuid,
907 This->DriverBindingHandle,
908 Controller
909 );
910
911 return Status;
912 }
913
914 STATIC
915 EFI_STATUS
916 EFIAPI
917 SimpleNetworkDriverStop (
918 IN EFI_DRIVER_BINDING_PROTOCOL *This,
919 IN EFI_HANDLE Controller,
920 IN UINTN NumberOfChildren,
921 IN EFI_HANDLE *ChildHandleBuffer
922 )
923 /*++
924
925 Routine Description:
926
927 Arguments:
928
929 Returns:
930
931 --*/
932 {
933 EFI_STATUS Status;
934 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;
935 SNP_DRIVER *Snp;
936
937 //
938 // Get our context back.
939 //
940 Status = gBS->OpenProtocol (
941 Controller,
942 &gEfiSimpleNetworkProtocolGuid,
943 (VOID **) &SnpProtocol,
944 This->DriverBindingHandle,
945 Controller,
946 EFI_OPEN_PROTOCOL_GET_PROTOCOL
947 );
948
949 if (EFI_ERROR (Status)) {
950 return EFI_UNSUPPORTED;
951 }
952
953 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);
954
955 Status = gBS->UninstallProtocolInterface (
956 Controller,
957 &gEfiSimpleNetworkProtocolGuid,
958 &Snp->snp
959 );
960
961 if (EFI_ERROR (Status)) {
962 return Status;
963 }
964
965 if (!Snp->IsOldUndi) {
966 Status = gBS->CloseProtocol (
967 Controller,
968 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,
969 This->DriverBindingHandle,
970 Controller
971 );
972 } else {
973 Status = gBS->CloseProtocol (
974 Controller,
975 &gEfiNetworkInterfaceIdentifierProtocolGuid,
976 This->DriverBindingHandle,
977 Controller
978 );
979 }
980
981 Status = gBS->CloseProtocol (
982 Controller,
983 &gEfiDevicePathProtocolGuid,
984 This->DriverBindingHandle,
985 Controller
986 );
987
988 pxe_shutdown (Snp);
989 pxe_stop (Snp);
990
991 if (Snp->IsOldUndi) {
992 Status = mPciIoFncs->Unmap (
993 mPciIoFncs,
994 Snp->FillHdrBufUnmap
995 );
996
997 mPciIoFncs->FreeBuffer (
998 mPciIoFncs,
999 SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen),
1000 Snp->fill_hdr_buf
1001 );
1002 Status = mPciIoFncs->Unmap (
1003 mPciIoFncs,
1004 Snp->ReceiveBufUnmap
1005 );
1006
1007 mPciIoFncs->FreeBuffer (
1008 mPciIoFncs,
1009 SNP_MEM_PAGES (Snp->init_info.MediaHeaderLen + Snp->init_info.FrameDataLen),
1010 Snp->receive_buf
1011 );
1012
1013 Status = mPciIoFncs->Unmap (
1014 mPciIoFncs,
1015 Snp->CpbUnmap
1016 );
1017 Status = mPciIoFncs->Unmap (
1018 mPciIoFncs,
1019 Snp->SnpDriverUnmap
1020 );
1021 }
1022
1023 mPciIoFncs->FreeBuffer (
1024 mPciIoFncs,
1025 SNP_MEM_PAGES (4096),
1026 Snp->cpb
1027 );
1028
1029 mPciIoFncs->FreeBuffer (
1030 mPciIoFncs,
1031 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),
1032 Snp
1033 );
1034
1035 return Status;
1036 }
1037
1038 //
1039 // Simple Network Protocol Driver Global Variables
1040 //
1041 EFI_DRIVER_BINDING_PROTOCOL mSimpleNetworkDriverBinding = {
1042 SimpleNetworkDriverSupported,
1043 SimpleNetworkDriverStart,
1044 SimpleNetworkDriverStop,
1045 0xa,
1046 NULL,
1047 NULL
1048 };
1049
1050 EFI_STATUS
1051 add_v2p (
1052 IN OUT struct s_v2p **v2p,
1053 EFI_PCI_IO_PROTOCOL_OPERATION type,
1054 VOID *vaddr,
1055 UINTN bsize
1056 )
1057 /*++
1058
1059 Routine Description:
1060 This routine maps the given CPU address to a Device address. It creates a
1061 an entry in the map list with the virtual and physical addresses and the
1062 un map cookie.
1063
1064 Arguments:
1065 v2p - pointer to return a map list node pointer.
1066 type - the direction in which the data flows from the given virtual address
1067 device->cpu or cpu->device or both ways.
1068 vaddr - virtual address (or CPU address) to be mapped
1069 bsize - size of the buffer to be mapped.
1070
1071 Returns:
1072
1073 EFI_SUCEESS - routine has completed the mapping
1074 other - error as indicated.
1075
1076 --*/
1077 {
1078 EFI_STATUS Status;
1079
1080 if ((v2p == NULL) || (vaddr == NULL) || (bsize == 0)) {
1081 return EFI_INVALID_PARAMETER;
1082 }
1083
1084 Status = gBS->AllocatePool (
1085 EfiBootServicesData,
1086 sizeof (struct s_v2p),
1087 (VOID **) v2p
1088 );
1089
1090 if (Status != EFI_SUCCESS) {
1091 return Status;
1092 }
1093
1094 Status = mPciIoFncs->Map (
1095 mPciIoFncs,
1096 type,
1097 vaddr,
1098 &bsize,
1099 &(*v2p)->paddr,
1100 &(*v2p)->unmap
1101 );
1102 if (Status != EFI_SUCCESS) {
1103 gBS->FreePool (*v2p);
1104 return Status;
1105 }
1106 (*v2p)->vaddr = vaddr;
1107 (*v2p)->bsize = bsize;
1108 (*v2p)->next = _v2p;
1109 _v2p = *v2p;
1110
1111 return EFI_SUCCESS;
1112 }
1113
1114 EFI_STATUS
1115 find_v2p (
1116 struct s_v2p **v2p,
1117 VOID *vaddr
1118 )
1119 /*++
1120
1121 Routine Description:
1122 This routine searches the linked list of mapped address nodes (for undi3.0
1123 interface) to find the node that corresponds to the given virtual address and
1124 returns a pointer to that node.
1125
1126 Arguments:
1127 v2p - pointer to return a map list node pointer.
1128 vaddr - virtual address (or CPU address) to be searched in the map list
1129
1130 Returns:
1131
1132 EFI_SUCEESS - if a match found!
1133 Other - match not found
1134
1135 --*/
1136 {
1137 struct s_v2p *v;
1138
1139 if (v2p == NULL || vaddr == NULL) {
1140 return EFI_INVALID_PARAMETER;
1141 }
1142
1143 for (v = _v2p; v != NULL; v = v->next) {
1144 if (v->vaddr == vaddr) {
1145 *v2p = v;
1146 return EFI_SUCCESS;
1147 }
1148 }
1149
1150 return EFI_NOT_FOUND;
1151 }
1152
1153 EFI_STATUS
1154 del_v2p (
1155 VOID *vaddr
1156 )
1157 /*++
1158
1159 Routine Description:
1160 This routine unmaps the given virtual address and frees the memory allocated
1161 for the map list node corresponding to that address.
1162
1163 Arguments:
1164 vaddr - virtual address (or CPU address) to be unmapped
1165
1166 Returns:
1167 EFI_SUCEESS - if successfully unmapped
1168 Other - as indicated by the error
1169
1170
1171 --*/
1172 {
1173 struct s_v2p *v;
1174 struct s_v2p *t;
1175 EFI_STATUS Status;
1176
1177 if (vaddr == NULL) {
1178 return EFI_INVALID_PARAMETER;
1179 }
1180
1181 if (_v2p == NULL) {
1182 return EFI_NOT_FOUND;
1183 }
1184 //
1185 // Is our node at the head of the list??
1186 //
1187 if ((v = _v2p)->vaddr == vaddr) {
1188 _v2p = _v2p->next;
1189
1190 Status = mPciIoFncs->Unmap (mPciIoFncs, v->unmap);
1191
1192 gBS->FreePool (v);
1193
1194 if (Status) {
1195 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %x\n", Status));
1196 }
1197 return Status;
1198 }
1199
1200 for (; v->next != NULL; v = t) {
1201 if ((t = v->next)->vaddr == vaddr) {
1202 v->next = t->next;
1203 Status = mPciIoFncs->Unmap (mPciIoFncs, t->unmap);
1204 gBS->FreePool (t);
1205
1206 if (Status) {
1207 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %x\n", Status));
1208 }
1209 return Status;
1210 }
1211 }
1212
1213 return EFI_NOT_FOUND;
1214 }