I've just apparently successfully built a scsi tape module to use with
a scsi-usb adapter - that is, I can use the tape drive!
There were quite a few gotchas en route, some of which people have
already mentioned, but some I haven't seen. Here's my summary of what
went wrong; ask for more details if you want.
I have the old firmware, with gcc installed.
The kernel is built with gcc 4.1, so I first tried to build that
directly on the Mybook, bootstrapping from the installed gcc-3.2.
Initially, this failed early on, because it tried (which it shouldn't
in a release) to build documentation, and makeinfo isn't installed.
This problem can be worked round by making with
This still failed, because of some problem about mismatch when linking
between object files compiled for hardware floating-point and for
software floating point. Googling suggested that at some point this
was a problem in gcc, probably in the specs file, but I couldn't face
understanding this. I found the suggestion that passing
—no-warn-mismatch to ld would ignore this error; but I couldn't find
a gcc configure option that would pass this option to ld whenever it
was called (setting LDFLAGS doesn't work everywhere). I eventually
gave up and replaced ld by a script that passes its argument to ld
with the —no-warn-mismatch option prepended.
I then configured with
../gcc-4.1.0/configure —enable-languages=c -enable-softfloat —disable-hardfloat
and made as above.
This still didn't work, because for some reason the automatic
configuration is not picking up that this is a uClibc system, and is
building executables that rely on ld-linux.so instead of ld-uclibc.so.
I'm sure there's an option to fix that, but again I was fed up, so I
just linked /lib/ld-uclibc.so.0 to the /lib/ld-linux.so.2 that the
compiler was putting in the executables. I guess this may mess up
normal programs in subtle ways, but I reckoned that kernel modules
don't depend on any of this stuff, so it shouldn't matter.
At this point, make install worked and gave me a 4.1 gcc in
I then unpacked the 22.214.171.124 kernel sources from the mybook package.
I did a manual configure, trying to do the easiest thing at every
Building modules was fairly straightforward - just remembering (since
I was building natively) to run with make CROSS_COMPILE= or
alternatively to edit the arm-linux-gnu out of the Makefile.
I then ran into the problems above about inserting the modules.
Firstly, to use modprobe one needs an up-to-date modules.dep .
One can edit by hand; but I decided to grab and install the depmod
utility (look for module-init-tools source).
Then I got version mismatch. My modules looked like locos' . However,
the pre-existing modules have version string
126.96.36.199 preempt mod_unload ARMv4 gcc-4.1
which gave the clue that:
- essential kernel config: enable PREEMPT
After reconfiguring and remaking, I got an st module that loaded ok,
and attached itself to the scsi tape drive.
However…whenever I tried to open the drive, the open failed, with a
kernel message from st.o that it couldn't allocate a one page buffer.
This took me three days to understand: I traced that alloc_pages was
failing in a place where it says it should never fail, and by
exploring some data structures via code my module, I found that indeed a
pointer was NULL that (supposedly) shouldn't have been. Very odd,
since obviously kernel memory allocation is working in the rest of the
I tried tweaking the most obviously related kernel config: switch on
support for EMBEDDED, and disable full-size core data structures.
Eventually a light went on, and I enabled the "optimize for size, not
speed" CC_OPTIMIZE_FOR_SIZE config option.
So, to repeat the key gotcha:
- enable CONFIG_CC_OPTIMIZE_FOR_SIZE in your kernel configuration.
I'd be happy to hear the correct way of doing all the horrible hacks I
did just to get things working.