

Writing serial port interrupt handler in linux  - aquarius

I got a new problem with the following interrupt handler code with respect to
serial port 1. I have a cable connecting two serial ports of two computers
with linux on them. On one computer there is minicom installed and on another
I have compiled and successfully insmoded the below shown module. But when I
type on minicom, it doesnt show anything (by the command 'dmesg') on the
other computer where my module is loaded !<p>Kindly help !!<p>#include &#60;linux/kernel.h&#62;
#include &#60;linux/interrupt.h&#62;
#include &#60;asm/io.h&#62;<p>#define PORT 0x3F8<p>irq_handler_t isrSerialPort (int irq, void <i>dev_id, struct pt_regs </i>regs)
{
               printk ("\nThank god !\n");
               return (irq_handler_t) IRQ_HANDLED;
}<p>int init_module ()
{
               outb (0x01, PORT + 1);
               outb (0x83, PORT + 3);<p><pre><code>               // Set Baud rate - Divisor Latch Low Byte
               outb (0x0C, PORT + 0);
               // Set Baud rate - Divisor Latch High Byte
               outb (0x00, PORT + 1);

               // number of bytes to read
              outb (0x07, PORT + 2);
              outb (0x03, PORT + 3);

               int h = request_irq (4, (irq_handler_t) isrSerialPort,</code></pre>
SA_SHIRQ, "God", (void *) (isrSerialPort));<p><pre><code>               // Interrupt when data received
               outb (0x01, PORT + 1);

               return h;</code></pre>
}<p>MODULE_LICENSE ("GPL");
======
a-priori
I'm going to assume you're doing this for intellectual curiosity, because I'm
sure the existing serial port drivers work fine. That's okay; I used to do
operating system development (aka "osdev") a few years back as a hobby, so I
understand how you feel :)

Here are my hunches for what the problem is: you're initializing the UART
wrong (it's been a while and I forget the details), you're conflicting with
something else that's using the serial port, or you're registering your ISR
wrong.

To test whether your UART initialization is correct, you can try removing
Linux from the mix. It's pretty simple to create a binary that GRUB can boot
(Google: multiboot specification), and that way you can test out your code in
isolation. You'll want to use polling rather than ISRs to wait for data, and
write directly into the VGA buffer (it's on the even bytes starting at
0xB8000) to print your data to screen.

You also might want to try running this through Bochs, because it can give you
hardware-level logs about what's going on. Are bytes actually being received?
Is the IRQ actually being raised? That sort of thing.

If that works, then your problem is with Linux itself, and I can't be much
help there. I suggest looking through the source for other drivers that
register IRQ handlers, or asking the linux-kernel mailing list.

Best of luck.

~~~
aquarius
Thanks for the guidelines !!

------
srn
This may not be likely, but - you don't specify a level for your printk
statement. It could be your message is just not getting printed to console.
Check out info for "/proc/sys/kernel/printk" as well as information about
syslogd and klogd as the message may be logged to somewhere else.

I also would like to mention that in general memory barriers can be useful for
working with i/o irrespective of your particular situation.

~~~
srn
More explicit handling of error conditions is also good FWIW - don't see you
doing it here. The kernel is not forgiving of using resources your don't have
or failing to free resources acquired.

~~~
srn
Also from what I know, which is not much, you should be requesting the ports
via request_region. If that fails you should probably not be writing to the
ports and should also mean you're sharing the port with another module.

kernel newbies is theoretically a good place to go with these kinds of
questions too.

------
brtzsnr
Homework?

I had this assignment while studying Operating Systems Design during college.
I can tell you I failed miserable. We used documentation from:
<http://www.beyondlogic.org/serial/serial.htm>. You can find some examples
there, but not for the Linux kernel.

------
JoeAltmaier
Start with outb (0x00, PORT + 1);

~~~
aquarius
Does the order of specification matter ?

