Gå til innhold

Interupt. Program som fanger signal frå ekstern kilde


Anbefalte innlegg

Eg har fått i oppgåva å laga eit program som printer ut "Au" på skjermen når ein nokon trykker på ein knapp som er fysisk utanfor datamaskina. Knapper er kobla til datamaskina via ein av portane til maskina. Dette blir gjort med hjelp av eit kort av eit eller anna slag som eg ikkje husker namnet på (Lurer på om det var eit dcs kort, dersom det er noko som heter det)

Operativsystemet som blir brukt er Linux

 

Her er den første kodesnutten som eg skal gjera ferdig: (Fekk 2 "kodeskjelett" som me skulle gjera ferdig) Alle plasser der ### TODO er plassert inn er dei plassene eg skal skriva kode for å få programmet til å fungera.

Er eg inne på noko når det gjeld det første eg har gjort?

DCS_HW_IRQ = register_chrdev(dcsIRQ_majorID, "bigRedButton", (file_operations) *dcsIRQ_fops);

majorID er sett til 1 i dcsIRQ_driver.c programmet, dcsIRQ_fops er ein struct i det same programmet. "bigRedButton" er som eg forstod berre eit namn eg kan finna på sjølv.

 

Det er lurer mest på her er om nokon kan hjelpa meg å forstå kva eg skal setta inn for IRQ mask offset, har ikkje forstått heilt kva IRQ mask er for noko, og ivertfall ikkje kva kommandoar eg skal bruka:)

Eg har fleire filer som eg ikkje har limt inn her, eg held sikkert tilbake anna opplysningar også som dåkken treng for å forstå kva eg skal gjera, men det hadde vore flott å fått nokre tankar på kva eg kan gjera spesielt i dcsIRQ_defines.h fila mi for å få det til å fungera.

Namnet på programmet: "dcsIRQ_defines.h"

 

 

/**

* DEFINES - HEADER FILE

*

* dcsIRQ - driver for the DCS board to catch a HW interrupt.

* This interrupt is then signaled to a registerd user space program as signal.

*

* <pre>

******************************************************************************

**

** This file is property of and copyright by the Experimental Nuclear

** Physics Group, Dep. of Physics and Technology

** University of Bergen, Norway, 2005

**

** Permission to use, copy, modify and distribute this software and its

** documentation strictly for non-commercial purposes is hereby granted

** without fee, provided that the above copyright notice appears in all

** copies and that both the copyright notice and this permission notice

** appear in the supporting documentation. The authors make no claims

** about the suitability of this software for any purpose. It is

** provided "as is" without express or implied warranty.

**

******************************************************************************

* </pre>

*

* @author Sebastian Bablok <[email protected]>

*

* @date 03.12.2005

*/

 

#ifndef DCS_IRQ_DEFINES_H

#define DCS_IRQ_DEFINES_H

 

/**

* Define the type of the version (release, debug or development)

*/

#define RELEASETYPE "development"

 

 

 

/**

* Define for IRQ line

*/

/// ### TODO define the line of the IRQ controller you want to register to

 

#define DCS_HW_IRQ

// Dette er kodesnutten eg har skreve til nå

//Interrupt request. Manage hardware operations. Interrupt tells the CPU that you need to interrupt the current job and let the hardware run

 

// int register_chrdev(unsigned int major, const char *name, struct file_operations *fops);

DCS_HW_IRQ = register_chrdev(dcsIRQ_majorID, "bigRedButton", (file_operations) *dcsIRQ_fops);

 

// int request_irq(unsigned int irq, *handler_func, unsigned long flags, const char* devname, void* dev_id)

//DCS_HW_IRQ request_irq( 5, (*handler_func), SA_INTERRUPT, "bigRedButton", NULL);

//One of these, or maybe both should be done.

// Dette er kodesnutten eg har skreve til nå

 

 

/// ------- Register addresses -------

#define DCS_INT_BASE_ADDRESS 0x7FFFC000

 

/// ### TODO: set the offset for setting IRQ mask (see handout)

#define DCS_INT_MASK_SET

 

/// ### TODO: set the offset for clearing IRQ mask (see handout)

#define DCS_INT_MASK_CLEAR

 

/// ### TODO: set the offset for interrupt status (see handout)

#define DCS_INT_SOURCE_STATUS

 

/// ### TODO: set the offset for status of pending interrupts (see handout)

#define DCS_INT_REQUEST_STATUS

 

/// ### TODO: set the offset for the register that gives the highest priority irq (see handout)

#define DCS_INT_ID

 

/// ### TODO: set the offset for register of the priority of the PLD (see handout)

#define DCS_INT_PLD_PRIORTITY

 

/// ### TODO: set the offset for interrupt operating mode register (see handout)

#define DCS_INT_MODE

 

/// ------- Bitsets to write to register -------

#define DCS_SETBIT_IRQ_1 0x00000002

 

/// ### TODO: set bitset to write '1' to P5 in IRQ register (similar to DCS_SETBIT_IRQ_1)

#define DCS_SETBIT_IRQ_5

 

/// ### TODO: set bitset to write '1' to IP in IRQ register (similar to DCS_SETBIT_IRQ_1)

#define DCS_SETBIT_IRQ_6

 

 

 

/// ----------------------------------------

 

 

 

Her er det andre programmet som eg skal fylla inn i:

Namnet på programmet: "dcsIRQ_driver.c"

 

 

 

dcsIRQ - driver for the DCS board to catch a HW interrupt.

* This interrupt is then signaled to a registerd user space program as signal.

*

* <pre>

******************************************************************************

**

** This file is property of and copyright by the Experimental Nuclear

** Physics Group, Dep. of Physics and Technology

** University of Bergen, Norway, 2005

**

** Permission to use, copy, modify and distribute this software and its

** documentation strictly for non-commercial purposes is hereby granted

** without fee, provided that the above copyright notice appears in all

** copies and that both the copyright notice and this permission notice

** appear in the supporting documentation. The authors make no claims

** about the suitability of this software for any purpose. It is

** provided "as is" without express or implied warranty.

**

******************************************************************************

* </pre>

*

* @author Sebastian Bablok <[email protected]>

*

* @date 12.04.2007

*/

 

 

// taken from dcs message buffer driver ... check if all needed !!!

#include <linux/fs.h> // basic file structures and methods

#include <linux/types.h> // basic data types

#include <linux/sched.h> // task schedule

#include <linux/errno.h> // error codes

#include <linux/slab.h> // kmalloc, kmfree

#include <asm/io.h> // ioremap, ...

#include <asm/uaccess.h> // user space memory access (e.g. copy_to_user)

//#include <linux/poll.h>

#include <linux/mm.h> // virtual memory mapping

#include <linux/ioport.h> // detecting and reserving system resources

#include <linux/spinlock.h>

#include <asm/system.h>

#include <linux/module.h>

 

 

#include <sys/siginfo.h>

/*

* local includes

*/

#include "version.h"

#include "dcsIRQ_driver.h"

#include "dcsIRQ_defines.h"

 

/*

* kernel logging realted functions

*/

#include "mrKernLogging.c"

 

#ifndef __KERNEL__

#define __KERNEL__

#endif

#ifndef MODULE

#define MODULE

#endif

 

 

/* -----------------------------------------------------------------------------

* module descriptions

* -------------------------------------------------------------------------- */

MODULE_AUTHOR("IRTG-Participant");

MODULE_DESCRIPTION("dcs-card HW interrupt driver");

MODULE_LICENSE("GPL");

 

// the major id for the installation of the driver

MODULE_PARM(dcsc_majorID, "i");

 

 

 

/* -----------------------------------------------------------------------------

* global variables

* -------------------------------------------------------------------------- */

 

/**

* global count of processes in use of this driver

* count of (open() - close()) calls

*/

static unsigned int gProcessCount;

 

/**

* Indicates, if an irq handler is currently registered

*/

static int gIRQActive = 0;

 

/**

* pointer to the first node in dcsIRQ list

*/

static ListNode* firstNode = 0;

 

/**

* pointer to the last node in dcsIRQ list

*/

static ListNode* lastNode = 0;

 

 

 

/// ### TODO 0) ###

/**

* default major no of the driver

*/

static int dcsIRQ_majorID = 1;

//Set to 1? Eg satte denne til 1, men er ikkje sikker på om det er rett [\b]

/// ### set here the fixed major number [choose yourself] ###

 

 

/* -----------------------------------------------------------------------------

* function definition

* -------------------------------------------------------------------------- */

 

/*

* method prototypes of driver access routines (see below for implementations)

*/

static loff_t dcsIRQ_llseek(struct file* filp, loff_t off, int ref);

static int dcsIRQ_read(struct file* filp, char* buf, size_t count, loff_t* f_pos);

static int dcsIRQ_write(struct file* filp, const char* buf, size_t count,

loff_t* f_pos);

static int dcsIRQ_open(struct inode* inode, struct file* filp);

static int dcsIRQ_close(struct inode* inode, struct file* filp);

static int dcsIRQ_mmap(struct file *filp, struct vm_area_struct *vma);

static int dcsIRQ_ioctl(struct inode* inode, struct file* filp, unsigned int cmd,

unsigned long arg);

 

/**

* File_operation structure to define the methods for the char device

* the methods are going to be called from the system

* pointers to the methods are provided at driver initialization via the

* file_operations structure

*/

struct file_operations dcsIRQ_fops = {

llseek: dcsIRQ_llseek,

read: dcsIRQ_read,

write: dcsIRQ_write,

ioctl: dcsIRQ_ioctl,

mmap: dcsIRQ_mmap,

open: dcsIRQ_open,

release: dcsIRQ_close,

};

 

 

/* ----------------------------------------------------------------------------

* interrupt handler routine

* -------------------------------------------------------------------------- */

 

/**

* HW interrupt handler function

* This function sends a signal to all registered processes, when an hw

* intterrupt has been fired.

*/

void hw_interrupt_handler(int irq, void *dev_id, struct pt_regs *regs) {

ListNode* currentNode;

u32 irqSet = 0;

int nRet = 0;

 

mrlogmessage(LOG_INFO, MR_KERN_DEBUG "Received interrupt nr %d", irq);

 

irqSet = translateIRQ(irq);

// disable IRQ during this handler -> so it cannot get interrupted again

 

 

/// ### TODO: disable the IRQ line (use therefore the value of irqSet - the translated irq)

 

 

// mrlogmessage(LOG_INFO, MR_KERN_DEBUG "Received interrupt nr %d", irq);

 

currentNode = firstNode;

while (currentNode != 0) {

siginfo_t info_sig;

 

// received interrupt -> send signal to all registered processes

 

/// ### TODO 1): send a defined signal to the user space of all registered processes,

/// ### The return value should be assigned to nRet.

/// ### TIP: 1. param: signal you want to fire, [define yourself]

/// ### 2. param: pointer to a siginfo object [use pointer to info_sig]

/// ### 3. param: PID which shall get the signal [use pid from list: "currentNode->pid"]

nRet = ;

 

 

if (nRet < 0) {

mrlogmessage(LOG_WARNING,

MR_KERN_DEBUG "Unable to send IRQ signal to PID %d",

currentNode->pid);

}

currentNode = currentNode->next;

}

 

// enable IRQ again

/// ### TODO: enable the IRQ line (use therefore the value of irqSet - the translated irq)

}

 

 

/* ----------------------------------------------------------------------------

* init - deinit functions

* -------------------------------------------------------------------------- */

// intialize interrupt driver

int init_module(void) {

int error = 0;

 

/// ### TODO 2) register char device in kernel and assigne retVal to error

error = ;

 

 

if (error < 0) {

mrlogmessage(LOG_ERROR,

KERN_ERR "module init: can't register driver (dcsIRQ)");

} else {

mrlogmessage(LOG_INFO,

KERN_INFO "Module (dcsIRQ) init (compiled "__DATE__", "__TIME__") version %d.%d - %s",

DRIVER_MAJOR_VERSION_NUMBER, DRIVER_MINOR_VERSION_NUMBER,

RELEASETYPE);

if (dcsIRQ_majorID == 0) { /* dynamic allocation of major number*/

dcsIRQ_majorID = error;

mrlogmessage(LOG_INFO,

KERN_INFO "dynamic allocation of major number for dcsIRQ: %d",

dcsIRQ_majorID);

} else {

mrlogmessage(LOG_INFO,

KERN_INFO "register dcsIRQ driver at major no. %d",

dcsIRQ_majorID);

}

 

/// ### TODO 3): try to register hw interrupt handler and assigne retVal to error

error = ;

 

 

if (error) {

mrlogmessage(LOG_ERROR,

KERN_ERR "module init: can't register interrupt handler (dcsIRQ)");

cleanup_module();

return -1;

} else {

mrlogmessage(LOG_INFO,

KERN_INFO "registered hw interrupt handler successfully.");

gIRQActive = 1;

enableIRQ(DCS_SETBIT_IRQ_5);

}

 

// driver just registered, so set count to 0

gProcessCount = 0;

 

InitDriverLock();

}

return error;

}

 

// deinitialize interrupt driver

void cleanup_module(void) {

disableIRQ(DCS_SETBIT_IRQ_5);

mrlogmessage(LOG_INFO, KERN_INFO "Module (dcsIRQ) exit");

 

/// ### TODO 4): unregister char device

 

 

if (gIRQActive) {

 

/// ### TODO 5) free irq handler

 

 

}

// clean list

emptyList();

}

 

 

/* -----------------------------------------------------------------------------

* enable and disable of IRQ

* -------------------------------------------------------------------------- */

void enableIRQ(unsigned long arg) {

u32* irq_reg_buffer = 0;

 

/// ### TODO 6): aquire access to correct interrupt register and assign to irq_reg_buffer

irq_reg_buffer = ;

 

 

/// ### TODO 7): write "arg" (see param of this function) to acquired register access (see above)

 

 

mrlogmessage(LOG_DBG, MR_KERN_DEBUG "Set IRQ mask: %x (hex)", arg);

 

if (irq_reg_buffer) {

/// ### TODO 8): release register buffer

 

}

}

 

 

void disableIRQ(unsigned long arg) {

u32* irq_reg_buffer = 0;

 

/// ### TODO 9): aquire access to correct interrupt register and assign to irq_reg_buffer

 

 

/// ### TODO 10): write "arg" (see param of this function) to acquired register access (see above)

 

 

mrlogmessage(LOG_DBG, MR_KERN_DEBUG "Cleared IRQ mask: %x (hex)", arg);

 

if (irq_reg_buffer) {

/// ### TODO 11): release register buffer

 

}

}

 

 

/* -----------------------------------------------------------------------------

* implementation of driver access methods defined above

* -------------------------------------------------------------------------- */

 

static int dcsIRQ_open(struct inode* inode, struct file* filp) {

int nRet = 0;

pid_t userPID = 0;

 

// check if process is not yet registered

userPID = current->pid;

if (!checkPID(userPID)) {

// register pid

nRet = registerPID(userPID);

} else {

// to something already opened

mrlogmessage(LOG_ERROR,

KERN_ERR "irq-driver opencall: already opened by process");

return nRet;

}

 

if (nRet >= 0) { /* OK */

mrlogmessage(LOG_OPEN_CLOSE | LOG_DBG,

MR_KERN_DEBUG "Process %d opened dcsIRQ", userPID);

}

 

return nRet;

}

 

 

static int dcsIRQ_close(struct inode* inode, struct file* filp) {

int nRet = 0;

 

if (deregisterPID(current->pid)) {

mrlogmessage(LOG_OPEN_CLOSE | LOG_DBG,

MR_KERN_DEBUG "close driver for process %d", current->pid);

} else {

mrlogmessage(LOG_OPEN_CLOSE | LOG_WARNING,

MR_KERN_DEBUG "close without a corresponding open, pid %d",

current->pid);

}

return nRet;

}

 

 

static loff_t dcsIRQ_llseek(struct file* filp, loff_t off, int ref) {

loff_t lPosition = 0;

 

return lPosition;

}

 

 

static int dcsIRQ_mmap(struct file* filp, struct vm_area_struct* vma) {

int nRet = 0;

 

return nRet;

}

 

 

static int dcsIRQ_read(struct file* filp, char* buf, size_t count,

loff_t* f_pos) {

u32* irq_reg_buffer = 0;

ListNode* node = 0;

 

if (count < 4) {

// buffer size to small

return -1;

}

 

node = findPID(current->pid);

if (node == 0) {

mrlogmessage(LOG_WARNING,

MR_KERN_DEBUG "Received command from not registered pid: %d",

current->pid);

return -3;

}

 

// reading from IRQ controller registers

//irq_reg_buffer = (u32*) ioremap((u32) (DCS_INT_BASE_ADDRESS + 0xC08), sizeof(u32));

irq_reg_buffer = (u32*) ioremap((u32) (DCS_INT_BASE_ADDRESS + node->regAddress), sizeof(u32));

 

(unsigned) *buf = readl(irq_reg_buffer);

 

if (irq_reg_buffer) {

iounmap((void*) irq_reg_buffer);

}

 

return sizeof(unsigned);

}

 

 

