Desarrollo de software de control para acceso a discos duros SATA TITULACIÓN: Ingeniería Técnica Industrial en Electrónica Industrial AUTOR: Mohamed Anaimi DIRECTOR: Esteban del Castillo Pérez FECHA: Septiembre del 2010 Índice 1 Introducción .................................................................................................5 2 Objetivo.........................................................................................................7 3 Especificaciones previas ..............................................................................8 4 Antecedentes.................................................................................................9 4.1 La evolución de los discos ............................................................................... 9 4.2 Elementos que hacen posible el funcionamiento del disco SATA ............. 13 4.2.1 Ordenador............................................................................................................ 13 4.2.2 Disco SATA: ........................................................................................................ 13 4.2.3 Advanced Host Controller Interface (AHCI) ..................................................... 14 4.3 Interfaz de usuario (parte gráfica)............................................................... 15 4.4 Beneficios del programa de gestión del disco.............................................. 16 5 Análisis previo ............................................................................................17 6 Disco SATA.................................................................................................18 6.1 El Hardware (el nivel físico) ......................................................................... 18 6.1.1 6.1.2 6.1.3 6.1.4 Spread Spectrum Clocking.................................................................................. 18 Cables y Conectores ............................................................................................ 18 Señales OOB (Out Of Band).............................................................................. 20 Secuencia de inicialización del phy ................................................................... 21 6.2 El nivel de Enlace........................................................................................... 21 6.2.1 Codificación 8b10b: Caracteres de datos, caracteres de control y patrón Coma ........................................................................................................................................ 21 6.2.2 Primitivas y Tramas ............................................................................................ 23 6.3 El nivel de Transporte................................................................................... 25 6.3.1 Modos de transferencia ....................................................................................... 25 6.3.1.1 Programmed I/O ............................................................................................ 26 6.3.1.2 DMA .............................................................................................................. 27 6.3.1.3 ULTRA DMA................................................................................................ 30 6.3.2 Los registros Shadow .......................................................................................... 32 6.3.2.1 Registro de comandos .................................................................................... 33 6.3.2.2 Puerto de datos............................................................................................... 34 6.3.2.3 Registro de datos............................................................................................ 35 6.3.2.4 Registro del dispositivo ................................................................................. 36 6.3.2.5 Registro de control del dispositivo ................................................................ 37 6.3.2.6 Registro de errores ......................................................................................... 38 6.3.2.7 Registro de características.............................................................................. 39 6.3.2.8 LBA alto ........................................................................................................ 40 6.3.2.9 LBA bajo........................................................................................................ 41 6.3.2.10 LBA medio .................................................................................................. 42 6.3.2.11 Registro de cuenta de sectores ..................................................................... 43 2 6.3.2.12 Registro de estado ........................................................................................ 44 6.3.2.13 Registro de estado alternativo...................................................................... 45 6.3.3 FIS (Frame Information Structure)................................................................... 46 6.3.4 Nuevo bloque de registros SATA ........................................................................ 47 6.3.5 Direccionamiento 48-bit...................................................................................... 48 6.3.6 Descripción de comandos.................................................................................... 50 6.3.5.1 Read Sectors .................................................................................................. 50 6.3.5.2 Read Sectors EXT.......................................................................................... 53 6.3.5.3 Write Sectors.................................................................................................. 55 6.3.5.4 Write Sectors EXT......................................................................................... 57 6.3.5.5 Read multiple................................................................................................. 59 6.3.5.6 Read multiple EXT ........................................................................................ 61 6.3.5.7 Write multiple ................................................................................................ 62 6.3.5.8 Write multiple EXT ....................................................................................... 65 6.3.5.9 Read DMA..................................................................................................... 66 6.3.5.10 Read DMA EXT .......................................................................................... 68 6.3.5.11 Write DMA .................................................................................................. 69 6.3.5.12 Write DMA EXT ......................................................................................... 71 6.3.5.13 Identify Device ............................................................................................ 72 6.3.5.14 Device reset.................................................................................................. 74 6.4 SATA II .......................................................................................................... 75 6.4.1 6.4.2 6.4.3 6.4.4 Extensiones de SATA .......................................................................................... 75 Multiplicador de Puertos..................................................................................... 75 Selector de Puerto................................................................................................ 76 Cables y Conectores ............................................................................................ 76 7 El lenguaje de programación C ................................................................77 8 Desarrollo del software..............................................................................79 8.1 Parte gráfica: ................................................................................................. 80 8.2 Parte funcional: ............................................................................................. 83 8.3 Pasos para la realización del software ......................................................... 86 9 Resultados finales.......................................................................................88 9.1 9.2 9.3 9.4 9.4 La función Editar .......................................................................................... 88 La opción Copiar ........................................................................................... 89 La opción Comparar ..................................................................................... 90 La opción Buscar ........................................................................................... 91 La opción Configurar.................................................................................... 92 10 Manual de instalación y uso....................................................................93 10.1 Instalación del disco duro SATA................................................................ 93 10.2 Instalación del sistema operativo MS-DOS............................................... 94 11 Presupuesto...............................................................................................96 12 Conclusiones .............................................................................................97 13 Bibliografía y referencias ........................................................................98 13.1 Referencias ................................................................................................... 98 13.2 Bibliografía................................................................................................... 98 3 14 Anexo.........................................................................................................99 14.1 Comandos..................................................................................................... 99 14.2 contenido de la respuesta al comando Identify device ............................ 101 14.3 Diferentes rutinas extraídas del código ................................................... 106 14.3.1 14.3.2 14.3.3 14.3.4 14.3.5 14.3.6 La función Disk_access48( )........................................................................... 106 La función x_disco48( ) .................................................................................. 110 La función main( ) .......................................................................................... 113 La rutina de atención a la interrupción ......................................................... 115 La función SetIdeDriver( ).............................................................................. 120 La función de obtención del valor tecleado.................................................... 122 4 1 Introducción Mediante la realización de este proyecto se pretende obtener una aplicación que permita el acceso a discos duros del tipo SATA1. La aplicación nos permitirá realizar operaciones de búsqueda, copia, comparación y edición sobre cualquier parte de cualquier disco duro, de este tipo o compatible, accesible en el sistema. El usuario podrá ver la información del disco en bits i código ASCII2. El acceso será del más bajo nivel posible, puesto que el consumidor podrá editar cualquier bit de los sectores del disco. Este software puede ser útil para restablecer información alterada en el disco duro, de forma que pueda ser reconocido de nuevo por el sistema operativo quedando accesible su información (recuperación de información), para realizar copias de seguridad con idéntico contenido (copia imagen), para realizar búsqueda de patrones (que permita localizar ficheros posiblemente borrados), etc Actualmente se comercializan muchas aplicaciones para Windows que permiten hacer esta tarea. El inconveniente de estas es que en caso de fallo del sistema operativo, el disco duro queda totalmente aislado y por tanto el acceso será imposible. Una ventaja de este programa es que opera bajo DOS3. Esto permite un rápido acceso a las herramientas desarrolladas en este proyecto y las hace independientes de cualquier sistema operativo instalado en el disco dañado. Las funciones principales del programa están explicas en el apartado Resultados finales. ATA paralela significa conexión de tecnología avanzada en paralelo, del inglés Parallel Advanced Technology Attachment (PATA). Ha sido la interfaz de las unidades de disco duro de los ordenadores de sobremesa durante más de 15 años. ATA paralela se puede encontrar en ordenadores de sobremesa, portátiles, electrónica de consumo y algunos servidores actuales. Aún existe gran cantidad de unidades de disco duro PATA en el mercado. Hasta que se produzca la total transición de paralelo a serie, muchos ordenadores seguirán utilizando las unidades de disco ATA paralela. La interfaz ATA serie (SATA) se diseñó para ser la sustituta de la interfaz ATA paralela en los sistemas de almacenamiento de red, ordenadores de sobremesa, ordenadores portátil y electrónica de consumo. SATA permite trasladar más datos en menos tiempo, lo que aumenta el rendimiento y la flexibilidad. La cola de comandos nativa, una de las características clave de SATA, hace posible ordenar y dar prioridad a varios comandos al mismo tiempo, y reducir el desgaste mecánico de la unidad. Otras características, como la conexión en caliente, la aceleración de giro escalonada y la velocidad de transferencia rápida de 3 Gb/s, hacen de SATA la elección perfecta para servidores, estaciones de trabajo, ordenadores de sobremesa, dispositivos de electrónica de consumo y ordenadores portátiles. 1 Véase el apartado 6.0 para ver la definición y las características de los discos SATA. El código ASCII (acrónimo inglés de American Standard Code for Information Interchange) es un código de caracteres basado en el alfabeto latino. Fue creado en 1963. el código ASCII utiliza 7 bits para representar los caracteres. 3 "DOS" es una familia de sistemas operativos para PC. 2 5 Tal y como hemos sido testigos durante estos últimos años, y al mismo ritmo que han ido creciendo las prestaciones de los discos duros, los canales de comunicación por los que circula la información entre estos y el resto del sistema ha ido sufriendo una paulatina y en el mismo tiempo una imprescindible modernización, acorde con el cada vez mayor caudal de datos en tránsito entre ambos extremos de la comunicación: host y disco duro. Esta aplicación ya fue desarrollada, por el profesor Esteban del Castillo, para discos Parallel ATA de hasta 137 Gigabytes de memoria. Nuestro objetivo será aprovechar la misma aplicación y mejorarla para acceder a discos Serial ATA con una limitación de memoria mucho más superior. Para eso se tendrá que adecuar el programa de tal forma que no se vea afectado por la enorme evolución de la capacidad de los discos duros permitiendo el correcto funcionamiento del mismo con dispositivos cuyas prestaciones son mejores que los actuales. Más adelante se hará una explicación detallada de la arquitectura de los discos SATA tanto a nivel físico y eléctrico como a nivel lógico. Esto será el punto de partida para entender las diferencias que hay respecto a los discos PATA. Es importante destacar que gracias a organismos como ‘Technical Committee T13’ o bien ‘Serial ATA International Organisation’ se ha hecho posible mantener una cierta compatibilidad entre los diferentes tipos de discos pese la complejidad de las interfaces. Quizá el paso más significante es la conservación de elementos, en las especificaciones del Serial ATA, que permiten el funcionamiento del ATA paralelo. El controlador SATA por un lado emula el funcionamiento de un interfaz ATA estándar, lo que permite a los programas BIOS y drivers actuales (denominados genéricamente software Heredado) acceder a los dispositivos SATA como si se trataran de dispositivos estándar ATA, y por otro implementa nuevos recursos para permitir que drivers SATA de nuevo desarrollo (software Nativo) puedan acceder a las nuevas funcionalidades y posibilidades del interfaz SATA. Para la realización de este proyecto vamos a tener que programar tanto a alto nivel (C) como a bajo nivel (ensamblador). Afortunadamente disponemos de una herramienta sencilla de programación (Borland C) que permite enlazar ficheros de los dos tipos y generar el ejecutable (.exe) deseado para Disk Operating System. 6 2 Objetivo El objetivo principal de este proyecto es la realización de una aplicación que permita el acceso directo del usuario a los discos duros SATA. La aplicación está diseñada tanto para usuarios con pocos conocimientos de informática como para programadores y personal de mantenimiento. Para realizar dicho proyecto se conseguirán otros dos objetivos didácticos: el primero es el conocimiento de los dispositivos de almacenamiento masivo, para conseguir esta información se consultarán manuales de fabricantes, documentos de especificaciones y también estándares publicados. El otro objetivo tiene que ver con la aplicación de los conocimientos adquiridos con los estudios de la carrera. Se trata de la profundización en la programación en lenguaje C sobre plataforma PC. Esto hace de este proyecto un importante complemento de formación, y posiblemente una continuación de la asignatura INFORMATICA INDUSTRIAL II. 7 3 Especificaciones previas Para la realización de este proyecto se marcaran las siguientes especificaciones previas: • El software debe desarrollarse en lenguaje de programación C. • Como paso previo, la realización de un código con una interfaz simple de lectura y escritura en el disco. • Se tendrá que mantener la compatibilidad con el programa original. • Se debe utilizar la interfaz facilitada y adecuarla para cantidades superiores de memoria. • Las modificaciones hechas en el programa original no deben afectar en ningún caso las funciones ya implementadas. El lenguaje de programación para este proyecto será el C, un código de fácil manejo con gran compatibilidad con muchos PCs. Este código permite programar tanto a alto nivel como a bajo nivel. Es importante destacar que se incluye en el proyecto un fichero hecho en lenguaje ensamblador, este último es para el manejo de las interrupciones donde es imprescindible la reducción de los tiempos de ejecución del código. El código que se tiene que realizar en la fase previa es totalmente orientativo. Podemos decir que es una introducción a una aplicación práctica de los conocimientos adquiridos de los manuales de especificaciones de los discos duros. En este caso no importa la parte grafica (interfaz de usuario) sino la parte funcional. Conseguir una simple lectura y escritura de un sector nos abrirá muchas puertas en el entendimiento de los diferentes métodos de acceso a estas unidades de almacenamiento. Las especificaciones anteriores se basan en la idea de hacer un programa para gestión de los diferentes tipos de discos duros que podemos encontrar en el mercado hoy en día. En el mismo tiempo se hace una prevención de posibles detalles de futuros avances en los discos duros como ahora el volumen de estos, un ámbito que avanza de forma brutal. Vista la gran evolución de las capacidades de los discos duros, nos vemos obligados a modificar la interfaz de usuario para una correcta visualización del número de sectores del disco y el tamaño de este. El número de sectores a los que se pueden acceder superará pronto el límite de tamaño de las variables que se pueden definir en C. 8 4 Antecedentes 4.1 La evolución de los discos En 1957, se introdujo como un componente de IBM RAMAC la primera unidad de discos duros. Requirió 50 discos de 24 pulgadas para guardar cinco megabytes (millón bytes, se abrevió MB) de datos y costó US$35.000 por año o arrendarlo a US$7.000 por megabyte anual. Fue el primer ordenador comercial que utilizaba disco duro de cabeza móvil (unidad de disco magnético) como almacenamiento secundario. IBM lo lanzó el 4 de septiembre de 1956. RAMAC eran las iniciales en inglés de "Sistema de Contabilidad con Memoria de Acceso Aleatorio" ("Random Access Memory ACcounting System" . Su diseño estuvo motivado por la necesidad de sustituir el fichero de tarjetas perforadas utilizado por la mayoría de las oficinas de la época. El primer RAMAC destinado a ser usado en la industria del automóvil estadounidense fue instalado en la Chrysler's MOPAR Division en 1957. Sustituyó a un gigantesco fichero que era parte del sistema de procesamiento para el control de inventario y pedidos de piezas de MOPAR. El 305 fue uno de los últimos ordenadores de tubo de vacío construídos por IBM. El sistema de disco IBM 350 almacenaba cinco millones de caracteres de siete bits (aproximadamente 4,2 MiB). Tenía cincuenta discos de veinticuatro pulgadas de diámetro. Dos brazos independientes se desplazaban verticalmente seleccionar un disco y horizontalmente para seleccionar una pista de grabación, todo para control de servomecanismos. El tiempo medio de posicionamiento en un registro era de seiscientos milisegundos. En la década de 1950 se añadieron varios modelos mejorados. El ordenador IBM RAMAC 305 con almacenamiento en disco 350 tenía un coste en "leasing" de 3.200 dólares mensuales en dólares de 1957, equivalente a un precio de compra de unos 160.000 dólares. Se construyeron más de 1.000 unidades. La producción terminó en 1961, el RAMAC pasó a ser obsoleto en 1962 con el lanzamiento del IBM 1401 y retirado del mercado en 1969. En el 1962 IBM introdujo un nuevo modelo, el 1301, con una capacidad de 28 MB y una velocidad de transferencia y una densidad de área 10 veces mayor que el RAMAC 305. La distancia entre los cabezales y la superficie del disco había descendido desde 20,32 µm a 6,35 µm. A partir del año 1962, muchos fabricantes comenzaron a vender discos duros como el 1301. La Unidad de almacenamiento en disco de IBM, con su mayor capacidad, flexibilidad y velocidad, se ha ampliado la capacidad operativa de la serie 7000 de los ordenadores de IBM (7070, 7094, 7080 y 7090). 9 Figura 1. El modelo 1301 con 28MB de memoria Utilizado en combinación con la serie 7000, el 1301 había muchos de los mismos y las características físicas generales de funcionamiento como cuando se utiliza con el IBM 1410 Data Processing System. Estas características incluyen: el concepto del cilindro (verticalmente alineados de lectura / escritura cabezas, una a una superficie del disco, para proporcionar la lectura y escritura de información en temas relacionados con el disco correspondiente y para eliminar la necesidad de acceso para el movimiento vertical); longitud de registro flexibles (diferentes registros de longitud podría ser almacenados en el archivo, aumentando enormemente la capacidad de almacenamiento real); y selectiva frente (números de registro fueron asignados por el usuario para una mayor eficacia en muchos puestos de trabajo, las direcciones no tienen que ser consecutivos, secuencial o numérico). El 1301 de los discos giran a 1.800 rpm. El 1301 proporcionó las 50 pistas por pulgada y grabación de hasta 520 bits por pulgada de pista (gracias a una reducción media en la cabeza-a-distancia de la superficie de 800 a 250 micropulgadas). Como resultado, la capacidad de almacenamiento por pulgada cuadrada de la superficie se incrementó 13 veces más de lo que había sido con la tecnología de IBM RAMAC de 1956. El Modelo 1 de la 1301 había un módulo, el Modelo 2 con dos módulos. Módulo de la capacidad de la 1301 utilizadas con 7000 equipos de la serie fue de 28 millones de caracteres, que se utiliza con el equipo del 1410, la capacidad del módulo fue de 25 millones de caracteres. Hasta el 10 módulos (cinco unidades de 1301) podría ser incorporada - 7631 utilizando el archivo de la unidad de control de IBM, y en algunos casos, los adaptadores y los canales de datos - a un sistema informático, proporcionando una capacidad máxima de 280 millones de caracteres de la serie 7000 máquina y 250 millones para el 1410. 10 Fabricado en la planta de IBM en San José, California, los 1301s fueron entregados a los clientes en el tercer trimestre de 1962. (A pocos días antes del 1301 se anunció oficialmente en junio de 1961, un modelo de ingeniería del 1301 fue enviado a IBM en Poughkeepsie, NY, instalaciones para el uso en las pruebas del famoso sistema SABRE reserva. Más tarde, en pleno funcionamiento, el sistema SABRE adjunta seis tambores magnéticos de almacenamiento y 16 de IBM 1301s.) El Modelo 1 con un costo módulo de $ 2.100 por mes para alquilar o podrían ser comprados por 115.500 dólares. El Modelo 2 con dos módulos de un costo de $ 3.500 por mes para alquilar o 185.500 dólares a la compra. Figura 2. El modelo 2310 En 1965, IBM lanzó el modelo 2310, cuya notable característica era ser un elemento de almacenamiento desmontable (el primer disco flexible). En abril de 1967, IBM anunció una expansión de cuatro modo de sistema de 1130. Nuevas características para el escritorio de computadora del tamaño de IBM más pequeño a la vez, incluyó la capacidad de leer la información de cinco discos magnéticos al mismo tiempo. Anteriormente, sólo un equipo autónomo de disco (primer plano) estaba disponible. Sin embargo, en 1967, hasta cuatro discos adicionales (a la derecha, parte trasera) se podría agregar. Cada uno puede almacenar hasta un millón de caracteres de información. El 2314, lanzado en 1966, tenía cabezales de lectura de ferrita (óxido de hierro). Anunció un año después de la System/360 en abril de 1965, el IBM 2314 proporcionó ocho unidades de disco y una de repuesto, junto con una unidad de control en una misma instalación. Un paquete nuevo disco con 11 discos duplicó el número de superficies de almacenamiento de más de los disponibles en el paquete de la primera de 11 disco extraíble. La densidad de grabación el incremento de la capacidad de almacenamiento de 29,2 millones de bytes por paquete o 233 millones de bytes en las ocho instalaciones de carga. El tiempo de acceso y la latencia de la 2314 era la misma que la de más edad de IBM 2311, pero el 2314 ofrece el doble de la velocidad de datos de 310.000 bytes por segundo. El 2314 también fue interesante porque era cuatro veces menor en el precio por megabyte de almacenamiento. Ayudado por OS/360 - s el IBM S/360 'del sistema operativo - el 2314 grandes bases de datos les permite tener acceso, y el sistema pasó de un trabajo a otro de forma automática siempre y cuando las instrucciones necesarias y los datos fueron en línea. Algunos observadores han dicho que OS/360 ayudado a hacer del 2314 el producto de almacenamiento más rentable que el tiempo y que el 2314 ha contribuido al éxito de la IBM S/360. En enero de 1969, IBM anunció dos nuevas versiones del 2314 - la A1 1 Modelo y Modelo 1 A2 - cada uno con un tiempo de acceso un 20 por ciento más rápido que el disponible anteriormente Modelo 1. Uno de los nuevos modelos de almacenamiento en disco con cinco unidades de disco independiente, y el otro tenía ocho. La versión de cinco unidades con una capacidad de almacenamiento de 145,8 millones de bytes; la más grande tenía una capacidad de 233,4 millones de bytes. El tiempo de acceso promedio se redujo en 75 a 60 milisegundos. El tiempo de acceso mínimo era de 25 milisegundos. Las nuevas versiones incluidas sus unidades de control propio y han sido diseñados para su uso con S/360 Modelos 30, 40, 50, 65, 67, 75 y 85. El más pequeño de 2314 alquiló 3.875 dólares al mes y se vendió por $ 175.075. La versión más grande de alquiler de 5.675 dólares al mes, con un precio de compra de 256.400 dólares. Primer cliente de los envíos se habían programado para el tercer trimestre de 1969. Más tarde, en 1969, una caja con dos unidades que se ofrecía. En 1970, la unidad de almacenamiento de 2319 se ha configurado con tres unidades de 2314, más la electrónica de control para la adhesión a los más pequeños de la recién anunciada System/370 transformadores. En el 1980 se hizo el primer disco duro de 5,25" (cinco-coma-veinticinco pulgadas), desarrollado por la compañía Seagate. La revolución de la computadora personal a comienzos de 1980 cambió todo, es la introducción de los primeros discos duros pequeños. Eran discos de 5.25 pulgadas los que manejaban de 5 a 10 MB de almacenamiento- el equivalente de 2.500 a 5.000 páginas de tecleo de información- en un aparato del tamaño de la caja de un zapato pequeño. Al tiempo se consideró que una capacidad de almacenamiento de 10 MB era demasiado grande para una llamada computadora "personal". Los primeros PCS usaron discos flexibles trasladables como aparatos de almacenamiento casi exclusivamente. El término "disco blando" con precisión se refiere a los primeros discos para PC de 8 y 5.25 pulgadas que tuvieron éxito. Los discos internos de hoy, más pequeños, se construyen 3.5 pulgadas de forma similar a los anteriores, pero se albergan en un casco de plástico rígido, que es más durable que el techado flexible de los discos más grandes. 12 Alrededor de 1992 varios modelos 1.8 pulgadas aparecieron, peso sólo unas onzas y entrega capacidades de hasta 40 MB. Igualmente aparecieron con formato de 1.3 pulgadas, del tamaño de una fosforera. Factores de forma más pequeños por supuesto, no eran necesariamente mejor que los más grandes. En el periodo entre 1995 y 1999 el disco duro más pequeño que puede encontrarse en ésta época es el de 4 GB, mientras que el más grande es de 15 GB. Podría decirse que los discos duros de cualquier tamaño, permiten instalar Windows, Office y un programa de contabilidad, y aún sobrará capacidad para, digamos, unas 50.000 cartas y varios millones de apuntes bancarios. En la actualidad, ya contamos en el uso cotidiano con discos duros de más de un terabyte (TB) o 1.048.576 megabytes. 4.2 Elementos que hacen posible el funcionamiento del disco SATA 4.2.1 Ordenador Este puede ser portátil o de sobremesa. Contiene todos los dispositivos que nos permiten, entre otras cosas, el acceso al disco. Podemos incluir también todos los periféricos como ahora el teclado, el ratón y la pantalla. La placa base tiene que ser compatible con los discos SATA de grandes capacidades. 4.2.2 Disco SATA: Figura 3. Disco Serial ATA 13 Se trata de un disco duro con una interfaz serie de transferencia de datos con la placa base. Un hecho ya conocido es que con estos discos se alcanzan velocidades de transferencia muy superiores a los discos que usan la conexión paralela. La primera generación especifica en velocidades de 1.5 Gbit por segundo, también conocida por SATA 1.5 Gb/s o Serial ATA-150. Actualmente se comercializan dispositivos SATA II, a 3 Gb/s, también conocida como Serial ATA-300 y los SATA III, a 6 Gb/s, que incluyen una velocidad de 6.0 Gb/s estándar. Los discos que soportan la velocidad de 3Gb/s son compatibles con un bus de 1,5 Gb/s. 4.2.3 Advanced Host Controller Interface (AHCI) Este dispositivo se encarga de emular el funcionamiento de un interfaz ATA estándar. La emulación puede consistir en presentar los dispositivos como si fueran Maestros de distintos puertos ATA, o presentarlos por parejas como si fueran Maestro y Esclavo de un puerto ATA. La emulación es completa, tanto a nivel del comportamiento del controlador como de los dispositivos, incluyendo el comportamiento de los bloques de registros de Comando y de Control, las transferencias en modo PIO, DMA y UDMA, las interrupciones y los distintos procesos de inicialización. En el interfaz paralelo, toda la comunicación a nivel de comandos, datos y estado entre un dispositivo y el driver se hace mediante los registros de Comando y de Control situados en el propio dispositivo. Cada dispositivo dispone de su propio bloque de registros y el driver lee y escribe directamente en ellos. Las direcciones de los registros son distintas para cada puerto ATA, pero son las mismas tanto para el Maestro como para el Esclavo de cada puerto, debiendo el driver seleccionar previamente a uno de ellos mediante la escritura de un bit de selección de dispositivo en uno de los registros. El dispositivo que no está seleccionado simplemente no hace caso a ninguna lectura o escritura en el bloque de registros, salvo las escrituras de dicho bit para detectar cuándo el driver lo selecciona para comunicarse con él. En el caso del interfaz SATA, el driver no puede evidentemente leer y escribir directamente en los registros de los dispositivos, por lo que el controlador SATA implementa un bloque de registros por cada dispositivo (denominado Bloque de Registros Shadow) que refleja el contenido y el comportamiento de los registros de los dispositivos. El driver entonces lee y escribe realmente en el bloque de registros shadow del controlador SATA, mientras que por el otro lado el controlador y los dispositivos SATA se intercambian la información a través de la línea serie para sincronizar los contenidos de los registros. En el caso de una emulación Maestro/Esclavo, es responsabilidad del controlador SATA enviar la información al dispositivo adecuado, en función del bit de selección de dispositivo escrito previamente por el driver en el registro shadow correspondiente. 14 4.3 Interfaz de usuario (parte gráfica) Como ya se ha comentado anteriormente, en este proyecto no se tendrá que hacer una interfaz de usuario puesto que ya disponemos de una diseñada para un programa de acceso a discos PATA. Disponemos de una interfaz muy completa que incluye prácticamente todas las opciones necesarias para la gestión de los discos duros. Esta interfaz permite elegir, en caso de varios discos, el dispositivo que se desea visualizar, editar, copiar, etc. La lista de los dispositivos disponibles y su información correspondiente se visualiza nada más al iniciar el programa. La interfaz está diseñada para acoplar trozos de código en forma de ficheros de un único proyecto donde se hará la comparación de discos, copia de una unidad a otra, búsqueda de información en modo binario o ASCII y por supuesto la edición manual de los sectores de los discos. Figura 4. Portada de la interfaz ejecutada en Windows (no permite ver discos) La capacidad de almacenamiento de los discos SATA, en la mayoría de los casos, es muy superior a los dispositivos con conexión paralela. Por esta razón, la interfaz necesita unas actualizaciones, sobre todo cuando se imprime por pantalla el tamaño del disco en Megabytes. La interfaz permite la posibilidad de acceso a cualquier sector del disco. Para ello el usuario podrá ir avanzando los sectores de uno en uno o bien introducir de forma numérica el orden del sector que quiere visualizar o editar. Las variables que contienen estos datos próximamente no podrán contener todo el valor. Quizá este sea uno de los detalles más importantes que se tendrán en cuenta como previsión de la evolución de las capacidades de almacenamiento de los discos duros. 15 4.4 Beneficios del programa de gestión del disco • Es un recurso flexible y adaptable a diferentes tipos de usos. El programa puede ser usado por programadores para corrección de sectores dañados, eliminación de datos y ficheros que afectan el correcto funcionamiento del sistema…también la aplicación puede servir como simple herramienta para hacer copias de seguridad o bien copia de datos de unos discos a otros. • Con este programa se consigue reducir de forma significativa el tiempo que dura una transferencia de datos de un disco duro: un ejemplo comprobado es el hecho de copiar 122 GB de memoria de un disco a otro en una hora y media. Mover esta cantidad de datos en Windows de un disco a otro puede tardar diez veces más. • El usuario se enfrenta a una tecnología sencilla, especialmente si se compara con otras herramientas para este fin. • El programa no necesita ningún tipo de instalación. Solo se tendrá que acceder a MS-DOS ubicado en un dispositivo de almacenamiento USB y ejecutar la aplicación. La ventaja de esto es que el acceso al disco es independiente de la información que tiene el mismo. En Windows, el sistema operativo se ubica en la memoria del disco duro. Si el disco está dañado no se podrá arrancar salvo que se use otro dispositivo compatible. • Para la mayoría de casos el uso de esta aplicación no requiere muchos conocimientos previos. Es una aplicación intuitiva. • El programa se podrá utilizar para la gestión de prácticamente todos los tipos de discos duros que se pueden encontrar en el mercado. Independientemente de la tecnología empleada y los protocolos de transferencia de datos (hay pocas limitaciones). Se podrá acceder a discos duros de los diferentes fabricantes. • El programa estará diseñado para gestionar discos duros con una capacidad de almacenamiento de datos mucho más superior a la actual. Se prevé un futuro uso de esta aplicación pese el progreso continuo en este ámbito. 16 5 Análisis previo Antes de empezar a realizar el programa de gestión de los discos duros deben fijarnos en las características principales que debe tener. Disponemos de una interfaz que se tiene que acoplar al proyecto y también de un programa ya hecho para gestión de discos duros IDE. Nuestro objetivo será hacer una parte que trabaje en paralelo con la existente sin influir en el correcto funcionamiento de esta. Entonces nos encontramos con dos opciones. La primera consiste en modificar todas las funciones del programa origen e introducir el código para el correcto funcionamiento en los discos SATA. En este caso se emplearán condicionales en casi todas las líneas de código en las que hay diferencia de funcionamiento. La segunda opción es la redacción de funciones totalmente independientes para el acceso a los disco serie y la conservación de las anteriores. En este caso, el flujo del programa dependerá del tipo del disco (véase el apartado 8.2). Está claro que la solución óptima es la segunda porque con esta evitaríamos tocar el código original y nos ahorraríamos posibles errores en el funcionamiento habitual del programa proporcionado. Aparte de eso, el código que regula las condiciones será mínimo (solo al ejecutar una función u otra). El inconveniente de esta solución es la extensión del código. Se puede llegar a duplicar las líneas de código del programa y por lo tanto un aumento del tamaño del programa. El tiempo de ejecución no se verá afectado porque, dependiendo del disco al que se acceda, se usarán unas funciones u otras. Un detalle muy importante que hay que tener en cuenta es la diferencia en los comandos que se envían al disco. Hablamos de comandos para discos que implementan 28 bits para el Direccionamiento de bloque lógico (LBA) con un máximo de 137.4 GB y otros comandos diferentes para los dispositivos de 48 bits de direccionamiento para capacidades muy grandes (144 Petabytes). Por cuestiones de compatibilidad, los comandos de los discos de 28 bits suelen ser válidos para los discos de direccionamiento superior (48 bits). Como diseño previo del proyecto hemos decidido acceder a cada disco con los comandos propios implementados especialmente para este, pese la existencia de la posibilidad de utilizar los otros comandos con ciertas limitaciones. Un ejemplo de estos casos es el comando: READ SECTOR, este comando es para discos que implementan un direccionamiento de 28 bits. Se podrá acceder a un disco de una capacidad superior a 137 GB siempre y cuando se lea un sector con orden inferior a esta cantidad de memoria. Si pretendemos leer un sector que se encuentra en una posición superior la lectura será errónea. 17 6 Disco SATA El disco duro es un dispositivo de almacenamiento de datos no volátil, que conserva la información aun con la pérdida de energía y que emplea un sistema de grabación magnética digital. Dentro de la carcasa hay una serie de platos metálicos apilados girando a gran velocidad. Sobre los platos se sitúan los cabezales encargados de leer o escribir los impulsos magnéticos. 6.1 El Hardware (el nivel físico) La interfaz SATA se compone de dos pares de señales diferenciales, una para transmitir en un sentido y otra para transmitir en el sentido opuesto. La información se transmite en código NRZ a una tensión nominal de +/- 250 mV. El interfaz eléctrico al cable se realiza por medio de un transceptor denominado Phy. Las velocidades de transmisión normalizadas por el momento son de 1,5 Gbps y 3 Gbps (1.500 y 3.000 Mbaudios respectivamente), equivalentes a una velocidad en el enlace físico de 150 y 300 MB/s respectivamente (ya que cada carácter se compone de 10 bits, debido a la codificación empleada 8b10b). 6.1.1 Spread Spectrum Clocking SATA utiliza una técnica denominada Spread Spectrum Clocking para rebajar el nivel de emisión electromagnética, distribuyéndola en un rango de frecuencias en vez de estar toda concentrada en una frecuencia fija. La técnica consiste en modular la frecuencia del reloj de transmisión, de manera que la frecuencia se hace variar lentamente siguiendo una forma triangular (decrece linealmente con el tiempo desde la frecuencia máxima hasta una determinada frecuencia mínima, y desde ahí crece de nuevo linealmente con el tiempo hasta la frecuencia máxima). En SATA la frecuencia máxima es igual a la frecuencia nominal, la frecuencia mínima es el 99,5% de la frecuencia nominal, y el periodo de la modulación triangular es de 33,33 us. Como la frecuencia se modula desde la frecuencia nominal hacia abajo, la técnica se denomina down-spreading. El receptor recibe los bits en código NRZ a la velocidad nominal de 1,5 ó 3 Gbps, teniendo en cuenta las variaciones en la frecuencia de recepción debidas a la técnica de down-spreading. A partir de la secuencia de bits el receptor recupera y deserializa los datos (convierte la secuencia serie en paralelo), y detecta una secuencia especial de bits denominada patrón Coma que le permite alinear los caracteres de entrada (es decir, le permite saber qué bit es el primero de cada carácter). 6.1.2 Cables y Conectores Los dispositivos SATA, tanto de 3,5” como de 2,5”, disponen de un conector macho con dos segmentos, uno de señal y otro de alimentación, mientras que los controladores pueden disponer de un conector hembra con los dos segmentos o de un conector macho con sólo el segmento de señal. El segmento de señal dispone de 7 contactos, 4 para los dos pares de señal y 3 para masa. El segmento de alimentación dispone de 15 contactos, 3 para cada alimentación 18 (5V, 12V y 3,3V), uno reservado y el resto para masas. Para permitir la conexión en caliente, los contactos tienen distintas longitudes para secuenciar la conexión. Figura 5. Conectores serie En el caso de conexión directa, el conector del dispositivo se inserta directamente en el conector hembra de dos segmentos del controlador, lo que proporciona al dispositivo todos los contactos tanto de señal como de alimentación. Para hacer posible este tipo de conexión, las posiciones de las señales de transmisión y recepción en el segmento de señal del controlador están invertidas respecto a las del dispositivo. En el caso de conexión por cable, el segmento de señal del dispositivo se conecta al conector macho de señal del controlador mediante un cable de señal SATA, el cual está formado por dos secciones de cable twinaxial, una para cada par de señal diferencial. La longitud del cable puede ser de hasta 1 metro y sus dos extremos son simétricos, por lo que cualquiera de los extremos se puede conectar tanto en el controlador como en el dispositivo. El conector macho de señal del controlador también tiene invertidas las 19 posiciones de las señales de transmisión y recepción, por lo que el cable de señal no intercambia las posiciones de los pares. Por otro lado, el segmento de alimentación del dispositivo se conecta a un cable de alimentación SATA que puede venir directamente de la fuente de alimentación del equipo o puede terminar en un conector para su conexión en algún lugar del equipo. Para facilitar la transición de ATA a SATA, en los dispositivos de 3,5” se permiten varias configuraciones mixtas de conectores SATA y ATA (denominados conectores heredados): • Configuración 35A1: Conector de dos segmentos SATA y ningún conector heredado • Configuración 35B1: Conector de dos segmentos SATA y conector heredado de alimentación y puentes de configuración. • Configuración 35B2: Conector de señal SATA y conector heredado de alimentación y puentes de configuración. • Configuración 35B3: Conector de señal SATA y conector heredado de alimentación. • Configuración 35B4: Conector de dos segmentos SATA y conector heredado de puentes de configuración. • Configuración 35B5: Conector de dos segmentos SATA y conector heredado de alimentación. • Configuración 35C1: Conector de señal SATA, conector heredado de señal ATA y conector heredado de alimentación Los dispositivos de 2,5” sólo disponen del conector de dos segmentos SATA: 6.1.3 Señales OOB (Out Of Band) Las señales OOB (Out of Band) son unos patrones de señales de baja velocidad que no aparecen durante las transmisiones, y que sólo se utilizan durante la inicialización del enlace. Consisten en ciclos de duraciones predefinidas de reposo y de transmisión de unas determinadas secuencias de señal (primitivas ALIGN, que se describen más adelante). La transmisión de las primitivas ALIGN se usa sólo para producir una envolvente, de forma de el receptor distingue las distintas señales OOB por la duración del intervalo de reposo que hay entre las consecutivas secuencias de señal (la duración de las secuencias de señal no se utiliza para distinguir las distintas señales OOB). SATA define dos señales OOB: • COMRESET / COMINIT El controlador la envía para transmitir la señal COMRESET, que origina una inicialización hardware en el dispositivo. El dispositivo la envía para transmitir la señal COMINIT, para solicitar al controlador la inicialización del enlace (negociación de la velocidad y comienzo de la comunicación). 20 • COMWAKE Esta señal la puede enviar tanto el controlador como el dispositivo, y se utiliza para despertar al otro Phy desde un estado de ahorro de energía, y también durante el proceso de inicialización del enlace. 6.1.4 Secuencia de inicialización del phy La secuencia de inicialización del phy consiste en una secuencia de señales OOB seguida de una secuencia de negociación de velocidad. La secuencia OOB puede comenzarla el controlador con la transmisión de COMRESET, o puede comenzarla el dispositivo con la transmisión de COMINIT. La secuencia también incluye un intercambio de señales COMWAKE y una fase de calibración de la impedancia de salida del transmisor del controlador (y opcionalmente también del dispositivo) para adaptarse a la impedancia de la interconexión (ya que puede ser directa o por cable). La fase de negociación de velocidad comienza entonces con la transmisión por parte del dispositivo de primitivas ALIGN a la velocidad más alta que soporte (las primitivas se describen más adelante), mientras que el controlador transmite un determinado dato a la velocidad más baja que soporte. Si el controlador soporta la velocidad a la que el dispositivo está transmitiendo las primitivas ALIGN, entonces pasa a transmitir también primitivas ALIGN a dicha velocidad, lo que el dispositivo interpreta como que la velocidad de enlace es correcta. Si el dispositivo no recibe primitivas ALIGN a esa velocidad en un intervalo de tiempo, entiende que el controlador no soporta esa velocidad de enlace y comienza un nuevo proceso a la velocidad inmediatamente más baja que soporte. 6.2 El nivel de Enlace El nivel de enlace define el uso de la codificación 8b/10b, el uso de las distintas Primitivas y algunos otros detalles como los relativos al código de detección de errores (CRC) y a la aleatorización de datos (scrambling), para distribuir la emisión de energía electromagnética cuando se transmiten secuencias repetitivas de caracteres. 6.2.1 Codificación 8b10b: Caracteres de datos, caracteres de control y patrón Coma La codificación 8b10b es muy utilizada actualmente en transmisión serie a velocidades cercanas y superiores al Gbps. Es la codificación utilizada por Fibre Channel (1 y 2 Gbps), posteriormente adoptada por Gigabit Ethernet (1 Gbps), y actualmente en uso por SAS y SATA (1,5 y 3 Gbps), FireWire 800 (800 Mbps), así como por InfiniBand (2,5 Gbps). 21 La codificación tiene las siguientes funciones: • Asegurar suficientes transiciones en la línea como para que el receptor pueda recuperar el reloj y así pueda recibir adecuadamente la secuencia de bits, • Incrementar en gran medida las posibilidades de detección de errores simples y múltiples que puedan ocurrir durante la transmisión, y • Permitir la transmisión de caracteres especiales que contienen un patrón fácilmente reconocible por el receptor (denominado patrón Coma), que le permite alinear palabras en la secuencia de bits que recibe (es decir, le permite conocer qué bit es el primero de una palabra). La codificación 8b10b consiste en sustituir cada octeto (8 bits) por un código de 10 bits antes de su transmisión. De todos los posibles códigos de 10 bits (en total 2^10 = 1024) sólo se utilizan 512 para codificar todos los posibles caracteres de datos (que en total pueden ser 2^8 = 256), y unos pocos códigos más para codificar una serie de caracteres de control (el motivo de utilizar el doble de códigos que de caracteres a codificar se explica más adelante). Todos los caracteres que se transmiten en SATA se agrupan en una secuencia de 4 octetos denominada dword. El primer carácter de una dword puede ser un carácter de dato, en cuyo caso la dword está formada por 4 caracteres de dato (y la información que transporta es por lo tanto un dato de 32 bits), o puede ser un carácter de control, en cuyo caso la dword está formada por el carácter de control y 3 caracteres de datos (la dword en este caso se denomina Primitiva, y transporta información de control). La codificación 8b10b utiliza un formato particular para expresar los caracteres de 8 bits: • Zxx.y Por un lado la letra Z identifica si el carácter es un dato (en cuyo caso Z = D), o si es un carácter de control (en cuyo caso Z = K). Por otro lado, xx es el valor decimal de los bits 4:0 mientras que y es el valor decimal de los bits 7:5 del carácter. Entonces Dxx.y expresa cualquiera de los 256 posibles caracteres de datos, mientras que Kxx.y expresa cualquiera de los caracteres de control válidos (la codificación 8b10b sólo permite 12 códigos de control válidos). El codificador 8b10b convierte cada carácter Dxx.y y Kxx.y a su correspondiente código de 10 bits, teniendo en cuenta que cada carácter puede codificarse mediante dos códigos distintos, dependiendo del valor de un parámetro que se denomina disparidad (por eso se necesitan el doble de códigos que de caracteres a codificar). El concepto de disparidad es el siguiente: de todos los posibles códigos de 10 bits, el sistema 8b10b sólo utiliza aquellos que tienen: • 5 unos y 5 ceros. En este caso se dice que el código tiene disparidad neutra, • 6 unos y 4 ceros. En este caso el código tiene disparidad positiva, y • 4 unos y 6 ceros. En este caso el código tiene disparidad negativa. 22 La idea es que cada código que se transmita cancele la disparidad producida por el código anterior, de forma que el nivel de continua de la señal eléctrica es nulo permanentemente. De los 12 posibles caracteres de control permitidos por el sistema 8b10b, SATA utiliza dos: el K28.3 y el K28.5. De los 12 posibles caracteres de control permitidos por el sistema 8b10b, hay 3 cuyos códigos de 10 bits contienen en sus 7 primeros bits un patrón especial que se denomina Coma, que consiste en 2 bits a un valor seguidos por 5 bits al valor contrario. Los phys utilizan este patrón especial para conseguir la sincronización (alineación) a nivel de dword, es decir, para conocer qué bit es el primero de una dword (una vez conseguida la alineación, el phy sabe que cada 40 bits comienza una nueva dword). De los dos caracteres utilizados por SATA, sólo el K28.5 contiene el patrón Coma, por lo que este carácter sólo se utiliza en la primitiva ALIGN, mientras que el carácter K28.3 se utiliza en todas las demás primitivas. De esta manera los Phys alinean los caracteres sólo cuando reciben la primitiva ALIGN. 6.2.2 Primitivas y Tramas Las primitivas y las tramas son las dos estructuras utilizadas para intercambiar información entre el controlador y el dispositivo. Las primitivas constan de una sola dword que comienza por un carácter de control, y es la forma más simple de intercambio de información. Las primitivas proporcionan información de control de bajo nivel. Las tramas son secuencias de dwords que transportan información. Las tramas siempre comienzan con la primitiva SOF (Start of Frame) y terminan con la primitiva EOF (End of Frame). La última dword (que no sea una primitiva) anterior a la primitiva EOF es el CRC de la trama, mientras que el resto de la trama (es decir, las dwords entre el SOF y el CRC) es la información propiamente dicha transportada en la trama y se denomina FIS (Frame Information Structure). Es posible la transmisión de ciertas primitivas de control de flujo en el interior de la trama (HOLD, HOLDA y CONT). Las primitivas definidas en SATA son: • ALIGN Se envía para que el nivel físico del receptor reajuste sus operaciones internas (entre otras, alinear la secuencia de bits de entrada en dwords de la manera correcta, a partir del patrón Coma). • CONT Se utiliza para eliminar secuencias repetitivas de la misma primitiva, con el objetivo de reducir el nivel de emisión electromagnética. Cuando hay que enviar repetidamente la misma primitiva, lo que se hace es enviar la primitiva seguida de la primitiva CONT y seguida de dwords aleatorias. El receptor interpreta como si estuviera recibiendo 23 repetidamente la primitiva recibida anteriormente a la primitiva CONT, en tanto no reciba una nueva primitiva. • DMAT La envía el receptor de una trama para solicitar al transmisor que aborte una transferencia de datos por DMA. • EOF Se usa para indicar el final de una trama. • HOLD El transmisor la envía dentro de una trama en puesto de una dword de dato cuando no tiene una dword de dato preparada para su transmisión (underrun), y el receptor la envía para indicar que no puede recibir todavía una nueva dword de dato (overrun). • HOLDA Se envía en respuesta a una primitiva HOLD, y se transmite siempre que se esté recibiendo HOLD. • PMACK Se envía en respuesta a una primitiva PMREQ_S o PMREQ_P, y se transmite cuando el receptor está preparado para entrar en el modo de ahorro de energía solicitado. • PMNAK Se envía en respuesta a una primitiva PMREQ_S o PMREQ_P, y se transmite cuando el receptor no está preparado para entrar en el modo de ahorro de energía solicitado o no lo soporta. • PMREQ_P Se envía para solicitar la entrada en el modo de ahorro de energía parcial. • PMREQ_S Se envía para solicitar la entrada en el modo de ahorro de energía total (denominado Slumber). • R_ERR La envía el receptor de una trama en respuesta a la primitiva WTRM para indicar que se ha detectado un error en la trama recibida. • R_IP La envía el receptor de una trama en respuesta a la recepción de cada dword de dato. • R_OK 24 La envía el receptor de una trama en respuesta a la primitiva WTRM para indicar que no se ha detectado ningún error en la trama recibida. • R_RDY Se envía en respuesta a una primitiva X_RDY para indicar que se está preparado para recibir una trama. • SOF Se usa para indicar el principio de una trama. • SYNC Se usa cuando no hay tramas ni primitivas que enviar (el enlace está desocupado). • WTRM La envía el transmisor de una trama tras el EOF mientras espera que el receptor de la trama envíe el estado de la recepción (R_ERR o R_OK). • X_RDY Se envía para indicar que hay una trama preparada para su transmisión. La trama no se envía hasta que no se reciba la primitiva R_RDY. 6.3 El nivel de Transporte 6.3.1 Modos de transferencia Los dispositivos SATA pueden transferir información principalmente empleando dos métodos: PIO y DMA. El modo PIO (Programmed I/O) depende del procesador para efectuar el trasiego de datos. A nivel de rendimiento no hay mayor problema, ya que los micros actuales tienen la suficiente capacidad para gestionar estas operaciones y alternarlas con otras, por supuesto. El otro método es el DMA, así la CPU se desentiende de la transferencia, teniendo ésta lugar por mediación de un chip DMA dedicado. La variante de la transferencia DMA usada actualmente en los discos duros es la BusMaster DMA. Esta modalidad aprovecha las ventajas de los chipsets de las placas base, cada vez más optimizados para estas labores (de acceso directo a memoria). Además de liberar al procesador, puede obtener por parte de éste un control casi total, de forma que la información sea transferida con la máxima prioridad. 25 6.3.1.1 Programmed I/O El método más antiguo de transferir datos en la interfaz IDE/ATA es el empleo del modo PIO (Programmed I/O). Esta técnica se basa en que la CPU del sistema y el hardware de apoyo controlen directamente la transferencia de datos entre el sistema y el disco duro. Existen varias velocidades de transferencia utilizando este método, estas variaciones se llaman modos de entrada - salida programados, o más comúnmente, modos de PIO. Durante mediados de los años 90, la entrada - salida programada era el único camino que la mayor parte de sistemas utilizaban para el acceso a discos duros IDE/ATA. Tres modos de velocidad fueron definidos en las normas ATA aparte de otros dos que fueron añadidos más tarde. A continuación la tabla nos muestra los cinco diferentes modos de PIO, con el tiempo de ciclo para cada transferencia y el rendimiento correspondiente del modo: Figura 6. Diferentes modos PIO Algunas cosas sobre esta tabla deben ser mencionadas. Ante todo, los modos PIO son definidos en función de su tiempo de ciclo, representando cuantos nanosegundos que este necesita para efectuar una transferencia. El índice de transferencia máxima es el recíproco del tiempo de ciclo, es el doble porque la interfaz es dos octetos (16 bits). También, es necesario destacar la ausencia en la tabla del supuesto " modo 5 de PIO ", Este no existe y nunca fue puesto en práctica en ningún disco duro. Al parecer, una vez alguna discusión ocurrió sobre la creación de un modo PIO más rápido, que provisionalmente llamaron " el modo 5 de PIO". Este modo debía soportar una velocidad de transferencia de 22.2 MB/S, pero nunca fue puesto en práctica (probablemente porque el modo mucho más rápido Ultra DMA de 33 MB/S 2 lo superaba mucho). Algunos fabricantes de placa madre se encargaron de dar apoyo a este modo propuesto para sus programas de BIOS pero al final no tuvieron éxito. Obviamente, los modos más rápidos son mejores, porque proporcionan una velocidad de transferencia de la interfaz teóricamente más alta. Esta representa la velocidad de transferencia de datos alrededor del dispositivo. Hay que recordar que es la velocidad de la interfaz y no necesariamente la velocidad de transferencia soportada por el disco, que es casi siempre más lento (y debería ser). Desde luego hoy todos los nuevos discos soportan velocidades de transferencia superiores a la máxima velocidad que el mejor modo PIO puede alcanzar, una de la razones porque PIO ha perdido importancia. 26 Como ya se ha mencionado, la I/O programadas se realiza por la CPU, el procesador del sistema es el responsable de ejecutar las instrucciones que transfieren los datos al disco y desde él, usando posiciones de entrada - salida especiales. Estos trabajos técnicos son ideales para dispositivos lentos como teclados y módems, pero para dispositivos de funcionamiento similar a los discos duros causa problemas de funcionamiento. PIO no es lo único que implica una atención elevada, la CPU está "distraída" con su trabajo ordinario hasta que un disco duro necesita ser leído o escrito. Esto quiere decir que la utilización de PIO es inmejorable para funcionamientos ligeros y tascas simples. Pero en el mismo tiempo quiere decir que con más transferencias de datos, más atascada está la CPU. Como las tasas de transferencia de los discos duros siguen aumentando, la carga sobre la CPU se hace cada vez mayor. Esta es otra razón clave por la cual los modos PIO son menos usados en nuevos sistemas, estos modos han sido substituidos por modos DMA, y más tarde por Ultra DMA. Existen dos canales IDE, cada canal admite el empleo de dos dispositivos, designados como el máster y el esclavo. Los sistemas modernos permiten que el dispositivo máster y el esclavo corran en modos PIO diferentes sobre el mismo canal, esto se llama independent device timing y es una función del chipset y la BIOS. Si no se suporta esta característica, ambos dispositivos pueden ser limitados al modo PIO más rápido del dispositivo más lento de los dos, pero esto no es un gran problema desde la segunda mitad de los años 90. Los modos PIO no requieren ningún driver especial en circunstancias normales, la BIOS del sistema contiene toda la información necesaria para un correcto funcionamiento de estos modos. Esta compatibilidad universal, pese su simplicidad conceptual, es la manera tradicional usada por defecto en la mayoría de discos. Hoy en día, sin embargo, PIO se sigue usando para discos modernos, que usan Ultra DMA para disminuir la carga sobre la CPU y permitir disfrutar de un rendimiento más alto. La compatibilidad de los modos PIO es todavía universal en casi todos los sistemas y discos actuales. Se usa, por ejemplo, como último recurso cuando el driver o el software presentan problemas con el acceso vía Ultra DMA. 6.3.1.2 DMA Como ya se ha descrito en el apartado anterior (programmed I/O). Aquel método de transferencia de datos entre el disco duro y el sistema tiene defectos muy serios puesto que requiere el cuidado y la atención de la CPU del sistema. Claramente, una mejor solución es dejar la CPU fuera del escenario completamente, y hacer que el disco duro y la memoria del sistema se comuniquen directamente. El acceso directo a memoria o DMA es el término genérico que se refiere a un protocolo de transferencia donde un dispositivo periférico transfiere información directamente a memoria o desde la misma, sin que se necesite una intervención del procesador de sistema para realizar la transacción. DMA ha sido usado en el PC durante años con el bús ISA, para dispositivos como las tarjetas de sonido y la interfaz del disquete. El DMA convencional usa los canales de DMA regulares que son un recurso del sistema estándar. 27 Varios modos DMA diferentes han sido definidos para la interfaz IDE/ATA, están agrupados en dos categorías. El primer juego de modos incluye modos DMA de un solo Word. Cuando se usan estos modos, cada transferencia es de un solo Word de datos (un Word es el término técnico de dos Bytes, o bien 16 bits de memoria). Hay tres modos DMA de un solo Word. Figura 7. Diferentes modos DMA Single Word Como hablé en el apartado de PIO, la tasa de transferencia máxima es doble del tiempo de ciclo específico para cada modo. Obviamente, estas velocidades de transferencia no son impresionantes para las especificaciones de hoy en día. Lo que es realmente claro es que realizar transferencias de una sola palabra cada vez es horriblemente ineficaz. Por eso, los modos Single Word DMA fueron rápidamente sustituidos por los modos DMA Multiword. Como el nombre indica, con estos modos "una serie" de transferencias ocurre una tras otro, un Word después de otro, evitando hacer, por separado, una transferencia para cada palabra. Aquí están los modos de transferencia DMA MultiWord: Figura 8. Diferentes modos DMA Multiword Puesto que el DMA Multiword es más eficiente, y también tiene velocidades de transferencia más altas, los modos Single Word DMA fueron rápidamente abandonados después de que el estándar ATA-2 fuera extensamente adoptado – estos modos fueron quitados de las normas ATA en las especificaciones del ATA-3. Entonces todos los 28 accesos vía DMA hoy en día (incluyendo Ultra DMA) son en realidad de MultiWord. El término "MultiWord" se da por sabido en casi todos los estándares del Serial y Parallel ATA. Otra característica importante del DMA es que hay dos modos diferentes de hacer transferencias. DMA convencional es lo que llaman “tercera parte” del DMA, que quiere decir que los controladores del DMA sobre la placa madre coordinan las transferencias de DMA. ("la tercera parte" es el controlador DMA.) Lamentablemente, estos controladores DMA eran viejos y muy lentos – se puede decir que no han sido modificados durante mucho tiempo. Estos dispositivos estaban bastante ligados a los viejos los buses de ISA, que se dejaron de usar para interfaces del disco duro por motivos de rendimiento. Cuando los modos 1 y 2 del DMA Multiword comenzaron a hacerse populares, se hizo el empleo del bús PCI de alta velocidad para tarjetas de controladores IDE/ATA. En aquel punto, el viejo modo de hacer transferencias vía DMA tuvo que ser cambiado. Los Discos duros modernos usan “primera parte” de DMA transferencias. El término "primera parte " quiere decir que el dispositivo periférico hace, él mismo, el trabajo de transferir datos de la memoria y hacia ella, sin el controlador externo del DMA. También se llama Bus Mastering, porque cuando dichas transferencias ocurren el dispositivo se hace "amo del bús”. Bus Mastering permite al disco duro y la memoria trabajar sin depender de los viejos controladores DMA incorporados en el sistema, o de cualquier apoyo de la CPU. Esto requiere el empleo del bús PCI - viejos buses como MCA también eran compatibles con el Bus Mastering, pero no son de uso abundante. En resumen, este método permite que la transferencia de datos entre la memoria del sistema y el disco duro sea más eficiente y también permite bajar la carga sobre la unidad central de proceso durante las transferencias. Curiosamente, a pesar de las ventajas del Bus Mastering, el empleo del modo 2 del busmastering multiword DMA nunca ganó realmente popularidad por varios motivos. El más importante era el pobre apoyo a esta tecnología en los primeros dos años. La Utilización de PIO no requería ningún trabajo y era muy simple. También, DMA no fue compatible con la primera versión de Windows 95, entonces se tuvieron que utilizar Drivers especiales. Los problemas con la implementación del Bus Mastering DMA en los sistemas entre 1996 y 1998 eran numerosos: dificultades con los Drivers, el software operaba correctamente, los lectores de CD-ROM no eran compatibles con los Drivers, etcétera. Ante estos problemas, DMA no marcó la diferencia como ya se esperaba. Es seguro que la reducción de uso de la CPU estaba muy bien, pero ya que la velocidad máxima del mejor modo DMA era la misma que la del modo PIO más alto (16.7 MB/S) no quedaba claro que DMA ofrecía unas ventajas importantes en comparación con PIO. Dadas las pequeñas diferencias, muchos programadores estuvieron lejos de usar DMA, para evitar las incompatibilidades y problemas de estabilidad que muy a menudo presentaba este último. Bus Mastering DMA finalmente entró en crisis cuando la industria siguió adelante con los proyectos de Ultra DMA. Cuando Ultra DMA/33 duplicó la velocidad de transferencia de la interfaz, DMA tuvo una ventaja de velocidad clara sobre PIO aparte de otras mejoras de eficacia. La compatibilidad con el DMA se planteó de forma correcta en Windows 9x, y la mayor parte de los problemas de los viejos Drivers fueron eliminados. Hoy en día, el uso del Ultra DMA es un estándar en la industria. 29 6.3.1.3 ULTRA DMA Desde luego, los discos duros se hacen más y más rápido, y la velocidad máxima del modo 2 del DMA Multiword, 16.7 MB/S, pronto se hizo insuficiente para los discos más rápidos. Sin embargo, los ingenieros que trabajaron para acelerar la interfaz descubrieron que no era ninguna tarea simple. La interfaz fue diseñada para transferencias de datos lentas - aproximadamente 5 MB/S. El aumento de la velocidad de la interfaz (reduciendo el tiempo de ciclo) causó todos los tipos de problemas relacionados con la interferencia. Para hacer la interfaz más rápida, unas medidas diferentes tuvieron que ser tomadas: mejora de la eficacia de la interfaz. El resultado era la creación de un nuevo tipo de modos de transferencia DMA, que se llamaron modos Ultra DMA. El avance tecnológico clave introducido en Ultra DMA era el double transition clocking. Antes del Ultra DMA, una transferencia de datos ocurría en cada ciclo de reloj, provocado por el pulso del reloj de la interfaz (o el “Strobe”). Con Ultra DMA, los datos se transfieren tanto si esta a 1 o a 0 el reloj. El Doble cronometrado de las transiciones, con algunos otros cambios menos importantes hechos, para mejorar la eficacia, basándose en la técnica señalada, permitieron que en el rendimiento fuera duplicado para cualquier velocidad de reloj. Para mejorar la integridad de esta interfaz prácticamente más rápido, Ultra DMA también introdujo el cyclical redundancy checking o CRC en la interfaz. El dispositivo que envía los datos usa el algoritmo CRC para calcular la información redundante de cada bloque de datos enviados en la interfaz. Este " código CRC" se envía con los datos. En el otro extremo de la interfaz, el dispositivo que recibe los datos hace el mismo cálculo CRC y compara el resultado con los datos que el remitente entrega. Si la información no cuadra, esto quiere decir que los datos fueron corrompidos de algún modo y el bloque de datos se elimina. (CRC es similar en concepto y operación al modo de comprobación de errores de la memoria del sistema.) Si los errores ocurren con frecuencia, el sistema puede determinar si hay problemas de hardware y así baja a un modo más lento de Ultra DMA, o bien desactiva del todo estos modos. La primera puesta en práctica del Ultra DMA fue especificada en el estándar ATA/ATAPI-4 que incluía tres modos Ultra DMA, que proporcionaban hasta 33 MB/S de rendimiento. Más tarde, se han ido añadiendo modos más rápidos del Ultra DMA. Esta tabla muestra todos los modos actuales del UDMA, con sus tiempos de ciclo y tasas de transferencia máximas: Ultra DMA Mode Cycle Time (nanoseconds) Maximum Transfer Rate (MB/s) Defining Standard Mode 0 240 16.7 ATA/ATAPI-4 Mode 1 160 25.0 ATA/ATAPI-4 30 Mode 2 120 33.3 ATA/ATAPI-4 Mode 3 90 44.4 ATA/ATAPI-5 Mode 4 60 66.7 ATA/ATAPI-5 Mode 5 40 100.0 ATA/ATAPI-6 Mode 6 15 133 ATA/ATAPI-7 (SATA 1.0) Figura 9. Diferentes modos Ultra DMA El tiempo de ciclo muestra la velocidad del reloj de la interfaz, la frecuencia del reloj es la inversa de este número. La tasa de transferencia máxima es cuatro veces el inverso del tiempo de ciclo - la doble transición que cronometra el medio cada ciclo tiene dos transferencias, y cada transferencia mueve dos Bytes. Double transition clocking es el que permite al modo 2 del UDMA tener una velocidad de transferencia máxima de 33.3 MB/S, a pesar del hecho de tener un tiempo de ciclo idéntico al modo 2 del MultiWord DMA, que alcanza la mitad de esta cifra. Ahora, usted puede preguntarse: ¿si ellos usaron el Double transition clocking para alcanzar los 33.3 MB/S, cómo consiguieron los 66 MB/S, los 100 MB/S, y luego los 133 MB/S? Bien, lo que se hizo realmente es acelerar la interfaz después. Pero el empleo del Double transition clocking les permitió quedarse en la mitad de la velocidad que realmente necesitaban. Sin este método, el modo 5, por ejemplo, del Ultra DMA habría requerido un tiempo de ciclo de 20 nanosegundos en vez de 40, haciendo la puesta en marcha mucho más difícil. Incluso con las ventajas del Double transition clocking, funcionando por encima de los 33 MB/S finalmente se excedieron las capacidades del cable 40-conductor standard IDE. Para usar modos superiores al 2 se requería un cable IDE especial 80-conductor. Este cable usa los mismos 40 pins que los viejos cables, pero añade 40 líneas de tierra entre las 40 señales originales para separarlas y para resolver problemas de corrupción de datos y interferencias. (El cable de 80 conductores en realidad fue especificado en ATA/ATAPI-4 con los primeros modos Ultra DMA, pero era "opcional" para los modos 0, 1 y 2.) Hoy, todos los sistemas modernos que usan discos IDE o SATA deberían usar uno de los modos Ultra DMA. Hay varios requisitos específicos para trabajar con Ultra DMA: • Compatibilidad con el disco duro: El disco duro mismo debe ser compatible con Ultra DMA. Además, el disco debe permitir el modo apropiado del Ultra DMA. • Compatibilidad con el controlador: se debe usar un controlador capaz de hacer transferencias Ultra DMA. Este puede ser el controlador de la interfaz incorporado en la placa madre, o bien uno añadido en la tarjeta de la interfaz. 31 • Compatibilidad con el Sistema operativo: La BIOS y/o el sistema operativo deben ser compatibles con las transferencias Ultra DMA, y el disco duro debe ser programado para funcionar en Ultra DMA en el sistema operativo. • Un cable de 80 conductores: Para modos Ultra DMA superiores al 2, se debe usar un cable de 80 conductores. Si el sistema no reconoce ningún cable de 80 conductores se desactivan los modos 4,5 y 6 del UDMA. En los nuevos sistemas hay pocas limitaciones con la compatibilidad del Ultra DMA, porque el hardware es nuevo y diseñado para funcionar con este modo de tranferencias. En los sistemas más viejos, la cosa es un poco más compleja. En teoría, los nuevos discos deben ser compatibles con los controladores más viejos, de tal modo que si instalamos un disco compatible con Ultra DMA en un PC viejo, esto debe causar que el sistema funcione con un modo lento como ahora PIO 4. Lamentablemente, ciertas placas madre no funcionan bien cuando se usa un disco UDMA, y esto puede causar errores. Una mejora de la BIOS del fabricante de la placa madre es una idea buena, si somos capaces de hacerlo. Otra solución sería usar una utilidad de software especial Ultra DMA (dada por el fabricante del disco) para informar el disco duro de que no tiene que funcionar en modos UDMA. La misma utilidad puede ser usada para permitir los modos UDMA en discos que están configurados para no usarlos. 6.3.2 Los registros Shadow Los registros Shadow son registros virtuales emulados en Sata para reflejar el contenido y el funcionamiento normal de los discos duros. Estos son los mismos que los registros de entrada y salida de los discos IDE. El bloque de registros de comando se usa para enviar comandos al dispositivo o bien para obtener información sobre el estado del mismo. El bloque de registros de Control se usa para el control de dispositivo y forzar un estado alterno. A continuación vamos a ver todos estos registros de forma resumida. 32 6.3.2.1 Registro de comandos Descripción del funcionamiento Este registro contiene el código del comando que se enviará al dispositivo. La ejecución del comando comienza inmediatamente después de que este registro se escriba. Las órdenes ejecutables y los códigos de los comando están resumidos en el apartado Comandos. Direccionamiento Este registro es de solo lectura. Si se lee esta dirección por Host, se lee el registro de Estado. Eficacia El procesamiento del comando comienza cuando este registro se escribe. El contenido del bloque de registros de comando se convierte en los parámetros de entrada del comando cuando este registro se escribe. La escritura de este registro limpia cualquier interrupción pendiente. Descripción de los bits: Para todo los comandos, excepto “Device Reset”, se debe escribir en este registro solo cuando los bits de estado BSY, DRQ y DMACK valen 0. Si ocurre lo contrario, no se puede saber el resultado de la operación excepto el comando “Device Reset”. Si el dispositivo esta en modo Sleep todos los comandos se ignoran. Restricciones de acceso 33 6.3.2.2 Puerto de datos Descripción del funcionamiento Direccionamiento El puerto de datos es de 16 bits de ancho. Este puerto es de lectura y escritura En el modo DMA, las escrituras y lecturas de datos en las dos direcciones (hacia host o hacia el dispositivo) son una serie de escrituras o lecturas consecutivas de este puerto. El resultado de una lectura de este puerto mientras se escribe o bien de una escritura mientras se lee es indeterminado. Eficacia Descripción de los bits: Restricciones de acceso Para todo los comandos, excepto “Device Reset”, se debe escribir en este registro solo cuando los bits de estado BSY, DRQ y DMACK valen 0. Si ocurre lo contrario, no se puede saber el resultado de la operación excepto el comando “Device Reset”. Si el dispositivo esta en modo Sleep todos los comandos se ignoran. 34 6.3.2.3 Registro de datos Descripción del funcionamiento Direccionamiento El puerto de datos es de 16 bits de ancho. Si un dispositivo trabaja con el modo PIO Single Word de 8 bits solo se usa la parte baja de este registro del DD7 a DD0. Este registro es de lectura y escritura En el modo PIO, las escrituras y lecturas de datos en las dos direcciones (hacia host o hacia el dispositivo) son una serie de escrituras y lecturas consecutivas de este puerto. El resultado de una lectura de este puerto mientras se escribe o bien de una escritura mientras se lee es indeterminado. Eficacia Descripción de los bits: Restricciones de acceso El controlador solo debe usar este registro cuando el bit de estado DRQ vale 1 y el bit DMACK vale 0. Los datos de este registro no son validos cuando el dispositivo esta en modo Sleep 35 6.3.2.4 Registro del dispositivo El bit 4, denominado DEV, es el seleccionador del dispositivo. Los otros bits dependen del comando. Se explican en el apartado Comandos Descripción del funcionamiento Direccionamiento Este registro es de lectura y escritura El bit DEV tiene importancia cuando se escribe este registro por el Host o bien cuando el mismo dispositivo actúa. Los otros bits son parámetros de entrada cuando se escribe en el registro de comandos. Eficacia Descripción de los bits: • DEV: es el selector de dispositivos, 0 selecciona el dispositivo 0 y 1 selecciona el • Los bits (3:0) se usan como parte del sector lógico que se quiere especificar. Así se suman 4 bits a los 24 bits de los registros LBA alto, medio y bajo. Cuando se trata de direccionamiento 48 bits estos bits se ignoran dispositivo 1. Este registro solo se debe escribir cuando los bits de estado BSY, DRQ y DMACK están a cero. El contenido de este registro es válido solo cuando BSY es 0. También es inválido el contenido cuando el dispositivo está en modo Sleep. Se desconoce el resultado de escritura de este registro cuando los bits de estado ya mencionados están a 1. Restricciones de acceso 36 6.3.2.5 Registro de control del dispositivo Este registro permite al Host hacer un Software reset del dispositivo conectado y habilitar o deshabilitar la aserción de la señal INTRQ por el dispositivo seleccionado. Cuando el registro de Control del Dispositivo se escribe, ambos dispositivos (Master y esclavo) responden a lo escrito independientemente de cuál es el dispositivo seleccionado. Cuando el bit de SRST se pone a uno, ambos dispositivos siguen el protocolo de reset del software. El dispositivo debe responder al bit de SRST cuando en el modo sleep. Descripción del funcionamiento Direccionamiento Este registro es solo de escritura. Si se lee en esta dirección, se lee el registro de estado alternativo. Eficacia Este registro solo es eficaz cuando se escribe. Descripción de los bits: • • • • • HOB es un bit relacionado con el direccionamiento 48 bit Los bits (6:3) están reservados SRST es el bit del software reset nIEN controla la señal INTRQ. Cero habilita y uno deshabilita El bit debe estar a cero. Este registro solo se debe escribir cuando el bit DMACK no está activado. Restricciones de acceso 37 6.3.2.6 Registro de errores Para todos los comandos, excepto los comandos EXECUTE DEVICE DIAGNOSTIC y DEVICE RESET, el contenido de este registro es válido cuando está activado el bit ERR del registro de estado. Después de un encendido o un comando de los citados anteriormente este registro contiene un código de diagnostico. Descripción del funcionamiento Este registro es solo de lectura. Si se escribe por el controlador, se escribe el registro características. Direccionamiento Eficacia ninguna Descripción de los bits: • • ABRT (comando abortado) este bit se pone a uno cuando ya se ha abortado el comando mandado porque el código o los parámetros no son válidos, hay problemas de compatibilidad con el comando o bien no se cumplen los prerrequisitos para ejecutar el comando. El resto de bits depende del comando. El contenido de este registro es válido cuando los bits de estado BSY y DRQ están a cero y el bit ERR o SE está a uno. También es válido después de un Poweron, un Hardware o Software reset, o después de la conclusión de la ejecución de los comandos EXECUTE DEVICE DIAGNOSTICS o DEVICE RESET. El contenido no es válido cuando el dispositivo está en modo sleep Restricciones de acceso 38 6.3.2.7 Registro de características Descripción del funcionamiento El contenido de este registro depende del comando. Se explica en el apartado Comandos. Direccionamiento Este registro es solo de escritura. Si se lee por el controlador, se lee el registro de errores. Eficacia El contenido de este registro se convierte en un parámetro de entrada cuando se escribe en el registro de comandos Dirección • DA: Device address • CS: Chip select Restricciones de acceso Este registro se debe escribir solo cuando BSY y DRQ están a cero y DMACK esta desactivado. Si se escribe mientras los bits de estado BSY y DRQ están a uno, el resultado es indeterminado. 39 6.3.2.8 LBA alto Descripción del funcionamiento Direccionamiento Eficacia Este registro contiene una parte del valor de sector lógico sobre el cual se desea operar. Este registro depende del comando enviado al disco. Este registro es de escritura y lectura. El contenido de este registro se convierte en un parámetro de entrada cuando se escribe en el registro de comandos Dirección • DA: Device address • CS: Chip select Restricciones de acceso Este registro se debe escribir solo cuando BSY y DRQ están a cero y DMACK esta desactivado. Si se escribe mientras los bits de estado BSY y DRQ están a uno, el resultado es indeterminado. El contenido de este registro no es válido cuando el disco está en modo Sleep. 40 6.3.2.9 LBA bajo Descripción del funcionamiento Direccionamiento Eficacia Este registro contiene una parte del valor de sector lógico sobre el cual se desea operar. Este registro depende del comando enviado al disco. Este registro es de escritura y lectura. El contenido de este registro se convierte en un parámetro de entrada cuando se escribe en el registro de comandos Dirección • DA: Device address • CS: Chip select Restricciones de acceso Este registro se debe escribir solo cuando BSY y DRQ están a cero y DMACK esta desactivado. Si se escribe mientras los bits de estado BSY y DRQ están a uno, el resultado es indeterminado. El contenido de este registro no es válido cuando el disco está en modo Sleep. 41 6.3.2.10 LBA medio Descripción del funcionamiento Direccionamiento Eficacia Este registro contiene una parte del valor de sector lógico sobre el cual se desea operar. Este registro depende del comando enviado al disco. Este registro es de escritura y lectura. El contenido de este registro se convierte en un parámetro de entrada cuando se escribe en el registro de comandos Dirección • DA: Device address • CS: Chip select Restricciones de acceso Este registro se debe escribir solo cuando BSY y DRQ están a cero y DMACK esta desactivado. Si se escribe mientras los bits de estado BSY y DRQ están a uno, el resultado es indeterminado. El contenido de este registro no es válido cuando el disco está en modo Sleep. 42 6.3.2.11 Registro de cuenta de sectores Descripción del funcionamiento Direccionamiento Eficacia Este registro contiene el número de sectores sobre los cuales se desea operar. Este registro depende del comando enviado al disco. Este registro es de escritura y lectura. El contenido de este registro se convierte en un parámetro de entrada cuando se escribe en el registro de comandos Dirección • DA: Device address • CS: Chip select Restricciones de acceso Este registro se debe escribir solo cuando BSY y DRQ están a cero y DMACK esta desactivado. Si se escribe mientras los bits de estado BSY y DRQ están a uno, el resultado es indeterminado. El contenido de este registro no es válido cuando el disco está en modo Sleep. 43 6.3.2.12 Registro de estado Descripción del funcionamiento Este registro contiene información sobre el estado del disco. El contenido de este registro se actualiza constantemente para reflejar el estado del dispositivo. Direccionamiento Este registro es solo de lectura. Si escribimos en esta dirección, escribimos en el registro de comandos Eficacia Leer este registro mientras hay una interrupción pendiente, elimina dicha interrupción. El controlador no debe leer este registro cuando se ejecuta una interrupción porque puede ser que no la reconozca. Descripción de los bits: • • • • • BSY: Este bit se pone a 1 cuando el dispositivo está ocupado. Cuando se escribe el registro de comandos y, obviamente, se ejecuta el comando, este bit o bien el DRQ se tiene que poner a 1 hasta que se cumpla la operación. DRDY: Este bit se pone a 1 cuando el disco está preparado para recibir comandos o cuando se cumpla la ejecución de un comando. DF: Este bit se pone a uno cuando hay algo que impide que el comando se ejecute correctamente y el defecto no está especificado en el registro de errores. DRQ: Este bit indica que el dispositivo está preparado para hacer transferencias entre el Host y el disco. Este bit se pone a 1 cuando los datos están preparados para ser transferidos. Cuando se cumpla la transferencia, este bit se pone a 0. ERR: Indica que un cierto error ha ocurrido. Cuando este bit se pone a uno el contenido del registro de errores es válido. Restricciones de acceso El contenido de este registro no es válido cuando BSY está a 1 o bien cuando el dispositivo está en modo Sleep 44 6.3.2.13 Registro de estado alternativo Descripción del funcionamiento Este registro contiene la misma información que el registro de estado. La descripción de los bits de este registro esta en el apartado anterior. Direccionamiento Este registro es solo de lectura. Cuando se escribe este registro por el controlador, se escribe el registro de comandos del dispositivo. Eficacia Una lectura a este registro no debe eliminar una interrupción pendiente. Dirección • DA: Device address • CS: Chip select Restricciones de acceso El contenido de este registro no es válido cuando BSY está a 1 o bien cuando el dispositivo está en modo Sleep 45 6.3.3 FIS (Frame Information Structure) El nivel de transporte construye las FIS (Frame Information Structure) que se van a transmitir dentro de las tramas y comprueba el contenido de las FIS de las tramas que se reciben. El tipo de la FIS se indica en el primer octeto de la primera dword de la FIS, el cual indica también de paso la longitud y el formato del contenido de la FIS. • FIS Registro – Controlador a Dispositivo Esta FIS la envía el controlador para transferir al dispositivo el contenido del bloque de registros shadow. Un bit de la FIS indica si la transferencia es a consecuencia de una escritura en el registro de Comando o en el registro de Control. El dispositivo actualiza su bloque de registros y ejecuta el comando o la función de control recibida. Este es el mecanismo por el cual el software heredado envía comandos al dispositivo. • FIS Registro – Dispositivo a Controlador Esta FIS la envía el dispositivo para transferir al controlador el contenido de su bloque de registros. El controlador actualiza su bloque de registros shadow. Un bit de la FIS indica si el controlador debe activar la línea de interrupción. Este es el mecanismo por el cual el dispositivo indica el estado de terminación de un comando. • FIS Set Device Bits – Dispositivo a Controlador Esta FIS la envía el dispositivo para transferir el contenido de ciertos bits al bloque de registros shadow del controlador, sobre los que el dispositivo tiene acceso exclusivo de escritura. Estos son los 8 bits del registro de Error y 6 bits del registro de Estado (todos excepto los bits DRQ y BSY). • FIS DMA Activate – Dispositivo a Controlador Esta FIS la envía el dispositivo para indicar al controlador que está preparado para recibir una FIS de datos como consecuencia de la ejecución de un comando de escritura por DMA. Si el controlador necesita enviar varias FIS de datos para completar la transferencia, el dispositivo envía una FIS DMA Activate por cada FIS de datos que deba recibir. • FIS DMA Setup – Dispositivo a Controlador o Controlador a Dispositivo (bidireccional) Esta FIS la puede enviar el dispositivo o el controlador para solicitar al otro que configure su canal de DMA para proceder con una o más transferencias de datos. Este es el mecanismo para iniciar una transferencia por el método de First-Party DMA. Es un nuevo método de transferencias en SATA que no soportan los dispositivos ni el software heredado, en el cual el propio dispositivo SATA gestiona el canal de DMA 46 para acceso directo a la memoria del sistema. El mecanismo es más eficiente que los mecanismos DMA heredados (Multiword DMA y UDMA). • FIS BIST Activate – Bidireccional Esta FIS la puede enviar el dispositivo o el controlador para solicitar al otro que se configure en un modo concreto de test (BIST = Built-In Self Test). • FIS PIO Setup – Dispositivo a Controlador Esta FIS la envía el dispositivo para indicar al controlador toda la información necesaria para la gestión de una transferencia de datos en modo PIO. Si son necesarias varias FIS de datos para completar la transferencia, el dispositivo envía una FIS PIO Setup por cada FIS de datos que se necesite transmitir. • FIS Dato – Controlador a Dispositivo o Dispositivo a Controlador (bidireccional) Esta FIS es la utilizada para transferir los datos como consecuencia de la ejecución de un comando de lectura o escritura en modo PIO, DMA o First-Party DMA. El dispositivo la usa para enviar datos al controlador (lectura) y el controlador para enviar datos al dispositivo (escritura). La longitud máxima de los datos es de 2,048 dwords, (8,192 bytes o 16 sectores de 512 bytes). 6.3.4 Nuevo bloque de registros SATA Los controladores SATA disponen de un bloque de registros adicional e independiente del bloque de registros estándar ATA, para permitir la gestión de las nuevas posibilidades exclusivas de SATA. Este nuevo bloque se denomina SATA SCRs (Status and Control Registers), y están organizados en 16 posiciones consecutivas de 32 bits. Los programas heredados no hacen uso de este nuevo bloque de registros. SATA define los primeros 3 de estos 16 registros: • Registro SStatus (Registro de Estado del interfaz SATA) Registro de sólo lectura que el controlador actualiza constantemente para dar información en tiempo real sobre el estado del interfaz y del controlador. • Registro SError (Registro de Error del interfaz SATA) Registro de lectura/escritura que el controlador actualiza con información sobre errores en el interfaz (un bit para cada tipo de error). El registro indica todos los errores acumulados desde que se borró por última vez. El software puede escribir en el registro para borrar los bits activados. • Registro SControl (Registro de Control del interfaz SATA) Registro de lectura/escritura por medio del cual el software puede controlar funciones del interfaz SATA. Las escrituras producen que el controlador o el interfaz SATA ejecuten alguna acción y las lecturas devuelven el último valor escrito. 47 6.3.5 Direccionamiento 48-bit El direccionamiento 48-bit es una opción que permite trabajar con discos de hasta 281,474,976,710,655 sectores. Estamos hablando de discos de más de 144 peta bytes de memoria (144,115,188,075,855,360 bytes). Además el número de sectores que se puede transferir con un solo comando se incrementa con la ampliación del registro contador de sectores a 16 bits. Los comandos válidos para este direccionamiento son: • • • • • • • • • • • • FLUSH CACHE EXT READ DMA EXT READ DMA QUEUED EXT READ MULTIPLE EXT READ NATIVE MAX ADDRESS EXT READ SECTOR(S) EXT READ VERIFY SECTOR(S) SET MAX ADDRESS EXT WRITE DMA EXT WRITE DMA QUEUED EXT WRITE MULTIPLE EXT WRITE SECTOR(S) EXT El direccionamiento 48-bit solo funciona con LBA (logical block address: dirección lineal del sector). Los dispositivos que implementan este tipo de direccionamiento son compatibles con el direccionamiento 28-bit anteriormente implementado. Toda la información sobre las compatibilidades se puede encontrar en la respuesta al comando Identify (anexo 2). En los dispositivos que implementan el direccionamiento 48-bit, el registro de características, el registro contador de sectores, los LBA bajo, medio y alto son de 16 bits del tipo FIFO. Cuando uno de estos registros se escribe, el contenido escrito se pone en la parte: “recientemente escrita”, y el contenido escrito anteriormente se pone en la parte: “anteriormente escrita”. Por ejemplo, cuando enviamos el comando Read Sector EXT a un dispositivo que implementa el direccionamiento 48 bit, las direcciones usadas son las descritas en la siguiente tabla. Registro “recientemente escrito” “anteriormente escrito” Características Contador de sectores Reservado Número de sectores (7:0) Reservado Número de sectores (15:8) LBA bajo LBA (7:0) LBA (31:24) LBA medio LBA (15:8) LBA (39:32) LBA alto LBA (23:16) LBA (47:40) Dispositivo Los bits 7 y 5 no importan. El bit LBA tiene que estar a 1. El bit DEV tiene que indicar el dispositivo. Los bits (3:0) están reservados. Reservado 48 Cuando se escribe el comando Read Sector se utiliza el direccionamiento 28-bit. Entonces el resultado es el descrito en la siguiente tabla. La descripción de estos registros es la misma que la descripción de los comandos. Registro “recientemente escrito” “anteriormente escrito” Características Nada Nada Contador de sectores Número de sectores (7:0) Nada LBA bajo LBA (7:0) Nada LBA medio LBA (15:8) Nada LBA alto LBA (23:16) Nada Dispositivo LBA (27:24) Nada El controlador debe leer el contenido “anteriormente escrito” del registro de características, el registro contador de sectores y los LBA alto, bajo y medio cuando el bit HOB del registro de control del dispositivo esta a 1, y después leer el contenido “recientemente escrito” de todos los registros. Si el bit HOB (bit 7) del registro controlador del dispositivo está a cero, el controlador lee el contenido “recientemente escrito” de los registros. La escritura a cualquier registro del bloque de comando causa la puesta a cero del bit HOB. El dispositivo indica la compatibilidad con el direccionamiento 48-bit en la respuesta al comando Identify. Además las palabras (103:100) contienen el número máximo más 1 de los LBA del dispositivo que son accesibles por los comandos del direccionamiento 48-bit. 49 6.3.6 Descripción de comandos Los comandos permiten al Host informar al dispositivo de las acciones que se pretenden hacer. Se trata de una serie de códigos que hacen referencia a cada acción. Los comandos se sirven escribiendo primero, en los registros correspondientes, los parámetros necesarios para la ejecución del mismo y después escribiendo el código del comando en el registro de comandos. Los registros que se deben escribir dependen del comando, por esta razón vamos a indicarlos con un contenido especifico en el apartado Entradas de cada comando. La descripción de cada comando tendrá unos sub-apartados: • Descripción: descripción de la función del comando. • Código del comando: especifica el código para este comando. • Protocolo: especifica el protocolo usado por el comando. • Entradas: describe los datos de los diferentes registros que subministrará el Host • Respuesta normal: describe los datos devueltos del disco cuando se finaliza la ejecución del comando. • Respuesta a error: describe los datos devueltos por el disco cuando se produce un error. • Prerrequisitos: describe las condiciones iníciales necesarias. A continuación vamos a ver la descripción de algunos comandos que se han utilizado en la realización del código del programa de gestión del disco duro. 6.3.5.1 Read Sectors Descripción: Este comando lee entre 1 y 256 sectores depende del número que se carga en el registro de cuenta de sectores. Si cargamos un 0 en este registro se transfieren 256 sectores. La transferencia empieza a partir del sector especificado en los registros LBA alto, medio y bajo y el registro del dispositivo. El bit DRQ está siempre a 1 antes de una trasferencia de datos independientemente de la presencia de una condición de error. El disco debe interrumpir por cada transferencia de bloque DRQ. Código del comando: 20h Protocolo: PIO Data-in Entradas: 50 • Sector count (registro de cuenta de sectores): el número de sectores que se pretenden transferir. • LBA Low (LBA bajo): la parte más baja del número de sector (7:0) se carga en este registro. • LBA Mid (LBA medio): en este registro se cargan los bits (15:8) del numero del sector. • LBA High (LBA alto): los bits (23:16) del LBA. • Device (registro del dispositivo): El bit DEV selecciona el dispositivo 0 o 1 y los bits (3:0) es donde se escriben los bits (27:24) del LBA Respuesta normal: • Registro del dispositivo (device): DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando la finalización del comando - DRDY se pone a 1. - DF se pone a 0. - DRQ y ERR se ponen a 0. Respuesta a error: Cualquier error encontrado durante la ejecución del comando causa la finalización de todo el procedimiento. El bloque de registros de comando tiene la dirección del primer sector donde ocurrió el error. • Registro de error: - UNC se pone a 1 cuando los datos no son correctos. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. 51 - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. Prerrequisitos: DRDY tiene que estar a 1 52 6.3.5.2 Read Sectors EXT Descripción: Este comando lee entre 1 y 65,536 sectores depende del número que se carga en el registro de cuenta de sectores. Si cargamos un 0 en este registro se transfieren 65,536 sectores. La transferencia empieza a partir del sector especificado en los registros LBA alto, medio y bajo y el registro del dispositivo. El bit DRQ está siempre a 1 antes de una trasferencia de datos independientemente de la presencia de una condición de error. El disco debe interrumpir por cada transferencia de bloque DRQ. Todos los comandos EXT sirven para direccionamiento 48-bit y no son compatibles con el modo 28-bit. Código del comando: 24h Protocolo: PIO data-in Entradas: * La explicación de procedimiento a seguir para escribir estos registros esta en el apartado direccionamiento 48-bit. • En el registro del dispositivo: el bit LBA se tiene que poner a 1 para indicar que la dirección especificada es un LBA. El bit DEV indica el dispositivo seleccionado. Respuesta normal: La respuesta normal es idéntica a la respuesta normal del comando Read sector. 53 Respuesta a error: La respuesta a error es idéntica a la respuesta a error del comando Read sector. Prerrequisitos: DRDY tiene que estar a 1. 54 6.3.5.3 Write Sectors Descripción: Este comando escribe entre 1 y 256 sectores depende del número que se carga en el registro de cuenta de sectores. Si cargamos un 0 en este registro escribimos 256 sectores. El disco debe interrumpir por cada transferencia de bloque DRQ. Código del comando: 30h Protocolo: PIO data-out Entradas: Los registros LBA bajo, medio y alto y el registro del dispositivo especifican la dirección del primer sector que va a ser escrito. En el registro de cuenta de sectores se debe especificar el número de sectores que se pretenden escribir. Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 55 Respuesta a error: Cualquier error encontrado durante la ejecución del comando causa la finalización de todo el procedimiento. El bloque de registros de comando tiene la dirección del primer sector donde ocurrió el error. • Registro de error: - WP se pone a 1 cuando el dispositivo está protegido contra escritura. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. Prerrequisitos: DRDY tiene que estar a 1. 56 6.3.5.4 Write Sectors EXT Descripción: Este comando escribe entre 1 y 65,536 sectores depende del número que se carga en el registro de cuenta de sectores. Si cargamos un 0 en este registro escribimos 65,536 sectores. El disco debe interrumpir por cada transferencia de bloque DRQ. Este comando es para direccionamiento 48-bit. (Véase el apartado direcc. 48-bit) Código del comando: 34h Protocolo: PIO data-out Entradas: Los registros LBA alto, medio y bajo deben ser escritos con la dirección del primer sector donde se empezará a escribir. (La forma de escribir estos sectores está explicada en el apartado direccionamiento 48-bit). El bit DEV especifica el dispositivo que se pretende escribir. 57 Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 Respuesta a error: Cualquier error encontrado durante la ejecución del comando causa la finalización de todo el procedimiento. El bloque de registros de comando tiene la dirección del primer sector donde ocurrió el error. Los bits de la respuesta a error son idénticos a los bits de la respuesta a error del comando Write sector. Lo único que cambia es la dirección del LBA que está codificada con 48 bits. Prerrequisitos: DRDY tiene que estar a 1. 58 6.3.5.5 Read multiple Descripción: Este comando lee el número de sectores especificado en el registro de cuenta de sectores. El número de sectores por bloque esta especificado en la palabra 59 de la respuesta al comando Identify Device. Cuando se manda el comando Read multiple, el registro de cuenta del dispositivo debe contener el número de sectores (no de bloques) solicitados. El dispositivo debe interrumpir por cada bloque enviado. Si el número de sectores no es divisible por el número de bloques, se mandan antes los bloques completos y después, al final, se manda el bloque parcial. Si se intenta mandar este comando mientras está desactivada está opción, la respuesta será abortar el comando. Cuando se encuentra un error se publica la dirección del principio del bloque completo o parcial. Pero el bit DRQ se mantiene a 1 y la transferencia de datos se hace igualmente. El controlador debe reintentar la transferencia a partir de esa dirección. El comando se continúa ejecutando solo cuando hay un error en los datos. Los demás errores causan la interrupción de la operación por completo. Código del comando: C4h Protocolo: PIO data-in Entradas: • Sector Count: especifica el número de sectores que se quieren transferir. • LBA alto, medio, bajo y registro del dispositivo especifican el primer sector donde se empieza la transferencia. • DEV selecciona el dispositivo sobre el cual se realizará la operación. Prerrequisitos: DRDY tiene que estar a 1. 59 Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 Respuesta a error: • Registro de error: - UNC se pone a 1 cuando los datos no son correctos. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. 60 6.3.5.6 Read multiple EXT Descripción: Este comando tiene la misma función que el comando Read Multiple. La diferencia entre los dos se basa en que este comando es para direccionamiento 48-bit y el segundo es para 28 bits. Este comando permite transferir hasta 65,536 sectores en lugar de 256. Código del comando: 29h Protocolo: PIO data-in Entradas: Respuesta normal: La respuesta normal es idéntica a la del comando Read multiple. Respuesta a error: La respuesta a error es idéntica a la del comando Read multiple. Prerrequisitos: Los prerrequisitos son los mismos. 61 6.3.5.7 Write multiple Descripción: Este comando escribe el número de sectores especificado en el registro de cuenta de sectores. El número de sectores por bloque esta especificado en la palabra 59 de la respuesta al comando Identify Device. Cuando se manda el comando Write multiple, el registro de cuenta del dispositivo debe contener el número de sectores (no de bloques) solicitados. El dispositivo debe interrumpir por cada bloque enviado. Si el número de sectores no es divisible por el número de bloques, se mandan antes los bloques completos y después, al final, se manda el bloque parcial. Si se intenta mandar este comando mientras está desactivada está opción, la respuesta será abortar el comando. Cuando se encuentra un error se publica la dirección del principio del bloque completo o parcial. La operación se interrumpe aunque el dispositivo este escribiendo un sector que está en el medio del bloque. A partir de allí no se envía ningún bloque. Código del comando: C5h Protocolo: PIO data-out Entradas: Los registros LBA alto, medio y bajo y el registro del dispositivo especifican el primer sector que se tiene que escribir. El registro contador de sectores especifica el numero de sectores que se deben escribir. Si en el registro contador se escribe un cero, el número de sectores que se van a transferir es 256. El bit DEV selecciona el dispositivo sobre el cual se desea trabajar. 62 Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 Respuesta a error: • Registro de error: - WP se pone a 1 cuando el dispositivo está protegido contra escritura. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. 63 - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. Prerrequisitos: DRDY tiene que estar a 1. 64 6.3.5.8 Write multiple EXT Descripción: Este comando tiene la misma función que el comando Write Multiple. La diferencia entre los dos se basa en que este comando es para direccionamiento 48-bit y el segundo es para 28 bits. Este comando permite transferir hasta 65,536 sectores en lugar de 256. Código del comando: 39h Protocolo: PIO data-out Entradas: Respuesta normal: La respuesta normal es idéntica a la del comando Write multiple. Respuesta a error: La respuesta a error es idéntica a la del comando Write multiple. Prerrequisitos: Los prerrequisitos son los mismos. 65 6.3.5.9 Read DMA Descripción: El comando Read DMA permite al Host leer datos usando el protocolo DMA en la transferencia de datos. Código del comando: C8h Protocolo: DMA Entradas: • Sector Count especifica el número de sectores que se pretenden transferir. • El bit DEV selecciona el dispositivo. • LBA alto, medio y bajo y el registro del dispositivo contienen la dirección del primer sector. Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 66 Respuesta a error: Cualquier error encontrado durante la ejecución del comando causa la finalización de todo el procedimiento. El bloque de registros de comando tiene la dirección del primer sector donde ocurrió el error. • Registro de error: - ICRC se tiene que poner a 1 cuando ocurre un error en la interfaz durante la transferencia de datos vía Ultra DMA - UNC se pone a 1 cuando los datos no son correctos. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. Prerrequisitos: DRDY tiene que estar a 1 y el controlador debe inicializar el canal DMA. 67 6.3.5.10 Read DMA EXT Descripción: El comando Read DMA EXT permite al Host leer datos usando el protocolo DMA en la transferencia de datos. Este comando es para direccionamiento 48-bit. Código del comando: 25h Protocolo: DMA Entradas: Respuesta normal: La respuesta normal es idéntica a la del comando Read DMA. Respuesta a error: La respuesta a error es idéntica a la del comando Read DMA. Prerrequisitos: Los prerrequisitos son los mismos. 68 6.3.5.11 Write DMA Descripción: El comando Read DMA EXT permite al Host escribir datos usando el protocolo DMA en la transferencia de datos. Código del comando: CAh Protocolo: DMA Entradas: Los registros LBA alto, medio y bajo y el registro del dispositivo especifican el primer sector que se tiene que escribir. El registro contador de sectores especifica el numero de sectores que se deben escribir. Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 69 Respuesta a error: • Registro de error: - ICRC se tiene que poner a 1 cuando ocurre un error en la interfaz durante la transferencia de datos vía Ultra DMA. - WP se pone a 1 cuando el dispositivo está protegido contra escritura. - MC se pone a 1 si media cambió desde el último comando ejecutado. El dispositivo debe pone este bit a cero más tarde. - IDNF se pone a 1 cuando no se encuentra una dirección accesible por el usuario. Este bit se pone a 1 cuando la dirección solicitada no está dentro del rango de direcciones accesibles por el dispositivo siempre y cuando bit de comando abortado no se ha activado. - MCR se pone a 1 cuando hay una petición de cambio de media de un dispositivo de media removible. - ABRT se pone a 1 cuando el comando no es compatible o bien el dispositivo no puede cumplir las acciones requeridas por el comando. Este bit se tiene que poner a 1 cuando se sale del rango de direcciones permitidas siempre y cuando IDNF no se active. • LBA bajo, LBA medio, LBA alto y registro del dispositivo: estos registros contienen la dirección del primer error ocurrido. El bit DEV indica el dispositivo seleccionado. • Registro de estado: - BSY se pone a 0 indicando el fin de ejecución del comando. - DRDY se pone a 1. - DF se tiene que poner a 1 si hay un fallo del dispositivo. - DRQ se tiene que poner a 0 - ERR se tiene que poner a 1 cuando se trata de un error indicado por los bits del registro de error. Prerrequisitos: DRDY tiene que estar a 1 y el controlador debe inicializar el canal DMA. 70 6.3.5.12 Write DMA EXT Descripción: El comando Write DMA EXT permite al Host escribir datos usando el protocolo DMA en la transferencia de datos. Este comando es para direccionamiento 48-bit. Código del comando: 35h Protocolo: DMA Entradas: Respuesta normal: La respuesta normal es idéntica a la del comando Write DMA. Respuesta a error: La respuesta a error es idéntica a la del comando Write DMA. Prerrequisitos: Los prerrequisitos son los mismos. 71 6.3.5.13 Identify Device Descripción: El comando Identify permite al Host recibir información del dispositivo. Algunos dispositivos necesitan leer los datos con cierto orden para completar el comando. Cuando se envía este comando, el dispositivo pone a 1 el bit BSY del registro de estado y se prepara para enviar 256 palabras de identificación del mismo al controlador, pone el bit DRQ a 1, desactiva el BSY y interrumpe al Host. Entonces es cuando el controlador empieza a recuperar los datos leyendo del registro de datos. El anexo 2 contiene la explicación con detalle de la información que contienen estas 256 palabras. Algunos parámetros superan el tamaño de un Word (16 bits), entonces lo que se hace es dividir el parámetro en varios Word ordenados. Código del comando: ECh Protocolo: PIO data-in Entradas: * En este caso lo único que se tiene que especificar es el dispositivo mediante el bit DEV. 72 Respuesta normal: • • • • El bit DEV indica el dispositivo seleccionado. El bit BSY se pone a cero cuando se cumple la ejecución del comando. El bit DRDY se pone a 1. Los bits DF, DRQ, ERR se ponen a 0 Respuesta a error: Los dispositivos no deben presentar en ningún error haciendo ejecutando este comando. Prerrequisitos: DRDY tiene que estar a 1. 73 6.3.5.14 Device reset Descripción: El comando Device reset permite al host resetear un solo dispositivo sin afectar a los otros dispositivos. Código del comando: 08h Protocolo: Device reset. Entradas: * En este caso lo único que se tiene que especificar es el dispositivo mediante el bit DEV. Respuesta normal: • El resultado del diagnostico se especifica en el registro de error. • El bloque de registros de comando se carga con la firma. • El registro de estado se pone a su estado normal: o El bit BSY se pone a cero cuando se cumple la ejecución del comando. o El bit DRDY se pone a 1. o Los bits DF, DRQ, ERR se ponen a 0 Respuesta a error: Si el dispositivo es compatible con este comando, no tiene que haber ningún error. Si este comando no es compatible y los bits BSY o DRQ están a 1, el resultado es indeterminado. En cambio, si no lo están el dispositivo activará el bit Comando abortado del registro de error. 74 6.4 SATA II A partir del desarrollo de SATA se han abierto nuevas líneas de trabajo, todas ellas recogidas bajo el nombre genérico de SATA II. Estas líneas y sus principales características (por ahora) son: 6.4.1 Extensiones de SATA Define una serie de extensiones sobre la especificación original SATA, que añaden nuevas posibilidades manteniendo la compatibilidad. Las extensiones pueden adoptarse por separado y según convenga por razones de mercado. Las más significativas son: • Una extensión a nivel eléctrico que permite la conexión de los controladores SATA II a un panel de conectores de 18”, de forma que los dispositivos actuales SATA se puedan conectar a dicho panel. Está enfocado a permitir la construcción de Arrays de discos (JBODs y RAIDs) en un rack estándar de 19” utilizando los servicios de cabinas de discos estándar tanto SAFTE (SCSI Accessed Fault-Tolerant Enclosure) como SES (SCSI Enclosure Services), las cuales se pueden conectar a un controlador SATA II (controlador normal o controlador RAID) o a cualquier otro sistema de interconexión como pueda ser Fibre Channel, Infiniband, Gigabit Ethernet (iSCSI), etc. • Nuevos comandos de lectura/escritura que utilizan un nuevo modelo de encolado nativo de comandos. El nuevo modelo de encolado está basado en el modelo heredado ATA, aunque con algunos aspectos modificados para aprovechar las nuevas posibilidades que ofrece SATA. Los dispositivos pueden encolar hasta 32 comandos y utilizan el mecanismo nativo First-Party DMA para ejecutar las transferencias de datos. • Nuevo método de notificación de eventos (Notificación Asíncrona), en la que el dispositivo avisa directamente al controlador cuando sucede un evento que requiera su atención (por ejemplo, la inserción de una media en un dispositivo de medios removibles). Esta función elimina la necesidad de que el controlador esté continuamente interrogando a los dispositivos para comprobar si ha sucedido un evento. 6.4.2 Multiplicador de Puertos Define un mecanismo al estilo de un multiplexor, mediante el cual el controlador SATA II junto con nuevo software nativo puede comunicarse con diferentes dispositivos SATA, en concreto hasta con un máximo de 15. La arquitectura está pensada para que un sistema con software heredado (BIOS y drivers actuales) o que disponga de un controlador SATA (o SATA II que no implemente la gestión del Multiplicador) pueda arrancar el sistema y trabajar con un dispositivo SATA conectado al puerto 0 del Multiplicador. Principalmente está enfocado a la construcción de Arrays de discos (a los que sólo hay que hacerles llegar una o dos líneas SATA, permitiendo mediante Multiplicadores internos al Array la conectividad con hasta 15 discos por cada línea SATA de entrada) y 75 la ampliación de puertos en equipo móviles (por ejemplo, integrando el Multiplicador en la dock-station). Otras características del Multiplicador son el soporte de hot-plug, el arranque controlado de los discos y la Notificación Asíncrona para avisar al controlador sobre nuevas conexiones de dispositivos a los puertos. El controlador SATA II puede gestionar el acceso a los dispositivos de dos formas, lo cual es independiente del Multiplicador en sí: • Cambio de contexto por comando: Los controladores que soportan este modo de gestión sólo pueden enviar comandos a los dispositivos de uno en uno. Sólo un dispositivo puede en cada momento estar ejecutando un comando. • Cambio de contexto por trama: Los controladores que soportan este modo de gestión pueden enviar comandos a todos los dispositivos concurrentemente. 6.4.3 Selector de Puerto Define un mecanismo, al estilo también de un multiplexor, que permite a dos controladores SATA (junto con nuevo software nativo) acceder a un dispositivo SATA, creando un acceso redundante. No está pensado como sistema multi-controlador en el que los dos controladores acceden concurrentemente al dispositivo, sino como sistema tolerante a fallo en el que un controlador es el activo y el otro es el de repuesto, a modo de hot-spare, que toma el control cuando el controlador activo falla. 6.4.4 Cables y Conectores Define distintas mejoras sobre la especificación SATA para permitir la conexión de dispositivos SATA en entornos servidores y de red, definiendo tanto las conexiones internas (entre la placa base o placa controladora y un panel de conectores), como las conexiones externas (entre un servidor y un Array externo situado en la misma cabina). 76 7 El lenguaje de programación C El lenguaje de programación C fue creado entre 1970 y 1972 por Brian Kernighan y Dennis Ritchie para escribir el código del sistema operativo UNIX. Desde su nacimiento se fue implantando como el lenguaje de programación de sistemas favorito para muchos programadores, sobre todo por ser un lenguaje que conjugaba la abstracción de los lenguajes de alto nivel con la eficiencia del lenguaje máquina. Los programadores de sistemas que trabajaban sobre MS-DOS y Macintosh también utilizaban C, con lo cual la práctica totalidad de aplicaciones de sistema para microordenadores y para sistemas UNIX está escrita en este lenguaje. A mediados de los ochenta el C se convierte en un estándar internacional ISO. Este estándar incluye tanto la definición del lenguaje como una enorme biblioteca de funciones para entrada / salida, tratamiento de textos, matemáticas, etc. A mediados de los ochenta se crea el C++, extensión de C orientada a objetos. El C++ se convierte en estándar ISO en 1998. En el momento actual, el lenguaje C no va a modificarse más. Será el C++ el que incorporará nuevos cambios. El lenguaje C es el resultado de un proceso de desarrollo que inició con un lenguaje denominado BCPL. Este influenció a otro llamado B (inventado por Ken Thompson). En los años 70; éste lenguaje llevó a la aparición del C. Con la popularidad de las microcomputadoras muchas compañías comenzaron a implementar su propio C por lo cual surgieron discrepancias entre sí. Por esta razón ANSI (American National Standars Institute, por sus siglas en inglés), estableció un comité en 1983 para crear una definición no ambigua del lenguaje C e independiente de la máquina que pudiera utilizarse en todos los tipos de C. Algunos de las C existentes son: Quick C, C++, Turbo C, Turbo C ++, Borland C, Borland C++, Microsoft C, etc. C es un lenguaje de programación de nivel medio ya que combina los elementos del lenguaje de alto nivel con la funcionalidad del ensamblador. Su característica principal es ser portable, es decir, es posible adaptar los programas escritos para un tipo de computadora en otra. Otra de sus características principales es el ser estructurado, es decir, el programa se divide en módulos (funciones) independientes entre sí. El lenguaje C inicialmente fue creado para la programación de: Sistemas operativos, Intérpretes, Editores, Ensambladores, Compiladores, Administradores de bases de datos. Actualmente, debido a sus características, puede ser utilizado para todo tipo de programas. 77 El C es un lenguaje de programación de propósito general, Sus principales Características son: • • • • • • • • • Programación Estructurada Economía en las expresiones Abundancia en operadores y tipos de datos Codificación de Alto y Bajo nivel simultáneamente Reemplaza ventajosamente la programación en ensamblador Utilización natural de las funciones primitivas del sistema No está orientado a ningún área en especial Producción de código objeto altamente optimizado Facilidad de aprendizaje Los tipos básicos de datos eran "CHAR" (carácter), "INT" (enteros), "FLOAT" (Reales en simple precisión), y "DOUBLE" (Reales en doble Precisión). Posteriormente se añadieron los tipos "SHORT" (Enteros de longitud<=longitud de un int), "LONG" (Enteros de longitud >= longitud de un entero), "UNSIGNED" (Enteros sin signo), y "ENUMERACIONES". Los tipos estructurados básicos de C son las estructuras, las uniones, y los arrays. Estos permiten la definición y declaración de tipos de mayor complejidad. Las instrucciones de control de flujo de C son las habituales de la programación estructurada: IF, FOR, WHILE, SWITCH - CASE, todas incluidas en su predecesor BCPL. C incluye también punteros y funciones. Los argumentos de las funciones se pasan por valor, esto es copiando su valor, lo cual hace que no se modifiquen los valores de los argumentos en la llamada. Cuando se desea modificar los argumentos en la llamada, éstos se pasan por referencia, es decir, se pasan las direcciones de los argumentos. Por otra parte, cualquier función puede ser llamada recursivamente. Una de las peculiaridades de C es su riqueza de operadores. Puede decirse que prácticamente dispone de un operador para cada una de las posibles operaciones en código máquina. Hay toda una serie de operaciones que pueden hacerse con el lenguaje C, que realmente no están incluidas en el compilador propiamente dicho, sino que las realiza un preprocesador justo antes de cada compilación. Las dos más importantes son #define (directriz de sustitución simbólica o de definición) e #include (Directriz de inclusión en el fichero fuente) Finalmente, C, que ha sido pensado para ser altamente transportable y para programar lo improgramable, igual que otros lenguajes tiene sus inconvenientes. Carece de instrucciones de entrada/salida, de instrucciones para manejo de cadenas de caracteres, con lo que este trabajo queda para la librería de rutinas, con la consiguiente pérdida de transportabilidad. La excesiva libertad en la escritura de los programas puede llevar a errores en la programación que, por ser correctos sintácticamente no se detectan a simple vista. Por otra parte las precedencias de los operadores convierten a veces las expresiones en pequeños rompecabezas. A pesar de todo, C ha demostrado ser un lenguaje extremadamente eficaz y expresivo. 78 8 Desarrollo del software Una vez vista la información sobre el hardware que vamos a necesitar para el desarrollo del proyecto, empezamos con el análisis del software. Como ya se ha comentado en la introducción, para la realización de este proyecto partimos de un software heredero que vamos a modificar para conseguir cumplir las especificaciones inicialmente concretadas. El programa heredero, creado por el profesor Esteban Del Castillo, dispone de 12 archivos del tipo *.C y 12 archivos de cabecera. En este caso podemos distinguir entre los ficheros que controlan la parte gráfica y los de la parte funcional, aunque a veces, a nivel de enlace entre las dos partes, hay algunos ficheros que contienen variables compartidas. Es importante decir que la modificación de la parte funcional impone una modificación parcial de la gráfica. Pues con la actualización del software se necesitarán más variables, más espacio para visualizarlas y también nuevas técnicas de conversión del contenido introducido por el usuario. Figura 10. Diagrama de flujo simplificado. En azul el inicio, en verde las opciones que se pueden seleccionar y en rojo partes que se ejecutan automáticamente. 79 8.1 Parte gráfica: Se trata de una interfaz de usuario ya implementada junto con el software heredero. Está compuesta básicamente por siete archivos del tipo *.C mas los correspondientes archivos de cabecera. Hay un archivo para cada función: editar, copiar, buscar, comparar y configurar y dos archivos para los menús que aparecen por pantalla. El funcionamiento básico de una función cualquiera de las cinco mencionadas anteriormente es visualizar las ventanas correspondientes a la opción seleccionada y en el mismo tiempo ejecutar las rutinas necesarias para completar dicha función. El lazo entre la parte funcional y la parte grafica viene después de saber el deseo del cliente (mediante la lectura de la tecla), que es realmente cuando se ejecutan las funciones de acceso al disco duro. Una vez obtenidos los datos del disco, cada opción los trata de forma distinta. Esta parte del código es totalmente válida puesto que está diseñada de forma prácticamente independiente de la parte funcional. Lo que nos interesa ahora es ampliar los límites establecidos para el acceso a los discos IDE. Estos límites básicamente son los espacios reservados para la visualización en la pantalla y también las variables que introduce el usuario. La modificación de los espacios en pantalla es más simple que la de las variables. Pues solo hay que localizar donde se escribe por pantalla y después modificar los parámetros. Esta interfaz está diseñada de forma muy inteligente puesto que hay una única función que dibuja las ventanas. Se trata de modificar las variables de tamaño de las ventanas en las rutinas de las diferentes opciones. Figura 11. Uno de los cambio del aspecto de la interfaz La modificación de las variables es más compleja, pues todas las conversiones de ASCII a binario se hacen para que el resultado sea una variable del tipo long (32 bits). A causa del gran aumento de la memoria de los discos, ciertas variables, como por 80 ejemplo el número del sector, son insuficientes para guardar los valores. Por esta razón se emplearán nuevas técnicas de conversión para guardar en 2 variables del tipo long en lugar de una. Disponíamos de una función que hace esta conversión pero que el resultado era una sola variable. La nueva función se planteo con una idea prácticamente diferente. Pues la primera obtiene el número tecleado por el usuario, lo guarda en un string4, después utiliza la base 10 para calcular la cifra exacta. Ejemplo: si el usuario teclea un 9, un 1 y un 8 para obtener el número 918 se hace lo siguiente: El string queda así: 9 1 8 Entonces lo que se hace es: 8*1 + 1*10 + 9*100 = 918 Equivale a: 8*10^0 + 8*10^1 + 8*10^2 = 918 El numero 918 se guarda en una variable del tipo long. ¿La pregunta ahora es: que pasa si el usuario teclea un número mayor que 4.294.967.295 (máximo valor que una variable del tipo long permite guardar)? La respuesta es que no se guardará el valor correcto y se limitará como máximo al valor anteriormente dicho. La idea de la nueva rutina es obtener el número correcto y guardarlo en tantas variables como sea necesario. Primero se hace la conversión del número tecleado a binario con la manera tradicional: resto de divisiones entre 2 y se guarda en otro string. De esta forma el string que contiene el resultado solo tendrá o un 1 o un 0 en cada casilla. El segundo paso es volver a convertir el número binario a decimal mediante potencias de 2, pero esta vez solo cogeremos los bits que suporta un long (32 bits). Entonces si por ejemplo tenemos 48 bits ocupados: hacemos la conversión de 32 bits y los guardamos en una variable y después hacemos la conversión de 16 bits y lo guardamos en otro variable. Es obvio que la segunda variable contiene la parte alta del número y la primera contiene la parte baja. Ejemplo: si el usuario teclea el valor 1.099.511.627.771 (posición de un sector). Se puede ver claramente que supera el límite de las variables long. Tenemos: 1 0 9 9 5 1 1 6 2 7 7 7 1 La conversión a binario: el string que guarda el resultado quedará así: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 1 1 4 Cadena de caracteres: es una secuencia ordenada de longitud arbitraria (aunque finita) de elementos que pertenecen a un cierto alfabeto. Desde el punto de vista de la programación, una cadena podrá estar formada por cualquier combinación finita de todo el juego caracteres disponibles. 81 Entonces en la primera variable vamos a guardar la conversión a decimal de los 32 bits (en naranja) y en la segunda variable guardamos la conversión a decimal de los 8 bits restantes (en azul). El resultado final será: Variable1: 0xFFFFFFFB y Variable2: 0x000000FF 82 8.2 Parte funcional: Como ya se ha comentado anteriormente, disponemos de un programa para acceso a discos IDE de menos de 137 Gigabytes de memoria. La idea principal es modificar este programa para conseguir el acceso a discos SATA sin limitación de memoria. La explicación del funcionamiento de esta parte se hará de forma muy simplificada puesto que es un programa muy complejo. La parte funcional del programa heredero está compuesta por 4 ficheros de tipo *.C y un fichero *.asm (ensamblador) más los correspondientes ficheros de cabecera. En este programa vamos a trabajar sobre los tres ficheros esenciales: • Inicialización: disk_ini.c • Acceso al disco: ide_drv1.c • Atención a las interrupciones: ide_drv0.asm En el primer fichero se hace, entre otras cosas, la identificación de todos los dispositivos que están conectados a la CPU. Estas rutinas se encargan de decidir si el acceso será normal (disco duro) o bien por la BIOS en caso de disquetera. En el primer caso se manda un comando de identificación a los discos. El tratamiento de la información se hace en rutinas del segundo y tercer fichero. Una de las funciones más importantes de las rutinas de inicialización es la determinación del modo de operación más eficiente para los discos duros. Esta opción se encarga de decidir el modo de acceso al disco (sea lectura o escritura). Las opciones son: lectura o escritura de un solo sector, de varios sectores (con el protocolo PIO) o bien, si el disco lo permite, el uso del modo Ultra DMA. La decisión del modo más eficiente se hace asociando un comando determinado, de los que hacen que el disco opere con los modos anteriores, a las dos opciones: lectura y escritura Para el acceso a discos que implementan el direccionamiento 48-bit, los comandos son diferentes. Para cada opción vamos a tener que emplear unos condicionales extras para saber si el disco es de direccionamiento 48-bit o bien de 28-bit. La variable que contiene la información sobre el tipo de direccionamiento que suporta el disco se inicializa mediante el comando Identify device. Una vez ya conocidos los comandos que el Host debe enviar al dispositivo, empieza el funcionamiento normal. El segundo fichero contiene rutinas para acceso al disco. Estas rutinas se encargan de proporcionar la información necesaria al disco para ejecutar los comandos mediante la programación de los registros. En el caso del comando Identify Device enviado desde las rutinas de inicialización, las rutinas de acceso al disco (disk_access( ) y x_disco( )), aparte de programar los registros con la información necesaria, se encargan de identificar la información que devuelve el dispositivo. La información que nos interesa es el número de serie del dispositivo, la revisión del firmware, el modelo del disco, la compatibilidad con transferencia de bloque, los modos PIO, los modos Ultra DMA, el número de sectores del disco, la compatibilidad con el modo Multiword DMA. 83 Toda esta información es totalmente útil para los discos SATA. Pero aparte de ésta, vamos a necesitar una variable que indicará si el dispositivo es compatible con el direccionamiento 48-bit y también vamos a necesitar dos variables del tipo long para guardar en número máximo de sectores a los que se puede acceder. El comando Identify device sirve para todos los tipos de discos. Por lo tanto, se puede ejecutar antes de saber el tipo de direccionamiento del disco. Es evidente que si no fuera así, nunca sabríamos de qué tipo es el disco puesto que el mismo comando es el encargado de devolver esta información. Para conservar el correcto funcionamiento del programa original, vamos a crear rutinas independientes de las originales. Eso supone crear otro “camino” en el flujo de programa. La variable que decide el recorrido del programa será la misma que contiene la información de compatibilidad con el direccionamiento 48-bit. Figura 12. Diagrama de flujo simplificado de la parte funcional. Una vez planteada la idea, vamos a crear unas rutinas compatibles con el programa original. En este sentido, todas las funciones tienen que ser fácilmente acopladas, es decir, tienen que tener las mismas entradas y las mismas salidas que las rutinas del programa heredero. 84 El acceso a los discos SATA con direccionamiento 48 bit está explicado en el apartado 6.3.5. El código fuente de las nuevas rutinas está en el Anexo 3, exactamente en el fichero IDE_DRV1.C. Este fichero contiene principalmente cuatro rutinas: dos para el acceso con direccionamiento 48-bit y dos para 28-bit. Las dos primeras rutinas y las dos segundas hacen prácticamente la misma función pero de forma distinta. Las rutinas disk_access28( ) y disk_access48( ) se encargan, entre varias cosas, de hacer inicializaciones especificas para cada comando preparando el acceso DMA o obteniendo el número de sectores para el acceso múltiple etc. En el caso del primer acceso al disco (identificación), estas rutinas se encargan de ordenar en variables distintas la información que devuelve el dispositivo. Las dos rutinas anteriormente mencionadas se encargan también de llamar a las funciones x_disco28( ) y x_disco48( ) respectivamente. La función principal de éstas es la programación de los registros con los diferentes valores que se necesitan para ejecutar un comando determinado y después esperar la respuesta del dispositivo. Aparte de esto, estas rutinas se encargan también de gestionar la respuesta a error del dispositivo, permitiendo al usuario darse cuenta mediante los distintos mensajes de error. El tercer fichero modificado es IDE_DRV0.asm. El fichero de código Assembler contiene rutinas de atención a las dos interrupciones que genera el disco duro (para los dos canales). La función de estas dos rutinas es idéntica, pues las dos se encargan del tratamiento de datos ya sea para una lectura (obteniendo datos del disco y guardándolos en memoria) o bien para una escritura (escritura desde la memoria al dispositivo). Éstas también se encargan de modificar el estado del flanco utilizado para saber si el dispositivo ha acabado o bien está ejecutando el comando. El fichero IDE_DRV0.asm también contiene funciones para el bus PCI. Son funciones para el acceso limitado al disco y a las disqueteras mediante el uso de la BIOS del sistema. El código fuente de todo el programa está comentado en el anexo 3. 85 8.3 Pasos para la realización del software Después de la explicación del funcionamiento del software me gustaría repasar un poco las etapas de realización de este proyecto. Pues me he encontrado con todo tipo de problemas pero gracias a la gran ayuda de mi tutor, los he podido superar. En este apartado del proyecto hablaré un poco de los problemas que han surgido. Lo primero que hice fue buscar información sobre los discos SATA. Creo que fue una de las etapas más difíciles del proyecto. La información que se podía encontrar en la web era sobre las características de estos discos y nunca sobre cómo acceder a éstos. Nunca me había imaginado que el mismo estándar de los discos IDE hablaba de los discos SATA en su octava edición. Una vez entendido aproximadamente como se puede acceder al disco, y para habituarme más al funcionamiento de éstos, mi tutor el profesor Esteban Del Castillo, me pidió hacer un programa que acceda a los dos tipos de discos, IDE y SATA. La interfaz no tenía importancia porque es un programa para practicar y aprender. Después de un tiempo trabajando sobre este programa conseguí acabarlo, y con esto tuve luz verde para comenzar la modificación del programa heredero. Figura 13. Captura de pantalla mientras se ejecuta el primer programa de acceso al disco. El programa heredero está compuesto por nada más y nada menos un total de 24 ficheros de código. Por suerte la mitad de estos pertenecían a la parte gráfica y no los tenía que modificar al principio. Estamos hablando de un programa súper complejo que se ha realizado en varios años. Entender el código de cada rutina, como estaba relacionada con las otras, cuando se le llama y que es lo que realmente hacía me llevo prácticamente la mitad del tiempo dedicado a esto proyecto. Obviamente, es más difícil entender el código de un programa ya hecho que hacerlo. La primera modificación que he realizado del proyecto no acaba de agradar, ya que había modificado las mismas rutinas añadiendo código para el acceso a los discos SATA y además no funcionaba como tenía que hacerlo. De allí salió la idea de hacer que el programa funcione solamente con SATA y más tarde conseguir los dos 86 funcionamientos a la vez. Eso supone la eliminación de las rutinas de acceso a discos IDE y crear otras funciones nuevas. Tardé dos meses en conseguir que el programa funcione con SATA, con este resultado pensé que prácticamente el programa está listo. Pues solo falta añadir las rutinas viejas y hacer que el programa sea compatible mediante unos cuantos condicionales. A causa de un problema inesperado con el compilador que utilizaba perdí mucho tiempo, ya que las modificaciones que hacía del código no daban ningún resultado positivo. Era el momento oportuno para solicitar ayuda de mi tutor el profesor Esteban. Él me dejó trabajar en su laboratorio utilizando su propio ordenador. La primera versión del programa que se ha realizado es para acceso a discos SATA de menos de 2,2 terabytes de memoria porque era el valor máximo que soportaban las variables del tipo long. La siguiente fase consistía en hacer que el programa acceso a todos los discos independientemente de su capacidad de almacenamiento. Para ello se modificaron varias variables y se introdujeron otras nuevas. Es obvio que introducir nuevas variables cause nuevas modificaciones de código, ya sea generando nuevas líneas o bien cambiando el mismo texto hecho anteriormente. Con cada modificación de la parte funcional, los cambios de la parte gráfica se requerían más. Era el momento de adaptar la interfaz al programa. Modificar las variables que usa ésta y la manera de obtener los valores es la parte esencial de la modificación, aparte claramente de la modificación de la apariencia y los espacios. Una vez hechas las modificaciones principales, me he dado cuenta que hay ciertas cosas que se tienen que cambiar para acabar de perfeccionar el programa. La idea es eliminar las líneas de código no necesarias, minimizar el número de variables utilizadas, tratar casos especiales de discos (algunos discos no llegan a 137GB de memoria pero implementan el direccionamiento 48-bit), etc. 87 9 Resultados finales El resultado final de todo el código explicado anteriormente presenta la siguiente forma visual de inicio: Figura 14. Pantalla principal del programa. Después de la presentación del programa y el mensaje de advertencia, podemos ver todos los discos que están conectados. En este caso solo se puede ver la disquetera porque el programa se ha ejecutado en Windows para hacer la captura de pantalla. Cuando se inicia el programa en MS-DOS se pueden ver los discos duros, disqueteras y también las unidades de memoria USB. Podemos ver en el centro de la pantalla las cinco opciones que el usuario puede seleccionar más la opción de salida. A continuación vamos a ver con detalle las diferentes opciones que ofrece este programa al usuario. Para hacer más entendible la explicación, ésta irá acompañada de una captura de pantalla hecha en Windows donde solamente se puede acceder a la disquetera. 9.1 La función Editar La opción de edición es la primera del menú. Ésta nos permite ver de forma explícita la información que tiene el disco. Esta información está en binario y en código ASCII. 88 Figura 15. Edición del disco En la parte superior de la pantalla podemos ver la información del disco como ahora el número de la unidad, el modelo (normalmente disquetera o disco duro), el número del sector y el cilindro-cabeza-sector (el primer sistema de direccionamiento para discos duros antes de que se crea el direccionamiento por el número del sector LBA). En la parte inferior podemos ver una pequeña guía para el usuario. Los comandos permitidos son F3 para editar cualquier bit de la tabla, F5 para guardar estos cambios, ESC para ver el menú, la flechas sirven para avanzar los sectores y los cilindros y para avanzar la cabezas usamos las teclas de avance de página. Las teclas inicio y fin también están habilitadas. Todo el resto de la pantalla se conserva para la visualización de la información. En cada pantalla solo se puede visualizar medio sector. En la parte izquierda podemos ver el offset de cada Word del sector. En la parte media están los datos en hexadecimal. Y en la parte derecha podemos ver los mismos datos pero en código ASCII. Si pulsamos la tecla ESC salta el menú de esta opción. Éste nos permite cambiar de unidad, ir al sector o al cilindro-cabeza-sector que deseamos o bien salir. 9.2 La opción Copiar Esta opción se creó para facilitar al usuario la transferencia de datos entre dos discos en un tiempo reducido. 89 Figura 16. Copiando datos del disco Esta opción nos permite seleccionar la unidad de origen donde se encuentran los datos que se tienen que copiar, la unidad de destino, el primer sector de donde empieza la transferencia, el primer sector del disco receptor, el numero de sectores (se puede seleccionar todo el disco o bien una cantidad en sectores o megabytes) y finalmente el archivo donde se guarda la información del procedimiento. Esta opción es muy útil para hacer copiar de seguridad con la totalidad de la información que contiene el disco, incluido el sistema operativo. Pues el nuevo disco solo necesitara ser instalado para hacer la misma función que el original. 9.3 La opción Comparar Esta opción nos permite comparar los datos de dos discos. La idea es seleccionar un determinado sector de inicio y empezar a comparar con otros sectores del otro disco. Figura 17. Comparación de datos de los discos 90 Cuando seleccionamos la opción Comparar del menú de inicio, nos salta esta pantalla donde podemos seleccionar las dos unidades que queremos comparar, los sectores de inicio de comparación, el número de sectores a comparar, el modo (con pausa o sin pausa) y el archivo donde se guarda la información. Una vez empieza la comparación, se abre un ventana donde se van a ver las diferencia entre los sectores comparados. Esta herramienta es muy eficaz para verificar que los datos que anteriormente se han copiado coinciden con la unidad de origen. 9.4 La opción Buscar La opción Buscar está diseñada para localizar cualquier dato en el todo el disco o bien en una parte del mismo. El dato buscado se puede especificar mediante números hexadecimales o bien caracteres del código ASCII. El programa especifica donde se encuentran estos datos y la cantidad de veces que aparecen. Figura 18. Búsqueda de datos en el disco La información que tenemos que proporcionar al disco para hacer la búsqueda es: la unidad donde se quiere buscar, el sector del cual empezará la búsqueda, el número de sectores a tratar, el modo de búsqueda (hexadecimal o ASCII), el patrón que se quiere localizar, el nombre del archivo donde se guardará la información del procedimiento. Cuando empieza el programa a buscar datos, nos muestra el sector donde se encuentra la información y cuantas veces se encuentra ese dato en un sector determinado. 91 9.4 La opción Configurar A diferencia de las otras opciones, la opción Configurar cada dispositivo según las preferencias del usuario. Nos permite determinar si el acceso es por la BIOS o bien mediante comandos del disco duro, el modo, las repeticiones, y la opción de guardar el procedimiento en un fichero Figura 19. Las opciones de configuración 92 10 Manual de instalación y uso 10.1 Instalación del disco duro SATA Los nuevos discos SATA son más simples de instalar que sus antecesores, los discos IDE. En esta guía hacemos referencia a la instalación física del disco para que la BIOS lo detecte y poder utilizar el programa. Lo primero que haremos es apagar y desconectar la CPU de la alimentación y fijar el disco en las ranuras del gabinete correspondiente. Luego, conectaremos el cable de datos del disco SATA; este cable de datos es muy probable que sea provisto junto al disco o junto con la placa base, sino es así, deberemos comprar un cable en cualquier negocio de informática. Una vez que tenemos el cable de datos del disco SATA, ubicaremos primero el conector SATA en la placa base (se suele encontrar en grupos de 2 o 4 conectores) y conectaremos allí uno de los extremos del cable (no importa cual extremo), el otro extremo lo conectaremos a la parte posterior del disco (el conector es una pequeña ficha con 7 pines). Por la forma que tiene la ficha solo tendremos una sola manera de conectarlo. Siguiendo con el proceso de instalación del disco SATA, ahora debemos conectar la alimentación al disco; el conector de alimentación puede ser el tradicional o el nuevo conector de alimentación SATA, este último es más pequeño que el anterior. El conector en nuestra CPU se encuentra en los cables que salen de la fuente de alimentación, y al igual que en el cable de datos solo lo podremos conectar de una manera. Si el disco SATA solo tiene el nuevo conector de alimentación y la fuente de alimentación no tiene estas fichas, tendremos que comprar un adaptador para poder completar la instalación. Figura 20. Cable de alimentación y de datos SATA Si ya hemos fijado el disco y conectado los cables de datos y alimentación habremos terminado de instalar el disco SATA en la CPU. Ahora, debemos encender la computadora e ingresar a la BIOS para ver que el mismo haya sido detectado correctamente. 93 10.2 Instalación del sistema operativo MS-DOS Como ya se ha comentado anteriormente, el programa esta diseñado para trabajar en MS-DOS. Por lo tanto, lo primero que se debe hacer es instalar este sistema operativo. Actualmente, la manera más simple de trabajar con este sistema operativo es instalarlo en un disco extraíble. Antes de empezar la instalación debemos descargar los archivos de MS-DOS y la herramienta HP_USB Storage Format Tool disponibles en la web. Los pasos a seguir son: 1. Instalar el programa HP_USB Storage Format Tool. 3. Conectar el dispositivo USB. 4. Formatear el dispositivo USB utilizando la utilidad HP_USB Storage Format Tool. Figura 21. Ejecución de la herramienta HP_USB Storage Format Tool Atención a la casilla que está debajo de “using DOS system files locates at:” se tiene que poner el subdirectorio donde se ha descomprimido el sistema operativo DOS. 94 5. Copiar todos los archivos auxiliares del SO al dispositivo USB. 6. Para arrancar del dispositivo USB lo primero que se tiene que hacer es entrar en el menú SETUP del ordenador en el momento de la arrancada. Posteriormente se tiene que cambiar la prioridad de dispositivos en el menú HDD boost priority, situado en la opción Advanced o Boost del menú Setup y colocar en primer lugar el dispositivo USB. 7. Salimos del menú SETUP guardando los cambios y a partir de entonces, cada vez que arrancamos con el dispositivo USB conectado, el ordenador arrancará con el DOS. Copiamos en Windows el ejecutable del programa al disco extraíble. Después iniciamos el ordenador con el pen conectado, y una vez dentro del sistema operativo ejecutamos el programa. 95 11 Presupuesto El presupuesto necesario para el desarrollo de este proyecto es el siguiente: Descripción Unidades Disco duro SATA 750GB Cable SATA Datos+Alimentación Memoria USB 1GB 1 Ud. 1 Ud. 1 Ud. Precio unitario 86,99 €/Ud. 5,86 €/Ud. 10,45 €/Ud. Preparación de la memoria USB. Horas de desarrollo del software TOTAL 0,5 h 320 h 35 €/h 35 €/h Precio total 86,99 € 5,86 € 10,45 € 17,50 € 11200 € 11320,80 € Si se prevén unas ventas de 1000 unidades para amortizar el coste de desarrollo del proyecto, el precio de venta de cada unidad de producto es el siguiente: Amortización Coste del disco duro por unidad 86,99 € Coste del material por unidad 16,31 € Coste de horas de preparación de la memoria USB por unidad 10,00 € Coste de amortización del desarrollo del proyecto 11,20 € SUBTOTAL 124,50 € Si queremos obtener un beneficio del 10% 12,45 € TOTAL 136,95 € En caso de que el usuario disponga de un disco duro SATA y solo necesite la memoria USB con el programa: Amortización Coste del material por unidad 10,45 € Coste de horas de preparación de la memoria USB por unidad 10,00 € Coste de amortización del desarrollo del proyecto 11,20 € Si queremos obtener un beneficio del 10% 3,17 € TOTAL 34,82 € El coste de horas de preparación de la memoria USB por unidad asciende a 10,00 €, debido a que para la preparación se ha tenido en cuenta que se puede hacer por una persona con calificación de Ciclo Formativo de Grado Medio en informática. Tomando como sueldo para esta calificación 20 €/h, y teniendo en cuenta que toda la instalación se puede hacer en media hora, el precio final de la preparación de la unidad USB es 10,00 €. 96 12 Conclusiones Después de un cierto tiempo buscando información para realizar este proyecto, me he dado cuenta que el programa realizado no está disponible en el mercado o al menos no he podido encontrar algo parecido. Eso hace que esta utilidad tenga una importancia especial vistas las ventajas que presenta tanto para usuarios con conocimientos medio de informática como para programadores. La ventaja más importante que tiene este programa es la gran mejora de la velocidad de transferencia respecto al sistema operativo más utilizado (Windows). La última prueba que se ha realizado ha demostrado que la transferencia se hace a la máxima velocidad permitida por el hardware. Esto presenta un record en comparación con lo que puede llegar a tardar la misma transferencia en la misma máquina trabajando con Windows. La idea de diseñar el programa para MS-DOS no está nada mal, pues a veces la pérdida de datos de un disco duro suele ser por un fallo del sistema operativo o bien por un archivo no seguro. MS-DOS nos permite acceder al disco para salvar datos sin tener que recorrer al sistema operativo. Desde el punto de vista del cliente, no solo interesa la calidad y la utilidad, sino que el precio es vital para la decisión de adquirir o no un cierto programa. Este proyecto ofrece una solución barata puesto que la utilidad preparada y instalada en una memoria USB solo cuesta 34,82 €. El precio incluye unas ganancias del 10 %. Se trata de un programa con una funcionalidad muy amplia. La más importante quizá es la posibilidad de copiar toda la información de un disco a otro. Solo la opción de modificación del disco puede tener mil y una utilidades. En general, se trata de un programa que nos puede ser útil para infinidad de aplicaciones. La realización de este proyecto me ha servido para perfeccionar mis conocimientos de la programación en lenguaje C y también en Ensamblador. El dominio del funcionamiento de los discos duros y de los modos de transferencia es un requisito esencial para la realización de este proyecto. Este proyecto realmente presenta una continuación del plan de formación de la ingeniería electrónica. En resumen, se ha podido realizar un programa que permite el acceso a los discos SATA y que permite múltiples opciones de gestión del disco. También se ha conservado la compatibilidad con las funciones anteriores: gestión de los discos IDE y disqueteras. Y finalmente se ha previsto un uso futuro del programa con discos de más memoria de los actuales. Por tanto, se han cumplido los objetivos iníciales. 97 13 Bibliografía y referencias 13.1 Referencias [1] Página Web http://es.wikipedia.org/wiki/Disco_duro 15/02/10 [2] Página Web http://www.monografias.com/trabajos14/discosduros/discos duros.shtml 15/02/10 [3] Página Web http://es.wikipedia.org/wiki/Serial_ATA 15/02/10 [4] Página Web http://www.serialata.org/ 18/02/10 [5] Página Web http://www.ata-atapi.com/ 18/02/10 [6] Página Web www.t13.org 09/03/10 [7] Página Web www.t13.org/Documents/.../project/d1410r3b-ATA-ATAPI6.pdf 09/03/10 [8] Página Web www.t13.org/Documents/.../docs2006/D1699r3f-ATA8- ACS.pdf 15/03/10 [9] Página Web www.moodle.urv.cat/informatica_industrialII 1/07/10 [10] Página Web http://html.rincondelvago.com/turbo-c.html 15/08/10 [11] Página Web http://www.pccity.es/discos_duros_1029_pc.html?partn er=15& nav=nav_superior 25/08/10 13.2 Bibliografía [1] Ceballos Sierra, Francisco Javier. El lenguaje de programación C. Madrid: RAMA, 2002 [2] FUJITSU ESPAÑA. Un paseo por SATA, publicación Marzo 2004 98 14 Anexos 14.1 Comandos La tabla siguiente contiene un resumen de los comandos compatibles con los discos SATA. (Continúa) 99 Figura 22. Tabla de comandos SATA 100 14.2 contenido de la respuesta al comando Identify device (Continúa) 101 102 (Continúa) 103 104 Figura 22. Los 256 Words de respuesta al comando Identify device 105 14.3 Diferentes rutinas extraídas del código A continuación vamos a ver algunas funciones del programa. 14.3.1 La función Disk_access48( ) Esta rutina se encarga de los accesos de discos SATA con direccionamiento 48-bit. int disk_access48(u_char command, disk_Base *disk_base) { u_int n, m, local_error=0; disk_irq.drive=disk_base->drive; /* inicializaci¢n de la estructura del driver */ disk_irq.nsectors=disk_base->nsectors; disk_irq.lba=disk_base->lba; disk_irq.buffer=disk_base->buffer; disk_irq.feature=disk_base->feature; disk_irq.cache_sectors=disk_base->piden->block_size; disk_irq.io_base=disk_base->io_base; disk_irq.command=command; disk_irq.nirqs=1; disk_irq.resto=0; switch(command) { /* seg£n comando */ case READ_DMA_R48: n=(disk_base->drive<2)?0:8; /* se requiere actualizar el puntero a la tabla descriptora cada vez */ if(!n) pci_io_write(disk_base->io_base+0x04, DTBA0, 4); /* puntero a tabla descriptora canal 1 */ else pci_io_write(disk_base->io_base+0x0C, DTBA1, 4); /* puntero a tabla descriptora canal 2 */ pci_io_write(disk_base->io_base+0x00+n, (u_long)((pci_io_read(disk_base->io_base+0x00+n,1)&0xFE)), 1); /* stop DMA */ pci_io_write(disk_base->io_base+0x02+n, (u_long)((pci_io_read(disk_base->io_base+0x02+n,1)|0x06)), 1); /* reset status irq+error */ pci_io_write(disk_base->io_base+0x00+n, (u_long)((pci_io_read(disk_base->io_base+0x00+n,1)|0x08)), 1); /* lectura DMA */ break; case WRITE_DMA_R48: n=(disk_base->drive<2)?0:8; /* se requiere actualizar el puntero a la tabla descriptora cada vez */ if(!n) pci_io_write(disk_base->io_base+0x04, DTBA0, 4); /* puntero a tabla descriptora canal 1 */ else pci_io_write(disk_base->io_base+0x0C, DTBA1, 4); /* puntero a tabla descriptora canal 2 */ pci_io_write(disk_base->io_base+0x00+n, (u_long)((pci_io_read(disk_base->io_base+0x00+n,1)&0xFE)), 1); /* stop DMA */ 106 pci_io_write(disk_base->io_base+0x02+n, (u_long)((pci_io_read(disk_base->io_base+0x02+n,1)|0x06)), 1); /* reset status irq+error */ pci_io_write(disk_base->io_base+0x00+n, (u_long)((pci_io_read(disk_base->io_base+0x00+n,1)&0xf7)), 1); /* escritura DMA */ break; case WRITE_MULTIPLE48: /* No existe en modo retry */ case READ_MULTIPLE48: /* No existe en modo retry */ disk_irq.nirqs=(disk_base->nsectors/disk_irq.cache_sectors); /* n§ irqs esperadas */ disk_irq.resto=disk_base->nsectors%disk_irq.cache_sectors; /* sectores restantes */ if(disk_irq.resto) disk_irq.nirqs++; break; case WRITE_SECTORS_R48: case READ_SECTORS_R48: disk_irq.nirqs=disk_base->nsectors; break; /* n§ irqs esperadas */ case SET_MULTIPLE: disk_irq.nsectors=disk_irq.cache_sectors; /* tama¤o del paquete por irq */ break; case INICIALIZAR: disk_irq.command=IDENTIFY; break; } if((local_error=x_disco48())!=0) return(local_error); /* llamada al manejador */ if(command==INICIALIZAR) /* captura de info a partir de IDENTIFY */ { /* Con el chip 82371EB, puede detectarse como existente un disco no instalado, incluso puede generarse la IRQ correspondiente. Para discriminarlo analizamos el sector devuelto por el comando IDENTIFY. Se supone que si el disco no est instalado, el contenido de este sector coincidir en todos sus elementos enteros. Cogemos un entero del campo del n§ de serie y lo comparamos con el contenido del campo del modelo. El contenido deber¡a ser id‚ntico si no existe el disco. */ for(n=0; n<20; n++) { if(*((u_int*)disk_base->buffer+10) != *((u_int*)disk_base>buffer+27+n)) break; } 107 if(n==20) return(0xAA00); /* disk not ready */ for(n=0; n<20; n+=2) /* copia del n£mero de serie con giro(AH->AL; AL->AH) */ { *(disk_base->piden->n_serial+n)=*((u_char*)disk_base>buffer+20+n+1); *(disk_base->piden->n_serial+n+1)=*((u_char*)disk_base>buffer+20+n); } for(n=19; n; n--) /* colocaci¢n de fin de cadena ajustada */ if(*((u_char*)disk_base->piden->n_serial+n)!=0x20) { *((u_char*)disk_base->piden->n_serial+n+1)='\0'; break; } /* est justificado a la derecha y nos interesa a la izquierda */ for(n=0; n<20; n++) /* primer elemento */ if(*(disk_base->piden->n_serial+n)!=0x20) break; m=n; for(n=0; n<21-m; n++) /* movimiento */ *(disk_base->piden->n_serial+n)=*(disk_base->piden>n_serial+n+m); for(n=0; n<8; n+=2) /* copia de la revisi¢n firmware con giro */ { *(disk_base->piden->r_firmware+n)=*((u_char*)disk_base>buffer+46+n+1); *(disk_base->piden->r_firmware+n+1)=*((u_char*)disk_base>buffer+46+n); } for(n=7; n; n--) /* colocaci¢n de fin de cadena ajustada */ if(*((u_char*)disk_base->piden->r_firmware+n)!=0x20) { *((u_char*)disk_base->piden->r_firmware+n+1)='\0'; break; } for(n=0; n<40; n+=2) /* copia del modelo con giro */ { *(disk_base->piden->model+n+1)=*((u_char*)disk_base>buffer+54+n); *(disk_base->piden->model+n)=*((u_char*)disk_base>buffer+54+n+1); } for(n=39; n; n--) /* colocaci¢n de fin de cadena ajustada */ if(*((u_char*)disk_base->piden->model+n)!=0x20) { *((u_char*)disk_base->piden->model+n+1)='\0'; break; } disk_base->piden->block_ready=*((u_char *)disk_base>buffer+119)&0x1; /* Se soporta transferencia de bloque? */ disk_base->piden->block_size=disk_base->piden->block_ready?\ *((u_char *)disk_base->buffer+118):0; /* n§ sectores por irq */ 108 // disk_base->piden->lba_ready=*((u_char*)disk_base->buffer+99)&0x02; /* soporta modo LBA */ if(*(disk_base->buffer+53)&0x02) /* PIO Mode advanced (3, 4, ...) */ { if(*(disk_base->buffer+64)&0x01) /* bit 1 */ disk_base->piden->pio_mode=3; if(*(disk_base->buffer+64)&0x02) /* bit 2 */ disk_base->piden->pio_mode=4; } else /* PIO Mode old (0, 1, 2) */ disk_base->piden->pio_mode=*((u_int*)disk_base->buffer+51)>>8; /* max modo PIO soportado */ disk_base->piden->udma_ready=(u_char)(*((u_int*)disk_base>buffer+53)&0x4); /* soporta modo ultra DMA */ if(disk_base->piden->udma_ready) /* UDMA Modes 0, 1, 2, 3, 4 */ { if(*(disk_base->buffer+88)&0x0100) disk_base->piden>udma_modes=0; if(*(disk_base->buffer+88)&0x0200) disk_base->piden>udma_modes=1; if(*(disk_base->buffer+88)&0x0400) disk_base->piden>udma_modes=2; if(*(disk_base->buffer+88)&0x0800) disk_base->piden>udma_modes=3; if(*(disk_base->buffer+88)&0x1000) disk_base->piden>udma_modes=4; } if(*(disk_base->buffer+83)&0x0400) disk_base->piden->bit_48=1; else disk_base->piden->bit_48=0; disk_base->piden->max_lba=*((u_long*)((u_char*)disk_base>buffer+120)); /* sector m s alejado */ if(disk_base->piden->max_lba>=0x0FFFFFFF) //si es el maximo { disk_base->piden->max_lba=*((u_long*)((u_char*)disk_base>buffer+200)); /* sector m s alejado (parte 1) */ disk_base->piden->max_lba2=*((u_long*)((u_char*)disk_base>buffer+204)); /* sector m s alejado (parte2) */ } else disk_base->piden->bit_48=0; disk_base->piden->mdma_modes=(u_char)(*((u_int*)disk_base>buffer+63))>>8; /* modos en multiword DMA soportados */ disk_irq.cache_sectors=disk_base->piden->block_size; /* para READ/WRITE MULTIPLE */ } return(local_error); } Código 1. Disk_access48( ) del archivo IDE_DRV1.C. 109 14.3.2 La función x_disco48( ) Esta función se ejecuta desde la rutina anterior. Su utilidad principal es enviar la información de configuración al disco mediante la escritura en los registros. u_int x_disco48(void) { u_int *code; u_char ready=SI, busy=NO, time_out=NO; struct{ unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned unsigned }err; /* c¢digo de error */ /* disco listo */ /* disco ocupado */ /* l¡mite de tiempo */ AMNF TK0N ABRT MCR IDNF MC UNC BBK :1; :1; :1; :1; :1; :1; :1; :1; ERR IDX CORR DRQ DSC DWF DRDY BUSY :1; :1; :1; :1; :1; :1; :1; :1; /* registro de error a byte bajo */ /* b7 */ /* registro de estado a byte alto */ /* b15 */ u_int canal, base, m_s; code=(u_int*)&err; *code=0; disk_irq.flag=OFF; irq14/irq15 */ /* canal 0/1: (IDE0, IDE1) */ /* direcci¢n base para acceso al disco */ /* master/slave */ /* variable de error */ /* no error */ /* este flag sirve para sincronizar con m_s=(disk_irq.drive>1)?(disk_irq.drive-2):disk_irq.drive; /* indica si master(0) • slave(1) */ base=(disk_irq.drive>1)?BASE_1:BASE_0; /* disco secundario o primario*/ canal=(disk_irq.drive>1)?CANAL_1:CANAL_0; /* canal IDE0 IDE1 */ //printf("drive:%u ", disk_irq.drive); //printf("status:%02X ",inportb(r_status2)); outportb(r_drive_head, (m_s?(0xF0):(0xE0)));/* LBA slave/master */ if(inportb(r_status2)&RDY) /* si disk ready */ 110 { int z; n_tics=10; /* 10 * 55ms = 550 ms m ximo */ //n_tics=TICS; /* tiempo de espera */ error=OFF; while((inportb(r_status2)&BSY) && n_tics); /* espera no busy */ if(n_tics!=0) { //printf(" No busy "); /* Programaci¢n de registros del tipo FIFO*/ //datos obtenidos de las dos variables LBA outportb(r_sec_count, disk_irq.nsectorsprev); outportb(r_sec_count, disk_irq.nsectors); outportb(r_sec_number,Sec_numberprev); outportb(r_sec_number, Sec_number); outportb(r_cil_low, Cil_lowprev); outportb(r_cil_low, Cil_low); outportb(r_cil_high, Cil_highprev); outportb(r_cil_high, Cil_high); switch(disk_irq.command) /* seg£n comando */ { case SET_FEATURE: outportb(r_feature, disk_irq.feature); /* establecimiento de caracter¡sticas */ break; case SET_IRQ: outportb(r_int, IRQ_ENABLE); return(0); break; case RESET: outportb(r_int, RESET); n_tics=TICS; outportb(r_int, SET_IRQ); /* validaci¢n de irqs */ /* reset */ /* tiempo de espera */ while((inportb(r_status2)&BSY) && n_tics!=0); /* espera ready */ if(n_tics==0) return(0xAA00); /* Drive not ready */ else return(0); break; } outportb(r_command, disk_irq.command); /* se env¡a comando al disco */ n_tics=10; switch(disk_irq.command) { case WRITE_MULTIPLE48: case WRITE_SECTORS_R48: while(((inportb(r_status2)&MASK_READY)!=READY) && n_tics); /* espera data ready */ lba_w(); /* transferencia hacia el disco (.asm)*/ break; 111 case READ_DMA_R48: case WRITE_DMA_R48: pci_io_write(disk_irq.io_base+canal, (u_long)(pci_io_read(disk_irq.io_base+canal,1)|0x01), 1); /* start DMA */ default: while(!disk_irq.flag && n_tics); /* espera conclusi¢n irq */ } if(n_tics==0) time_out=SI; /* tiempo excedido */ } else busy=SI; /* disco ocupado */ } else ready=NO; /* disco no preparado */ disk_irq.flag=OFF; *code=error; /* error lo actualiza el manejador de IRQ */ if(!ready || busy || time_out) /* situaci¢n de error grave */ { *code=(u_int)inportb(r_status1); if((*code & 0x01)!=0) *code=(*code<<8) | (u_int)inportb(r_error); err.DRDY=ON; /* tiempo excedido (Drive not ready) */ outportb(r_int, SRST); /* reset del disco */ n_tics=10; while(n_tics); /* pausa 10*55=550 ms */ if(inportb(r_error)!=0x01) error=0x05; /* luego de reset r_error es distinto */ outportb(r_int, IEN); /* disk enable */ n_tics=5; while(n_tics); /* pausa 5*55=275 ms (se requiere)*/ if(error=0x05) return(error); } //printf("error:%04X\t code:%04X\n",error, *code); if(*code) /* error particular */ { inportb(r_status1); /* reset error */ if(time_out) error=0xAA; /* Drive not ready */ else if(err.BBK) error=0x01; /* Bad sector */ ///////////////////// else if(err.UNC) error=0x10; /* Bad CRC/ECC */ else if(err.IDNF) error=0x04; /* Sector not found */ else if(err.ABRT) error=0x01; /* Bad command */ else if(err.TK0N) error=0x05; /* Reset fail */ else if(err.AMNF) error=0x02; /* Address mark not found */ else if(err.DRDY) error=0xAA; /* Drive not ready */ else if(err.DWF) error=0xCC; /* Write fault */ else if(err.CORR) error=0x11; /* CRC/RCC corectable */ else if(err.ERR) error=0xE0; /* Status error */ /* error=0x08 -> fallo DMA */ } //getch(); return(error<<8); } Código 2. x_disco48( ) del archivo IDE_DRV1.C. 112 14.3.3 La función main( ) Como ya se sabe, esta rutina es la primera rutina q ejecuta el compilador. En este programa se encarga de inicializar, presentar la información en pantalla y de llamar a las diferentes rutinas para las diferentes opciones. int main(int argc, char **argv) { int fila=8, /* coordenadas para presentaci¢n de info de discos */ columna=4; int fin=NO, option, op=1; 'editar') */ /* flag: 1=> fin de bucle */ /* opci¢n seleccionadas del men£ */ /* opci¢n anterior (por defecto if(analisis_arg(argc, argv)!=0) return(1); /* an lisis de argumentos */ if((n_discos=ini_disks())<0) /* inicializaci¢n de drivers para discos */ { if(n_discos==-1) printf("Error durante la detecci¢n de los discos\n"); else if((n_discos*=-1)>MAX_DISKS) printf("Se detectan %d discos.\nEste software est preparado para un m ximo de %d unidades.\n", n_discos, MAX_DISKS); salir(fin_driver(1, p_disco[0].pbase)); } ini_video_0(&color); ini_window(p_disco); ventanas */ ini_window_copy(p_disco); ini_window_cmp(p_disco); ini_window_config(p_disco); ini_window_scan(p_disco); gotoxy(1,25); error */ printf(" /* presentaci¢n principal */ /* inicializa caracter¡sticas de las /* /* /* /* ventanas ventanas ventanas ventanas para para para para COPY */ CMP */ CONFIG */ SCAN */ /* borrados de zona de mensajes de "); PresInfoDiscos(columna, fila); /* presenta info sobre los discos */ while(!fin && !error && (option=menu_0(op-1))!=6) /* me£ principal */ { gotoxy(1,25); /* borrados de zona de mensajes de error */ printf(" "); switch(option) { case 0: op=6; /* se puls¢ ESC y situamos el ¡ndice en salir */ continue; case 1: 113 if(disk_edit()) fin=ON; break; case 2: if(disk_copy(p_disco)) fin=ON; discos */ break; case 3: if(disk_cmp(p_disco)) fin=ON; discos */ break; case 4: if(disk_scan(p_disco)) fin=ON; patrones en discos */ break; case 5: if(disk_config(p_disco)) fin=ON; */ break; } /* editor de discos */ /* copia de /* comparaci¢n entre /* b£squeda de /* configuraci¢n op=option; if(!fin) /* si no hay errores */ { ini_video_0(&color); /* presentaci¢n principal */ PresInfoDiscos(columna, fila); /* presenta info sobre los discos */ } else /* errores */ { getch(); /* captura tecla */ printf("\n"); /* posiciona el cursor */ } } _setcursortype(_NORMALCURSOR); textbackground(NEGRO); /* colores originales por defecto */ textcolor(BLANCO); gotoxy(1,25); if(!error) /* borrados de zona de mensajes de error */ printf(" "); freeallmem_win(); ventanas */ /* libera posible memoria reservada para salir(fin_driver(1, p_disco[0].pbase)); return(error); } Código 3. main( ) del archivo DISK_CAS.C. 114 /* condicones iniciales */ 14.3.4 La rutina de atención a la interrupción Esta rutina hecha en código Assembler se encarga de atender a la interrupción 14 del disco. Hay otra rutina similar para la interrupción 15. ;--------------------------------------------------------------------; attn_irq14() rutina de atenci¢n a la interrupci¢n de disco duro CANAL 0 ;--------------------------------------------------------------------attn_irq14 PROC FAR push ds push ax mov ax,seg disk_irq mov ds,ax cmp byte ptr [disk_irq.NIRQS],0 jz command_def14 ;n§ de irqs acontecidas dec byte ptr[disk_irq.NIRQS] ;irq-jnz irq_14_0 mov byte ptr[disk_irq.FLAG],ON ;indicaci¢n de evento (el disco acab¢) irq_14_0: ; cmp byte ptr[disk_irq.COMMAND], WRITE_DMA mov al, byte ptr[disk_irq.COMMAND]; cmp al, WRITE_DMA jz command_def14 cmp al, WRITE_DMA_R jz command_def14 cmp al, WRITE_DMA_R48 jz command_def14 ; cmp byte ptr[disk_irq.COMMAND], READ_DMA cmp al, READ_DMA jz command_def14 cmp al, READ_DMA_R jz command_def14 cmp al, READ_DMA_R48 jz command_def14 ; cmp byte ptr[disk_irq.COMMAND], WRITE_MULTIPLE cmp al,WRITE_MULTIPLE ;No existe este comando con retry jz c_write_mul cmp al,WRITE_MULTIPLE48 ;No existe este comando con retry jz c_write_mul command_a: ; cmp byte ptr[disk_irq.COMMAND], WRITE_SECTORS cmp al, WRITE_SECTORS jz c_write_sec cmp al, WRITE_SECTORS_R jz c_write_sec cmp al, WRITE_SECTORS_R48 115 jz c_write_sec ;command_b: ; cmp byte ptr[disk_irq.COMMAND], READ_MULTIPLE cmp al, READ_MULTIPLE ;No existe este comando con retry jz mod1 cmp al, READ_MULTIPLE48 ;No existe este comando con retry jz mod1 jnz command_c mod1: push cx xor cx,cx ;dejamos en cx la cantidad de word a transferir mov cl, byte ptr[disk_irq.CACHE_SECTORS] cmp byte ptr[disk_irq.NIRQS],0 jnz command_b0 cmp byte ptr[disk_irq.RESTO],0 ;sectores restantes jz command_b0 ;se leer n cache_sectors mov cl, byte ptr[disk_irq.RESTO] command_b0: sal cx, 7 jmp c_read_multiple ;x128 doubles words command_c: ; cmp byte ptr[disk_irq.COMMAND], READ_SECTORS cmp al, READ_SECTORS jz c_rsectors cmp al, READ_SECTORS_R jz c_rsectors cmp al, READ_SECTORS_R48 jz c_rsectors jnz command_d c_rsectors: push cx mov cx, 128 ;doubles words a leer jmp c_read_sectors command_d: ; cmp byte ptr[disk_irq.COMMAND], IDENTIFY cmp al, IDENTIFY jnz command_e push cx mov cx, 128 ;doubles words a leer jmp c_identify command_e: ; cmp byte ptr[disk_irq.COMMAND], INI_PARAM cmp al, INI_PARAM jnz command_f jmp c_ini_param command_f: ; cmp byte ptr[disk_irq.COMMAND], SET_FEATURE cmp al, SET_FEATURE jnz command_def14 jmp c_set_feature 116 command_def14: ;************* c_read_dma: c_write_dma: c_ini_param: c_write_mul: c_write_sec: c_set_feature: push dx mov byte ptr[disk_irq.FLAG],ON ;indicaci¢n de evento (el disco acab¢) ;seguir14: mov error, OFF ;no error ; cmp byte ptr[disk_irq.COMMAND], READ_DMA cmp al, READ_DMA jz def_dma14 cmp al, READ_DMA_R jz def_dma14 cmp al, READ_DMA_R48 jz def_dma14 ; cmp byte ptr[disk_irq.COMMAND], WRITE_DMA cmp al, WRITE_DMA jz def_dma14 cmp al, WRITE_DMA_R jz def_dma14 cmp al, WRITE_DMA_R48 jz def_dma14 jmp def_a14 def_dma14: mov dx, word ptr[disk_irq.IO_BASE] add dx, 08h ;start/stop DMA in al, dx and al,0feh ;stop DMA out dx, al mov dx, word ptr[disk_irq.IO_BASE] add dx, 0Ah ;status DMA in al, dx mov ah, al or al, 6 out dx, al ;reset irq + error test ah, 02 jz def_a14 mov error, 8 ;test b1 ;si no error ;error de DMA def_a14: mov dx, R_STATUS in al, dx ;lectura de estado test al,01 ;error? b0=1 => error jz salir_def ;si no error sal ax, 8 ;R_STATUS pasa al byte alto mov dx, R_ERROR in al, dx ;R_ERROR pasa al byte bajo mov error, ax ;variable global de error 117 salir_def: mov dx, mov al, out dx, mov dx, out dx, 20h 20h al 0A0h al pop dx pop ax pop ds sti iret ; salida ; fin 8259 master ; fin 8259 slave ;validamos irqs ;----------------------------------------------------------------;lee uno o m s sectores y los coloca a partir de [disk_irq+BUFFER] ;-----------------------------------------------------------------;El sector se lee a£n cuando pueda haber error c_read_sectors: c_identify: c_read_multiple: push di push dx push es ; ; salva registros efectados mov error, OFF ;no error mov dx, R_STATUS in al, dx ;lectura de estado test al,01 ;error? b0=1 => error jz leer ;si no error sal ax, 8 ;R_STATUS pasa al byte alto mov dx, R_ERROR in al, dx ;R_ERROR pasa al byte bajo mov error, ax ;variable global de error ;leemos a£n cuando haya error jmp fin_read ;salir leer: mov mov mov cld rep ;todo OK es, [disk_irq+BUFFER+2] ;segmento del buffer di, [disk_irq.BUFFER] ;offset del buffer dx, R_DATA ;port de lectura IDE insd ;bucle de lectura de doubles words fin_read: mov [disk_irq.BUFFER], di mov mov out mov out dx, al, dx, dx, dx, pop pop pop pop pop es dx di cx ax 20h 20h al 0A0h al ;actualizamos puntero ; salida ; fin 8259 master ; fin 8259 slave ; recupera registros 118 pop ds sti ;validamos irqs iret ; fin del manejador ;****************************************** attn_irq14 ENDP ; fin del procedimiento Código 4. Attn_irq14 del archivo IDE_DRV0.asm 119 14.3.5 La función SetIdeDriver( ) Esta función se encuentra dentro del conjunto de rutinas de inicialización. Se encarga de identificar los discos que forman parte del sistema y también de asignar el método más eficiente y el comando adecuado para el acceso a los distintos dispositivos. int SetIdeDriver(disco_info* disk) { int local_error; /* error local */ prueba=0; disk->ide=NO; /* inicializamos */ if(driver==1) /* propio, no BIOS */ { if((local_error=disk_access(INICIALIZAR, disk->pbase))!=0) { //printf("La unidad %d no existe. error: %04x\n", m, local_error); //error=0; /* disk_access actualiza la variable global error */ return(local_error); } else /* esta unidad IDE existe */ { if(no_IDE_PCI) disk->pbase->piden->udma_ready=NO; /* no se puede activar el modo UDMA */ *(disk->pbase->piden->model+19)='\0'; /* control de l¡mites de cadena */ disk->unidad=disk->pbase->drive; disk->ide=SI; if(disk->sec_disco < disk->pbase->piden->max_lba) { disk->sec_disco=disk->pbase->piden->max_lba; //disk->sec_disco2=disk->pbase->piden->max_lba2; disk->cil=(disk->pbase->piden->max_lba/((disk->cab+1)*disk>sec))-1; /* cil l¢gicos */ //se puede selecionar disk->sec_parti=(unsigned long)(disk->cil+1)*(disk>cab+1)*disk->sec-disk->sec; } } /* Determinaci¢n del modo de operaci¢n m s eficiente ---------------------------------------------------- */ if(disk->pbase->piden->udma_ready) { if(ini_dma(disk->pbase)) { gotoxy(1,25); printf("Error en asignaci¢n de memoria"); //salir(fin_driver(0, disk->pbase)); error=1; return(-1); } if(disk->pbase->piden->bit_48==1){ disk->pbase->c_read=READ_DMA_R48; disk->pbase->c_write=WRITE_DMA_R48;} 120 // else if(disk->pbase->piden->bit_48==0) { disk->pbase->c_read=READ_DMA; disk->pbase->c_write=WRITE_DMA; } disk->driver=1; /* driver propio*/ disk->defect_driver=1; disk->modo=2; /* DMA */ disk->defect_modo=2; disk->retry=0; /* no retry */ disk->defect_retry=0; cprintf("Disco %u Protocolo: Ultra DMA/33 - /66", n); } else if(disk->pbase->piden->block_size>1) { if(disk->pbase->piden->bit_48==1){ disk->pbase->c_read=READ_MULTIPLE48; disk->pbase->c_write=WRITE_MULTIPLE48; } else if(disk->pbase->piden->bit_48==0){ disk->pbase->c_read=READ_MULTIPLE; disk->pbase->c_write=WRITE_MULTIPLE; } disk->driver=1; /* driver propio */ disk->defect_driver=1; disk->modo=1; /* IRQ por bloque */ disk->defect_modo=1; disk->retry=0; /* no retry */ disk->defect_retry=0; // cprintf("Disco %u Protocolo: PIO %u sec/irq\n", n, disk->pbase>piden->block_size); } else { if(disk->pbase->piden->bit_48==1){ disk->pbase->c_read=READ_SECTORS_R48; disk->pbase->c_write=WRITE_SECTORS_R48; } // else if(disk->pbase->piden->bit_48==0){ disk->pbase->c_read=READ_SECTORS; disk->pbase->c_write=WRITE_SECTORS; } disk->driver=1; /* driver propio */ disk->defect_driver=1; disk->modo=0; /* IRQ por sector */ disk->defect_modo=0; disk->retry=0; /* no retry */ disk->defect_retry=0; cprintf("Disco %u Protocolo: PIO 1 sec/irq", n); } } return(error); } Código 5. SetIdeDriver( ) del archivo DISK_INI.C 121 14.3.6 La función de obtención del valor tecleado Esta función está diseñada para obtener el valor tecleado por el usuario y guardarlo en dos variables del tipo long (32 bits). Básicamente se usa para pasar el valor tecleado por el usuario de un string a dos variables distintas. Int Asciitolong2(char *str) { int i,stres[16],resta,por=1,bits[49],n=9,k,proxima=0; unsigned int y; int str[16]; clrscr(); for(i=14;i>-1;i--) if(str[i]) { n=i; break; } k=0; //obtencion del numero de caracteres tecleados if(str[n]<2) proxima=1; //reduccion del numero bits[k]=str[0]%2; //obtencion del primer bit k++; while(n>-1) { for(i=n;i>-1;i--) { if(str[i]>=2) { stres[i]=str[i]/2; resta=str[i]%2; str[i-1]+=(resta*10); por=1; } else { por*=10; str[i-1]+=str[i]*por; stres[i]=0; } } por=1; //divisiones / 2 ->conversion a binario //si el resto es <2 for(i=0;i<14;i++) str[i]=stres[i]; //nueva operación de division bits[k]=str[0]%2; k++; //obtencion del bit if(proxima) { n-=1; proxima=0; } //reduccion del numero de posiciones if(str[n]<2) proxima=1; } 122 for(i=48;i>-1;i--) //numero de bits obtenidos if(bits[i]) { k=i; break; } for(y=0;y<32;y++) num1+=bits[y]*potencia(2,y); //variable 1 for(y=32;y<48;y++) num2+=((unsigned long)bits[y]*potencia(2,y32)); //variable 2 return(0); } Código 6. Asciitolong( ) del archivo MENUS.C 123