I'm pretty sure it was a fantastic success! I don't remember perfectly. I'm writing this on 2007-01-24. I don't remember who was there.
But I remember what I did. And this was the most impressive One Night of Work for me. I didn't finish the project during the three hours, though. I did about half of it, and then the other half just naturally during the rest of the week.
The problem is going to take like three big paragraphs to motivate. so, settle down for some long rant-reading.
I'm working on an XBox. Its DVD-ROM drive is broken. I tried to order another one from etech4sale.com, and they charged me $35 for a DOA drive that I had to send back. They said they don't have any more of the good kind of drive in stock. Even when you get a good XBox DVD-ROM, they aren't that good. Most of them can't read CDR's. The Samsung is supposedly the best, which we have in an older XBox, and it also sucks. It sucks at reading scratched DVD's. The drive in my Sun can read them way better.
so, what do I do? Use my credit card with increasingly shady Interweb vendors just to get another crappy used XBox drive for $35? For $38 shipping-included I can get a Samsung SH-S182D, a dual-layer writer with great reviews on the Interweb. It's actually ``Toshiba-Samsung Storage Technology,'' and the same damn drive is sold as the Sony DRU-830A. I used it to burn most of my christmas gifts, and it's capable of writing a DVD+R at 4x in what seems to be CLV mode, so (1) you don't need a tricked-out gamer box capable of feeding it at high data rate in order to get a good burn, and (2) CLV mode means no unsightly speed-change rings. It has great reviews on the Interweb. The only mark against: it was unable to read certain crippled round discs with music on them, discs which cannot legally be called CD-ROMs anyway. And it's basically cheaper than an XBox drive. I'd be stupid not to get this instead.
The front covers on the trays of all CD-ROM drives are snap-on and interchangeable, so believe it or not, I think it's possible to rip the faceplate off the TSST drive, swap the trayplate with the chunky XBox plate, and have an XBox that looks original!
The XBox drive has a half-cylinder bite taken out of the left side to make room for a long structural screw that holds the top and bottom of the XBox together. I will have to dremmel the new drive into the XBox and leave out this screw, making the case a little more fragile.
The XBox DVD-ROM has a custom power-and-eject jack on the back. It was easy to cut a molex wire off a dead ATX supply and solder it into the XBox for power. I'd done that already.
Also on the power-and-eject jack, there is an output pin indicating
the tray position, a Load input-pin, and an Eject input-pin. All
three go to the PIC microcontroller. Then, there's a button on the
front of the XBox that sends PIC-Interrupts when you press it. XBox
Linux has added a PIC driver and mangled the IDE CD-ROM driver. On
all drives, the Eject button works using the Tray position, Load, and
Eject pins on the power-and-eject jack, so the Eject button will not
work with my TSST DVD writer. On certain drives, the
eject and eject -t shell-prompt commands
(and the ioctl they send) are implemented through the Load and Eject
pins on the power-and-eject jack as well. But on normal drives and
certain other XBox drives, these commands are sent over the IDE bus
just like on a regular PeeCee.
I need the Eject button to send commands over the IDE bus. This is a tricky proposition because of ATAPI's primitive, quirky way of handling the return of status/error information. Commands can take 30 seconds to complete. The whole bus can be locked out while the command is outstanding. Example: if you have a volume manager running, it could be probing the CD-ROM every second to ask if a new disk has been inserted. If one has, the CD-ROM could refuse to answer the question for 30 seconds while it tries to determine the medium type and read the TOC. During this 30 seconds, access to your root filesystem could be frozen. It's flaming crap.
It also means implementing something simple like, ``If someone presses the button, then check if the tray is closed. If it's closed, open it. If it's open, close it.'' is not sufficient. Each step could take tens of seconds, and commands to open and close could queue up from repeated button-presses. A furious button-tapper could launch off fifteen minutes of highly frustrating tray gyrations.
The existing code was an interrupt handler plus a kernel thread. I use an interrupt handler plus two kernel threads: one thread interacts with the PIC to keep it happy, because the PIC demands immediate answers, and if the PIC becomes angry it will reboot the machine. The second thread is the one that gets to sleep waiting for ATAPI bullshit. All three contexts are synchronized using semaphores.
Here is the diff (latest version) and one of my comments:
/*
* now, our job is to determine based on context what the user meant by
* jabbing the button---to open, or to close?
*
* here is what I do as a user:
* if the drive is closed, and I want it open:
* I jab the button.
* If it doesn't open instantly, I growl, curse Microsoft, and then jab
* the button two or three more times in <1sec.
* if the drive is open, and I want it closed:
* I backhand the tray and expect the drive to notice and suck in
* if the drive doesn't notice I shove the tray again.
* if it's still not closing I might press the button
* if the tray is stuck and won't budge, I press the button. I have one
* Samsung drive with a broken gear (from too vigorous backhanding?)
* that can't be shoved closed, so making the button open-only is no good.
* if the drive is neither open nor closed:
* I press the button about once per second until the tray starts moving
* in the direction I want it to, then quit pressing and wait about five
* seconds.
* If the tray won't settle and keeps moving in/out, I grab it, and stop it
* from moving. When I can feel its pressure going in the direction I want,
* I let go.
*
* ATAPI doesn't give us as much information or as low latency as the PIC control
* lines on the proprietary XBox drive, so we will just have to accomodate the above
* as best we can.
*/
I don't account for all those use-cases in my state machine. The finished system is not as snappy as the hardware button on the front of some CD-ROM's, but it is not too frustrating, and it will never queue more than one ATAPI command so the 15min tray gyrations are impossible.
In addition, I've moved the code that implements eject
and eject -t behind a semaphore so that the state machine
behind the Eject button is aware of ioctl()-induced tray movement.
That was a bitch, because Linux has three layers of CD-ROM abstraction
and is schitzophrenic about which layer belongs above which other, and
is full of necrotic tray-movement code that never gets executed, or
worse yet is clearly meant to never be executed but still is in one
particular corner case where a tray movement is done implicitly rather
than explicitly. seriously, it's garbage. BSD and Solaris might not
work as well, but from a programmer's perspective their quality blasts
Linux out of the water.
What's left TODO, is add this patch to my Gentoo ebuild, and test it with one of the original XBox DVD-ROM's. The latter test is limited because I don't have all the different kinds of drives, just one model, and the different models of original XBox drive are treated differently by Linux. Finally ide and ide-cd should be tested as a module instead of compiled in. My changes should fix the kernel-panics-if-ide-is-module bug induced by the old XBox patches, but I haven't tested yet. The ebuild should then be changed so the .config puts ide in the initrd by default. For an NFS-rooted XBox, this is appropriate.
I was also thinking of connecting the ring-light to the Eject state machine. I think that would be comparatively easy, and a better use of the light than just leaving it to some Thomas Pedley userland peek-poke craplet, but it would require adding vold-like ATAPI polling which brings on the ATAPI nightmare I described above. I mean, everyone else does it. I could do it. but making the thing needlessly less stable for the sake of a gimmick seems wrong.