Desarrollo de controlador de dispositivo PCI bajo Linux

  
        

En primer lugar, la arquitectura del sistema de bus PCI

PCI es la abreviatura de Peripheral Component Interconnect, como un estándar general de interfaz de bus, se ha utilizado ampliamente en los sistemas informáticos actuales. Aplicacion PCI proporciona un conjunto completo de especificaciones de interfaz de bus con el fin de describir cómo los dispositivos periféricos en un sistema informático están conectados entre sí de manera estructurada y controlada, al tiempo que describen las propiedades eléctricas de los dispositivos periféricos cuando están conectados. Características y convenciones de comportamiento, y define en detalle cómo los diferentes componentes en un sistema informático deben interactuar correctamente.

Ya sea en una PC basada en Intel o en una estación de trabajo basada en Alpha, PCI es sin duda el estándar de interfaz de bus más utilizado. A diferencia del antiguo bus ISA, PCI separa completamente el subsistema de bus del subsistema de almacenamiento en el sistema informático. La CPU completa la interacción con el subsistema de bus a través de un dispositivo llamado PCI-Bridge, como se muestra en la Figura 1. Se muestra
Figura 1 Arquitectura del subsistema PCI

Debido a la mayor frecuencia de reloj, el bus PCI puede lograr un mejor rendimiento general que el bus ISA. La frecuencia de reloj del bus PCI está generalmente en el rango de 25MHz a 33MHz, y algunos incluso pueden alcanzar 66MHz o 133MHz, mientras que en sistemas de 64 bits, el máximo puede alcanzar 266MHz. Aunque los dispositivos PCI utilizan principalmente buses de datos de 32 bits, la implementación extendida de 64 bits se ha incluido en la especificación PCI, lo que hace que el bus PCI sea mejor independiente de la plataforma. Ahora, el bus PCI se puede usar para IA-32, Alpha. En la arquitectura de PowerPC, SPARC64 y IA-64.

El bus PCI tiene tres ventajas muy importantes, que le permiten cumplir la misión histórica de reemplazar eventualmente el bus ISA:

Mejor rendimiento al transferir datos entre computadoras y periféricos; Puede ser lo más independiente posible de una plataforma específica; plug and play se puede implementar fácilmente. La Figura 2 es un diagrama esquemático de un sistema informático típico basado en un bus PCI con varias partes del sistema conectadas por un bus PCI y un puente PCI-PCI. No es difícil ver en la figura que la CPU y la RAM deben conectarse al bus PCI 0 (es decir, el bus PCI principal) a través del puente PCI, y la tarjeta gráfica con la interfaz PCI puede conectarse directamente al bus PCI principal. El puente PCI-PCI es un dispositivo PCI especial que se encarga de conectar el bus PCI 0 y el bus PCI 1 (es decir, desde la línea principal de PCI). Por lo general, el bus PCI 1 se denomina flujo descendente del puente PCI-PCI y el bus PCI. 0 se llama el flujo ascendente del puente PCI-PCI. Conectadas al bus PCI esclavo en la figura están las tarjetas SCSI y las tarjetas Ethernet. Para ser compatible con el antiguo estándar de bus ISA, el bus PCI también se puede conectar al bus ISA a través de un puente PCI-ISA para admitir dispositivos ISA anteriores. Un controlador de E /S multifunción está conectado al bus ISA para controlar el teclado, el mouse y la unidad de disquete.
Figura 2 Diagrama del sistema PCI

