Friday, December 28, 2007

NY gift from Juniper

Juniper released FreeBSD/MIPS port to public. There are no references to JNPR-specific hardware pieces but a lot of mature code for generic MIPS devices that mips2 tree lacks: VM/pmap, libc, FPU support. Nice gift, thanks JNPR!

Sunday, December 9, 2007

RB532 progress

This weekend I spent writing driver for IDT RC32434 on-board Ethernet adapter. Weird hobby, isn't it? Writing NIC drivers is new to me so I shared my time between reading if_XX sources, reading IDT specs and writing my own code. Task turned out easier then it appeared and 15 minutes ago I managed to mount root over NFS using kr0 interface. Time to get some beer and celebrate!

Saturday, December 1, 2007

Mikrotik RB532 - single user mode.

Today I managed to get shell prompt on Mikrotik's Routerboard 532. So now we have 3 platforms with single user mode for FreeBSD/mips, not very useful :) The last problem was getting high-level console interface working. I always fell lost when it comes to resource allocation and uart stuff. I should write a couple of posts on these subjects to memorize all details better.

Sunday, November 25, 2007

INTR_FAST and selwakeup

I stumbled over this problem a couple of years ago, ignored it, was punished for my carelessness, came out with hackerish solution and now I know "The Right Way" to solve this issue. So, the headache starts when you're trying to wakeup userland application polling on a descriptor from INTR_FAST IRQ handler (for 7.X and later that would be interrupt filter). INTR_FAST/interrupt filter routines are usually used for timing-critical tasks and run in IRQ dispatcher context, so no operations that may cause context switch are allowed in this code. Unfortunately selwakeup(9) tries to acquire sellock that leads to a possible context switch and leaves us in a total mess. My solution was handmade kernel thread that has been running through list of channels and performed all dirty work, not the cleanest and easiest to maintain code. "Zaptel-bsd take 2" utilizes taskqueue(9) interface to work around IRQ handler limitations. There is handler routine:


static void
handle_selwakeup(void *context, int pending)
{
struct selinfo *sel = context;
selwakeup(sel);
}


then selinfo/task structures for every channel:

...
/* thingy for select stuff */
struct selinfo sel;
struct task selwakup_task;
...


which should be initialized during channel allocation:

...
TASK_INIT(&chan->selwakup_task, 0,
handle_selwakeup, &chan->sel);
...


and used anytime we'd like to call selwakeup:

...
taskqueue_enqueue_fast(taskqueue_fast,
&timer->selwakup_task);
...

Tuesday, November 20, 2007

Module/kernel parameters

Sometimes it's desirable to pass some arguments to module to customize its behavior, e.g.: to set/unset verbosity level of debug output, set operation mode etc... Linux modules can get this information from insmod utility, but kldload is not capable of doing such kind of things. What a pity. But don't get desperate - tunables to the rescue!

Just like an ordinary command shell (bash, csh, sh) kernel has its own environment, the set of <name, value> pairs. You can get, set, test, unset these variables using getenv, setenv, testenv, unsetenv functions in the kernel and kenv(2) syscall or kenv(1) command in userland. So if you want to set verbosity level for module, you would do something like this:


# kenv zaptel.debug=1
# kldload ./zaptel.ko

and then in module initialization routine:

static int debug = 0; /* Hush-hush */
...
char * value = getenv("zaptel.debug");
if (value) {
debug = strtol(value, NULL, 10);
freeenv(value);
}

Too much code for such a simple task, don't you think? Yeah, like for every common task there are useful macroses defined in kernel headers, you should just find them. Heavy coffeinated kernel hackers knew most of them. In this particular case neat code would look something like that (for statically initialized variable):

static int debug = 0; /* Hush-hush */
TUNABLE_INT("zaptel.debug", &debug);

or, if debug is the member of structure or local variable:

sc->debug = 0;
TUNABLE_INT_FETCH("zaptel.debug", &sc->debug);


TUNABLE_XXX macroses exist for INT, LONG, ULONG and STR types. TUNABLE_STR unlike the others requires third parameter - maximum size of the string. For a dynamic value retrieval every type has TUNABLE_XXX_FETCH macro defined. Nota bene: if there is no environent variable set with requested name, the value of acceptor variable remains untouched.

Monday, October 29, 2007

Introduction

Hello. My name is Oleksandr Tymoshenko. I'm a software developer. My involvement in FreeBSD project started in 1998 by making static entries in ARP table really static. Though patch hasn't made out of my university's network it was "the beginning of a beautiful friendship". My first significant contribution to FreeBSD community (or so I'd like to think) was porting of Zaptel drivers from Linux to FreeBSD. About two years ago I happened to work with a MIPS board and got some interest to the architecture. Since then I've been doing my best trying to bring FreeBSD to this platform and, actually, succeeded to some extent with a help from developers crowd.

In this blog I'm going to make notes on drivers development and porting process. Mostly for myself - to memorize gotchas and pitfalls which happen from time to time. But I hope that these notes will be of some use to other kernel hacker wannabes.