Thursday, July 16, 2009

Probing Works--But Still Error 12

I've been off on a little side project learning SQL for something sort of interesting. So I haven't been working on my Linux stuff. But this morning is a good time to check it out. Last time, I had finally gotten the new driver to compile after getting the detection code connected and got it loaded on my USB stick. Sooo....

I rebooted my computer and from the GRUB menu, typed in 'bootp'.

There is some searching for items on the PCI bus, but here is the most important output:


bus 02, function 00, vendor 8086, device 109a
Found Intel EtherExpressPro1000 Marks Kluge at 0x3000, ROM address 0x0000
NIC_LIST start
...
NIC_LIST vendor = 8086 dev_id = 109a ioaddr=3000
NIC_LIST end
Probing...[Intel EtherExpressPro1000 Marks Kluge]e1000: hw_addr=00000000, rom_addr=00000000
Can't do this! Mark.e1000: mmio_start = 00067c3c, mmio_len = 04000000
PCI latency timer (CLFI) is unreasonably low at 0. Setting to 32 clocks.
vendor = 00008086, device = 0000109a, revision = 00000000, subsys = 0000107b
e1000_set_mac_type
e1000: Unknown MAC type

Error 12: Invalid device requested

So, progress. But still a lot of questions. Why is a mmio_start not some nice round number? Why is the PCI latency timer 0? What is the PCI latency timer? Are 0 valid values for hw_addr and rom_address?

Hopefully, these are answers I can find. I've come pretty far. The light on the horizon is fading a bit, but it's not extinguished. Stay tuned...

Tuesday, July 7, 2009

Adding a Kluge

I added a couple of things to my drivers. The big one is this addition to config.c.

{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546EB_FIBER,
"Intel EtherExpressPro1000 82545EB Fiber", 0, 0, 0, 0},
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82546GB_COPPER,
"Intel EtherExpressPro1000 82546GB Copper", 0, 0, 0, 0},
/* Mark start */
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MARKS_KLUGE,
"Intel EtherExpressPro1000 Marks Kluge", 0, 0, 0, 0},
/* Mark end */
This makes it recognize my device by telling the pci.c to expect it. I saw the debug code print out that it found it, but I still got the Error 12: Invalid device.

So I looked and found another structure I hadn't updated yet in config.c:


static struct pci_dispatch_table PCI_NIC[] =
{
...
# ifdef INCLUDE_E1000
{ PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_MARKS_KLUGE, e1000_probe },
# endif /* INCLUDE_E1000 */
...


e1000_probe is the function that finds the device and actually assigns pointers to the correct driver functions (I hope they are correct enough) to the driver struct that holds pointers.

Baby steps. It's my first time working with drivers in Linux. It sure has its challenges.

So, I make. And as you might expect, I get build errors.

Seems the e1000.c uses pci_read_config_word whereas the rest of the files use pcibios_read_config_word. The same pattern applies to a few pci BIOS access routines. Those are easy enough with #defines for the time being. But there are 2 undefined functions--pci_bar_start and pci_bar_size. This will be a little tougher. There is code out there for VirtualBox. Is it the same thing?

Well, I guess I'll post this now and see what this bar address stuff is all about. Stay tuned.

Monday, July 6, 2009

Finding The E1000 HW

I've been of doing something else for a little while, so I haven't been doing Linux stuff. But as of today, I'm back at it.

So, to recap, I can get my USB drive to boot properly and it loads stage 2. But it can't find my Intel ethernet card when I enter dhcp or bootp. So time to see what I can get it to tell me. The first step--see if I can turn on some debug information.

builtins.c is where there bootp and dhcp commands are found. They probe the drive with eth_probe(...) in config.c and e1000_probe(...) in e1000.c. Turning on DEBUG caused the build to fail. But it was a simple fix--just a printf printing a non-existent field.

So, I'm now in the process of tracking down the problem. I was lead to pci.c where it seems to be failing to find the ethernet card. I can see it looking through the stuff out there on the PCI bus.

I see things that have the Intel vendor ID (0x8086) but none that have an e1000 device ID. So I headed off to check out /proc/bus/pci and found my e1000 NIC device. It has a device ID of 0x109a. Hmmm.... My driver has a list of devices but none go that high.

Well, it's 11:30 at night right now. I guess I'll see what I can do in the morning. But I'm off again. And making progress.

Wednesday, June 17, 2009

Solving Error 12: Invalid device requested

OK, I found a problem. INCLUDE_PCI wasn't defined because I didn't have INCLUDE_E1000 in the list of drivers that bring in INCLUDE_PCI. So all is not lost!

I fixed this issue and a little hiccup with device ID definitions not being found. But now ready to reboot and see what happens...

[It is now Monday. I have been busy this weekend and won't be getting back to this until Tuesday, so I thought I'd just publish as is.]

Adding Intel E1000 Net Adapter Driver To Grub 0.97

The nice thing about getting into Linux later on, a lot of the problems have been solved. Or, at least, other people have encountered the problems and gotten things into good enough shape that they can get by. And some of those efforts are googlable.

Last night as I was drifting off, I was looking for evidence that people want to use Grub with the Intel e1000 network driver that I have on my computer. And, yes, it is true--not only did people want it--one guy was desperate for it.

I found some files at a site and copied them into a directory in my patch directory. The driver files were simply added to my netboot directory where they all are. The rest of it was makefiles. I found it easier to just modify them according to the patterns--all drivers essentially have the same patterns in the makefile. The exception being that this driver requires one more command line define so I had to make sure it was in the right places. The config.c file had to get all of these strings that describe the driver in English for users to read.

Then I had to wrestling with the configure files. Grub lets you set up makefiles with ./configure with options. I was getting problems there until I did a make clean. Then, the makefiles were setup properly.

Next, I typed 'make' and held my breath.

It wouldn't be Linux if it compiled the first time, right? I needed to add definitions for uint32_t, uint16_t, uint64_t, uint8_t and int32_t. Easy enough, although I had to check /usr/includes/limits.h to confirm that an unsigned uint64_t would be an unsigned long long.

There were a couple of PCI constants that needed copying from the patch. And I needed to get rid of an __unused in an argument list. After that it compiled!

Woohoo! But will it run?

It runs! I typed 'bootp' and...
Error 12: Invalid device requested
Sigh. Well, this is going to take some effort to solve. So, my solution (or white flag) will be in a future post...

Tuesday, June 16, 2009

Grub Success--Now For The Next Challenge

I succeeded. Grub loads off my USB stick and goes into interactive mode. I spend an hour spinning my wheels in Grub because I forgot the 'sudo' and it wasn't able to see the drives. But, it sent me to gdb and I learned a little more about Grub. And, once I had that solved, it all came together pretty quickly.

In interactive mode, there is no (hd2). But there is an (fd0). This is because the USB drive is 0x00 and since bit 7 isn't set, it is regarded as a floppy disk. I need to figure out how to either remap 0x00 to 0x82 or else force stage2 to address fd0 in LBA mode.

I also tried the 'bootp' command and it said it couldn't detect the hardware. I had compiled in the driver for an older intel 10/100 connection whereas my computer has hardware for a 10/100/1000 circuit. I would think there would be some backward compatibility. But if not, I'll see what I can do.

But those are tasks for tomorrow.

Monday, June 15, 2009

Why Stage 1 Loads Only One Sector of Stage 1.5

I thought Grub was supposed to load a 1 sector stage 1 that loads a multiple sector stage 1.5. But, that's not how it works. It actually loads 1 sector of stage 1.5 (or stage 2.0) and then that sector loads up the rest of its sectors.

Now that mystery is solved. And start.S in the stage2 directory has the courtesy of saying that one of its data sections will be filled in by the 'install' command. Though it does do this:
/* restore %ax */
popw %ax
Hmm.... Now what was %ax, again? It would be nice to know. What's the point of a comment like that? I spent a minute tracking down the push to figure out what %ax was when it was pushed--the number of sectors loaded. Sheesh!

Oh, and I learned the point of the .mode byte in stage1.S. It is to tell the next stage if it can use LBA mode or has to use CHS mode.

So--my path from here is clear. I need to make sure the part of stage1 that gets patched by the grub utility with 'nop; nop;' doesn't hold code. I'll replace that whole chunk of code with 'nop; nop;" so the patch is rendered useless. The second thing I'll do is make sure it lets me into LBA mode with the bit7 unset. That's a little 2 line snippet of code that checks the bit and jumps to the CHS section if it is set. That will be excised. I'll load it up and see what happens. And in order to really confirm that I'm getting to my own stage 1_5 start sector, I'll modify it to spew the notification string to the screen in an endless loop. That'll be the acid test.