static int dcsIRQ_write(struct file* filp, const char* buf, size_t count,

loff_t* f_pos) {

int nRet = 0;

 

/// ### TODO (optional !!!): if you want you can implement write to IRQ registers

/// ### similar to the dcsIRQ_read (see above). NOTE: first check if your driver works,

/// ### this feature is not required for main purpose.

 

return nRet;

}

 

 

static int dcsIRQ_ioctl(struct inode* inode, struct file* filp,

unsigned int cmd, unsigned long arg) {

int nRet = 0;

ListNode* node = 0;

 

switch (cmd) {

case (DCS_IRQ_FIRE):

// to simulate an interrupt, we can also call the handler function our self

// hw_interrupt_handler(DCS_HW_IRQ, 0, 0); // we just calls the handler routine ourself

hw_interrupt_handler((int) arg, 0, 0); // fire interrupt line given by arg

nRet = gProcessCount;

break;

 

case (DCS_IRQ_MASK):

enableIRQ(arg);

break;

 

case (DCS_IRQ_CLEAR):

disableIRQ(arg);

break;

 

case (DCS_IRQ_SELECT_REG):

node = findPID(current->pid);

if (node == 0) {

// pid not in list -> error

mrlogmessage(LOG_WARNING,

MR_KERN_DEBUG "Received command from not registered pid: %d",

current->pid);

nRet = -3;

break;

}

// checking argument if allowed reg address

if (!validateArg(arg)) {

mrlogmessage(LOG_WARNING,

MR_KERN_DEBUG "Received invalid register address: %x (hex)",

arg);

nRet = -4;

break;

}

node->regAddress = (u32) arg;

mrlogmessage(LOG_DBG,

MR_KERN_DEBUG "Set read reg address to %x for pid %d",

(DCS_INT_BASE_ADDRESS + arg), current->pid);

break;

 

default:

mrlogmessage(LOG_WARNING,

MR_KERN_DEBUG "Received unknown ioctl command: %d", cmd);

nRet = -1;

}

 

return nRet;

}

 

 

/* ----------------------------------------------------------------------------

* internal operations

* -------------------------------------------------------------------------- */

 

 

u32 translateIRQ(irq) {

return (0x00000001 << irq);

}

 

int validateArg(unsigned long argument) {

 

return (((argument == DCS_INT_MASK_SET) || (argument == DCS_INT_MASK_CLEAR)

|| (argument == DCS_INT_SOURCE_STATUS) ||

(argument == DCS_INT_REQUEST_STATUS) || (argument == DCS_INT_ID) ||

(argument == DCS_INT_PLD_PRIORTITY) || (argument == DCS_INT_MODE)) ?

1 : 0);

}

 

 

/* ----------------------------------------------------------------------------

* internal list operations

* -------------------------------------------------------------------------- */

 

void emptyList() {

ListNode* currentNode;

ListNode* nextNode;

 

if (firstNode == 0) {

return; // list is empty -> nothing to delete

}

currentNode = firstNode;

do {

nextNode = currentNode->next;

kfree(currentNode);

gProcessCount--;

currentNode = nextNode;

} while (currentNode != 0);

}

 

int checkPID(pid_t processID) {

int nRet = 0;

ListNode* currentNode = 0;

 

if (firstNode == 0) { // list is empty -> cannot be registered yet

return nRet;

} else {

currentNode = firstNode;

do {

if (currentNode->pid == processID) { // process is registered

return 1;

}

currentNode = currentNode->next;

} while (currentNode != 0);

}

return nRet;

}

 

ListNode* findPID(pid_t processID) {

ListNode* currentNode = 0;

 

if (firstNode == 0) { // list is empty -> cannot be registered yet

return 0;

} else {

currentNode = firstNode;

do {

if (currentNode->pid == processID) { // process is registered

return currentNode;

}

currentNode = currentNode->next;

} while (currentNode != 0);

}

return 0;

}

 

