Category Archives: Linux

ZD1211 rewrite driver partially usable

I just announced our just-about-functional rewritten ZD1211 driver on the zd1211-devs mailing list. The driver is actually usable (and reliable!) on unencrypted networks.

A fully usable (WLAN client) driver is now well within sight, we just need to implement connecting to encrypted networks and automatic rate management.

More advanced features (such as ad-hoc connectivity, master mode, monitor mode, …) will come later. Hopefully the community will help us out there.

Linux Wireless Summit

I was lucky enough to spend most of last week in Portland, Oregon. After a chaotic flight all day Tuesday, several of us met on Wednesday and attended a larger social meeting that evening. It was really nice meeting so many active kernel developers who were previously just names in my inbox.

For those that don’t know, wireless networking is one of the weaker areas of the Linux kernel in terms of hardware support, general usability, and excess functional code duplication.

The actual summit took place over Thursday/Friday at OSDL‘s offices. The main topics addressed at the summit were unification of the various generic wireless “stacks” that exist, how we can get more drivers ready for kernel inclusion, and how we can improve communication with vendors and the FCC.


Picture from Jean Tourrihles. Note OSDL’s wireless network key clearly visible on the far right, ahem.

On Friday, I met for dinner with 5 other Gentoo developers. Corey Shields (cshields), Donnie Berkholz (spyderous) and Michael Marineau (marineam) travelled up from OSU. Aaron Kulbe (SuperLag) joined us, who already resides in Portland. Henrik Brix Andersen (brix) was also attending the conference, and brought along two Gentoo users. We had a good time, and I’m going to have to visit OSL if I ever get the opportunity again.

There wasn’t much opportunity for hacking at the summit, but a few us of got together on Saturday and went through some issues. I have never worked on kernel stuff with other kernel hackers in-person before, and this was highly productive. Johannes Berg monitored the wireless traffic produced from our ZD1211 driver rewrite, and threw around some suggestions and softmac patches. Michael Buesch went through the driver source and pointed out a few bugs. Ulrich Kunitz improved the locking. At the end of the session, we had our ZD1211 device associated to the hotel network and browsing the web!

I travelled home on Sunday, just when I was getting used to the timezone. Many thanks to Greg KH who was in the right place at the right time when I realised I had misread my flight timetable (oops!). Also thanks to OSDL for sponsoring my travel and the event itself.

Linux-friendly wireless vendors

I’ll write more about the Linux Wireless Summit when I am back at home, but here’s a taster.

One item that was discussed was vendor interaction with the Linux wireless development community, or the lack of it. The wireless networking market is still young and lack of vendor cooperation is one of the things that has resulted in Linux’s support for wireless networking being below par.

Without direct company contacts, there’s not a lot we can do to actively improve this, other than be friendly to those who have cooperated, and be patient. With that, we identified the vendors who have been cooperative:

  • Intel rock – they have done the whole shebang. They write open-source drivers for their Intel Centrino wireless adapters (ipw2100/ipw2200), cooperate enough with the Linux developer community for those drivers to be included in mainline Linux, allow firmware to be redistributed, and have contributed to a generic wireless stack shared between all wireless drivers. These cards are probably the best supported wireless adapters under Linux at this time.
  • ZyDAS write GPL drivers for most of their products, and distribute device specs to Linux developers. They also allow redistribution of device firmware. In terms of hardware support, Linux supports the older ZD1201 USB-Wireless adapters, but I’d really recommend the newer ZD1211 devices instead. ZD1211 will be well supported in mainline Linux hopefully within a few weeks.
  • Ralink have apparently contributed device specs. If anyone has details on hardware support under Linux, leave a comment.

Please keep these vendors in mind when purchasing hardware in the future, and be sure to thank them for their contributions.

ZD1211 TX operational

After a couple of weeks of head-scratching, I managed to get the rewritten USB-wireless ZD1211 driver transmitting data.

The code has been written for a while, and although it seems to work (the device doesn’t indicate any form of failure), the frames simply weren’t “hitting the air”.

The problem originates from the huge number of undocumented physical registers in the vendor driver. Rather than list all 200 of them in our driver source in the ugly manner which ZyDAS do so, we devised a quick one-line macro to perform the same task:

