• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1  /** @file
2  
3    This driver produces Virtio Device Protocol instances for Virtio PCI devices.
4  
5    Copyright (C) 2012, Red Hat, Inc.
6    Copyright (c) 2012, Intel Corporation. All rights reserved.<BR>
7    Copyright (C) 2013, ARM Ltd.
8  
9    This program and the accompanying materials are licensed and made available
10    under the terms and conditions of the BSD License which accompanies this
11    distribution. The full text of the license may be found at
12    http://opensource.org/licenses/bsd-license.php
13  
14    THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT
15    WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16  
17  **/
18  #include <Library/BaseMemoryLib.h>
19  #include <Library/DebugLib.h>
20  #include <Library/MemoryAllocationLib.h>
21  #include <Library/UefiBootServicesTableLib.h>
22  #include <Library/UefiLib.h>
23  #include "VirtioPciDevice.h"
24  
25  /**
26  
27    Read a word from Region 0 of the device specified by VirtIo Device protocol.
28  
29    The function implements the ReadDevice protocol member of
30    VIRTIO_DEVICE_PROTOCOL.
31  
32    @param[in] This         VirtIo Device protocol.
33  
34    @param[in] FieldOffset  Source offset.
35  
36    @param[in] FieldSize    Source field size, must be in { 1, 2, 4, 8 }.
37  
38    @param[in] BufferSize   Number of bytes available in the target buffer. Must
39                            equal FieldSize.
40  
41    @param[out] Buffer      Target buffer.
42  
43  
44    @return  Status code returned by PciIo->Io.Read().
45  
46  **/
47  EFI_STATUS
48  EFIAPI
VirtioPciDeviceRead(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINTN FieldOffset,IN UINTN FieldSize,IN UINTN BufferSize,OUT VOID * Buffer)49  VirtioPciDeviceRead (
50    IN  VIRTIO_DEVICE_PROTOCOL    *This,
51    IN  UINTN                     FieldOffset,
52    IN  UINTN                     FieldSize,
53    IN  UINTN                     BufferSize,
54    OUT VOID                      *Buffer
55    )
56  {
57    VIRTIO_PCI_DEVICE         *Dev;
58  
59    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
60  
61    return VirtioPciIoRead (Dev,
62        Dev->DeviceSpecificConfigurationOffset + FieldOffset,
63        FieldSize, BufferSize, Buffer);
64  }
65  
66  /**
67  
68    Write a word into Region 0 of the device specified by VirtIo Device protocol.
69  
70    @param[in] This         VirtIo Device protocol.
71  
72    @param[in] FieldOffset  Destination offset.
73  
74    @param[in] FieldSize    Destination field size, must be in { 1, 2, 4, 8 }.
75  
76    @param[in] Value        Little endian value to write, converted to UINT64.
77                            The least significant FieldSize bytes will be used.
78  
79  
80    @return  Status code returned by PciIo->Io.Write().
81  
82  **/
83  EFI_STATUS
84  EFIAPI
VirtioPciDeviceWrite(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINTN FieldOffset,IN UINTN FieldSize,IN UINT64 Value)85  VirtioPciDeviceWrite (
86    IN VIRTIO_DEVICE_PROTOCOL *This,
87    IN UINTN                  FieldOffset,
88    IN UINTN                  FieldSize,
89    IN UINT64                 Value
90    )
91  {
92    VIRTIO_PCI_DEVICE         *Dev;
93  
94    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
95  
96    return VirtioPciIoWrite (Dev,
97        Dev->DeviceSpecificConfigurationOffset + FieldOffset, FieldSize, Value);
98  }
99  
100  EFI_STATUS
101  EFIAPI
VirtioPciGetDeviceFeatures(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT32 * DeviceFeatures)102  VirtioPciGetDeviceFeatures (
103    IN VIRTIO_DEVICE_PROTOCOL *This,
104    OUT UINT32                *DeviceFeatures
105    )
106  {
107    VIRTIO_PCI_DEVICE         *Dev;
108  
109    if (DeviceFeatures == NULL) {
110      return EFI_INVALID_PARAMETER;
111    }
112  
113    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
114  
115    return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES, sizeof (UINT32),
116        sizeof (UINT32), DeviceFeatures);
117  }
118  
119  EFI_STATUS
120  EFIAPI
VirtioPciGetQueueAddress(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT32 * QueueAddress)121  VirtioPciGetQueueAddress (
122    IN  VIRTIO_DEVICE_PROTOCOL *This,
123    OUT UINT32                 *QueueAddress
124    )
125  {
126    VIRTIO_PCI_DEVICE         *Dev;
127  
128    if (QueueAddress == NULL) {
129      return EFI_INVALID_PARAMETER;
130    }
131  
132    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
133  
134    return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
135        sizeof (UINT32), QueueAddress);
136  }
137  
138  EFI_STATUS
139  EFIAPI
VirtioPciGetQueueSize(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT16 * QueueNumMax)140  VirtioPciGetQueueSize (
141    IN  VIRTIO_DEVICE_PROTOCOL  *This,
142    OUT UINT16                  *QueueNumMax
143    )
144  {
145    VIRTIO_PCI_DEVICE         *Dev;
146  
147    if (QueueNumMax == NULL) {
148      return EFI_INVALID_PARAMETER;
149    }
150  
151    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
152  
153    return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
154        sizeof (UINT16), QueueNumMax);
155  }
156  
157  EFI_STATUS
158  EFIAPI
VirtioPciGetDeviceStatus(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT8 * DeviceStatus)159  VirtioPciGetDeviceStatus (
160    IN  VIRTIO_DEVICE_PROTOCOL  *This,
161    OUT UINT8                   *DeviceStatus
162    )
163  {
164    VIRTIO_PCI_DEVICE         *Dev;
165  
166    if (DeviceStatus == NULL) {
167      return EFI_INVALID_PARAMETER;
168    }
169  
170    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
171  
172    return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
173        sizeof (UINT8), sizeof (UINT8), DeviceStatus);
174  }
175  
176  EFI_STATUS
177  EFIAPI
VirtioPciSetGuestFeatures(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINT32 Features)178  VirtioPciSetGuestFeatures (
179    IN VIRTIO_DEVICE_PROTOCOL  *This,
180    IN UINT32                   Features
181    )
182  {
183    VIRTIO_PCI_DEVICE *Dev;
184  
185    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
186  
187    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
188        sizeof (UINT32), Features);
189  }
190  
191  EFI_STATUS
192  EFIAPI
VirtioPciSetQueueAddress(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Address)193  VirtioPciSetQueueAddress (
194    VIRTIO_DEVICE_PROTOCOL    *This,
195    UINT32                    Address
196    )
197  {
198    VIRTIO_PCI_DEVICE *Dev;
199  
200    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
201  
202    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
203        Address);
204  }
205  
206  EFI_STATUS
207  EFIAPI
VirtioPciSetQueueSel(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Sel)208  VirtioPciSetQueueSel (
209    VIRTIO_DEVICE_PROTOCOL    *This,
210    UINT16                    Sel
211    )
212  {
213    VIRTIO_PCI_DEVICE *Dev;
214  
215    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
216  
217    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
218        Sel);
219  }
220  
221  EFI_STATUS
222  EFIAPI
VirtioPciSetQueueAlignment(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Alignment)223  VirtioPciSetQueueAlignment (
224    VIRTIO_DEVICE_PROTOCOL *This,
225    UINT32                  Alignment
226    )
227  {
228    return EFI_SUCCESS;
229  }
230  
231  EFI_STATUS
232  EFIAPI
VirtioPciSetPageSize(VIRTIO_DEVICE_PROTOCOL * This,UINT32 PageSize)233  VirtioPciSetPageSize (
234    VIRTIO_DEVICE_PROTOCOL *This,
235    UINT32                  PageSize
236    )
237  {
238    return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
239  }
240  
241  EFI_STATUS
242  EFIAPI
VirtioPciSetQueueNotify(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Index)243  VirtioPciSetQueueNotify (
244    VIRTIO_DEVICE_PROTOCOL *This,
245    UINT16                 Index
246    )
247  {
248    VIRTIO_PCI_DEVICE *Dev;
249  
250    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
251  
252    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
253        Index);
254  }
255  
256  EFI_STATUS
257  EFIAPI
VirtioPciSetQueueSize(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Size)258  VirtioPciSetQueueSize (
259    VIRTIO_DEVICE_PROTOCOL *This,
260    UINT16                 Size
261    )
262  {
263    //
264    // This function is only applicable in Virtio-MMIO.
265    // (The QueueSize field is read-only in Virtio proper (PCI))
266    //
267    return EFI_SUCCESS;
268  }
269  
270  EFI_STATUS
271  EFIAPI
VirtioPciSetDeviceStatus(VIRTIO_DEVICE_PROTOCOL * This,UINT8 DeviceStatus)272  VirtioPciSetDeviceStatus (
273    VIRTIO_DEVICE_PROTOCOL *This,
274    UINT8                  DeviceStatus
275    )
276  {
277    VIRTIO_PCI_DEVICE *Dev;
278  
279    Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
280  
281    return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
282        sizeof (UINT8), DeviceStatus);
283  }
284