1 /* 2 * Copyright (C) 2006 Michael Brown <mbrown (at) 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 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <stdint.h> 22 #include <errno.h> 23 #include <gpxe/malloc.h> 24 #include <gpxe/iobuf.h> 25 26 /** @file 27 * 28 * I/O buffers 29 * 30 */ 31 32 /** 33 * Allocate I/O buffer 34 * 35 * @v len Required length of buffer 36 * @ret iobuf I/O buffer, or NULL if none available 37 * 38 * The I/O buffer will be physically aligned to a multiple of 39 * @c IOBUF_SIZE. 40 */ 41 struct io_buffer * alloc_iob ( size_t len ) { 42 struct io_buffer *iobuf = NULL; 43 void *data; 44 45 /* Pad to minimum length */ 46 if ( len < IOB_ZLEN ) 47 len = IOB_ZLEN; 48 49 /* Align buffer length */ 50 len = ( len + __alignof__( *iobuf ) - 1 ) & 51 ~( __alignof__( *iobuf ) - 1 ); 52 53 /* Allocate memory for buffer plus descriptor */ 54 data = malloc_dma ( len + sizeof ( *iobuf ), IOB_ALIGN ); 55 if ( ! data ) 56 return NULL; 57 58 iobuf = ( struct io_buffer * ) ( data + len ); 59 iobuf->head = iobuf->data = iobuf->tail = data; 60 iobuf->end = iobuf; 61 return iobuf; 62 } 63 64 /** 65 * Free I/O buffer 66 * 67 * @v iobuf I/O buffer 68 */ 69 void free_iob ( struct io_buffer *iobuf ) { 70 if ( iobuf ) { 71 assert ( iobuf->head <= iobuf->data ); 72 assert ( iobuf->data <= iobuf->tail ); 73 assert ( iobuf->tail <= iobuf->end ); 74 free_dma ( iobuf->head, 75 ( iobuf->end - iobuf->head ) + sizeof ( *iobuf ) ); 76 } 77 } 78 79 /** 80 * Ensure I/O buffer has sufficient headroom 81 * 82 * @v iobuf I/O buffer 83 * @v len Required headroom 84 * 85 * This function currently only checks for the required headroom; it 86 * does not reallocate the I/O buffer if required. If we ever have a 87 * code path that requires this functionality, it's a fairly trivial 88 * change to make. 89 */ 90 int iob_ensure_headroom ( struct io_buffer *iobuf, size_t len ) { 91 92 if ( iob_headroom ( iobuf ) >= len ) 93 return 0; 94 return -ENOBUFS; 95 } 96 97