[tcp] Allow out-of-order receive queue to be discarded
[gpxe.git] / src / interface / efi / efi_io.c
blob0ba16f8f64299c11f4d949ae483fa0802508b7ec
1 /*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 FILE_LICENCE ( GPL2_OR_LATER );
21 #include <assert.h>
22 #include <gpxe/io.h>
23 #include <gpxe/efi/efi.h>
24 #include <gpxe/efi/Protocol/CpuIo.h>
25 #include <gpxe/efi/efi_io.h>
27 /** @file
29 * gPXE I/O API for EFI
33 /** CPU I/O protocol */
34 static EFI_CPU_IO_PROTOCOL *cpu_io;
35 EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
37 /** Maximum address that can be used for port I/O */
38 #define MAX_PORT_ADDRESS 0xffff
40 /**
41 * Determine whether or not address is a port I/O address
43 * @v io_addr I/O address
44 * @v is_port I/O address is a port I/O address
46 #define IS_PORT_ADDRESS(io_addr) \
47 ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
49 /**
50 * Determine EFI CPU I/O width code
52 * @v size Size of value
53 * @ret width EFI width code
55 * Someone at Intel clearly gets paid by the number of lines of code
56 * they write. No-one should ever be able to make I/O this
57 * convoluted. The EFI_CPU_IO_PROTOCOL_WIDTH enum is my favourite
58 * idiocy.
60 static EFI_CPU_IO_PROTOCOL_WIDTH efi_width ( size_t size ) {
61 switch ( size ) {
62 case 1 : return EfiCpuIoWidthFifoUint8;
63 case 2 : return EfiCpuIoWidthFifoUint16;
64 case 4 : return EfiCpuIoWidthFifoUint32;
65 case 8 : return EfiCpuIoWidthFifoUint64;
66 default :
67 assert ( 0 );
68 /* I wonder what this will actually do... */
69 return EfiCpuIoWidthMaximum;
73 /**
74 * Read from device
76 * @v io_addr I/O address
77 * @v size Size of value
78 * @ret data Value read
80 unsigned long long efi_ioread ( volatile void *io_addr, size_t size ) {
81 EFI_CPU_IO_PROTOCOL_IO_MEM read;
82 unsigned long long data = 0;
83 EFI_STATUS efirc;
85 read = ( IS_PORT_ADDRESS ( io_addr ) ?
86 cpu_io->Io.Read : cpu_io->Mem.Read );
88 if ( ( efirc = read ( cpu_io, efi_width ( size ),
89 ( intptr_t ) io_addr, 1,
90 ( void * ) &data ) ) != 0 ) {
91 DBG ( "EFI I/O read at %p failed: %s\n",
92 io_addr, efi_strerror ( efirc ) );
93 return -1ULL;
96 return data;
99 /**
100 * Write to device
102 * @v data Value to write
103 * @v io_addr I/O address
104 * @v size Size of value
106 void efi_iowrite ( unsigned long long data, volatile void *io_addr,
107 size_t size ) {
108 EFI_CPU_IO_PROTOCOL_IO_MEM write;
109 EFI_STATUS efirc;
111 write = ( IS_PORT_ADDRESS ( io_addr ) ?
112 cpu_io->Io.Write : cpu_io->Mem.Write );
114 if ( ( efirc = write ( cpu_io, efi_width ( size ),
115 ( intptr_t ) io_addr, 1,
116 ( void * ) &data ) ) != 0 ) {
117 DBG ( "EFI I/O write at %p failed: %s\n",
118 io_addr, efi_strerror ( efirc ) );
123 * String read from device
125 * @v io_addr I/O address
126 * @v data Data buffer
127 * @v size Size of values
128 * @v count Number of values to read
130 void efi_ioreads ( volatile void *io_addr, void *data,
131 size_t size, unsigned int count ) {
132 EFI_CPU_IO_PROTOCOL_IO_MEM read;
133 EFI_STATUS efirc;
135 read = ( IS_PORT_ADDRESS ( io_addr ) ?
136 cpu_io->Io.Read : cpu_io->Mem.Read );
138 if ( ( efirc = read ( cpu_io, efi_width ( size ),
139 ( intptr_t ) io_addr, count,
140 ( void * ) data ) ) != 0 ) {
141 DBG ( "EFI I/O string read at %p failed: %s\n",
142 io_addr, efi_strerror ( efirc ) );
147 * String write to device
149 * @v io_addr I/O address
150 * @v data Data buffer
151 * @v size Size of values
152 * @v count Number of values to write
154 void efi_iowrites ( volatile void *io_addr, const void *data,
155 size_t size, unsigned int count ) {
156 EFI_CPU_IO_PROTOCOL_IO_MEM write;
157 EFI_STATUS efirc;
159 write = ( IS_PORT_ADDRESS ( io_addr ) ?
160 cpu_io->Io.Write : cpu_io->Mem.Write );
162 if ( ( efirc = write ( cpu_io, efi_width ( size ),
163 ( intptr_t ) io_addr, count,
164 ( void * ) data ) ) != 0 ) {
165 DBG ( "EFI I/O write at %p failed: %s\n",
166 io_addr, efi_strerror ( efirc ) );
171 * Wait for I/O-mapped operation to complete
174 static void efi_iodelay ( void ) {
175 /* Write to non-existent port. Probably x86-only. */
176 outb ( 0, 0x80 );
179 PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
180 PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
181 PROVIDE_IOAPI_INLINE ( efi, ioremap );
182 PROVIDE_IOAPI_INLINE ( efi, iounmap );
183 PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
184 PROVIDE_IOAPI_INLINE ( efi, readb );
185 PROVIDE_IOAPI_INLINE ( efi, readw );
186 PROVIDE_IOAPI_INLINE ( efi, readl );
187 PROVIDE_IOAPI_INLINE ( efi, readq );
188 PROVIDE_IOAPI_INLINE ( efi, writeb );
189 PROVIDE_IOAPI_INLINE ( efi, writew );
190 PROVIDE_IOAPI_INLINE ( efi, writel );
191 PROVIDE_IOAPI_INLINE ( efi, writeq );
192 PROVIDE_IOAPI_INLINE ( efi, inb );
193 PROVIDE_IOAPI_INLINE ( efi, inw );
194 PROVIDE_IOAPI_INLINE ( efi, inl );
195 PROVIDE_IOAPI_INLINE ( efi, outb );
196 PROVIDE_IOAPI_INLINE ( efi, outw );
197 PROVIDE_IOAPI_INLINE ( efi, outl );
198 PROVIDE_IOAPI_INLINE ( efi, insb );
199 PROVIDE_IOAPI_INLINE ( efi, insw );
200 PROVIDE_IOAPI_INLINE ( efi, insl );
201 PROVIDE_IOAPI_INLINE ( efi, outsb );
202 PROVIDE_IOAPI_INLINE ( efi, outsw );
203 PROVIDE_IOAPI_INLINE ( efi, outsl );
204 PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
205 PROVIDE_IOAPI_INLINE ( efi, mb );