Linux drivers for Apogee Cameras

Here at the MMT Observatory, we use a (now obsolete) Apogee KX series CCD camera as part of the telescope wave front sensor. We also use this on a linux system (currently Fedora 14 as of 3/2011). We use it thanks to the drivers written by Dave Mills (The Random Factory).

We have a couple of the old ISA bus controller cards, and at least one of the newer (but no longer supported, and scarcely acknowledged by Apogee) PCI controller cards.

There is an open source driver on Sourceforge (version 1.2), but this was released in August 2004. There are many versions of newer drivers on the randomfactory site, the latest being version 3.1.12 which was released in April of 2009 and supports many of the newer cameras.

To install the software (we still run version 1.2 !!), the first step is to unpack the tarball into /opt/apogee. Then you are recommended to run /opt/apogee/modinstall to set up the kernel modules. After this, each user should run /opt/apogee/install, which seems to primarily generate the file .apccd.ini Note that this file had the setting Cable = LONG or Cable = SHORT.

OK, now I am doing this:

cd /opt/apogee/src/apogee/module26
insmod apogeeISA.ko
insmod: error inserting 'apogeeISA.ko': -1 Operation not permitted
Insmod is hardly helpful with the error messages it spits out. In fact the -1 status is simply a value returned by the module when it detects something it doesn't like, the string "Operation not permitted" is entirely bogus. The thing to do is to look at /var/log/messages and see what messages the module is spitting out via printk.

Some folks think that the proper way to install modules is as follows (and they may be correct). I have yet to follow this advice.

copy the module to lib/modules/$(uname -r)/kernel/drivers/misc
depmod -a
modprobe

What I did do was two things.  First I discovered that the apogee ISA
module needs and expects an argument specifying the base address (it can
be a list of addresses) as follows:

insmod apogeeISA.ko apisa_addr=0x290
Secondly I added some code to check the return value from the request_region() call in the driver. It turns out that the base address 0x290 was not being accepted by the kernel as it conflicts with a small block of preallocated PNP device addresses. However the base address 0x200 seems to work just fine.

The PCI driver, when it happily insmods yields:

Mar  6 15:10:48 archive kernel: [  308.380727] appci: ********** Initializing module...
Mar  6 15:10:48 archive kernel: [  308.380779] appci: Device found: bus 0, device 9, function 0
Mar  6 15:10:48 archive kernel: [  308.380802] appci: PLX configuration registers at 0x0000d400
Mar  6 15:10:48 archive kernel: [  308.380825] appci: PLX reg range is  0x000000ff
Mar  6 15:10:48 archive kernel: [  308.380853] appci: memory 0 starts at 0xe8001000
Mar  6 15:10:48 archive kernel: [  308.380867] appci: memory 1 starts at 0x0000d400
Mar  6 15:10:48 archive kernel: [  308.380883] appci: memory 2 starts at 0xfeed0000
Mar  6 15:10:48 archive kernel: [  308.380948] appci: memory 2 remapped to 0xe085c000
Mar  6 15:10:48 archive kernel: [  308.380965] appci: APOGEE read 0x0000  =  0x0000ff73
Mar  6 15:10:48 archive kernel: [  308.380981] appci: APOGEE read 0x0001  =  0x0000009f
Mar  6 15:10:48 archive kernel: [  308.380998] appci: APOGEE read 0x0002  =  0x0000009f
Mar  6 15:10:48 archive kernel: [  308.381083] appci: APOGEE read 0x0003  =  0x00000c06
Mar  6 15:10:48 archive kernel: [  308.381102] appci: APOGEE read 0x0004  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381118] appci: APOGEE read 0x0005  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381135] appci: APOGEE read 0x0006  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381151] appci: APOGEE read 0x0007  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381167] appci: APOGEE read 0x0008  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381183] appci: APOGEE read 0x0009  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381199] appci: APOGEE read 0x000a  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381215] appci: APOGEE read 0x000b  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381231] appci: APOGEE read 0x000c  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381247] appci: APOGEE read 0x000d  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381264] appci: APOGEE read 0x000e  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381280] appci: APOGEE read 0x000f  =  0x00000000
Mar  6 15:10:48 archive kernel: [  308.381323] appci: ********** Driver successfully initialized.

It is vital to note that the driver(s) use some hardwired special device numbers and require some specific files in the /dev directory.

The PCI driver uses major number 60

The ISA driver uses major number 62

A script to produce the special files required is as follows:

mknod /dev/apisa0 c 62 0
mknod /dev/apisa1 c 62 1
mknod /dev/apisa2 c 62 2
mknod /dev/apisa3 c 62 3
chmod og+rw /dev/apisa*

mknod /dev/appci0 c 60 0
mknod /dev/appci1 c 60 1
mknod /dev/appci2 c 60 2
mknod /dev/appci3 c 60 3
chmod og+rw /dev/appci*

Here is what I see after successfully installing the ISA driver and trying to take one exposure:

Mar  6 15:58:01 archive kernel: [   83.517272] apisa: ********** Initializing module...
Mar  6 15:58:01 archive kernel: [   83.517460] apisa: Board 1 registered at 0x200
Mar  6 15:58:01 archive kernel: [   83.517725] apisa: reg 0 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.517831] apisa: reg 2 = 0xbb
Mar  6 15:58:01 archive kernel: [   83.517932] apisa: reg 4 = 0xbb
Mar  6 15:58:01 archive kernel: [   83.518099] apisa: reg 6 = 0xc06
Mar  6 15:58:01 archive kernel: [   83.518215] apisa: reg 8 = 0x0
Mar  6 15:58:01 archive kernel: [   83.518323] apisa: reg 10 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.518451] apisa: reg 12 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.518579] apisa: reg 14 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.518691] apisa: reg 16 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.518802] apisa: reg 18 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.518911] apisa: reg 20 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519065] apisa: reg 22 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519181] apisa: reg 24 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519289] apisa: reg 26 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519397] apisa: reg 28 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519504] apisa: reg 30 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.519614] apisa: reg 32 = 0xffff
Mar  6 15:58:01 archive kernel: [   83.532537] apisa: attempt to allocate registers for board 1 at base: 0x200
Mar  6 15:58:01 archive kernel: [   83.536845] apisa: Successfully allocated device registers for board 1 at base: 0x200
Mar  6 15:58:01 archive kernel: [   83.541255] apisa: ********** Driver successfully initialized.

Mar  6 16:00:26 archive kernel: [  228.730924] apisa: camera/board 0 open
Mar  6 16:00:28 archive kernel: [  230.765896] apisa: release

Have any comments? Questions? Drop me a line!

Adventures in Computing / tom@mmto.org