00001 /**********************************************************/ 00002 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00003 /* 00004 Copyright: 1993 - Grupo de Voz (DAET) ETSII/IT-Bilbao 00005 00006 Nombre fuente................ LMEM.C 00007 Nombre paquete............... - 00008 Lenguaje fuente.............. C (Borland C/C++ 3.1) 00009 Estado....................... Completado 00010 Dependencia Hard/OS.......... Memoria segmentada 16:16 00011 Codigo condicional........... - 00012 00013 Codificacion................. Borja Etxebarria 00014 00015 Version dd/mm/aa Autor Proposito de la edicion 00016 ------- -------- -------- ----------------------- 00017 3.0.0 22/02/94 Borja unificacion 64kb y 128kb ---> {kbpage}, etc 00018 2.1.0 15/03/94 Borja permite enviar NULL en {lmem} y {usebytes} 00019 2.0.0 20/02/94 Borja funciones fixlen???() 00020 1.0.1 20/02/94 Borja incorporacion de {align} y {granularity} 00021 1.0.0 06/08/93 Borja Codificacion inicial. 00022 00023 ======================== Contenido ======================== 00024 Funciones fix??() para la adecuacion de bloques de memoria en 00025 operaciones de transferencia DMA. Utilizan los tipos y macros 00026 definidos en LMEM.H. 00027 Mirar LMEM.H para informacion sobre las macros definidas. 00028 .................... 00029 The fix??() functions are used to manage memory blocks 00030 adecuate for DMA transfer. They use types and macros defined 00031 in file LMEM.H. 00032 Refer to LMEM.H for more information about the defined macros. 00033 =========================================================== 00034 */ 00035 /*/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\*/ 00036 /**********************************************************/ 00037 00038 #include "lmem.h" 00039 00040 /**********************************************************/ 00041 /* pasa kb de kbytes a bytes */ 00042 00043 #define KB2B(kb) (((UINT32)(kb)) << 10) 00044 00045 /**********************************************************/ 00046 /* Recibe en {ptr} un puntero a un bloque de {nbytes} bytes de 00047 longitud. La funcion busca dentro de este bloque, el subbloque 00048 mas grande que no cruce una pagina de {kbpage} kilobytes (usar 00049 64kb para buffer DMA-8bits, o 128kb para DMA-16 bits), y {devuelve} 00050 un puntero a ese subbloque, y tambien devuelve este mismo puntero 00051 pero en memoria lineal (direccionamiento plano) en {lmem}. En {usebytes} 00052 se devuelve el numero de bytes que tiene el subbloque. 00053 Ademas, el buffer devuelto cumple las condiciones de estar alineado 00054 en un multiplo de {align} bytes, y de tener una longitud multiplo 00055 de {granularity}. 00056 Para asegurarse de que el buffer DMA devuelto 00057 tenga un numero N de elementos, utilizar un vector {ptr} con el doble 00058 de elementos (N*2 en {nbytes}). No tiene sentido enviar {nbytes} 00059 mayor que 2*{kbpage}kb, pues logicamente, {usebytes} sera 00060 {kbpage}kb como maximo. 00061 En {lmem} y {usebytes} se puede enviar NULL si no interesa alguno 00062 de estos valores. 00063 .................... 00064 This function receives in {ptr} a pointer to a memory block of length 00065 {nbytes}. The function will search in this memory block the largest 00066 sub-block valid for DMA transfers. The DMA transfer condition will be 00067 the following: the buffer must not cross a {kbpage} kilobytes memory 00068 page (use {kbpage}=64 for DMA8 and {kbpage}=128 for DMA16). 00069 The function {returns} a pointer to this usable buffer. It will also 00070 return this same pointer in {lmem} but using 32bit lineal memory format. 00071 In {usebytes} the function returns the block length in bytes of the 00072 usable buffer. 00073 Moreover, the returned buffer will be memory-aligned to a multiple of 00074 {align} (you can send 1 for DMA8, and 2 for DMA16), and it's length 00075 will be a multiple of {granularity}. 00076 00077 If you want to assure that the usable DMA buffer will be N bytes 00078 length, you can allocate ({ptr}) a memory block of N*2 bytes ({nbytes}). 00079 It's a nonsense to send a buffer with {nbytes} > 2*{kbpage}*1024 00080 as the maximum value for {usebytes} will be {kbpage}*1024. 00081 You can send NULL in {lmem} and {usebytes} if you are not interested 00082 in any of this values. */ 00083 00084 pfVOID fixmem( pfVOID ptr, UINT32 nbytes, UINT16 kbpage, UINT32 align, 00085 UINT32 granularity, UINT32 * lmem, UINT32 * usebytes ) 00086 { 00087 UINT32 lm, lm2, bpage, tmp, lmem2, page; 00088 00089 page = KB2B(kbpage); 00090 if (nbytes > (page<<1)) /* limita nbytes a 2*page */ 00091 nbytes = (page << 1); 00092 if (!align) /* el alineamiento minimo es 1 */ 00093 align = 1; 00094 if (!granularity) /* la granularidad minima es 1 */ 00095 granularity = 1; 00096 00097 lm = PTR2LMEM(ptr); /* convierte a puntero lineal */ 00098 tmp = (align - (lm % align)) % align; /* correccion de alineamiento */ 00099 lm += tmp; 00100 nbytes -= tmp; 00101 00102 /* busca siguiente cambio de {page} bytes */ 00103 bpage = ((lm + page) / page) * page; 00104 lm2 = bpage + (align - (bpage % align)) % align; /* alineamiento */ 00105 tmp = bpage - lm; /* longitud primer bloque */ 00106 00107 if (tmp >= (nbytes >> 1)) { /*primera parte mayor que la mitad*/ 00108 lmem2 = lm; /* usa la primera parte */ 00109 if (nbytes > tmp) /* fija longitud a usar */ 00110 nbytes = tmp; 00111 } 00112 else { 00113 lmem2 = lm2; /* usa la segunda parte */ 00114 nbytes -= (lm2 - lm); /* y olvida la primera */ 00115 } 00116 if (nbytes > page) 00117 nbytes = page; 00118 00119 /* vector a usar */ 00120 if (lmem) 00121 *lmem = lmem2; 00122 /* longitud a usar, teniendo en cuenta la granularidad */ 00123 if (usebytes) 00124 *usebytes = nbytes - (nbytes % granularity); 00125 return LMEM2PTR(lmem2); /* devuelve puntero al bloque utilizable */ 00126 } 00127 00128 /**********************************************************/ 00129 /* similar a fixmem() solo que {devuelve} directamente la longitud 00130 utilizable comenzando en el propio {ptr}, si el buffer tiene 00131 {nbytes} bytes, no debe cruzar una pagina de {kbpage} kbytes y debe 00132 cumplir estar alineado a {align} y con granularidad {granularity} 00133 .................... 00134 this function is similar to fixmem() but it will directly {return} 00135 the usable length from the first byte pointed by {ptr}. The 00136 whole buffer is {nbytes} long. The usable buffer will not cross 00137 a {kbpage} kilobytes memory page (send 64 for DMA8 or 128 for DMA16). 00138 The buffer should be aligned to {align} bytes, and the granularity 00139 will be {granularity} */ 00140 00141 UINT32 fixlen( pfVOID ptr, UINT32 nbytes, UINT16 kbpage, UINT32 align, 00142 UINT32 granularity ) 00143 { 00144 UINT32 lm, bpage, tmp, page; 00145 00146 page = KB2B(kbpage); 00147 if (!align) /* el alineamiento minimo es 1 */ 00148 align = 1; 00149 if (!granularity) /* la granularidad minima es 1 */ 00150 granularity = 1; 00151 00152 lm = PTR2LMEM(ptr); /* convierte a puntero lineal */ 00153 tmp = lm % align; /* alineamiento */ 00154 if (!tmp) { /* si esta alineado */ 00155 bpage = ((lm + page) / page) * page; /* siguientes 64k */ 00156 tmp = bpage - lm; /* longitud primera parte */ 00157 if (tmp > nbytes) /* fija longitud a usar */ 00158 tmp = nbytes; 00159 } 00160 00161 /* {devuelve} longitud a usar, teniendo en cuenta la granularidad */ 00162 return (tmp - (tmp % granularity)); 00163 } 00164 00165 /**********************************************************/ 00166