[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

[PATCH] Firmware removal



On Sun, 2008-10-19 at 03:11 +0100, Ben Hutchings wrote:
[...]
> My modified firmware-nonfree is at <http://womble.decadent.org.uk/tmp/>.
> I'll post a new patch for linux-2.6 tomorrow.

Sorry for the delay, I was too tired yesterday to get this finished.
The patch against SVN follows.

The modified linux-2.6 and firmware-nonfree source packages, and the
linux-source-2.6.26 and firmware-* binary packages, can be found in:
http://people.debian.org/~benh/firmware-removal/

Please test them if you can.  I have only been able to test the radeon
changes myself.

Index: linux-2.6/debian/changelog
===================================================================
--- linux-2.6/debian/changelog	(revision 12348)
+++ linux-2.6/debian/changelog	(working copy)
@@ -1,3 +1,22 @@
+linux-2.6 (2.6.26.dfsg.1-10) unstable; urgency=low
+
+  * Remove firmware from drivers and make them use request_firmware():
+    - cassini (closes: #498631)
+    - dabusb (closes: #502663)
+    - e100 (closes: #494308)
+    - kaweth (closes: #502665)
+    - mga (closes: #502666)
+    - qla1280 (closes: #502667)
+    - r128 (closes: #494007)
+    - radeon (closes: #494009)
+    - starfire (closes: #501152)
+    - tehuti (closes: #501153)
+    - typhoon (closes: #502669)
+    - whiteheat (closes: #502668)
+  * Add source for dsp56k firmware (closes: #494010)
+
+ -- Ben Hutchings <ben@decadent.org.uk>  Sun, 19 Oct 2008 19:59:26 +0100
+
 linux-2.6 (2.6.26-9) unstable; urgency=low
 
   [ Bastian Blank ]
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-cassini-disable.patch	(revision 0)
@@ -0,0 +1,45 @@
+From 524d72dfc7d9be55e7b41d21213e555c0b9b5a1a Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:01:11 +0100
+Subject: [PATCH] cassini: Add #ifdef markers around firmware and mark broken
+
+---
+ drivers/net/Kconfig   |    1 +
+ drivers/net/cassini.h |    2 ++
+ 2 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 0836ea8..9426787 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -584,6 +584,7 @@ config SUNGEM
+ config CASSINI
+ 	tristate "Sun Cassini support"
+ 	depends on PCI
++	depends on BROKEN
+ 	select CRC32
+ 	help
+ 	  Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
+index 552af89..6e8650c 100644
+--- a/drivers/net/cassini.h
++++ b/drivers/net/cassini.h
+@@ -2514,6 +2514,7 @@ static cas_hp_inst_t cas_prog_null[] = { {NULL} };
+ #define CAS_HP_FIRMWARE               cas_prog_null
+ #endif
+ 
++#ifdef REMOVE_DFSG
+ /* firmware patch for NS_DP83065 */
+ typedef struct cas_saturn_patch {
+ 	u16 addr;
+@@ -4029,6 +4030,7 @@ cas_saturn_patch_t cas_saturn_patch[] = {
+ {0x8aca,    0x0039}, { 0x0, 0x0 }
+ };
+ #endif
++#endif /* REMOVE_DFSG */
+ 
+ 
+ /* phy types */
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-media-video-dabusb-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From a2189e45ec8dfa32e028c7b5d6e6632af2543a7e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 13:33:37 +0100
+Subject: [PATCH] dabusb: Mark as broken
+
+---
+ drivers/media/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index 7a7803b..ec7baaa 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -125,6 +125,7 @@ if DAB
+ config USB_DABUSB
+ 	tristate "DABUSB driver"
+ 	depends on USB
++	depends on BROKEN
+ 	---help---
+ 	  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ 	  brought to you by the DAB-Team
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/files-1
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/files-1	(revision 12348)
+++ linux-2.6/debian/patches/debian/dfsg/files-1	(working copy)
@@ -9,10 +9,18 @@
 rm drivers/atm/pca200e_ecd.data
 rm drivers/atm/sba200e_ecd.data
 
+rm drivers/char/drm/mga_ucode.h
+
+unifdef drivers/char/drm/r128_cce.c -UREMOVE_DFSG
+
+rm drivers/char/drm/radeon_microcode.h
+
 rm drivers/char/ip2/fip_firm.h
 
 rm drivers/media/dvb/ttusb-budget/dvb-ttusb-dspbootcode.h
 
+rm drivers/media/video/dabfirmware.h
+
 rm drivers/net/acenic_firmware.h
 
 unifdef drivers/net/tg3.c -UREMOVE_DFSG
@@ -27,11 +35,19 @@
 
 rm drivers/net/bnx2x_init_values.h
 
+unifdef drivers/net/cassini.h -UREMOVE_DFSG
+
+unifdef drivers/net/e100.c -UREMOVE_DFSG
+
 rm drivers/net/hamradio/yam1200.h
 rm drivers/net/hamradio/yam9600.h
 
 rm drivers/net/myri_code.h
 
+rm drivers/net/starfire_firmware.h
+
+rm drivers/net/tehuti_fw.h
+
 rm drivers/net/tokenring/3c359.c
 rm drivers/net/tokenring/3c359.h
 rm drivers/net/tokenring/3c359_microcode.h
@@ -40,6 +56,14 @@
 rm drivers/net/tokenring/smctr.h
 rm drivers/net/tokenring/smctr_firmware.h
 
+rm drivers/net/typhoon-firmware.h
+
+rm drivers/net/usb/kawethfw.h
+
+rm drivers/scsi/ql1040_fw.h
+rm drivers/scsi/ql12160_fw.h
+rm drivers/scsi/ql1280_fw.h
+
 rm drivers/scsi/qlogicpti_asm.c
 
 rm drivers/usb/misc/emi26.c
@@ -62,6 +86,8 @@
 rm drivers/usb/serial/keyspan_usa49w_fw.h
 rm drivers/usb/serial/keyspan_usa49wlc_fw.h
 
+rm drivers/usb/serial/whiteheat_fw.h
+
 rm sound/pci/cs46xx/cs46xx_image.h
 rm sound/pci/cs46xx/imgs
 unifdef sound/pci/korg1212/korg1212.c -UCONFIG_SND_KORG1212_FIRMWARE_IN_KERNEL
Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-r128-disable.patch	(revision 0)
@@ -0,0 +1,45 @@
+From 9122274287bc54d52cee7b79f879fd2715333826 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 00:40:17 +0100
+Subject: [PATCH] r128: Add #ifdef markers around firmware and mark broken
+
+---
+ drivers/char/drm/Kconfig    |    1 +
+ drivers/char/drm/r128_cce.c |    2 ++
+ 2 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index 610d6fd..8f9c893 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -26,6 +26,7 @@ config DRM_TDFX
+ config DRM_R128
+ 	tristate "ATI Rage 128"
+ 	depends on DRM && PCI
++	depends on BROKEN
+ 	help
+ 	  Choose this option if you have an ATI Rage 128 graphics card.  If M
+ 	  is selected, the module will be called r128.  AGP support for
+diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
+index c31afbd..04d8358 100644
+--- a/drivers/char/drm/r128_cce.c
++++ b/drivers/char/drm/r128_cce.c
+@@ -36,6 +36,7 @@
+ 
+ #define R128_FIFO_DEBUG		0
+ 
++#ifdef REMOVE_DFSG
+ /* CCE microcode (from ATI) */
+ static u32 r128_cce_microcode[] = {
+ 	0, 276838400, 0, 268449792, 2, 142, 2, 145, 0, 1076765731, 0,
+@@ -80,6 +81,7 @@ static u32 r128_cce_microcode[] = {
+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
++#endif /* REMOVE_DFSG */
+ 
+ static int R128_READ_PLL(struct drm_device * dev, int addr)
+ {
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-scsi-qla1280-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From dbb422c3adf3bb2e9721203e407d4236daf1f4c3 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:14:43 +0100
+Subject: [PATCH] qla1280: Mark as broken
+
+---
+ drivers/scsi/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 81ccbd7..94831ae 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -1316,6 +1316,7 @@ config SCSI_QLOGIC_FC_FIRMWARE
+ config SCSI_QLOGIC_1280
+ 	tristate "Qlogic QLA 1240/1x80/1x160 SCSI support"
+ 	depends on PCI && SCSI
++	depends on BROKEN
+ 	help
+ 	  Say Y if you have a QLogic ISP1240/1x80/1x160 SCSI host adapter.
+ 
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-char-dsp56k-fw-source.patch	(revision 0)
@@ -0,0 +1,104 @@
+diff --git a/firmware/dsp56k/bootstrap.asm b/firmware/dsp56k/bootstrap.asm
+new file mode 100644
+index 0000000..10d8919
+--- /dev/null
++++ b/firmware/dsp56k/bootstrap.asm
+@@ -0,0 +1,98 @@
++; Author: Frederik Noring <noring@nocrew.org>
++;
++; This file is subject to the terms and conditions of the GNU General Public
++; License.  See the file COPYING in the main directory of this archive
++; for more details.
++
++; DSP56k loader
++
++; Host Interface
++M_BCR   EQU     $FFFE           ; Port A Bus Control Register
++M_PBC   EQU     $FFE0           ; Port B Control Register
++M_PBDDR EQU     $FFE2           ; Port B Data Direction Register
++M_PBD   EQU     $FFE4           ; Port B Data Register
++M_PCC   EQU     $FFE1           ; Port C Control Register
++M_PCDDR EQU     $FFE3           ; Port C Data Direction Register
++M_PCD   EQU     $FFE5           ; Port C Data Register
++
++M_HCR   EQU     $FFE8           ; Host Control Register
++M_HSR   EQU     $FFE9           ; Host Status Register
++M_HRX   EQU     $FFEB           ; Host Receive Data Register
++M_HTX   EQU     $FFEB           ; Host Transmit Data Register
++
++; SSI, Synchronous Serial Interface
++M_RX    EQU     $FFEF           ; Serial Receive Data Register
++M_TX    EQU     $FFEF           ; Serial Transmit Data Register
++M_CRA   EQU     $FFEC           ; SSI Control Register A
++M_CRB   EQU     $FFED           ; SSI Control Register B
++M_SR    EQU     $FFEE           ; SSI Status Register
++M_TSR   EQU     $FFEE           ; SSI Time Slot Register
++
++; Exception Processing
++M_IPR   EQU     $FFFF           ; Interrupt Priority Register
++
++        org     P:$0
++start   jmp     <$40
++
++        org     P:$40
++;       ; Zero 16384 DSP X and Y words
++;       clr     A #0,r0
++;       clr     B #0,r4
++;       do      #64,<_block1
++;       rep     #256
++;       move    A,X:(r0)+ B,Y:(r4)+
++;_block1        ; Zero (32768-512) Program words
++;       clr     A #512,r0
++;       do      #126,<_block2
++;       rep     #256
++;       move    A,P:(r0)+
++;_block2
++
++        ; Copy DSP program control
++        move    #real,r0
++        move    #upload,r1
++        do      #upload_end-upload,<_copy
++        move    P:(r0)+,x0
++        move    x0,P:(r1)+
++_copy   movep   #>4,X:<<M_HCR
++        movep   #>$c00,X:<<M_IPR
++        and     #<$fe,mr
++        jmp     upload
++
++real
++        org     P:$7ea9
++upload
++        movep   #>1,X:<<M_PBC
++        movep   #>0,X:<<M_BCR
++
++next    jclr    #0,X:<<M_HSR,*
++        movep   X:<<M_HRX,A
++        move    #>3,x0
++        cmp     x0,A #>1,x0
++        jeq     <$0
++_get_address
++        jclr    #0,X:<<M_HSR,_get_address
++        movep   X:<<M_HRX,r0
++_get_length
++        jclr    #0,X:<<M_HSR,_get_length
++        movep   X:<<M_HRX,y0
++        cmp     x0,A #>2,x0
++        jeq     load_X
++        cmp     x0,A
++        jeq     load_Y
++
++load_P  do      y0,_load
++        jclr    #0,X:<<M_HSR,*
++        movep   X:<<M_HRX,P:(r0)+
++_load   jmp     next
++load_X  do      y0,_load
++        jclr    #0,X:<<M_HSR,*
++        movep   X:<<M_HRX,X:(r0)+
++_load   jmp     next
++load_Y  do      y0,_load
++        jclr    #0,X:<<M_HSR,*
++        movep   X:<<M_HRX,Y:(r0)+
++_load   jmp     next
++
++upload_end
++        end
Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-radeon-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From 32e3f3ea4c0aed82f3e79c84060126d8e5a0038e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 01:21:34 +0100
+Subject: [PATCH] radeon: Mark as broken
+
+---
+ drivers/char/drm/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index ea26dfd..3b0dd6a 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -35,6 +35,7 @@ config DRM_R128
+ config DRM_RADEON
+ 	tristate "ATI Radeon"
+ 	depends on DRM && PCI
++	depends on BROKEN
+ 	help
+ 	  Choose this option if you have an ATI Radeon graphics card.  There
+ 	  are both PCI and AGP versions.  You don't need to choose this to
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-typhoon-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From 74c4e0c5cd3183c6a0535e00517e662822810f8e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 14:07:10 +0100
+Subject: [PATCH] typhoon: Mark as broken
+
+---
+ drivers/net/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 616db30..25902d7 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -731,6 +731,7 @@ config VORTEX
+ config TYPHOON
+ 	tristate "3cr990 series \"Typhoon\" support"
+ 	depends on NET_VENDOR_3COM && PCI
++	depends on BROKEN
+ 	select CRC32
+ 	---help---
+ 	  This option enables driver support for the 3cr990 series of cards:
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-tehuti-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From 87460126549f1142c958c1ddda0b52569fc353d2 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:43:20 +0100
+Subject: [PATCH] tehuti: Mark as broken
+
+---
+ drivers/net/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index a167a5e..8cec089 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -2570,6 +2570,7 @@ config MLX4_DEBUG
+ config TEHUTI
+ 	tristate "Tehuti Networks 10G Ethernet"
+ 	depends on PCI
++	depends on BROKEN
+ 	help
+ 	  Tehuti Networks 10G Ethernet NIC
+ 
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-usb-serial-whiteheat-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From dab9a198bf25cf06aab4af5cd75bb9b2ac97299d Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:45:07 +0100
+Subject: [PATCH] whiteheat: Mark as broken
+
+---
+ drivers/usb/serial/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index 9ba64cc..96f811b 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -102,6 +102,7 @@ config USB_SERIAL_CH341
+ 
+ config USB_SERIAL_WHITEHEAT
+ 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
++	depends on BROKEN
+ 	select USB_EZUSB
+ 	help
+ 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-e100-disable.patch	(revision 0)
@@ -0,0 +1,45 @@
+From 9b32fded74fd68bf33a0114344715f48905c8a8f Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 01:49:15 +0100
+Subject: [PATCH] e100: Add #ifdef markers around firmware and mark broken
+
+---
+ drivers/net/Kconfig |    1 +
+ drivers/net/e100.c  |    2 ++
+ 2 files changed, 3 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index f4182cf..ac4ee2d 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1442,6 +1442,7 @@ config EEPRO100
+ config E100
+ 	tristate "Intel(R) PRO/100+ support"
+ 	depends on NET_PCI && PCI
++	depends on BROKEN
+ 	select MII
+ 	---help---
+ 	  This driver supports Intel(R) PRO/100 family of adapters.
+diff --git a/drivers/net/e100.c b/drivers/net/e100.c
+index 1037b13..e842718 100644
+--- a/drivers/net/e100.c
++++ b/drivers/net/e100.c
+@@ -1049,6 +1049,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+ 		c[16], c[17], c[18], c[19], c[20], c[21], c[22], c[23]);
+ }
+ 
++#ifdef REMOVE_DFSG
+ /********************************************************/
+ /*  Micro code for 8086:1229 Rev 8                      */
+ /********************************************************/
+@@ -1186,6 +1187,7 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ }
++#endif /* REMOVE_DFSG */
+ 
+ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+ {
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-usb-kaweth-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From e31ad6c4e29509bf9c2bfcdbfc29b8534585bb71 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:11:28 +0100
+Subject: [PATCH] kaweth: Mark as broken
+
+---
+ drivers/net/usb/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
+index 0604f3f..2c0b805 100644
+--- a/drivers/net/usb/Kconfig
++++ b/drivers/net/usb/Kconfig
+@@ -29,6 +29,7 @@ config USB_CATC
+ 
+ config USB_KAWETH
+ 	tristate "USB KLSI KL5USB101-based ethernet device support"
++	depends on BROKEN
+ 	---help---
+ 	  Say Y here if you want to use one of the following 10Mbps only
+ 	  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-char-drm-mga-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From f94f9c90f7a67262b174efac6783e8ad2a40009e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 02:46:55 +0100
+Subject: [PATCH] mga: Mark as broken
+
+---
+ drivers/char/drm/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index 17edd8a..1a3d250 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -81,6 +81,7 @@ endchoice
+ config DRM_MGA
+ 	tristate "Matrox g200/g400"
+ 	depends on DRM
++	depends on BROKEN
+ 	help
+ 	  Choose this option if you have a Matrox G200, G400 or G450 graphics
+ 	  card.  If M is selected, the module will be called mga.  AGP
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch	(revision 0)
+++ linux-2.6/debian/patches/debian/dfsg/drivers-net-starfire-disable.patch	(revision 0)
@@ -0,0 +1,24 @@
+From de1dfbcd060a33ad0d434a0891c3c6544cf90a83 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:09:01 +0100
+Subject: [PATCH] starfire: Mark as broken
+
+---
+ drivers/net/Kconfig |    1 +
+ 1 files changed, 1 insertions(+), 0 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index eaacc85..ae6d38f 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1304,6 +1304,7 @@ config AMD8111E_NAPI
+ config ADAPTEC_STARFIRE
+ 	tristate "Adaptec Starfire/DuraLAN support"
+ 	depends on NET_PCI && PCI
++	depends on BROKEN
+ 	select CRC32
+ 	select MII
+ 	help
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/series/10
===================================================================
--- linux-2.6/debian/patches/series/10	(revision 0)
+++ linux-2.6/debian/patches/series/10	(revision 0)
@@ -0,0 +1,14 @@
+- features/all/firmware-ihex-early.patch
++ features/all/firmware-ihex.patch
++ features/all/drivers-char-drm-mga-request_firmware.patch
++ features/all/drivers-char-drm-r128-request_firmware.patch
++ features/all/drivers-char-drm-radeon-request_firmware.patch
++ features/all/drivers-media-video-dabusb-request_firmware.patch
++ features/all/drivers-net-cassini-request_firmware.patch
++ features/all/drivers-net-e100-request_firmware.patch
++ features/all/drivers-net-starfire-request_firmware.patch
++ features/all/drivers-net-tehuti-request_firmware.patch
++ features/all/drivers-net-typhoon-request_firmware.patch
++ features/all/drivers-net-usb-kaweth-request_firmware.patch
++ features/all/drivers-scsi-qla1280-request_firmware.patch
++ features/all/drivers-usb-serial-whiteheat-request_firmware.patch
Index: linux-2.6/debian/patches/series/orig-1
===================================================================
--- linux-2.6/debian/patches/series/orig-1	(revision 0)
+++ linux-2.6/debian/patches/series/orig-1	(revision 0)
@@ -0,0 +1,30 @@
++ debian/dfsg/drivers-char-drm-r128-disable.patch
++ debian/dfsg/drivers-net-cassini-disable.patch
++ debian/dfsg/drivers-net-e100-disable.patch
++ debian/dfsg/drivers-net-tg3-mark.patch
+X debian/dfsg/files-1
++ debian/dfsg/drivers-atm.patch
++ debian/dfsg/drivers-char-computone.patch
++ debian/dfsg/drivers-char-drm-mga-disable.patch
++ debian/dfsg/drivers-char-drm-radeon-disable.patch
++ debian/dfsg/drivers-char-dsp56k-fw-source.patch
++ debian/dfsg/drivers-media-video-dabusb-disable.patch
++ debian/dfsg/drivers-media-dvb-ttusb-budget.patch
++ debian/dfsg/drivers-net-acenic-remove.patch
++ debian/dfsg/drivers-net-bnx2-disable.patch
++ debian/dfsg/drivers-net-bnx2x-disable.patch
++ debian/dfsg/drivers-net-appletalk-cops.patch
++ debian/dfsg/drivers-net-hamradio-yam.patch
++ debian/dfsg/drivers-net-myri.patch
++ debian/dfsg/drivers-net-starfire-disable.patch
++ debian/dfsg/drivers-net-tehuti-disable.patch
++ debian/dfsg/drivers-net-tg3-remove.patch
++ debian/dfsg/drivers-net-tokenring-3c359-smctr.patch
++ debian/dfsg/drivers-net-typhoon-disable.patch
++ debian/dfsg/drivers-net-usb-kaweth-disable.patch
++ debian/dfsg/drivers-scsi-qla1280-disable.patch
++ debian/dfsg/drivers-scsi-qlogicpti.patch
++ debian/dfsg/drivers-usb-misc-emi62-emi26.patch
++ debian/dfsg/drivers-usb-serial-keyspan-remove.patch
++ debian/dfsg/drivers-usb-serial-whiteheat-disable.patch
++ debian/dfsg/sound-pci.patch
Index: linux-2.6/debian/patches/features/all/firmware-ihex-early.patch
===================================================================
--- linux-2.6/debian/patches/features/all/firmware-ihex-early.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/firmware-ihex-early.patch	(revision 0)
@@ -0,0 +1,35 @@
+diff --git a/include/linux/ihex.h b/include/linux/ihex.h
+new file mode 100644
+index 0000000..902222f
+--- /dev/null
++++ b/include/linux/ihex.h
+@@ -0,0 +1,28 @@
++/*
++ * Compact binary representation of ihex records. Some devices need their
++ * firmware loaded in strange orders rather than a single big blob, but 
++ * actually parsing ihex-as-text within the kernel seems silly. Thus,...
++ */
++
++#ifndef __LINUX_IHEX_H__
++#define __LINUX_IHEX_H__
++
++#include <linux/types.h>
++
++struct ihex_binrec {
++	__be32 addr;
++	uint8_t len;
++	uint8_t data[0];
++} __attribute__((aligned(4)));
++
++/* Find the next record, taking into account the 4-byte alignment */
++static inline const struct ihex_binrec *
++ihex_next_binrec(const struct ihex_binrec *rec)
++{
++	int next = ((rec->len + 4) & ~3) - 1;
++	rec = (void *)&rec->data[next];
++
++	return rec->len ? rec : NULL;
++}
++
++#endif /* __LINUX_IHEX_H__ */
+
Index: linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-typhoon-request_firmware.patch	(revision 0)
@@ -0,0 +1,167 @@
+From c2bd127e355be09451b57eac3e7e0439e4a912e2 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:04:33 +0100
+Subject: [PATCH] typhoon: use request_firmware
+
+Based on patch by Jaswinder Singh <jaswinder@infradead.org>,
+with additional validation of the firmware size.
+
+made following const as we treat firmware data as const:
+        struct typhoon_file_header *fHdr
+        struct typhoon_section_header *sHdr
+        u8 *image_data
+---
+ drivers/net/Kconfig   |    2 +-
+ drivers/net/typhoon.c |   74 +++++++++++++++++++++++++++++++++++++++++--------
+ 2 files changed, 63 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 25902d7..7a9316b 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -731,7 +731,7 @@ config VORTEX
+ config TYPHOON
+ 	tristate "3cr990 series \"Typhoon\" support"
+ 	depends on NET_VENDOR_3COM && PCI
+-	depends on BROKEN
++	select FW_LOADER
+ 	select CRC32
+ 	---help---
+ 	  This option enables driver support for the 3cr990 series of cards:
+diff --git a/drivers/net/typhoon.c b/drivers/net/typhoon.c
+index c0dd25b..2134240 100644
+--- a/drivers/net/typhoon.c
++++ b/drivers/net/typhoon.c
+@@ -130,16 +130,18 @@ static const int multicast_filter_limit = 32;
+ #include <linux/in6.h>
+ #include <linux/version.h>
+ #include <linux/dma-mapping.h>
++#include <linux/firmware.h>
+ 
+ #include "typhoon.h"
+-#include "typhoon-firmware.h"
+ 
+ static char version[] __devinitdata =
+     "typhoon.c: version " DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
++#define FIRMWARE_NAME		"3com/typhoon.bin"
+ MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
+ MODULE_VERSION(DRV_MODULE_VERSION);
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_NAME);
+ MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
+ MODULE_PARM_DESC(rx_copybreak, "Packets smaller than this are copied and "
+ 			       "the buffer given back to the NIC. Default "
+@@ -1347,14 +1349,60 @@ typhoon_init_rings(struct typhoon *tp)
+ 	tp->txHiRing.lastRead = 0;
+ }
+ 
++static const struct firmware *typhoon_fw;
++
++static int typhoon_init_firmware(struct typhoon *tp)
++{
++	const struct typhoon_file_header *fHdr;
++	const struct typhoon_section_header *sHdr;
++	u32 numSections;
++	u32 len;
++	int i;
++	int err;
++
++	err = request_firmware(&typhoon_fw, FIRMWARE_NAME, &tp->pdev->dev);
++	if (err) {
++		printk(KERN_ERR "%s: Failed to load firmware \"%s\"\n",
++		       tp->name, FIRMWARE_NAME);
++		return err;
++	}
++
++	fHdr = (const struct typhoon_file_header *) typhoon_fw->data;
++	if (typhoon_fw->size < sizeof(*fHdr) || memcmp(fHdr->tag, "TYPHOON", 8)) {
++		err = -EINVAL;
++		goto out;
++	}
++	numSections = le32_to_cpup(&fHdr->numSections);
++	len = sizeof(*fHdr);
++	for (i = 0; i < numSections; i++) {
++		if (typhoon_fw->size < len + sizeof(*sHdr)) {
++			err = -EINVAL;
++			break;
++		}
++		sHdr = (const struct typhoon_section_header *)
++			(typhoon_fw->data + len);
++		len += sizeof(*sHdr) + le32_to_cpup(&sHdr->len);
++	}
++	if (typhoon_fw->size != len)
++		err = -EINVAL;
++
++out:
++	if (err) {
++		printk(KERN_ERR "%s: Invalid firmware image \"%s\"\n",
++		       tp->name, FIRMWARE_NAME);
++		release_firmware(typhoon_fw);
++	}
++	return err;
++}
++
+ static int
+ typhoon_download_firmware(struct typhoon *tp)
+ {
+ 	void __iomem *ioaddr = tp->ioaddr;
+ 	struct pci_dev *pdev = tp->pdev;
+-	struct typhoon_file_header *fHdr;
+-	struct typhoon_section_header *sHdr;
+-	u8 *image_data;
++	const struct typhoon_file_header *fHdr;
++	const struct typhoon_section_header *sHdr;
++	const u8 *image_data;
+ 	void *dpage;
+ 	dma_addr_t dpage_dma;
+ 	__sum16 csum;
+@@ -1369,13 +1417,8 @@ typhoon_download_firmware(struct typhoon *tp)
+ 	int err;
+ 
+ 	err = -EINVAL;
+-	fHdr = (struct typhoon_file_header *) typhoon_firmware_image;
+-	image_data = (u8 *) fHdr;
+-
+-	if(memcmp(fHdr->tag, "TYPHOON", 8)) {
+-		printk(KERN_ERR "%s: Invalid firmware image!\n", tp->name);
+-		goto err_out;
+-	}
++	fHdr = (const struct typhoon_file_header *) typhoon_fw->data;
++	image_data = typhoon_fw->data;
+ 
+ 	/* Cannot just map the firmware image using pci_map_single() as
+ 	 * the firmware is part of the kernel/module image, so we allocate
+@@ -1428,7 +1471,7 @@ typhoon_download_firmware(struct typhoon *tp)
+ 	 * we don't need a typhoon_post_pci_writes() after it.
+ 	 */
+ 	for(i = 0; i < numSections; i++) {
+-		sHdr = (struct typhoon_section_header *) image_data;
++		sHdr = (const struct typhoon_section_header *) image_data;
+ 		image_data += sizeof(struct typhoon_section_header);
+ 		load_addr = le32_to_cpu(sHdr->startAddr);
+ 		section_len = le32_to_cpu(sHdr->len);
+@@ -2445,6 +2488,10 @@ typhoon_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 	 */
+ 	tp->name = pci_name(pdev);
+ 
++	err = typhoon_init_firmware(tp);
++	if (err)
++		goto error_out_reset;
++
+ 	typhoon_init_interface(tp);
+ 	typhoon_init_rings(tp);
+ 
+@@ -2595,6 +2642,9 @@ typhoon_remove_one(struct pci_dev *pdev)
+ 	pci_set_power_state(pdev, PCI_D0);
+ 	pci_restore_state(pdev);
+ 	typhoon_reset(tp->ioaddr, NoWait);
++
++	release_firmware(typhoon_fw);
++
+ 	pci_iounmap(pdev, tp->ioaddr);
+ 	pci_free_consistent(pdev, sizeof(struct typhoon_shared),
+ 			    tp->shared, tp->shared_dma);
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-tehuti-request_firmware.patch	(revision 0)
@@ -0,0 +1,167 @@
+From 99b544d9483102180e35c3d679385222845a2ae7 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:47:03 +0100
+Subject: [PATCH] tehuti: use request_firmware
+
+Based on patch by Jaswinder Singh <jaswinder@infradead.org>
+
+Firmware blob is little endian.
+
+Removed bdx_firmware_endianess() as firmware blob is already little endian
+---
+ drivers/net/Kconfig  |    2 +-
+ drivers/net/tehuti.c |   43 ++++++++++++++++++++++++++++++-------------
+ drivers/net/tehuti.h |    1 +
+ 3 files changed, 32 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 8cec089..616db30 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -2570,7 +2570,7 @@ config MLX4_DEBUG
+ config TEHUTI
+ 	tristate "Tehuti Networks 10G Ethernet"
+ 	depends on PCI
+-	depends on BROKEN
++	select FW_LOADER
+ 	help
+ 	  Tehuti Networks 10G Ethernet NIC
+ 
+diff --git a/drivers/net/tehuti.c b/drivers/net/tehuti.c
+index 432e837..ea9a2ee 100644
+--- a/drivers/net/tehuti.c
++++ b/drivers/net/tehuti.c
+@@ -63,7 +63,10 @@
+  */
+ 
+ #include "tehuti.h"
+-#include "tehuti_fw.h"
++
++/* Firmware section */
++#define FIRMWARE_BDX	"tehuti/bdx.bin"
++static const struct firmware *bdx_fw;
+ 
+ static struct pci_device_id __devinitdata bdx_pci_tbl[] = {
+ 	{0x1FC9, 0x3009, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0},
+@@ -80,7 +83,8 @@ static void bdx_tx_cleanup(struct bdx_priv *priv);
+ static int bdx_rx_receive(struct bdx_priv *priv, struct rxd_fifo *f, int budget);
+ 
+ /* Definitions needed by FW loading */
+-static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size);
++static void bdx_tx_push_desc_safe(struct bdx_priv *priv,
++				  const void *data, int size);
+ 
+ /* Definitions needed by hw_start */
+ static int bdx_tx_init(struct bdx_priv *priv);
+@@ -309,6 +313,19 @@ static int bdx_poll(struct napi_struct *napi, int budget)
+ 	return work_done;
+ }
+ 
++/* bdx_fw_init - intialize firmware  */
++static int bdx_fw_init(struct pci_dev *pdev)
++{
++	int err;
++
++	err = request_firmware(&bdx_fw, FIRMWARE_BDX, &pdev->dev);
++	if (err)
++		printk(KERN_ERR "tehuti: Failed to load firmware \"%s\"\n",
++		       FIRMWARE_BDX);
++
++	return err;
++}
++
+ /* bdx_fw_load - loads firmware to NIC
+  * @priv - NIC private structure
+  * Firmware is loaded via TXD fifo, so it must be initialized first.
+@@ -324,7 +341,7 @@ static int bdx_fw_load(struct bdx_priv *priv)
+ 	ENTER;
+ 	master = READ_REG(priv, regINIT_SEMAPHORE);
+ 	if (!READ_REG(priv, regINIT_STATUS) && master) {
+-		bdx_tx_push_desc_safe(priv, s_firmLoad, sizeof(s_firmLoad));
++		bdx_tx_push_desc_safe(priv, bdx_fw->data, bdx_fw->size);
+ 		mdelay(100);
+ 	}
+ 	for (i = 0; i < 200; i++) {
+@@ -618,13 +635,6 @@ err:
+ 	RET(rc);
+ }
+ 
+-static void __init bdx_firmware_endianess(void)
+-{
+-	int i;
+-	for (i = 0; i < ARRAY_SIZE(s_firmLoad); i++)
+-		s_firmLoad[i] = CPU_CHIP_SWAP32(s_firmLoad[i]);
+-}
+-
+ static int bdx_range_check(struct bdx_priv *priv, u32 offset)
+ {
+ 	return (offset > (u32) (BDX_REGS_SIZE / priv->nic->port_num)) ?
+@@ -1831,7 +1841,7 @@ static void bdx_tx_free(struct bdx_priv *priv)
+  *    of the caller. Neither does it check that data size is smaller then
+  *    fifo size.
+  */
+-static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size)
++static void bdx_tx_push_desc(struct bdx_priv *priv, const void *data, int size)
+ {
+ 	struct txd_fifo *f = &priv->txd_fifo0;
+ 	int i = f->m.memsz - f->m.wptr;
+@@ -1858,7 +1868,8 @@ static void bdx_tx_push_desc(struct bdx_priv *priv, void *data, int size)
+  * NOTE: this func does check for available space and, if neccessary, waits for
+  *   NIC to read existing data before writing new one.
+  */
+-static void bdx_tx_push_desc_safe(struct bdx_priv *priv, void *data, int size)
++static void bdx_tx_push_desc_safe(struct bdx_priv *priv,
++				  const void *data, int size)
+ {
+ 	int timer = 0;
+ 	ENTER;
+@@ -1987,6 +1998,10 @@ bdx_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+ 		DBG("HW does not support MSI\n");
+ #endif
+ 
++	/* Initialize firmware */
++	if (bdx_fw_init(pdev))
++		goto err_out_iomap;
++
+     /************** netdev **************/
+ 	for (port = 0; port < nic->port_num; port++) {
+ 		if (!(ndev = alloc_etherdev(sizeof(struct bdx_priv)))) {
+@@ -2468,6 +2483,8 @@ static void __devexit bdx_remove(struct pci_dev *pdev)
+ 		pci_disable_msi(pdev);
+ #endif
+ 
++	release_firmware(bdx_fw);
++
+ 	iounmap(nic->regs);
+ 	pci_release_regions(pdev);
+ 	pci_disable_device(pdev);
+@@ -2498,7 +2515,6 @@ static void __init print_driver_id(void)
+ static int __init bdx_module_init(void)
+ {
+ 	ENTER;
+-	bdx_firmware_endianess();
+ 	init_txd_sizes();
+ 	print_driver_id();
+ 	RET(pci_register_driver(&bdx_pci_driver));
+@@ -2516,5 +2532,6 @@ static void __exit bdx_module_exit(void)
+ module_exit(bdx_module_exit);
+ 
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_BDX);
+ MODULE_AUTHOR(DRIVER_AUTHOR);
+ MODULE_DESCRIPTION(BDX_DRV_DESC);
+diff --git a/drivers/net/tehuti.h b/drivers/net/tehuti.h
+index efd170f..b9acb3f 100644
+--- a/drivers/net/tehuti.h
++++ b/drivers/net/tehuti.h
+@@ -30,6 +30,7 @@
+ #include <linux/version.h>
+ #include <linux/interrupt.h>
+ #include <linux/vmalloc.h>
++#include <linux/firmware.h>
+ #include <asm/byteorder.h>
+ 
+ /* Compile Time Switches */
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-usb-serial-whiteheat-request_firmware.patch	(revision 0)
@@ -0,0 +1,158 @@
+From 5084013135f2efabd241f74fdd83520fc54ccaaf Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:58:59 +0100
+Subject: [PATCH] whiteheat: use request_firmware()
+
+Based on patch by David Woodhouse <dwmw2@infradead.org>.
+---
+ drivers/usb/serial/Kconfig     |    2 +-
+ drivers/usb/serial/whiteheat.c |   79 ++++++++++++++++++++++++++--------------
+ 2 files changed, 53 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/usb/serial/Kconfig b/drivers/usb/serial/Kconfig
+index 96f811b..4335d44 100644
+--- a/drivers/usb/serial/Kconfig
++++ b/drivers/usb/serial/Kconfig
+@@ -102,8 +102,8 @@ config USB_SERIAL_CH341
+ 
+ config USB_SERIAL_WHITEHEAT
+ 	tristate "USB ConnectTech WhiteHEAT Serial Driver"
+-	depends on BROKEN
+ 	select USB_EZUSB
++	select FW_LOADER
+ 	help
+ 	  Say Y here if you want to use a ConnectTech WhiteHEAT 4 port
+ 	  USB to serial converter device.
+diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c
+index f07e8a4..914784f 100644
+--- a/drivers/usb/serial/whiteheat.c
++++ b/drivers/usb/serial/whiteheat.c
+@@ -81,7 +81,8 @@
+ #include <linux/serial_reg.h>
+ #include <linux/serial.h>
+ #include <linux/usb/serial.h>
+-#include "whiteheat_fw.h"		/* firmware for the ConnectTech WhiteHEAT device */
++#include <linux/firmware.h>
++#include <linux/ihex.h>
+ #include "whiteheat.h"			/* WhiteHEAT specific commands */
+ 
+ static int debug;
+@@ -280,58 +281,79 @@ static int firm_report_tx_done(struct usb_serial_port *port);
+ static int whiteheat_firmware_download (struct usb_serial *serial, const struct usb_device_id *id)
+ {
+ 	int response;
+-	const struct whiteheat_hex_record *record;
++	const struct firmware *loader_fw, *firmware_fw;
++	const struct ihex_binrec *record;
+ 	
+ 	dbg("%s", __func__);
+ 	
++	response = request_ihex_firmware(&firmware_fw, "whiteheat.fw",
++				    &serial->dev->dev);
++	if (response) {
++		err("%s - request \"whiteheat.fw\" failed", __func__);
++		return response;
++	}
++	response = request_ihex_firmware(&loader_fw, "whiteheat_loader.fw",
++				    &serial->dev->dev);
++	if (response) {
++		err("%s - request \"whiteheat_loader.fw\" failed", __func__);
++		goto out_release_1;
++	}
+ 	response = ezusb_set_reset (serial, 1);
+ 
+-	record = &whiteheat_loader[0];
+-	while (record->address != 0xffff) {
+-		response = ezusb_writememory (serial, record->address, 
+-				(unsigned char *)record->data, record->data_size, 0xa0);
++	record = (const struct ihex_binrec *)loader_fw->data;
++	while (record) {
++		response = ezusb_writememory(serial, be32_to_cpu(record->addr),
++					     (unsigned char *)record->data,
++					     be16_to_cpu(record->len), 0xa0);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for loader (%d %04X %p %d)",
+-				__func__, response, record->address, record->data, record->data_size);
+-			break;
++			    __func__, response, be32_to_cpu(record->addr),
++			    record->data, be16_to_cpu(record->len));
++			goto out_reset;
+ 		}
+-		++record;
++		record = ihex_next_binrec(record);
+ 	}
+ 
+ 	response = ezusb_set_reset (serial, 0);
+ 
+-	record = &whiteheat_firmware[0];
+-	while (record->address < 0x1b40) {
+-		++record;
+-	}
+-	while (record->address != 0xffff) {
+-		response = ezusb_writememory (serial, record->address, 
+-				(unsigned char *)record->data, record->data_size, 0xa3);
++	record = (const struct ihex_binrec *)firmware_fw->data;
++	while (record && be32_to_cpu(record->addr) < 0x1b40)
++		record = ihex_next_binrec(record);
++	while (record) {
++		response = ezusb_writememory(serial, be32_to_cpu(record->addr),
++					     (unsigned char *)record->data,
++					     be16_to_cpu(record->len), 0xa3);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for first firmware step (%d %04X %p %d)", 
+-				__func__, response, record->address, record->data, record->data_size);
+-			break;
++			    __func__, response, be32_to_cpu(record->addr),
++			    record->data, be16_to_cpu(record->len));
++			goto out_reset;
+ 		}
+ 		++record;
+ 	}
+ 	
+ 	response = ezusb_set_reset (serial, 1);
+ 
+-	record = &whiteheat_firmware[0];
+-	while (record->address < 0x1b40) {
+-		response = ezusb_writememory (serial, record->address, 
+-				(unsigned char *)record->data, record->data_size, 0xa0);
++	record = (const struct ihex_binrec *)firmware_fw->data;
++	while (record && be32_to_cpu(record->addr) < 0x1b40) {
++		response = ezusb_writememory(serial, be32_to_cpu(record->addr),
++					     (unsigned char *)record->data,
++					     be16_to_cpu(record->len), 0xa0);
+ 		if (response < 0) {
+ 			err("%s - ezusb_writememory failed for second firmware step (%d %04X %p %d)", 
+-				__func__, response, record->address, record->data, record->data_size);
+-			break;
++			    __func__, response, be32_to_cpu(record->addr),
++			    record->data, be16_to_cpu(record->len));
++			goto out_reset;
+ 		}
+ 		++record;
+ 	}
+ 
+-	response = ezusb_set_reset (serial, 0);
+-
+-	return 0;
++out_reset:
++	ezusb_set_reset(serial, 0);
++	release_firmware(loader_fw);
++out_release_1:
++	release_firmware(firmware_fw);
++	return response;
+ }
+ 
+ 
+@@ -1503,6 +1525,9 @@ MODULE_AUTHOR( DRIVER_AUTHOR );
+ MODULE_DESCRIPTION( DRIVER_DESC );
+ MODULE_LICENSE("GPL");
+ 
++MODULE_FIRMWARE("whiteheat.fw");
++MODULE_FIRMWARE("whiteheat_loader.fw");
++
+ module_param(urb_pool_size, int, 0);
+ MODULE_PARM_DESC(urb_pool_size, "Number of urbs to use for buffering");
+ 
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-scsi-qla1280-request_firmware.patch	(revision 0)
@@ -0,0 +1,309 @@
+From 701b45853d4dbfb93880b9e02da689d2026c52f2 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:43:31 +0100
+Subject: [PATCH] qla1280: use request_firmware
+
+Firmware blob is little endian looks like this...
+	unsigned char  Version1
+	unsigned char  Version2
+	unsigned char  Version3
+	unsigned char  Padding
+	unsigned short start_address
+	unsigned short data
+
+Signed-off-by: Jaswinder Singh <jaswinder@infradead.org>
+Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
+Acked-by: Jes Sorensen <jes@sgi.com>
+---
+ drivers/scsi/Kconfig   |    2 +-
+ drivers/scsi/qla1280.c |  121 +++++++++++++++++++++++++++++++----------------
+ drivers/scsi/qla1280.h |    6 ++
+ 3 files changed, 87 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
+index 94831ae..61a20e1 100644
+--- a/drivers/scsi/Kconfig
++++ b/drivers/scsi/Kconfig
+@@ -1316,7 +1316,7 @@ config SCSI_QLOGIC_FC_FIRMWARE
+ config SCSI_QLOGIC_1280
+ 	tristate "Qlogic QLA 1240/1x80/1x160 SCSI support"
+ 	depends on PCI && SCSI
+-	depends on BROKEN
++	select FW_LOADER
+ 	help
+ 	  Say Y if you have a QLogic ISP1240/1x80/1x160 SCSI host adapter.
+ 
+diff --git a/drivers/scsi/qla1280.c b/drivers/scsi/qla1280.c
+index 3754ab8..7b033c5 100644
+--- a/drivers/scsi/qla1280.c
++++ b/drivers/scsi/qla1280.c
+@@ -348,6 +348,7 @@
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/dma-mapping.h>
++#include <linux/firmware.h>
+ 
+ #include <asm/io.h>
+ #include <asm/irq.h>
+@@ -384,11 +385,7 @@
+ #define	MEMORY_MAPPED_IO	1
+ #endif
+ 
+-#define UNIQUE_FW_NAME
+ #include "qla1280.h"
+-#include "ql12160_fw.h"		/* ISP RISC codes */
+-#include "ql1280_fw.h"
+-#include "ql1040_fw.h"
+ 
+ #ifndef BITS_PER_LONG
+ #error "BITS_PER_LONG not defined!"
+@@ -418,6 +415,11 @@
+ 				ha->pdev->device == PCI_DEVICE_ID_QLOGIC_ISP12160)
+ 
+ 
++/* Firmware Names */
++#define FW_QLA12160		"qlogic/12160.bin"
++#define FW_QLA1040		"qlogic/1040.bin"
++#define FW_QLA1280		"qlogic/1280.bin"
++
+ static int qla1280_probe_one(struct pci_dev *, const struct pci_device_id *);
+ static void qla1280_remove_one(struct pci_dev *);
+ 
+@@ -541,10 +543,7 @@ __setup("qla1280=", qla1280_setup);
+ struct qla_boards {
+ 	unsigned char name[9];	/* Board ID String */
+ 	int numPorts;		/* Number of SCSI ports */
+-	unsigned short *fwcode;	/* pointer to FW array         */
+-	unsigned short *fwlen;	/* number of words in array    */
+-	unsigned short *fwstart;	/* start address for F/W       */
+-	unsigned char *fwver;	/* Ptr to F/W version array    */
++	char *fwname;		/* firmware name        */
+ };
+ 
+ /* NOTE: the last argument in each entry is used to index ql1280_board_tbl */
+@@ -567,19 +566,13 @@ MODULE_DEVICE_TABLE(pci, qla1280_pci_tbl);
+ 
+ static struct qla_boards ql1280_board_tbl[] = {
+ 	/* Name ,  Number of ports, FW details */
+-	{"QLA12160", 2, &fw12160i_code01[0], &fw12160i_length01,
+-	 &fw12160i_addr01, &fw12160i_version_str[0]},
+-	{"QLA1040", 1, &risc_code01[0], &risc_code_length01,
+-	 &risc_code_addr01, &firmware_version[0]},
+-	{"QLA1080", 1, &fw1280ei_code01[0], &fw1280ei_length01,
+-	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-	{"QLA1240", 2, &fw1280ei_code01[0], &fw1280ei_length01,
+-	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-	{"QLA1280", 2, &fw1280ei_code01[0], &fw1280ei_length01,
+-	 &fw1280ei_addr01, &fw1280ei_version_str[0]},
+-	{"QLA10160", 1, &fw12160i_code01[0], &fw12160i_length01,
+-	 &fw12160i_addr01, &fw12160i_version_str[0]},
+-	{"        ", 0}
++	{"QLA12160",	2, FW_QLA12160},
++	{"QLA1040",	1, FW_QLA1040},
++	{"QLA1080",	1, FW_QLA1280},
++	{"QLA1240",	2, FW_QLA1280},
++	{"QLA1280",	2, FW_QLA1280},
++	{"QLA10160",	1, FW_QLA12160},
++	{"        ",	0, "   "},
+ };
+ 
+ static int qla1280_verbose = 1;
+@@ -704,7 +697,7 @@ qla1280_info(struct Scsi_Host *host)
+ 	sprintf (bp,
+ 		 "QLogic %s PCI to SCSI Host Adapter\n"
+ 		 "       Firmware version: %2d.%02d.%02d, Driver version %s",
+-		 &bdp->name[0], bdp->fwver[0], bdp->fwver[1], bdp->fwver[2],
++		 &bdp->name[0], ha->fwver1, ha->fwver2, ha->fwver3,
+ 		 QLA1280_VERSION);
+ 	return bp;
+ }
+@@ -1648,36 +1641,60 @@ qla1280_chip_diag(struct scsi_qla_host *ha)
+ static int
+ qla1280_load_firmware_pio(struct scsi_qla_host *ha)
+ {
+-	uint16_t risc_address, *risc_code_address, risc_code_size;
++	const struct firmware *fw;
++	const __le16 *fw_data;
++	uint16_t risc_address, risc_code_size;
+ 	uint16_t mb[MAILBOX_REGISTER_COUNT], i;
+ 	int err;
+ 
++	err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
++			       &ha->pdev->dev);
++	if (err) {
++		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
++		       ql1280_board_tbl[ha->devnum].fwname, err);
++		return err;
++	}
++	if ((fw->size % 2) || (fw->size < 6)) {
++		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
++		       fw->size, ql1280_board_tbl[ha->devnum].fwname);
++		err = -EINVAL;
++		goto out;
++	}
++	ha->fwver1 = fw->data[0];
++	ha->fwver2 = fw->data[1];
++	ha->fwver3 = fw->data[2];
++	fw_data = (const __le16 *)&fw->data[0];
++	ha->fwstart = __le16_to_cpu(fw_data[2]);
++
+ 	/* Load RISC code. */
+-	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+-	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+-	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
++	risc_address = ha->fwstart;
++	fw_data = (const __le16 *)&fw->data[4];
++	risc_code_size = (fw->size - 6) / 2;
+ 
+ 	for (i = 0; i < risc_code_size; i++) {
+ 		mb[0] = MBC_WRITE_RAM_WORD;
+ 		mb[1] = risc_address + i;
+-		mb[2] = risc_code_address[i];
++		mb[2] = __le16_to_cpu(fw_data[i]);
+ 
+ 		err = qla1280_mailbox_command(ha, BIT_0 | BIT_1 | BIT_2, mb);
+ 		if (err) {
+ 			printk(KERN_ERR "scsi(%li): Failed to load firmware\n",
+ 					ha->host_no);
+-			return err;
++			goto out;
+ 		}
+ 	}
+-
+-	return 0;
++out:
++	release_firmware(fw);
++	return err;
+ }
+ 
+ #define DUMP_IT_BACK 0		/* for debug of RISC loading */
+ static int
+ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ {
+-	uint16_t risc_address, *risc_code_address, risc_code_size;
++	const struct firmware *fw;
++	const __le16 *fw_data;
++	uint16_t risc_address, risc_code_size;
+ 	uint16_t mb[MAILBOX_REGISTER_COUNT], cnt;
+ 	int err = 0, num, i;
+ #if DUMP_IT_BACK
+@@ -1689,10 +1706,29 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ 		return -ENOMEM;
+ #endif
+ 
++	err = request_firmware(&fw, ql1280_board_tbl[ha->devnum].fwname,
++			       &ha->pdev->dev);
++	if (err) {
++		printk(KERN_ERR "Failed to load image \"%s\" err %d\n",
++		       ql1280_board_tbl[ha->devnum].fwname, err);
++		return err;
++	}
++	if ((fw->size % 2) || (fw->size < 6)) {
++		printk(KERN_ERR "Bogus length %zu in image \"%s\"\n",
++		       fw->size, ql1280_board_tbl[ha->devnum].fwname);
++		err = -EINVAL;
++		goto out;
++	}
++	ha->fwver1 = fw->data[0];
++	ha->fwver2 = fw->data[1];
++	ha->fwver3 = fw->data[2];
++	fw_data = (const __le16 *)&fw->data[0];
++	ha->fwstart = __le16_to_cpu(fw_data[2]);
++
+ 	/* Load RISC code. */
+-	risc_address = *ql1280_board_tbl[ha->devnum].fwstart;
+-	risc_code_address = ql1280_board_tbl[ha->devnum].fwcode;
+-	risc_code_size = *ql1280_board_tbl[ha->devnum].fwlen;
++	risc_address = ha->fwstart;
++	fw_data = (const __le16 *)&fw->data[4];
++	risc_code_size = (fw->size - 6) / 2;
+ 
+ 	dprintk(1, "%s: DMA RISC code (%i) words\n",
+ 			__FUNCTION__, risc_code_size);
+@@ -1708,10 +1744,9 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ 
+ 		dprintk(2, "qla1280_setup_chip:  loading risc @ =(0x%p),"
+ 			"%d,%d(0x%x)\n",
+-			risc_code_address, cnt, num, risc_address);
++			fw_data, cnt, num, risc_address);
+ 		for(i = 0; i < cnt; i++)
+-			((__le16 *)ha->request_ring)[i] =
+-				cpu_to_le16(risc_code_address[i]);
++			((__le16 *)ha->request_ring)[i] = fw_data[i];
+ 
+ 		mb[0] = MBC_LOAD_RAM;
+ 		mb[1] = risc_address;
+@@ -1763,7 +1798,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ #endif
+ 		risc_address += cnt;
+ 		risc_code_size = risc_code_size - cnt;
+-		risc_code_address = risc_code_address + cnt;
++		fw_data = fw_data + cnt;
+ 		num++;
+ 	}
+ 
+@@ -1771,6 +1806,7 @@ qla1280_load_firmware_dma(struct scsi_qla_host *ha)
+ #if DUMP_IT_BACK
+ 	pci_free_consistent(ha->pdev, 8000, tbuf, p_tbuf);
+ #endif
++	release_firmware(fw);
+ 	return err;
+ }
+ 
+@@ -1786,7 +1822,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
+ 	/* Verify checksum of loaded RISC code. */
+ 	mb[0] = MBC_VERIFY_CHECKSUM;
+ 	/* mb[1] = ql12_risc_code_addr01; */
+-	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
++	mb[1] = ha->fwstart;
+ 	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, mb);
+ 	if (err) {
+ 		printk(KERN_ERR "scsi(%li): RISC checksum failed.\n", ha->host_no);
+@@ -1796,7 +1832,7 @@ qla1280_start_firmware(struct scsi_qla_host *ha)
+ 	/* Start firmware execution. */
+ 	dprintk(1, "%s: start firmware running.\n", __FUNCTION__);
+ 	mb[0] = MBC_EXECUTE_FIRMWARE;
+-	mb[1] = *ql1280_board_tbl[ha->devnum].fwstart;
++	mb[1] = ha->fwstart;
+ 	err = qla1280_mailbox_command(ha, BIT_1 | BIT_0, &mb[0]);
+ 	if (err) {
+ 		printk(KERN_ERR "scsi(%li): Failed to start firmware\n",
+@@ -1821,7 +1857,7 @@ qla1280_load_firmware(struct scsi_qla_host *ha)
+ 	if (err)
+ 		goto out;
+ 	err = qla1280_start_firmware(ha);
+- out:
++out:
+ 	return err;
+ }
+ 
+@@ -4451,6 +4487,9 @@ module_exit(qla1280_exit);
+ MODULE_AUTHOR("Qlogic & Jes Sorensen");
+ MODULE_DESCRIPTION("Qlogic ISP SCSI (qla1x80/qla1x160) driver");
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FW_QLA1040);
++MODULE_FIRMWARE(FW_QLA1280);
++MODULE_FIRMWARE(FW_QLA12160);
+ MODULE_VERSION(QLA1280_VERSION);
+ 
+ /*
+diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
+index ff2c363..d7c44b8 100644
+--- a/drivers/scsi/qla1280.h
++++ b/drivers/scsi/qla1280.h
+@@ -1069,6 +1069,12 @@ struct scsi_qla_host {
+ 
+ 	struct nvram nvram;
+ 	int nvram_valid;
++
++	/* Firmware Info */
++	unsigned short fwstart; /* start address for F/W   */
++	unsigned char fwver1;   /* F/W version first char  */
++	unsigned char fwver2;   /* F/W version second char */
++	unsigned char fwver3;   /* F/W version third char  */
+ };
+ 
+ #endif /* _QLA1280_H */
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-char-drm-r128-request_firmware.patch	(revision 0)
@@ -0,0 +1,139 @@
+From a349c45d1ba3726c61e4b205006b07fd07543221 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 02:27:57 +0100
+Subject: [PATCH] r128: Use request_firmware() to load CCE microcode
+
+Firmware blob looks like this:
+    __be32 datah
+    __be32 datal
+
+Compile-tested only.
+---
+ drivers/char/drm/Kconfig    |    2 +-
+ drivers/char/drm/r128_cce.c |   54 ++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 49 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index 8f9c893..ea26dfd 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -26,7 +26,7 @@ config DRM_TDFX
+ config DRM_R128
+ 	tristate "ATI Rage 128"
+ 	depends on DRM && PCI
+-	depends on BROKEN
++	select FW_LOADER
+ 	help
+ 	  Choose this option if you have an ATI Rage 128 graphics card.  If M
+ 	  is selected, the module will be called r128.  AGP support for
+diff --git a/drivers/char/drm/r128_cce.c b/drivers/char/drm/r128_cce.c
+index a9ee89a..63bed21 100644
+--- a/drivers/char/drm/r128_cce.c
++++ b/drivers/char/drm/r128_cce.c
+@@ -29,6 +29,9 @@
+  *    Gareth Hughes <gareth@valinux.com>
+  */
+ 
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
++
+ #include "drmP.h"
+ #include "drm.h"
+ #include "r128_drm.h"
+@@ -36,6 +39,9 @@
+ 
+ #define R128_FIFO_DEBUG		0
+ 
++#define FIRMWARE_NAME		"r128/r128_cce.bin"
++
++MODULE_FIRMWARE(FIRMWARE_NAME);
+ 
+ static int R128_READ_PLL(struct drm_device * dev, int addr)
+ {
+@@ -132,20 +138,50 @@ static int r128_do_wait_for_idle(drm_r128_private_t * dev_priv)
+  */
+ 
+ /* Load the microcode for the CCE */
+-static void r128_cce_load_microcode(drm_r128_private_t * dev_priv)
++static int r128_cce_load_microcode(drm_r128_private_t *dev_priv)
+ {
+-	int i;
++	struct platform_device *pdev;
++	const struct firmware *fw;
++	const __be32 *fw_data;
++	int rc, i;
+ 
+ 	DRM_DEBUG("\n");
+ 
++	pdev = platform_device_register_simple("r128_cce", 0, NULL, 0);
++	if (IS_ERR(pdev)) {
++		printk(KERN_ERR "r128_cce: Failed to register firmware\n");
++		return PTR_ERR(pdev);
++	}
++	rc = request_firmware(&fw, FIRMWARE_NAME, &pdev->dev);
++	platform_device_unregister(pdev);
++	if (rc) {
++		printk(KERN_ERR "r128_cce: Failed to load firmware \"%s\"\n",
++		       FIRMWARE_NAME);
++		return rc;
++	}
++
++	if (fw->size != 256 * 8) {
++		printk(KERN_ERR
++		       "r128_cce: Bogus length %zu in firmware \"%s\"\n",
++		       fw->size, FIRMWARE_NAME);
++		rc = -EINVAL;
++		goto out_release;
++	}
++
+ 	r128_do_wait_for_idle(dev_priv);
+ 
++	fw_data = (const __be32 *)fw->data;
+ 	R128_WRITE(R128_PM4_MICROCODE_ADDR, 0);
+ 	for (i = 0; i < 256; i++) {
+-		R128_WRITE(R128_PM4_MICROCODE_DATAH, r128_cce_microcode[i * 2]);
++		R128_WRITE(R128_PM4_MICROCODE_DATAH,
++			   be32_to_cpup(&fw_data[i * 2]));
+ 		R128_WRITE(R128_PM4_MICROCODE_DATAL,
+-			   r128_cce_microcode[i * 2 + 1]);
++			   be32_to_cpup(&fw_data[i * 2 + 1]));
+ 	}
++
++out_release:
++	release_firmware(fw);
++	return rc;
+ }
+ 
+ /* Flush any pending commands to the CCE.  This should only be used just
+@@ -306,6 +342,7 @@ static void r128_cce_init_ring_buffer(struct drm_device * dev,
+ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
+ {
+ 	drm_r128_private_t *dev_priv;
++	int rc;
+ 
+ 	DRM_DEBUG("\n");
+ 
+@@ -532,13 +569,18 @@ static int r128_do_init_cce(struct drm_device * dev, drm_r128_init_t * init)
+ #endif
+ 
+ 	r128_cce_init_ring_buffer(dev, dev_priv);
+-	r128_cce_load_microcode(dev_priv);
++	rc = r128_cce_load_microcode(dev_priv);
+ 
+ 	dev->dev_private = (void *)dev_priv;
+ 
+ 	r128_do_engine_reset(dev);
+ 
+-	return 0;
++	if (rc) {
++		DRM_ERROR("Failed to load firmware!\n");
++		r128_do_cleanup_cce(dev);
++	}
++
++	return rc;
+ }
+ 
+ int r128_do_cleanup_cce(struct drm_device * dev)
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-e100-request_firmware.patch	(revision 0)
@@ -0,0 +1,223 @@
+From b4ae97fb6c6ab3df6abef40cc18df2e6ea68182e Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 01:56:51 +0100
+Subject: [PATCH] e100: Use request_firmware() to load microcode where needed
+
+Based on patch by Jaswinder Singh <jaswinder@infradead.org> and
+David Woodhouse <dwmw2@infradead.org>.
+---
+ drivers/net/Kconfig |    2 +-
+ drivers/net/e100.c  |  145 ++++++++++++++++++++++++++++++---------------------
+ 2 files changed, 87 insertions(+), 60 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index ac4ee2d..0836ea8 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1442,7 +1442,7 @@ config EEPRO100
+ config E100
+ 	tristate "Intel(R) PRO/100+ support"
+ 	depends on NET_PCI && PCI
+-	depends on BROKEN
++	select FW_LOADER
+ 	select MII
+ 	---help---
+ 	  This driver supports Intel(R) PRO/100 family of adapters.
+diff --git a/drivers/net/e100.c b/drivers/net/e100.c
+index b255a84..6e7d623 100644
+--- a/drivers/net/e100.c
++++ b/drivers/net/e100.c
+@@ -161,6 +161,7 @@
+ #include <linux/skbuff.h>
+ #include <linux/ethtool.h>
+ #include <linux/string.h>
++#include <linux/firmware.h>
+ #include <asm/unaligned.h>
+ 
+ 
+@@ -178,6 +179,9 @@ MODULE_DESCRIPTION(DRV_DESCRIPTION);
+ MODULE_AUTHOR(DRV_COPYRIGHT);
+ MODULE_LICENSE("GPL");
+ MODULE_VERSION(DRV_VERSION);
++MODULE_FIRMWARE("e100/d101m_ucode.bin");
++MODULE_FIRMWARE("e100/d101s_ucode.bin");
++MODULE_FIRMWARE("e100/d102e_ucode.bin");
+ 
+ static int debug = 3;
+ static int eeprom_bad_csum_allow = 0;
+@@ -1050,40 +1054,6 @@ static void e100_configure(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+ }
+ 
+ 
+-static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
+-{
+-/* *INDENT-OFF* */
+-	static struct {
+-		u32 ucode[UCODE_SIZE + 1];
+-		u8 mac;
+-		u8 timer_dword;
+-		u8 bundle_dword;
+-		u8 min_size_dword;
+-	} ucode_opts[] = {
+-		{ D101M_B_RCVBUNDLE_UCODE,
+-		  mac_82559_D101M,
+-		  D101M_CPUSAVER_TIMER_DWORD,
+-		  D101M_CPUSAVER_BUNDLE_DWORD,
+-		  D101M_CPUSAVER_MIN_SIZE_DWORD },
+-		{ D101S_RCVBUNDLE_UCODE,
+-		  mac_82559_D101S,
+-		  D101S_CPUSAVER_TIMER_DWORD,
+-		  D101S_CPUSAVER_BUNDLE_DWORD,
+-		  D101S_CPUSAVER_MIN_SIZE_DWORD },
+-		{ D102_E_RCVBUNDLE_UCODE,
+-		  mac_82551_F,
+-		  D102_E_CPUSAVER_TIMER_DWORD,
+-		  D102_E_CPUSAVER_BUNDLE_DWORD,
+-		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
+-		{ D102_E_RCVBUNDLE_UCODE,
+-		  mac_82551_10,
+-		  D102_E_CPUSAVER_TIMER_DWORD,
+-		  D102_E_CPUSAVER_BUNDLE_DWORD,
+-		  D102_E_CPUSAVER_MIN_SIZE_DWORD },
+-		{ {0}, 0, 0, 0, 0}
+-	}, *opts;
+-/* *INDENT-ON* */
+-
+ /*************************************************************************
+ *  CPUSaver parameters
+ *
+@@ -1143,42 +1113,99 @@ static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb
+ #define BUNDLEMAX (u16)6
+ #define INTDELAY (u16)1536 /* 0x600 */
+ 
++static const struct firmware *e100_request_firmware(struct nic *nic)
++{
++	const char *fw_name;
++	const struct firmware *fw;
++	u8 timer, bundle, min_size;
++	int err;
++
+ 	/* do not load u-code for ICH devices */
+ 	if (nic->flags & ich)
+-		goto noloaducode;
++		return NULL;
+ 
+ 	/* Search for ucode match against h/w revision */
+-	for (opts = ucode_opts; opts->mac; opts++) {
+-		int i;
+-		u32 *ucode = opts->ucode;
+-		if (nic->mac != opts->mac)
+-			continue;
+-
+-		/* Insert user-tunable settings */
+-		ucode[opts->timer_dword] &= 0xFFFF0000;
+-		ucode[opts->timer_dword] |= INTDELAY;
+-		ucode[opts->bundle_dword] &= 0xFFFF0000;
+-		ucode[opts->bundle_dword] |= BUNDLEMAX;
+-		ucode[opts->min_size_dword] &= 0xFFFF0000;
+-		ucode[opts->min_size_dword] |= (BUNDLESMALL) ? 0xFFFF : 0xFF80;
++	if (nic->mac == mac_82559_D101M)
++		fw_name = "e100/d101m_ucode.bin";
++	else if (nic->mac == mac_82559_D101S)
++		fw_name = "e100/d101s_ucode.bin";
++	else if (nic->mac == mac_82551_F || nic->mac == mac_82551_10)
++		fw_name = "e100/d102e_ucode.bin";
++	else /* No ucode on other devices */
++		return NULL;
++
++	err = request_firmware(&fw, fw_name, &nic->pdev->dev);
++	if (err) {
++		DPRINTK(PROBE,ERR, "Failed to load firmware \"%s\": %d\n",
++			fw_name, err);
++		return ERR_PTR(err);
++	}
++	/* Firmware should be precisely UCODE_SIZE (words) plus three bytes
++	   indicating the offsets for BUNDLESMALL, BUNDLEMAX, INTDELAY */
++	if (fw->size != UCODE_SIZE * 4 + 3) {
++		DPRINTK(PROBE,ERR, "Firmware \"%s\" has wrong size %zu\n",
++			fw_name, fw->size);
++		release_firmware(fw);
++		return ERR_PTR(-EINVAL);
++	}
+ 
+-		for (i = 0; i < UCODE_SIZE; i++)
+-			cb->u.ucode[i] = cpu_to_le32(ucode[i]);
+-		cb->command = cpu_to_le16(cb_ucode | cb_el);
+-		return;
++	/* Read timer, bundle and min_size from end of firmware blob */
++	timer = fw->data[UCODE_SIZE * 4];
++	bundle = fw->data[UCODE_SIZE * 4 + 1];
++	min_size = fw->data[UCODE_SIZE * 4 + 2];
++
++	if (timer >= UCODE_SIZE || bundle >= UCODE_SIZE ||
++	    min_size >= UCODE_SIZE) {
++		DPRINTK(PROBE,ERR, "Firmware \"%s\" has bogus offset values (0x%x,0x%x,0x%x)\n",
++			fw_name, timer, bundle, min_size);
++		release_firmware(fw);
++		return ERR_PTR(-EINVAL);
+ 	}
++	/* OK, firmware is validated and ready to use... */
++	return fw;
++}
+ 
+-noloaducode:
+-	cb->command = cpu_to_le16(cb_nop | cb_el);
++static void e100_setup_ucode(struct nic *nic, struct cb *cb, struct sk_buff *skb)
++{
++	const struct firmware *fw = (void *)skb;
++	u8 timer, bundle, min_size;
++
++	/* It's not a real skb; we just abused the fact that e100_exec_cb
++	   will pass it through to here... */
++	cb->skb = NULL;
++
++	/* firmware is stored as little endian already */
++	memcpy(cb->u.ucode, fw->data, UCODE_SIZE * 4);
++
++	/* Read timer, bundle and min_size from end of firmware blob */
++	timer = fw->data[UCODE_SIZE * 4];
++	bundle = fw->data[UCODE_SIZE * 4 + 1];
++	min_size = fw->data[UCODE_SIZE * 4 + 2];
++
++	/* Insert user-tunable settings in cb->u.ucode */
++	cb->u.ucode[timer] &= cpu_to_le32(0xFFFF0000);
++	cb->u.ucode[timer] |= cpu_to_le32(INTDELAY);
++	cb->u.ucode[bundle] &= cpu_to_le32(0xFFFF0000);
++	cb->u.ucode[bundle] |= cpu_to_le32(BUNDLEMAX);
++	cb->u.ucode[min_size] &= cpu_to_le32(0xFFFF0000);
++	cb->u.ucode[min_size] |= cpu_to_le32((BUNDLESMALL) ? 0xFFFF : 0xFF80);
++
++	cb->command = cpu_to_le16(cb_ucode | cb_el);
+ }
+ 
+-static inline int e100_exec_cb_wait(struct nic *nic, struct sk_buff *skb,
+-	void (*cb_prepare)(struct nic *, struct cb *, struct sk_buff *))
++static inline int e100_load_ucode_wait(struct nic *nic)
+ {
++	const struct firmware *fw;
++
+ 	int err = 0, counter = 50;
+ 	struct cb *cb = nic->cb_to_clean;
+ 
+-	if ((err = e100_exec_cb(nic, NULL, e100_setup_ucode)))
++	fw = e100_request_firmware(nic);
++	/* If it's NULL, then no ucode is required */
++	if (!fw || IS_ERR(fw))
++		return PTR_ERR(fw);
++
++	if ((err = e100_exec_cb(nic, (void *)fw, e100_setup_ucode)))
+ 		DPRINTK(PROBE,ERR, "ucode cmd failed with error %d\n", err);
+ 
+ 	/* must restart cuc */
+@@ -1298,7 +1325,7 @@ static int e100_hw_init(struct nic *nic)
+ 		return err;
+ 	if((err = e100_exec_cmd(nic, ruc_load_base, 0)))
+ 		return err;
+-	if ((err = e100_exec_cb_wait(nic, NULL, e100_setup_ucode)))
++	if ((err = e100_load_ucode_wait(nic)))
+ 		return err;
+ 	if((err = e100_exec_cb(nic, NULL, e100_configure)))
+ 		return err;
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-usb-kaweth-request_firmware.patch	(revision 0)
@@ -0,0 +1,141 @@
+From 501cc6ba7b2b1ad48a231d6b9395c0f5973f58b6 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 16:13:47 +0100
+Subject: [PATCH] kaweth: use request_firmware()
+
+Based on patch by David Woodhouse <dwmw2@infradead.org>.
+---
+ drivers/net/usb/Kconfig  |    2 +-
+ drivers/net/usb/kaweth.c |   43 ++++++++++++++++++++++++++-----------------
+ 2 files changed, 27 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig
+index 2c0b805..aec69f5 100644
+--- a/drivers/net/usb/Kconfig
++++ b/drivers/net/usb/Kconfig
+@@ -29,7 +29,7 @@ config USB_CATC
+ 
+ config USB_KAWETH
+ 	tristate "USB KLSI KL5USB101-based ethernet device support"
+-	depends on BROKEN
++	select FW_LOADER
+ 	---help---
+ 	  Say Y here if you want to use one of the following 10Mbps only
+ 	  USB Ethernet adapters based on the KLSI KL5KUSB101B chipset:
+diff --git a/drivers/net/usb/kaweth.c b/drivers/net/usb/kaweth.c
+index 7c66b05..d6829db 100644
+--- a/drivers/net/usb/kaweth.c
++++ b/drivers/net/usb/kaweth.c
+@@ -57,13 +57,12 @@
+ #include <linux/ethtool.h>
+ #include <linux/dma-mapping.h>
+ #include <linux/wait.h>
++#include <linux/firmware.h>
+ #include <asm/uaccess.h>
+ #include <asm/byteorder.h>
+ 
+ #undef DEBUG
+ 
+-#include "kawethfw.h"
+-
+ #define KAWETH_MTU			1514
+ #define KAWETH_BUF_SIZE			1664
+ #define KAWETH_TX_TIMEOUT		(5 * HZ)
+@@ -108,6 +107,10 @@
+ MODULE_AUTHOR("Michael Zappe <zapman@interlan.net>, Stephane Alnet <stephane@u-picardie.fr>, Brad Hards <bhards@bigpond.net.au> and Oliver Neukum <oliver@neukum.org>");
+ MODULE_DESCRIPTION("KL5USB101 USB Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE("kaweth/new_code.bin");
++MODULE_FIRMWARE("kaweth/new_code_fix.bin");
++MODULE_FIRMWARE("kaweth/trigger_code.bin");
++MODULE_FIRMWARE("kaweth/trigger_code_fix.bin");
+ 
+ static const char driver_name[] = "kaweth";
+ 
+@@ -385,17 +388,28 @@ static int kaweth_set_receive_filter(struct kaweth_device *kaweth,
+  *     kaweth_download_firmware
+  ****************************************************************/
+ static int kaweth_download_firmware(struct kaweth_device *kaweth,
+-				    __u8 *data,
+-				    __u16 data_len,
++				    const char *fwname,
+ 				    __u8 interrupt,
+ 				    __u8 type)
+ {
+-	if(data_len > KAWETH_FIRMWARE_BUF_SIZE)	{
+-		err("Firmware too big: %d", data_len);
++	const struct firmware *fw;
++	int data_len;
++	int ret;
++
++	ret = request_firmware(&fw, fwname, &kaweth->dev->dev);
++	if (ret) {
++		err("Firmware request failed\n");
++		return ret;
++	}
++
++	if (fw->size > KAWETH_FIRMWARE_BUF_SIZE) {
++		err("Firmware too big: %zu", fw->size);
+ 		return -ENOSPC;
+ 	}
++	data_len = fw->size;
++	memcpy(kaweth->firmware_buf, fw->data, fw->size);
+ 
+-	memcpy(kaweth->firmware_buf, data, data_len);
++	release_firmware(fw);
+ 
+ 	kaweth->firmware_buf[2] = (data_len & 0xFF) - 7;
+ 	kaweth->firmware_buf[3] = data_len >> 8;
+@@ -406,8 +420,7 @@ static int kaweth_download_firmware(struct kaweth_device *kaweth,
+ 		   kaweth->firmware_buf[2]);
+ 
+ 	dbg("Downloading firmware at %p to kaweth device at %p",
+-	    data,
+-	    kaweth);
++	    fw->data, kaweth);
+ 	dbg("Firmware length: %d", data_len);
+ 
+ 	return kaweth_control(kaweth,
+@@ -1009,8 +1022,7 @@ static int kaweth_probe(
+ 		info("Downloading firmware...");
+ 		kaweth->firmware_buf = (__u8 *)__get_free_page(GFP_KERNEL);
+ 		if ((result = kaweth_download_firmware(kaweth,
+-						      kaweth_new_code,
+-						      len_kaweth_new_code,
++						      "kaweth/new_code.bin",
+ 						      100,
+ 						      2)) < 0) {
+ 			err("Error downloading firmware (%d)", result);
+@@ -1018,8 +1030,7 @@ static int kaweth_probe(
+ 		}
+ 
+ 		if ((result = kaweth_download_firmware(kaweth,
+-						      kaweth_new_code_fix,
+-						      len_kaweth_new_code_fix,
++						      "kaweth/new_code_fix.bin",
+ 						      100,
+ 						      3)) < 0) {
+ 			err("Error downloading firmware fix (%d)", result);
+@@ -1027,8 +1038,7 @@ static int kaweth_probe(
+ 		}
+ 
+ 		if ((result = kaweth_download_firmware(kaweth,
+-						      kaweth_trigger_code,
+-						      len_kaweth_trigger_code,
++						      "kaweth/trigger_code.bin",
+ 						      126,
+ 						      2)) < 0) {
+ 			err("Error downloading trigger code (%d)", result);
+@@ -1037,8 +1047,7 @@ static int kaweth_probe(
+ 		}
+ 
+ 		if ((result = kaweth_download_firmware(kaweth,
+-						      kaweth_trigger_code_fix,
+-						      len_kaweth_trigger_code_fix,
++						      "kaweth/trigger_code_fix.bin",
+ 						      126,
+ 						      3)) < 0) {
+ 			err("Error downloading trigger code fix (%d)", result);
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-char-drm-mga-request_firmware.patch	(revision 0)
@@ -0,0 +1,295 @@
+From 32f99018901dd149fbd1be7da408f6f6b5246f5b Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 04:28:10 +0100
+Subject: [PATCH] mga: Use request_firmware() to load microcode
+
+Image format is IHEX, one record for each pipe in order (record
+addresses are ignored).
+
+Compile-tested only.
+---
+ drivers/char/drm/Kconfig    |    2 +-
+ drivers/char/drm/mga_dma.c  |    4 +-
+ drivers/char/drm/mga_drm.h  |    2 +-
+ drivers/char/drm/mga_drv.h  |    1 -
+ drivers/char/drm/mga_warp.c |  180 +++++++++++++++++++------------------------
+ 5 files changed, 82 insertions(+), 107 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index 1a3d250..5268ad4 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -81,7 +81,7 @@ endchoice
+ config DRM_MGA
+ 	tristate "Matrox g200/g400"
+ 	depends on DRM
+-	depends on BROKEN
++	select FW_LOADER
+ 	help
+ 	  Choose this option if you have a Matrox G200, G400 or G450 graphics
+ 	  card.  If M is selected, the module will be called mga.  AGP
+diff --git a/drivers/char/drm/mga_dma.c b/drivers/char/drm/mga_dma.c
+index c1d12db..bcd3ff1 100644
+--- a/drivers/char/drm/mga_dma.c
++++ b/drivers/char/drm/mga_dma.c
+@@ -439,7 +439,7 @@ static int mga_do_agp_dma_bootstrap(struct drm_device * dev,
+ {
+ 	drm_mga_private_t *const dev_priv =
+ 	    (drm_mga_private_t *) dev->dev_private;
+-	unsigned int warp_size = mga_warp_microcode_size(dev_priv);
++	unsigned int warp_size = MGA_WARP_UCODE_SIZE;
+ 	int err;
+ 	unsigned offset;
+ 	const unsigned secondary_size = dma_bs->secondary_bin_count
+@@ -614,7 +614,7 @@ static int mga_do_pci_dma_bootstrap(struct drm_device * dev,
+ {
+ 	drm_mga_private_t *const dev_priv =
+ 	    (drm_mga_private_t *) dev->dev_private;
+-	unsigned int warp_size = mga_warp_microcode_size(dev_priv);
++	unsigned int warp_size = MGA_WARP_UCODE_SIZE;
+ 	unsigned int primary_size;
+ 	unsigned int bin_count;
+ 	int err;
+diff --git a/drivers/char/drm/mga_drm.h b/drivers/char/drm/mga_drm.h
+index 944b50a..0b8fc27 100644
+--- a/drivers/char/drm/mga_drm.h
++++ b/drivers/char/drm/mga_drm.h
+@@ -69,7 +69,7 @@
+ #define MGA_MAX_G200_PIPES	8	/* no multitex */
+ #define MGA_MAX_G400_PIPES	16
+ #define MGA_MAX_WARP_PIPES	MGA_MAX_G400_PIPES
+-#define MGA_WARP_UCODE_SIZE	32768	/* in bytes */
++#define MGA_WARP_UCODE_SIZE	40960	/* in bytes */
+ 
+ #define MGA_CARD_TYPE_G200	1
+ #define MGA_CARD_TYPE_G400	2
+diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
+index f6ebd24..e3945c2 100644
+--- a/drivers/char/drm/mga_drv.h
++++ b/drivers/char/drm/mga_drv.h
+@@ -176,7 +176,6 @@ extern void mga_do_dma_wrap_end(drm_mga_private_t * dev_priv);
+ extern int mga_freelist_put(struct drm_device * dev, struct drm_buf * buf);
+ 
+ 				/* mga_warp.c */
+-extern unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv);
+ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
+ extern int mga_warp_init(drm_mga_private_t * dev_priv);
+ 
+diff --git a/drivers/char/drm/mga_warp.c b/drivers/char/drm/mga_warp.c
+index 651b93c..9aad484 100644
+--- a/drivers/char/drm/mga_warp.c
++++ b/drivers/char/drm/mga_warp.c
+@@ -27,132 +27,108 @@
+  *    Gareth Hughes <gareth@valinux.com>
+  */
+ 
++#include <linux/firmware.h>
++#include <linux/ihex.h>
++#include <linux/platform_device.h>
++
+ #include "drmP.h"
+ #include "drm.h"
+ #include "mga_drm.h"
+ #include "mga_drv.h"
+-#include "mga_ucode.h"
++
++#define FIRMWARE_G200 "matrox/g200_warp.fw"
++#define FIRMWARE_G400 "matrox/g400_warp.fw"
++
++MODULE_FIRMWARE(FIRMWARE_G200);
++MODULE_FIRMWARE(FIRMWARE_G400);
+ 
+ #define MGA_WARP_CODE_ALIGN		256	/* in bytes */
+ 
+-#define WARP_UCODE_SIZE( which )					\
+-	((sizeof(which) / MGA_WARP_CODE_ALIGN + 1) * MGA_WARP_CODE_ALIGN)
+-
+-#define WARP_UCODE_INSTALL( which, where )				\
+-do {									\
+-	DRM_DEBUG( " pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase );\
+-	dev_priv->warp_pipe_phys[where] = pcbase;			\
+-	memcpy( vcbase, which, sizeof(which) );				\
+-	pcbase += WARP_UCODE_SIZE( which );				\
+-	vcbase += WARP_UCODE_SIZE( which );				\
+-} while (0)
+-
+-static const unsigned int mga_warp_g400_microcode_size =
+-    (WARP_UCODE_SIZE(warp_g400_tgz) +
+-     WARP_UCODE_SIZE(warp_g400_tgza) +
+-     WARP_UCODE_SIZE(warp_g400_tgzaf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzs) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsa) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsaf) +
+-     WARP_UCODE_SIZE(warp_g400_tgzsf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gz) +
+-     WARP_UCODE_SIZE(warp_g400_t2gza) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzaf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzf) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzs) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzsa) +
+-     WARP_UCODE_SIZE(warp_g400_t2gzsaf) + WARP_UCODE_SIZE(warp_g400_t2gzsf));
+-
+-static const unsigned int mga_warp_g200_microcode_size =
+-    (WARP_UCODE_SIZE(warp_g200_tgz) +
+-     WARP_UCODE_SIZE(warp_g200_tgza) +
+-     WARP_UCODE_SIZE(warp_g200_tgzaf) +
+-     WARP_UCODE_SIZE(warp_g200_tgzf) +
+-     WARP_UCODE_SIZE(warp_g200_tgzs) +
+-     WARP_UCODE_SIZE(warp_g200_tgzsa) +
+-     WARP_UCODE_SIZE(warp_g200_tgzsaf) + WARP_UCODE_SIZE(warp_g200_tgzsf));
+-
+-unsigned int mga_warp_microcode_size(const drm_mga_private_t * dev_priv)
++#define WARP_UCODE_SIZE(size)		ALIGN(size, MGA_WARP_CODE_ALIGN)
++
++int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+ {
++	unsigned char *vcbase = dev_priv->warp->handle;
++	unsigned long pcbase = dev_priv->warp->offset;
++	const char *firmware_name;
++	struct platform_device *pdev;
++	const struct firmware *fw = NULL;
++	const struct ihex_binrec *rec;
++	unsigned int size;
++	int n_pipes, where;
++	int rc = 0;
++
+ 	switch (dev_priv->chipset) {
+ 	case MGA_CARD_TYPE_G400:
+ 	case MGA_CARD_TYPE_G550:
+-		return PAGE_ALIGN(mga_warp_g400_microcode_size);
++		firmware_name = FIRMWARE_G400;
++		n_pipes = MGA_MAX_G400_PIPES;
++		break;
+ 	case MGA_CARD_TYPE_G200:
+-		return PAGE_ALIGN(mga_warp_g200_microcode_size);
++		firmware_name = FIRMWARE_G200;
++		n_pipes = MGA_MAX_G200_PIPES;
++		break;
+ 	default:
+-		return 0;
++		return -EINVAL;
+ 	}
+-}
+-
+-static int mga_warp_install_g400_microcode(drm_mga_private_t * dev_priv)
+-{
+-	unsigned char *vcbase = dev_priv->warp->handle;
+-	unsigned long pcbase = dev_priv->warp->offset;
+-
+-	memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+-
+-	WARP_UCODE_INSTALL(warp_g400_tgz, MGA_WARP_TGZ);
+-	WARP_UCODE_INSTALL(warp_g400_tgzf, MGA_WARP_TGZF);
+-	WARP_UCODE_INSTALL(warp_g400_tgza, MGA_WARP_TGZA);
+-	WARP_UCODE_INSTALL(warp_g400_tgzaf, MGA_WARP_TGZAF);
+-	WARP_UCODE_INSTALL(warp_g400_tgzs, MGA_WARP_TGZS);
+-	WARP_UCODE_INSTALL(warp_g400_tgzsf, MGA_WARP_TGZSF);
+-	WARP_UCODE_INSTALL(warp_g400_tgzsa, MGA_WARP_TGZSA);
+-	WARP_UCODE_INSTALL(warp_g400_tgzsaf, MGA_WARP_TGZSAF);
+-
+-	WARP_UCODE_INSTALL(warp_g400_t2gz, MGA_WARP_T2GZ);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzf, MGA_WARP_T2GZF);
+-	WARP_UCODE_INSTALL(warp_g400_t2gza, MGA_WARP_T2GZA);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzaf, MGA_WARP_T2GZAF);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzs, MGA_WARP_T2GZS);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzsf, MGA_WARP_T2GZSF);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzsa, MGA_WARP_T2GZSA);
+-	WARP_UCODE_INSTALL(warp_g400_t2gzsaf, MGA_WARP_T2GZSAF);
+-
+-	return 0;
+-}
+-
+-static int mga_warp_install_g200_microcode(drm_mga_private_t * dev_priv)
+-{
+-	unsigned char *vcbase = dev_priv->warp->handle;
+-	unsigned long pcbase = dev_priv->warp->offset;
+-
+-	memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
+-
+-	WARP_UCODE_INSTALL(warp_g200_tgz, MGA_WARP_TGZ);
+-	WARP_UCODE_INSTALL(warp_g200_tgzf, MGA_WARP_TGZF);
+-	WARP_UCODE_INSTALL(warp_g200_tgza, MGA_WARP_TGZA);
+-	WARP_UCODE_INSTALL(warp_g200_tgzaf, MGA_WARP_TGZAF);
+-	WARP_UCODE_INSTALL(warp_g200_tgzs, MGA_WARP_TGZS);
+-	WARP_UCODE_INSTALL(warp_g200_tgzsf, MGA_WARP_TGZSF);
+-	WARP_UCODE_INSTALL(warp_g200_tgzsa, MGA_WARP_TGZSA);
+-	WARP_UCODE_INSTALL(warp_g200_tgzsaf, MGA_WARP_TGZSAF);
+ 
+-	return 0;
+-}
++	pdev = platform_device_register_simple("mga_warp", 0, NULL, 0);
++	if (IS_ERR(pdev)) {
++		DRM_ERROR("mga: Failed to register microcode\n");
++		return PTR_ERR(pdev);
++	}
++	rc = request_ihex_firmware(&fw, firmware_name, &pdev->dev);
++	platform_device_unregister(pdev);
++	if (rc) {
++		DRM_ERROR("mga: Failed to load microcode \"%s\"\n",
++			  firmware_name);
++		return rc;
++	}
+ 
+-int mga_warp_install_microcode(drm_mga_private_t * dev_priv)
+-{
+-	const unsigned int size = mga_warp_microcode_size(dev_priv);
++	size = 0;
++	where = 0;
++	for (rec = (const struct ihex_binrec *)fw->data;
++	     rec;
++	     rec = ihex_next_binrec(rec)) {
++		size += WARP_UCODE_SIZE(be16_to_cpu(rec->len));
++		where++;
++	}
+ 
++	if (where != n_pipes) {
++		DRM_ERROR("mga: Invalid microcode \"%s\"\n", firmware_name);
++		rc = -EINVAL;
++		goto out;
++	}
++	size = PAGE_ALIGN(size);
+ 	DRM_DEBUG("MGA ucode size = %d bytes\n", size);
+ 	if (size > dev_priv->warp->size) {
+ 		DRM_ERROR("microcode too large! (%u > %lu)\n",
+ 			  size, dev_priv->warp->size);
+-		return -ENOMEM;
++		rc = -ENOMEM;
++		goto out;
+ 	}
+ 
+-	switch (dev_priv->chipset) {
+-	case MGA_CARD_TYPE_G400:
+-	case MGA_CARD_TYPE_G550:
+-		return mga_warp_install_g400_microcode(dev_priv);
+-	case MGA_CARD_TYPE_G200:
+-		return mga_warp_install_g200_microcode(dev_priv);
+-	default:
+-		return -EINVAL;
++	memset(dev_priv->warp_pipe_phys, 0, sizeof(dev_priv->warp_pipe_phys));
++
++	where = 0;
++	for (rec = (const struct ihex_binrec *)fw->data;
++	     rec;
++	     rec = ihex_next_binrec(rec)) {
++		unsigned int src_size, dst_size;
++
++		DRM_DEBUG(" pcbase = 0x%08lx  vcbase = %p\n", pcbase, vcbase);
++		dev_priv->warp_pipe_phys[where] = pcbase;
++		src_size = be16_to_cpu(rec->len);
++		dst_size = WARP_UCODE_SIZE(src_size);
++		memcpy(vcbase, rec->data, src_size);
++		pcbase += dst_size;
++		vcbase += dst_size;
++		where++;
+ 	}
++
++out:
++	release_firmware(fw);
++	return rc;
+ }
+ 
+ #define WMISC_EXPECTED		(MGA_WUCODECACHE_ENABLE | MGA_WMASTER_ENABLE)
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-starfire-request_firmware.patch	(revision 0)
@@ -0,0 +1,180 @@
+From 24add72cd3fc11429f3e0db2a50d08a0f272835c Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:13:56 +0100
+Subject: [PATCH] starfire: use request_firmware()
+
+Based on patch by Jaswinder Singh <jaswinder@infradead.org> and
+David Woodhouse <David.Woodhouse@intel.com>.
+
+Firmware blob is big endian
+---
+ drivers/net/Kconfig    |    2 +-
+ drivers/net/starfire.c |   68 +++++++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 63 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index ae6d38f..a167a5e 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -1304,9 +1304,9 @@ config AMD8111E_NAPI
+ config ADAPTEC_STARFIRE
+ 	tristate "Adaptec Starfire/DuraLAN support"
+ 	depends on NET_PCI && PCI
+-	depends on BROKEN
+ 	select CRC32
+ 	select MII
++	select FW_LOADER
+ 	help
+ 	  Say Y here if you have an Adaptec Starfire (or DuraLAN) PCI network
+ 	  adapter. The DuraLAN chip is used on the 64 bit PCI boards from
+diff --git a/drivers/net/starfire.c b/drivers/net/starfire.c
+index 7b7b171..63e426b 100644
+--- a/drivers/net/starfire.c
++++ b/drivers/net/starfire.c
+@@ -42,11 +42,11 @@
+ #include <linux/mii.h>
+ #include <linux/if_vlan.h>
+ #include <linux/mm.h>
++#include <linux/firmware.h>
+ #include <asm/processor.h>		/* Processor type for cache alignment. */
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ 
+-#include "starfire_firmware.h"
+ /*
+  * The current frame processor firmware fails to checksum a fragment
+  * of length 1. If and when this is fixed, the #define below can be removed.
+@@ -214,6 +214,9 @@ do { \
+ #endif /* not HAVE_NETDEV_POLL */
+ /* end of compatibility code */
+ 
++/* Firmware names */
++#define FIRMWARE_RX	"adaptec/starfire_rx.bin"
++#define FIRMWARE_TX	"adaptec/starfire_tx.bin"
+ 
+ /* These identify the driver base version and may not be removed. */
+ static char version[] =
+@@ -223,6 +226,8 @@ KERN_INFO " (unofficial 2.2/2.4 kernel port, version " DRV_VERSION ", " DRV_RELD
+ MODULE_AUTHOR("Donald Becker <becker@scyld.com>");
+ MODULE_DESCRIPTION("Adaptec Starfire Ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_RX);
++MODULE_FIRMWARE(FIRMWARE_TX);
+ MODULE_VERSION(DRV_VERSION);
+ 
+ module_param(max_interrupt_work, int, 0);
+@@ -622,6 +627,9 @@ struct netdev_private {
+ 	int phy_cnt;			/* MII device addresses. */
+ 	unsigned char phys[PHY_CNT];	/* MII device addresses. */
+ 	void __iomem *base;
++
++	/* Firmware section */
++	const struct firmware *fw_rx, *fw_tx;
+ };
+ 
+ 
+@@ -682,6 +690,42 @@ static void netdev_vlan_rx_kill_vid(struct net_device *dev, unsigned short vid)
+ }
+ #endif /* VLAN_SUPPORT */
+ 
++static int starfire_init_firmware(struct netdev_private *np)
++{
++	int retval;
++
++	retval = request_firmware(&np->fw_rx, FIRMWARE_RX, &np->pci_dev->dev);
++	if (retval) {
++		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
++		       FIRMWARE_RX);
++		return retval;
++	}
++	if (np->fw_rx->size % 4) {
++		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
++		       np->fw_rx->size, FIRMWARE_RX);
++		retval = -EINVAL;
++		goto out_rx;
++	}
++	retval = request_firmware(&np->fw_tx, FIRMWARE_TX, &np->pci_dev->dev);
++	if (retval) {
++		printk(KERN_ERR "starfire: Failed to load firmware \"%s\"\n",
++		       FIRMWARE_TX);
++		goto out_rx;
++	}
++	if (np->fw_tx->size % 4) {
++		printk(KERN_ERR "starfire: bogus length %zu in \"%s\"\n",
++		       np->fw_tx->size, FIRMWARE_TX);
++		retval = -EINVAL;
++		goto out_tx;
++	}
++	return 0;
++
++out_tx:
++	release_firmware(np->fw_tx);
++out_rx:
++	release_firmware(np->fw_rx);
++	return retval;
++}
+ 
+ static int __devinit starfire_init_one(struct pci_dev *pdev,
+ 				       const struct pci_device_id *ent)
+@@ -868,6 +912,9 @@ static int __devinit starfire_init_one(struct pci_dev *pdev,
+ 	       dev->name, netdrv_tbl[chip_idx].name, base,
+ 	       print_mac(mac, dev->dev_addr), irq);
+ 
++	if (starfire_init_firmware(np))
++		goto err_out_cleardev;
++
+ 	if (drv_flags & CanHaveMII) {
+ 		int phy, phy_idx = 0;
+ 		int mii_status;
+@@ -946,7 +993,9 @@ static int netdev_open(struct net_device *dev)
+ {
+ 	struct netdev_private *np = netdev_priv(dev);
+ 	void __iomem *ioaddr = np->base;
++	const __be32 *fw_rx_data, *fw_tx_data;
+ 	int i, retval;
++	size_t tx_size, rx_size;
+ 	size_t tx_done_q_size, rx_done_q_size, tx_ring_size, rx_ring_size;
+ 
+ 	/* Do we ever need to reset the chip??? */
+@@ -1083,11 +1132,15 @@ static int netdev_open(struct net_device *dev)
+ 	writel(ETH_P_8021Q, ioaddr + VlanType);
+ #endif /* VLAN_SUPPORT */
+ 
++	fw_rx_data = (const __be32 *)&np->fw_rx->data[0];
++	fw_tx_data = (const __be32 *)&np->fw_tx->data[0];
++	rx_size = np->fw_rx->size / 4;
++	tx_size = np->fw_tx->size / 4;
+ 	/* Load Rx/Tx firmware into the frame processors */
+-	for (i = 0; i < FIRMWARE_RX_SIZE * 2; i++)
+-		writel(firmware_rx[i], ioaddr + RxGfpMem + i * 4);
+-	for (i = 0; i < FIRMWARE_TX_SIZE * 2; i++)
+-		writel(firmware_tx[i], ioaddr + TxGfpMem + i * 4);
++	for (i = 0; i < rx_size; i++)
++		writel(be32_to_cpup(&fw_rx_data[i]), ioaddr + RxGfpMem + i * 4);
++	for (i = 0; i < tx_size; i++)
++		writel(be32_to_cpup(&fw_tx_data[i]), ioaddr + TxGfpMem + i * 4);
+ 	if (enable_hw_cksum)
+ 		/* Enable the Rx and Tx units, and the Rx/Tx frame processors. */
+ 		writel(TxEnable|TxGFPEnable|RxEnable|RxGFPEnable, ioaddr + GenCtrl);
+@@ -1099,7 +1152,7 @@ static int netdev_open(struct net_device *dev)
+ 		printk(KERN_DEBUG "%s: Done netdev_open().\n",
+ 		       dev->name);
+ 
+-	return 0;
++	return retval;
+ }
+ 
+ 
+@@ -2009,6 +2062,9 @@ static void __devexit starfire_remove_one (struct pci_dev *pdev)
+ 
+ 	BUG_ON(!dev);
+ 
++	release_firmware(np->fw_tx);
++	release_firmware(np->fw_rx);
++
+ 	unregister_netdev(dev);
+ 
+ 	if (np->queue_mem)
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-char-drm-radeon-request_firmware.patch	(revision 0)
@@ -0,0 +1,358 @@
+From 6e8e826c3577a4d4d875c754fd207e132c8f3a8a Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 01:29:35 +0100
+Subject: [PATCH] radeon: Use request_firmware() to load CP microcode
+
+Tested on Radeon 7500 (RV200) with and without firmware installed.
+---
+ drivers/char/drm/Kconfig      |    2 +-
+ drivers/char/drm/radeon_cp.c  |  151 ++++++++++++++++++++++++-----------------
+ drivers/char/drm/radeon_drv.h |    6 ++
+ 3 files changed, 95 insertions(+), 64 deletions(-)
+
+diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
+index 3b0dd6a..17edd8a 100644
+--- a/drivers/char/drm/Kconfig
++++ b/drivers/char/drm/Kconfig
+@@ -35,7 +35,7 @@ config DRM_R128
+ config DRM_RADEON
+ 	tristate "ATI Radeon"
+ 	depends on DRM && PCI
+-	depends on BROKEN
++	select FW_LOADER
+ 	help
+ 	  Choose this option if you have an ATI Radeon graphics card.  There
+ 	  are both PCI and AGP versions.  You don't need to choose this to
+diff --git a/drivers/char/drm/radeon_cp.c b/drivers/char/drm/radeon_cp.c
+index e53158f..5542b0b 100644
+--- a/drivers/char/drm/radeon_cp.c
++++ b/drivers/char/drm/radeon_cp.c
+@@ -35,10 +35,23 @@
+ #include "radeon_drv.h"
+ #include "r300_reg.h"
+ 
+-#include "radeon_microcode.h"
+-
+ #define RADEON_FIFO_DEBUG	0
+ 
++/* Firmware Names */
++#define FIRMWARE_R100		"radeon/R100_cp.bin"
++#define FIRMWARE_R200		"radeon/R200_cp.bin"
++#define FIRMWARE_R300		"radeon/R300_cp.bin"
++#define FIRMWARE_R420		"radeon/R420_cp.bin"
++#define FIRMWARE_RS690		"radeon/RS690_cp.bin"
++#define FIRMWARE_R520		"radeon/R520_cp.bin"
++
++MODULE_FIRMWARE(FIRMWARE_R100);
++MODULE_FIRMWARE(FIRMWARE_R200);
++MODULE_FIRMWARE(FIRMWARE_R300);
++MODULE_FIRMWARE(FIRMWARE_R420);
++MODULE_FIRMWARE(FIRMWARE_RS690);
++MODULE_FIRMWARE(FIRMWARE_R520);
++
+ static int radeon_do_cleanup_cp(struct drm_device * dev);
+ 
+ static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr)
+@@ -320,66 +333,48 @@ static void radeon_init_pipes(drm_radeon_private_t *dev_priv)
+  */
+ 
+ /* Load the microcode for the CP */
+-static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
++static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv)
+ {
+-	int i;
++	struct platform_device *pdev;
++	const char *fw_name = NULL;
++	int err;
++
+ 	DRM_DEBUG("\n");
+ 
+-	radeon_do_wait_for_idle(dev_priv);
++	pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
++	err = IS_ERR(pdev);
++	if (err) {
++		printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
++		return -EINVAL;
++	}
+ 
+-	RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
+ 	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) ||
+ 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) ||
+ 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) ||
+ 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) ||
+ 	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) {
+ 		DRM_INFO("Loading R100 Microcode\n");
+-		for (i = 0; i < 256; i++) {
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     R100_cp_microcode[i][1]);
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     R100_cp_microcode[i][0]);
+-		}
++		fw_name = FIRMWARE_R100;
+ 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) {
+ 		DRM_INFO("Loading R200 Microcode\n");
+-		for (i = 0; i < 256; i++) {
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     R200_cp_microcode[i][1]);
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     R200_cp_microcode[i][0]);
+-		}
++		fw_name = FIRMWARE_R200;
+ 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) {
+ 		DRM_INFO("Loading R300 Microcode\n");
+-		for (i = 0; i < 256; i++) {
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     R300_cp_microcode[i][1]);
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     R300_cp_microcode[i][0]);
+-		}
++		fw_name = FIRMWARE_R300;
+ 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) {
+ 		DRM_INFO("Loading R400 Microcode\n");
+-		for (i = 0; i < 256; i++) {
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     R420_cp_microcode[i][1]);
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     R420_cp_microcode[i][0]);
+-		}
++		fw_name = FIRMWARE_R420;
+ 	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) {
+ 		DRM_INFO("Loading RS690 Microcode\n");
+-		for (i = 0; i < 256; i++) {
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     RS690_cp_microcode[i][1]);
+-			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     RS690_cp_microcode[i][0]);
+-		}
++		fw_name = FIRMWARE_RS690;
+ 	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) ||
+@@ -387,11 +382,40 @@ static void radeon_cp_load_microcode(drm_radeon_private_t * dev_priv)
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) ||
+ 		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) {
+ 		DRM_INFO("Loading R500 Microcode\n");
+-		for (i = 0; i < 256; i++) {
++		fw_name = FIRMWARE_R520;
++	}
++
++	err = request_firmware(&dev_priv->fw, fw_name, &pdev->dev);
++	platform_device_unregister(pdev);
++	if (err)
++		printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n",
++		       fw_name);
++	else if (dev_priv->fw->size % 8) {
++		printk(KERN_ERR
++		       "radeon_cp: Bogus length %zu in firmware \"%s\"\n",
++		       dev_priv->fw->size, fw_name);
++		err = -EINVAL;
++		release_firmware(dev_priv->fw);
++	}
++	return err;
++}
++
++static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv)
++{
++	const __be32 *fw_data;
++	int i, size;
++
++	radeon_do_wait_for_idle(dev_priv);
++
++	if (dev_priv->fw) {
++		size = dev_priv->fw->size / 4;
++		fw_data = (const __be32 *)&dev_priv->fw->data[0];
++		RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0);
++		for (i = 0; i < size; i += 2) {
+ 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAH,
+-				     R520_cp_microcode[i][1]);
++				     be32_to_cpup(&fw_data[i]));
+ 			RADEON_WRITE(RADEON_CP_ME_RAM_DATAL,
+-				     R520_cp_microcode[i][0]);
++				     be32_to_cpup(&fw_data[i + 1]));
+ 		}
+ 	}
+ }
+@@ -853,14 +877,14 @@ static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on)
+ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ {
+ 	drm_radeon_private_t *dev_priv = dev->dev_private;
++	int err = -EINVAL;
+ 
+ 	DRM_DEBUG("\n");
+ 
+ 	/* if we require new memory map but we don't have it fail */
+ 	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
+ 		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
+@@ -874,16 +898,14 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 
+ 	if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) {
+ 		DRM_ERROR("PCI GART memory not allocated!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	dev_priv->usec_timeout = init->usec_timeout;
+ 	if (dev_priv->usec_timeout < 1 ||
+ 	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
+ 		DRM_DEBUG("TIMEOUT problem!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	/* Enable vblank on CRTC1 for older X servers
+@@ -911,8 +933,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
+ 	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
+ 		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	switch (init->fb_bpp) {
+@@ -980,28 +1001,24 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 	dev_priv->sarea = drm_getsarea(dev);
+ 	if (!dev_priv->sarea) {
+ 		DRM_ERROR("could not find sarea!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
+ 	if (!dev_priv->cp_ring) {
+ 		DRM_ERROR("could not find cp ring region!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
+ 	if (!dev_priv->ring_rptr) {
+ 		DRM_ERROR("could not find ring read pointer!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 	dev->agp_buffer_token = init->buffers_offset;
+ 	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
+ 	if (!dev->agp_buffer_map) {
+ 		DRM_ERROR("could not find dma buffer region!\n");
+-		radeon_do_cleanup_cp(dev);
+-		return -EINVAL;
++		goto out;
+ 	}
+ 
+ 	if (init->gart_textures_offset) {
+@@ -1009,8 +1026,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 		    drm_core_findmap(dev, init->gart_textures_offset);
+ 		if (!dev_priv->gart_textures) {
+ 			DRM_ERROR("could not find GART texture region!\n");
+-			radeon_do_cleanup_cp(dev);
+-			return -EINVAL;
++			goto out;
+ 		}
+ 	}
+ 
+@@ -1027,8 +1043,7 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 		    !dev_priv->ring_rptr->handle ||
+ 		    !dev->agp_buffer_map->handle) {
+ 			DRM_ERROR("could not find ioremap agp regions!\n");
+-			radeon_do_cleanup_cp(dev);
+-			return -EINVAL;
++			goto out;
+ 		}
+ 	} else
+ #endif
+@@ -1180,21 +1195,25 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 			if (dev_priv->flags & RADEON_IS_PCIE) {
+ 				DRM_ERROR
+ 				    ("Cannot use PCI Express without GART in FB memory\n");
+-				radeon_do_cleanup_cp(dev);
+-				return -EINVAL;
++				goto out;
+ 			}
+ 		}
+ 
+ 		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {
+ 			DRM_ERROR("failed to init PCI GART!\n");
+-			radeon_do_cleanup_cp(dev);
+-			return -ENOMEM;
++			err = -ENOMEM;
++			goto out;
+ 		}
+ 
+ 		/* Turn on PCI GART */
+ 		radeon_set_pcigart(dev_priv, 1);
+ 	}
+ 
++	err = radeon_cp_init_microcode(dev_priv);
++	if (err) {
++		DRM_ERROR("Failed to load firmware!\n");
++		goto out;
++	}
+ 	radeon_cp_load_microcode(dev_priv);
+ 	radeon_cp_init_ring_buffer(dev, dev_priv);
+ 
+@@ -1204,6 +1223,9 @@ static int radeon_do_init_cp(struct drm_device * dev, drm_radeon_init_t * init)
+ 	radeon_test_writeback(dev_priv);
+ 
+ 	return 0;
++out:
++	radeon_do_cleanup_cp(dev);
++	return err;
+ }
+ 
+ static int radeon_do_cleanup_cp(struct drm_device * dev)
+@@ -1249,6 +1271,9 @@ static int radeon_do_cleanup_cp(struct drm_device * dev)
+ 			dev_priv->gart_info.addr = 0;
+ 		}
+ 	}
++
++	release_firmware(dev_priv->fw);
++
+ 	/* only clear to the start of flags */
+ 	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
+ 
+diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
+index 3f0eca9..5cc808e 100644
+--- a/drivers/char/drm/radeon_drv.h
++++ b/drivers/char/drm/radeon_drv.h
+@@ -31,6 +31,9 @@
+ #ifndef __RADEON_DRV_H__
+ #define __RADEON_DRV_H__
+ 
++#include <linux/firmware.h>
++#include <linux/platform_device.h>
++
+ /* General customization:
+  */
+ 
+@@ -311,6 +314,9 @@ typedef struct drm_radeon_private {
+ 	unsigned long fb_aper_offset;
+ 
+ 	int num_gb_pipes;
++
++	/* firmware */
++	const struct firmware *fw;
+ } drm_radeon_private_t;
+ 
+ typedef struct drm_radeon_buf_priv {
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/firmware-ihex.patch
===================================================================
--- linux-2.6/debian/patches/features/all/firmware-ihex.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/firmware-ihex.patch	(revision 0)
@@ -0,0 +1,114 @@
+From cd76b5773b38860d3ffbe6f332d2feddae9191c1 Mon Sep 17 00:00:00 2001
+From: David Woodhouse <dwmw2@infradead.org>
+Date: Fri, 30 May 2008 13:57:27 +0300
+Subject: [PATCH] ihex.h: binary representation of ihex records
+
+Combination of two patches by David Woodhouse:
+
+Some devices need their firmware as a set of {address, len, data...}
+records in some specific order rather than a simple blob.
+
+The normal way of doing this kind of thing is 'ihex', which is a text
+format and not entirely suitable for use in the kernel.
+
+This provides a binary representation which is very similar, but much
+more compact -- and a helper routine to skip to the next record,
+because the alignment constraints mean that everybody will screw it up
+for themselves otherwise.
+
+Also a helper function which can verify that a 'struct firmware'
+contains a valid set of ihex records, and that following them won't run
+off the end of the loaded data.
+
+Provide a helper to load the file and validate it in one call, to
+simplify error handling in the drivers which are going to use it.
+
+Signed-off-by: David Woodhouse <dwmw2@infradead.org>
+---
+ include/linux/ihex.h |   74 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 files changed, 74 insertions(+), 0 deletions(-)
+ create mode 100644 include/linux/ihex.h
+
+diff --git a/include/linux/ihex.h b/include/linux/ihex.h
+new file mode 100644
+index 0000000..2baace2
+--- /dev/null
++++ b/include/linux/ihex.h
+@@ -0,0 +1,74 @@
++/*
++ * Compact binary representation of ihex records. Some devices need their
++ * firmware loaded in strange orders rather than a single big blob, but
++ * actually parsing ihex-as-text within the kernel seems silly. Thus,...
++ */
++
++#ifndef __LINUX_IHEX_H__
++#define __LINUX_IHEX_H__
++
++#include <linux/types.h>
++#include <linux/firmware.h>
++#include <linux/device.h>
++
++/* Intel HEX files actually limit the length to 256 bytes, but we have
++   drivers which would benefit from using separate records which are
++   longer than that, so we extend to 16 bits of length */
++struct ihex_binrec {
++	__be32 addr;
++	__be16 len;
++	uint8_t data[0];
++} __attribute__((aligned(4)));
++
++/* Find the next record, taking into account the 4-byte alignment */
++static inline const struct ihex_binrec *
++ihex_next_binrec(const struct ihex_binrec *rec)
++{
++	int next = ((be16_to_cpu(rec->len) + 5) & ~3) - 2;
++	rec = (void *)&rec->data[next];
++
++	return be16_to_cpu(rec->len) ? rec : NULL;
++}
++
++/* Check that ihex_next_binrec() won't take us off the end of the image... */
++static inline int ihex_validate_fw(const struct firmware *fw)
++{
++	const struct ihex_binrec *rec;
++	size_t ofs = 0;
++
++	while (ofs <= fw->size - sizeof(*rec)) {
++		rec = (void *)&fw->data[ofs];
++
++		/* Zero length marks end of records */
++		if (!be16_to_cpu(rec->len))
++			return 0;
++
++		/* Point to next record... */
++		ofs += (sizeof(*rec) + be16_to_cpu(rec->len) + 3) & ~3;
++	}
++	return -EINVAL;
++}
++
++/* Request firmware and validate it so that we can trust we won't
++ * run off the end while reading records... */
++static inline int request_ihex_firmware(const struct firmware **fw,
++					const char *fw_name,
++					struct device *dev)
++{
++	const struct firmware *lfw;
++	int ret;
++
++	ret = request_firmware(&lfw, fw_name, dev);
++	if (ret)
++		return ret;
++	ret = ihex_validate_fw(lfw);
++	if (ret) {
++		dev_err(dev, "Firmware \"%s\" not valid IHEX records\n",
++			fw_name);
++		release_firmware(lfw);
++		return ret;
++	}
++	*fw = lfw;
++	return 0;
++}
++#endif /* __LINUX_IHEX_H__ */
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-net-cassini-request_firmware.patch	(revision 0)
@@ -0,0 +1,148 @@
+From 1fcdebdd05d5f730afc74cc910ab52497656fb93 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 02:06:48 +0100
+Subject: [PATCH] cassini: Use request_firmware() to load Saturn PHY firmware patch
+
+Based on patch by Jaswinder Singh <jaswinder@infradead.org>.
+
+Firmware blob looks like this...
+        __le16 load_address
+        unsigned char data[]
+---
+ drivers/net/Kconfig   |    2 +-
+ drivers/net/cassini.c |   44 ++++++++++++++++++++++++++++++++++++++------
+ drivers/net/cassini.h |    3 +++
+ 3 files changed, 42 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig
+index 9426787..eaacc85 100644
+--- a/drivers/net/Kconfig
++++ b/drivers/net/Kconfig
+@@ -584,8 +584,8 @@ config SUNGEM
+ config CASSINI
+ 	tristate "Sun Cassini support"
+ 	depends on PCI
+-	depends on BROKEN
+ 	select CRC32
++	select FW_LOADER
+ 	help
+ 	  Support for the Sun Cassini chip, aka Sun GigaSwift Ethernet. See also
+ 	  <http://www.sun.com/products-n-solutions/hardware/docs/pdf/817-4341-10.pdf>
+diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c
+index 83768df..71096ea 100644
+--- a/drivers/net/cassini.c
++++ b/drivers/net/cassini.c
+@@ -91,6 +91,7 @@
+ #include <linux/ip.h>
+ #include <linux/tcp.h>
+ #include <linux/mutex.h>
++#include <linux/firmware.h>
+ 
+ #include <net/checksum.h>
+ 
+@@ -188,6 +189,7 @@
+ #define CAS_RESET_SPARE                 3
+ #endif
+ 
++#define FIRMWARE_NAME			"sun/cassini.bin"
+ static char version[] __devinitdata =
+ 	DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+ 
+@@ -197,6 +199,7 @@ static int link_mode;
+ MODULE_AUTHOR("Adrian Sun (asun@darksunrising.com)");
+ MODULE_DESCRIPTION("Sun Cassini(+) ethernet driver");
+ MODULE_LICENSE("GPL");
++MODULE_FIRMWARE(FIRMWARE_NAME);
+ module_param(cassini_debug, int, 0);
+ MODULE_PARM_DESC(cassini_debug, "Cassini bitmapped debugging message enable value");
+ module_param(link_mode, int, 0);
+@@ -800,9 +803,33 @@ static int cas_reset_mii_phy(struct cas *cp)
+ 	return (limit <= 0);
+ }
+ 
++static int cas_saturn_firmware_init(struct cas *cp)
++{
++	int err;
++
++	if (PHY_NS_DP83065 != cp->phy_id) {
++		cp->fw = NULL;
++		return 0;
++	}
++
++	err = request_firmware(&cp->fw, FIRMWARE_NAME, &cp->pdev->dev);
++	if (err)
++		printk(KERN_ERR "cassini: Failed to load firmware \"%s\"\n",
++		       FIRMWARE_NAME);
++	else if (cp->fw->size < 2) {
++		printk(KERN_ERR "cassini: bogus length %zu in \"%s\"\n",
++		       cp->fw->size, FIRMWARE_NAME);
++		err = -EINVAL;
++		release_firmware(cp->fw);
++	}
++
++	return err;
++}
++
+ static void cas_saturn_firmware_load(struct cas *cp)
+ {
+-	cas_saturn_patch_t *patch = cas_saturn_patch;
++	int i;
++	u16 fw_load_addr;
+ 
+ 	cas_phy_powerdown(cp);
+ 
+@@ -819,13 +846,13 @@ static void cas_saturn_firmware_load(struct cas *cp)
+ 	cas_phy_write(cp, DP83065_MII_REGE, 0x8ffc);
+ 	cas_phy_write(cp, DP83065_MII_REGD, 0x39);
+ 
++	fw_load_addr = cp->fw->data[1] << 8 | cp->fw->data[0];
++
+ 	/* download new firmware */
+ 	cas_phy_write(cp, DP83065_MII_MEM, 0x1);
+-	cas_phy_write(cp, DP83065_MII_REGE, patch->addr);
+-	while (patch->addr) {
+-		cas_phy_write(cp, DP83065_MII_REGD, patch->val);
+-		patch++;
+-	}
++	cas_phy_write(cp, DP83065_MII_REGE, fw_load_addr);
++	for (i = 2; i < cp->fw->size; i++)
++		cas_phy_write(cp, DP83065_MII_REGD, cp->fw->data[i]);
+ 
+ 	/* enable firmware */
+ 	cas_phy_write(cp, DP83065_MII_REGE, 0x8ff8);
+@@ -5096,6 +5123,9 @@ static int __devinit cas_init_one(struct pci_dev *pdev,
+ 	cas_reset(cp, 0);
+ 	if (cas_check_invariants(cp))
+ 		goto err_out_iounmap;
++	if (cp->cas_flags & CAS_FLAG_SATURN)
++		if (cas_saturn_firmware_init(cp))
++			goto err_out_iounmap;
+ 
+ 	cp->init_block = (struct cas_init_block *)
+ 		pci_alloc_consistent(pdev, sizeof(struct cas_init_block),
+@@ -5205,6 +5235,8 @@ static void __devexit cas_remove_one(struct pci_dev *pdev)
+ 	cp = netdev_priv(dev);
+ 	unregister_netdev(dev);
+ 
++	release_firmware(cp->fw);
++
+ 	mutex_lock(&cp->pm_mutex);
+ 	flush_scheduled_work();
+ 	if (cp->hw_running)
+diff --git a/drivers/net/cassini.h b/drivers/net/cassini.h
+index 70f8b36..6f0f62f 100644
+--- a/drivers/net/cassini.h
++++ b/drivers/net/cassini.h
+@@ -2874,6 +2874,9 @@ struct cas {
+ 	dma_addr_t block_dvma, tx_tiny_dvma[N_TX_RINGS];
+ 	struct pci_dev *pdev;
+ 	struct net_device *dev;
++
++	/* Firmware section */
++	const struct firmware	*fw;
+ };
+ 
+ #define TX_DESC_NEXT(r, x)  (((x) + 1) & (TX_DESC_RINGN_SIZE(r) - 1))
+-- 
+1.5.6.5
+
Index: linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch
===================================================================
--- linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch	(revision 0)
+++ linux-2.6/debian/patches/features/all/drivers-media-video-dabusb-request_firmware.patch	(revision 0)
@@ -0,0 +1,165 @@
+From 3c26f7c55d6a0bc1769eff3d41db3db46620b37c Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Sat, 18 Oct 2008 15:48:14 +0100
+Subject: [PATCH] dabusb: Use request_firmware() to load firmware and FPGA bitfile
+
+Based on patch by David Woodhouse <David.Woodhouse@intel.com>.
+---
+ drivers/media/Kconfig        |    2 +-
+ drivers/media/video/dabusb.c |   60 +++++++++++++++++++++++++++++++++--------
+ 2 files changed, 49 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
+index ec7baaa..89fadba 100644
+--- a/drivers/media/Kconfig
++++ b/drivers/media/Kconfig
+@@ -125,7 +125,7 @@ if DAB
+ config USB_DABUSB
+ 	tristate "DABUSB driver"
+ 	depends on USB
+-	depends on BROKEN
++	select FW_LOADER
+ 	---help---
+ 	  A Digital Audio Broadcasting (DAB) Receiver for USB and Linux
+ 	  brought to you by the DAB-Team
+diff --git a/drivers/media/video/dabusb.c b/drivers/media/video/dabusb.c
+index 8d1f8ee..3d52e07 100644
+--- a/drivers/media/video/dabusb.c
++++ b/drivers/media/video/dabusb.c
+@@ -38,9 +38,10 @@
+ #include <linux/delay.h>
+ #include <linux/usb.h>
+ #include <linux/mutex.h>
++#include <linux/firmware.h>
++#include <linux/ihex.h>
+ 
+ #include "dabusb.h"
+-#include "dabfirmware.h"
+ 
+ /*
+  * Version Information
+@@ -49,6 +50,12 @@
+ #define DRIVER_AUTHOR "Deti Fliegl, deti@fliegl.de"
+ #define DRIVER_DESC "DAB-USB Interface Driver for Linux (c)1999"
+ 
++#define FIRMWARE_NAME "dabusb/firmware.fw"
++#define BITSTREAM_NAME "dabusb/bitstream.bin"
++
++MODULE_FIRMWARE(FIRMWARE_NAME);
++MODULE_FIRMWARE(BITSTREAM_NAME);
++
+ /* --------------------------------------------------------------------- */
+ 
+ #ifdef CONFIG_USB_DYNAMIC_MINORS
+@@ -297,7 +304,8 @@ static int dabusb_bulk (pdabusb_t s, pbulk_transfer_t pb)
+ 	return ret;
+ }
+ /* --------------------------------------------------------------------- */
+-static int dabusb_writemem (pdabusb_t s, int pos, unsigned char *data, int len)
++static int dabusb_writemem (pdabusb_t s, int pos, const unsigned char *data,
++			    int len)
+ {
+ 	int ret;
+ 	unsigned char *transfer_buffer =  kmalloc (len, GFP_KERNEL);
+@@ -324,24 +332,35 @@ static int dabusb_8051_reset (pdabusb_t s, unsigned char reset_bit)
+ static int dabusb_loadmem (pdabusb_t s, const char *fname)
+ {
+ 	int ret;
+-	PINTEL_HEX_RECORD ptr = firmware;
++	const struct ihex_binrec *rec;
++	const struct firmware *fw;
+ 
+ 	dbg("Enter dabusb_loadmem (internal)");
+ 
++	ret = request_ihex_firmware(&fw, FIRMWARE_NAME, &s->usbdev->dev);
++	if (ret) {
++		err("Failed to load \"" FIRMWARE_NAME "\": %d\n", ret);
++		goto out;
++	}
+ 	ret = dabusb_8051_reset (s, 1);
+-	while (ptr->Type == 0) {
+ 
+-		dbg("dabusb_writemem: %04X %p %d)", ptr->Address, ptr->Data, ptr->Length);
++	for (rec = (const struct ihex_binrec *)fw->data; rec;
++	     rec = ihex_next_binrec(rec)) {
++		dbg("dabusb_writemem: %04X %p %d)", be32_to_cpu(rec->addr),
++		    rec->data, be16_to_cpu(rec->len));
+ 
+-		ret = dabusb_writemem (s, ptr->Address, ptr->Data, ptr->Length);
++		ret = dabusb_writemem(s, be32_to_cpu(rec->addr), rec->data,
++				       be16_to_cpu(rec->len));
+ 		if (ret < 0) {
+-			err("dabusb_writemem failed (%d %04X %p %d)", ret, ptr->Address, ptr->Data, ptr->Length);
++			err("dabusb_writemem failed (%d %04X %p %d)", ret,
++			    be32_to_cpu(rec->addr), rec->data,
++			    be16_to_cpu(rec->len));
+ 			break;
+ 		}
+-		ptr++;
+ 	}
+ 	ret = dabusb_8051_reset (s, 0);
+-
++	release_firmware(fw);
++ out:
+ 	dbg("dabusb_loadmem: exit");
+ 
+ 	return ret;
+@@ -376,9 +395,9 @@ static int dabusb_fpga_init (pdabusb_t s, pbulk_transfer_t b)
+ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+ {
+ 	pbulk_transfer_t b = kmalloc (sizeof (bulk_transfer_t), GFP_KERNEL);
++	const struct firmware *fw;
+ 	unsigned int blen, n;
+ 	int ret;
+-	unsigned char *buf = bitstream;
+ 
+ 	dbg("Enter dabusb_fpga_download (internal)");
+ 
+@@ -387,10 +406,24 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+ 		return -ENOMEM;
+ 	}
+ 
++	ret = request_firmware(&fw, BITSTREAM_NAME, &s->usbdev->dev);
++	if (ret) {
++		err("Failed to load \"" BITSTREAM_NAME "\": %d\n", ret);
++		goto out_free;
++	}
++	if (fw->size < 74) {
++		ret = -EINVAL;
++		goto out_release;
++	}
++	blen = fw->data[73] + (fw->data[72] << 8);
++	if (fw->size != 74 + blen) {
++		ret = -EINVAL;
++		goto out_release;
++	}
++
+ 	b->pipe = 1;
+ 	ret = dabusb_fpga_clear (s, b);
+ 	mdelay (10);
+-	blen = buf[73] + (buf[72] << 8);
+ 
+ 	dbg("Bitstream len: %i", blen);
+ 
+@@ -402,7 +435,7 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+ 	for (n = 0; n <= blen + 60; n += 60) {
+ 		// some cclks for startup
+ 		b->size = 64;
+-		memcpy (b->data + 4, buf + 74 + n, 60);
++		memcpy (b->data + 4, fw->data + 74 + n, 60);
+ 		ret = dabusb_bulk (s, b);
+ 		if (ret < 0) {
+ 			err("dabusb_bulk failed.");
+@@ -412,6 +445,9 @@ static int dabusb_fpga_download (pdabusb_t s, const char *fname)
+ 	}
+ 
+ 	ret = dabusb_fpga_init (s, b);
++out_release:
++	release_firmware(fw);
++out_free:
+ 	kfree (b);
+ 
+ 	dbg("exit dabusb_fpga_download");
+-- 
+1.5.6.5
+

Attachment: signature.asc
Description: This is a digitally signed message part


Reply to: