int skel_major = 0; /* default: dynamic */
int skel_base = 0; /* default: autodetect */
int skel_irq = -1; /* default: autodetect */
Static int skel_boards = 0; /* how many of them are there */
typedef struct Skel_Hw {
int base; /* I/O port */
int irq; /* IRQ being used */
int hwirq; /* The detected one */
int irqcount;
int usecount;
/* .... */
} Skel_Hw;
Skel_Hw skel_hw[SKEL_MAX_BOARDS];
#define PORT0(board) ((board)->base+0)
#define PORT1(board) ((board)->base+1)
/* ... */
Static file_operations skel_fops; /* defined later on */
int init_module (void)
{
int base, err, i;
/* Look for a major */
err = register_chrdev (skel_major, "skel", ∓skel_fops);
if (err < 0) {
printk(KERN_NOTICE "skel init: error %d\n", -err);
return err;
}
if (skel_major==0) skel_major=err; /* dynamic */
/*
* Look for ports: PORT_MIN, PORT_STEP, PORT_MAX define
* the range of (consecutive) addresses supported by the board
*/
base = skel_base ? skel_base : PORT_MIN;
do {
if (check_region(base, PORT_STEP) != 0)
continue; /* in use */
request_region(base, PORT_STEP, "skel");
skel_hw[skel_boards].base=base;
if ( (err=skel_find(skel_hw+skel_boards)) == 0) {
/* found one */
skel_boards++;
continue;
}
release_region(base, PORT_STEP);
}
/* if autodetecting skel_base is 0, otherwise, do it only once */
while (skel_base==0 && (base+=PORT_STEP) < PORT_MAX);
if (skel_boards==0) {
printk(KERN_NOTICE "skel init: no boards found\n");
return -ENODEV;
}
/* do other initialization here */
if ( (err=request_resource_1()) != 0 )
goto fail_resource_1:
if ( (err=request_resource_2()) != 0 )
goto fail_resource_2:
if ( (err=request_resource_3()) != 0 )
goto fail_resource_3:
return 0; /* success */
fail_resource_3: free_resource_2()
fail_resource_2: free_resource_1()
fail_resource_1: printk(KERN_NOTICE "skel init: error %i\n",
-err);
/* release your boards */
for (i=0; i<skel_boards; i++)
release_region(skel_hw[i].base, PORT_STEP);
return err; /* failure */
}
void cleanup_module (void)
{
int b;
if (MOD_IN_USE)
return /* -EBUSY */;
printk(KERN_INFO "skel driver unloaded\n");
for (b=0; b<skel_boards; b++) {
/* shutdown the board.... */
release_region(skel_hw[b].base, PORT_STEP);
if (skel_hw[b].irq >= 0)
free_irq(skel_hw[b].irq);
}
unregister_chrdev(skel_major, "skel");
return;
}
Copyright © 1994 - 2019 Linux Journal. All rights reserved.