Return to BSD News archive
Newsgroups: comp.os.386bsd.development Path: sserve!newshost.anu.edu.au!munnari.oz.au!news.Hawaii.Edu!ames!elroy.jpl.nasa.gov!decwrl!netcomsv!netcom.com!jmonroy From: jmonroy@netcom.com (Jesus Monroy Jr) Subject: Code for: Test of the Intel 8254 shut-down/parity-check command Message-ID: <jmonroyCDDv6z.ErA@netcom.com> Organization: NETCOM On-line Communication Services (408 241-9760 guest) Date: Wed, 15 Sep 1993 06:54:35 GMT Lines: 613 # This is a shell archive. Save it in a file, remove anything before # this line, and then unpack it by entering "sh file". Note, it may # create directories; files and directories will be owned by you and # have default permissions. # # This archive contains: # # i8254/i82.c # i8254/i82.doc # i8254/isa.h # i8254/isa_bus.s # i8254/notes # i8254/osdepend.h # i8254/timer.h # echo x - i8254/i82.c sed 's/^X//' >i8254/i82.c << 'END-of-i8254/i82.c' X/* X Test of the Intel 8254 shut-down/parity-check command X X*/ X X/* Internal Documentation */ X#define TEST_TYPE "shut-down/parity-check" X#define PROGRAM_VERSION "version 1.0.0" X X/* identify OS and compiler maker */ X#define COMPILER __ZTC__ X X/* standard headers */ X#include <stdio.h> /* Standard Input/Ouput */ X#include <stdlib.h> /* Standard Library */ X#include <stddef.h> /* Standard Definitions for ANSI C */ X X/* alias for readablity */ X#define u_char unsigned char /* alias */ X#define u_short u_char /* another alias */ X X/* stuff to fiddle with */ X#define SHORT_COUNT 10 /* count-down time for timer */ X#define DEBUG 0 /* Debugging aids ON=1/OFF=0 */ X#define SHOW_IT(x) printf(#x" %02x\n",x) X X/* local headers (same directory) */ X#include "osdepend.h" /* OS Dependent routines and variables */ X#include "timer.h" /* Constants for Intel 8254 timer */ X X/* ////////////////////////////////////////////////// X X Program constants X X*/ X#define START_INTERNAL "INTERNAL NOTES: " X#define END_INTERNAL "END INTERNAL NOTES!!!" X#define AUTHOR "jmonroy@netcom.com" X#define MAINTAINER AUTHOR X#define FILENAME "Filename:" X#define CHIP_IN_TEST "Intel 8254" X#define COMPILE_TimeDate "compile time & date:" X X/* Internal documentation to executable */ Xstatic u_char *compile_info[8] = { (u_char *) START_INTERNAL, X (u_char *) AUTHOR"; ", X (u_char *) FILENAME" "__FILE__, X (u_char *) CHIP_IN_TEST"; ", X (u_char *) TEST_TYPE" "PROGRAM_VERSION"; ", X (u_char *) COMPILE_TimeDate" " __TIME__" ", X (u_char *) __DATE__ , /* stamps todays date */ X (u_char *) END_INTERNAL X }; X X/* ////////////////////////////////////////////////// X X M A I N X X*/ Xmain (int argc,char **argv) X{ X u_char scratch,temp; X int offset; X X X printf(" Test of the "CHIP_IN_TEST" "TEST_TYPE" for the "OS_STRG"\n"); X printf(" Report errors to "MAINTAINER"\n"); X X /* Don't shut down the time of day so parity will error */ X for (offset = TIMER1_COUNTER1; offset < TIMER1_COUNTER2 + 1; offset++) { X X /* Set control mode to software retriggerable */ X /* Set read/write to LSB then MSB */ X /* and Identify counter */ X scratch = CNTLR_MODE4 | CNTRL_RW_LSB_MSB | (CNTRL_WRD_COUNTER0 << offset); X X #if DEBUG X SHOW_IT(scratch); X #endif X X /* issue command */ X outb(TIMER1_BASE_ADDR + TIMER1_CNTRL_WORD, scratch); X X /* write LSB */ X outb(TIMER1_BASE_ADDR + offset, SHORT_COUNT); X X /* write MSB */ X outb(TIMER1_BASE_ADDR + offset, SHORT_COUNT); X X } X X printf(" ************ ENDS RESET ************\n"); X printf(" READ-BACK COMMAND REPORTS\n"); X X for (offset = TIMER1_COUNTER0; offset < TIMER1_COUNTER2 + 1; offset++) { X X /* identify readback command parameters */ X scratch = CMD_READBACK | (CMD_COUNTER0 << offset); X X #if DEBUG X SHOW_IT(scratch); X #endif X X /* issue command */ X outb(TIMER1_BASE_ADDR + TIMER1_CNTRL_WORD, scratch); X X /* get back status */ X scratch = inb(TIMER1_BASE_ADDR + offset); X X /* report results */ X printf("\n Timer channel %i reports %2x\n", offset, scratch); X X X /* report OUT pin and Null count */ X if (scratch & STAT_OUTPUT_HI) X printf(" The OUT pin is high.\n"); X if (scratch & STAT_NULL_COUNT) X printf(" Null count is returned.\n"); X X X /* should return a value 1..6 */ X temp = ((scratch & CNTRL_MODE_MASK) >> 1); X printf(" Control mode is %4x; ", temp); X X X /* report if counting in BSD or binary mode */ X temp = (scratch & CNTRL_NUM_MASK); X printf("counting in %s.\n", (temp) ? "bcd":"binary"); X X /* read/write is lsb, msb or "lsb then msb" */ X printf(" Read/Write format is "); X switch (scratch & CNTRL_RW_MASK) { X case CNTRL_RW_LSB_MSB: X printf("LSB_MSB"); X scratch = inb(TIMER1_BASE_ADDR + offset); X temp = inb(TIMER1_BASE_ADDR + offset); X printf(" %#02x%02x", scratch, temp); X break; X case CNTRL_RW_MSB: X printf("MSB"); X scratch = inb(TIMER1_BASE_ADDR + offset); X printf(" %#02x", scratch); X break; X case CNTRL_RW_LSB: X printf("LSB") ; X scratch = inb(TIMER1_BASE_ADDR + offset); X printf(" %#02x", scratch); X break; X } X printf("\n"); X X } X printf(" ************ ENDS REPORTS ************\n"); X X} X X END-of-i8254/i82.c echo x - i8254/i82.doc sed 's/^X//' >i8254/i82.doc << 'END-of-i8254/i82.doc' X X X Test of the Intel 8254 shut-down/parity-check command X ----------------------------------------------------- X Xversion: 1.0.0 Xdate: 09-14-1993 Xauthor: jmonroy@netcom.com X X Purpose: Test the for parity errors by shutting down X the RAM refresh timer. X X While looking for the reason for DMA overruns X in the development of an FDC driver for X 386bsd, suggestions were made that shutting X down the timer has no effect on the system; X reasons for this varied. X X Compiling: I have made the code transportable. X It has been tested with: X X MSDOS X ----- X Zortech Personal C v. 1.07 X Turbo C v. 2.01 X Microsoft Quick C v. 2.50 X X 386BSD X ------ X GNU C++ v. 1.39 X X X X How this works. X --------------- X Simply the program issue a command to change X to mode 4 (described in the notes) with a "count-down" X value of 0x0a0a (2,570). This is done to timers 1 and 2, X the RAM refresh timer and the speaker timer, respectively. X Timer 0 is left running because most OSes cannot operate X without a timer for the "deadloop". X X X What should happen. X ------------------- X On most 286 systems nothing will happen till a X interrupt is generated (I.E., keyboard pressed) or a RAM X chip finally loses it's charge. At this point, some system X will hang for a long while, some will immediately parity X error. X On 386bsd expect a "csh" coredump followed by a X system panic. The system will then reboot. On some systems X a parity error will never register. X X X What does this prove? X --------------------- X Namely that the RAM refresh is controllable via X the i8254 timer on the IBM/ISA architecture. X X X WARNING WARNING WARNING WARNING X WARNING WARNING WARNING WARNING X WARNING WARNING WARNING WARNING X ------- ------- ------- ------- X X To get your system back in working order you will X have to do a "cold boot". This means the RAM has to be X recounted. The equivalent is hit the red button on the X front of the computer _or_ if you don't have one -- turn X your machine off, then on (don't forget to count to 10). X X Also if you have a slightly flakey RAM chip this X may be just the thing to make it fail completely. You X have been warned. X X X About 386BSD X ------------ X For the 386bsd version it was necessary to add the X inb() and outb() code. Even though this is in the "locore" X section of the kernel, I do not know the exact method of adding X it to this code. X X Compile as: X X cc -c isa_bus.s X cc i82.c isa_bus.o X X X Files included X -------------- X i82.c Source code for the main program. X i82.doc This file. X isa.h Included for convience. X timer.h Code related directly to the Intel 8254 timer. X osdepend.h Operating System Dependent stuff. X isa_bus.s GAS (Gnu ASsemble) code for inb() and outb(). X This file is only for 386bsd. X notes My notes for the Intel 8254 from various X sources. X X X ERRORS, PROBLEMS or QUESTIONS X ----------------------------- X X To reach me send e-mail to jmonroy@netcom.com X END-of-i8254/i82.doc echo x - i8254/isa.h sed 's/^X//' >i8254/isa.h << 'END-of-i8254/isa.h' X/*- X * Copyright (c) 1990 The Regents of the University of California. X * All rights reserved. X * X * This code is derived from software contributed to Berkeley by X * William Jolitz. X * X * @(#)isa.h 5.7 (Berkeley) 5/9/91 X */ X X/* X * ISA Bus conventions X */ X X#ifndef LOCORE Xunsigned char inb(), rtcin(); Xvoid outb(); Xextern unsigned int atdevbase; /* offset in virtual memory of ISA io mem */ Xvoid sysbeep(int,int); Xunsigned kbd_8042cmd(int); X#endif X X X/* X * Input / Output Port Assignments X */ X X#ifndef IO_BEGIN X#define IO_ISABEGIN 0x000 /* 0x000 - Beginning of I/O Registers */ X X /* CPU Board */ X#define IO_DMA1 0x000 /* 8237A DMA Controller #1 */ X#define IO_ICU1 0x020 /* 8259A Interrupt Controller #1 */ X#define IO_TIMER1 0x040 /* 8252 Timer #1 */ X#define IO_TIMER2 0x048 /* 8252 Timer #2 */ X#define IO_KBD 0x060 /* 8042 Keyboard */ X#define IO_RTC 0x070 /* RTC */ X#define IO_NMI IO_RTC /* NMI Control */ X#define IO_DMAPG 0x080 /* DMA Page Registers */ X#define IO_ICU2 0x0A0 /* 8259A Interrupt Controller #2 */ X#define IO_DMA2 0x0C0 /* 8237A DMA Controller #2 */ X#define IO_NPX 0x0F0 /* Numeric Coprocessor */ X X /* Cards */ X /* 0x100 - 0x16F Open */ X X#define IO_WD2 0x170 /* Secondary Fixed Disk Controller */ X X /* 0x178 - 0x1EF Open */ X X#define IO_WD1 0x1f0 /* Primary Fixed Disk Controller */ X#define IO_GAME 0x200 /* Game Controller */ X X /* 0x208 - 0x277 Open */ X X#define IO_LPT2 0x278 /* Parallel Port #2 */ X X /* 0x280 - 0x2F7 Open */ X X#define IO_COM2 0x2f8 /* COM2 i/o address */ X X /* 0x300 - 0x36F Open */ X X#define IO_FD2 0x370 /* secondary base i/o address */ X#define IO_LPT1 0x378 /* Parallel Port #1 */ X X /* 0x380 - 0x3AF Open */ X X#define IO_MDA 0x3B0 /* Monochome Adapter */ X#define IO_LPT3 0x3BC /* Monochome Adapter Printer Port */ X#define IO_VGA 0x3C0 /* E/VGA Ports */ X#define IO_CGA 0x3D0 /* CGA Ports */ X X /* 0x3E0 - 0x3EF Open */ X X#define IO_FD1 0x3f0 /* primary base i/o address */ X#define IO_COM1 0x3f8 /* COM1 i/o address */ X X#define IO_ISAEND 0x3FF /* - 0x3FF End of I/O Registers */ X#endif IO_ISABEGIN X X/* X * Input / Output Memory Physical Addresses X */ X X#ifndef IOM_BEGIN X#define IOM_BEGIN 0x0a0000 /* Start of I/O Memory "hole" */ X#define IOM_END 0x100000 /* End of I/O Memory "hole" */ X#define IOM_SIZE (IOM_END - IOM_BEGIN) X#endif IOM_BEGIN X X/* X * RAM Physical Address Space (ignoring the above mentioned "hole") X */ X X#ifndef RAM_BEGIN X#define RAM_BEGIN 0x0000000 /* Start of RAM Memory */ X#define RAM_END 0x1000000 /* End of RAM Memory */ X#define RAM_SIZE (RAM_END - RAM_BEGIN) X#endif RAM_BEGIN X X/* X * Oddball Physical Memory Addresses X */ X#ifndef COMPAQ_RAMRELOC X#define COMPAQ_RAMRELOC 0x80c00000 /* Compaq RAM relocation/diag */ X#define COMPAQ_RAMSETUP 0x80c00002 /* Compaq RAM setup */ X#define WEITEK_FPU 0xC0000000 /* WTL 2167 */ X#define CYRIX_EMC 0xC0000000 /* Cyrix EMC */ X#endif COMPAQ_RAMRELOC END-of-i8254/isa.h echo x - i8254/isa_bus.s sed 's/^X//' >i8254/isa_bus.s << 'END-of-i8254/isa_bus.s' X /* X * I/O bus instructions via C X */ X .globl _inb X_inb: movl 4(%esp),%edx X subl %eax,%eax # clr eax X NOP X inb %dx,%al X ret X X X .globl _inw X_inw: movl 4(%esp),%edx X subl %eax,%eax # clr eax X NOP X inw %dx,%ax X ret X X X .globl _rtcin X_rtcin: movl 4(%esp),%eax X outb %al,$0x70 X subl %eax,%eax # clr eax X inb $0x71,%al # Compaq SystemPro X ret X X .globl _outb X_outb: movl 4(%esp),%edx X NOP X movl 8(%esp),%eax X outb %al,%dx X NOP X ret X X .globl _outw X_outw: movl 4(%esp),%edx X NOP X movl 8(%esp),%eax X outw %ax,%dx X NOP X ret X END-of-i8254/isa_bus.s echo x - i8254/notes sed 's/^X//' >i8254/notes << 'END-of-i8254/notes' X XNotes to the i8254 timer chip. X X From: IBM Personal Computer Troubleshooting & Repair X for the IBM PC, PC/XT, and PC AT; by Robert C. Brenner X Pub. Howard W. Sams & Company X X pg. 106 X timer 0 (zero) produces the time-of-day irq at 18.2 times/sec. X timer 1 produces the RAM refresh at 66,287 times/sec. X timer 2 is varied for the speaker driver. X X pg. 122 X Out1 occurs every 15usec (microseconds). X Note: Out1 is directly tied to timer 1. X X From: 1988 Intel Microprocessor and Peripherial Handbook, vol.2 X X pg. 2-34 X Mode 2: Rate Generator (condensed) X The mode functions like a divide-by-N counter. X OUT will initially be high. When the initial count X has decremented to 1, OUT goes low for one CLK pulse. X OUT goes high again, the Counter reloads the initial X count and the process is repeated. Mode 2 is X periodic; the same sequence is repeated indefinitely. X X (Read book/section for programming specifics.) X Note: A count (N) of 1 is illegal. X X pg. 2-39 X Mode 4: Software Triggered Strobe (condensed) X OUT will be initially high. When the initial count X expires, OUT will go low for one CLK pulse and then go X high again. The counting sequence is "triggered" by X writting the initial count. X X OUT will not go low again until a new count is loaded; X this then is the software "trigger", allowing OUT to X go low when the count terminates again. X X (Read book/section for programming specifics.) X Note: OUT does not strobe low until N+1 CLK pulses X after the initial count is written. X X END-of-i8254/notes echo x - i8254/osdepend.h sed 's/^X//' >i8254/osdepend.h << 'END-of-i8254/osdepend.h' X/* X X functions as dependent on OS and Compiler X*/ X#if (MSDOS) X X #define OS_STRG "MSDOS" X #define TIMER1_BASE_ADDR 0x40 /* IO_TIMER1 for 386bsd*/ X X #if (COMPILER == __ZTC__) /* Zortech Personal C */ X X #include <dos.h> X #define outb(addr,var) outp(addr,var) X #define inb(addr) inp(addr) X X #elif (COMPILER == __TC__) /* Borland Turbo C */ X X #include <dos.h> X #define outb(addr,var) outportb(addr,var) X #define inb(addr) inportb(addr) X X #elif (COMPILER == __MSC__) /* Microsoft Quick C */ X X #include <conio.h> X #define outb(addr,var) outp(addr,var) X #define inb(addr) inp(addr) X #endif X X#else /* assume 386BSD and GNU C++ */ X #include "isa.h" X #define OS_STRG "386BSD" X #define TIMER1_BASE_ADDR IO_TIMER1 X#endif X X END-of-i8254/osdepend.h echo x - i8254/timer.h sed 's/^X//' >i8254/timer.h << 'END-of-i8254/timer.h' X/* ///////////////////////////////////////////// X X Some defines for the Intel 8254 PIT (Programable Interrupt Timer) X X*/ X/* ///////////////////////////////////////////// X X I/O Address and offsets to registers. X X*/ X#define TIMER1_COUNTER0 0 /* Offset to counter 0 */ X#define TIMER1_COUNTER1 1 /* Offset to counter 1 */ X#define TIMER1_COUNTER2 2 /* Offset to counter 2 */ X#define TIMER1_CNTRL_WORD 3 /* Offset to Control Register */ X X/* ///////////////////////////////////////////// X X Control Word Format X X See data guides for how the modes work. X Note: Except for the READBACK command, X only one counter can be programed X at a time. X*/ X X#define CNTRL_WRD_READBACK 0xC0 /* 1100 0000 */ X#define CNTRL_WRD_COUNTER2 0x80 /* control applies to this register, if high */ X#define CNTRL_WRD_COUNTER1 0x40 /* control applies to this register, if high */ X#define CNTRL_WRD_COUNTER0 0x20 /* control applies to this register, if high */ X#define CNTRL_COUNTER_LATCH 0X00 /* bits 5 & 4 must be zero */ X#define CNTRL_RW_LSB_MSB 0x30 /* read/write to counter register is LSB then MSB */ X#define CNTRL_RW_MSB 0x20 /* read/write to counter register is MSB */ X#define CNTRL_RW_LSB 0x10 /* read/write to counter register is LSB */ X#define CNTLR_MODE5 0x0A /* 1 << 5 */ X#define CNTLR_MODE4 0x08 /* 1 << 4 */ X#define CNTLR_MODE3 0x06 /* 1 << 3 */ X#define CNTLR_MODE2 0x04 /* 1 << 2 */ X#define CNTLR_MODE1 0x02 /* 1 << 1 */ X#define CNTLR_MODE0 0x00 /* 1 << 0; bit 1 must be low */ X#define CNTRL_DO_BCD 0x01 /* count as Binary Coded Decimal */ X#define CNTRL_DO_BIN 0x00 /* bit 0 must be low for Binary counting */ X X/* Alias Logic Masks for readablity */ X#define CNTRL_RW_MASK CNTRL_RW_LSB_MSB X#define CNTRL_MODE_MASK 0x0E /* Look at high 3 bits in nibble */ X#define CNTRL_NUM_MASK CNTRL_DO_BCD X X X/* ///////////////////////////////////////////// X X Command Format X X Issuing the correct bits will return the program X mode and "latched" count of the counter, in the X respective counter register. X X*/ X#define CMD_READBACK CNTRL_WRD_READBACK /* without this - the command does not happen */ X#define CMD_NO_LATCH_COUNT 0x20 /* don't latch the current timer value */ X#define CMD_NO_LATCH_STAT 0x10 /* don't latch the current status value */ X#define CMD_COUNTER2 0x08 /* this command applies to this register, if bit high */ X#define CMD_COUNTER1 0x04 /* same as above */ X#define CMD_COUNTER0 0x02 /* same as above */ X#define CMD_RESERVE 0x01 /* don't use this bit */ X X/* X X Status Register Format X X After issuing a ""readback"" command the status X information comes back in the format below. X The lower 6 bits follow the Control Word Format. X X*/ X#define STAT_OUTPUT_HI 0x80 /* The OUT pin is High */ X#define STAT_NULL_COUNT 0x40 /* currently a null count hit on the counter */ X END-of-i8254/timer.h exit