#define CR(reg)                CTL_REG((reg)*4)

However, it appears that ZyDAS have some trouble counting. A snippet from the vendor driver:

#define        ZD_CR1            0x0004
#define        ZD_CR2            0x0008
#define        ZD_CR3            0x000C
#define        ZD_CR5            0x0010
#define        ZD_CR6            0x0014
#define        ZD_CR7            0x0018
#define        ZD_CR8            0x001C
#define        ZD_CR4            0x0020
#define        ZD_CR9            0x0024

1,2,3,5,6,7,8,4,9… Our macro obviously doesn’t match the unordered nature of those low CR addresses.
After inserting the appropriate hacks into our driver, packets start flying, as confirmed by another wireless card in monitor mode.

Be warned: although we have transmit and receive working to some degree, the driver isn’t ready for users wanting to connect to networks yet.

I’m attending the OSDL Wireless Developer Summit in the first week of April, and I’m hoping that we’ll have a partially usable driver in time for that.

ZD1211 wireless hacking

I’ve been spending some time over the last few weeks hacking on a USB Wireless-LAN adapter based on the ZyDAS ZD1211 chip. There are actually 40+ ZD1211-based products available on the market so Linux support for this device has some big implications.

ZyDAS themselves produce a Linux driver which is updated semi-regularly, however the code is horrible and the driver is unreliable for many. On the other hand, it’s good that they have released a full GPL driver and have also been cooperative with providing technical documentation and flexibility on redistributing the firmware. There have been some forks which try to stabilise the vendor driver, the latest being zd1211.ath.cx, but none of these forks have been aiming for kernel inclusion.

In January, myself and Danny van Dyk started a driver rewrite project and published some initial code. Soon after doing so, I was contacted by Ulrich Kunitz, a hacker who had spent several weeks previously developing a rewritten driver. We switched over to Ulrich’s driver base and continued from there.

Unlike the vendor driver, we are taking full advantage of Linux’s IEEE 802.11 wireless stack. As the driver must do most things in software, we are also using the softmac extension which simplifies many generic operations (scanning, authentication, etc). A nice side effect of this is that when we have written the code to send and receive packets, the driver is almost complete (the other layers do the rest of the work).

Yesterday, I hacked together an initial scanning implementation and successfully scanned my local area for wireless networks. This means that receiving packets is more-or-less working – a nice milestone to reach.

Some information and links to the code can be found here. Be warned, this is useful for users yet. Watch this space for updates.

Using git-bisect to find buggy kernel patches

A keen Gentoo user (Ronald) recently came onto IRC, with a strange kernel problem: 2.6.15 only using one of his CPU’s although it sees both, 2.6.14 works fine.

He was keen to investigate the problem himself so I thought now would be a good time to try the git bisect feature for the first time. There were approximately 5500 patches merged between 2.6.14 and 2.6.15, and this method found the offending patch in only 13 reboots (OK – still a high number, I said this guy was keen though!).

This feature is very effective and very easy to use, so I’m going to demonstrate it here. Linus also wrote a nice HOWTO on the topic.

You first have to clone the Linux kernel git repository. This is the same concept checking out a repository from CVS.

# git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git linux-git
# cd linux-git

This directory looks like an ordinary kernel source distribution as you might expect in /usr/src/linux. It also has a hidden .git subdirectory which is where git stores its magical data. Tell git that we want to find a buggy patch through bisection:

# git bisect start

Next, tell git which kernel was the last known-working kernel, and which kernel is known to be not working. To identify these kernels, you can either use the long hexadecimal commit numbers, or you can abbreviate those numbers, or you can refer to tags directly. Linus tags every release with the version number, so the next step is as simple as:

# git bisect bad v2.6.15
# git bisect good v2.6.14

git now runs off and locates the commit exactly halfway between 2.6.14 and 2.6.15. It then “checks out” this tree, so the kernel infront of you is effectively a snapshot from halfway inbetween 2.6.14 and 2.6.15.

Bisecting: 2705 revisions left to test after this
[dd0314f7bb407bc4bdb3ea769b9c8a3a5d39ffd7] fbcon: Initialize new driver when old driver is released

