]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/SnpDxe/Snp.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[mirror_edk2.git] / MdeModulePkg / Universal / Network / SnpDxe / Snp.c
CommitLineData
a15a4195 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
0e549d5b 224 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
a15a4195 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
0e549d5b 236 DEBUG ((EFI_D_ERROR, "Unmap failed with status = %r\n", Status));\r
a15a4195 237 }\r
238 return Status;\r
239 }\r
240 }\r
241\r
242 return EFI_NOT_FOUND;\r
243}\r
244\r
a15a4195 245EFI_STATUS\r
246issue_hwundi_command (\r
247 UINT64 cdb\r
248 )\r
249/*++\r
250\r
251Routine Description:\r
252\r
253Arguments:\r
254\r
255Returns:\r
256\r
257--*/\r
258{\r
259 DEBUG ((EFI_D_ERROR, "\nissue_hwundi_command() - This should not be called!"));\r
260\r
261 if (cdb == 0) {\r
262 return EFI_INVALID_PARAMETER;\r
263\r
264 }\r
265 //\r
266 // %%TBD - For now, nothing is done.\r
267 //\r
268 return EFI_UNSUPPORTED;\r
269}\r
270\r
271\r
272/**\r
273 Compute 8-bit checksum of a buffer.\r
274\r
275 @param ptr Pointer to buffer.\r
276 @param len Length of buffer in bytes.\r
277\r
278 @return 8-bit checksum of all bytes in buffer.\r
279 @return If ptr is NULL or len is zero, zero is returned.\r
280\r
281**/\r
a15a4195 282UINT8\r
283calc_8bit_cksum (\r
284 VOID *ptr,\r
285 UINTN len\r
286 )\r
287{\r
288 UINT8 *bptr;\r
289 UINT8 cksum;\r
290\r
291 bptr = ptr;\r
292 cksum = 0;\r
293\r
294 if (ptr == NULL || len == 0) {\r
295 return 0;\r
296 }\r
297\r
298 while (len--) {\r
299 cksum = (UINT8) (cksum +*bptr++);\r
300 }\r
301\r
302 return cksum;\r
303}\r
304\r
305\r
306/**\r
307 Test to see if this driver supports Controller. Any Controller\r
308 that contains a Nii protocol can be supported.\r
309\r
310 @param This Protocol instance pointer.\r
311 @param Controller Handle of device to test.\r
312 @param RemainingDevicePath Not used.\r
313\r
314 @retval EFI_SUCCESS This driver supports this device.\r
315 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
316 @retval other This driver does not support this device.\r
317\r
318**/\r
319EFI_STATUS\r
320EFIAPI\r
321SimpleNetworkDriverSupported (\r
322 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
323 IN EFI_HANDLE Controller,\r
324 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
325 )\r
326{\r
327 EFI_STATUS Status;\r
328 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *NiiProtocol;\r
329 PXE_UNDI *pxe;\r
330\r
331 Status = gBS->OpenProtocol (\r
332 Controller,\r
333 &gEfiDevicePathProtocolGuid,\r
334 NULL,\r
335 This->DriverBindingHandle,\r
336 Controller,\r
337 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
338 );\r
339 if (EFI_ERROR (Status)) {\r
340 return Status;\r
341 }\r
342\r
343 Status = gBS->OpenProtocol (\r
344 Controller,\r
345 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
346 (VOID **) &NiiProtocol,\r
347 This->DriverBindingHandle,\r
348 Controller,\r
349 EFI_OPEN_PROTOCOL_BY_DRIVER\r
350 );\r
351\r
352 if (EFI_ERROR (Status)) {\r
353 if (Status == EFI_ALREADY_STARTED) {\r
0e549d5b 354 DEBUG ((EFI_D_INFO, "Support(): Already Started. on handle %p\n", Controller));\r
a15a4195 355 }\r
356 return Status;\r
357 }\r
358\r
0e549d5b 359 DEBUG ((EFI_D_INFO, "Support(): UNDI3.1 found on handle %p\n", Controller));\r
a15a4195 360\r
361 //\r
362 // check the version, we don't want to connect to the undi16\r
363 //\r
364 if (NiiProtocol->Type != EfiNetworkInterfaceUndi) {\r
365 Status = EFI_UNSUPPORTED;\r
366 goto Done;\r
367 }\r
368 //\r
369 // Check to see if !PXE structure is valid. Paragraph alignment of !PXE structure is required.\r
370 //\r
371 if (NiiProtocol->ID & 0x0F) {\r
372 DEBUG ((EFI_D_NET, "\n!PXE structure is not paragraph aligned.\n"));\r
373 Status = EFI_UNSUPPORTED;\r
374 goto Done;\r
375 }\r
376\r
377 pxe = (PXE_UNDI *) (UINTN) (NiiProtocol->ID);\r
378\r
379 //\r
380 // Verify !PXE revisions.\r
381 //\r
382 if (pxe->hw.Signature != PXE_ROMID_SIGNATURE) {\r
383 DEBUG ((EFI_D_NET, "\n!PXE signature is not valid.\n"));\r
384 Status = EFI_UNSUPPORTED;\r
385 goto Done;\r
386 }\r
387\r
388 if (pxe->hw.Rev < PXE_ROMID_REV) {\r
389 DEBUG ((EFI_D_NET, "\n!PXE.Rev is not supported.\n"));\r
390 Status = EFI_UNSUPPORTED;\r
391 goto Done;\r
392 }\r
393\r
394 if (pxe->hw.MajorVer < PXE_ROMID_MAJORVER) {\r
395\r
396 DEBUG ((EFI_D_NET, "\n!PXE.MajorVer is not supported.\n"));\r
397 Status = EFI_UNSUPPORTED;\r
398 goto Done;\r
399\r
400 } else if (pxe->hw.MajorVer == PXE_ROMID_MAJORVER && pxe->hw.MinorVer < PXE_ROMID_MINORVER) {\r
401 DEBUG ((EFI_D_NET, "\n!PXE.MinorVer is not supported."));\r
402 Status = EFI_UNSUPPORTED;\r
403 goto Done;\r
404 }\r
405 //\r
406 // Do S/W UNDI specific checks.\r
407 //\r
408 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) == 0) {\r
409 if (pxe->sw.EntryPoint < pxe->sw.Len) {\r
410 DEBUG ((EFI_D_NET, "\n!PXE S/W entry point is not valid."));\r
411 Status = EFI_UNSUPPORTED;\r
412 goto Done;\r
413 }\r
414\r
415 if (pxe->sw.BusCnt == 0) {\r
416 DEBUG ((EFI_D_NET, "\n!PXE.BusCnt is zero."));\r
417 Status = EFI_UNSUPPORTED;\r
418 goto Done;\r
419 }\r
420 }\r
421\r
422 Status = EFI_SUCCESS;\r
0e549d5b 423 DEBUG ((EFI_D_INFO, "Support(): supported on %p\n", Controller));\r
a15a4195 424\r
425Done:\r
426 gBS->CloseProtocol (\r
427 Controller,\r
428 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
429 This->DriverBindingHandle,\r
430 Controller\r
431 );\r
432\r
433 return Status;\r
434}\r
435\r
436\r
437/**\r
438 called for any handle that we said "supported" in the above call!\r
439\r
440 @param This Protocol instance pointer.\r
441 @param Controller Handle of device to start\r
442 @param RemainingDevicePath Not used.\r
443\r
444 @retval EFI_SUCCESS This driver supports this device.\r
445 @retval other This driver failed to start this device.\r
446\r
447**/\r
448EFI_STATUS\r
449EFIAPI\r
450SimpleNetworkDriverStart (\r
451 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
452 IN EFI_HANDLE Controller,\r
453 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
454 )\r
455{\r
456 EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii;\r
457 EFI_DEVICE_PATH_PROTOCOL *NiiDevicePath;\r
458 EFI_STATUS Status;\r
459 PXE_UNDI *pxe;\r
460 SNP_DRIVER *snp;\r
461 VOID *addr;\r
462 EFI_HANDLE Handle;\r
463 PXE_PCI_CONFIG_INFO ConfigInfo;\r
464 PCI_TYPE00 *ConfigHeader;\r
465 UINT32 *TempBar;\r
466 UINT8 BarIndex;\r
467 PXE_STATFLAGS InitStatFlags;\r
468\r
469 DEBUG ((EFI_D_NET, "\nSnpNotifyNetworkInterfaceIdentifier() "));\r
470\r
471 Status = gBS->OpenProtocol (\r
472 Controller,\r
473 &gEfiDevicePathProtocolGuid,\r
474 (VOID **) &NiiDevicePath,\r
475 This->DriverBindingHandle,\r
476 Controller,\r
477 EFI_OPEN_PROTOCOL_BY_DRIVER\r
478 );\r
479\r
480 if (EFI_ERROR (Status)) {\r
481 return Status;\r
482 }\r
483\r
484 Status = gBS->LocateDevicePath (\r
485 &gEfiPciIoProtocolGuid,\r
486 &NiiDevicePath,\r
487 &Handle\r
488 );\r
489\r
490 if (EFI_ERROR (Status)) {\r
491 return Status;\r
492 }\r
493\r
494 Status = gBS->OpenProtocol (\r
495 Handle,\r
496 &gEfiPciIoProtocolGuid,\r
497 (VOID **) &mPciIoFncs,\r
498 This->DriverBindingHandle,\r
499 Controller,\r
500 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
501 );\r
502 if (EFI_ERROR (Status)) {\r
503 return Status;\r
504 }\r
505 //\r
506 // Get the NII interface.\r
507 //\r
508 Status = gBS->OpenProtocol (\r
509 Controller,\r
510 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
511 (VOID **) &Nii,\r
512 This->DriverBindingHandle,\r
513 Controller,\r
514 EFI_OPEN_PROTOCOL_BY_DRIVER\r
515 );\r
516 if (EFI_ERROR (Status)) {\r
517 gBS->CloseProtocol (\r
518 Controller,\r
519 &gEfiDevicePathProtocolGuid,\r
520 This->DriverBindingHandle,\r
521 Controller\r
522 );\r
523 return Status;\r
524 }\r
525\r
526 DEBUG ((EFI_D_INFO, "Start(): UNDI3.1 found\n"));\r
527\r
528 pxe = (PXE_UNDI *) (UINTN) (Nii->ID);\r
529\r
530 if (calc_8bit_cksum (pxe, pxe->hw.Len) != 0) {\r
531 DEBUG ((EFI_D_NET, "\n!PXE checksum is not correct.\n"));\r
532 goto NiiError;\r
533 }\r
534\r
535 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
536 //\r
537 // We can get any packets.\r
538 //\r
539 } else if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
540 //\r
541 // We need to be able to get broadcast packets for DHCP.\r
542 // If we do not have promiscuous support, we must at least have\r
543 // broadcast support or we cannot do DHCP!\r
544 //\r
545 } else {\r
546 DEBUG ((EFI_D_NET, "\nUNDI does not have promiscuous or broadcast support."));\r
547 goto NiiError;\r
548 }\r
549 //\r
550 // OK, we like this UNDI, and we know snp is not already there on this handle\r
551 // Allocate and initialize a new simple network protocol structure.\r
552 //\r
553 Status = mPciIoFncs->AllocateBuffer (\r
554 mPciIoFncs,\r
555 AllocateAnyPages,\r
556 EfiBootServicesData,\r
557 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
558 &addr,\r
559 0\r
560 );\r
561\r
562 if (Status != EFI_SUCCESS) {\r
563 DEBUG ((EFI_D_NET, "\nCould not allocate SNP_DRIVER structure.\n"));\r
564 goto NiiError;\r
565 }\r
566\r
567 snp = (SNP_DRIVER *) (UINTN) addr;\r
568\r
569 ZeroMem (snp, sizeof (SNP_DRIVER));\r
570\r
571 snp->IoFncs = mPciIoFncs;\r
572 snp->Signature = SNP_DRIVER_SIGNATURE;\r
573\r
574 EfiInitializeLock (&snp->lock, TPL_NOTIFY);\r
575\r
576 snp->snp.Revision = EFI_SIMPLE_NETWORK_PROTOCOL_REVISION;\r
577 snp->snp.Start = snp_undi32_start;\r
578 snp->snp.Stop = snp_undi32_stop;\r
579 snp->snp.Initialize = snp_undi32_initialize;\r
580 snp->snp.Reset = snp_undi32_reset;\r
581 snp->snp.Shutdown = snp_undi32_shutdown;\r
582 snp->snp.ReceiveFilters = snp_undi32_receive_filters;\r
583 snp->snp.StationAddress = snp_undi32_station_address;\r
584 snp->snp.Statistics = snp_undi32_statistics;\r
585 snp->snp.MCastIpToMac = snp_undi32_mcast_ip_to_mac;\r
586 snp->snp.NvData = snp_undi32_nvdata;\r
587 snp->snp.GetStatus = snp_undi32_get_status;\r
588 snp->snp.Transmit = snp_undi32_transmit;\r
589 snp->snp.Receive = snp_undi32_receive;\r
590 snp->snp.WaitForPacket = NULL;\r
591\r
592 snp->snp.Mode = &snp->mode;\r
593\r
594 snp->tx_rx_bufsize = 0;\r
595 snp->tx_rx_buffer = NULL;\r
596\r
597 snp->if_num = Nii->IfNum;\r
598\r
599 if ((pxe->hw.Implementation & PXE_ROMID_IMP_HW_UNDI) != 0) {\r
600 snp->is_swundi = FALSE;\r
601 snp->issue_undi32_command = &issue_hwundi_command;\r
602 } else {\r
603 snp->is_swundi = TRUE;\r
604\r
605 if ((pxe->sw.Implementation & PXE_ROMID_IMP_SW_VIRT_ADDR) != 0) {\r
606 snp->issue_undi32_command = (issue_undi32_command) (UINTN) pxe->sw.EntryPoint;\r
607 } else {\r
608 snp->issue_undi32_command = (issue_undi32_command) (UINTN) ((UINT8) (UINTN) pxe + pxe->sw.EntryPoint);\r
609 }\r
610 }\r
611 //\r
612 // Allocate a global CPB and DB buffer for this UNDI interface.\r
613 // we do this because:\r
614 //\r
615 // -UNDI 3.0 wants all the addresses passed to it (even the cpb and db) to be\r
616 // within 2GB limit, create them here and map them so that when undi calls\r
617 // v2p callback to check if the physical address is < 2gb, we will pass.\r
618 //\r
619 // -This is not a requirement for 3.1 or later UNDIs but the code looks\r
620 // simpler if we use the same cpb, db variables for both old and new undi\r
621 // interfaces from all the SNP interface calls (we don't map the buffers\r
622 // for the newer undi interfaces though)\r
623 // .\r
624 // -it is OK to allocate one global set of CPB, DB pair for each UNDI\r
625 // interface as EFI does not multi-task and so SNP will not be re-entered!\r
626 //\r
627 Status = mPciIoFncs->AllocateBuffer (\r
628 mPciIoFncs,\r
629 AllocateAnyPages,\r
630 EfiBootServicesData,\r
631 SNP_MEM_PAGES (4096),\r
632 &addr,\r
633 0\r
634 );\r
635\r
636 if (Status != EFI_SUCCESS) {\r
637 DEBUG ((EFI_D_NET, "\nCould not allocate CPB and DB structures.\n"));\r
638 goto Error_DeleteSNP;\r
639 }\r
640\r
641 snp->cpb = (VOID *) (UINTN) addr;\r
642 snp->db = (VOID *) ((UINTN) addr + 2048);\r
643\r
644 //\r
645 // pxe_start call is going to give the callback functions to UNDI, these callback\r
646 // functions use the BarIndex values from the snp structure, so these must be initialized\r
647 // with default values before doing a pxe_start. The correct values can be obtained after\r
648 // getting the config information from UNDI\r
649 //\r
650 snp->MemoryBarIndex = 0;\r
651 snp->IoBarIndex = 1;\r
652\r
653 //\r
654 // we need the undi init information many times in this snp code, just get it\r
655 // once here and store it in the snp driver structure. to get Init Info\r
656 // from UNDI we have to start undi first.\r
657 //\r
658 Status = pxe_start (snp);\r
659\r
660 if (Status != EFI_SUCCESS) {\r
661 goto Error_DeleteSNP;\r
662 }\r
663\r
664 snp->cdb.OpCode = PXE_OPCODE_GET_INIT_INFO;\r
665 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
666\r
667 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
668 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
669\r
670 snp->cdb.DBsize = sizeof snp->init_info;\r
671 snp->cdb.DBaddr = (UINT64)(UINTN) &snp->init_info;\r
672\r
673 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
674 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
675\r
676 snp->cdb.IFnum = snp->if_num;\r
677 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
678\r
679 DEBUG ((EFI_D_NET, "\nsnp->undi.get_init_info() "));\r
680\r
681 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
682\r
683 //\r
684 // Save the INIT Stat Code...\r
685 //\r
686 InitStatFlags = snp->cdb.StatFlags;\r
687\r
688 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
689 DEBUG ((EFI_D_NET, "\nsnp->undi.init_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));\r
690 pxe_stop (snp);\r
691 goto Error_DeleteSNP;\r
692 }\r
693\r
694 snp->cdb.OpCode = PXE_OPCODE_GET_CONFIG_INFO;\r
695 snp->cdb.OpFlags = PXE_OPFLAGS_NOT_USED;\r
696\r
697 snp->cdb.CPBsize = PXE_CPBSIZE_NOT_USED;\r
698 snp->cdb.CPBaddr = PXE_DBADDR_NOT_USED;\r
699\r
700 snp->cdb.DBsize = sizeof ConfigInfo;\r
701 snp->cdb.DBaddr = (UINT64)(UINTN) &ConfigInfo;\r
702\r
703 snp->cdb.StatCode = PXE_STATCODE_INITIALIZE;\r
704 snp->cdb.StatFlags = PXE_STATFLAGS_INITIALIZE;\r
705\r
706 snp->cdb.IFnum = snp->if_num;\r
707 snp->cdb.Control = PXE_CONTROL_LAST_CDB_IN_LIST;\r
708\r
709 DEBUG ((EFI_D_NET, "\nsnp->undi.get_config_info() "));\r
710\r
711 (*snp->issue_undi32_command) ((UINT64)(UINTN) &snp->cdb);\r
712\r
713 if (snp->cdb.StatCode != PXE_STATCODE_SUCCESS) {\r
714 DEBUG ((EFI_D_NET, "\nsnp->undi.config_info() %xh:%xh\n", snp->cdb.StatFlags, snp->cdb.StatCode));\r
715 pxe_stop (snp);\r
716 goto Error_DeleteSNP;\r
717 }\r
718 //\r
719 // Find the correct BAR to do IO.\r
720 //\r
721 //\r
722 // Enumerate through the PCI BARs for the device to determine which one is\r
723 // the IO BAR. Save the index of the BAR into the adapter info structure.\r
724 // for regular 32bit BARs, 0 is memory mapped, 1 is io mapped\r
725 //\r
726 ConfigHeader = (PCI_TYPE00 *) &ConfigInfo.Config.Byte[0];\r
727 TempBar = (UINT32 *) &ConfigHeader->Device.Bar[0];\r
728 for (BarIndex = 0; BarIndex <= 5; BarIndex++) {\r
729 if ((*TempBar & PCI_BAR_MEM_MASK) == PCI_BAR_MEM_64BIT) {\r
730 //\r
731 // This is a 64-bit memory bar, skip this and the\r
732 // next bar as well.\r
733 //\r
734 TempBar++;\r
735 }\r
736\r
737 if ((*TempBar & PCI_BAR_IO_MASK) == PCI_BAR_IO_MODE) {\r
738 snp->IoBarIndex = BarIndex;\r
739 break;\r
740 }\r
741\r
742 TempBar++;\r
743 }\r
744\r
745 //\r
746 // Initialize simple network protocol mode structure\r
747 //\r
748 snp->mode.State = EfiSimpleNetworkStopped;\r
749 snp->mode.HwAddressSize = snp->init_info.HWaddrLen;\r
750 snp->mode.MediaHeaderSize = snp->init_info.MediaHeaderLen;\r
751 snp->mode.MaxPacketSize = snp->init_info.FrameDataLen;\r
752 snp->mode.NvRamAccessSize = snp->init_info.NvWidth;\r
753 snp->mode.NvRamSize = snp->init_info.NvCount * snp->mode.NvRamAccessSize;\r
754 snp->mode.IfType = snp->init_info.IFtype;\r
755 snp->mode.MaxMCastFilterCount = snp->init_info.MCastFilterCnt;\r
756 snp->mode.MCastFilterCount = 0;\r
757\r
758 switch (InitStatFlags & PXE_STATFLAGS_CABLE_DETECT_MASK) {\r
759 case PXE_STATFLAGS_CABLE_DETECT_SUPPORTED:\r
760 snp->mode.MediaPresentSupported = TRUE;\r
761 break;\r
762\r
763 case PXE_STATFLAGS_CABLE_DETECT_NOT_SUPPORTED:\r
764 default:\r
765 snp->mode.MediaPresentSupported = FALSE;\r
766 }\r
767\r
768 if ((pxe->hw.Implementation & PXE_ROMID_IMP_STATION_ADDR_SETTABLE) != 0) {\r
769 snp->mode.MacAddressChangeable = TRUE;\r
770 } else {\r
771 snp->mode.MacAddressChangeable = FALSE;\r
772 }\r
773\r
774 if ((pxe->hw.Implementation & PXE_ROMID_IMP_MULTI_FRAME_SUPPORTED) != 0) {\r
775 snp->mode.MultipleTxSupported = TRUE;\r
776 } else {\r
777 snp->mode.MultipleTxSupported = FALSE;\r
778 }\r
779\r
780 snp->mode.ReceiveFilterMask = EFI_SIMPLE_NETWORK_RECEIVE_UNICAST;\r
781\r
782 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) != 0) {\r
783 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
784\r
785 }\r
786\r
787 if ((pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_RX_SUPPORTED) != 0) {\r
788 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS;\r
789\r
790 }\r
791\r
792 if ((pxe->hw.Implementation & PXE_ROMID_IMP_BROADCAST_RX_SUPPORTED) != 0) {\r
793 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_BROADCAST;\r
794\r
795 }\r
796\r
797 if ((pxe->hw.Implementation & PXE_ROMID_IMP_FILTERED_MULTICAST_RX_SUPPORTED) != 0) {\r
798 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_MULTICAST;\r
799\r
800 }\r
801\r
802 if (pxe->hw.Implementation & PXE_ROMID_IMP_PROMISCUOUS_MULTICAST_RX_SUPPORTED) {\r
803 snp->mode.ReceiveFilterMask |= EFI_SIMPLE_NETWORK_RECEIVE_PROMISCUOUS_MULTICAST;\r
804\r
805 }\r
806\r
807 snp->mode.ReceiveFilterSetting = 0;\r
808\r
809 //\r
810 // need to get the station address to save in the mode structure. we need to\r
811 // initialize the UNDI first for this.\r
812 //\r
813 snp->tx_rx_bufsize = snp->init_info.MemoryRequired;\r
814 Status = pxe_init (snp, PXE_OPFLAGS_INITIALIZE_DO_NOT_DETECT_CABLE);\r
815\r
816 if (Status) {\r
817 pxe_stop (snp);\r
818 goto Error_DeleteSNP;\r
819 }\r
820\r
821 Status = pxe_get_stn_addr (snp);\r
822\r
823 if (Status != EFI_SUCCESS) {\r
824 DEBUG ((EFI_D_ERROR, "\nsnp->undi.get_station_addr() failed.\n"));\r
825 pxe_shutdown (snp);\r
826 pxe_stop (snp);\r
827 goto Error_DeleteSNP;\r
828 }\r
829\r
830 snp->mode.MediaPresent = FALSE;\r
831\r
832 //\r
833 // We should not leave UNDI started and initialized here. this DriverStart()\r
834 // routine must only find and attach the SNP interface to UNDI layer that it\r
835 // finds on the given handle!\r
836 // The UNDI layer will be started when upper layers call snp->start.\r
837 // How ever, this DriverStart() must fill up the snp mode structure which\r
838 // contains the MAC address of the NIC. For this reason we started and\r
839 // initialized UNDI here, now we are done, do a shutdown and stop of the\r
840 // UNDI interface!\r
841 //\r
842 pxe_shutdown (snp);\r
843 pxe_stop (snp);\r
844\r
845 //\r
846 // add SNP to the undi handle\r
847 //\r
848 Status = gBS->InstallProtocolInterface (\r
849 &Controller,\r
850 &gEfiSimpleNetworkProtocolGuid,\r
851 EFI_NATIVE_INTERFACE,\r
852 &(snp->snp)\r
853 );\r
854\r
855 if (!EFI_ERROR (Status)) {\r
856 return Status;\r
857 }\r
858\r
859 Status = mPciIoFncs->FreeBuffer (\r
860 mPciIoFncs,\r
861 SNP_MEM_PAGES (4096),\r
862 snp->cpb\r
863 );\r
864\r
865Error_DeleteSNP:\r
866\r
867 mPciIoFncs->FreeBuffer (\r
868 mPciIoFncs,\r
869 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
870 snp\r
871 );\r
872NiiError:\r
873 gBS->CloseProtocol (\r
874 Controller,\r
875 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
876 This->DriverBindingHandle,\r
877 Controller\r
878 );\r
879\r
880 gBS->CloseProtocol (\r
881 Controller,\r
882 &gEfiDevicePathProtocolGuid,\r
883 This->DriverBindingHandle,\r
884 Controller\r
885 );\r
886\r
887 return Status;\r
888}\r
889\r
890\r
891/**\r
892\r
893\r
894\r
895**/\r
896EFI_STATUS\r
897EFIAPI\r
898SimpleNetworkDriverStop (\r
899 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
900 IN EFI_HANDLE Controller,\r
901 IN UINTN NumberOfChildren,\r
902 IN EFI_HANDLE *ChildHandleBuffer\r
903 )\r
904{\r
905 EFI_STATUS Status;\r
906 EFI_SIMPLE_NETWORK_PROTOCOL *SnpProtocol;\r
907 SNP_DRIVER *Snp;\r
908\r
909 //\r
910 // Get our context back.\r
911 //\r
912 Status = gBS->OpenProtocol (\r
913 Controller,\r
914 &gEfiSimpleNetworkProtocolGuid,\r
915 (VOID **) &SnpProtocol,\r
916 This->DriverBindingHandle,\r
917 Controller,\r
918 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
919 );\r
920\r
921 if (EFI_ERROR (Status)) {\r
922 return EFI_UNSUPPORTED;\r
923 }\r
924\r
925 Snp = EFI_SIMPLE_NETWORK_DEV_FROM_THIS (SnpProtocol);\r
926\r
927 Status = gBS->UninstallProtocolInterface (\r
928 Controller,\r
929 &gEfiSimpleNetworkProtocolGuid,\r
930 &Snp->snp\r
931 );\r
932\r
933 if (EFI_ERROR (Status)) {\r
934 return Status;\r
935 }\r
936\r
937 Status = gBS->CloseProtocol (\r
938 Controller,\r
939 &gEfiNetworkInterfaceIdentifierProtocolGuid_31,\r
940 This->DriverBindingHandle,\r
941 Controller\r
942 );\r
943\r
944 Status = gBS->CloseProtocol (\r
945 Controller,\r
946 &gEfiDevicePathProtocolGuid,\r
947 This->DriverBindingHandle,\r
948 Controller\r
949 );\r
950\r
951 pxe_shutdown (Snp);\r
952 pxe_stop (Snp);\r
953\r
954 mPciIoFncs->FreeBuffer (\r
955 mPciIoFncs,\r
956 SNP_MEM_PAGES (4096),\r
957 Snp->cpb\r
958 );\r
959\r
960 mPciIoFncs->FreeBuffer (\r
961 mPciIoFncs,\r
962 SNP_MEM_PAGES (sizeof (SNP_DRIVER)),\r
963 Snp\r
964 );\r
965\r
966 return Status;\r
967}\r
968\r
969\r
970/**\r
971 Install all the driver protocol\r
972\r
973 @param entry EFI_IMAGE_ENTRY_POINT)\r
974\r
975 @retval EFI_SUCEESS Initialization routine has found UNDI hardware,\r
976 loaded it's ROM, and installed a notify event for\r
977 the Network Indentifier Interface Protocol\r
978 successfully.\r
979 @retval Other Return value from HandleProtocol for\r
980 DeviceIoProtocol or LoadedImageProtocol\r
981\r
982**/\r
983EFI_STATUS\r
984EFIAPI\r
985InitializeSnpNiiDriver (\r
986 IN EFI_HANDLE ImageHandle,\r
987 IN EFI_SYSTEM_TABLE *SystemTable\r
988 )\r
989{\r
990 return EfiLibInstallDriverBindingComponentName2 (\r
991 ImageHandle,\r
992 SystemTable,\r
993 &mSimpleNetworkDriverBinding,\r
994 NULL,\r
995 &gSimpleNetworkComponentName,\r
996 &gSimpleNetworkComponentName2\r
997 );\r
998}\r