source: bootcd/isolinux/syslinux-6.03/gpxe/src/interface/efi/efi_io.c

Last change on this file was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 5.5 KB
Line 
1/*
2 * Copyright (C) 2008 Michael Brown <mbrown@fensystems.co.uk>.
3 *
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.
8 *
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.
13 *
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.
17 */
18
19FILE_LICENCE ( GPL2_OR_LATER );
20
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>
26
27/** @file
28 *
29 * gPXE I/O API for EFI
30 *
31 */
32
33/** CPU I/O protocol */
34static EFI_CPU_IO_PROTOCOL *cpu_io;
35EFI_REQUIRE_PROTOCOL ( EFI_CPU_IO_PROTOCOL, &cpu_io );
36
37/** Maximum address that can be used for port I/O */
38#define MAX_PORT_ADDRESS 0xffff
39
40/**
41 * Determine whether or not address is a port I/O address
42 *
43 * @v io_addr           I/O address
44 * @v is_port           I/O address is a port I/O address
45 */
46#define IS_PORT_ADDRESS(io_addr) \
47        ( ( ( intptr_t ) (io_addr) ) <= MAX_PORT_ADDRESS )
48
49/**
50 * Determine EFI CPU I/O width code
51 *
52 * @v size              Size of value
53 * @ret width           EFI width code
54 *
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.
59 */
60static 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;
70        }
71}
72
73/**
74 * Read from device
75 *
76 * @v io_addr           I/O address
77 * @v size              Size of value
78 * @ret data            Value read
79 */
80unsigned 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;
84
85        read = ( IS_PORT_ADDRESS ( io_addr ) ?
86                 cpu_io->Io.Read : cpu_io->Mem.Read );
87
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;
94        }
95
96        return data;
97}
98
99/**
100 * Write to device
101 *
102 * @v data              Value to write
103 * @v io_addr           I/O address
104 * @v size              Size of value
105 */
106void 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;
110
111        write = ( IS_PORT_ADDRESS ( io_addr ) ?
112                  cpu_io->Io.Write : cpu_io->Mem.Write );
113
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 ) );
119        }
120}
121
122/**
123 * String read from device
124 *
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
129 */
130void 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;
134
135        read = ( IS_PORT_ADDRESS ( io_addr ) ?
136                 cpu_io->Io.Read : cpu_io->Mem.Read );
137
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 ) );
143        }
144}
145
146/**
147 * String write to device
148 *
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
153 */
154void 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;
158
159        write = ( IS_PORT_ADDRESS ( io_addr ) ?
160                 cpu_io->Io.Write : cpu_io->Mem.Write );
161
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 ) );
167        }
168}
169
170/**
171 * Wait for I/O-mapped operation to complete
172 *
173 */
174static void efi_iodelay ( void ) {
175        /* Write to non-existent port.  Probably x86-only. */
176        outb ( 0, 0x80 );
177}
178
179PROVIDE_IOAPI_INLINE ( efi, phys_to_bus );
180PROVIDE_IOAPI_INLINE ( efi, bus_to_phys );
181PROVIDE_IOAPI_INLINE ( efi, ioremap );
182PROVIDE_IOAPI_INLINE ( efi, iounmap );
183PROVIDE_IOAPI_INLINE ( efi, io_to_bus );
184PROVIDE_IOAPI_INLINE ( efi, readb );
185PROVIDE_IOAPI_INLINE ( efi, readw );
186PROVIDE_IOAPI_INLINE ( efi, readl );
187PROVIDE_IOAPI_INLINE ( efi, readq );
188PROVIDE_IOAPI_INLINE ( efi, writeb );
189PROVIDE_IOAPI_INLINE ( efi, writew );
190PROVIDE_IOAPI_INLINE ( efi, writel );
191PROVIDE_IOAPI_INLINE ( efi, writeq );
192PROVIDE_IOAPI_INLINE ( efi, inb );
193PROVIDE_IOAPI_INLINE ( efi, inw );
194PROVIDE_IOAPI_INLINE ( efi, inl );
195PROVIDE_IOAPI_INLINE ( efi, outb );
196PROVIDE_IOAPI_INLINE ( efi, outw );
197PROVIDE_IOAPI_INLINE ( efi, outl );
198PROVIDE_IOAPI_INLINE ( efi, insb );
199PROVIDE_IOAPI_INLINE ( efi, insw );
200PROVIDE_IOAPI_INLINE ( efi, insl );
201PROVIDE_IOAPI_INLINE ( efi, outsb );
202PROVIDE_IOAPI_INLINE ( efi, outsw );
203PROVIDE_IOAPI_INLINE ( efi, outsl );
204PROVIDE_IOAPI ( efi, iodelay, efi_iodelay );
205PROVIDE_IOAPI_INLINE ( efi, mb );
Note: See TracBrowser for help on using the repository browser.