Build that kernel in the normal way, and reboot into it. It works, so we know the bug was introduced after this point. We inform git of this:

# git bisect good

git now discards the whole first half of commits between 2.6.14 and 2.6.15 and bisects the remaining half (the changes after the point we just tested, but before 2.6.15). This is just a simple binary search. git now presents us with a new kernel snapshot (in this case, 3 quarters of the way between 2.6.14 and 2.6.15) and we have to test this.

A couple of kernels later, the search gives us a kernel which exhibits the bug. Telling git about this isn’t any harder:

# git bisect bad

The search continues, with the user telling git if the kernel was “good” or “bad” each time, and several reboots later we end up with the exact patch that introduced the bug:

# git bisect bad
cd8e2b48daee891011a4f21e2c62b210d24dcc9e is first bad commit
diff-tree cd8e2b48daee891011a4f21e2c62b210d24dcc9e (from d2149b542382bfc206cb28485108f6470c979566)
Author: Venkatesh Pallipadi <venkatesh .pallipadi@intel.com>
Date:   Fri Oct 21 19:22:00 2005 -0400
    [ACPI] fix 2.6.13 boot hang regression on HT box w/ broken BIOS

Ronald filed kernel bug 5930 about this. Usually this stuff is a nightmare to debug, and even though this did require many reboots to locate, it’s definately a step in the right direction. The number of bisections you need to do is obviously less if you have a smaller range to test (e.g. if he’d known that 2.6.15-rc1 was OK and 2.6.15-rc4 was bad, some time would have been saved).

Alauda driver merged

Just a quick entry to point out that my Alauda driver project (a driver for certain XD and SmartMedia card readers) has been merged upstream into Linux 2.6.16-rc1, and will be included and supported in all future releases. That’s one driver out of the way!

Recent hacking on VIA 82Cxxx IDE driver

I’ve recently been doing some hacking on the Linux VIA IDE driver. The driver now supports multiple controllers on the same system (if such a situation could ever exist) and support has been added for the VT6410 and VT8251 chipsets.

All of this is included in Linux 2.6.15.

A side effect of this work is that we had to drop the /proc/ide/via file, a dynamic text file which provided some advanced information and stats about the VIA IDE hardware present on the system, and the attached disks. This kind of querying should be done in userspace anyway, so I have produced viaideinfo to do the same thing. viaideinfo has been tested by quite a few people and is now at version 0.3. It is in portage as sys-block/viaideinfo.

Alauda driver is complete

The driver

I completed development of the Alauda driver in September and submitted the driver for inclusion to the Linux kernel.

The driver duplicates some code (checksum, media ID table) which is also present in other drivers, and it looks like we want to figure out a good way to share this code before including my work, which is a fair point – we don’t want to duplicate this yet again.

For now I’m publishing my driver as a standalone patch which people can use until we figure out the real integration details. These devices seem to be more common than I originally thought. Patch available here (against Linux 2.6.14).

Juice Box

In true open-source style, a group of hackers have taken my work and used it for something I didn’t design for: hacking the Juice Box – a portable media player based on ucLinux.

From what I gather, these devices boot from a small amount of NAND flash. To customise the device to a decent level, you need to replace this flash with your own.

Fortunately, xD media is basically NAND flash with a slightly different pin configuration, so they have done crazy things such as solder a pre-programmed XD card to the PCB:

However, you can’t just pre-program these XD cards on any old reader/writer. You need to use a device which gives you access to the physical block layout of the media, so that you can write to block 0 (amongst other things). Almost all XD reader/writer devices on the market handle physical block translation in hardware, and only provide a logical block interface to the host operating system, which does not satisfy the needs of these hackers.

The Alauda is probably the most common device that provides physical access, making writing a driver considerably harder, but allowing you to hack the media in ways such as this. I may even donate my spare Alauda device to their project.

Alauda driver now reads all XD

Quick update on the Alauda driver status:

Figured out the rest of the block addressing, so it can now support more card sizes. It also should detect the media size automatically and work “out of the box”, at least it does with the two XD cards I have here.

XD media reading is now pretty much complete, except for a few performance improvements which will be made at a later date. Next up I’ll be getting my hands on some SmartMedia and implementing read support for that.

Code is available from SourceForge CVS.