diff --git a/LDP/guide/docbook/cpg/Custom-Porting-Guide.xml b/LDP/guide/docbook/cpg/Custom-Porting-Guide.xml index d07b4ffe..ed7c46d9 100644 --- a/LDP/guide/docbook/cpg/Custom-Porting-Guide.xml +++ b/LDP/guide/docbook/cpg/Custom-Porting-Guide.xml @@ -1,4 +1,4 @@ - + @@ -142,13 +142,13 @@ host two PCI Mezzanine cards (CCPMC) - Mezzanine cards that comply with Std CCPM -Copyright & License +Copyright & License Copyright (c) 2002 Shie Elrich Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. - A copy of the license is included in . + A copy of the license is included in . @@ -195,10 +195,12 @@ kernel is not from the HardHat CD, you should enable cross-compiling in the Makefile by defining a CROSS_COMPILE entry in the following manner: (a code segment from the main Makefile) + The Linux kernel is modular, and allows you to configure it and choose which blocks should be compiled with the kernel. In order to do this, first cd /usr/src/linux @@ -231,7 +233,7 @@ and perform the following steps: Initialize the target by pressing Target|Initialize Press File|Load Executable. A dialog box will open, asking you to choose a file. Please choose your kernel image (vmlinux). Before pressing - Load, don't forget to enter a value in the +/- Bias field. + Load, don't forget to enter a value in the +/- Bias field. The bias field makes it possible to tell ICE to load a certain image in a different address than what's stated in the ELF binary. We wanted to load the kernel into address 0x300000, and since the binary was linked to 0xC0000000, we entered @@ -267,6 +269,7 @@ is it really booting? and the oldest way is good here - printing to the screen. Obviously, we couldn't use printk(), so we wrote a short function which pushes characters straight into the serial port. We used the boot process map shown in the previous section, and inserted some prints along the way. This helped us to know at what stage we are completing and where we're dying. The following piece of code prints a single character to the serial port, by polling it and waiting for it to be free. + There's a better code for printing directly to the serial port, however, it's a bit @@ -298,12 +302,14 @@ which are used to mark a certain machine, architecture or device. We defined our it CONFIG_TESTMACH), and surrounded our new/modified code with these flags: + To activate our code, we added the new flag to the kernel configuration file - .config - @@ -326,6 +332,7 @@ in our case 9600n1, and did not allow any command line options or This function determines the console configuration at startup. Here's a small part of it: + The first (naive) thing we tried, was to configure the console the way we wanted. @@ -359,7 +367,7 @@ decided it was a good time to let us know that our serial port wasn't standard. flow control were not connected. We decided to remark-out the following line, which sets the RTS and DTR lines high, because we just didn't have them. -serial_out(info, UART_MCR, UART_MCR_DTR | UART_MCR_RTS); + Ofcourse, this didn't help us much :-( The lesson learned here was check, check, check your hardware!. Custom boards might not be standard, and the porting will go a lot quicker if you know about it. @@ -376,11 +384,13 @@ using the board's local bus frequency, bus clock to system clock ratio etc. This out what the base baud was in a vxWorks system we had running on the board, and changed it to: + A quick compilation, and a reboot later we had a booting kernel visible through our serial port. Success! @@ -402,6 +412,7 @@ A quick compilation, and a reboot later we had a booting kernel visible through Once all this was done, we found todc_calibrate_descr(), which again uses the RTC chip. We had to replace that function with our own: + @@ -424,6 +436,7 @@ void calibrate_decr() { We discovered that the CPC700 can be initialized to do automatic byte-swapping, which does little-to-big endian convertion on the fly. As it seems, our board was initialized to do just that. We added a small code segment in setup_arch(), which checks if byte-swapping is enabled, and if so, disables it: + A short compilation later, PCI probing was working! We got some beer and partied ;-) @@ -452,6 +466,7 @@ A short compilation later, PCI probing was working! We got some beer and partied Our board uses an Intel ethernet chip, called i82559er, which has a module called eepro100. After compiling the module and booting, we discovered that the module isn't working, although an ethernet device was found. We guessed that it was an irq problem, and that the devices don't get the IRQs they need. We modified a function called pmppc_map_irq() to map our ethernet devices: + The function maps IRQs according to IDselects, which means in the order on the PCI bus by which the devices are set. This structure is a bit tricky: min_idsel denotes the topleft corner of the array, and max_idsel is the bottomleft corner. irqs_per_slot is the number of IRQs per line. The structure is as follows: + As you can see, our i8559er needs IRQ 22, and is seated in IDselect 3. Of course, we didn't know that at the start, so we wrote a small piece of code that read all the vendor IDs in all the IDselects. Once done we compiled, but the ethernet device still didn't work. @@ -506,11 +524,13 @@ As you can see, our i8559er needs IRQ 22, and is seated in IDselect 3. Of course As mentioned, there is another way of mapping memory - ioremap(). ioremap() is used to map physical addresses into virtual ones, making them available to the kernel. The function does not allocate any memory, simply returns a virtual address by which one can access the memory region. The following is a snippet from MMU_init(): + As you can see, we don't take the return value of ioremap(). We don't need it, since at this stage the kernel maps the addresses so that virtual address == physical address. @@ -530,6 +550,7 @@ As you can see, we don't take the return value of ioremap()After messing with cache lines, we decided to go the FP way, and added the following function: + The function adds a floating point to the PowerPC MSR register, and makes sure that no exceptions will be generated as a result of doing FP. Once done, it uses an assembly code, described below in the sysOut64() to do the actual floating-point operation. Note that the function turns off interrupts, but this is acceptable here, since we use the function on rare occasion. +