int registerPID(pid_t processID) {

ListNode* currentNode = 0;

 

if (firstNode == 0) { // list is empty

firstNode = (ListNode*) kmalloc(sizeof(ListNode), GFP_KERNEL);

if (firstNode == 0) { //kmalloc went wrong

return -1;

}

// check first if lastNode is also 0, if not then something is

// broken -> panic !!!

lastNode = firstNode;

firstNode->previous = 0;

firstNode->next = 0;

 

firstNode->pid = processID;

gProcessCount++;

return 1;

}

 

currentNode = lastNode;

lastNode = (ListNode*) kmalloc(sizeof(ListNode), GFP_KERNEL);

if (lastNode == 0) { //kmalloc went wrong

return -1;

}

currentNode->next = lastNode;

lastNode->previous = currentNode;

lastNode->next = 0;

lastNode->pid = processID;

gProcessCount++;

return 1;

}

 

int deregisterPID(pid_t processID) {

ListNode* currentNode = 0;

 

if (firstNode == 0) {

return 0; // list is empty -> nothing to deregister

}

 

currentNode = firstNode;

do {

if (currentNode->pid == processID) { // process is registered

if (currentNode->previous != 0) {

currentNode->previous->next = currentNode->next;

} else {

firstNode = currentNode->next;

}

if (currentNode->next != 0) {

currentNode->next->previous = currentNode->previous;

} else {

lastNode = currentNode->previous;

}

kfree(currentNode);

gProcessCount--;

return 1;

}

currentNode = currentNode->next;

} while (currentNode != 0);

 

return 0; // not found in list

}

 

 

 

 

/* ----------------------------------------------------------------------------

* driver lock

* -------------------------------------------------------------------------- */

 

/* global variables

*/

wait_queue_head_t g_waitQueue;

// the wait queue for the concurrenting processes

 

// an emergency back door, all released processes terminate lockDriver()

int g_iLockReset = 0;

 

int g_iLock = 0; // the lock itself

spinlock_t g_spinlock;

int g_iLockInitialized = 0;

 

 

int InitDriverLock() {

int nRet = 0;

init_waitqueue_head(&g_waitQueue);

spin_lock_init(&g_spinlock);

g_iLockReset = 0;

g_iLock = 0;

g_iLockInitialized = 1;

return nRet;

}

 

int lockActivate() {

int iResult=0;

g_iLockReset=0;

return iResult;

}

 

int lockReset() {

int nRet = 0;

g_iLockReset = 1;

// set the flag so that the processes do not try to lock again

if (g_iLockInitialized) {

wake_up(&g_waitQueue); // wake up all processes

}

g_iLock = 0;

return nRet;

}

 

int checkAndLock() {

int nRet = 0;

if (g_iLockInitialized) {

spin_lock(&g_spinlock);

if (g_iLock == 0) {

nRet = g_iLock = 1;

}

spin_unlock(&g_spinlock);

}

return nRet;

}

 

int lockDriver(int iTimeOut) {

int nRet = 0;

if (g_iLockInitialized) {

int iPid = 0;

if (current) {

iPid = current->pid;

}

while ((g_iLockReset == 0) && ((nRet = checkAndLock()) == 0)) {

mrlogmessage(LOG_DRIVER_LCK,

MR_KERN_DEBUG "lockDriver: process %d, timeout %d put to sleep",

iPid, iTimeOut);

interruptible_sleep_on(&g_waitQueue);

mrlogmessage(LOG_DRIVER_LCK,

MR_KERN_DEBUG "lockDriver: process %d woken up", iPid);

}

if (nRet >= 0) {

mrlogmessage(LOG_DRIVER_LCK, MR_KERN_DEBUG "lockDriver: process %d",

iPid);

}

}

return nRet;

}

 

int unlockDriver() {

int nRet = 0;

if (g_iLockInitialized) {

int iPid = 0;

if (current) {

iPid = current->pid;

}

mrlogmessage(LOG_DRIVER_LCK, MR_KERN_DEBUG "unlockDriver: process %d",

iPid);

spin_lock(&g_spinlock);

g_iLock = 0;

wake_up(&g_waitQueue); // wake up all processes

spin_unlock(&g_spinlock);

}

return nRet;

}

 

 

 

 

Eg kan også ta med "dcsIRQ_driver.h" fila, skal ikkje endra på noko i den, men den skal brukast:

 

 

