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