Aquí solo doy una introducción general a la arquitectura del sistema de bus PCI, si el lector desea saber más, David A Rusling en El núcleo de Linux (http: //tldp. Org /LDP /tlk /dd /pci.html tiene una introducción más detallada al subsistema PCI de Linux.

En segundo lugar, el marco del controlador de Linux

Linux considera a todos los dispositivos externos como un tipo especial de archivo, llamado "archivo de dispositivo", si la llamada al sistema es el kernel y la aplicación de Linux La interfaz entre los programas, entonces el controlador del dispositivo puede verse como la interfaz entre el kernel de Linux y los dispositivos externos. El controlador del dispositivo protege a la aplicación de los detalles de implementación del hardware, lo que permite que la aplicación funcione con el dispositivo externo como si fuera un archivo normal.

1. Dispositivos de caracteres y dispositivos de bloque

Linux abstrae el procesamiento del hardware. Todos los dispositivos de hardware pueden verse como archivos normales: pueden usar el mismo estándar que los archivos de operación. El sistema llama a la interfaz para realizar operaciones de apertura, cierre, lectura y escritura, y control de E /S, y la tarea principal del controlador es implementar estas funciones de llamada al sistema. Todos los dispositivos de hardware en un sistema Linux están representados por un archivo de dispositivo especial. Por ejemplo, el primer disco duro IDE en el sistema está representado por /dev /hda. Cada archivo de dispositivo tiene dos números de dispositivo: uno es el número de dispositivo principal, identifica el tipo de dispositivo y también identifica el controlador utilizado por el dispositivo, y el otro es el número de dispositivo secundario, que identifica el hardware diferente que utiliza el mismo controlador de dispositivo. Equipo El número de dispositivo principal del archivo del dispositivo debe coincidir con el número de dispositivo principal que el controlador del dispositivo aplicó al iniciar sesión en el dispositivo; de lo contrario, el proceso del usuario no podrá acceder al controlador del dispositivo.

Hay dos tipos principales de archivos de dispositivo en el sistema operativo Linux: uno es un dispositivo de caracteres y el otro es un dispositivo de bloque. Un dispositivo de caracteres es un dispositivo que realiza operaciones de E /S una por una en unidades de bytes. Cuando se realiza una solicitud de lectura o escritura en un dispositivo de caracteres, la E /S de hardware real se produce inmediatamente. Generalmente, la memoria caché en el dispositivo de caracteres está disponible. No, y no admite el acceso aleatorio. El dispositivo de bloque utiliza una memoria del sistema como búfer. Cuando el proceso del usuario realiza una solicitud de lectura o escritura al dispositivo, el controlador primero verifica el contenido del búfer y si los datos del búfer pueden satisfacer la solicitud del usuario, se devuelven los datos correspondientes. De lo contrario, se llama a la función de solicitud correspondiente para realizar la operación de E /S real. El dispositivo de bloque está diseñado principalmente para dispositivos lentos, como discos, y su propósito es evitar gastar demasiado tiempo de CPU para esperar a que finalice la operación. En general, las tarjetas PCI suelen ser dispositivos de caracteres.

El número de dispositivo principal de todos los dispositivos de hardware que se han registrado (es decir, el controlador se ha cargado) se puede obtener del archivo /proc /devices. Utilice el comando mknod para crear un archivo de dispositivo del tipo especificado y asignarle los números de dispositivo mayor y menor correspondientes. Por ejemplo, el siguiente comando:

[root @ gary root] # mknod /dev /lp0 c 6 0

Se creará un dispositivo de caracteres con un número de dispositivo mayor de 6 y un número de dispositivo menor de 0. El archivo /dev /lp0. Cuando la aplicación realiza una llamada del sistema a un archivo de dispositivo, el kernel de Linux llama al controlador correspondiente de acuerdo con el tipo de dispositivo y el número de dispositivo principal del archivo de dispositivo, e ingresa al estado central desde el estado del usuario, y luego el controlador determina el dispositivo. El número de dispositivo menor, y finalmente completar la operación del hardware correspondiente.

2. Interfaz de controlador de dispositivo

El subsistema de E /S en Linux proporciona una interfaz de dispositivo estándar uniforme a otras partes del kernel, que es a través de include /linux /fs. La estructura de datos file_operations en h se realiza:

struct file_operations {

struct module * owner;

loff_t (* llseek) (struct file *, loff_t, int);

ssize_t (* read) (archivo de estructura *, char *, size_t, loff_t *);

ssize_t (* write) (archivo de estructura *, const char *, size_t, loff_t * );;

int (* readdir) (archivo struct *, void *, filldir_t);

unsigned int (* poll) (struct file *, struct poll_table_struct *);

int (* ioctl) (struct inode *, struct file *, unsigned int, unsigned long);

int (* mmap) (struct file *, struct vm_area_struct *);

Int (* abrir) (struct inode *, struct file *);

int (* flush) (struct file *);

int (* release) (struct inode *, struct file *);

int (* fsync) ( Struct file *, struct dentry *, int datasync);

int (* fasync) (int, struct file *, int);

int (* lock) (struct file *, int , struct file_lock *);

ssize_t (* readv) (struct file *, const struct iovec *, unsigned long, loff_t *);

ssize_t (* writev) (struct file *, Const struct iovec *, unsigned long, loff_t *);

ssize_t (* sendpage) (archivo struct *, struct page *, int, size_t, loff_t *, int);

sin signo largo (* get_unmapped_area) (struct file *, unsigned long,

unsigned long, unsigned long, unsigned long);

};

Cuando la aplicación crea un archivo de dispositivo como Al abrir, cerrar, leer, escribir, etc., el kernel de Linux accederá a las funciones proporcionadas por el controlador a través de la estructura de operación de archivos. Por ejemplo, cuando una aplicación realiza una operación de lectura en un archivo de dispositivo, el kernel llamará a la función de lectura en la estructura de operaciones de archivo.

Copyright © Conocimiento de Windows All Rights Reserved