Compartir a través de


Escritura de controladores de audio de 64 bits

Si está escribiendo un controlador de 64 bits o escribiendo un controlador que se puede compilar para ejecutarse en sistemas de 32 y 64 bits, siga las directrices de portabilidad en Técnicas de programación de controladores. A continuación se describen algunos de los problemas que puede encontrar al escribir un controlador de audio de 64 bits.

En primer lugar, un posible problema para buscar en el código de controlador de 32 bits existente es la conversión entre tipos de puntero y tipos enteros, como DWORD o ULONG. Es posible que los programadores con experiencia en la escritura de código para máquinas de 32 bits se usen para asumir que un valor de puntero se ajusta a un DWORD o ULONG. Para el código de 64 bits, esta suposición es peligrosa. La conversión de un puntero al tipo DWORD o ULONG puede hacer que se trunque un puntero de 64 bits. Un mejor enfoque consiste en convertir el puntero al tipo DWORD_PTR o ULONG_PTR. Un entero sin signo de tipo DWORD_PTR o ULONG_PTR siempre es lo suficientemente grande como para almacenar todo el puntero, independientemente de si el código se compila para una máquina de 32 o 64 bits.

Por ejemplo, el campo de puntero IRPIoStatus. La información es de tipo ULONG_PTR. En el código siguiente se muestra lo que no se debe hacer al copiar un valor de puntero de 64 bits en este campo:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG)pDeviceRelations;  // wrong

Este ejemplo de código convierte erróneamente el pDeviceRelations puntero al tipo ULONG, que puede truncar el valor del puntero si sizeof(pDeviceRelations) > sizeof(ULONG). El enfoque correcto consiste en convertir el puntero en ULONG_PTR, como se muestra en lo siguiente:

    PDEVICE_RELATIONS pDeviceRelations;
    Irp->IoStatus.Information = (ULONG_PTR)pDeviceRelations;  // correct

Esto conserva los 64 bits del valor de puntero.

Una lista de recursos almacena la dirección física de un recurso en una estructura de tipo PHYSICAL_ADDRESS (consulte IResourceList). Para evitar truncar una dirección de 64 bits, debe tener acceso al miembro QuadPart de la estructura en lugar de a su miembro LowPart al copiar una dirección en la estructura o leer una dirección de la estructura. Por ejemplo, la macro FindTranslatedPort devuelve un puntero a una estructura de CM_PARTIAL_RESOURCE_DESCRIPTOR que contiene la dirección base de un puerto de E/S. U.Puerto. El miembro Start de esta estructura es un puntero PHYSICAL_ADDRESS a la dirección base. En el código siguiente se muestra lo que no se debe hacer:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.LowPart;  // wrong

De nuevo, esto puede truncar el puntero. En su lugar, debe acceder al QuadPart de este miembro, como se muestra en lo siguiente:

    PUSHORT pBase = (PUSHORT)FindTranslatedPort(0)->u.Port.Start.QuadPart;  // correct

Esto copia el puntero de 64 bits completo.

Las funciones Win64 insertadas, como PtrToUlong y UlongToPtr , convierten de forma segura entre tipos de puntero e entero sin depender de suposiciones sobre los tamaños relativos de estos tipos. Si un tipo es más corto que el otro, se debe extender al convertir al tipo más largo. Si el tipo más corto se extiende rellenando con el bit de signo o con ceros está bien definido para cada función Win64. Esto significa que cualquier fragmento de código, como

    ULONG ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = ULONG(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // wrong

debe reemplazarse por

    ULONG_PTR ulSlotPhysAddr[NUM_PHYS_ADDRS];
    ulSlotPhysAddr[0] = PtrToUlong(pulPhysDmaBuffer) + DMA_BUFFER_SIZE;  // correct

Esto es preferible aunque ulSlotPhysAddr podría representar el valor de un registro de hardware que solo es de 32 en lugar de 64 bits de longitud. Para obtener una lista de todas las nuevas funciones auxiliares de Win64 para la conversión entre tipos de puntero e entero, consulta Los nuevos tipos de datos.