Files
seta75D d6fe8fe829 Init
2021-10-11 22:19:34 -03:00

357 lines
13 KiB
C

static char sccsid[] = "@(#)75 1.1 src/bos/usr/lib/methods/common/lducode.c, cfgmethods, bos411, 9428A410j 8/2/92 15:09:09";
/*
* COMPONENT_NAME: (CFGMETH) cfgampx
*
* FUNCTIONS: load_ucode(), swap_bytes()
*
* 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
* All Rights Reserved
*
* US Government Users Restricted Rights - Use, duplication or
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
*/
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ³
³ ³
³ PURPOSE: Loads tasks on to ARTIC adapters using the machine device ³
³ driver ³
³ ³
³ ALGORITHM DESCRIPTION: Described under each function ³
³ ³
³ EXTERNAL VARIABLES USED: None ³
³ ³
³ PUBLIC VARIABLES DECLARED: None ³
³ ³
³ PUBLIC SUBROUTINES DECLARED: load_diag_task ³
³ ³
³ EXTERNAL ROUTINES CALLED: ³
³ getbuffers ³
³ issuecmd ³
³ intwait ³
³ readmem ³
³ writemem ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include "lducode.h"
#include <sys/errno.h>
#include <sys/mdio.h>
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Macros used to access fields in task header ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#define TASKNUM(x) *((uchar *)&x[4])
#define CMDSEG(x) *((ushort *)&x[12])
#define INITSEG(x) *((ushort *)&x[16])
#define DATASEG(x) *((ushort *)&x[18])
#define STACKSEG(x) *((ushort *)&x[20])
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Size of xxxxxxxx.com file headers ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#define TASK_HEADER_SIZE 28
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Size of data packets read from task file and ³
³ transferred to card ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#define XFERSIZE 128
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ ROS Command codes ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#define REQUEST_TASK_LOAD 0x01
#define START_TASK 0x05
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Return codes from load_ucode ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
#define SUCCESS 0
#define E_FILE_OPEN -1
#define E_GET_BUFFERS -2
#define E_FILE_READ -3
#define E_REQ_TASK_LOAD -4
#define E_NO_INTERRUPT -5
#define E_READ_BUSMEM -6
#define E_WRITE_BUSMEM -7
#define E_RTL_CMD -8
#define E_ISSUECMD -9
#define E_TASK_HEADER -10
#define E_RESET -11
#define E_TASK_ALREADY_LOADED -12
void swap_bytes(word)
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Swaps the two bytes pointed to by the word parameter. ³
³ Used to convert data into Intel format for use on the cards ³
³ ³
³ INPUTS: address of word to swap ³
³ ³
³ OUTPUTS: none ³
³ ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
ushort *word; /* Word to be swapped */
{
uchar *p, tmp;
p = (uchar *) word;
tmp = *p;
*p = *(p+1);
*(p+1) = tmp;
}
int load_ucode(fd, pos, fname, tasknum)
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Loads the task indicated by fname unto a specific card. The routine will ³
³ fail if tasknum is already loaded on the card. Also note that this will ³
³ only load tasks in .COM format. ³
³ ³
³ INPUTS: file descriptor for machine device driver ³
³ POS register info of target adapter ³
³ path name of task (microcode) ³
³ task number to load task as ³
³ ³
³ OUTPUTS: return code 0 no errors ³
³ < 0 Error ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
int fd; /* File descriptor of machine device driver */
POS_INFO *pos; /* POS reg info of target adapter */
char *fname; /* Name of task to load */
uchar tasknum; /* Tasknumber to load task as */
{
uchar ros_stat[2]; /* Status returned by ROS */
FILE *dfh; /* Task file handle */
BUFFER_ADDRS bufs; /* Task's buffer addresses */
char parmbuf[8]; /* Used to get diag file size */
char taskhdbuf[TASK_HEADER_SIZE]; /* Used relocate task header */
uint numwritten, numread; /* Byte counts during load */
ushort start_seg; /* Segment on card to load task */
uchar primstat; /* Task's primary status byte */
uchar load_page; /* Page/off representation of */
uint load_offset; /* task's load segment */
uchar xferbuf[XFERSIZE]; /* Used to xfer data from task file */
/* to card */
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Open task file ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if ((dfh = fopen(fname,"rb")) == NULL)
return(E_FILE_OPEN);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Get task's primary status byte ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (getprimstat(fd, pos, tasknum, &primstat))
{
fclose(dfh);
return(E_READ_BUSMEM);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ If task is already loaded return error if tasknum > 0 ³
³ else reset the adapter and continue ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (primstat != 0x00)
{
if (tasknum != 0)
{
fclose(dfh);
return(E_TASK_ALREADY_LOADED);
}
else
{
if (reset(fd, pos))
{
fclose(dfh);
return(E_RESET);
}
}
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Get task's input, output and secondary status buffers ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (getbuffers(fd, pos, tasknum, &bufs))
{
fclose(dfh);
return(E_GET_BUFFERS);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Indicate task number to be loaded ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
parmbuf[0] = tasknum;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Get task file size ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (fread(&parmbuf[1],1,4,dfh) != 4)
{
fclose(dfh);
return(E_FILE_READ);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Issue Request Task Load Commmand to ROS ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (issuecmd(fd, pos, tasknum, REQUEST_TASK_LOAD, 1000, 5, parmbuf))
{
fclose(dfh);
return(E_ISSUECMD);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Wait for ROS to interrupt back ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (intwait(fd, pos, tasknum, 1000))
{
fclose(dfh);
return(E_NO_INTERRUPT);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Check ROS's return code from RTL Command ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (readmem(fd, pos, bufs.sspage, bufs.ssoffset, 1, ros_stat))
{
fclose(dfh);
return(E_READ_BUSMEM);
}
if (ros_stat[0])
{
fclose(dfh);
return(E_RTL_CMD);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Read starting segment from ROS input buffer ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (readmem(fd, pos, bufs.inpage, bufs.inoffset, 2, &start_seg))
{
fclose(dfh);
return(E_READ_BUSMEM);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Reset file ptr to beginning of task file ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
fseek(dfh, 0L, 0);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Read task header ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
numread = fread(taskhdbuf,1,TASK_HEADER_SIZE,dfh);
if (numread < TASK_HEADER_SIZE)
{
fclose(dfh);
return(E_FILE_READ);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Do relocation on task header ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
TASKNUM(taskhdbuf) = tasknum;
CMDSEG(taskhdbuf) = start_seg;
INITSEG(taskhdbuf) = start_seg;
DATASEG(taskhdbuf) = start_seg;
STACKSEG(taskhdbuf) = start_seg;
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Get page and offset of task start address ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
swap_bytes(&start_seg);
load_page = (start_seg << 4)/pos->win_size;
load_offset = (start_seg << 4) - (load_page * pos->win_size);
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Write task header to card ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (writemem(fd, pos, load_page, load_offset, TASK_HEADER_SIZE, taskhdbuf))
{
fclose(dfh);
return(E_WRITE_BUSMEM);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Write rest of task to card ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
numwritten = TASK_HEADER_SIZE;
load_offset += numwritten;
while (1)
{
numread = fread(xferbuf,1,128,dfh);
if (numread > 0)
{
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³Adjust page and offset if we cross a page boundary ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (load_offset >= pos->win_size)
{
load_offset -= pos->win_size;
++load_page;
}
if (writemem(fd, pos, load_page, load_offset, numread, xferbuf))
{
fclose(dfh);
return(E_WRITE_BUSMEM);
}
numwritten += numread;
load_offset += numread;
}
else
break;
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Verify the right number of bytes were written to card ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
swap_bytes((ushort *) (parmbuf+1));
if (*((ushort *) (parmbuf+1)) != numwritten)
{
fclose(dfh);
return(E_TASK_HEADER);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Issue Start Task Command to ROS ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (issuecmd(fd, pos, tasknum, START_TASK, 1000, 1, &tasknum))
{
fclose(dfh);
return(E_ISSUECMD);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Wait for started task to interrupt back ³
³ NOTE: no need to check command status in ³
³ secondary status buffer because if the ³
³ command is executed successfully the task ³
³ will interrupt back ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
if (intwait(fd, pos, tasknum, 1000))
{
fclose(dfh);
return(E_NO_INTERRUPT);
}
/*ÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
³ Indicate successful load ³
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ*/
fclose(dfh);
return(SUCCESS);
}