2010-12-27

Chumby upgrade problems

My Chumby One hasn't automatically upgraded it software since I bought it earlier this year.  So I downloaded the latest firmware file onto a USB stick and did a manual upgrade.

After upgrading to "chumby one version 1.0.7 and control panel version 2.8.73" (from fw 1.0.3) via USB stick, the "My Streams" function would not produce any audio output when playing an mp3 stream URL.

  • Rebooting the Chumby did not help.
  • The volume knob moved the on screen volume slider.
  • The sound worked for the FM Radio function.

So the last resort was to log in via SSH and look around.  I was finally able to get btplay working via ssh:

killall btplayd; btplay --start-daemon --output=alsa:plug:dmixer http://202.6.74.107:8060/triplej.mp3

After running the above command once on my Chumby, it now plays My Streams properly, even after a rebooting.  All fixed.

My other complaint was that I had to re-enter all my mp3 streaming URLs, and all of my custom Alarms via the touchscreen.  Shouldn't these settings be carried forward during the upgrade ?

It's fun to see how other Embedded Linux devices are setup and managed - I am always looking to improve my professional work.

2010-09-06

Userspace access to PCI memory

Intro

When I start working on a new PCI device driver I generally go through a discovery phase of reading and writing to certain regsiters on the PCI card. Over the years I have written lots of small kernel modules to probe addresses within the PCI memory space, constantly iterating: modify code, recompile, scp to target, load module, unload module, dmesg.


Urk! There has to be a better way - sysfs and mmap() to the rescue.


Sysfs

Let's start at with the PCI files under sysfs:
bash# ls -l /sys/devices/pci0001\:00/0001\:00\:07.0/
total 0
-rw-r--r-- 1 root root     4096 Jul  2 20:13 broken_parity_status
lrwxrwxrwx 1 root root        0 Jul  2 20:13 bus -> ../../../bus/pci
-r--r--r-- 1 root root     4096 Jul  2 20:13 class
-rw-r--r-- 1 root root      256 Jul  2 20:13 config
-r--r--r-- 1 root root     4096 Jul  2 20:13 device
-r--r--r-- 1 root root     4096 Jul  2 20:13 devspec
-rw------- 1 root root     4096 Jul  2 20:13 enable
-r--r--r-- 1 root root     4096 Jul  2 20:13 irq
-r--r--r-- 1 root root     4096 Jul  2 20:13 local_cpus
-r--r--r-- 1 root root     4096 Jul  2 20:13 modalias
-rw-r--r-- 1 root root     4096 Jul  2 20:13 msi_bus
-r--r--r-- 1 root root     4096 Jul  2 20:13 resource
-rw------- 1 root root     4096 Jul  2 20:13 resource0
-rw------- 1 root root    65536 Jul  2 20:13 resource1
-rw------- 1 root root 16777216 Jul  2 20:13 resource2
lrwxrwxrwx 1 root root        0 Jul  2 20:13 subsystem -> ../../../bus/pci
-r--r--r-- 1 root root     4096 Jul  2 20:13 subsystem_device
-r--r--r-- 1 root root     4096 Jul  2 20:13 subsystem_vendor
-rw-r--r-- 1 root root     4096 Jul  2 20:13 uevent
-r--r--r-- 1 root root     4096 Jul  2 20:13 vendor

The vendor and device files report the PCI vendor ID and device ID:
bash# cat device
0x0001

This info is also available from lspci
bash# lspci -v
0001:00:07.0 Class 0680: Unknown device bec0:0001 (rev 01)
    Flags: bus master, 66MHz, medium devsel, latency 128, IRQ 31
    Memory at 8d010000 (32-bit, non-prefetchable) [size=4K]
    Memory at 8d000000 (32-bit, non-prefetchable) [size=64K]
    Memory at 8c000000 (32-bit, non-prefetchable) [size=16M]

