• 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 UINT64 * DeviceFeatures)102 VirtioPciGetDeviceFeatures (
103   IN VIRTIO_DEVICE_PROTOCOL *This,
104   OUT UINT64                *DeviceFeatures
105   )
106 {
107   VIRTIO_PCI_DEVICE         *Dev;
108   EFI_STATUS                Status;
109   UINT32                    Features32;
110 
111   if (DeviceFeatures == NULL) {
112     return EFI_INVALID_PARAMETER;
113   }
114 
115   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
116 
117   Status = VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_DEVICE_FEATURES,
118              sizeof (UINT32), sizeof (UINT32), &Features32);
119   if (!EFI_ERROR (Status)) {
120     *DeviceFeatures = Features32;
121   }
122   return Status;
123 }
124 
125 EFI_STATUS
126 EFIAPI
VirtioPciGetQueueSize(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT16 * QueueNumMax)127 VirtioPciGetQueueSize (
128   IN  VIRTIO_DEVICE_PROTOCOL  *This,
129   OUT UINT16                  *QueueNumMax
130   )
131 {
132   VIRTIO_PCI_DEVICE         *Dev;
133 
134   if (QueueNumMax == NULL) {
135     return EFI_INVALID_PARAMETER;
136   }
137 
138   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
139 
140   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_SIZE, sizeof (UINT16),
141       sizeof (UINT16), QueueNumMax);
142 }
143 
144 EFI_STATUS
145 EFIAPI
VirtioPciGetDeviceStatus(IN VIRTIO_DEVICE_PROTOCOL * This,OUT UINT8 * DeviceStatus)146 VirtioPciGetDeviceStatus (
147   IN  VIRTIO_DEVICE_PROTOCOL  *This,
148   OUT UINT8                   *DeviceStatus
149   )
150 {
151   VIRTIO_PCI_DEVICE         *Dev;
152 
153   if (DeviceStatus == NULL) {
154     return EFI_INVALID_PARAMETER;
155   }
156 
157   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
158 
159   return VirtioPciIoRead (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
160       sizeof (UINT8), sizeof (UINT8), DeviceStatus);
161 }
162 
163 EFI_STATUS
164 EFIAPI
VirtioPciSetGuestFeatures(IN VIRTIO_DEVICE_PROTOCOL * This,IN UINT64 Features)165 VirtioPciSetGuestFeatures (
166   IN VIRTIO_DEVICE_PROTOCOL  *This,
167   IN UINT64                   Features
168   )
169 {
170   VIRTIO_PCI_DEVICE *Dev;
171 
172   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
173 
174   if (Features > MAX_UINT32) {
175     return EFI_UNSUPPORTED;
176   }
177   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_GUEST_FEATURES,
178       sizeof (UINT32), Features);
179 }
180 
181 EFI_STATUS
182 EFIAPI
VirtioPciSetQueueAddress(IN VIRTIO_DEVICE_PROTOCOL * This,IN VRING * Ring)183 VirtioPciSetQueueAddress (
184   IN VIRTIO_DEVICE_PROTOCOL  *This,
185   IN VRING                   *Ring
186   )
187 {
188   VIRTIO_PCI_DEVICE *Dev;
189 
190   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
191 
192   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_ADDRESS, sizeof (UINT32),
193       (UINT32)((UINTN)Ring->Base >> EFI_PAGE_SHIFT));
194 }
195 
196 EFI_STATUS
197 EFIAPI
VirtioPciSetQueueSel(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Sel)198 VirtioPciSetQueueSel (
199   VIRTIO_DEVICE_PROTOCOL    *This,
200   UINT16                    Sel
201   )
202 {
203   VIRTIO_PCI_DEVICE *Dev;
204 
205   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
206 
207   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_SELECT, sizeof (UINT16),
208       Sel);
209 }
210 
211 EFI_STATUS
212 EFIAPI
VirtioPciSetQueueAlignment(VIRTIO_DEVICE_PROTOCOL * This,UINT32 Alignment)213 VirtioPciSetQueueAlignment (
214   VIRTIO_DEVICE_PROTOCOL *This,
215   UINT32                  Alignment
216   )
217 {
218   return EFI_SUCCESS;
219 }
220 
221 EFI_STATUS
222 EFIAPI
VirtioPciSetPageSize(VIRTIO_DEVICE_PROTOCOL * This,UINT32 PageSize)223 VirtioPciSetPageSize (
224   VIRTIO_DEVICE_PROTOCOL *This,
225   UINT32                  PageSize
226   )
227 {
228   return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
229 }
230 
231 EFI_STATUS
232 EFIAPI
VirtioPciSetQueueNotify(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Index)233 VirtioPciSetQueueNotify (
234   VIRTIO_DEVICE_PROTOCOL *This,
235   UINT16                 Index
236   )
237 {
238   VIRTIO_PCI_DEVICE *Dev;
239 
240   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
241 
242   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_NOTIFY, sizeof (UINT16),
243       Index);
244 }
245 
246 EFI_STATUS
247 EFIAPI
VirtioPciSetQueueSize(VIRTIO_DEVICE_PROTOCOL * This,UINT16 Size)248 VirtioPciSetQueueSize (
249   VIRTIO_DEVICE_PROTOCOL *This,
250   UINT16                 Size
251   )
252 {
253   //
254   // This function is only applicable in Virtio-MMIO.
255   // (The QueueSize field is read-only in Virtio proper (PCI))
256   //
257   return EFI_SUCCESS;
258 }
259 
260 EFI_STATUS
261 EFIAPI
VirtioPciSetDeviceStatus(VIRTIO_DEVICE_PROTOCOL * This,UINT8 DeviceStatus)262 VirtioPciSetDeviceStatus (
263   VIRTIO_DEVICE_PROTOCOL *This,
264   UINT8                  DeviceStatus
265   )
266 {
267   VIRTIO_PCI_DEVICE *Dev;
268 
269   Dev = VIRTIO_PCI_DEVICE_FROM_VIRTIO_DEVICE (This);
270 
271   return VirtioPciIoWrite (Dev, VIRTIO_PCI_OFFSET_QUEUE_DEVICE_STATUS,
272       sizeof (UINT8), DeviceStatus);
273 }
274