/**

* FUNCTION HEADER - FILE

*

* dcsIRQ - driver for the DCS board to catch a HW interrupt.

* This interrupt is then signaled to a registerd user space program as signal.

*

* <pre>

******************************************************************************

**

** This file is property of and copyright by the Experimental Nuclear

** Physics Group, Dep. of Physics and Technology

** University of Bergen, Norway, 2005

**

** Permission to use, copy, modify and distribute this software and its

** documentation strictly for non-commercial purposes is hereby granted

** without fee, provided that the above copyright notice appears in all

** copies and that both the copyright notice and this permission notice

** appear in the supporting documentation. The authors make no claims

** about the suitability of this software for any purpose. It is

** provided "as is" without express or implied warranty.

**

******************************************************************************

* </pre>

*

* @author Sebastian Bablok <[email protected]>

*

* @date 03.12.2005

*/

 

#ifndef DCS_IRQ_DRIVER_H

#define DCS_IRQ_DRIVER_H

 

/**

* Typedef dcsIRQ list node.

* dcsIRQ list node is a struct for building a doubly linked list of

* ids of registered processes in this driver.

*/

typedef struct Node {

/** struct value previous -> pointer to previous ItemNode.*/

struct Node* previous;

/** struct value next -> pointer to next ItemNode.*/

struct Node* next;

/** struct value id -> process id of registered process in driver.*/

pid_t pid;

/**

* struct value regAddress -> the register address, which shall be read by

* the next read command.

*/

u32 regAddress;

} ListNode;

 

 

/**

* init_module called from the system during insmod command

*

* @return gives back an error code in case of failure

*/

int init_module(void);

 

/**

* Deinitialisation of driver

* cleanup_module called from the system during rmmod command

*/

void cleanup_module(void);

 

 

/**

* Function checks, if of PID has already registered in the list of process

* opened this driver (an not closed it yet).

*

* @param processID the PID which should be checked

*

* @return 1 if processID is already registered, else 0

*/

int checkPID(pid_t processID);

 

/**

* Function to register a PID in the list of process, which

* opened this driver (an not closed it yet).

*

* @param processID the PID which should be checked

*

* @return 1 if processID is sucessfully registered, else -1 (error case)

*/

int registerPID(pid_t processID);

 

/**

* Function to deregister a PID during cloase call.

*

* @param processID the PID to deregister

*

* @return 0, if PID was not found in list, else 1

*/

int deregisterPID(pid_t processID);

 

/**

* Function looks for the node in the driver list, which matches the given ID.

*

* @param processID the pid, for which the list node shall be found.

*

* @return the matching list node, if search has been successful; else 0.

*/

ListNode* findPID(pid_t processID);

 

/**

* Empties list in driver comnpletely

*/

void emptyList();

 

/**

* Function to valid an argument as valid reg address

*

* @param argument the argument to be checked

*

* @return 0 if argument is NOT valid

*/

int validateArg(unsigned long argument);

 

/**

* Function to enable the interrupt at the given IRQ mask

*

* @param arg the bitset mask of which IRQs shall be enabled

*/

void enableIRQ(unsigned long arg);

 

/**

* Function to disable the interrupt at the given IRQ mask

*

* @param arg the bitset mask of which IRQs shall be disabled

*/

void disableIRQ(unsigned long arg);

 

/**

* Translates a given IRQ in the corresponding bit set mask

*

* @param irq the IRQ to translate

*

* @return the bit set mask of the translated irq

*/

u32 translateIRQ(int irq);

 

 

////////////////////////////////////////////////////////////////////////////////

// Function taken from dcs message buffer river //

////////////////////////////////////////////////////////////////////////////////

 

int InitDriverLock();

 

int lockActivate();

 

int lockReset();

 

/**

* spin lock protected check of the lock status variable

* if the lock is free it will be set

*

* @return 1 if free and now set, 0 if already blocked, <0 error

*/

int checkAndLock();

 

/**

* try to lock the driver, go to sleep if already locked

* after the process got woken up it tries again to lock

*

* @param iTimeOut - time out for the sleep

*

* @return 1 if successfully locked, 0 if not locked, -ETIMEDOUT if time out

*/

int lockDriver(int iTimeOut);

 

/**

* unlock the driver and wake up all sleeping processes

*

* @return ???

*/

int unlockDriver();

 

#endif

 

 

 

Lenke til kommentar

Opprett en konto eller logg inn for å kommentere

Du må være et medlem for å kunne skrive en kommentar

Opprett konto

Det er enkelt å melde seg inn for å starte en ny konto!

Start en konto

Logg inn

Har du allerede en konto? Logg inn her.

Logg inn nå
×
×
  • Opprett ny...