/************************************************************************/ /* */ /* EEPROM.C */ /* */ /* Copyright (c) 1992, ATI Technologies Incorporated. */ /************************************************************************/ /********************** PolyTron RCS Utilities $Revision: 1.3 $ $Date: 23 Jan 1996 11:45:50 $ $Author: RWolff $ $Log: S:/source/wnt/ms11/miniport/archive/eeprom.c_v $ * * Rev 1.3 23 Jan 1996 11:45:50 RWolff * Eliminated level 3 warnings. * * Rev 1.2 23 Dec 1994 10:47:34 ASHANMUG * ALPHA/Chrontel-DAC * * Rev 1.1 07 Feb 1994 14:07:06 RWOLFF * Added alloc_text() pragmas to allow miniport to be swapped out when * not needed. * * Rev 1.0 31 Jan 1994 11:08:14 RWOLFF * Initial revision. Rev 1.2 08 Oct 1993 15:17:42 RWOLFF No longer includes VIDFIND.H. Rev 1.1 03 Sep 1993 14:23:06 RWOLFF Partway through CX isolation. Rev 1.0 16 Aug 1993 13:23:00 Robert_Wolff Initial revision. Rev 1.10 21 Apr 1993 17:29:48 RWOLFF Now uses AMACH.H instead of 68800.H/68801.H. Rev 1.9 25 Mar 1993 11:14:42 RWOLFF Added typecast to get rid of warnings. Rev 1.8 08 Mar 1993 19:30:28 BRADES submit to MS NT Rev 1.5 06 Jan 1993 11:02:04 Robert_Wolff Eliminated dead code. Rev 1.4 24 Dec 1992 14:41:36 Chris_Brady fixup warnings Rev 1.3 27 Nov 1992 15:19:12 STEPHEN No change. Rev 1.2 13 Nov 1992 17:08:28 Robert_Wolff Now includes 68801.H, which consists of the now-obsolete MACH8.H and elements moved from VIDFIND.H. Rev 1.1 12 Nov 1992 16:54:00 Robert_Wolff Same source file can now be used with both Windows NT driver and VIDEO.EXE test program. Rev 1.0 05 Nov 1992 14:06:02 Robert_Wolff Initial revision. Rev 1.1 14 Sep 1992 09:44:40 Robert_Wolff Moved EEPROM opcodes to VIDEO.H, made VGA routine names consistent with same-purpose routines for 8514. Rev 1.0 02 Sep 1992 12:12:54 Chris_Brady Initial revision. End of PolyTron RCS section *****************/ #ifdef DOC EEPROM.C - EEPROM functions for 8514/Ultra, Graphics Ultra adapters see EEVGA.ASM for the VGA class eeprom functions. Since time marches on, and the names of accelerator products changes often, these names are equivalent : { Mach32 or 68800 or Graphics Ultra Pro } #endif #include #include "miniport.h" #include "ntddvdeo.h" #include "video.h" #include "stdtyp.h" #include "amach.h" #include "amach1.h" #include "atimp.h" #include "eeprom.h" #include "services.h" //----------------IFNDEF DATA_ASM extern WORD rom_segment; extern WORD rom_offset; //----------------IFNDEF INIT_ASM extern WORD default_640_set; extern WORD default_1024_set; /* * Global EEPROM data structures */ struct st_eeprom_data ee; // the location of I/O port bits //----------------------------------------- // function prototypes void ee_wait (void); void ee_clock_16 (WORD eedata); void ee_sel_16 (void); void ee_deselect_16 (void); WORD ee_read (short index); void ee_write (short index, WORD eedata); //----------------------------------------- /* * Allow miniport to be swapped out when not needed. * * The following routines are called through function pointers * rather than an explicit call to the routine, and may run into * trouble if paged out. If problems develop, make them un-pageable: * ee_cmd_16() * ee_cmd_1K() * ee_read_8514() */ #if defined (ALLOC_PRAGMA) #pragma alloc_text(PAGE_M, ee_wait) #pragma alloc_text(PAGE_M, ee_cmd_16) #pragma alloc_text(PAGE_M, ee_cmd_1K) #pragma alloc_text(PAGE_M, ee_sel_16) #pragma alloc_text(PAGE_M, ee_deselect_16) #pragma alloc_text(PAGE_M, ee_clock_16) #pragma alloc_text(PAGE_M, ee_read) #pragma alloc_text(PAGE_M, ee_read_8514) #pragma alloc_text(PAGE_M, ee_write) #pragma alloc_text(PAGE_M, Mach32DescribeEEPROM) #pragma alloc_text(PAGE_M, Mach8UltraDescribeEEPROM) #pragma alloc_text(PAGE_M, Mach8ComboDescribeEEPROM) #endif // these commands do NOT use the index component bits 5-0 so there // is not a problem addressing up to 8 bit indexes , 256 words. #define EE_EWEN 0x04C0 // program enable #define EE_EWDS 0x0400 // program disable #define EE_ERAL 0x0480 // erase all #define EE_WRAL 0x0440 // program all //;---------------------------------------------------------------------- //; EE_WAIT //; Waits for the requisite minimum setup time for the EEPROM //;---------------------------------------------------------------------- void ee_wait () { //EE_DELAY_TIME (256-1) * 0.8381 usec = 214.0 usec delay (1); // delay in milliseconds } /* ee_wait */ //---------------------------------------------------------------------- // EE_CMD_16 // Sends EEPROM opcode and address to a 1k, 2k eeprom // instruct is an 5 bit command in the form of 0111 1100 0000 // with a 6 bit index in the form of 0000 0011 1111 // IF bit 10 is 1, then 8 bit address follows, else address not used. // Write data Serially to the EE_DATA_OUT_M32 bit of the ee->out. // Send out in high to low bit order // //---------------------------------------------------------------------- void ee_cmd_16 (WORD instruct) { int jj; WORD bittest = 0x400; // 0100 0000 0000b bit 10 WORD eedata; struct st_eeprom_data *ee = phwDeviceExtension->ee; ee_clock_16((WORD) (ee->select | ee->chipselect)); // start bit for (jj=0; jj < 11; jj++) { ee_wait(); if (instruct & bittest) // is a one bit eedata = ee->select | ee->chipselect | ee->data_out; else eedata = ee->select | ee->chipselect; OUTPW (ee->iop_out, eedata); ee_clock_16 (eedata); // send cmd bit bittest >>= 1; // next bit to the right } return; } /* ee_cmd_16 */ //---------------------------------------------------------------------- // EE_CMD_1K // Sends EEPROM opcode and address to a 1k, 2k eeprom // instruct is an 5 bit command in the form of 0111 1100 0000 // with a 6 bit index in the form of 0000 0011 1111 // IF bit 10 is 1, then 8 bit address follows, else address not used. // Write data Serially to the EE_DATA_OUT_M32 bit of the ee->iop_out. // Send out in high to low bit order // //---------------------------------------------------------------------- void ee_cmd_1K (WORD instruct) { int jj; WORD bittest = 0x400; // 0100 0000 0000b bit 10 WORD eedata; struct st_eeprom_data *ee = phwDeviceExtension->ee; ee_clock_16((WORD) (ee->select | ee->chipselect)); // start bit for (jj=0; jj < 3; jj++) { ee_wait(); if (instruct & bittest) // is a one bit eedata = ee->select | ee->chipselect | ee->data_out; else eedata = ee->select | ee->chipselect; OUTPW (ee->iop_out, eedata); ee_clock_16 (eedata); // send cmd bit bittest >>= 1; // next bit to the right } bittest = 0x20; // 0010 0000b bit 5 for (jj=0; jj < 6; jj++) { ee_wait(); if (instruct & bittest) // is a one bit eedata = ee->select | ee->chipselect | ee->data_out; else eedata = ee->select | ee->chipselect; OUTPW (ee->iop_out, eedata); ee_clock_16 (eedata); // send cmd bit bittest >>= 1; // next bit to the right } return; } /* ee_cmd_1K */ //;---------------------------------------------------------------------- //; EE_SEL_16 //; Pull EEPROM chip select high //; //;---------------------------------------------------------------------- void ee_sel_16 (void) { struct st_eeprom_data *ee = phwDeviceExtension->ee; ee_wait(); OUTPW (ee->iop_out, (WORD)((ee->select) | (ee->chipselect))); // EE_CS high ee_wait(); return; } /* ee_sel_16 */ //;---------------------------------------------------------------------- //; EE_DESELECT_16 //; Pull EEPROM chip select low //; //;---------------------------------------------------------------------- void ee_deselect_16 (void) { struct st_eeprom_data *ee = phwDeviceExtension->ee; ee_wait(); OUTPW (ee->iop_out, ee->select); // EE_CS high ee_clock_16 (ee->select); // send cmd bit OUTPW (ee->iop_out, 0); // disable EEprom activity ee_wait(); return; } /* ee_deselect_16 */ //;---------------------------------------------------------------------- //; EE_CLOCK_16 //; Toggle EEPROM CLK line high then low //; //; INPUT: eedata = select status for EEPROM //;---------------------------------------------------------------------- void ee_clock_16 (WORD eedata) { struct st_eeprom_data *ee = phwDeviceExtension->ee; ee_wait(); OUTPW (ee->iop_out, (WORD)(eedata | (ee->clock))); // clock ON ee_wait(); OUTPW (ee->iop_out, (WORD)(eedata & ~(ee->clock))); // clock OFF ee_wait(); } /* ee_clock_16 */ //;---------------------------------------------------------------------- //; EE_READ - was a 68800 function //; Read a word from EEPROM ONLY called from INIT.asm //; INPUT: bl = index //; OUTPUT: ax = data //;---------------------------------------------------------------------- WORD ee_read (short index) { WORD indata=0; if (INPW(CONFIG_STATUS_1) & 1) //is 8514 or VGA eeprom { // VGA disabled, use 8514 method indata = ee_read_8514 (index); } else{ indata = ee_read_vga (index); // VGA method } return (indata); } /* ee_read */ //;---------------------------------------------------------------------- //; EE_READ_8514 //; Read a word from using 8514 EEPROM registers //; INPUT: bl = index //; OUTPUT: ax = data //;---------------------------------------------------------------------- WORD ee_read_8514 (short index) { struct st_eeprom_data *ee = phwDeviceExtension->ee; int jj; WORD save_misc, indata=0; save_misc = INPW (R_MISC_CNTL); // Read only location ee_sel_16(); (ee->EEcmd) ((WORD) (EE_READ | index)); // send read cmd and index to EEPROM ee_clock_16 ((WORD) (ee->select | ee->chipselect)); for (jj=0; jj < 16; jj++) { indata <<= 1; if (INPW(ee->iop_in) & ee->data_in) // get data bit indata |= 1; ee_clock_16 ((WORD) (ee->select | ee->chipselect)); } ee_deselect_16(); OUTPW (MISC_CNTL, save_misc); return (indata); } /* ee_read_8514 */ //;---------------------------------------------------------------------- //; EE_WRITE //; Writes a word to EEPROM //; However, this will fail since 1K eeprom does NOT need //; the EE_EWEN, EE_EWDS commands +++++++++++++++++ //; See EEVGA.C ee_write_vga(). //; INPUT: index = which word to write //; data = data to write //;---------------------------------------------------------------------- void ee_write (short index, WORD eedata) { struct st_eeprom_data *ee = phwDeviceExtension->ee; int jj; WORD save_misc, indata=0; if (INPW(CONFIG_STATUS_1) & 1) //is 8514 or VGA eeprom { // VGA disabled, use 8514 method save_misc = INPW (R_MISC_CNTL); // Read only location OUTP (DISP_CNTL, 0x53); // disable CRT before writing EEPROM ee_sel_16(); ee_cmd_16 (EE_EWEN); // enable EEPROM write ee_deselect_16(); // EE_CS low ee_sel_16(); ee_cmd_16 ((WORD) (EE_ERASE | index)); ee_deselect_16(); // EE_CS low delay (50); ee_sel_16(); ee_cmd_16 ((WORD) (EE_WRITE | index)); // EEPROM write data for (jj=0; jj < 16; jj++) { ee_wait(); if (eedata & 0x8000) // get data bit OUTPW (ee->iop_out, (WORD)((ee->select) | (ee->chipselect) | (ee->data_out))); else OUTPW (ee->iop_out, (WORD)((ee->select) | (ee->chipselect))); ee_clock_16 ((WORD) (ee->select | ee->chipselect)); eedata <<= 1; } ee_deselect_16(); // EE_CS low delay (50); // in milliseconds ee_sel_16(); ee_cmd_16 (EE_EWDS); // disable EEPROM write ee_deselect_16(); // EE_CS low OUTPW (ee->iop_out, save_misc); } else{ ee_write_vga (index, eedata); // VGA method } } /* ee_write */ /*************************************************************************** * * New Functions * ***************************************************************************/ /* * void Mach32DescribeEEPROM(Style); * * int Style; Is data stored 8514-style or VGA-style? * * Fill in the EEPROM description structure for the Mach 32 card. */ void Mach32DescribeEEPROM(int Style) { ee.iop_out = MISC_CNTL; ee.iop_in = EXT_GE_STATUS; ee.clock = EE_CLK_M32; ee.select = EE_SELECT_M32; ee.chipselect = EE_CS_M32; ee.data_out = EE_DATA_OUT_M32; ee.data_in = EE_DATA_IN; if (Style == STYLE_8514) { ee.EEread = ee_read_8514; // 8514 style ee.EEcmd = ee_cmd_16; } else{ ee.EEread = ee_read_vga; // VGA style ee.EEcmd = ee_cmd_vga; ee.addr_size = 8; } return; } /* * void Mach8UltraDescribeEEPROM(BusWidth); * * int BusWidth; Is 8514/ULTRA plugged into 8 or 16 bit slot? * * Fill in the EEPROM description structure for the 8514/ULTRA. */ void Mach8UltraDescribeEEPROM(int BusWidth) { ee.data_in = EE_DATA_IN; ee.iop_out = EXT_GE_CONFIG; ee.iop_in = EXT_GE_STATUS; ee.EEread = ee_read_8514; // how read eeprom ee.EEcmd = ee_cmd_1K; // send command to eeprom /* * Only the 8514/Ultra has a hardware bug that prevents it * from writing to the EEPROM when it is in an 8 bit ISA bus. */ if (BusWidth == BUS_8BIT) { ee.clock = EE_CLK_M8_8; ee.select = EE_SELECT_M8_8; ee.chipselect = EE_CS_M8_8; ee.data_out = EE_DATA_OUT_M8_8; } else{ ee.clock = EE_CLK_M8_16; // assume are in a 16 bit bus ee.select = EE_SELECT_M8_16; ee.chipselect = EE_CS_M8_16; ee.data_out = EE_DATA_OUT_M8_16; } return; } /* * void Mach8ComboDescribeEEPROM(void); * * Fill in the EEPROM description structure for the Graphics ULTRA * and Graphics VANTAGE. These cards always have both the 8514 and * the VGA enabled, so the EEPROM is ALWAYS read VGA style. */ extern void Mach8ComboDescribeEEPROM(void) { ee.addr_size = 6; ee.iop_out = EXT_GE_CONFIG; ee.iop_in = EXT_GE_STATUS; ee.data_in = EE_DATA_IN; ee.clock = EE_CLK_M8_16; // are in a 16 bit bus ee.select = EE_SELECT_M8_16; ee.chipselect = EE_CS_M8_16; ee.data_out = EE_DATA_OUT_M8_16; ee.EEread = ee_read_vga; // VGA style ee.EEcmd = ee_cmd_vga; return; } //******************* end of EEPROM.C ******************************