1747 lines
42 KiB
C
1747 lines
42 KiB
C
|
||
/* dbScan.c */
|
||
/* share/src/db $Id$ */
|
||
|
||
/*
|
||
* dbScan.c - Database scanners
|
||
*
|
||
* tasks and subroutines to scan the database
|
||
*
|
||
* Author: Bob Dalesio
|
||
* Date: 11-30-88
|
||
* @(#)dbscan.c 1.1S
|
||
*
|
||
* Control System Software for the GTA Project
|
||
*
|
||
* Copyright 1988, 1989, the Regents of the University of California.
|
||
*
|
||
* This software was produced under a U.S. Government contract
|
||
* (W-7405-ENG-36) at the Los Alamos National Laboratory, which is
|
||
* operated by the University of California for the U.S. Department
|
||
* of Energy.
|
||
*
|
||
* Developed by the Controls and Automation Group (AT-8)
|
||
* Accelerator Technology Division
|
||
* Los Alamos National Laboratory
|
||
*
|
||
* Direct inqueries to:
|
||
* Bob Dalesio, AT-8, Mail Stop H820
|
||
* Los Alamos National Laboratory
|
||
* Los Alamos, New Mexico 87545
|
||
* Phone: (505) 667-3414
|
||
* E-mail: dalesio@luke.lanl.gov
|
||
*
|
||
* Modification Log:
|
||
* -----------------
|
||
* .01 02-24-89 lrd modified for vxWorks 4.0
|
||
* changed spawn to taskSpawn and changed args
|
||
* .02 02-24-89 lrd moved task info into task_params.h
|
||
* linked to vw for vx include files
|
||
* .03 02-28-89 lrd added check in build_scan_lists to verify the
|
||
* database section is loaded
|
||
* .04 03-14-89 lrd change task id's to int
|
||
* .05 03-23-89 lrd add restart logic
|
||
* .06 03-27-89 lrd modified to use the dbcommon structure
|
||
* deleted subroutine set_alarm
|
||
* .07 04-05-89 lrd added flag to signal drivers when we're ready to
|
||
* accept events
|
||
* .08 05-03-89 lrd removed process mask from dbProcess calls
|
||
* .09 05-25-89 lrd added support for the PID record
|
||
* .10 06-06-89 lrd added support for the SEL record
|
||
* .11 06-28-89 lrd only give undefined event msg on the first
|
||
* occurance of the event - keep a list of the
|
||
* undefined ones
|
||
* .10 07-21-89 lrd added support for the COMPRESS record
|
||
* .11 01-25-90 lrd added support for SUB records
|
||
* .12 04-05-90 lrd added the momentary output task
|
||
* .13 05-22-89 mrk periodic scan now scans at correct rate
|
||
* .14 08-08-90 lrd removed T_AI from initialization at start up
|
||
* only outputs need to be read at initialization
|
||
* .15 08-30-90 lrd renamed the interrupt scanner wakeup from
|
||
* intr_event_poster to io_scanner_wakeup
|
||
* .16 09-14-90 mrk changed for new record/device support
|
||
*/
|
||
|
||
/*
|
||
* Code Portions:
|
||
*
|
||
* periodicScanTask Task which processes the periodic records
|
||
* ioEventTask Task which processes records on I/O interrupt
|
||
* eventTask Task which processes records on global events
|
||
* wdScanTask Task which restarts other tasks when suspended
|
||
* momentaryTask Task that turns off momentary outputs
|
||
* scan_init Build the scan lists and start the tasks
|
||
* remove_scan_tasks Delete scan tasks, free any malloc'd memory
|
||
* args
|
||
* tasks flags which tasks to remove
|
||
* build_scan_lists Looks through database and builds scan lists
|
||
* args
|
||
* lists flags which lists to build
|
||
* intialize_ring_buffers Initializes the ring buffers for the events
|
||
* args
|
||
* lists flags which ring buffers to initialize
|
||
* start_scan_tasks Start the scan tasks
|
||
* args
|
||
* tasks flags which scan tasks to start
|
||
* add_to_scan_list Adds an entry to a scan list
|
||
* args
|
||
* paddr pointer to this record
|
||
* lists which lists to build
|
||
* add_to_periodic_list Add an entry to the periodic scan list
|
||
* args
|
||
* paddr pointer to this record
|
||
* phase phase on which this record is scanned
|
||
* list_index which periodic list to place this record on
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* add_to_io_event_list Add an entry to the I/O event list
|
||
* args
|
||
* paddr pointer to this record
|
||
* phase phase on which this record is scanned
|
||
* io_type I/O type of this record
|
||
* card_type card type of this records input
|
||
* card_number card number of this records input
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* add_to_event_list Add an entry to the global event scanner
|
||
* args
|
||
* paddr pointer to this record
|
||
* phase phase on which this record is scanned
|
||
* event event on which this record will be scanned
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* delete_from_scan_list Delete an entry from a scan list
|
||
* args
|
||
* paddr pointer to this record
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
*
|
||
* delete_from_periodic_list Delete an entry from the periodic scan list
|
||
* args
|
||
* paddr pointer to this record
|
||
* list_index which periodic list to remove this record from
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* delete_from_io_event_list Delete an entry from the I/O event list
|
||
* args
|
||
* paddr pointer to this record
|
||
* phase phase on which this record is scanned
|
||
* io_type i/o type of this record
|
||
* card_type type of this records io card
|
||
* card_number card number of this record
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* delete_from_event_list Delete an entry from the global event list
|
||
* args
|
||
* paddr pointer to this record
|
||
* phase phase on which this record is scanned
|
||
* event event on which this record is scanned
|
||
* returns
|
||
* 0 successful
|
||
* -1 failed
|
||
* get_io_info get io_type,card_type,card_number
|
||
* args
|
||
* paddr
|
||
* &pio_type
|
||
* &card_type
|
||
* &card_number
|
||
* print_lists Prints the periodic scan lists
|
||
* print_io_event_lists Print the I/O event lists
|
||
* print_event_lists Print the event lists
|
||
*
|
||
* io_scanner_wakeup Post an I/O event
|
||
* args
|
||
* io_type io type from which the event has come
|
||
* card_type card type from which the event has come
|
||
* card_number card number from which the event has come
|
||
}
|
||
* post_event Post an event
|
||
* args
|
||
* event event number
|
||
*/
|
||
|
||
#include <vxWorks.h>
|
||
#include <types.h>
|
||
#include <sysLib.h>
|
||
#include <semLib.h> /* library for semaphore support */
|
||
#include <rngLib.h> /* library for ring buffer support */
|
||
|
||
#include <dbDefs.h>
|
||
#include <alarm.h>
|
||
#include <dbAccess.h>
|
||
#include <dbCommon.h>
|
||
#include <dbRecords.h>
|
||
#include <devSup.h>
|
||
#include <link.h>
|
||
#include <interruptEvent.h>
|
||
#include <taskParams.h>
|
||
#include <module_types.h>
|
||
|
||
|
||
|
||
typedef unsigned long TIME;
|
||
|
||
/* number of addr records in each set (malloc'ed at a time) */
|
||
#define NUM_RECS_PER_SET 100
|
||
#define NUM_SETS 4
|
||
|
||
/* db address struct: will contain the scan lists for all tasks */
|
||
struct scan_list{
|
||
unsigned short lock;
|
||
unsigned short scan_type;
|
||
unsigned short num_records;
|
||
unsigned short num_scan;
|
||
unsigned short scan_index;
|
||
unsigned short set;
|
||
unsigned short index;
|
||
unsigned int diagnostic;
|
||
struct scan_element *pscan;
|
||
struct scan_element *psets[NUM_SETS];
|
||
};
|
||
/* scan types */
|
||
/* These must match the GBL_SCAN choices in choiceGbl.ascii */
|
||
#define PASSIVE 0
|
||
#define P2SECOND 1
|
||
#define PSECOND 2
|
||
#define PHALFSECOND 3
|
||
#define PFIFTHSECOND 4
|
||
#define PTENTHSECOND 5
|
||
#define E_IO_INTERRUPT 6
|
||
#define E_EXTERNAL 7
|
||
|
||
#define SL2SECOND 0
|
||
#define SLSECOND 1
|
||
#define SLHALFSECOND 2
|
||
#define SLFIFTHSECOND 3
|
||
#define SLTENTHSECOND 4
|
||
#define NUM_LISTS (SLTENTHSECOND+1)
|
||
|
||
struct scan_element{
|
||
struct dbAddr dbAddr;
|
||
short phase;
|
||
};
|
||
|
||
#define PERIOD_BASE_RATE 6 /* 60 ticks per second */
|
||
|
||
/* I/O event driven scanner information */
|
||
|
||
#define IO_EVENT_PRIORITY 99
|
||
#define MAX_IO_EVENTS 10
|
||
#define MAX_IO_EVENT_CHANS 32
|
||
struct io_event_list{
|
||
short lock;
|
||
short defined;
|
||
short io_type;
|
||
short card_type;
|
||
short card_number;
|
||
short number_defined;
|
||
struct scan_element element[MAX_IO_EVENT_CHANS];
|
||
};
|
||
|
||
|
||
/* Event driven scanner information */
|
||
#define MAX_EVENTS 100
|
||
#define MAX_EVENT_CHANS 10
|
||
struct event_list{
|
||
short lock;
|
||
short defined;
|
||
short event_number;
|
||
short number_defined;
|
||
struct scan_element element[MAX_EVENT_CHANS];
|
||
};
|
||
|
||
|
||
|
||
/* initialization field in database records */
|
||
#define ARCH_INIT 2 /* first archive msg sent */
|
||
|
||
|
||
|
||
#define IO_EVENT 0x01
|
||
#define EVENT 0x02
|
||
#define PERIODIC 0x04
|
||
#define WDSCAN 0x08
|
||
#define MOMENTARY 0x10
|
||
|
||
int fd; /* used for the print list diagnostics */
|
||
|
||
/* link to the interrupable table from module_types.h */
|
||
extern short *pinterruptable[];
|
||
|
||
/* PERIODIC SCANNER GLOBALS */
|
||
/* periodic scan lists */
|
||
static struct scan_list lists[NUM_LISTS];
|
||
|
||
/* number of periods in each scan list */
|
||
static short periods_to_complete[] = {20,10,5,2,1};
|
||
|
||
static int periodicScanTaskId = 0;
|
||
|
||
|
||
/* I/O EVENT GLOBALS */
|
||
/* I/O event scan list */
|
||
static struct io_event_list io_event_lists[MAX_IO_EVENTS];
|
||
static struct io_event_list io_events_undefined[MAX_IO_EVENTS];
|
||
|
||
/* semaphore on which the I/O scan task waits */
|
||
static SEMAPHORE ioEventSem;
|
||
|
||
/* ring buffer into which the drivers place the events which occured */
|
||
static RING_ID ioEventQ;
|
||
|
||
static int ioEventTaskId = 0;
|
||
|
||
|
||
/* EVENT GLOBALS */
|
||
/* Event scan list */
|
||
static struct event_list event_lists[MAX_EVENTS];
|
||
|
||
/* semaphore on which the I/O scan task waits */
|
||
static SEMAPHORE eventSem;
|
||
|
||
/* ring buffer into which the drivers place the events which occured */
|
||
static RING_ID eventQ;
|
||
|
||
static int eventTaskId = 0;
|
||
|
||
|
||
/* WATCHDOG GLOBALS */
|
||
static int wdScanTaskId = 0;
|
||
static int wdScanOff = 0;
|
||
|
||
|
||
/* MOMENTARY GLOBALS */
|
||
/* semaphore on which the momentary output task waits */
|
||
SEMAPHORE momentarySem;
|
||
|
||
/* ring buffer into which the drivers place the binary outputs to zero */
|
||
RING_ID momentaryQ;
|
||
|
||
static int momentaryTaskId = 0;
|
||
extern long masks[]; /* masks for bit numbers */
|
||
|
||
/* flag to the drivers that they can start to send events to the event tasks */
|
||
short wakeup_init;
|
||
|
||
|
||
/*
|
||
* periodicScanTask
|
||
*
|
||
* scan all periodic scan lists
|
||
*/
|
||
periodicScanTask()
|
||
{
|
||
long start_time,delay;
|
||
register short list,scan;
|
||
register struct scan_list *plist;
|
||
short disableListScan[NUM_LISTS];
|
||
short periodsComplete[NUM_LISTS];
|
||
int i;
|
||
|
||
for(i=0; i < NUM_LISTS; i++){
|
||
periodsComplete[i] = 0;
|
||
disableListScan[i] = FALSE;
|
||
}
|
||
|
||
while(1){
|
||
|
||
/* get the start timex */
|
||
start_time = tickGet();
|
||
|
||
/* do for all records */
|
||
plist = &lists[0];
|
||
for (list = 0; list < NUM_LISTS; list++,plist++){
|
||
if (plist->num_records == 0){
|
||
continue;
|
||
}
|
||
|
||
/*enable processing list every periods_to_complete*/
|
||
if(periodsComplete[list] >= periods_to_complete[list] ){
|
||
disableListScan[list] = FALSE;
|
||
periodsComplete[list] = 0;
|
||
}
|
||
periodsComplete[list]++;
|
||
/*after processing all records in list , wait until enabled*/
|
||
if(disableListScan[list]) continue;
|
||
|
||
/* lock the list */
|
||
if (!vxTas(&plist->lock)) continue;
|
||
|
||
/* process each set in each scan list */
|
||
for (scan=0; scan < plist->num_scan; scan++){
|
||
struct dbAddr *paddr=&plist->pscan->dbAddr;
|
||
struct dbCommon *precord=
|
||
(struct dbCommon *)(paddr->precord);
|
||
|
||
/* process this record */
|
||
dbScanLock(precord);
|
||
if(!(precord->pact))dbProcess(paddr);
|
||
dbScanUnlock(precord);
|
||
|
||
/* get the pointer to the next record */
|
||
plist->scan_index++;
|
||
plist->index++;
|
||
if (plist->scan_index >= plist->num_records){
|
||
/*when all records in list processed*/
|
||
/* disable processing list*/
|
||
plist->index = 0;
|
||
plist->set = 0;
|
||
plist->scan_index = 0;
|
||
plist->pscan = plist->psets[0];
|
||
disableListScan[list] = TRUE;
|
||
}else if (plist->index >= NUM_RECS_PER_SET){
|
||
plist->index = 0;
|
||
plist->set++;
|
||
if (plist->set > NUM_SETS) plist->set = 0;
|
||
plist->pscan = plist->psets[plist->set];
|
||
}else{
|
||
plist->pscan++;
|
||
}
|
||
}
|
||
/* unlock it */
|
||
plist->lock = 0;
|
||
}
|
||
|
||
/* sleep until next tenth second */
|
||
delay = 60/10 - (tickGet() - start_time);
|
||
if (delay > 0)
|
||
taskDelay(delay);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ioEventTask
|
||
*
|
||
* interrupt event scanner
|
||
*/
|
||
ioEventTask()
|
||
{
|
||
struct intr_event intr_event;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
register struct io_event_list *pio_event_list;
|
||
register struct scan_element *pelement;
|
||
register struct intr_event *pintr_event = &intr_event;
|
||
|
||
/* forever */
|
||
FOREVER {
|
||
/* wait for somebody to wake us up */
|
||
semTake(&ioEventSem);
|
||
|
||
/* process requests in the command ring buffer */
|
||
while (rngBufGet(ioEventQ,pintr_event,INTR_EVENT_SZ) == INTR_EVENT_SZ){
|
||
/* find the event list */
|
||
event_index = 0;
|
||
pio_event_list = &io_event_lists[0];
|
||
found = FALSE;
|
||
while ((event_index < MAX_IO_EVENTS) && (!found)){
|
||
if ((pio_event_list->defined)
|
||
&& ((pio_event_list->io_type == pintr_event->io_type)
|
||
&& (pio_event_list->card_type == pintr_event->card_type)
|
||
&& (pio_event_list->card_number == pintr_event->card_number))){
|
||
found = TRUE;
|
||
}else{
|
||
pio_event_list++;
|
||
event_index++;
|
||
}
|
||
}
|
||
if (!found){
|
||
/* only give a message the first time an undefined */
|
||
/* event occurs */
|
||
pio_event_list = &io_events_undefined[0];
|
||
found = FALSE;
|
||
while ((event_index < MAX_IO_EVENTS) && (!found) && (pio_event_list->defined)){
|
||
if ((pio_event_list->io_type == pintr_event->io_type)
|
||
&& (pio_event_list->card_type == pintr_event->card_type)
|
||
&& (pio_event_list->card_number == pintr_event->card_number)){
|
||
found = TRUE;
|
||
}else{
|
||
pio_event_list++;
|
||
event_index++;
|
||
}
|
||
}
|
||
if (!found){
|
||
printf("no event list for iotype: %d card type: %d card number: %d\n",
|
||
pintr_event->io_type,
|
||
pintr_event->card_type,
|
||
pintr_event->card_number);
|
||
|
||
/* add this to the list */
|
||
if (pio_event_list->defined == 0){
|
||
pio_event_list->defined = 1;
|
||
pio_event_list->io_type = pintr_event->io_type;
|
||
pio_event_list->card_type = pintr_event->card_type;
|
||
pio_event_list->card_number = pintr_event->card_number;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
/* process each record in the scan list */
|
||
if (!vxTas(&pio_event_list->lock)) return; /* lock it */
|
||
index = 0;
|
||
pelement = &pio_event_list->element[0];
|
||
while (index < pio_event_list->number_defined){
|
||
struct dbAddr *paddr=&pelement->dbAddr;
|
||
struct dbCommon *precord=
|
||
(struct dbCommon *)(paddr->precord);
|
||
|
||
/* process this record */
|
||
dbScanLock(precord);
|
||
if(!(precord->pact))dbProcess(paddr);
|
||
dbScanUnlock(precord);
|
||
|
||
pelement++;
|
||
index++;
|
||
}
|
||
pio_event_list->lock = 0; /* unlock it */
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* eventTask
|
||
*
|
||
* event scanner
|
||
*/
|
||
eventTask()
|
||
{
|
||
short event;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
register struct event_list *pevent_list;
|
||
register struct scan_element *pelement;
|
||
|
||
/* forever */
|
||
FOREVER {
|
||
/* wait for somebody to wake us up */
|
||
semTake(&eventSem);
|
||
|
||
/* process requests in the command ring buffer */
|
||
while (rngBufGet(eventQ,&event,sizeof(short)) == sizeof(short)){
|
||
|
||
/* find the event list */
|
||
event_index = 0;
|
||
pevent_list = &event_lists[0];
|
||
found = FALSE;
|
||
while ((event_index < MAX_EVENTS) && (!found)){
|
||
if ((pevent_list->defined)
|
||
&& (pevent_list->event_number == event)){
|
||
found = TRUE;
|
||
}else{
|
||
pevent_list++;
|
||
event_index++;
|
||
}
|
||
}
|
||
if (!found){
|
||
printf("no event list for event: %d\n",event);
|
||
continue;
|
||
}
|
||
|
||
/* process each record in the scan list */
|
||
if (!vxTas(&pevent_list->lock)) return; /* lock it */
|
||
index = 0;
|
||
pelement = &pevent_list->element[0];
|
||
while (index < pevent_list->number_defined){
|
||
struct dbAddr *paddr=&pelement->dbAddr;
|
||
struct dbCommon *precord=
|
||
(struct dbCommon *)(paddr->precord);
|
||
|
||
/* process this record */
|
||
dbScanLock(precord);
|
||
if(!(precord->pact))dbProcess(paddr);
|
||
dbScanUnlock(precord);
|
||
|
||
pelement++;
|
||
index++;
|
||
}
|
||
pevent_list->lock = 0; /* unlock it */
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* wdScanTask
|
||
*
|
||
* watch dog scan task
|
||
*/
|
||
wdScanTask()
|
||
{
|
||
short lists;
|
||
|
||
while(1){
|
||
|
||
/* verify the watchdog is desired */
|
||
if (wdScanOff == 0){
|
||
lists = 0;
|
||
|
||
/* check the I/O Event Task */
|
||
if (taskIsSuspended(ioEventTaskId)){
|
||
printf("wdScanTask: Restarting ioEventTask\n");
|
||
lists |= IO_EVENT;
|
||
}
|
||
|
||
/* check the Event Task */
|
||
if (taskIsSuspended(eventTaskId)){
|
||
printf("wdScanTask: Restarting eventTask\n");
|
||
lists |= EVENT;
|
||
}
|
||
|
||
/* check the Periodic Scan Task */
|
||
if (taskIsSuspended(periodicScanTaskId)){
|
||
printf("wdScanTask: Restarting periodicScanTask\n");
|
||
lists |= PERIODIC;
|
||
}
|
||
|
||
/* if any are suspended - restart them */
|
||
if (lists){
|
||
/* remove scan tasks */
|
||
remove_scan_tasks(lists);
|
||
|
||
/* build the scan lists */
|
||
build_scan_lists(lists);
|
||
|
||
/* create event ring buffers */
|
||
initialize_ring_buffers(lists);
|
||
|
||
/* Spawn scanner tasks */
|
||
start_scan_tasks(lists);
|
||
}
|
||
}
|
||
|
||
/* sleep awhile */
|
||
taskDelay(WDSCAN_DELAY);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* Momentary output task
|
||
*
|
||
* turns off momentary outputs after expired time
|
||
*/
|
||
momentaryTask(){
|
||
struct intr_momentary intr_data;
|
||
|
||
FOREVER {
|
||
/* wait for somebody to wake us up */
|
||
semTake (&momentarySem);
|
||
|
||
/* process requests in the command ring buffer */
|
||
while (rngBufGet(momentaryQ,&intr_data,sizeof(intr_data))) {
|
||
(*intr_data.callback)(intr_data.arg);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* SCAN_INIT
|
||
*
|
||
* scanner intialization code:
|
||
* builds scan lists
|
||
* spawns the scan and watchdog tasks
|
||
*/
|
||
scan_init()
|
||
{
|
||
/* remove scan tasks */
|
||
remove_scan_tasks(EVENT | IO_EVENT | PERIODIC | MOMENTARY);
|
||
|
||
/* build the scan lists */
|
||
build_scan_lists(EVENT | IO_EVENT | PERIODIC);
|
||
|
||
/* create event ring buffers */
|
||
initialize_ring_buffers(EVENT | IO_EVENT | MOMENTARY);
|
||
|
||
/* Spawn scanner tasks */
|
||
start_scan_tasks(EVENT | IO_EVENT | PERIODIC | WDSCAN | MOMENTARY);
|
||
|
||
/* let drivers know we're ready to accept events */
|
||
wakeup_init = 1;
|
||
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* REMOVE_SCAN_TASKS
|
||
*
|
||
* remove any tasks which are in existance
|
||
*/
|
||
remove_scan_tasks(tasks)
|
||
register short tasks;
|
||
{
|
||
|
||
register short set;
|
||
register short list_index;
|
||
|
||
/* delete the ioEventTask if it is running */
|
||
if (tasks & IO_EVENT){
|
||
if (ioEventTaskId)
|
||
if (td(ioEventTaskId) != 0)
|
||
ioEventTaskId = 0;
|
||
|
||
/* initialize the IO event lists */
|
||
fill(io_event_lists,sizeof(struct event_list)*MAX_IO_EVENTS,0);
|
||
}
|
||
|
||
/* delete the eventTask if it is running */
|
||
if (tasks & EVENT){
|
||
if (eventTaskId)
|
||
if (td(eventTaskId) != 0)
|
||
eventTaskId = 0;
|
||
|
||
/* initialize the event lists */
|
||
fill(event_lists,sizeof(struct event_list)*MAX_EVENTS,0);
|
||
}
|
||
|
||
/* delete the momentaryTask if it is running */
|
||
if (tasks & MOMENTARY){
|
||
if (momentaryTaskId)
|
||
if (td(momentaryTaskId) != 0)
|
||
momentaryTaskId = 0;
|
||
}
|
||
|
||
/* delete the periodicScanTask if it is running */
|
||
if (tasks & PERIODIC){
|
||
if (periodicScanTaskId){
|
||
if (td(periodicScanTaskId) != 0)
|
||
periodicScanTaskId = 0;
|
||
for(list_index = 0; list_index < NUM_LISTS; list_index++){
|
||
for (set = 0; set < NUM_SETS; set++){
|
||
if (lists[list_index].psets[set]){
|
||
free(lists[list_index].psets[set]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/* initialize the scan lists */
|
||
fill(lists,sizeof(lists),0);
|
||
}
|
||
|
||
/* delete the watchdog scan task */
|
||
if (tasks & WDSCAN){
|
||
if (wdScanTaskId){
|
||
if (td(wdScanTaskId) != 0)
|
||
wdScanTaskId = 0;
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
/*
|
||
* BUILD_SCAN_LISTS
|
||
*
|
||
* build the specified scan lists
|
||
*/
|
||
build_scan_lists(lists)
|
||
register short lists;
|
||
{
|
||
struct dbAddr dbAddr; /* database address */
|
||
struct recLoc *precLoc;
|
||
struct dbCommon *precord; /* pointer to record */
|
||
long status;
|
||
int i,j;
|
||
|
||
if(dbRecords==NULL) {
|
||
errMessage(S_record_noRecords,
|
||
"Error detected in build_scan_lists");
|
||
exit(0);
|
||
}
|
||
/* look through all of the database records and place them on lists */
|
||
for (i=0; i<dbRecords->number; i++) {
|
||
if((precLoc=dbRecords->papRecLoc[i])==NULL) continue;
|
||
for(j=0, precord=(struct dbCommon*)(precLoc->pFirst);
|
||
j<precLoc->no_records;
|
||
j++, precord = (struct dbCommon *)
|
||
((char *)precord + precLoc->rec_size)) {
|
||
if(precord->name[0]==0) continue;
|
||
/* get database address from access routines */
|
||
if ((status=dbNameToAddr(precord->name,&dbAddr)) == 0){
|
||
/* add it to a scan list */
|
||
add_to_scan_list(&dbAddr,lists);
|
||
} else {
|
||
recGblDbaddrError(status,&dbAddr,
|
||
"build_scan_lists");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* INITIALIZE_RING_BUFFERS
|
||
*
|
||
* initialize the ring buffers for the event tasks
|
||
*/
|
||
initialize_ring_buffers(lists)
|
||
register short lists;
|
||
{
|
||
/* create the interrupt event ring buffer and semaphore */
|
||
if (lists & IO_EVENT){
|
||
/* clear it if it is created */
|
||
if (ioEventQ){
|
||
rngFlush(ioEventQ);
|
||
/* create it if it does not exist */
|
||
}else if ((ioEventQ = rngCreate(INTR_EVENT_SZ * MAX_EVENTS))
|
||
== (RING_ID)NULL){
|
||
panic ("scan_init: ioEventQ not created\n");
|
||
}
|
||
semInit(&ioEventSem);
|
||
}
|
||
|
||
/* create the event ring buffer and semaphore */
|
||
if (lists & EVENT){
|
||
/* clear it if it is created */
|
||
if (eventQ){
|
||
rngFlush(eventQ);
|
||
/* create it if it does not exist */
|
||
}else if ((eventQ = rngCreate(sizeof(short) * MAX_EVENTS))
|
||
== (RING_ID)NULL){
|
||
panic ("scan_init: eventQ not created\n");
|
||
}
|
||
semInit(&eventSem);
|
||
}
|
||
|
||
/* create the momentary ring buffer and semaphore */
|
||
if (lists & MOMENTARY){
|
||
/* clear it if it is created */
|
||
if (momentaryQ){
|
||
rngFlush(momentaryQ);
|
||
/* create it if it does not exist */
|
||
}else if ((momentaryQ = rngCreate(sizeof(struct intr_momentary) * MAX_EVENTS))
|
||
== (RING_ID)NULL){
|
||
panic ("scan_init: momentaryQ not created\n");
|
||
}
|
||
semInit(&momentarySem);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* START_SCAN_TASKS
|
||
*
|
||
* start the specified scan tasks
|
||
* parameters are from task_params.h
|
||
*/
|
||
start_scan_tasks(tasks)
|
||
register short tasks;
|
||
{
|
||
if (tasks & IO_EVENT){
|
||
ioEventTaskId =
|
||
taskSpawn(IOEVENTSCAN_NAME,
|
||
IOEVENTSCAN_PRI,
|
||
IOEVENTSCAN_OPT,
|
||
IOEVENTSCAN_STACK,
|
||
ioEventTask);
|
||
}
|
||
|
||
if (tasks & EVENT){
|
||
eventTaskId =
|
||
taskSpawn(EVENTSCAN_NAME,
|
||
EVENTSCAN_PRI,
|
||
EVENTSCAN_OPT,
|
||
EVENTSCAN_STACK,
|
||
eventTask);
|
||
}
|
||
|
||
if (tasks & PERIODIC){
|
||
periodicScanTaskId =
|
||
taskSpawn(PERIODSCAN_NAME,
|
||
PERIODSCAN_PRI,
|
||
PERIODSCAN_OPT,
|
||
PERIODSCAN_STACK,
|
||
periodicScanTask);
|
||
}
|
||
|
||
if (tasks & WDSCAN){
|
||
wdScanTaskId =
|
||
taskSpawn(WDSCAN_NAME,
|
||
WDSCAN_PRI,
|
||
WDSCAN_OPT,
|
||
WDSCAN_STACK,
|
||
wdScanTask);
|
||
}
|
||
|
||
if (tasks & MOMENTARY){
|
||
momentaryTaskId =
|
||
taskSpawn(MOMENTARY_NAME,
|
||
MOMENTARY_PRI,
|
||
MOMENTARY_OPT,
|
||
MOMENTARY_STACK,
|
||
momentaryTask);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* ADD_TO_SCAN_LIST
|
||
*
|
||
* add a new record's address to a scan list
|
||
*/
|
||
add_to_scan_list(paddr,lists)
|
||
register struct dbAddr *paddr;
|
||
register short lists;
|
||
{
|
||
struct dbCommon *precord= (struct dbCommon *)(paddr->precord);
|
||
short scan_type;
|
||
short phase;
|
||
short event;
|
||
register short status;
|
||
|
||
/* get the list on which this record belongs */
|
||
scan_type = precord->scan;
|
||
phase = precord->phas;
|
||
event = precord->evnt;
|
||
/* add to the periodic scan or the event list */
|
||
switch (scan_type){
|
||
case (PASSIVE):
|
||
break;
|
||
case (P2SECOND):
|
||
if (lists & PERIODIC)
|
||
status =
|
||
add_to_periodic_list(paddr,phase,SL2SECOND);
|
||
else
|
||
return;
|
||
break;
|
||
|
||
case (PSECOND):
|
||
if (lists & PERIODIC)
|
||
status =
|
||
add_to_periodic_list(paddr,phase,SLSECOND);
|
||
else
|
||
return;
|
||
break;
|
||
case (PHALFSECOND):
|
||
if (lists & PERIODIC)
|
||
status =
|
||
add_to_periodic_list(paddr,phase,SLHALFSECOND);
|
||
else
|
||
return;
|
||
break;
|
||
case (PFIFTHSECOND):
|
||
if (lists & PERIODIC)
|
||
status =
|
||
add_to_periodic_list(paddr,phase,SLFIFTHSECOND);
|
||
else
|
||
return;
|
||
break;
|
||
case (PTENTHSECOND):
|
||
if (lists & PERIODIC)
|
||
status =
|
||
add_to_periodic_list(paddr,phase,SLTENTHSECOND);
|
||
else
|
||
return;
|
||
break;
|
||
case (E_IO_INTERRUPT):
|
||
if (lists & IO_EVENT) {
|
||
short io_type;
|
||
short card_type;
|
||
short card_number;
|
||
|
||
status=get_io_info(paddr,&io_type,
|
||
&card_type,&card_number);
|
||
if(status!=0) {
|
||
recGblDbaddrError(status,paddr,
|
||
"dbScan(get_io_info)");
|
||
return;
|
||
}
|
||
status = add_to_io_event_list(paddr,phase,
|
||
io_type,card_type,card_number);
|
||
} else return;
|
||
break;
|
||
case (E_EXTERNAL):
|
||
if (lists & EVENT)
|
||
status =
|
||
add_to_event_list(paddr,phase,event);
|
||
else
|
||
return;
|
||
break;
|
||
default:
|
||
return;
|
||
}
|
||
|
||
if (status < 0){
|
||
((struct dbCommon *)(paddr->precord))->stat = SCAN_ALARM;
|
||
((struct dbCommon *)(paddr->precord))->sevr = MAJOR_ALARM;
|
||
}
|
||
return;
|
||
}
|
||
|
||
/*
|
||
* ADD_TO_PERIODIC_LIST
|
||
*
|
||
* add a new record's address to a periodic scan list
|
||
*/
|
||
static add_to_periodic_list(paddr,phase,list_index)
|
||
register struct dbAddr *paddr;
|
||
short phase;
|
||
short list_index;
|
||
{
|
||
register short set,index,found;
|
||
register struct scan_element *pspare_element;
|
||
register struct scan_element *ptest_element;
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&lists[list_index].lock)) return(-1); /* lock it */
|
||
|
||
/* determine if we need to create a new set on this scan list */
|
||
set = lists[list_index].num_records / NUM_RECS_PER_SET;
|
||
if ((lists[list_index].num_records % NUM_RECS_PER_SET) == 0){
|
||
if (set >= NUM_SETS){
|
||
lists[list_index].lock = 0; /* unlock it */
|
||
return(-1);
|
||
}
|
||
if ((lists[list_index].psets[set] =
|
||
(struct scan_element *)malloc(NUM_RECS_PER_SET*sizeof(struct scan_element))) == 0){
|
||
lists[list_index].lock = 0; /* unlock it */
|
||
return(-1);
|
||
}
|
||
fill(lists[list_index].psets[set],NUM_RECS_PER_SET*sizeof(struct scan_element),0);
|
||
}
|
||
|
||
/* pointer to the slot at the end of the scan list */
|
||
index = lists[list_index].num_records % NUM_RECS_PER_SET;
|
||
pspare_element = lists[list_index].psets[set];
|
||
pspare_element += index;
|
||
|
||
/* pointer to the last used slot in the scan list */
|
||
index--;
|
||
if (index < 0){
|
||
index = NUM_RECS_PER_SET - 1;
|
||
set--;
|
||
ptest_element = lists[list_index].psets[set];
|
||
ptest_element += index;
|
||
}else{
|
||
ptest_element = pspare_element - 1;
|
||
}
|
||
|
||
/* determine where this record belongs */
|
||
found = FALSE;
|
||
while(!found){
|
||
/* beginning of list or test record has higher or equal phase */
|
||
if ((set < 0) || (ptest_element->phase <= phase)){
|
||
/* put the new record into the spare space */
|
||
pspare_element->dbAddr = *paddr;
|
||
pspare_element->phase = phase;
|
||
found = TRUE;
|
||
/* move the tested record into the spare record space */
|
||
}else{
|
||
*pspare_element = *ptest_element;
|
||
pspare_element = ptest_element;
|
||
}
|
||
|
||
/* find the next test element */
|
||
index--;
|
||
if (index < 0){
|
||
index = NUM_RECS_PER_SET - 1;
|
||
set--;
|
||
ptest_element = lists[list_index].psets[set];
|
||
ptest_element += index;
|
||
}else{
|
||
ptest_element--;
|
||
}
|
||
}
|
||
|
||
/* adjust the list information */
|
||
lists[list_index].num_records++;
|
||
lists[list_index].num_scan =
|
||
(lists[list_index].num_records / periods_to_complete[list_index]) + 1;
|
||
lists[list_index].pscan = lists[list_index].psets[0];
|
||
lists[list_index].scan_index = 0;
|
||
lists[list_index].index = 0;
|
||
lists[list_index].set = 0;
|
||
|
||
/* unlock it */
|
||
lists[list_index].lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* ADD_TO_IO_EVENT_LIST
|
||
*
|
||
* add a new record's address to an interrupt event scan list
|
||
*/
|
||
static add_to_io_event_list(paddr,phase,io_type,card_type,card_number)
|
||
register struct dbAddr *paddr;
|
||
short phase;
|
||
short io_type;
|
||
short card_type;
|
||
short card_number;
|
||
{
|
||
struct io_event_list *pio_event_list;
|
||
struct scan_element *pelement;
|
||
struct scan_element *pspare;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
|
||
/* verify this card has an interrupt */
|
||
if (!pinterruptable[io_type][card_type])
|
||
return(-1);
|
||
|
||
/* is there a list for this iotype and card type */
|
||
pio_event_list = &io_event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_IO_EVENTS) && (!found)){
|
||
if ((pio_event_list->defined)
|
||
&& ((pio_event_list->io_type == io_type)
|
||
&& (pio_event_list->card_type == card_type)
|
||
&& (pio_event_list->card_number == card_number))){
|
||
found = TRUE;
|
||
}else{
|
||
pio_event_list++;
|
||
event_index++;
|
||
}
|
||
|
||
}
|
||
|
||
/* look for a spare list */
|
||
if (!found){
|
||
pio_event_list = &io_event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_IO_EVENTS) && (!found)){
|
||
if (!pio_event_list->defined){
|
||
found = TRUE;
|
||
}else{
|
||
pio_event_list++;
|
||
event_index++;
|
||
}
|
||
}
|
||
if (found){
|
||
pio_event_list->defined = TRUE;
|
||
pio_event_list->io_type = io_type;
|
||
pio_event_list->card_type = card_type;
|
||
pio_event_list->card_number = card_number;
|
||
}else{
|
||
return(-1);
|
||
}
|
||
}
|
||
|
||
/* check for available space */
|
||
if (pio_event_list->number_defined >= MAX_IO_EVENT_CHANS){
|
||
return(-1);
|
||
}
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&pio_event_list->lock)) return(-1);
|
||
|
||
/* add this record to the list */
|
||
if (pio_event_list->number_defined == 0){
|
||
pio_event_list->element[0].dbAddr = *paddr;
|
||
pio_event_list->element[0].phase = phase;
|
||
}else{
|
||
index = pio_event_list->number_defined;
|
||
pspare = &pio_event_list->element[index];
|
||
pelement = &pio_event_list->element[index-1];
|
||
while ((pelement->phase > phase) && (index > 0)){
|
||
*pspare = *pelement;
|
||
pelement--;
|
||
pspare--;
|
||
index--;
|
||
}
|
||
pspare->phase = phase;
|
||
pspare->dbAddr = *paddr;
|
||
}
|
||
pio_event_list->number_defined++;
|
||
|
||
/* unlock the list */
|
||
pio_event_list->lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* ADD_TO_EVENT_LIST
|
||
*
|
||
* add a new record's address to an event scan list
|
||
*/
|
||
static add_to_event_list(paddr,phase,event)
|
||
register struct dbAddr *paddr;
|
||
short phase;
|
||
short event;
|
||
{
|
||
struct event_list *pevent_list;
|
||
struct scan_element *pelement;
|
||
struct scan_element *pspare;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
|
||
/* is there a list for this event */
|
||
pevent_list = &event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_EVENTS) && (!found)){
|
||
if ((pevent_list->defined)
|
||
&& (pevent_list->event_number == event)){
|
||
found = TRUE;
|
||
}else{
|
||
pevent_list++;
|
||
event_index++;
|
||
}
|
||
|
||
}
|
||
|
||
/* look for a spare list */
|
||
if (!found){
|
||
pevent_list = &event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_EVENTS) && (!found)){
|
||
if (!pevent_list->defined){
|
||
found = TRUE;
|
||
}else{
|
||
pevent_list++;
|
||
event_index++;
|
||
}
|
||
}
|
||
if (found){
|
||
pevent_list->defined = TRUE;
|
||
pevent_list->event_number = event;
|
||
}else{
|
||
return(-1);
|
||
}
|
||
}
|
||
|
||
/* check for available space */
|
||
if (pevent_list->number_defined >= MAX_EVENT_CHANS){
|
||
return(-1);
|
||
}
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&pevent_list->lock)) return(-1);
|
||
|
||
/* add this record to the list */
|
||
if (pevent_list->number_defined == 0){
|
||
pevent_list->element[0].dbAddr = *paddr;
|
||
pevent_list->element[0].phase = phase;
|
||
}else{
|
||
index = pevent_list->number_defined;
|
||
pspare = &pevent_list->element[index];
|
||
pelement = &pevent_list->element[index-1];
|
||
while ((pelement->phase > phase) && (index > 0)){
|
||
*pspare = *pelement;
|
||
pelement--;
|
||
pspare--;
|
||
index--;
|
||
}
|
||
pspare->phase = phase;
|
||
pspare->dbAddr = *paddr;
|
||
}
|
||
pevent_list->number_defined++;
|
||
|
||
/* unlock the list */
|
||
pevent_list->lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* DELETE_FROM_SCAN_LIST
|
||
*
|
||
* delete a record's address from a scan list
|
||
*/
|
||
delete_from_scan_list(paddr)
|
||
register struct dbAddr *paddr;
|
||
{
|
||
struct dbCommon *precord= (struct dbCommon *)(paddr->precord);
|
||
short scan_type;
|
||
short phase;
|
||
short event;
|
||
register short status;
|
||
|
||
/* get the list on which this record belongs */
|
||
scan_type = precord->scan;
|
||
phase = precord->phas;
|
||
event = precord->evnt;
|
||
/* add to the periodic scan or the event list */
|
||
switch (scan_type){
|
||
case (PASSIVE):
|
||
return(-1);
|
||
case (P2SECOND):
|
||
return(delete_from_periodic_list(paddr,SL2SECOND));
|
||
case (PSECOND):
|
||
return(delete_from_periodic_list(paddr,SLSECOND));
|
||
case (PHALFSECOND):
|
||
return(delete_from_periodic_list(paddr,SLHALFSECOND));
|
||
case (PFIFTHSECOND):
|
||
return(delete_from_periodic_list(paddr,SLFIFTHSECOND));
|
||
case (PTENTHSECOND):
|
||
return(delete_from_periodic_list(paddr,SLTENTHSECOND));
|
||
case (E_IO_INTERRUPT): {
|
||
short io_type;
|
||
short card_type;
|
||
short card_number;
|
||
|
||
status=get_io_info(paddr,&io_type,
|
||
&card_type,&card_number);
|
||
if(status!=0) {
|
||
recGblDbaddrError(status,paddr,
|
||
"dbScan(get_io_info)");
|
||
return;
|
||
}
|
||
return(delete_from_io_event_list(paddr,phase,io_type,
|
||
card_type,card_number));
|
||
}
|
||
case (E_EXTERNAL):
|
||
return(delete_from_event_list(paddr,phase,event));
|
||
default:
|
||
return(-1);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* DELETE_FROM_PERIODIC_LIST
|
||
*
|
||
* delete a record's address from a periodic scan list
|
||
*/
|
||
static delete_from_periodic_list(paddr,list_index)
|
||
register struct dbAddr *paddr;
|
||
short list_index;
|
||
{
|
||
register short set,index,found;
|
||
register struct scan_element *pelement;
|
||
register struct scan_element *pnext_element;
|
||
short end_of_list;
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&lists[list_index].lock)) return(-1);
|
||
|
||
/* find this record */
|
||
found = FALSE;
|
||
set = 0;
|
||
index = 0;
|
||
end_of_list = FALSE;
|
||
pelement = lists[list_index].psets[set];
|
||
while((!found) && (!end_of_list)){
|
||
if (pelement->dbAddr.precord == paddr->precord){
|
||
found = TRUE;
|
||
}else{
|
||
index++;
|
||
if (index >= NUM_RECS_PER_SET){
|
||
index = 0;
|
||
set++;
|
||
pelement = lists[list_index].psets[set];
|
||
if (set >= NUM_SETS) end_of_list = TRUE;
|
||
}else{
|
||
pelement++;
|
||
}
|
||
}
|
||
}
|
||
if (!found){
|
||
lists[list_index].lock = 0; /* unlock it */
|
||
return(-1);
|
||
}
|
||
|
||
/* move each record in the scan list down */
|
||
while (!end_of_list){
|
||
index++;
|
||
if (index >= NUM_RECS_PER_SET){
|
||
index = 0;
|
||
set++;
|
||
if (set >= NUM_SETS){
|
||
end_of_list = TRUE;
|
||
}else{
|
||
pnext_element=lists[list_index].psets[set];
|
||
}
|
||
}else{
|
||
pnext_element = pelement + 1;
|
||
}
|
||
|
||
if (!end_of_list){
|
||
*pelement = *pnext_element;
|
||
pelement = pnext_element;
|
||
}else{
|
||
fill(pelement,sizeof(struct scan_element),0);
|
||
}
|
||
}
|
||
|
||
/* adjust the list information */
|
||
lists[list_index].num_records--;
|
||
lists[list_index].num_scan =
|
||
(lists[list_index].num_records/periods_to_complete[list_index])+1;
|
||
|
||
/* determine if we need to free the memory for a set */
|
||
if ((lists[list_index].num_records % NUM_RECS_PER_SET) == 0){
|
||
set = lists[list_index].num_records / NUM_RECS_PER_SET;
|
||
free(lists[list_index].psets[set]);
|
||
lists[list_index].psets[set] = 0;
|
||
}
|
||
|
||
/* unlock the scan list */
|
||
lists[list_index].lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* DELETE_FROM_IO_EVENT_LIST
|
||
*
|
||
* delete a record's address to an interrupt event scan list
|
||
*/
|
||
static delete_from_io_event_list(paddr,phase,io_type,card_type,card_number)
|
||
register struct dbAddr *paddr;
|
||
short phase;
|
||
short io_type;
|
||
short card_type;
|
||
short card_number;
|
||
{
|
||
struct io_event_list *pio_event_list;
|
||
struct scan_element *pelement;
|
||
struct scan_element *pnext_element;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
|
||
/* is there a list for this iotype,card type and card number */
|
||
pio_event_list = &io_event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_IO_EVENTS) && (!found)){
|
||
if ((pio_event_list->defined)
|
||
&& ((pio_event_list->io_type == io_type)
|
||
&& (pio_event_list->card_type == card_type)
|
||
&& (pio_event_list->card_number == card_number))){
|
||
found = TRUE;
|
||
}else{
|
||
pio_event_list++;
|
||
event_index++;
|
||
}
|
||
|
||
}
|
||
if (!found) return(-1);
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&pio_event_list->lock)) return(-1);
|
||
|
||
/* find this record in the list */
|
||
index = 0;
|
||
pelement = &pio_event_list->element[0];
|
||
found = FALSE;
|
||
while ((!found)
|
||
&& (index < pio_event_list->number_defined)){
|
||
if (pelement->dbAddr.precord == paddr->precord){
|
||
found = TRUE;
|
||
}else{
|
||
pelement++;
|
||
index++;
|
||
}
|
||
}
|
||
if (!found){
|
||
pio_event_list->lock = 0; /* unlock it */
|
||
return(-1);
|
||
}
|
||
|
||
/* delete this record from the list */
|
||
index++;
|
||
pnext_element = &pio_event_list->element[index];
|
||
while (index < pio_event_list->number_defined) {
|
||
*pelement = *pnext_element;
|
||
pelement++;
|
||
pnext_element++;
|
||
index++;
|
||
}
|
||
fill(pelement,sizeof(struct scan_element),0);
|
||
pio_event_list->number_defined--;
|
||
|
||
/* if this is the last scan element in the list - free it */
|
||
if (pio_event_list->number_defined == 0){
|
||
pio_event_list->defined = FALSE;
|
||
pio_event_list->io_type = 0;
|
||
pio_event_list->card_type = 0;
|
||
pio_event_list->card_number = 0;
|
||
}
|
||
|
||
/* unlock the list */
|
||
pio_event_list->lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* DELETE_FROM_EVENT_LIST
|
||
*
|
||
* delete a record's address to an event scan list
|
||
*/
|
||
static delete_from_event_list(paddr,phase,event)
|
||
register struct dbAddr *paddr;
|
||
short phase;
|
||
short event;
|
||
{
|
||
struct event_list *pevent_list;
|
||
struct scan_element *pelement;
|
||
struct scan_element *pnext_element;
|
||
register short event_index;
|
||
register short index;
|
||
register short found;
|
||
|
||
/* is there a list for this iotype,card type and card number */
|
||
pevent_list = &event_lists[0];
|
||
event_index = 0;
|
||
found = FALSE;
|
||
while ((event_index < MAX_EVENTS) && (!found)){
|
||
if ((pevent_list->defined)
|
||
&& (pevent_list->event_number == event)){
|
||
found = TRUE;
|
||
}else{
|
||
pevent_list++;
|
||
event_index++;
|
||
}
|
||
|
||
}
|
||
if (!found) return(-1);
|
||
|
||
/* lock the list during modification */
|
||
if (!vxTas(&pevent_list->lock)) return(-1);
|
||
|
||
/* find this record in the list */
|
||
index = 0;
|
||
pelement = &pevent_list->element[0];
|
||
found = FALSE;
|
||
while ((!found)
|
||
&& (index < pevent_list->number_defined)){
|
||
if (pelement->dbAddr.precord == paddr->precord){
|
||
found = TRUE;
|
||
}else{
|
||
pelement++;
|
||
index++;
|
||
}
|
||
}
|
||
if (!found){
|
||
pevent_list->lock = 0; /* unlock it */
|
||
return(-1);
|
||
}
|
||
|
||
/* delete this record from the list */
|
||
index++;
|
||
pnext_element = &pevent_list->element[index];
|
||
while (index < pevent_list->number_defined) {
|
||
*pelement = *pnext_element;
|
||
pelement++;
|
||
pnext_element++;
|
||
index++;
|
||
}
|
||
fill(pelement,sizeof(struct scan_element),0);
|
||
pevent_list->number_defined--;
|
||
|
||
/* if this is the last scan element in the list - free it */
|
||
if (pevent_list->number_defined == 0){
|
||
pevent_list->defined = FALSE;
|
||
pevent_list->event_number = 0;
|
||
}
|
||
|
||
/* unlock the list */
|
||
pevent_list->lock = 0;
|
||
|
||
return(0);
|
||
}
|
||
|
||
/*
|
||
* GET_IO INFO
|
||
*
|
||
* get the io_type,card_type, and card_number
|
||
*/
|
||
static long get_io_info(paddr,pio_type,pcard_type,pcard_number)
|
||
struct dbAddr *paddr;
|
||
short *pio_type;
|
||
short *pcard_type;
|
||
short *pcard_number;
|
||
{
|
||
struct dbCommon *precord=(struct dbCommon *)(paddr->precord);
|
||
long status;
|
||
|
||
if((precord->dset == NULL) ||(precord->dset->get_ioint_info == NULL ))
|
||
return(S_dev_noDevSup);
|
||
status=(*precord->dset->get_ioint_info)
|
||
(paddr,pio_type,pcard_type,pcard_number);
|
||
return(status);
|
||
}
|
||
|
||
/*
|
||
* PRINT_LIST
|
||
*
|
||
* print the scan lists
|
||
*/
|
||
print_list()
|
||
{
|
||
struct scan_element *pelement;
|
||
struct scan_list *plist;
|
||
register short set,num_records,index;
|
||
short list;
|
||
char input[5];
|
||
|
||
fd = fioStdIn();
|
||
|
||
/* print each scan list */
|
||
printf("\n");
|
||
plist = &lists[0];
|
||
for (list = 0; list < NUM_LISTS; list++,plist++){
|
||
if (plist->num_records == 0){
|
||
printf("list %d is empty\n",list);
|
||
continue;
|
||
}
|
||
if (plist->num_records >= NUM_RECS_PER_SET * NUM_SETS){
|
||
printf("list %d is full\n",list);
|
||
}else{
|
||
printf("list %d has %d entries\n",list,plist->num_records);
|
||
}
|
||
|
||
/* print each set in each scan list */
|
||
num_records = 0;
|
||
for (set=0; (set<NUM_SETS) && (num_records<plist->num_records); set++){
|
||
printf("\tset %d\n",set);
|
||
|
||
/* print each element in each set */
|
||
pelement = plist->psets[set];
|
||
for (index=0; (index<NUM_RECS_PER_SET) && (num_records<plist->num_records); index++,pelement++){
|
||
num_records++;
|
||
if ((pelement->dbAddr.precord[0] >= 'A') && (pelement->dbAddr.precord[0] <= 'z'))
|
||
printf("\t\t%s\n",pelement->dbAddr.precord);
|
||
else
|
||
printf("\t\tnot printable\n");
|
||
}
|
||
}
|
||
|
||
/* wait for a character to print the next set */
|
||
read(fd,input,1);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* PRINT_IO_EVENT_LISTS
|
||
*
|
||
* print the io event lists
|
||
*/
|
||
print_io_event_lists()
|
||
{
|
||
struct io_event_list *plist;
|
||
register short set,num_records,index;
|
||
short list;
|
||
char input[5];
|
||
struct scan_element *pelement;
|
||
|
||
fd = fioStdIn();
|
||
|
||
/* print each scan list */
|
||
printf("\n");
|
||
plist = &io_event_lists[0];
|
||
for (list = 0; list < MAX_IO_EVENTS; list++,plist++){
|
||
if (plist->defined == 0){
|
||
printf("event list %d is unused\n",list);
|
||
continue;
|
||
}
|
||
if (plist->number_defined >= MAX_IO_EVENT_CHANS){
|
||
printf("event list %d is full\n",list);
|
||
printf("\tio type: %d card type: %d card number: %d\n",
|
||
plist->io_type,plist->card_type,plist->card_number);
|
||
}else{
|
||
printf("event list %d has %d entries\n",list,plist->number_defined);
|
||
printf("\tio type: %d card type: %d card number: %d\n",
|
||
plist->io_type,plist->card_type,plist->card_number);
|
||
}
|
||
|
||
/* print each set in each scan list */
|
||
num_records = 0;
|
||
pelement = &plist->element[0];
|
||
for (index=0; (index<MAX_IO_EVENT_CHANS) && (num_records<plist->number_defined); index++,pelement++){
|
||
num_records++;
|
||
if ((pelement->dbAddr.precord[0] >= 'A') && (pelement->dbAddr.precord[0] <= 'z'))
|
||
printf("\t\t%s\n",pelement->dbAddr.precord);
|
||
else
|
||
printf("\t\tnot printable\n");
|
||
}
|
||
|
||
/* wait for a character to print the next set */
|
||
read(fd,input,1);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* PRINT_EVENT_LISTS
|
||
*
|
||
* print the event lists
|
||
*/
|
||
print_event_lists()
|
||
{
|
||
struct event_list *plist;
|
||
register short set,num_records,index;
|
||
short list;
|
||
char input[5];
|
||
struct scan_element *pelement;
|
||
|
||
fd = fioStdIn();
|
||
|
||
/* print each scan list */
|
||
printf("\n");
|
||
plist = &event_lists[0];
|
||
for (list = 0; list < MAX_EVENTS; list++,plist++){
|
||
if (plist->defined == 0){
|
||
printf("event list %d is unused\n",list);
|
||
continue;
|
||
}
|
||
if (plist->number_defined >= MAX_EVENT_CHANS){
|
||
printf("event list %d is full\n",list);
|
||
printf("\tevent: %d\n",plist->event_number);
|
||
}else{
|
||
printf("event list %d has %d entries\n",list,plist->number_defined);
|
||
printf("\tevent: %d\n",plist->event_number);
|
||
}
|
||
|
||
/* print each set in each scan list */
|
||
num_records = 0;
|
||
pelement = &plist->element[0];
|
||
for (index=0; (index<MAX_EVENT_CHANS) && (num_records<plist->number_defined); index++,pelement++){
|
||
num_records++;
|
||
if ((pelement->dbAddr.precord[0] >= 'A') && (pelement->dbAddr.precord[0] <= 'z'))
|
||
printf("\t\t%s\n",pelement->dbAddr.precord);
|
||
else
|
||
printf("\t\tnot printable\n");
|
||
}
|
||
|
||
/* wait for a character to print the next set */
|
||
read(fd,input,1);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* IO_SCANNER_WAKEUP
|
||
*
|
||
* wake up the I/O interrupt event scanner
|
||
*/
|
||
io_scanner_wakeup(io_type,card_type,card_number)
|
||
short io_type,card_type,card_number;
|
||
{
|
||
struct intr_event intr_event;
|
||
|
||
if (wakeup_init != 1) return; /* not awake yet */
|
||
intr_event.io_type = io_type;
|
||
intr_event.card_type = card_type;
|
||
intr_event.card_number = card_number;
|
||
|
||
rngBufPut(ioEventQ,&intr_event,INTR_EVENT_SZ);
|
||
semGive(&ioEventSem);
|
||
}
|
||
|
||
/*
|
||
* POST_EVENT
|
||
*
|
||
* wake up the event scanner
|
||
*/
|
||
post_event(event_number)
|
||
short event_number;
|
||
{
|
||
if (wakeup_init != 1) return; /* not awake yet */
|
||
/* logMsg("Post Events\n"); */
|
||
rngBufPut(eventQ,&event_number,sizeof(short));
|
||
semGive(&eventSem);
|
||
}
|
||
|
||
|