2 This file contains two sets of callback routines for undi3.0 and undi3.1.
3 the callback routines for Undi3.1 have an extra parameter UniqueId which
4 stores the interface context for the NIC that snp is trying to talk.
6 Copyright (c) 2006, Intel Corporation
7 All rights reserved. This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 // these 2 global variables are used only for 3.0 undi. we could not place
22 // them in the snp structure because we will not know which snp structure
23 // in the callback context!
25 BOOLEAN mInitializeLock
= TRUE
;
29 // End Global variables
31 extern EFI_PCI_IO_PROTOCOL
*mPciIoFncs
;
34 snp_undi32_callback_v2p_30 (
36 IN OUT UINT64 DeviceAddrPtr
41 This is a callback routine supplied to UNDI at undi_start time.
42 UNDI call this routine with a virtual or CPU address that SNP provided
43 to convert it to a physical or device address. Since EFI uses the identical
44 mapping, this routine returns the physical address same as the virtual address
45 for most of the addresses. an address above 4GB cannot generally be used as a
46 device address, it needs to be mapped to a lower physical address. This routine
47 does not call the map routine itself, but it assumes that the mapping was done
48 at the time of providing the address to UNDI. This routine just looks up the
49 address in a map table (which is the v2p structure chain)
52 CpuAddr - virtual address of a buffer
53 DeviceAddrPtr - pointer to the physical address
56 void - The DeviceAddrPtr will contain 0 in case of any error
62 // Do nothing if virtual address is zero or physical pointer is NULL.
63 // No need to map if the virtual address is within 4GB limit since
64 // EFI uses identical mapping
66 if ((CpuAddr
== 0) || (DeviceAddrPtr
== 0)) {
67 DEBUG ((EFI_D_ERROR
, "\nv2p: Null virtual address or physical pointer.\n"));
71 if (CpuAddr
< FOUR_GIGABYTES
) {
72 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
76 // SNP creates a vaddr tp paddr mapping at the time of calling undi with any
77 // big address, this callback routine just looks up in the v2p list and
78 // returns the physical address for any given virtual address.
80 if (find_v2p (&v2p
, (VOID
*) (UINTN
) CpuAddr
) != EFI_SUCCESS
) {
81 *(UINT64
*) (UINTN
) DeviceAddrPtr
= CpuAddr
;
83 *(UINT64
*) (UINTN
) DeviceAddrPtr
= v2p
->paddr
;
88 snp_undi32_callback_block_30 (
94 This is a callback routine supplied to UNDI at undi_start time.
95 UNDI call this routine when it wants to have exclusive access to a critical
96 section of the code/data
99 Enable - non-zero indicates acquire
100 zero indicates release
107 // tcpip was calling snp at tpl_notify and if we acquire a lock that was
108 // created at a lower level (TPL_CALLBACK) it gives an assert!
110 if (mInitializeLock
) {
111 EfiInitializeLock (&mLock
, TPL_NOTIFY
);
112 mInitializeLock
= FALSE
;
116 EfiAcquireLock (&mLock
);
118 EfiReleaseLock (&mLock
);
123 snp_undi32_callback_delay_30 (
124 IN UINT64 MicroSeconds
129 This is a callback routine supplied to UNDI at undi_start time.
130 UNDI call this routine with the number of micro seconds when it wants to
134 MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
140 if (MicroSeconds
!= 0) {
141 gBS
->Stall ((UINTN
) MicroSeconds
);
146 snp_undi32_callback_memio_30 (
147 IN UINT8 ReadOrWrite
,
150 IN OUT UINT64 BufferAddr
155 This is a callback routine supplied to UNDI at undi_start time.
156 This is the IO routine for UNDI. This is not currently being used by UNDI3.0
157 because Undi3.0 uses io/mem offsets relative to the beginning of the device
158 io/mem address and so it needs to use the PCI_IO_FUNCTION that abstracts the
159 start of the device's io/mem addresses. Since SNP cannot retrive the context
160 of the undi3.0 interface it cannot use the PCI_IO_FUNCTION that specific for
161 that NIC and uses one global IO functions structure, this does not work.
162 This however works fine for EFI1.0 Undis because they use absolute addresses
166 ReadOrWrite - indicates read or write, IO or Memory
167 NumBytes - number of bytes to read or write
168 Address - IO or memory address to read from or write to
169 BufferAddr - memory location to read into or that contains the bytes
176 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
180 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
184 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
188 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
192 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
195 switch (ReadOrWrite
) {
197 mPciIoFncs
->Io
.Read (
200 1, // BAR 1, IO base address
203 (VOID
*) (UINTN
) BufferAddr
208 mPciIoFncs
->Io
.Write (
211 1, // BAR 1, IO base address
214 (VOID
*) (UINTN
) BufferAddr
219 mPciIoFncs
->Mem
.Read (
222 0, // BAR 0, Memory base address
225 (VOID
*) (UINTN
) BufferAddr
230 mPciIoFncs
->Mem
.Write (
233 0, // BAR 0, Memory base address
236 (VOID
*) (UINTN
) BufferAddr
244 // New callbacks for 3.1:
245 // there won't be a virtual2physical callback for UNDI 3.1 because undi3.1 uses
246 // the MemMap call to map the required address by itself!
249 snp_undi32_callback_block (
256 This is a callback routine supplied to UNDI3.1 at undi_start time.
257 UNDI call this routine when it wants to have exclusive access to a critical
258 section of the code/data
261 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
262 Undi interface context (Undi does not read or write this variable)
263 Enable - non-zero indicates acquire
264 zero indicates release
273 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
275 // tcpip was calling snp at tpl_notify and when we acquire a lock that was
276 // created at a lower level (TPL_CALLBACK) it gives an assert!
279 EfiAcquireLock (&snp
->lock
);
281 EfiReleaseLock (&snp
->lock
);
286 snp_undi32_callback_delay (
288 IN UINT64 MicroSeconds
293 This is a callback routine supplied to UNDI at undi_start time.
294 UNDI call this routine with the number of micro seconds when it wants to
298 MicroSeconds - number of micro seconds to pause, ususlly multiple of 10
304 if (MicroSeconds
!= 0) {
305 gBS
->Stall ((UINTN
) MicroSeconds
);
310 * IO routine for UNDI start CPB.
313 snp_undi32_callback_memio (
323 This is a callback routine supplied to UNDI at undi_start time.
324 This is the IO routine for UNDI3.1.
327 ReadOrWrite - indicates read or write, IO or Memory
328 NumBytes - number of bytes to read or write
329 Address - IO or memory address to read from or write to
330 BufferAddr - memory location to read into or that contains the bytes
338 EFI_PCI_IO_PROTOCOL_WIDTH Width
;
340 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
342 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 0;
345 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 1;
349 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 2;
353 Width
= (EFI_PCI_IO_PROTOCOL_WIDTH
) 3;
357 switch (ReadOrWrite
) {
359 snp
->IoFncs
->Io
.Read (
362 snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
365 (VOID
*) (UINTN
) BufferAddr
370 snp
->IoFncs
->Io
.Write (
373 snp
->IoBarIndex
, // BAR 1 (for 32bit regs), IO base address
376 (VOID
*) (UINTN
) BufferAddr
381 snp
->IoFncs
->Mem
.Read (
384 snp
->MemoryBarIndex
, // BAR 0, Memory base address
387 (VOID
*) (UINTN
) BufferAddr
392 snp
->IoFncs
->Mem
.Write (
395 snp
->MemoryBarIndex
, // BAR 0, Memory base address
398 (VOID
*) (UINTN
) BufferAddr
407 snp_undi32_callback_map (
412 IN OUT UINT64 DeviceAddrPtr
417 This is a callback routine supplied to UNDI at undi_start time.
418 UNDI call this routine when it has to map a CPU address to a device
422 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
423 Undi interface context (Undi does not read or write this variable)
424 CpuAddr - Virtual address to be mapped!
425 NumBytes - size of memory to be mapped
426 Direction - direction of data flow for this memory's usage:
427 cpu->device, device->cpu or both ways
428 DeviceAddrPtr - pointer to return the mapped device address
435 EFI_PHYSICAL_ADDRESS
*DevAddrPtr
;
436 EFI_PCI_IO_PROTOCOL_OPERATION DirectionFlag
;
442 BuffSize
= (UINTN
) NumBytes
;
443 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
444 DevAddrPtr
= (EFI_PHYSICAL_ADDRESS
*) (UINTN
) DeviceAddrPtr
;
452 case TO_AND_FROM_DEVICE
:
453 DirectionFlag
= EfiPciIoOperationBusMasterCommonBuffer
;
457 DirectionFlag
= EfiPciIoOperationBusMasterWrite
;
461 DirectionFlag
= EfiPciIoOperationBusMasterRead
;
467 // any non zero indicates error!
472 // find an unused map_list entry
474 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
475 if (snp
->map_list
[Index
].virt
== 0) {
480 if (Index
>= MAX_MAP_LENGTH
) {
481 DEBUG ((EFI_D_INFO
, "SNP maplist is FULL\n"));
486 snp
->map_list
[Index
].virt
= (EFI_PHYSICAL_ADDRESS
) CpuAddr
;
488 Status
= snp
->IoFncs
->Map (
491 (VOID
*) (UINTN
) CpuAddr
,
494 &(snp
->map_list
[Index
].map_cookie
)
496 if (Status
!= EFI_SUCCESS
) {
498 snp
->map_list
[Index
].virt
= 0;
505 snp_undi32_callback_unmap (
515 This is a callback routine supplied to UNDI at undi_start time.
516 UNDI call this routine when it wants to unmap an address that was previously
517 mapped using map callback
520 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
521 Undi interface context (Undi does not read or write this variable)
522 CpuAddr - Virtual address that was mapped!
523 NumBytes - size of memory mapped
524 Direction- direction of data flow for this memory's usage:
525 cpu->device, device->cpu or both ways
526 DeviceAddr - the mapped device address
535 snp
= (SNP_DRIVER
*) (UINTN
) UniqueId
;
537 for (Index
= 0; Index
< MAX_MAP_LENGTH
; Index
++) {
538 if (snp
->map_list
[Index
].virt
== CpuAddr
) {
543 if (Index
>= MAX_MAP_LENGTH
)
545 DEBUG ((EFI_D_ERROR
, "SNP could not find a mapping, failed to unmap.\n"));
549 snp
->IoFncs
->Unmap (snp
->IoFncs
, snp
->map_list
[Index
].map_cookie
);
550 snp
->map_list
[Index
].virt
= 0;
551 snp
->map_list
[Index
].map_cookie
= NULL
;
556 snp_undi32_callback_sync (
566 This is a callback routine supplied to UNDI at undi_start time.
567 UNDI call this routine when it wants synchronize the virtual buffer contents
568 with the mapped buffer contents. The virtual and mapped buffers need not
569 correspond to the same physical memory (especially if the virtual address is
570 > 4GB). Depending on the direction for which the buffer is mapped, undi will
571 need to synchronize their contents whenever it writes to/reads from the buffer
572 using either the cpu address or the device address.
574 EFI does not provide a sync call, since virt=physical, we sould just do
575 the synchronization ourself here!
578 UniqueId - This was supplied to UNDI at Undi_Start, SNP uses this to store
579 Undi interface context (Undi does not read or write this variable)
580 CpuAddr - Virtual address that was mapped!
581 NumBytes - size of memory mapped
582 Direction- direction of data flow for this memory's usage:
583 cpu->device, device->cpu or both ways
584 DeviceAddr - the mapped device address
590 if ((CpuAddr
== 0) || (DeviceAddr
== 0) || (NumBytes
== 0)) {
597 CopyMem ((UINT8
*) (UINTN
) CpuAddr
, (UINT8
*) (UINTN
) DeviceAddr
, NumBytes
);
601 CopyMem ((UINT8
*) (UINTN
) DeviceAddr
, (UINT8
*) (UINTN
) CpuAddr
, NumBytes
);