xref: /dpdk/drivers/net/virtio/virtio_pci.c (revision 6c3169a3dc041cbdbef506f19e3779940caa4b29)
1*6c3169a3SBruce Richardson /*-
2*6c3169a3SBruce Richardson  *   BSD LICENSE
3*6c3169a3SBruce Richardson  *
4*6c3169a3SBruce Richardson  *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.
5*6c3169a3SBruce Richardson  *   All rights reserved.
6*6c3169a3SBruce Richardson  *
7*6c3169a3SBruce Richardson  *   Redistribution and use in source and binary forms, with or without
8*6c3169a3SBruce Richardson  *   modification, are permitted provided that the following conditions
9*6c3169a3SBruce Richardson  *   are met:
10*6c3169a3SBruce Richardson  *
11*6c3169a3SBruce Richardson  *     * Redistributions of source code must retain the above copyright
12*6c3169a3SBruce Richardson  *       notice, this list of conditions and the following disclaimer.
13*6c3169a3SBruce Richardson  *     * Redistributions in binary form must reproduce the above copyright
14*6c3169a3SBruce Richardson  *       notice, this list of conditions and the following disclaimer in
15*6c3169a3SBruce Richardson  *       the documentation and/or other materials provided with the
16*6c3169a3SBruce Richardson  *       distribution.
17*6c3169a3SBruce Richardson  *     * Neither the name of Intel Corporation nor the names of its
18*6c3169a3SBruce Richardson  *       contributors may be used to endorse or promote products derived
19*6c3169a3SBruce Richardson  *       from this software without specific prior written permission.
20*6c3169a3SBruce Richardson  *
21*6c3169a3SBruce Richardson  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*6c3169a3SBruce Richardson  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*6c3169a3SBruce Richardson  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24*6c3169a3SBruce Richardson  *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25*6c3169a3SBruce Richardson  *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26*6c3169a3SBruce Richardson  *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27*6c3169a3SBruce Richardson  *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28*6c3169a3SBruce Richardson  *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29*6c3169a3SBruce Richardson  *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30*6c3169a3SBruce Richardson  *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31*6c3169a3SBruce Richardson  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32*6c3169a3SBruce Richardson  */
33*6c3169a3SBruce Richardson #include <stdint.h>
34*6c3169a3SBruce Richardson 
35*6c3169a3SBruce Richardson #include "virtio_pci.h"
36*6c3169a3SBruce Richardson #include "virtio_logs.h"
37*6c3169a3SBruce Richardson 
38*6c3169a3SBruce Richardson static uint8_t vtpci_get_status(struct virtio_hw *);
39*6c3169a3SBruce Richardson 
40*6c3169a3SBruce Richardson void
41*6c3169a3SBruce Richardson vtpci_read_dev_config(struct virtio_hw *hw, uint64_t offset,
42*6c3169a3SBruce Richardson 		void *dst, int length)
43*6c3169a3SBruce Richardson {
44*6c3169a3SBruce Richardson 	uint64_t off;
45*6c3169a3SBruce Richardson 	uint8_t *d;
46*6c3169a3SBruce Richardson 	int size;
47*6c3169a3SBruce Richardson 
48*6c3169a3SBruce Richardson 	off = VIRTIO_PCI_CONFIG(hw) + offset;
49*6c3169a3SBruce Richardson 	for (d = dst; length > 0; d += size, off += size, length -= size) {
50*6c3169a3SBruce Richardson 		if (length >= 4) {
51*6c3169a3SBruce Richardson 			size = 4;
52*6c3169a3SBruce Richardson 			*(uint32_t *)d = VIRTIO_READ_REG_4(hw, off);
53*6c3169a3SBruce Richardson 		} else if (length >= 2) {
54*6c3169a3SBruce Richardson 			size = 2;
55*6c3169a3SBruce Richardson 			*(uint16_t *)d = VIRTIO_READ_REG_2(hw, off);
56*6c3169a3SBruce Richardson 		} else {
57*6c3169a3SBruce Richardson 			size = 1;
58*6c3169a3SBruce Richardson 			*d = VIRTIO_READ_REG_1(hw, off);
59*6c3169a3SBruce Richardson 		}
60*6c3169a3SBruce Richardson 	}
61*6c3169a3SBruce Richardson }
62*6c3169a3SBruce Richardson 
63*6c3169a3SBruce Richardson void
64*6c3169a3SBruce Richardson vtpci_write_dev_config(struct virtio_hw *hw, uint64_t offset,
65*6c3169a3SBruce Richardson 		void *src, int length)
66*6c3169a3SBruce Richardson {
67*6c3169a3SBruce Richardson 	uint64_t off;
68*6c3169a3SBruce Richardson 	uint8_t *s;
69*6c3169a3SBruce Richardson 	int size;
70*6c3169a3SBruce Richardson 
71*6c3169a3SBruce Richardson 	off = VIRTIO_PCI_CONFIG(hw) + offset;
72*6c3169a3SBruce Richardson 	for (s = src; length > 0; s += size, off += size, length -= size) {
73*6c3169a3SBruce Richardson 		if (length >= 4) {
74*6c3169a3SBruce Richardson 			size = 4;
75*6c3169a3SBruce Richardson 			VIRTIO_WRITE_REG_4(hw, off, *(uint32_t *)s);
76*6c3169a3SBruce Richardson 		} else if (length >= 2) {
77*6c3169a3SBruce Richardson 			size = 2;
78*6c3169a3SBruce Richardson 			VIRTIO_WRITE_REG_2(hw, off, *(uint16_t *)s);
79*6c3169a3SBruce Richardson 		} else {
80*6c3169a3SBruce Richardson 			size = 1;
81*6c3169a3SBruce Richardson 			VIRTIO_WRITE_REG_1(hw, off, *s);
82*6c3169a3SBruce Richardson 		}
83*6c3169a3SBruce Richardson 	}
84*6c3169a3SBruce Richardson }
85*6c3169a3SBruce Richardson 
86*6c3169a3SBruce Richardson uint32_t
87*6c3169a3SBruce Richardson vtpci_negotiate_features(struct virtio_hw *hw, uint32_t host_features)
88*6c3169a3SBruce Richardson {
89*6c3169a3SBruce Richardson 	uint32_t features;
90*6c3169a3SBruce Richardson 	/*
91*6c3169a3SBruce Richardson 	 * Limit negotiated features to what the driver, virtqueue, and
92*6c3169a3SBruce Richardson 	 * host all support.
93*6c3169a3SBruce Richardson 	 */
94*6c3169a3SBruce Richardson 	features = host_features & hw->guest_features;
95*6c3169a3SBruce Richardson 
96*6c3169a3SBruce Richardson 	VIRTIO_WRITE_REG_4(hw, VIRTIO_PCI_GUEST_FEATURES, features);
97*6c3169a3SBruce Richardson 	return features;
98*6c3169a3SBruce Richardson }
99*6c3169a3SBruce Richardson 
100*6c3169a3SBruce Richardson 
101*6c3169a3SBruce Richardson void
102*6c3169a3SBruce Richardson vtpci_reset(struct virtio_hw *hw)
103*6c3169a3SBruce Richardson {
104*6c3169a3SBruce Richardson 	/*
105*6c3169a3SBruce Richardson 	 * Setting the status to RESET sets the host device to
106*6c3169a3SBruce Richardson 	 * the original, uninitialized state.
107*6c3169a3SBruce Richardson 	 */
108*6c3169a3SBruce Richardson 	vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_RESET);
109*6c3169a3SBruce Richardson 	vtpci_get_status(hw);
110*6c3169a3SBruce Richardson }
111*6c3169a3SBruce Richardson 
112*6c3169a3SBruce Richardson void
113*6c3169a3SBruce Richardson vtpci_reinit_complete(struct virtio_hw *hw)
114*6c3169a3SBruce Richardson {
115*6c3169a3SBruce Richardson 	vtpci_set_status(hw, VIRTIO_CONFIG_STATUS_DRIVER_OK);
116*6c3169a3SBruce Richardson }
117*6c3169a3SBruce Richardson 
118*6c3169a3SBruce Richardson static uint8_t
119*6c3169a3SBruce Richardson vtpci_get_status(struct virtio_hw *hw)
120*6c3169a3SBruce Richardson {
121*6c3169a3SBruce Richardson 	return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_STATUS);
122*6c3169a3SBruce Richardson }
123*6c3169a3SBruce Richardson 
124*6c3169a3SBruce Richardson void
125*6c3169a3SBruce Richardson vtpci_set_status(struct virtio_hw *hw, uint8_t status)
126*6c3169a3SBruce Richardson {
127*6c3169a3SBruce Richardson 	if (status != VIRTIO_CONFIG_STATUS_RESET)
128*6c3169a3SBruce Richardson 		status = (uint8_t)(status | vtpci_get_status(hw));
129*6c3169a3SBruce Richardson 
130*6c3169a3SBruce Richardson 	VIRTIO_WRITE_REG_1(hw, VIRTIO_PCI_STATUS, status);
131*6c3169a3SBruce Richardson }
132*6c3169a3SBruce Richardson 
133*6c3169a3SBruce Richardson uint8_t
134*6c3169a3SBruce Richardson vtpci_isr(struct virtio_hw *hw)
135*6c3169a3SBruce Richardson {
136*6c3169a3SBruce Richardson 
137*6c3169a3SBruce Richardson 	return VIRTIO_READ_REG_1(hw, VIRTIO_PCI_ISR);
138*6c3169a3SBruce Richardson }
139*6c3169a3SBruce Richardson 
140*6c3169a3SBruce Richardson 
141*6c3169a3SBruce Richardson /* Enable one vector (0) for Link State Intrerrupt */
142*6c3169a3SBruce Richardson uint16_t
143*6c3169a3SBruce Richardson vtpci_irq_config(struct virtio_hw *hw, uint16_t vec)
144*6c3169a3SBruce Richardson {
145*6c3169a3SBruce Richardson 	VIRTIO_WRITE_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR, vec);
146*6c3169a3SBruce Richardson 	return VIRTIO_READ_REG_2(hw, VIRTIO_MSI_CONFIG_VECTOR);
147*6c3169a3SBruce Richardson }
148