This PCI card makes 3 separate regions of memory available to the host computer. The sysfs resource0 file corresponds to the first memory region. The PCI card lets the host computer know about these memory regions using the BAR registers in the PCI config.

mmap()

These sysfs resource can be used with mmap() to map the PCI memory into a userspace applications memory space. The application then has a pointer to the start of the PCI memory region and can read and write values directly. (There is a bit more going on here with respect to memory pointers, but that is all taken care of by the kernel).

fd = open("/sys/devices/pci0001\:00/0001\:00\:07.0/resource0", O_RDWR | O_SYNC);
ptr = mmap(0, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
printf("PCI BAR0 0x0000 = 0x%4x\n",  *((unsigned short *) ptr);

Utils

The utility application "pcimem" reads and writes single values within the PCI memory space.

bash# ./pcimem /sys/devices/pci0001\:00/0001\:00\:07.0/resource0 0 w

/sys/devices/pci0001:00/0001:00:07.0/resource0 opened.
Target offset is 0x0, page size is 4096
mmap(0, 4096, 0x3, 0x1, 3, 0x0)
PCI Memory mapped to address 0x4801f000.
Value at offset 0x0 (0x4801f000): 0xC0BE0100

Download the source: http://github.com/billfarrow/pcimem

PowerPC

To make this work on a PowerPC architecture you also need to make a small
change to the pci core. My example is from kernel 2.6.34, and hopefully this will be fixed for us in a later kernel version.

bash# vi arch/powerpc/kernel/pci-common.c

    /* If memory, add on the PCI bridge address offset */
     if (mmap_state == pci_mmap_mem) {
-#if 0 /* See comment in pci_resource_to_user() for why this is disabled */
+#if 1 /* See comment in pci_resource_to_user() for why this is disabled */
         *offset += hose->pci_mem_offset;
 #endif
         res_bit = IORESOURCE_MEM;

 
         /* We pass a fully fixed up address to userland for MMIO instead of
         * a BAR value because X is lame and expects to be able to use that
         * to pass to /dev/mem !
         *
         * That means that we'll have potentially 64 bits values where some
         * userland apps only expect 32 (like X itself since it thinks only
         * Sparc has 64 bits MMIO) but if we don't do that, we break it on
         * 32 bits CHRPs :-(
         *
         * Hopefully, the sysfs insterface is immune to that gunk. Once X
         * has been fixed (and the fix spread enough), we can re-enable the
         * 2 lines below and pass down a BAR value to userland. In that case
         * we'll also have to re-enable the matching code in
         * __pci_mmap_make_offset().
         *
         * BenH.
         */
-#if 0
+#if 1
        else if (rsrc->flags & IORESOURCE_MEM)
                offset = hose->pci_mem_offset;
#endif

2010-05-29

Macbook OS X disk recovery

This is another story of why we should all do automated backups...

Problem:
Kelly's Macbook stopped booting.  It would show the Apple Logo and a progress bar, and then just switch itself off.

Diagnosis:
To show boot sequence details; hold down the "Command" and "V" keys when powering on.  This is called the Verbose Boot Mode, and it might show you what is going wrong.  In my case the boot sequence was failing at the filesystem check:

** The volume Macintosh HD could not be repaired.

Raw Disk Backup:
Before risking further damage and loss of data, I make a backup of the entire drive.  Many failures like this are caused by a failing hard disk with bad sectors. Normal copying programs fail when they hit a back sector, so I use the GNU ddrescue tool.  This makes a low level raw copy of the disk, and attempts to recover as much data as possible from dying disks.

The ddrescue tool is available for on most Linux distributions. I used an Ubuntu computer with the Macbook hard drive attached via a SATA cable for maximum speed.  You will need to work out which disk is the macbook drive, and then run:

mount /dev/sdb1 /mnt
ddrescue /dev/sda /mnt/macbook-ddrescue.img /mnt/macbook-ddrescue.log

If ddrescue fails to fully recover all of the data from the disk due to back sectors, you can run it again to make further attempts.  Don't worry, it uses the log file to only repeat reading the parts that it couldn't copy the first time.

File Backup:
Now that I have a full raw disk image, I am less concerned about doing something wrong and loosing data.  Putting the hard drive back into the macbook and booting into Single User mode, I was able to mount the broken filesystem in read-only mode and copy the files to another backup drive over USB.  This backup drive was previously formatted with HFS+, and could be mounted in Single User Mode.

Insert the Snow Leopard Install DVD and boot it by holding "C" down while powering on.

Eventually the Snow Leopard install screen will be displayed.  Don't follow the usual install process, but select Terminal from the Utilities menu.  From the terminal we can hopefully mount the broken drive and backup the files.

mkdir  /Volumes/internal
mount -o rdonly /dev/disk0s2 /Volumes/internal

mkdir  /Volumes/backup
mount /dev/disk9s2 /Volumes/backup

ditto  -v -V /Volumes/internal /Volumes/backup/.

First Attempted fix:
Boot into Single User mode by holding down the "Command" and "S" keys while  powering on, and run the filesystem check by hand.

fsck -fy /dev/disk0s2 

If this doesn't work, try running this command to rebuild the B-Tree catalog:

fsck_hfs -r  /dev/disk0s2

Some people reported that they had to run this up to three times to finally fix their filesystem. In my case this didn't help.

Manufacturers Disk Diagnostic Tools
Most hard drive manufactures provide free tools to check and diagnose their disks for low level hardware errors.  They do this to help minimize people RMA'ing perfectly good disks due to software problems.

The Seagate tools are available as a DOS bootable CDROM image.  Run the short test first, and then the extended tests.  These tests can take several hours, so be patient.

Re-Installing Snow Leopard
Now that I have the two separate backups, I felt more confidant about erasing the Macbook drive and re-installing Snow Leopard from scratch.

Insert the OS X installation DVD and hold down the "C" key to boot from the DVD drive.

The installation process will present you with an option to restore from a backup or migrate data from another machine. I was able to plug in the USB backup drive and restore all of the user data and applications. This was the easy part - thankyou Apple.

After all that, the Macbook is up and running with everything exactly as it was. Nice.

2010-02-18

OTA Digital TV Antenna

This post is about setting up an Over-The-Air (OTA) Digital TV Antenna in Raleigh, North Carolina, USA.

Background:
Our living room TV is a large computer screen connected to a quiet Linux PC. We watch OTA Digital TV using MythTV and a Silicondust HDHomeRun tuner.  We get following channels over the air for free:

WUNC (PBS), WRAL (CBS), WTVD (ABC), WNCN (NBC), WLFL (CW), WRDC (MNT), WRPX (ION, qubo, ION Life), WRAZ (FOX, RTN).

Gray Hoverman Antenna:
I built a Gray Hoverman antenna out of a cardboard box, some fencing wire, hot glue, and a $5 balun from Radio Shack. The antenna is mounted upstairs in the loft along with the HDHomerun box and just an ethernet cable running down to the main network switch.


Local TV Transmission Towers:
The Gray Hoverman antenna is directional by design, which makes it sensitive to small variations in rotation and tilt. I used a combination of the webpages listed below and hdhomerun_config_gui which tunes into each channel and displays the signal strength.
 


Right now we point our antenna directly East so that it picks up WRAL (CBS) and most other channels except UNC (PBS) which is in the opposite direction. 



Future directions:
There are some occasional drops in signal quality which cause glitches in the picture.  If I can't improve these by tweaking the antenna position then I may have to try adding an omnidirectional antenna to my setup.  Suggestions are welcome.

Resources:
Gray Hoverman antenna plans:
http://www.digitalhome.ca/ota/superantenna/

This webpage lists the local stations around your zip code:
http://antennaweb.org

This webpage displays a Google Map of the transmission towers around major cities in the USA
http://www.hdtvmagazine.com/programming/broadcast.php