4401 lines
117 KiB
C
4401 lines
117 KiB
C
static char sccsid[] = "@(#)70 1.19 src/bos/usr/lib/methods/graphics/cfg_graphics_frs_tools.c, dispcfg, bos411, 9428A410j 6/16/94 17:48:48";
|
||
/*
|
||
* COMPONENT_NAME: DISPCFG
|
||
*
|
||
* FUNCTIONS: FRS_Copy_File
|
||
* FRS_Enable_BUID_2x_Device1620
|
||
* FRS_Enable_BUID_40_Device1715
|
||
* FRS_Find_Video_Device2292
|
||
* FRS_Make_Temp_File2599
|
||
* FRS_Search_for_RSCAN_6001_BLK1801
|
||
* FRS_Search_for_RSCAN_6002_BLK2032
|
||
* FRS_Test_Addr_for_RSCAN_PS21447
|
||
* FRS_Update_ODM_From_File2824
|
||
* FRS_Validate_RSCAN_VIDEO_HEAD1306
|
||
* FRS_checksum
|
||
* FRS_crc16
|
||
* nvram_close
|
||
* nvram_iocc_read_byte
|
||
* nvram_iocc_write_byte
|
||
* nvram_open
|
||
* nvram_read_byte
|
||
* nvram_read_bytes
|
||
* nvram_read_word
|
||
* nvram_read_words
|
||
* nvram_write_byte
|
||
* nvram_write_word
|
||
*
|
||
*
|
||
* ORIGINS: 27
|
||
*
|
||
* IBM CONFIDENTIAL -- (IBM Confidential Restricted when
|
||
* combined with the aggregated modules for this product)
|
||
* SOURCE MATERIALS
|
||
*
|
||
* (C) COPYRIGHT International Business Machines Corp. 1992, 1993, 1994
|
||
* All Rights Reserved
|
||
* US Government Users Restricted Rights - Use, duplication or
|
||
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
||
*/
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** MODULE HEADER TOP ************************************
|
||
*****************************************************************************
|
||
---------------------------------------------------------------------------
|
||
|
||
PURPOSE:
|
||
This routine is part of a problem-state process that
|
||
is executed by the system during configuration and by
|
||
the system when certain configuration commands are
|
||
invoked. The functions it contains are the standard
|
||
functions used by the AIX devices configuration architecture.
|
||
|
||
Typically, device specific configuration methods are
|
||
compiled into a ".o" which are linked with a standard
|
||
"main.o". This is because the configuration process is
|
||
relatively standard. However, for display devices, there
|
||
are sufficient reasons to have a separate "main" that
|
||
has been design just for graphics.
|
||
|
||
This software therefore is called from routines in
|
||
the companion file "cfg_graphics.c".
|
||
|
||
This routine also supports the common character mode
|
||
VDD device driver in addition to the regular full function
|
||
VDD. See design 13588 for additional details.
|
||
|
||
MODULE ORGANIZATION:
|
||
|
||
The executable config method for any graphics device is composed
|
||
of several modules that are linked together. The following
|
||
is a list of the required and the optional modules:
|
||
|
||
cfg_graphics.o This module provides the "main" routine.
|
||
It contains the control flow and the
|
||
device independent front end. It manages
|
||
most of the interface with the ODM.
|
||
|
||
The module contains static internal routines
|
||
that it alone uses.
|
||
|
||
The module also contains some global data
|
||
available to all of the other modules.
|
||
|
||
cfg_graphics_tools.o A set of device independent tools that support
|
||
the cfg_graphics programs but are useful to
|
||
other configuration methods and to device
|
||
dependent mehtods as well.
|
||
|
||
cfg_graphics_frs_tools.o A set of device independent routines which
|
||
help manage the Feature ROM Scan capabilities
|
||
found on newer display adapters.
|
||
|
||
chkslot.o This is a system module that does checking
|
||
of the MicroChannel slot.
|
||
|
||
cfgtools.o This is a system module that provides a
|
||
basic set of configuration tools for use
|
||
by the other pieces of the configuration
|
||
method executable.
|
||
|
||
cfg_ccmdd.o This module contains the common character
|
||
mode substitutes that are used instead
|
||
of the per-device entry points. The
|
||
"main" routine will either route its
|
||
device cfg method calls to the device
|
||
method or to cfg_ccmdd.o, depending on
|
||
the presence of a working device vdd and
|
||
a working device ucode file.
|
||
|
||
NOTES ON MACROS:
|
||
|
||
1. This module makes heavy use of macros.
|
||
2. In general, macos begin with CAPITALIZED words.
|
||
3. Macros with common prefix values are generally all related
|
||
and may all come from the same .h file.
|
||
4. The following pairing of macros and include files
|
||
is useful to understand:
|
||
|
||
INCLUDE FILE MACRO FILE PREFIX
|
||
============ ============== ===========
|
||
ccm.h ccm_macros.h CCM_
|
||
cdd.h cdd_macros.h CDD_
|
||
frs.h frs_macs.h RSCAN_
|
||
frs_display.h frs_display_macs.h RSCAN_
|
||
cfg_graphics.h cfg_graphics_macros.h CFGGRAPH_
|
||
|
||
5. Inside a given macro file, there are usually references
|
||
to more than one typedef. Each typedef has its own
|
||
unique string. This string is added to the macro file
|
||
prefix. For example, consider "frs.h" with prefix "FRS_"
|
||
used in its macros. The following table would apply:
|
||
|
||
File: frs.h Prefix: FRS_
|
||
|
||
TYPEDEF MACRO_PREFIX
|
||
========= ==============
|
||
rom_scan_ps2_header_t RSCAN_PS2_
|
||
rom_scan_R2_6002_block_t RSCAN_6002_BLK_
|
||
|
||
6. The portion of the macro which references specific members
|
||
of a structure is usually not capitalized, e.g.
|
||
|
||
RSCAN_PS2_dynamic_rom_flag( &head )
|
||
|
||
7. If a string is FULL CAPS and has the naming convention above,
|
||
it is most likely a constant and was most likely defined
|
||
in the include file rather than the macro file. The only
|
||
exceptions to this are the macros which are used as
|
||
typedefs or structure sizeof values.
|
||
|
||
|
||
*****************************************************************************
|
||
********************** MODULE HEADER BOTTOM *********************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*==========================================================================
|
||
|
|
||
| System include files required by all cfg method main programs
|
||
|
|
||
|==========================================================================*/
|
||
|
||
#include <stdio.h>
|
||
#include <sys/types.h>
|
||
#include <sys/errno.h>
|
||
#include <sys/lockl.h>
|
||
#include <sys/cfgdb.h>
|
||
#include <sys/cfgodm.h>
|
||
#include <cf.h>
|
||
#include <sys/sysconfig.h>
|
||
#include <sys/sysmacros.h>
|
||
#include <sys/device.h>
|
||
#include <fcntl.h>
|
||
#include <sys/mode.h>
|
||
|
||
#include <sys/stat.h> /* used by DD_Not_Found */
|
||
|
||
|
||
|
||
/*==========================================================================
|
||
|
|
||
| Local debug routines are defined here
|
||
|
|
||
|==========================================================================*/
|
||
|
||
#include "cfgdebug.h"
|
||
|
||
#undef WGA_PROTOTYPE_MODEL
|
||
|
||
/*==========================================================================
|
||
|
|
||
| Include files which describe the common character mode interface and
|
||
| the video ROM scan interface
|
||
|
|
||
|==========================================================================*/
|
||
|
||
#ifdef CFGDEBUG
|
||
# define STATIC
|
||
#else
|
||
# define STATIC static
|
||
#endif
|
||
|
||
#define FAIL -1
|
||
#define PASS 0
|
||
|
||
#define MEM_BLOCK_40K ( 40 * 1024 )
|
||
#define MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) )
|
||
|
||
#define Boolean unsigned int /* need by aixfont.h */
|
||
#define Bool unsigned int /* need by aixfont.h */
|
||
|
||
#include <sys/aixfont.h>
|
||
#include <sys/dir.h> /* needed by ccm_dds.h */
|
||
#include <sys/mdio.h> /* needed by cdd_macros.h */
|
||
#include <sys/file.h> /* needed by ccm.h */
|
||
#include <sys/intr.h> /* needed by vt.h */
|
||
|
||
#include <sys/ioacc.h> /* needed by ccm_dds.h */
|
||
#include <sys/adspace.h> /* needed by ccm_dds.h */
|
||
|
||
#include <sys/display.h>
|
||
#include "vt.h"
|
||
|
||
#include "cdd.h"
|
||
#include "cdd_macros.h"
|
||
|
||
#include "cdd_intr.h"
|
||
#include "cdd_intr_macros.h"
|
||
|
||
#include "ccm.h"
|
||
#include "ccm_macros.h"
|
||
|
||
#include "frs.h"
|
||
#include "frs_macs.h"
|
||
|
||
#include "frs_display.h"
|
||
#include "frs_display_macs.h"
|
||
|
||
#include <graphics/60x_regs.h> /* 601_CHANGE */
|
||
#include "frs_60x.h"
|
||
|
||
/*==========================================================================
|
||
|
|
||
| include a file which defines the cfg macros used by our cfg methods
|
||
|
|
||
|==========================================================================*/
|
||
|
||
#include "cfg_graphics.h"
|
||
#include "cfg_graphics_frs.h"
|
||
#include "cfg_graphics_macros.h"
|
||
|
||
|
||
/*==========================================================================
|
||
|
|
||
| Define function references
|
||
|
|
||
|==========================================================================*/
|
||
|
||
/*--- from libc.a ---*/
|
||
extern int getopt( );
|
||
extern void exit( );
|
||
extern int strncmp( );
|
||
extern int atoi( );
|
||
extern long strtol( );
|
||
|
||
|
||
/*--- from libcfg.a ---*/
|
||
extern int busresolve ();
|
||
|
||
|
||
|
||
/*--- from chkslot.o ----*/
|
||
extern int chkslot ();
|
||
|
||
|
||
|
||
|
||
/*---- from cfgtools.o ----*/
|
||
extern int Get_Parent_Bus( );
|
||
extern int getatt( );
|
||
extern int convert_att( );
|
||
extern int convert_seq( );
|
||
extern struct attr * att_changed( );
|
||
extern int mk_sp_file( );
|
||
extern char * read_descriptor( );
|
||
extern void add_descriptor( );
|
||
extern void put_vpd( );
|
||
|
||
|
||
|
||
/*--- from AIX BOS runtime environment ---*/
|
||
extern int odm_initialize ( );
|
||
extern int odm_lock( );
|
||
extern void setleds( );
|
||
|
||
|
||
/*==========================================================================
|
||
|
|
||
| Define some data global to these functions, so that it can be readily
|
||
| shared and accessed by the functions and by the "main" and other functions
|
||
| in "cfg_graphics.c" and the functions in cfgyyy.c
|
||
|
|
||
|==========================================================================*/
|
||
|
||
|
||
/*=========================================================
|
||
|
|
||
| Define the anchor pointer used for cfg_graphics macros
|
||
| to access various pieces of global data required by
|
||
| the config methods and their device specific pieces
|
||
|
|
||
|==========================================================*/
|
||
|
||
|
||
extern cfg_graphics_data_t * __GLOBAL_DATA_PTR;
|
||
|
||
|
||
CLASS_SYMBOL odm_mount_class();
|
||
extern int stanza_line_number;
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** GENERAL COMMENTS ON FEATURE ROM SCAN *****************
|
||
*****************************************************************************
|
||
|
||
The purpose of the ROM Scan function is to allow future
|
||
Microchannel adapters to participate as display consoles without
|
||
requiring changes to IPL ROS or to the Common Character Mode
|
||
display device driver architecture. It also minimizes the media
|
||
requirements of boot and diagnostic media, since no device
|
||
microcode is stored on the media, and since only one device
|
||
driver is stored.
|
||
|
||
Microchannel cards implement ROM Scan using a dynamic linked
|
||
list of ROM blocks. Each ROM block has a field which
|
||
identifies the ROM class. The ROM Scan process involves a
|
||
search of this linked list for ROMs with the class "switch
|
||
adapter ROM". If a ROM of this class is found, and it is
|
||
identified as a RISC/6000 ROM, then IPL ROS will attempt to
|
||
load and execute this code in order to complete the IPL
|
||
process.
|
||
|
||
ROM Scan involves two main functions:
|
||
|
||
1. Search for feature ROM Scan cards on the Microchannel. The
|
||
results of this search are stored in CDD structures.
|
||
|
||
2. Add the various XCOFF binaries to the program or to the
|
||
kernel using the load or the kmod_load calls, respectively.
|
||
|
||
|
||
DESIGN CONSIDERATIONS/HISTORY
|
||
_____________________________
|
||
|
||
(NOTE: This section is based on the Microchannel adapter
|
||
strategy. See other design documents for the strategy for
|
||
other buses. )
|
||
|
||
ROM Scan cards will contain ROMs with Video ROM Feature Code
|
||
that will enable the adapter to participate in the CCM
|
||
process. PC and PS/2 systems have used a ROM Scan process
|
||
which allows adapter cards to automatically link their
|
||
initialization functions into the IPL process.
|
||
|
||
Listed below are some of the design considerations for
|
||
Video ROM Scan:
|
||
|
||
|
||
1. Each RISC/6000 ROM will have a field which identifies it as
|
||
either Device Boot or Video Expansion code (Video ROM Scan
|
||
will be supported in Release 3.2.2).
|
||
|
||
2. All cards implementing ROM Scan will contain a PS/2 ROM
|
||
header. PS/2 ROMs will be validated using a checksum. The
|
||
algorithm is a modulo 0x100 summation of all the bytes of
|
||
the PS/2 ROM. The sum will be zero for a valid ROM.
|
||
|
||
3. The Feature ROMs are accessed as Bus memory.
|
||
|
||
4. PS/2 ROM header records will be located on 2K boundaries in
|
||
bus memory address space ranges of hex C0000 through C3FFF
|
||
and C8000 through C9FFF.
|
||
|
||
5. RISC/6000 ROMs must be in the bus memory address range
|
||
of 1M to 2M.
|
||
|
||
6. No CCM DD or config method shall use any DMA or Interrupt
|
||
services in accessing the adapter card's Feature ROM.
|
||
|
||
7. RISC/6000 ROMs will validated by a 16 bit CRC. The CRC
|
||
polynomial is 1 + X(5) + X(12) + X(16) with the CRC being
|
||
initialized to hex 'FFFF'. The CRC is calculated by
|
||
starting at the fifth byte ( offset 4) in the RISC/6000
|
||
ROM.
|
||
|
||
8. During any ROM Scan I/O attempt with a ROM Scan card, all
|
||
other cards on the same bus will be disabled.
|
||
|
||
|
||
PSEUDOCODE / LOGICAL STATES
|
||
|
||
The three status flags adapter_present, adapter_ bad and
|
||
detected_error are set according to the following conditions:
|
||
|
||
o Adapter_present:
|
||
|
||
This flag is set to '1' if the conditions below are met:
|
||
|
||
- A valid PS/2 ROM is found (i.e. Hex 55,AA for the first
|
||
two bytes)
|
||
- A dynamic link flag of 0x7D is found.
|
||
- The PS/2 ROM contains a block with the "RISC6000" flag.
|
||
|
||
o Detected_error:
|
||
|
||
This flag is set to 0, 1, 2 or 3 depending on the
|
||
following conditions:
|
||
|
||
0 - No software error was detected by Romscan.
|
||
1 - The RISC/6000 ROM failed the CRC (adapter_present will be '1').
|
||
2 - The address of the RISC/6000 ROM was not in the valid range
|
||
(adapter_present will be '1').
|
||
3 - The PS/2 ROM failed the Check sum (adapter_present will be zero).
|
||
|
||
o Adapter_bad:
|
||
|
||
This flag is meaningful only when the adapter_present flag
|
||
is '1'. It is set to 0,1 or 2 depending on the following conditions:
|
||
|
||
0 - No software error was detected.
|
||
1 - The RISC/6000 ROM failed the CRC. (adapter_present will be '1')
|
||
2 - The address of the RISC/6000 ROM was out of the valid range
|
||
(adapter_present will be '1').
|
||
|
||
|
||
ADAPTER ROMS
|
||
|
||
All cards implementing ROM Scan will contain the standard PS/2
|
||
ROM header. CCM will first look at this header to
|
||
determine if the card contains a dynamic ROM list in which a
|
||
RISC/6000 ROM might be found. The PS/2 ROM header has the
|
||
format shown in Figure 1.
|
||
|
||
|
||
0 *-----------------------------------------------------*
|
||
| |
|
||
| Hex '55AA' |
|
||
| |
|
||
2 |-----------------------------------------------------|
|
||
| |
|
||
| Length of PS/2 ROM in 512 byte blocks |
|
||
| |
|
||
3 |-----------------------------------------------------|
|
||
| . |
|
||
| . |
|
||
| . |
|
||
125 |-----------------------------------------------------|
|
||
| |
|
||
| Flag indicating Dynamic ROM list exists |
|
||
| This Byte will equal hex '7D' if list exists |
|
||
| |
|
||
126 |-----------------------------------------------------|
|
||
| . |
|
||
| . |
|
||
| . |
|
||
256 |-----------------------------------------------------|
|
||
| |
|
||
| Length of Dynamic ROM list |
|
||
| |
|
||
258 |-----------------------------------------------------|
|
||
| |
|
||
| Offset to beginning of Dynamic ROM list |
|
||
| (two bytes) |
|
||
| |
|
||
*-----------------------------------------------------*
|
||
0 31
|
||
|
||
Figure 1. Format PS/2 ROM Header for ROM Scan adapter cards
|
||
|
||
|
||
|
||
The Dynamic ROM list will be contained in the PS/2 ROM. All
|
||
blocks in the linked list will have a pointer and a block
|
||
identifier. A RISC/6000 block will have the format shown in
|
||
Figure 2.
|
||
|
||
|
||
|
||
0 *-----------------------------------------------------*
|
||
| |
|
||
| Pointer to next block in linked list |
|
||
| (zero if last block in list) |
|
||
| |
|
||
2 |-----------------------------------------------------|
|
||
| |
|
||
| Block Identifier: 1 = "Switch Adapter ROM" |
|
||
| |
|
||
|-----------------------------------------------------|
|
||
| |
|
||
| **** The following fields pertain only to a **** |
|
||
| **** RISC/6000 Block **** |
|
||
| |
|
||
4 |-----------------------------------------------------|
|
||
| |
|
||
| RISC/6000 ROM Identifier Flag |
|
||
| ASCII characters "RISC6000" |
|
||
| |
|
||
12 |-----------------------------------------------------|
|
||
| |
|
||
| Address of RISC/6000 ROM when enabled |
|
||
| |
|
||
16 |-----------------------------------------------------|
|
||
| |
|
||
| Value of POS Registers 2-5 to enable |
|
||
| RISC/6000 ROM (4 bytes) |
|
||
| |
|
||
*-----------------------------------------------------*
|
||
0 31
|
||
|
||
Figure 2. Structure of blocks in Dynamic ROM list
|
||
|
||
ROM Scan will traverse this linked list looking for a block
|
||
with an ID of '1'. This identifies the ROM associated with
|
||
this block as a "Feature ROM" and can be "switched in" as a
|
||
replacement for the PS/2 ROM. For a RISC/6000 ROM, the eight
|
||
bytes after the block ID will contain the ASCII characters
|
||
"RISC6000". The block will also contain the start address of
|
||
the RISC/6000 ROM and the value of the POS Registers two
|
||
through five which should be used to enable the ROM. These
|
||
values must be written to the POS registers for RISC/6000 ROM
|
||
to be accessed.
|
||
|
||
The RISC/6000 ROM will have a 256 byte header with the format
|
||
shown in Figure 3.
|
||
|
||
|
||
|
||
|
||
0 *-----------------------------------------------------*
|
||
| |
|
||
| Length of RISC/6000 ROM in 512 byte blocks |
|
||
| |
|
||
2 |-----------------------------------------------------|
|
||
| |
|
||
| 16 bit CRC for RISC/6000 ROM |
|
||
| |
|
||
4 |-----------------------------------------------------|
|
||
| |
|
||
| RISC/6000 ROM Type |
|
||
| |
|
||
8 |-----------------------------------------------------|
|
||
| |
|
||
| Offset to boot expansion code |
|
||
| |
|
||
12 |-----------------------------------------------------|
|
||
| |
|
||
| Length of data area |
|
||
| required by boot expansion code |
|
||
| |
|
||
16 |-----------------------------------------------------|
|
||
| |
|
||
| 240 bytes Reserved |
|
||
| |
|
||
*-----------------------------------------------------*
|
||
0 31
|
||
|
||
Figure 3. Format of RISC/6000 ROM header for ROM Scan adapter cards
|
||
|
||
FUNCTION/FLOW
|
||
_____________
|
||
|
||
|
||
For each slot the following steps must be performed:
|
||
|
||
1. Initialize the three status flags adapter_present,
|
||
adapter_bad and detected_error to FALSE:
|
||
|
||
2. Check if an adapter card is present
|
||
Note:
|
||
For slots greater than 7 (slots start at 0) the BUID
|
||
in the segment register must be changed
|
||
in order to access them.
|
||
|
||
3. If an adapter is present then enable the card.
|
||
|
||
4. Scan the I/O address range C0000 -> DFFFF in 2K increments
|
||
for a PS/2 header (55 AA). (Only one header per slot)
|
||
|
||
5. If a PS/2 header is found then validate the PS/2 ROM by
|
||
using a modulo hex 100 checksum.
|
||
|
||
- If the Checksum fails then set the detected_error flag
|
||
|
||
6. If the PS/2 ROM is valid then check if a Dynamic ROM list exists.
|
||
|
||
7. If a Dynamic ROM list exists then do a linear search of
|
||
the linked list for a RISC/6000 ROM.
|
||
|
||
8. If a RISC/6000 ROM does exist then set the adapter_present
|
||
flag to TRUE.
|
||
|
||
9. Enable RISC/6000 ROM by writing the given values to the
|
||
POS registers 2 through 5.
|
||
|
||
10. Check to see if the RISC/6000 ROM address is in the
|
||
valid range of 64K to 1Meg.
|
||
|
||
- If the address is invalid then set the adapter_bad
|
||
and detected_error flags
|
||
|
||
11. If the address is valid then perform a 16 bit CRC on
|
||
the RISC/6000 ROM.
|
||
|
||
- If the ROM is invalid then set the adapter_bad
|
||
and detected_error flags
|
||
|
||
12. If the status flags have been set to the following state:
|
||
|
||
- adapter_present= TRUE
|
||
- adapter_bad= FALSE
|
||
- detected_error = FALSE
|
||
- RISC6000_ROM_type = VIDEO_ROM
|
||
|
||
then set the scan_code_present flag to VIDEO_ROM. If
|
||
the flags are not in the valid state then set the
|
||
scan_code_present flag equal to the detected_error flag.
|
||
|
||
13. If the ROM is valid then attempt to allocate memory
|
||
for the various load modules and then attempt to read them in.
|
||
|
||
|
||
14. Disable card by resetting bit 0 in POS register 2.
|
||
|
||
|
||
*****************************************************************************
|
||
********************** END OF GENERAL COMMENTS ******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME:
|
||
nvram_open()
|
||
nvram_close
|
||
nvram_read_byte()
|
||
nvram_read_bytes()
|
||
nvram_read_word()
|
||
nvram_write_byte()
|
||
nvram_write_word()
|
||
|
||
|
||
TITLE: Functions which driver the machine device driver and perform
|
||
I/O to determine the existence of Feature ROM Scan constructs
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
/dev/nvram is the most general means of access to the machine
|
||
device driver. Other forms include /dev/bus0. We will use
|
||
the general means whenever possible
|
||
|
||
NOTE: Defect 64362 discusses a bug in /usr/ccs/libc.a.min in whihc
|
||
the ioctlx function is not exported from the library. The
|
||
workaround for this defect in our code is to use another
|
||
exported symbol, __ioctl. Not pretty, but it works.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - a structure of type FRS_access_t *
|
||
this structure holds the data and pointers that
|
||
are used by all FRS_* subroutines
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
the member ctl.mdd is updated after calls to the machine device
|
||
driver
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
#define IOCTLX __ioctl
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_open(
|
||
FRS_access_t * ctl
|
||
)
|
||
{
|
||
ctl->fd = open( "/dev/nvram", O_RDWR, 0 );
|
||
|
||
if ( ctl->fd < 0 )
|
||
{
|
||
DEBUG_1( "Open of /dev/nvram failed with rc=%x \n", ctl->fd )
|
||
|
||
return (ctl->fd);
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_close(
|
||
FRS_access_t * ctl
|
||
)
|
||
{
|
||
close( ctl->fd );
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_read_byte(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar * pval
|
||
)
|
||
{
|
||
int rc;
|
||
uchar local_value;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) &local_value;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_BYTE;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSGET,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
*pval = local_value;
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_iocc_read_byte(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar * pval
|
||
)
|
||
{
|
||
int rc;
|
||
uchar local_value;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) &local_value;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_BYTE;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSGET,
|
||
& (ctl->mdd),
|
||
ctl->iocc_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
*pval = local_value;
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_read_word(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
ulong * pval
|
||
)
|
||
{
|
||
int rc;
|
||
ulong local_value;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) pval;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_WORD;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSGET,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
*pval = local_value;
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
| This function is not a general purpose read words function!
|
||
|
|
||
| It is mainly used to read the Feature ROM. On 601 device,
|
||
| it uses ioctl MIOVPGGET provided by the machine driver
|
||
|
|
||
| Currently MIOVPDGET only works on power pc and it only
|
||
| reads the ROM in bytes.
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_read_words(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar * pval,
|
||
ulong len /* Length in bytes */
|
||
)
|
||
{
|
||
int rc;
|
||
int i;
|
||
ulong address;
|
||
void * local_values;
|
||
|
||
|
||
if ( ADDR_IS_60x_VPD_FRS_SPACE(ctl->bus_segreg, addr) )
|
||
{
|
||
rc = rd_60x_vpd_feat_rom (ctl->bus_slot, addr, pval, len);
|
||
|
||
if (rc)
|
||
{
|
||
DEBUG_3("601 read_words:failed - slot=%x, seg=%x, addr=%x\n",
|
||
ctl->bus_slot,ctl->bus_segreg,addr);
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
return (0);
|
||
|
||
}
|
||
else if ( ADDR_IS_60x_CFG_SPACE(ctl->bus_segreg, addr) )
|
||
{
|
||
DEBUG_3("illegal 601 read_words - slot=%x, seg=%x, addr=%x\n",
|
||
ctl->bus_slot,ctl->bus_segreg, addr);
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
local_values = (void *)malloc( len );
|
||
|
||
if ( local_values == NULL )
|
||
{
|
||
return( E_MALLOC );
|
||
}
|
||
|
||
ctl->mdd.md_data = (char * ) local_values;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_WORD;
|
||
address = addr;
|
||
for (i = 0 ; i < ( len/sizeof(int) ) ; i++)
|
||
{
|
||
ctl->mdd.md_addr = address;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSGET,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
ctl->mdd.md_data +=4;
|
||
address +=4;
|
||
}
|
||
memcpy( pval, local_values, len );
|
||
free (local_values);
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_write_byte(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar val
|
||
)
|
||
{
|
||
int rc;
|
||
uchar local_value = val;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) &local_value;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_BYTE;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSPUT,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_iocc_write_byte(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar val
|
||
)
|
||
{
|
||
int rc;
|
||
uchar local_value = val;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) &local_value;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_BYTE;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSPUT,
|
||
& (ctl->mdd),
|
||
ctl->iocc_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| Write 1 to POS2 - bit0 - to enable
|
||
| Micro-channel adapter at the given slot
|
||
|
|
||
|-----------------------------------------------*/
|
||
int
|
||
enable_device(p_ctl)
|
||
|
||
FRS_access_t * p_ctl;
|
||
|
||
{
|
||
int iocc_addr, rc;
|
||
unsigned char val;
|
||
|
||
/*
|
||
calculate POS2 in iocc space for the given slot
|
||
By iocc rule, only use logical slot which is
|
||
equal to physical slot minus one.
|
||
*/
|
||
|
||
iocc_addr = POSREG(2,p_ctl->bus_slot) + CDD_IOCC_BASE;
|
||
|
||
rc = nvram_iocc_read_byte(p_ctl, iocc_addr, &val) ;
|
||
|
||
if ( rc == 0)
|
||
{
|
||
#define CARD_ENABLE 0x1
|
||
|
||
rc = nvram_iocc_write_byte(p_ctl, iocc_addr, (val | CARD_ENABLE) ) ;
|
||
}
|
||
|
||
return (rc);
|
||
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| Write 0 to POS2 - bit0 - to disable
|
||
| Micro-channel adapter at the given slot
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int
|
||
disable_device(p_ctl)
|
||
|
||
FRS_access_t * p_ctl;
|
||
|
||
{
|
||
int iocc_addr, rc;
|
||
unsigned char val;
|
||
|
||
/*
|
||
calculate POS2 in iocc space for the given slot
|
||
By iocc rule, only use logical slot which is
|
||
equal to physical slot minus one.
|
||
*/
|
||
|
||
iocc_addr = POSREG(2,p_ctl->bus_slot) + CDD_IOCC_BASE;
|
||
|
||
rc = nvram_iocc_read_byte(p_ctl, iocc_addr, &val) ;
|
||
|
||
if ( rc == 0 )
|
||
{
|
||
#define CARD_DISABLE (~ (0x1) )
|
||
|
||
val = (unsigned char) (val & CARD_DISABLE);
|
||
rc = nvram_iocc_write_byte(p_ctl, iocc_addr, val) ;
|
||
}
|
||
|
||
return (rc);
|
||
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_write_word(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
ulong val
|
||
)
|
||
{
|
||
int rc;
|
||
ulong local_value = val;
|
||
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) &local_value;
|
||
ctl->mdd.md_size = 1;
|
||
ctl->mdd.md_incr = MV_WORD;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSPUT,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
| This function is not a general purpose read bytes function!
|
||
|
|
||
| It is mainly used to read the Feature ROM. On 601 device,
|
||
| it uses ioctl MIOVPGGET provided by the machine driver
|
||
|
|
||
| Currently MIOVPDGET only works on power pc and it only
|
||
| reads the ROM in bytes.
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
nvram_read_bytes(
|
||
FRS_access_t * ctl,
|
||
ulong addr,
|
||
uchar * pval,
|
||
ulong len
|
||
)
|
||
{
|
||
int rc;
|
||
uchar * local_values;
|
||
|
||
if ( ADDR_IS_60x_VPD_FRS_SPACE(ctl->bus_segreg, addr) )
|
||
{
|
||
rc = rd_60x_vpd_feat_rom (ctl->bus_slot, addr, pval, len);
|
||
|
||
if (rc)
|
||
{
|
||
DEBUG_3("601 read_bytes:failed - slot=%x, seg=%x, addr=%x\n",
|
||
ctl->bus_slot, ctl->bus_segreg,addr);
|
||
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
return (0);
|
||
|
||
}
|
||
else if ( ADDR_IS_60x_CFG_SPACE(ctl->bus_segreg, addr) )
|
||
{
|
||
DEBUG_3("illegal 601 read_bytes - slot=%x, seg=%x, addr=%x\n",
|
||
ctl->bus_slot, ctl->bus_segreg, addr);
|
||
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
local_values = (uchar *)malloc( len );
|
||
|
||
if ( local_values == NULL )
|
||
{
|
||
return( E_MALLOC );
|
||
}
|
||
|
||
ctl->mdd.md_addr = addr;
|
||
ctl->mdd.md_data = (char * ) local_values;
|
||
ctl->mdd.md_size = len;
|
||
ctl->mdd.md_incr = MV_BYTE;
|
||
|
||
rc = IOCTLX( ctl->fd,
|
||
MIOBUSGET,
|
||
& (ctl->mdd),
|
||
ctl->bus_segreg );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
memcpy( pval, local_values, len );
|
||
free (local_values);
|
||
|
||
return (0);
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_checksum( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_PS2 structure in memory has a valid checksum
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initializes local pointers.
|
||
Computes span of full size of header including linked list.
|
||
Allocates local storage for full span.
|
||
Reads in the full header and romscan blocks.
|
||
Computes the checksum.
|
||
Returns the result.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
bus_head - holds the bus address of the RSCAN_PS2 structure
|
||
|
||
mem_head - holds the mem address of the copy of the RSCAN_PS2 structure
|
||
|
||
ctl - holds an FRS control structure pointer
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_checksum(
|
||
FRS_access_t * ctl,
|
||
RSCAN_PS2 * bus_head,
|
||
RSCAN_PS2 * mem_head,
|
||
int (* fp) ()
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
uchar checksum;
|
||
char * buffer;
|
||
size_t head_size;
|
||
int i, j;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
|
||
/*------------------------------------
|
||
| set up a buffer the size of the ROM
|
||
|------------------------------------*/
|
||
|
||
head_size = CFG_GRAPH_FRS_BLK_SIZE * RSCAN_PS2_Blength( mem_head );
|
||
|
||
buffer = (char *) malloc( head_size );
|
||
|
||
if ( buffer == NULL ) { return (E_MALLOC); }
|
||
|
||
/*-------------------------------------
|
||
| read in the full ROM
|
||
|-------------------------------------*/
|
||
|
||
rc = (* fp )( ctl, (uchar *) bus_head,
|
||
buffer, head_size );
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*--------------------------------------
|
||
| do the checksum
|
||
|--------------------------------------*/
|
||
|
||
checksum = 0;
|
||
|
||
for( i = 0; i < head_size; i++)
|
||
{
|
||
checksum += *( buffer + i );
|
||
}
|
||
|
||
/*-------------------------------------
|
||
| clean up and return results
|
||
|-------------------------------------*/
|
||
|
||
free( buffer );
|
||
|
||
if( checksum != 0 ) /** if checksum nonzero then error */
|
||
{
|
||
return(E_VPD);
|
||
}
|
||
|
||
return(0); /** checksum is zero, ROM OK */
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_crc16( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_VIDEO_HEAD structure in memory has a valid CRC residue
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
RISC/6000 ROMs will validated by a 16 bit CRC.
|
||
The CRC polynomial is 1 + X(5) + X(12) + X(16)
|
||
with the CRC being initialized to hex 'FFFF'.
|
||
The CRC is calculated by starting at the fifth
|
||
byte ( offset 4) in the RISC/6000 ROM.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds an FRS control structure pointer
|
||
|
||
buffer - holds the mem address of the copy of the total
|
||
VIDEO rom contents
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_crc16(
|
||
FRS_access_t * ctl,
|
||
RSCAN_VIDEO_HEAD * mem_head
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
int i;
|
||
ushort rom_Blength;
|
||
size_t rom_size;
|
||
ushort rom_residue;
|
||
|
||
char * p_buffer;
|
||
char datav;
|
||
|
||
#define CRC_MASK 0xff07
|
||
#define COMBINE(x, y) (((x) << 8) | (y))
|
||
|
||
struct bytes
|
||
{
|
||
char msb;
|
||
char lsb;
|
||
};
|
||
|
||
union accum
|
||
{
|
||
ushort whole;
|
||
struct bytes byte;
|
||
|
||
} avalue, dvalue;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
rom_Blength = RSCAN_VIDEO_HEAD_rom_Blength( mem_head );
|
||
rom_size = CFG_GRAPH_FRS_BLK_SIZE * rom_Blength;
|
||
|
||
dvalue.whole = 0xffff;
|
||
avalue.whole = 0;
|
||
|
||
p_buffer = (char *) mem_head;
|
||
|
||
/*----------------------------------------------------
|
||
| process the CRC
|
||
|
|
||
| start at the 4/th byte
|
||
|
|
||
| result is stored in dvalue.whole upon exit
|
||
|-----------------------------------------------------*/
|
||
|
||
for ( i=4; i < rom_size; i++ )
|
||
{
|
||
datav = *(p_buffer+i);
|
||
|
||
avalue.byte.lsb = (datav ^ dvalue.byte.lsb);
|
||
dvalue.byte.lsb = avalue.byte.lsb;
|
||
avalue.whole = ((avalue.whole * 16) ^ dvalue.byte.lsb);
|
||
dvalue.byte.lsb = avalue.byte.lsb;
|
||
avalue.whole <<= 8;
|
||
|
||
avalue.whole >>= 1;
|
||
avalue.byte.lsb ^= dvalue.byte.lsb;
|
||
|
||
avalue.whole >>= 4;
|
||
|
||
avalue.whole = COMBINE(avalue.byte.lsb, avalue.byte.msb);
|
||
avalue.whole = ((avalue.whole & CRC_MASK) ^ dvalue.byte.lsb);
|
||
avalue.whole = COMBINE(avalue.byte.lsb, avalue.byte.msb);
|
||
avalue.byte.lsb ^= dvalue.byte.msb;
|
||
dvalue.whole = avalue.whole;
|
||
}
|
||
|
||
/*------------------------------------------------------------
|
||
| test the residue against what is stored in the ROM
|
||
|------------------------------------------------------------*/
|
||
|
||
rom_residue = RSCAN_VIDEO_HEAD_residue( mem_head );
|
||
|
||
if ( rom_residue != dvalue.whole )
|
||
{
|
||
return ( E_VPD );
|
||
}
|
||
|
||
return (0);
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Validate_RSCAN_VIDEO_Head( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_VIDEO_HEAD structure sits at a particular address.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initialize local pointers.
|
||
Read in the RSCAN_VIDEO_HEAD structure.
|
||
From it, get the block length and compute total size.
|
||
Allocate a buffer for the total size.
|
||
Read in the full VIDEO rom.
|
||
Perform the CRC test on the memory copy.
|
||
If OK, then update pointers.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
The ctl->bus_rscan_r2_head member holds the address
|
||
of the header to be tested.
|
||
|
||
valid - a boolean stating whether the address is
|
||
a valid RSCAN_PS2 block
|
||
|
||
RETURNS:
|
||
mallocs space for the RSCAN_VIDEO_HEAD contents in the ctl structure
|
||
The space holds the full ROM contents.
|
||
|
||
returns an integer return code stating whether an error occurred or not.
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Validate_RSCAN_VIDEO_HEAD(
|
||
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
ulong * valid, /* boolean return var */
|
||
ulong buid_type
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
char * buffer;
|
||
RSCAN_VIDEO_HEAD * bus_head;
|
||
RSCAN_VIDEO_HEAD mem_head;
|
||
ushort rom_Blength;
|
||
size_t rom_size;
|
||
int (* read_func )() ;
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
ctl->mem_rscan_r2_head = NULL;
|
||
|
||
bus_head = (RSCAN_VIDEO_HEAD *) ctl->bus_rscan_r2_head;
|
||
|
||
DEBUG_1("Validate_RSCAN_VIDEO_HEAD: R2 header offset =%x\n",bus_head);
|
||
|
||
switch (buid_type)
|
||
{
|
||
case CFG_GRAPH_BUID_2x:
|
||
|
||
read_func = ctl->read_bytes;
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_7F:
|
||
case CFG_GRAPH_BUID_40:
|
||
|
||
read_func = ctl->read_words;
|
||
|
||
break;
|
||
|
||
default:
|
||
;
|
||
}
|
||
|
||
/*------------------------------------------------------------
|
||
| read the RSCAN_VIDEO_HEAD into the memory copy
|
||
|-------------------------------------------------------------*/
|
||
|
||
rc = ( * read_func )( ctl,
|
||
(uchar *) bus_head,
|
||
(uchar *) &mem_head,
|
||
( RSCAN_VIDEO_HEAD_SIZE ) );
|
||
|
||
DEBUG_1("Validate_RSCAN_VIDEO_HEAD: read R2 header rc =%d\n",rc);
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*------------------------------------------------------------
|
||
| query the head, to get the total size of the structure
|
||
|-------------------------------------------------------------*/
|
||
|
||
rom_Blength = RSCAN_VIDEO_HEAD_rom_Blength( &mem_head );
|
||
|
||
rom_size = CFG_GRAPH_FRS_BLK_SIZE * rom_Blength;
|
||
|
||
DEBUG_2("Validate_RSCAN_VIDEO_HEAD: len (512) =%d, len =%d\n",rom_Blength, rom_size);
|
||
|
||
/*----------------------------------------------------------
|
||
| set up a buffer to read in the total VIDEO rom structures
|
||
| from bus memory
|
||
|-----------------------------------------------------------*/
|
||
|
||
buffer = (char *) malloc( rom_size );
|
||
|
||
if ( buffer == NULL ) { return (E_MALLOC); }
|
||
|
||
/*------------------------------------------------------------
|
||
| read the total VIDEO rom into the memory buffer
|
||
|-------------------------------------------------------------*/
|
||
|
||
rc = ( * read_func )( ctl,
|
||
(uchar *) bus_head,
|
||
(uchar *) buffer,
|
||
( rom_size ) );
|
||
|
||
DEBUG_1("Validate_RSCAN_VIDEO_HEAD: read total Video ROM rc =%d\n",rc);
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*-------------------------------------------------------------
|
||
| perform the CRC test on the VIDEO rom contents
|
||
|--------------------------------------------------------------*/
|
||
|
||
rc = FRS_crc16( ctl,
|
||
(RSCAN_VIDEO_HEAD *) buffer );
|
||
|
||
DEBUG_1("Validate_RSCAN_VIDEO_HEAD: rc =%d from FRS_crc16\n",rc);
|
||
|
||
if ( rc != 0 ) { return (rc); }
|
||
|
||
/*--------------------------------------------------------------
|
||
| the ROM is valid
|
||
|--------------------------------------------------------------*/
|
||
|
||
ctl->mem_rscan_r2_head = (void *) buffer;
|
||
|
||
*valid = TRUE;
|
||
|
||
return (0);
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Test_Addr_For_RSCAN_PS2( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_PS2 structure sits at a particular address.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initialize local variables.
|
||
Read in a RSCAN_PS2 header from the bus test address.
|
||
If error on first read, assume that the address is invalid.
|
||
Validate the RSCAN_PS2 header id and flag fields.
|
||
Validate the RSCAN_PS2 checksum.
|
||
Validate the RSCAN_PS2 contents.
|
||
Malloc storage for the contents and save them in the ctl structure.
|
||
Return.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
test_addr - holds the candidate address
|
||
|
||
valid - holds a boolean stating whether the address is
|
||
a valid RSCAN_PS2 block
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
mallocs block to hold the contents and places it in ctl->p_rscan_head
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Test_Addr_for_RSCAN_PS2(
|
||
|
||
FRS_access_t * ctl,
|
||
ulong test_addr,
|
||
ulong * valid,
|
||
ulong buid_type
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
RSCAN_PS2 head;
|
||
ulong bus_addr;
|
||
int ( * read_func ) ();
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
bus_addr = test_addr;
|
||
|
||
*valid = FALSE;
|
||
|
||
ctl->mem_rscan_ps2 = NULL;
|
||
ctl->bus_rscan_ps2 = NULL;
|
||
|
||
/*--------------------------------------
|
||
| read the header from bus memory into our
|
||
| local copy (head)
|
||
|--------------------------------------*/
|
||
|
||
switch (buid_type)
|
||
{
|
||
case CFG_GRAPH_BUID_2x:
|
||
|
||
read_func= ctl->read_bytes ;
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_7F:
|
||
case CFG_GRAPH_BUID_40:
|
||
|
||
read_func= ctl->read_words ;
|
||
|
||
break;
|
||
|
||
}
|
||
|
||
rc = (* read_func )( ctl, (uchar *) bus_addr,
|
||
(uchar *) &head, ( RSCAN_PS2_SIZE ) );
|
||
if ( rc != 0 )
|
||
{
|
||
/*----------------------------------
|
||
| we got an error on the first access
|
||
| to the adapter. It was already re-tried
|
||
| by the machine device driver.
|
||
|
|
||
| We assume that there is no Feature ROM,
|
||
| and that the error was an expected DSI.
|
||
|
|
||
| Given this assumption, we conclude that
|
||
| the address is not valid, and we return
|
||
| with a good RC but a valid=FALSE
|
||
|
|
||
|-------------------------------------*/
|
||
|
||
return (0);
|
||
}
|
||
|
||
/*-----------------------------------
|
||
| use a while construct to permit a long
|
||
| series of "if this" and "if that" and
|
||
| break out if one of the required tests fails
|
||
| If we break from loop, rc will hold correct value
|
||
| and *valid will be FALSE
|
||
|------------------------------------*/
|
||
|
||
rc = 0; /* preset the rc */
|
||
|
||
while ( *valid == FALSE )
|
||
{
|
||
/*-------------------------------------------
|
||
| test the individual locations in the header
|
||
|-------------------------------------------*/
|
||
|
||
if ( ( RSCAN_PS2_id_hex55( &head ) != 0x55 )
|
||
|
||
|| ( RSCAN_PS2_id_hexAA( &head ) != 0xAA )
|
||
|
||
|| ( RSCAN_PS2_flag( &head ) != RSCAN_DYNAMIC_ROM_FLAG_VAL )
|
||
)
|
||
{ break; }
|
||
|
||
/*------------------------------------------
|
||
| the structure has the correct flags, so
|
||
| check its contents
|
||
|
|
||
| test the checksum of the header
|
||
|------------------------------------------*/
|
||
|
||
rc = FRS_checksum( ctl, bus_addr, &head , read_func);
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
rc = E_VPD;
|
||
break;
|
||
}
|
||
|
||
/*-----------------------------------------
|
||
| test for non-NULL pointers
|
||
|-----------------------------------------*/
|
||
|
||
if ( ( RSCAN_PS2_dynamic_rom_length( &head ) == 0 )
|
||
|
||
|| ( RSCAN_PS2_dynamic_rom_head( &head ) == 0 )
|
||
)
|
||
{
|
||
rc = E_VPD;
|
||
break;
|
||
}
|
||
|
||
/*-------------------------------------------
|
||
| the header is valid
|
||
| allocate permanent storage for the copy
|
||
| and copy it from the local storage
|
||
| into the ctl structure. Update the ctl pointers.
|
||
| mark the result as valid. return.
|
||
|-------------------------------------------*/
|
||
|
||
ctl->mem_rscan_ps2 = (void *) malloc( RSCAN_PS2_SIZE );
|
||
|
||
if ( ctl->mem_rscan_ps2 == NULL ) { return (E_MALLOC); }
|
||
|
||
memcpy( (char *) ctl->mem_rscan_ps2 , (char *) &head , RSCAN_PS2_SIZE );
|
||
|
||
DEBUG_1("FRS_Test_Addr_for_RSCAN_PS2: found PS2 at %x\n",bus_addr);
|
||
|
||
ctl->bus_rscan_ps2 = bus_addr;
|
||
|
||
*valid = TRUE;
|
||
}
|
||
|
||
return (rc);
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Enable_BUID_2x_Device( )
|
||
|
||
TITLE: Function to enable a BUID 2X Device to read its
|
||
RSCAN_R2_HEAD structure
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
bus_romblk - bus address of the previously found RSCAN_6001_BLK
|
||
|
||
mem_romblk - mem address of copy of RSCAN_6001_BLK
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Enable_BUID_2x_Device(
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
RSCAN_6001_BLK * bus_romblk, /* bus address */
|
||
RSCAN_6001_BLK * mem_romblk /* already in memory */
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
int i;
|
||
int num_vals;
|
||
ulong iocc_addr;
|
||
ulong pos_val;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
/*---------------------------------------
|
||
| loop through the set of POS values,
|
||
| writing them one at a time to the adapter
|
||
|---------------------------------------*/
|
||
|
||
num_vals = RSCAN_6001_BLK_num_pos_vals( mem_romblk );
|
||
|
||
if ( num_vals == 0 ) { return (0); } /* nothing to do */
|
||
|
||
for ( i=0; i < num_vals; i++ )
|
||
{
|
||
pos_val = RSCAN_6001_BLK_pos_val( mem_romblk, i );
|
||
|
||
iocc_addr = POSREG( RSCAN_6001_BLK_pos_reg( mem_romblk, i ),
|
||
ctl->bus_slot ) | CDD_IOCC_BASE ;
|
||
|
||
rc = ( * ctl->iocc_write_byte )( ctl,
|
||
iocc_addr,
|
||
pos_val );
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
}
|
||
|
||
/*--------------------------------------
|
||
| all done
|
||
|--------------------------------------*/
|
||
|
||
return (0);
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Enable_BUID_40_Device( )
|
||
|
||
TITLE: Function to enable a BUID 40 Device to read its
|
||
RSCAN_R2_HEAD structure
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Returns 0. There is no setup for BUID 40
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
bus_romblk - holds address in bus space of RSCAN_6002_BLK
|
||
|
||
mem_romblk - holds address of mem copy of RSCAN_6002_BLK
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Enable_BUID_40_Device(
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
RSCAN_6002_BLK * bus_romblk, /* address on the bus */
|
||
RSCAN_6001_BLK * mem_romblk /* already in memory */
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
int num_vals;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
/*---------------------------------------
|
||
| loop through the set of cfg_register values,
|
||
| writing them one at a time to the adapter
|
||
|---------------------------------------*/
|
||
|
||
num_vals = RSCAN_6001_BLK_num_pos_vals( mem_romblk );
|
||
|
||
if ( num_vals == 0 ) { return (0); } /* nothing to do */
|
||
else { return (0); } /* BUID 40 needs no setup */
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Search_for_RSCAN_6001_BLK( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_6001_BLK structure sits at a particular address.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initialize pointers with addresses of RSCAN_PS2 head.
|
||
Validate the rom block header.
|
||
Loop through linked list of rom blocks:
|
||
Compute the correct bus address of the block.
|
||
Read the block into memory.
|
||
Validate the block class and id string.
|
||
If valid,
|
||
Validate the block VIDEO rom address.
|
||
Enable the adapter to read VIDEO rom.
|
||
Save the memory copy in the ctl structure.
|
||
Exit
|
||
Else continue
|
||
Exit with proper state.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
valid - a boolean stating whether the address is
|
||
a valid RSCAN_PS2 block
|
||
|
||
RETURNS:
|
||
returns an integer return code stating whether an error occurred or not.
|
||
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Search_for_RSCAN_6001_BLK(
|
||
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
ulong * valid /* boolean return var */
|
||
)
|
||
{
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
RSCAN_PS2 * head;
|
||
RSCAN_PS2 * bus_head;
|
||
int romblk_offset;
|
||
int romblk_next_offset;
|
||
int romblk_max_offset;
|
||
RSCAN_6001_BLK * bus_romblk;
|
||
RSCAN_6001_BLK mem_romblk;
|
||
ushort blk_class;
|
||
ulong this_block_not_ours;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
head = (RSCAN_PS2 *) ctl->mem_rscan_ps2;
|
||
bus_head = (RSCAN_PS2 *) ctl->bus_rscan_ps2;
|
||
|
||
ctl->mem_rscan_blk = NULL;
|
||
ctl->bus_rscan_blk = NULL;
|
||
|
||
/*---------------------------------------
|
||
| Get the first address of the linked list of
|
||
| ROMSCAN_ROMBLK structures
|
||
| Make sure it is valid.
|
||
|---------------------------------------*/
|
||
|
||
romblk_offset = (int) RSCAN_PS2_dynamic_rom_head( head );
|
||
romblk_next_offset = 0;
|
||
|
||
if ( romblk_offset == 0 ) { return (E_VPD); }
|
||
|
||
romblk_max_offset = romblk_offset + (int) RSCAN_PS2_dynamic_rom_length( head );
|
||
|
||
/*---------------------------------------------------------
|
||
| walk the list of ROMBLKS
|
||
|
|
||
| the exit condition is based upon the FRS block links
|
||
|----------------------------------------------------------*/
|
||
|
||
for ( /* no initial conditions */ ;
|
||
|
||
/* exit conditions */
|
||
( (romblk_offset < romblk_max_offset )
|
||
&& (romblk_offset != 0 ) );
|
||
|
||
/* iteration terms */
|
||
romblk_offset = romblk_next_offset
|
||
)
|
||
{
|
||
this_block_not_ours = FALSE; /* preset */
|
||
|
||
/*---------------------------------------
|
||
| compute the bus address of the block
|
||
| - offsets are always relative to start
|
||
| of the RSCAN_PS2 head
|
||
|----------------------------------------*/
|
||
|
||
bus_romblk = (RSCAN_6001_BLK *)
|
||
( ((char *) bus_head ) + romblk_offset );
|
||
|
||
/*---------------------------------------
|
||
| read in the next block from bus memory
|
||
|----------------------------------------*/
|
||
|
||
/* rc = ( * ctl->read_words )( ctl, */
|
||
rc = ( * ctl->read_bytes )( ctl,
|
||
(uchar *) bus_romblk,
|
||
(uchar *) &mem_romblk,
|
||
( RSCAN_6001_BLK_SIZE ) );
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*--------------------------------------
|
||
| test the copy in memory for validity
|
||
|
|
||
| start with the class value and ID string
|
||
|---------------------------------------*/
|
||
|
||
if ( ( RSCAN_6001_BLK_class( &mem_romblk ) != RSCAN_DYNAMIC_ROM_BLOCK_ID_VAL )
|
||
|| ( strncmp( RSCAN_6001_BLK_id( &mem_romblk ),
|
||
RSCAN_R2_STRING_ID_2,
|
||
8 ))
|
||
)
|
||
{ this_block_not_ours = TRUE; } /* not one of ours */
|
||
|
||
/*----------------------------------------------
|
||
| this block is valid if it has met the above tests.
|
||
| check to see. If not, then set up pointer to the
|
||
| next block and continue on
|
||
|-----------------------------------------------*/
|
||
|
||
if ( this_block_not_ours )
|
||
{
|
||
romblk_next_offset = RSCAN_6001_BLK_next( &mem_romblk );
|
||
continue;
|
||
}
|
||
|
||
/*--------------------------------------
|
||
| class and string match
|
||
|
|
||
| check whether a valid pointer to S/6000 ROM
|
||
|--------------------------------------*/
|
||
|
||
if ( ( RSCAN_6001_BLK_rom_addr( &mem_romblk ) < CFG_GRAPH_BUID_2x_ROM_LO_ADDR )
|
||
|| ( RSCAN_6001_BLK_rom_addr( &mem_romblk ) > CFG_GRAPH_BUID_2x_ROM_HI_ADDR )
|
||
)
|
||
{ return (E_VPD); } /* invalid pointer to ROM */
|
||
|
||
/*-------------------------------------
|
||
| this block is valid and has good pointers
|
||
|
|
||
| prepare to read the RSCAN_R2_HEAD structure
|
||
| to do this, we need to process this blk for
|
||
| instructions on how to
|
||
| enable the hardware for reading the
|
||
| S/6000 ROM by processing the cfg reg list
|
||
|---------------------------------------*/
|
||
|
||
rc = FRS_Enable_BUID_2x_Device( ctl,
|
||
bus_romblk,
|
||
&mem_romblk );
|
||
|
||
if ( rc != 0 ) { return (rc); } /* failed to enable */
|
||
|
||
/*-----------------------------------
|
||
| if we reach here, we have found a valid
|
||
| block. Malloc storage for this block.
|
||
| Copy the mem_romblk into the malloc area.
|
||
| Update the ctl pointer.
|
||
| Make sure to set the bus address of the R2_HEAD
|
||
| into the ctl structure, for use later by others
|
||
|------------------------------------*/
|
||
|
||
ctl->mem_rscan_blk = (void *) malloc( RSCAN_6001_BLK_SIZE );
|
||
|
||
if ( ctl->mem_rscan_blk == NULL ) { return (E_MALLOC); }
|
||
|
||
memcpy( (char *) ctl->mem_rscan_blk, (char *) &mem_romblk, RSCAN_6001_BLK_SIZE );
|
||
|
||
ctl->bus_rscan_blk = (void *) bus_romblk;
|
||
|
||
ctl->bus_rscan_r2_head = (void *) RSCAN_6001_BLK_rom_addr( &mem_romblk );
|
||
|
||
*valid = TRUE;
|
||
|
||
return (0);
|
||
|
||
} /* end of for loop */
|
||
|
||
/*-----------------------------------------------
|
||
| fall through to here means we did not find
|
||
| a valid block
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
return (0);
|
||
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Search_for_RSCAN_6002_BLK( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_6002_BLK structure sits at a particular address.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initialize pointers with addresses of RSCAN_PS2 head.
|
||
Validate the rom block header.
|
||
Loop through linked list of rom blocks:
|
||
Compute the correct bus address of the block.
|
||
Read the block into memory.
|
||
Validate the block class and id string.
|
||
If valid,
|
||
Validate the block VIDEO rom address.
|
||
Enable the adapter to read VIDEO rom.
|
||
Save the memory copy in the ctl structure.
|
||
Exit
|
||
Else continue
|
||
Exit with proper state.
|
||
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used to access the segment)
|
||
|
||
valid - a boolean stating whether the address is
|
||
a valid RSCAN_PS2 block
|
||
|
||
RETURNS:
|
||
returns an integer return code stating whether an error occurred or not.
|
||
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Search_for_RSCAN_6002_BLK(
|
||
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
ulong * valid /* boolean return var */
|
||
)
|
||
{
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
RSCAN_PS2 * head;
|
||
RSCAN_PS2 * bus_head;
|
||
int romblk_offset;
|
||
int romblk_next_offset;
|
||
int romblk_max_offset;
|
||
RSCAN_6002_BLK * bus_romblk;
|
||
RSCAN_6002_BLK mem_romblk;
|
||
ushort blk_class;
|
||
ulong this_block_not_ours;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
head = (RSCAN_PS2 *) ctl->mem_rscan_ps2;
|
||
bus_head = (RSCAN_PS2 *) ctl->bus_rscan_ps2;
|
||
|
||
ctl->mem_rscan_blk = NULL;
|
||
ctl->bus_rscan_blk = NULL;
|
||
|
||
/*---------------------------------------
|
||
| Get the first address of the linked list of
|
||
| ROMSCAN_ROMBLK structures
|
||
| Make sure it is valid.
|
||
| Then compute the max offset value
|
||
|---------------------------------------*/
|
||
|
||
romblk_offset = (int) RSCAN_PS2_dynamic_rom_head( head );
|
||
romblk_next_offset = 0;
|
||
|
||
if ( romblk_offset == 0 ) { return (E_VPD); }
|
||
|
||
romblk_max_offset = romblk_offset + (int) RSCAN_PS2_dynamic_rom_length( head );
|
||
|
||
/*---------------------------------------------------------
|
||
| walk the list of ROMBLKS
|
||
|
|
||
| the exit condition is based upon the FRS block links
|
||
|----------------------------------------------------------*/
|
||
|
||
for ( /* no initial conditions */ ;
|
||
|
||
/* exit conditions */
|
||
( (romblk_offset < romblk_max_offset )
|
||
&& (romblk_offset != 0 ) );
|
||
|
||
/* iteration terms */
|
||
romblk_offset = romblk_next_offset
|
||
)
|
||
{
|
||
this_block_not_ours = FALSE; /* preset */
|
||
|
||
/*---------------------------------------
|
||
| compute the bus address of the block
|
||
| - offsets are always relative to start
|
||
| of the RSCAN_PS2 head
|
||
|----------------------------------------*/
|
||
|
||
bus_romblk = (RSCAN_6002_BLK *)
|
||
( ((char *) bus_head ) + romblk_offset );
|
||
|
||
/*---------------------------------------
|
||
| read in the next block from bus memory
|
||
|----------------------------------------*/
|
||
|
||
rc = ( * ctl->read_words )( ctl,
|
||
(uchar *) bus_romblk,
|
||
(uchar *) &mem_romblk,
|
||
( RSCAN_6002_BLK_SIZE ) );
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*--------------------------------------
|
||
| test the copy in memory for validity
|
||
|
|
||
| start with the class value and ID string
|
||
|---------------------------------------*/
|
||
|
||
if ( ( RSCAN_6002_BLK_class( &mem_romblk ) != RSCAN_DYNAMIC_ROM_BLOCK_ID_VAL )
|
||
|| ( strncmp( RSCAN_6002_BLK_id( &mem_romblk ),
|
||
RSCAN_R2_STRING_ID_3,
|
||
8 ))
|
||
)
|
||
{ this_block_not_ours = TRUE; } /* not one of ours */
|
||
|
||
/*----------------------------------------------
|
||
| this block is valid if it has met the above tests.
|
||
| check to see. If not, then set up pointer to the
|
||
| next block and continue on
|
||
|-----------------------------------------------*/
|
||
|
||
if ( this_block_not_ours )
|
||
{
|
||
romblk_next_offset = RSCAN_6002_BLK_next( &mem_romblk );
|
||
continue;
|
||
}
|
||
|
||
/*--------------------------------------
|
||
| class and string match
|
||
|
|
||
| check whether a valid pointer to S/6000 ROM
|
||
|--------------------------------------*/
|
||
|
||
if ( ( RSCAN_6002_BLK_rom_addr( &mem_romblk ) < CFG_GRAPH_BUID_40_ROM_LO_ADDR )
|
||
|| ( RSCAN_6002_BLK_rom_addr( &mem_romblk ) > CFG_GRAPH_BUID_40_ROM_HI_ADDR )
|
||
)
|
||
{ return (E_VPD); } /* invalid pointer to ROM */
|
||
|
||
/*-------------------------------------
|
||
| this block is valid and has good pointers
|
||
|
|
||
| prepare to read the RSCAN_R2_HEAD structure
|
||
| to do this, we need to process this blk for
|
||
| instructions on how to
|
||
| enable the hardware for reading the
|
||
| S/6000 ROM by processing the cfg reg list
|
||
|---------------------------------------*/
|
||
|
||
rc = FRS_Enable_BUID_40_Device( ctl,
|
||
bus_romblk,
|
||
&mem_romblk );
|
||
|
||
if ( rc != 0 ) { return (rc); } /* failed to enable */
|
||
|
||
/*-----------------------------------
|
||
| if we reach here, we have found a valid
|
||
| block. Malloc storage for this block.
|
||
| Copy the mem_romblk into the malloc area.
|
||
| Update the ctl pointer.
|
||
| Make sure to set the bus address of the R2_HEAD
|
||
| into the ctl structure, for use later by others
|
||
|------------------------------------*/
|
||
|
||
ctl->mem_rscan_blk = (void *) malloc( RSCAN_6002_BLK_SIZE );
|
||
|
||
if ( ctl->mem_rscan_blk == NULL ) { return (E_MALLOC); }
|
||
|
||
memcpy( (char *) ctl->mem_rscan_blk, (char *) &mem_romblk, RSCAN_6002_BLK_SIZE );
|
||
|
||
ctl->bus_rscan_blk = (void *) bus_romblk;
|
||
|
||
ctl->bus_rscan_r2_head = (void *) RSCAN_6002_BLK_rom_addr( &mem_romblk );
|
||
|
||
*valid = TRUE;
|
||
|
||
return (0);
|
||
|
||
} /* end of for loop */
|
||
|
||
/*-----------------------------------------------
|
||
| fall through to here means we did not find
|
||
| a valid block
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
return (0);
|
||
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Search_for_RSCAN_6003_BLK( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan
|
||
RSCAN_6003_BLK structure sits at a particular address.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Initialize pointers with addresses of RSCAN_PS2 head.
|
||
Validate the rom block header.
|
||
Loop through linked list of rom blocks:
|
||
Compute the correct bus address of the block.
|
||
Read the block into memory.
|
||
Validate the block class and id string.
|
||
If valid,
|
||
Validate the block VIDEO rom address.
|
||
Save the memory copy in the ctl structure.
|
||
Exit
|
||
Else continue
|
||
Exit with proper state.
|
||
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
ctl - holds a structure of type FRS_access_t for use
|
||
in accessing the data via the correct bus
|
||
(ctl->bus_segreg is used by nvram_read_words/bytes to tell if 601)
|
||
(ctl->bus_slot is passed to mdd to do the read for us)
|
||
|
||
valid - a boolean stating whether the address is
|
||
a valid RSCAN_PS2 block
|
||
|
||
RETURNS:
|
||
returns an integer return code stating whether an error occurred or not.
|
||
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
STATIC int
|
||
FRS_Search_for_RSCAN_6003_BLK( /* 601_CHANGE : new func */
|
||
|
||
FRS_access_t * ctl, /* standard ctl structure */
|
||
ulong * valid /* boolean return var */
|
||
)
|
||
{
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
RSCAN_PS2 * head;
|
||
RSCAN_PS2 * bus_head;
|
||
int romblk_offset;
|
||
int romblk_next_offset;
|
||
int romblk_max_offset;
|
||
RSCAN_6003_BLK * bus_romblk;
|
||
RSCAN_6003_BLK mem_romblk;
|
||
|
||
ushort blk_class, word_incr;
|
||
|
||
ulong this_block_not_ours,
|
||
dev_characteristic;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
|
||
/* ---------------------------------------------------------------
|
||
| 1, read the device characteristic register
|
||
|
|
||
| 2, from it examine the word increment value. If it is 4 then
|
||
| it is a one-to-one mapping; if it is 8, then every 4 bytes
|
||
| of ROM are mapped to every 8 bytes of system address space.
|
||
| We don't have to deal with this; the machine dd does all the
|
||
| reading for us; however, we need to know this to handle
|
||
| set the limit of where to stop looking for the 6003 block.
|
||
|
|
||
---------------------------------------------------------------*/
|
||
|
||
/*
|
||
* here we can read a word because this register is not in ROM
|
||
*/
|
||
rc = rd_60x_std_cfg_reg_w( ctl->bus_slot, BUS_60X_DEV_CHAR_REG,
|
||
& dev_characteristic);
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
DEBUG_2("Search_6003_BLK: can't read dev char, slot=%x, reg=%x\n",
|
||
ctl->bus_slot, BUS_60X_DEV_CHAR_REG);
|
||
return (rc);
|
||
}
|
||
|
||
if ( ((dev_characteristic & RSCAN_60X_DEVCHAR_TYPE_MASK) == RSCAN_60X_DEVCHAR_TYPE_NOT_PRESENT) ||
|
||
((dev_characteristic & RSCAN_60X_DEVCHAR_TYPE_MASK) != RSCAN_60X_DEVCHAR_TYPE_IO )
|
||
)
|
||
{
|
||
DEBUG_0("Search_6003_BLK: *** NO DEVICE PRESENT ****\n");
|
||
return (-1);
|
||
}
|
||
|
||
/*
|
||
* compute word stride factor
|
||
*/
|
||
if ( RSCAN_60X_BOOL_INCREMENT_1(dev_characteristic) )
|
||
{
|
||
DEBUG_0("Search_6003_BLK: word increment value is 4 bytes\n");
|
||
word_incr = 1;
|
||
}
|
||
else if ( RSCAN_60X_BOOL_INCREMENT_2(dev_characteristic) )
|
||
{
|
||
DEBUG_0("Search_6003_BLK: word increment value is 8 bytes\n");
|
||
word_incr = 2;
|
||
}
|
||
else
|
||
{
|
||
DEBUG_0("Search_6003_BLK: unknown word increment value !\n");
|
||
}
|
||
|
||
/*
|
||
address of where PS2 ROM Header is in the form of 0xFFA0 0000 + some offset
|
||
note offset < 0x1FFFFF
|
||
*/
|
||
bus_head = (RSCAN_PS2 *) ctl->bus_rscan_ps2;
|
||
|
||
DEBUG_1("Search_6003_BLK: ctl->bus_rscan_ps2 =%x\n", bus_head);
|
||
|
||
*valid = FALSE;
|
||
|
||
head = (RSCAN_PS2 *) ctl->mem_rscan_ps2; /* buffer with PS/2 Header */
|
||
|
||
ctl->mem_rscan_blk = NULL;
|
||
ctl->bus_rscan_blk = NULL;
|
||
|
||
/*---------------------------------------
|
||
| Get the first address of the linked list of
|
||
| ROMSCAN_ROMBLK structures
|
||
| Make sure it is valid.
|
||
| Then compute the max offset value
|
||
|
|
||
| *** ASSUME rom block offseet is accounted for
|
||
| differnt work incr
|
||
| ***
|
||
|
|
||
|---------------------------------------*/
|
||
|
||
/*
|
||
Offset to to the beginning of ROM blocks in linked list from
|
||
the PS2 ROM Header
|
||
*/
|
||
romblk_offset = (int) RSCAN_PS2_dynamic_rom_head( head );
|
||
|
||
DEBUG_1("Search_6003_BLK: PS2 offset = %x\n",bus_head);
|
||
|
||
DEBUG_0("Search_6003_BLK: linked list offset must be equal to size of ps2\n");
|
||
DEBUG_1("Search_6003_BLK: linked list offset =%x\n", romblk_offset);
|
||
DEBUG_1("Search_6003_BLK: size of ps2 =%x\n", sizeof(RSCAN_PS2));
|
||
|
||
romblk_next_offset = 0;
|
||
|
||
if ( romblk_offset == 0 )
|
||
{
|
||
return (E_VPD);
|
||
}
|
||
|
||
if (word_incr == 1)
|
||
{
|
||
romblk_max_offset = romblk_offset +
|
||
(int)RSCAN_PS2_dynamic_rom_length(head);
|
||
}
|
||
else
|
||
{
|
||
/*---------------------------------
|
||
| every 4 bytes of data take up
|
||
| twice as much sytem address space
|
||
-------------------------------- */
|
||
romblk_max_offset = romblk_offset +
|
||
( ( (int)RSCAN_PS2_dynamic_rom_length(head) / 4 ) +1) * 8 ;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------
|
||
| walk the list of ROMBLKS
|
||
|
|
||
| the exit condition is based upon the FRS block links
|
||
|----------------------------------------------------------*/
|
||
|
||
for ( ; (romblk_offset < romblk_max_offset ) && (romblk_offset != 0 ) ;
|
||
romblk_offset = romblk_next_offset)
|
||
{
|
||
this_block_not_ours = FALSE; /* preset */
|
||
|
||
/*---------------------------------------
|
||
| compute the bus address of the block
|
||
| - offsets are always relative to start
|
||
| of the RSCAN_PS2 head
|
||
|----------------------------------------*/
|
||
|
||
bus_romblk = (RSCAN_6003_BLK *)
|
||
( ((char *) bus_head ) + romblk_offset );
|
||
|
||
if ( bus_romblk > BUS_60X_END_VPD_FEATURE_ROM)
|
||
{
|
||
/*
|
||
should never happen. will take out break point later
|
||
*/
|
||
DEBUG_0("Search_6003_BLK: **** invalid rom address **** \n");
|
||
|
||
return (E_DEVACCESS);
|
||
}
|
||
/*---------------------------------------
|
||
| read in the next block from bus memory
|
||
|----------------------------------------*/
|
||
|
||
DEBUG_1("Search_6003_BLK: for loop. ioctl rd addr =%x\n", bus_romblk);
|
||
|
||
rc = ( * ctl->read_bytes )( ctl,
|
||
(uchar *) bus_romblk,
|
||
(uchar *) &mem_romblk,
|
||
( RSCAN_6003_BLK_SIZE ) );
|
||
|
||
DEBUG_1("Search_6003_BLK: call read_bytes, rc =%x\n", rc);
|
||
|
||
DEBUG_2("Search_6003_BLK: 6003 id str =<%s>, blk id =%d\n",
|
||
RSCAN_6003_BLK_id( &mem_romblk ), RSCAN_6003_BLK_class(&mem_romblk));
|
||
|
||
if ( rc != 0 ) { return (E_DEVACCESS); }
|
||
|
||
/*--------------------------------------
|
||
| test the copy in memory for validity
|
||
|
|
||
| start with the class value and ID string
|
||
|---------------------------------------*/
|
||
|
||
if ( (RSCAN_6003_BLK_class(&mem_romblk) !=
|
||
RSCAN_DYNAMIC_ROM_BLOCK_ID_VAL)
|
||
|
||
|| ( strncmp( RSCAN_6003_BLK_id( &mem_romblk ),
|
||
RSCAN_R2_STRING_ID_4, 8 ) )
|
||
)
|
||
|
||
{
|
||
DEBUG_1("Search_6003_BLK: for loop. not found RISC6003 @a %x\n", bus_romblk);
|
||
this_block_not_ours = TRUE; /* not one of ours */
|
||
}
|
||
|
||
/*----------------------------------------------
|
||
| this block is valid if it has met the above tests.
|
||
| check to see. If not, then set up pointer to the
|
||
| next block and continue on
|
||
|-----------------------------------------------*/
|
||
|
||
if ( this_block_not_ours )
|
||
{
|
||
romblk_next_offset = RSCAN_6003_BLK_next( &mem_romblk );
|
||
continue;
|
||
}
|
||
|
||
/*--------------------------------------
|
||
| class and string match
|
||
|
|
||
| check whether a valid pointer to S/6000 ROM
|
||
|--------------------------------------*/
|
||
|
||
if (
|
||
(RSCAN_6003_BLK_rom_addr(&mem_romblk) < BUS_60X_START_VPD_FEATURE_ROM)
|
||
|| (RSCAN_6003_BLK_rom_addr(&mem_romblk) > BUS_60X_END_VPD_FEATURE_ROM)
|
||
|
||
)
|
||
{
|
||
/* invalid pointer to ROM */
|
||
return (E_VPD);
|
||
}
|
||
|
||
DEBUG_1("Search_6003_BLK: for loop. found RISC6003 @a %x\n", bus_romblk);
|
||
|
||
/*-----------------------------------
|
||
| if we reach here, we have found a valid
|
||
| block. Malloc storage for this block.
|
||
| Copy the mem_romblk into the malloc area.
|
||
| Update the ctl pointer.
|
||
| Make sure to set the bus address of the R2_HEAD
|
||
| into the ctl structure, for use later by others
|
||
|------------------------------------*/
|
||
|
||
ctl->mem_rscan_blk = (void *) malloc( RSCAN_6003_BLK_SIZE );
|
||
|
||
if ( ctl->mem_rscan_blk == NULL ) { return (E_MALLOC); }
|
||
|
||
memcpy( (char *) ctl->mem_rscan_blk, (char *) &mem_romblk,
|
||
RSCAN_6003_BLK_SIZE);
|
||
|
||
ctl->bus_rscan_blk = (void *) bus_romblk;
|
||
|
||
/*
|
||
* This is the absolute address of where the video rom is.
|
||
*/
|
||
|
||
ctl->bus_rscan_r2_head = (int)RSCAN_6003_BLK_rom_addr(&mem_romblk) ;
|
||
|
||
*valid = TRUE;
|
||
|
||
return (0);
|
||
|
||
} /* for loop */
|
||
|
||
/*-----------------------------------------------
|
||
| fall through to here means we did not find
|
||
| a valid block
|
||
|-----------------------------------------------*/
|
||
|
||
*valid = FALSE;
|
||
|
||
return (0);
|
||
|
||
}
|
||
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Find_Video_Device( )
|
||
|
||
TITLE: Function to detect whether a Feature ROM Scan Device exists
|
||
on a particular bus at a particular subaddress.
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
Writes NULL to the return data pointer.
|
||
Sets up pointers to function in the ctl structure.
|
||
Sets up state flags in the ctl structure.
|
||
|
||
Does the pre-processing phase:
|
||
|
||
If Microchannel,
|
||
Opens the machine device driver.
|
||
saves input subaddresses in ctl structure.
|
||
If buid40,
|
||
Opens the machine device driver.
|
||
initializes ctl structure.
|
||
|
||
If buid7F,
|
||
initializes ctl structure (bus segment and slot number fields)
|
||
|
||
Attempts to locate a RSCAN_PS2 header on the adapter.
|
||
|
||
If Microchannel,
|
||
loops through a range of possible address points, looking for
|
||
first valid occurrence.
|
||
|
||
If buid40,
|
||
checks a hard-coded address.
|
||
|
||
If buid7F,
|
||
|
||
read device characteristic at 0xFF20 0000. From this figure out
|
||
the word increment (also named delta or i)
|
||
|
||
VPD and FRS begin at 0xFFA0 0000 - so called the ROM BASE
|
||
|
||
read ROM characteristic at BASE + 1 * i, to get number of ROM objects -
|
||
(right now there are 2, VPD and Feature ROM (more in the future)
|
||
Each object are described by 3 words, its type, offset from BASE and its
|
||
length
|
||
|
||
Read the object array (length = number of object * 4 bytes) beginning at
|
||
BASE + 3 * i
|
||
|
||
Search this object array for block id (lower 16 bits of type field) equal 2 (FRS)
|
||
If found, use offset to look for PS2 ROM header.
|
||
|
||
Attempts to locate a RSCAN_600x_BLK on the adapter.
|
||
|
||
If Microchannel, looks for 6001.
|
||
|
||
If buid40, looks for 6002.
|
||
|
||
If buid7F, looks for 6003.
|
||
|
||
Attempts to locate a RSCAN_VIDEO_HEAD header on the adapter.
|
||
|
||
Same for all buses. If found, copies in the full
|
||
structure for later use by caller.
|
||
|
||
Writes back pointer to copy of VIDEO rom and returns.
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
buid_type - a flag stating the type of bus being searched
|
||
at present only Microchannel, BUID=40 and BUID=7F are
|
||
supported
|
||
|
||
p_video_head - address of pointer which will hold the location
|
||
of the RSCAN_R2_HEAD structure. The contents are assumed
|
||
to have been malloc-ed by this routine, and should
|
||
be freed by the calling routine
|
||
|
||
subaddr_1 - if buid_type == Microchannel or 7F (601 - Rain Bow Box)
|
||
then holds the bus memory segment reg contents
|
||
|
||
else ignored
|
||
|
||
subaddr_2 - if buid_type == Microchannel
|
||
then holds the iocc segment register contents
|
||
|
||
else ignored
|
||
|
||
subaddr_3 - if buid_type == Microchannel or 7F (601 - Rain Bow Box)
|
||
then holds the Microchannel/601 slot number
|
||
|
||
else ignored
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
E_NODETECT could not locate/validate some piece of FRS structures
|
||
E_OPEN could not open a file or device driver
|
||
E_MALLOC failed to malloc somewhere
|
||
E_BADATTR invalid input to some routine
|
||
E_DEVACCESS one of the machine device driver calls failed
|
||
E_VPD CRC, checksum, or contents of FRS structure was not good
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int
|
||
FRS_Find_Video_Device(
|
||
int buid_type,
|
||
void ** p_video_head,
|
||
ulong subaddr_1,
|
||
ulong subaddr_2,
|
||
ulong subaddr_3
|
||
)
|
||
{
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
FRS_access_t ctl;
|
||
int rc;
|
||
int scan_address;
|
||
void * block;
|
||
ulong valid;
|
||
|
||
RSCAN_ROMBLK * mem_romblk;
|
||
RSCAN_VIDEO_HEAD * mem_head;
|
||
|
||
|
||
ulong addr, /* 601_CHANGE */
|
||
dev_characteristic;
|
||
|
||
rscan_60x_romchar_t rom_char;
|
||
char * ptr;
|
||
rscan32_60x_obj_info_t * p_obj_info_buf;
|
||
|
||
unsigned int i, nbytes, len,
|
||
delta,
|
||
num_objects,
|
||
ps2_offset; /* offset from 0xFFA0 0000 to PS2 Header blk */
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
*p_video_head = (void *) NULL;
|
||
|
||
/*--------------------------------------
|
||
| set up pointers to function for machine
|
||
| device driver access
|
||
|---------------------------------------*/
|
||
|
||
ctl.open = nvram_open;
|
||
ctl.close = nvram_close;
|
||
ctl.read_byte = nvram_read_byte;
|
||
ctl.read_bytes = nvram_read_bytes;
|
||
ctl.read_word = nvram_read_word;
|
||
ctl.read_words = nvram_read_words;
|
||
ctl.write_byte = nvram_write_byte;
|
||
ctl.write_word = nvram_write_word;
|
||
ctl.iocc_read_byte = nvram_iocc_read_byte;
|
||
ctl.iocc_write_byte = nvram_iocc_write_byte;
|
||
|
||
/*---------------------------------------
|
||
| preset the FRS detection variables
|
||
|---------------------------------------*/
|
||
|
||
ctl.frs_adapter_present = -1;
|
||
ctl.frs_detected_error = -1;
|
||
ctl.frs_adapter_bad = -1;
|
||
|
||
|
||
/*--------------------------------------
|
||
| Pre-Processing Phase
|
||
|
|
||
| Set up Segment Registers
|
||
| Set up read/write functions
|
||
|
|
||
|--------------------------------------*/
|
||
|
||
switch (buid_type)
|
||
{
|
||
|
||
case CFG_GRAPH_BUID_2x:
|
||
|
||
/*--------------------------------------
|
||
| open /dev/nvram (machine device driver)
|
||
|--------------------------------------*/
|
||
|
||
rc = ( * ctl.open )( &ctl );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_OPEN);
|
||
}
|
||
|
||
ctl.bus_segreg = subaddr_1;
|
||
ctl.iocc_segreg = subaddr_2;
|
||
|
||
/*
|
||
* physical slot is passed in.
|
||
*
|
||
* To access iocc space (POS), need to use logical slot which is
|
||
* one less than that
|
||
*/
|
||
|
||
ctl.bus_slot = subaddr_3 - 1;
|
||
|
||
/*
|
||
In order to read the FRS ROM, the
|
||
card has to be enabled by setting
|
||
bit 0 of POS2 to 1
|
||
*/
|
||
rc = enable_device(&ctl);
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (rc);
|
||
}
|
||
|
||
break;
|
||
|
||
|
||
case CFG_GRAPH_BUID_40:
|
||
|
||
/*--------------------------------------
|
||
| open /dev/nvram (machine device driver)
|
||
|--------------------------------------*/
|
||
|
||
rc = ( * ctl.open )( &ctl );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
return (E_OPEN);
|
||
}
|
||
|
||
ctl.bus_segreg = CFG_GRAPH_BUID_40_SEG;
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_7F: /* 601_CHANGE */
|
||
|
||
/*
|
||
* Don't need to open /dev/nvram because the read/write
|
||
* functions for 60x does its own open (see 60x_tools.c)
|
||
*/
|
||
|
||
ctl.bus_segreg = subaddr_1; /* used by nvram_read_words/bytes to tell 601 h/w */
|
||
|
||
ctl.bus_slot = subaddr_3; /* need to pass it to machine driver */
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
return (E_BADATTR);
|
||
|
||
} /* end of switch */
|
||
|
||
/*-------------------------------------------------------------------
|
||
| Locate a Valid RSCAN_PS2 header
|
||
|
|
||
| The output of each case should either return
|
||
| if no head was found, or it should set valid=TRUE
|
||
|
|
||
| if valid, then the ctl structure holds:
|
||
| ctl.bus_rscan_ps2 - bus address of structure
|
||
| ctl.mem_rscan_ps2 - mem address of copy of structure
|
||
|
|
||
|--------------------------------------------------------------------*/
|
||
|
||
valid = FALSE;
|
||
|
||
switch (buid_type)
|
||
{
|
||
|
||
case CFG_GRAPH_BUID_2x:
|
||
|
||
/*-------------------------------------------
|
||
| Microchannel adapters can place the ROM within
|
||
| ranges of addresses, aligned on 2K boundaries.
|
||
| We need to search the all possible ranges to find a
|
||
| header
|
||
|---------------------------------------------*/
|
||
|
||
for ( scan_address = CFG_GRAPH_BUID_2x_PS2_HEADER_START_ADDR1;
|
||
scan_address < CFG_GRAPH_BUID_2x_PS2_HEADER_STOP_ADDR1;
|
||
scan_address += CFG_GRAPH_BUID_2x_ADDR_INCR )
|
||
{
|
||
rc = FRS_Test_Addr_for_RSCAN_PS2( &ctl,
|
||
scan_address,
|
||
&valid, buid_type);
|
||
if ( valid || (rc != 0) ) { break; }
|
||
}
|
||
|
||
/*
|
||
* if we have not found the PS2 header, scan the 2nd range
|
||
*/
|
||
if ( !valid )
|
||
{
|
||
|
||
for ( scan_address = CFG_GRAPH_BUID_2x_PS2_HEADER_START_ADDR2;
|
||
scan_address < CFG_GRAPH_BUID_2x_PS2_HEADER_STOP_ADDR2;
|
||
scan_address += CFG_GRAPH_BUID_2x_ADDR_INCR )
|
||
{
|
||
rc = FRS_Test_Addr_for_RSCAN_PS2( &ctl,
|
||
scan_address,
|
||
&valid, buid_type);
|
||
if ( valid || (rc != 0) ) { break; }
|
||
}
|
||
}
|
||
|
||
if ( (! valid) || rc)
|
||
{
|
||
|
||
/*
|
||
disable the card by
|
||
setting bit 0 of POS2 to 0
|
||
*/
|
||
disable_device(&ctl);
|
||
|
||
if (!valid)
|
||
{
|
||
rc = E_NODETECT;
|
||
}
|
||
return (rc);
|
||
}
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_40:
|
||
|
||
scan_address = CFG_GRAPH_BUID_40_START_ADDR;
|
||
|
||
rc = FRS_Test_Addr_for_RSCAN_PS2( &ctl,
|
||
scan_address,
|
||
&valid, buid_type);
|
||
|
||
if ( rc != 0 ) { return (rc); }
|
||
if ( ! valid ) { return (E_NODETECT); }
|
||
|
||
break;
|
||
|
||
|
||
case CFG_GRAPH_BUID_7F: /* 601_CHANGE */
|
||
|
||
/* ---------------------------------------------------------------
|
||
| 1, read the device characteristic register
|
||
|
|
||
| - which tells us how to address each byte of the ROM and whether
|
||
| the ROM can be read in words or bytes. Byte access is permitted
|
||
| in both cases. To keep it simple (i.e., not handle word access
|
||
| when H/W is capable of), mdd always choose byte access.
|
||
|
|
||
| 2, read VPD/Feature ROM characteristic register
|
||
|
|
||
| - which tells us how many objects the ROM contains.
|
||
|
|
||
| 3, read the offset, length and type fields (3 words) for each object
|
||
|
|
||
| - search the object array for the feature rom object, If found
|
||
| use the offset to find the PS2 ROM header.
|
||
|
|
||
-----------------------------------------------------------------*/
|
||
|
||
/* here we can read a word because this register is not in ROM */
|
||
rc = rd_60x_std_cfg_reg_w( ctl.bus_slot, BUS_60X_DEV_CHAR_REG,
|
||
& dev_characteristic);
|
||
|
||
DEBUG_1("cfg_graphics_frs_tools.c:Find_Video_Device: dev char =%x\n", dev_characteristic);
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: can't read dev char\n");
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
if ( ((dev_characteristic & RSCAN_60X_DEVCHAR_TYPE_MASK) == RSCAN_60X_DEVCHAR_TYPE_NOT_PRESENT) ||
|
||
((dev_characteristic & RSCAN_60X_DEVCHAR_TYPE_MASK) != RSCAN_60X_DEVCHAR_TYPE_IO )
|
||
)
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: Device not present or none IO type\n");
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
/* compute word stride factor */
|
||
if ( RSCAN_60X_BOOL_INCREMENT_1(dev_characteristic) )
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: word increment value is 4 bytes\n");
|
||
delta = 4;
|
||
}
|
||
else if ( RSCAN_60X_BOOL_INCREMENT_2(dev_characteristic) )
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: word increment value is 8 bytes\n");
|
||
delta = 8;
|
||
}
|
||
else
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: unknown word increment value !\n");
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
|
||
/*
|
||
ROM Characteristic Register is at 0xFFA0 0000 + 1 * delta
|
||
*/
|
||
addr = BUS_60X_START_VPD_FEATURE_ROM + delta;
|
||
|
||
rc = rd_60x_vpd_feat_rom (ctl.bus_slot, addr, &rom_char, sizeof(rom_char));
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: can't read ROM char\n");
|
||
return (E_DEVACCESS);
|
||
}
|
||
|
||
/*
|
||
extract the number of objects contain in ROM from the ROM
|
||
characteristic register.
|
||
*/
|
||
num_objects = rom_char.sub.num_items;
|
||
|
||
DEBUG_1("cfg_graphics_frs_tools.c:Find_Video_Device: number of objects =%d\n", num_objects);
|
||
|
||
if (num_objects == 0) /* ROM contains only VPD data */
|
||
{
|
||
return (E_NODETECT);
|
||
}
|
||
|
||
/* allocate space for the ROM objects array */
|
||
|
||
nbytes = sizeof(rscan32_60x_obj_info_t) * num_objects;
|
||
ptr = (char *) malloc(nbytes);
|
||
|
||
/*
|
||
Here read the Feature/VPD information array which begins at
|
||
0xFFA0 0000 + 3 * delta
|
||
*/
|
||
|
||
addr = BUS_60X_START_VPD_FEATURE_ROM + 3 * delta;
|
||
|
||
rc = rd_60x_vpd_feat_rom (ctl.bus_slot, addr, ptr, nbytes);
|
||
|
||
p_obj_info_buf = (rscan32_60x_obj_info_t *) ptr;
|
||
|
||
ps2_offset = 0; /* offset from 0xFFA0 0000 to PS2 ROM header */
|
||
len = 0;
|
||
|
||
for (i=0 ; i < num_objects ; i ++)
|
||
{
|
||
|
||
/* looking for Feature ROM object in the array */
|
||
|
||
if (p_obj_info_buf->type.sub.id == RSCAN_60X_ROM_FRS)
|
||
{
|
||
ps2_offset = p_obj_info_buf->offset;
|
||
len = p_obj_info_buf->length; /* what is this len for ? */
|
||
}
|
||
|
||
p_obj_info_buf ++; /* point to next object in array */
|
||
|
||
}
|
||
|
||
if (! ps2_offset) /* if no Feature ROM */
|
||
{
|
||
DEBUG_0("cfg_graphics_frs_tools.c:Find_Video_Device: No Feature ROM object found !\n");
|
||
return (E_NODETECT);
|
||
}
|
||
|
||
/*
|
||
* ROM creater makes sure this offset is from 0xFFA0 0000 and
|
||
* accounts for word increment too
|
||
*/
|
||
scan_address = ps2_offset + BUS_60X_START_VPD_FEATURE_ROM;
|
||
|
||
DEBUG_1("cfg_graphics_frs_tools.c:Find_Video_Device: found FRS obj, ps2 offset =%x\n",ps2_offset);
|
||
|
||
/*
|
||
Note we set ctl.read_words to the address of nvram_60x_rd_bytes...
|
||
so it should read the rom in bytes in stead of words
|
||
*/
|
||
rc = FRS_Test_Addr_for_RSCAN_PS2( &ctl,
|
||
scan_address,
|
||
&valid, buid_type);
|
||
|
||
DEBUG_3("cfg_graphics_frs_tools.c:Find_Video_Device: Test_Addr_for_RSCAN_PS2 returns rc = %d, valid = %d, PS2 at %x \n", rc,valid,ctl.bus_rscan_ps2);
|
||
|
||
if ( rc != 0 ) { return (rc); }
|
||
if ( ! valid ) { return (E_NODETECT); }
|
||
|
||
|
||
break;
|
||
|
||
default:
|
||
/* should never get here */
|
||
|
||
/*
|
||
assert( 0 );
|
||
*/
|
||
break;
|
||
|
||
} /* end of switch */
|
||
|
||
/*--------------------------------------------------------
|
||
| We have a vaild RSCAN_PS2 header
|
||
| Now locate a valid RSCAN_600X_BLK structure
|
||
|
|
||
| Walk the linked list of dynamic blocks
|
||
| (Starting at the head) and find the
|
||
| first one that matches our needs
|
||
| If the search routine finds a valid block, it will also
|
||
| enable the adapter to have the block read
|
||
|
|
||
| if valid, then the ctl structure holds:
|
||
| ctl.bus_rscan_blk - bus address of structure
|
||
| ctl.mem_rscan_blk - mem address of copy of structure
|
||
| ctl.bus_rscan_r2_head - bus address of RSCAN_VIDEO_HEAD
|
||
| ctl.mem_rscan_r2_head - invalid (NULL)
|
||
|
|
||
| also, if valid, the device will be enabled for reading the
|
||
| Feature ROM Scan contents
|
||
|
|
||
|--------------------------------------------------------*/
|
||
|
||
valid = FALSE;
|
||
|
||
switch (buid_type)
|
||
{
|
||
|
||
case CFG_GRAPH_BUID_2x:
|
||
|
||
rc = FRS_Search_for_RSCAN_6001_BLK( &ctl,
|
||
&valid );
|
||
|
||
if ( rc || ( ! valid ) )
|
||
{
|
||
/*
|
||
disable the card by
|
||
setting bit 0 of POS2 to 0
|
||
*/
|
||
disable_device(&ctl);
|
||
|
||
if ( ! valid )
|
||
{
|
||
rc = E_NODETECT;
|
||
}
|
||
return (rc);
|
||
}
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_40:
|
||
|
||
rc = FRS_Search_for_RSCAN_6002_BLK( &ctl,
|
||
&valid );
|
||
if ( rc != 0 ) { return (rc); }
|
||
if ( ! valid ) { return (E_NODETECT); }
|
||
|
||
break;
|
||
|
||
case CFG_GRAPH_BUID_7F: /* 601_CHANGE */
|
||
|
||
|
||
rc = FRS_Search_for_RSCAN_6003_BLK( &ctl,
|
||
&valid );
|
||
|
||
DEBUG_2("cfg_graphics_frs_tools.c:Find_Video_Device: FRS_Search_for_6003_BLK returns rc = %d, valid = %d \n", rc,valid);
|
||
|
||
if ( rc != 0 ) { return (rc); }
|
||
if ( ! valid ) { return (E_NODETECT); }
|
||
|
||
break;
|
||
|
||
default:
|
||
/* should never get here */
|
||
|
||
/*
|
||
assert( 0 );
|
||
*/
|
||
break;
|
||
} /* end of switch */
|
||
|
||
/*--------------------------------------------------------
|
||
| We have a vaild RSCAN_PS2 header and a valid RSCAN_600X_BLK structure
|
||
|
|
||
| Now validate the RSCAN_VIDEO_HEAD
|
||
|
|
||
| if valid, then the ctl structure holds:
|
||
| ctl.mem_rscan_r2_head - mem address of copy of VIDEO rom
|
||
|
|
||
| also, if valid, the device will be enabled for reading the
|
||
| Feature ROM Scan contents
|
||
|
|
||
|--------------------------------------------------------*/
|
||
|
||
valid = FALSE;
|
||
|
||
rc = FRS_Validate_RSCAN_VIDEO_HEAD( &ctl,
|
||
&valid, buid_type );
|
||
|
||
DEBUG_2("cfg_graphics_frs_tools.c:Find_Video_Device: FRS_Validate_RSCAN_VIDEO_HEAD returns rc = %d, valid = %d \n", rc,valid);
|
||
|
||
|
||
/*------------------------------------------------------
|
||
|
|
||
| disable the card by
|
||
| setting bit 0 of POS2 to 0
|
||
|------------------------------------------------------*/
|
||
|
||
if ( buid_type == CFG_GRAPH_BUID_2x)
|
||
{
|
||
disable_device(&ctl);
|
||
}
|
||
|
||
if ( rc != 0 ) { return (rc); }
|
||
if ( ! valid ) { return (E_NODETECT); }
|
||
|
||
|
||
|
||
/*------------------------------------------------------
|
||
|
|
||
| Everything is valid.
|
||
|
|
||
| release the malloc-ed structures that we no longer need
|
||
|------------------------------------------------------*/
|
||
|
||
if ( ctl.mem_rscan_ps2 != NULL ) { free( ctl.mem_rscan_ps2 ); }
|
||
if ( ctl.mem_rscan_blk != NULL ) { free( ctl.mem_rscan_blk ); }
|
||
|
||
|
||
/*------------------------------------------------------
|
||
| pass back the pointer to the VIDEO rom
|
||
|
|
||
| DON'T free up this one. Caller gets to use it!!
|
||
|-------------------------------------------------------*/
|
||
|
||
*p_video_head = (void *) ctl.mem_rscan_r2_head;
|
||
|
||
return(0);
|
||
|
||
}
|
||
|
||
|
||
|
||
/*****************************************************************************
|
||
********************** FUNCTION HEADER TOP***********************************
|
||
*****************************************************************************
|
||
|
||
FUNCTION NAME: FRS_Make_Temp_File( )
|
||
|
||
TITLE: Function to create a temporary file that will be used later
|
||
to transform an FRS module into something usefile by AIX
|
||
|
||
------------------------------------------------------------------------
|
||
|
||
FUNCTION:
|
||
|
||
EXECUTION ENVIRONMENT: User process environment only
|
||
|
||
INPUTS:
|
||
p_video_head - address of pointer which holds the location
|
||
of the RSCAN_R2_HEAD structure. This pointer was
|
||
created by FRS_Find_Video_Device( )
|
||
|
||
frs_module - id of which FRS module to extract and place into
|
||
the temporary file
|
||
|
||
file_perms - the permissions desired for the file
|
||
|
||
file_name - address of pointer which will hold the filename
|
||
|
||
RETURNS:
|
||
an integer return code stating whether an error occurred or not.
|
||
|
||
E_NODETECT could not locate/validate some piece of FRS structures
|
||
E_OPEN could not open a file or device driver
|
||
E_MALLOC failed to malloc somewhere
|
||
E_BADATTR invalid input to some routine
|
||
E_DEVACCESS one of the machine device driver calls failed
|
||
E_VPD CRC, checksum, or contents of FRS structure was not good
|
||
|
||
*****************************************************************************
|
||
********************** FUNCTION HEADER BOTTOM *******************************
|
||
*****************************************************************************/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int
|
||
FRS_Make_Temp_File(
|
||
void * p_video_head,
|
||
int frs_module,
|
||
int file_perms,
|
||
char ** file_name
|
||
)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int rc;
|
||
RSCAN_VIDEO_HEAD * mem_head;
|
||
char * buffer;
|
||
ulong buffer_offset;
|
||
size_t buffer_length;
|
||
struct stat s_stat;
|
||
int fd;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
mem_head = (RSCAN_VIDEO_HEAD *) p_video_head;
|
||
|
||
/*-------------------------------------
|
||
| validate input parameters
|
||
|-------------------------------------*/
|
||
|
||
if ( mem_head == NULL ) { return (E_BADATTR); }
|
||
if ( file_perms == 0 ) { return (E_BADATTR); }
|
||
|
||
/*--------------------------------------
|
||
| Create the temp file name
|
||
|--------------------------------------*/
|
||
|
||
(void) tmpnam( file_name );
|
||
|
||
/*-------------------------------------
|
||
| Check if the file already exists.
|
||
| If it does, unlink it
|
||
|--------------------------------------*/
|
||
|
||
rc = stat( file_name, &s_stat );
|
||
|
||
if ( rc == 0 )
|
||
{
|
||
/*--- file exists ---*/
|
||
rc = unlink( file_name );
|
||
|
||
if ( rc != 0 ) { return (E_STAT); }
|
||
}
|
||
|
||
/*---------------------------------------
|
||
| Now create the new file
|
||
|---------------------------------------*/
|
||
|
||
fd = creat( file_name, file_perms );
|
||
|
||
if ( fd < 0 ) { return (E_STAT); }
|
||
|
||
/*---------------------------------------
|
||
| all exits after this point should close the
|
||
| file and check the file_name for validity!
|
||
|----------------------------------------*/
|
||
|
||
/*--------------------------------------
|
||
| use the frs_module to read in the correct
|
||
| item from the RSCAN_VIDEO_HEAD rom
|
||
|
|
||
| the following modules are supported:
|
||
|
|
||
| CFG_GRAPH_ODM_FILE
|
||
| CFG_GRAPH_METHOD_FILE
|
||
| CFG_GRAPH_CDD_FILE
|
||
| CFG_GRAPH_CDD_PIN_FILE
|
||
| CFG_GRAPH_UCODE_FILE
|
||
|
|
||
|--------------------------------------*/
|
||
|
||
switch (frs_module)
|
||
{
|
||
|
||
case CFG_GRAPH_ODM_FILE:
|
||
|
||
buffer_offset = RSCAN_VIDEO_HEAD_odm_offset( mem_head );
|
||
buffer_length = RSCAN_VIDEO_HEAD_odm_len( mem_head );
|
||
break;
|
||
|
||
case CFG_GRAPH_UCODE_FILE:
|
||
|
||
buffer_offset = RSCAN_VIDEO_HEAD_ucode_offset( mem_head );
|
||
buffer_length = RSCAN_VIDEO_HEAD_ucode_len( mem_head );
|
||
break;
|
||
|
||
case CFG_GRAPH_METHOD_FILE:
|
||
|
||
buffer_offset = RSCAN_VIDEO_HEAD_kmod_offset( mem_head, VRS_KMOD_CFG_METHOD );
|
||
buffer_length = RSCAN_VIDEO_HEAD_kmod_len( mem_head, VRS_KMOD_CFG_METHOD );
|
||
break;
|
||
|
||
case CFG_GRAPH_CDD_FILE:
|
||
|
||
buffer_offset = RSCAN_VIDEO_HEAD_kmod_offset( mem_head, VRS_KMOD_ENTRY_POINT );
|
||
buffer_length = RSCAN_VIDEO_HEAD_kmod_len( mem_head, VRS_KMOD_ENTRY_POINT );
|
||
break;
|
||
|
||
case CFG_GRAPH_CDD_PIN_FILE:
|
||
|
||
buffer_offset = RSCAN_VIDEO_HEAD_kmod_offset( mem_head, VRS_KMOD_INTERRUPT );
|
||
buffer_length = RSCAN_VIDEO_HEAD_kmod_len( mem_head, VRS_KMOD_INTERRUPT );
|
||
break;
|
||
|
||
default:
|
||
(void) close( fd );
|
||
(void) unlink( *file_name );
|
||
*file_name = NULL;
|
||
return (E_BADATTR);
|
||
}
|
||
|
||
/*---------------------------------------------
|
||
| was there really a kmod in the ROM copy?
|
||
|----------------------------------------------*/
|
||
|
||
if ( ( buffer_offset == 0 )
|
||
|| ( buffer_length == 0 )
|
||
)
|
||
{
|
||
/*-------------------------
|
||
| NO. Clean up and exit
|
||
|--------------------------*/
|
||
|
||
(void) close( fd );
|
||
(void) unlink( *file_name );
|
||
*file_name = NULL;
|
||
return (E_NODETECT);
|
||
}
|
||
|
||
/*-------------------------------------------------
|
||
| move the kmod into the file
|
||
|-------------------------------------------------*/
|
||
|
||
buffer = ((char *) mem_head) + buffer_offset;
|
||
|
||
rc = write( fd, buffer, buffer_length );
|
||
|
||
if ( rc != buffer_length )
|
||
{
|
||
/*-------------------------
|
||
| Clean up and exit
|
||
|--------------------------*/
|
||
|
||
(void) close( fd );
|
||
(void) unlink( *file_name );
|
||
*file_name = NULL;
|
||
return (E_STAT);
|
||
}
|
||
|
||
rc = fsync( fd );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
/*-------------------------
|
||
| Clean up and exit
|
||
|--------------------------*/
|
||
|
||
(void) close( fd );
|
||
(void) unlink( *file_name );
|
||
*file_name = NULL;
|
||
return (E_STAT);
|
||
}
|
||
|
||
/*--------------------------------------------------
|
||
| Everything is OK
|
||
|--------------------------------------------------*/
|
||
|
||
rc = close( fd );
|
||
|
||
if ( rc != 0 )
|
||
{
|
||
/*-------------------------
|
||
| Clean up and exit
|
||
|--------------------------*/
|
||
|
||
return (E_STAT);
|
||
}
|
||
|
||
return(0);
|
||
|
||
}
|
||
|
||
|
||
/*
|
||
* NAME: FRS_Update_ODM_From_File()
|
||
*
|
||
* FUNCTION:
|
||
*
|
||
* This routine opens a file containing the odm stanzas and
|
||
* builds the appropriate struct for that stanza. It then queries
|
||
* the database for entries of the same type. If the entry is
|
||
* not in the data base it is added. If the entry in the database
|
||
* is different it is removed and the new entry is added, otherwase,
|
||
* no action is taken.
|
||
*
|
||
* EXECUTION ENVIRONMENT:
|
||
*
|
||
* The objects come from a file
|
||
*
|
||
* RETURNS: .
|
||
*
|
||
* Returns a 0 if successful, a number greater than 0 if not
|
||
*/
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| FUNCTION DECLARATION
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
int
|
||
FRS_Update_ODM_From_File(char * stanza_input_file,
|
||
char ** uniquetype,
|
||
char ** method_file)
|
||
{
|
||
/*-----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
/*-------------------------------
|
||
| external data
|
||
|--------------------------------*/
|
||
|
||
extern int odmerrno;
|
||
|
||
/*-------------------------------
|
||
| data for this function
|
||
|-------------------------------*/
|
||
|
||
FILE * file_ptr;
|
||
|
||
int stanza_length;
|
||
int skip_spaces;
|
||
int number_of_values;
|
||
int descriptor_index;
|
||
int returnstatus;
|
||
|
||
unsigned int offset;
|
||
|
||
char terminating_char;
|
||
char sstring[255];
|
||
|
||
char * stanza;
|
||
char * class_name;
|
||
char * descrip_name;
|
||
char * descrip_value;
|
||
char * new_entry;
|
||
char * old_entry;
|
||
char * descriptor_offset;
|
||
|
||
CLASS_SYMBOL Class;
|
||
CLASS_SYMBOL return_class;
|
||
|
||
char ** vchar_location; /* ptr to vchar location in the structure */
|
||
char * first_err;
|
||
|
||
struct PdAt * p_PdAt;
|
||
|
||
struct PdDv * p_PdDv;
|
||
|
||
struct PdCn * p_PdCn;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
/*---------------------------------------------------------
|
||
| Initialiaze some data
|
||
|--------------------------------------------------------*/
|
||
|
||
stanza_line_number = 0;
|
||
**method_file = '\0';
|
||
**uniquetype = '\0';
|
||
|
||
|
||
if (odm_initialize () == FAIL)
|
||
{
|
||
/* initialization failed */
|
||
DEBUG_0 ("FRS_Update_ODM_From_File: odm_initialize() failed\n");
|
||
return (odmerrno);
|
||
}
|
||
|
||
/*---------------------------------------------------------
|
||
| open the input file
|
||
|---------------------------------------------------------*/
|
||
|
||
file_ptr = fopen(stanza_input_file,"r");
|
||
|
||
if (file_ptr == NULL )
|
||
{
|
||
return ODMI_OPEN_ERR;
|
||
}
|
||
|
||
/*--------------------------------------------------------
|
||
| loop through the file contents
|
||
|--------------------------------------------------------*/
|
||
|
||
while ( (stanza_length = get_ascii_phrase(file_ptr,STANZA,&stanza)) > 0)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: stanza length is %d\n",stanza_length);
|
||
|
||
skip_spaces = FALSE;
|
||
|
||
/*--------------------------------------------------*/
|
||
/* Get the first value from the phrase. Subsequent */
|
||
/* calls will be made with the value 'NULL' for */
|
||
/* 'ascii_string' since the 'get_value' routine */
|
||
/* keeps track of where it was last. */
|
||
/*--------------------------------------------------*/
|
||
|
||
class_name = get_value_from_string(stanza,":\n",skip_spaces,
|
||
&terminating_char);
|
||
|
||
if (class_name == (char *) NULL || terminating_char != ':')
|
||
{
|
||
/*--------------------------------*/
|
||
/* Could not find the class name. */
|
||
/*--------------------------------*/
|
||
|
||
DEBUG_0("FRS_Update_ODM_From_File: could not find class name!\n");
|
||
|
||
} /* endif */
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: class name %s\n",class_name);
|
||
|
||
if( ( (Class=odm_mount_class(class_name))==NULL )
|
||
|| ( Class == (CLASS_SYMBOL) -1 )
|
||
)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: could not open class %s\n",class_name);
|
||
fclose( file_ptr );
|
||
return(ODMI_INVALID_CLASS);
|
||
|
||
}
|
||
else
|
||
{
|
||
skip_spaces = TRUE;
|
||
|
||
return_class = (CLASS_SYMBOL) odm_open_class(Class);
|
||
|
||
if ((int) return_class == FAIL)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: Could not open class! err %d\n",odmerrno);
|
||
fclose( file_ptr );
|
||
return(ODMI_OPEN_ERR);
|
||
} /* endif */
|
||
|
||
new_entry = (char *) malloc(Class->structsize);
|
||
|
||
if (new_entry == (char *) NULL)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: new_entry malloc failed! %d\n", Class->structsize);
|
||
fclose( file_ptr );
|
||
return(ODMI_MALLOC_ERR);
|
||
} /* endif */
|
||
|
||
old_entry = (char *) malloc(Class->structsize);
|
||
|
||
if (old_entry == (char *) NULL)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: old_entry malloc failed! %d\n", Class->structsize);
|
||
(void) free( new_entry );
|
||
fclose( file_ptr );
|
||
return(ODMI_MALLOC_ERR);
|
||
} /* endif */
|
||
|
||
bzero(new_entry,Class->structsize);
|
||
bzero(old_entry,Class->structsize);
|
||
|
||
/*------------------------------------------------------------*/
|
||
/* Since the variable length char (vchars) are stored in a */
|
||
/* separate buffer rather than in the structure itself, */
|
||
/* go through the class info and malloc space for the vchars */
|
||
/*------------------------------------------------------------*/
|
||
|
||
for ( descriptor_index = 0;
|
||
descriptor_index < Class->nelem;
|
||
descriptor_index++ )
|
||
{
|
||
|
||
if ((Class->elem)[descriptor_index].type == ODM_VCHAR)
|
||
{
|
||
|
||
vchar_location = (char **)
|
||
(new_entry + (Class->elem)[descriptor_index].offset);
|
||
|
||
*vchar_location = (char *) NULL;
|
||
} /* endif */
|
||
} /* endfor */
|
||
|
||
while (TRUE)
|
||
{
|
||
/*-------------------------------------------*/
|
||
/* Find the name of the next descriptor */
|
||
/*-------------------------------------------*/
|
||
|
||
DEBUG_0("obj_find_string: looking for stanza descrip NAME\n");
|
||
|
||
descrip_name = get_value_from_string( (char *) NULL,"=\n",
|
||
skip_spaces,
|
||
&terminating_char);
|
||
|
||
if ( ( descrip_name == (char *) NULL)
|
||
|| ((*descrip_name == '\0' && terminating_char == '\0')))
|
||
{
|
||
/*---------------------------*/
|
||
/* Found the end-of-stanza. */
|
||
/*---------------------------*/
|
||
DEBUG_0("obj_find_string: found_stanza_end!!\n");
|
||
break;
|
||
}
|
||
else if (terminating_char != '=')
|
||
{
|
||
/*---------------------*/
|
||
/* free(descrip_name); */
|
||
/*---------------------*/
|
||
DEBUG_0("FRS_Update_ODM_From_File: could not find name!!\n");
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
}
|
||
else
|
||
{
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: descriptor NAME is %s\n",descrip_name);
|
||
} /* endif */
|
||
|
||
|
||
/*-------------------------------------------*/
|
||
/* Determine the offset for this descriptor. */
|
||
/*-------------------------------------------*/
|
||
|
||
for ( descriptor_index = 0;
|
||
descriptor_index < Class->nelem;
|
||
descriptor_index++ )
|
||
{
|
||
|
||
if (0 == strcmp( (Class->elem)[descriptor_index].elemname,
|
||
descrip_name) )
|
||
{
|
||
/*-------------*/
|
||
/* Found name! */
|
||
/*-------------*/
|
||
DEBUG_1("FRS_Update_ODM_From_File: found table name %d\n",descriptor_index);
|
||
break;
|
||
|
||
}
|
||
} /* endfor */
|
||
|
||
if (descriptor_index >= Class->nelem)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: could not find name %s\n",descrip_name);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
} /* endif */
|
||
|
||
/*-----------------------------------*/
|
||
/* Get the value for this descriptor */
|
||
/*-----------------------------------*/
|
||
|
||
|
||
|
||
descrip_value = get_value_from_string((char *) NULL,"\n",
|
||
skip_spaces, &terminating_char);
|
||
|
||
if (descrip_value == (char *) NULL)
|
||
{
|
||
/*-----------------------------------------------*/
|
||
/* Could not find the value for this descriptor. */
|
||
/*-----------------------------------------------*/
|
||
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
|
||
} /* endif */
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: Descriptor value is %s\n",descrip_value);
|
||
|
||
/*-------------------------------------------------------*/
|
||
/* We now have the descriptor name and its value. Store */
|
||
/* it in the structure. */
|
||
/*-------------------------------------------------------*/
|
||
|
||
|
||
descriptor_offset = new_entry + Class->elem[descriptor_index].offset;
|
||
|
||
switch ( (Class->elem)[descriptor_index].type )
|
||
{
|
||
case ODM_LINK:
|
||
|
||
/* skip pointers */
|
||
descriptor_offset = descriptor_offset + 2 * sizeof (char *);
|
||
|
||
/*-----------------------------------*/
|
||
/* Fall through and save the string. */
|
||
/*-----------------------------------*/
|
||
|
||
case ODM_CHAR:
|
||
case ODM_LONGCHAR:
|
||
case ODM_METHOD:
|
||
|
||
*descriptor_offset = '\0';
|
||
|
||
strncat( descriptor_offset,descrip_value,
|
||
(Class->elem)[descriptor_index].size - 1);
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: storing character %s\n", descriptor_offset);
|
||
break;
|
||
|
||
case ODM_VCHAR:
|
||
|
||
/*------------------------------------------------*/
|
||
/* Since the vchars are not put directly into the */
|
||
/* structure, we need to save the string in the */
|
||
/* buffer pointed to by descriptor_offset. */
|
||
/*------------------------------------------------*/
|
||
|
||
vchar_location = (char **) descriptor_offset;
|
||
|
||
if (*vchar_location != NULL)
|
||
{
|
||
/*-----------------------------------------------*/
|
||
/* When *vchar_location != NULL occurs, this */
|
||
/* means that the user has two lines in the */
|
||
/* stanza for the same value. Free the previous */
|
||
/* buffer and malloc a new buffer so we only */
|
||
/* keep the last value. */
|
||
/*-----------------------------------------------*/
|
||
free(*vchar_location);
|
||
*vchar_location = NULL;
|
||
} /* endif */
|
||
|
||
*vchar_location = (char *) malloc(strlen(descrip_value) + 1);
|
||
|
||
if (*vchar_location == NULL)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: vchar malloc failed! %d\n",
|
||
strlen(descrip_value) + 1);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
|
||
return(ODMI_MALLOC_ERR);
|
||
} /* endif */
|
||
|
||
strcpy(*vchar_location,descrip_value);
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: storing character %s\n", descrip_value);
|
||
break;
|
||
|
||
case ODM_BINARY:
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: converting hex %s\n",descrip_value);
|
||
|
||
returnstatus = convert_to_binary(descrip_value,
|
||
descriptor_offset,
|
||
(Class->elem)[descriptor_index].size);
|
||
if (returnstatus < 0)
|
||
{
|
||
DEBUG_0("FRS_Update_ODM_From_File: could not convert hex\n");
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
} /* endif */
|
||
|
||
break;
|
||
|
||
case ODM_LONG:
|
||
|
||
*(long *)descriptor_offset= strtol(descrip_value,&first_err,NULL);
|
||
|
||
if(*first_err)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: bad long value %s\n", descrip_value);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
} /* endif */
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: storing long %ld\n", *(long *)descriptor_offset);
|
||
break;
|
||
|
||
case ODM_DOUBLE:
|
||
|
||
*(double *)descriptor_offset= strtod(descrip_value,&first_err);
|
||
|
||
if (*first_err)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: bad double value %s\n", descrip_value);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
} /* endif */
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: storing long %ld\n", *(long *)descriptor_offset);
|
||
break;
|
||
|
||
case ODM_SHORT:
|
||
|
||
*(short *)descriptor_offset= (short) strtol(descrip_value,&first_err,NULL);
|
||
if (*first_err)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: bad short value %s\n", descrip_value);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_OPEN);
|
||
} /* endif */
|
||
|
||
DEBUG_1("FRS_Update_ODM_From_File: storing short %d\n", *(short *)descriptor_offset);
|
||
break;
|
||
|
||
default:
|
||
|
||
DEBUG_2("FRS_Update_ODM_From_File: bad type!! %s, type %d",
|
||
(Class->elem)[descriptor_index].elemname,
|
||
(Class->elem)[descriptor_index].type);
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
|
||
return(E_OPEN);
|
||
|
||
}
|
||
|
||
|
||
number_of_values++;
|
||
|
||
/*----------------------------------------*/
|
||
/* if (descrip_value) */
|
||
/* free(descrip_value); */
|
||
/* */
|
||
/* if (descrip_name) */
|
||
/* free(descrip_name); */
|
||
/*----------------------------------------*/
|
||
|
||
} /* endwhile */
|
||
|
||
/*---------------------------------------------------
|
||
| Setup the search criterion
|
||
|--------------------------------------------------*/
|
||
|
||
if ( ( strncmp(Class->classname, "PdDv", 4) ) == 0 )
|
||
{
|
||
p_PdDv = (struct PdDv *) new_entry;
|
||
offset = sizeof (p_PdDv->_id) +
|
||
sizeof (p_PdDv->_reserved) +
|
||
sizeof (p_PdDv->_scratch);
|
||
sprintf(sstring, "type = '%s'", p_PdDv->type);
|
||
strcpy( *uniquetype, p_PdDv->uniquetype );
|
||
|
||
}
|
||
else if ( ( strncmp(Class->classname, "PdCn", 4) ) == 0 )
|
||
{
|
||
p_PdCn = (struct PdCn *) new_entry;
|
||
offset = sizeof (p_PdCn->_id) +
|
||
sizeof (p_PdCn->_reserved) +
|
||
sizeof (p_PdCn->_scratch);
|
||
/* sprintf(sstring, "uniquetype = '%s'", p_PdCn->uniquetype); */
|
||
sprintf(sstring, "uniquetype = '%s' and connkey = '%s'", p_PdCn->uniquetype,p_PdCn->connkey);
|
||
}
|
||
else if ( ( strncmp(Class->classname, "PdAt", 4) ) == 0 )
|
||
{
|
||
p_PdAt = (struct PdAt *) new_entry;
|
||
offset = sizeof (p_PdAt->_id) +
|
||
sizeof (p_PdAt->_reserved) +
|
||
sizeof (p_PdAt->_scratch);
|
||
sprintf(sstring, "uniquetype = '%s'and attribute = '%s'",
|
||
p_PdAt->uniquetype,p_PdAt->attribute );
|
||
if ( strncmp ( p_PdAt->attribute, "cfg_method_load", 15) == 0 )
|
||
{
|
||
strcpy( *method_file, p_PdAt->deflt );
|
||
}
|
||
if ( !strncmp ( p_PdAt->attribute, "belongs_to", 10 ) )
|
||
{
|
||
/* if we detect "belongs_to=hft0" we need to remove */
|
||
/* it and replace it with "belongs_to=graphics" for */
|
||
/* AIX 4.1 LFT which replaces the older HFT. */
|
||
|
||
if ( !strncmp ( p_PdAt->deflt, "hft0", 4 ) ) {
|
||
DEBUG_0("Found hft0 in ODM database\n")
|
||
strcpy( p_PdAt->deflt, "graphics" );
|
||
/* delete "hft0" stinky from ODM and add "graphics" */
|
||
returnstatus = odm_rm_obj ( Class, sstring );
|
||
DEBUG_1("deleting belongs_to=hft0 returned %d\n",returnstatus)
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return ODMI_INVALID_CLASS;
|
||
}
|
||
|
||
|
||
returnstatus = odm_get_obj ( Class, sstring, old_entry, ODM_FIRST);
|
||
|
||
if ( returnstatus == NULL )
|
||
{
|
||
if ((returnstatus = odm_add_obj(Class,new_entry)) < 0)
|
||
{
|
||
(void) free( new_entry );
|
||
(void) free( old_entry );
|
||
fclose( file_ptr );
|
||
return(E_VPD);
|
||
}
|
||
}
|
||
else if ( memcmp((new_entry + offset),
|
||
(old_entry + offset),
|
||
((Class->structsize) - offset ) ) != 0)
|
||
{
|
||
returnstatus = odm_rm_obj ( Class, sstring );
|
||
|
||
if ( returnstatus != FAIL )
|
||
{
|
||
odm_add_obj(Class,new_entry);
|
||
}
|
||
|
||
}
|
||
free(new_entry);
|
||
free(old_entry);
|
||
|
||
/*------------------------------------------------------------*/
|
||
/* Since the variable length char (vchars) are stored in a */
|
||
/* separate buffer rather than in the structure itself, */
|
||
/* go through the class info and free space for the vchars */
|
||
/*------------------------------------------------------------*/
|
||
|
||
for (descriptor_index = 0; descriptor_index < Class->nelem;
|
||
descriptor_index++)
|
||
{
|
||
|
||
if ((Class->elem)[descriptor_index].type == ODM_VCHAR)
|
||
{
|
||
vchar_location = (char **)
|
||
(new_entry + (Class->elem)[descriptor_index].offset);
|
||
|
||
if (*vchar_location != NULL)
|
||
{
|
||
free (*vchar_location);
|
||
*vchar_location = NULL;
|
||
}
|
||
} /* endif */
|
||
} /* endfor */
|
||
} /* if OpenClass */
|
||
|
||
/*--------------------------------*/
|
||
/* if (stanza != (char *) NULL) */
|
||
/* free(stanza); */
|
||
/*--------------------------------*/
|
||
|
||
|
||
} /* endwhile */
|
||
|
||
/*------------------------------------*/
|
||
/* returnstatus = close_class(Class); */
|
||
/*------------------------------------*/
|
||
|
||
if (stanza_length < 0)
|
||
{
|
||
DEBUG_1("FRS_Update_ODM_From_File: Stanza length is negative!! %d\n",stanza_length);
|
||
fclose( file_ptr );
|
||
return(E_VPD);
|
||
} /* endif */
|
||
|
||
fclose( file_ptr );
|
||
return(0);
|
||
|
||
} /* end FRS_Update_ODM_From_File()*/
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
int
|
||
FRS_Copy_File(char * s_pathname, char * d_pathname)
|
||
{
|
||
|
||
|
||
/*----------------------------------------------
|
||
|
|
||
| DATA DECLARATIONS
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
char * p_buffer;
|
||
|
||
FILE * source_desc;
|
||
FILE * destination_desc;
|
||
|
||
int num_bytes;
|
||
int total_bytes;
|
||
int block_size;
|
||
|
||
struct stat s_stat;
|
||
|
||
/*-----------------------------------------------
|
||
|
|
||
| START OF SOURCE CODE
|
||
|
|
||
|-----------------------------------------------*/
|
||
|
||
/*-------------------------------------------------
|
||
|
|
||
| First test that the supplied source pathname is valid
|
||
|
|
||
|----------------------------------------------------*/
|
||
|
||
if(( s_pathname == NULL ) || (( stat( s_pathname, &s_stat )) != 0 ))
|
||
{
|
||
/*-------------------------------------------
|
||
| the source_path is invalid
|
||
|------------------------------------------*/
|
||
|
||
return( E_OPEN );
|
||
}
|
||
|
||
/*-------------------------------------------------
|
||
| malloc enough memory to read in the file, if not
|
||
| more than 40kB, otherwise malloc 40K
|
||
|------------------------------------------------*/
|
||
|
||
block_size = MIN (s_stat.st_size, MEM_BLOCK_40K) ;
|
||
p_buffer = malloc ( block_size );
|
||
|
||
if ( p_buffer == NULL )
|
||
{
|
||
return( E_MALLOC );
|
||
}
|
||
|
||
|
||
/*-------------------------------------------------
|
||
| Open the source and destination files
|
||
| then read and write the file
|
||
| then close them up
|
||
|------------------------------------------------*/
|
||
|
||
if ( ( source_desc = fopen ( s_pathname, "r") ) == NULL )
|
||
{
|
||
free ( p_buffer );
|
||
return E_OPEN ;
|
||
}
|
||
|
||
if ( ( destination_desc = fopen ( d_pathname, "w") ) == NULL )
|
||
{
|
||
free ( p_buffer );
|
||
return E_OPEN ;
|
||
}
|
||
|
||
|
||
/*---------------------------------------------------------
|
||
| Read the file and check that we got it all
|
||
|--------------------------------------------------------*/
|
||
|
||
num_bytes = 0;
|
||
total_bytes = 0;
|
||
|
||
do
|
||
{
|
||
num_bytes = fread(p_buffer,
|
||
1,
|
||
block_size,
|
||
source_desc);
|
||
|
||
/*---------------------------------------------------------
|
||
| Write the file and check that we got it all
|
||
|--------------------------------------------------------*/
|
||
|
||
if ( (fwrite(p_buffer, 1, num_bytes, destination_desc) ) != s_stat.st_size )
|
||
{
|
||
free (p_buffer);
|
||
return E_OPEN;
|
||
}
|
||
total_bytes += num_bytes;
|
||
}
|
||
while ( total_bytes < s_stat.st_size );
|
||
|
||
/*----------------------------------------------------------
|
||
| Free up the memory we used and close files
|
||
|---------------------------------------------------------*/
|
||
|
||
free ( p_buffer );
|
||
|
||
fclose ( source_desc) ;
|
||
fclose ( destination_desc);
|
||
|
||
return PASS;
|
||
}
|
||
|