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

[PATCH] Firmware removal



I'm going to post a series of patches that aim to fix the RC bugs
relating to sourceless firmware.

This is a patch against SVN which adds source for dsp56k's firmware and
modifies the other drivers to use request_firmware, and removes the
other firmware from the original tarball.

The driver patches are largely based on work by Jaswinder Singh and
David Woodhouse, though the r128 patch is my own work.  I have *not*
tested these beyond compiling the results, though I will test the
patched radeon driver shortly.

Ben.

Index: linux-2.6/debian/changelog
===================================================================
--- linux-2.6/debian/changelog	(revision 12311)
+++ linux-2.6/debian/changelog	(working copy)
@@ -1,4 +1,4 @@
-linux-2.6 (2.6.26-9) UNRELEASED; urgency=low
+linux-2.6 (2.6.26.dfsg.1-9) unstable; urgency=low
 
   [ Bastian Blank ]
   * Add stable release 2.6.26.6:
@@ -92,8 +92,18 @@
   * [arm/ixp4xx] Enable USB_ATM and USB_SPEEDTOUCH (closes: #502182).
   * [arm/iop32x, arm/orion5x] Likewise.
 
- -- Bastian Blank <waldi@debian.org>  Thu, 09 Oct 2008 15:14:50 +0200
+  [ Ben Hutchings ]
+  * Remove firmware from drivers and make them use request_firmware():
+    - cassini (closes: #498631)
+    - e100 (closes: #494308)
+    - r128 (closes: #494007)
+    - radeon (closes: #494009)
+    - starfire (closes: #501152)
+    - tehuti (closes: #501153)
+  * Add source for dsp56k firmware (closes: #494010)
 
+ -- Ben Hutchings <ben@decadent.org.uk>  Thu, 16 Oct 2008 00:55:32 +0100
+
 linux-2.6 (2.6.26-8) unstable; urgency=medium
 
   [ dann frazier ]
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 bde459e3ebb5f3f3c51bc56035ab8ef77e6201dc 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/files-1
===================================================================
--- linux-2.6/debian/patches/debian/dfsg/files-1	(revision 12311)
+++ linux-2.6/debian/patches/debian/dfsg/files-1	(working copy)
@@ -9,6 +9,10 @@
 rm drivers/atm/pca200e_ecd.data
 rm drivers/atm/sba200e_ecd.data
 
+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
@@ -27,11 +31,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
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 0a751d12c2cd6834d0dcf742fcc70dc94668d50c 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-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-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 ab2dc0c7e697f0009704f8f1b64bd01d629989ca 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-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 d02f7cbe1eccb8208afdd2b4489f03e973aca511 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-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 b211942d072cd3f88af4c4b17691f11f0b4fda0d 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/9
===================================================================
--- linux-2.6/debian/patches/series/9	(revision 12311)
+++ linux-2.6/debian/patches/series/9	(working copy)
@@ -4,3 +4,10 @@
 - bugfix/s390/prevent-ptrace-padding-area-read-write-in-31-bit-mode.patch
 + bugfix/all/stable/2.6.26.6.patch
 + bugfix/all/stable/2.6.26.6-abi-1.patch
+
++ features/all/drivers-char-drm-r128-request_firmware.patch
++ features/all/drivers-char-drm-radeon-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
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,24 @@
++ 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-radeon-disable.patch
++ debian/dfsg/drivers-char-dsp56k-fw-source.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-scsi-qlogicpti.patch
++ debian/dfsg/drivers-usb-misc-emi62-emi26.patch
++ debian/dfsg/drivers-usb-serial-keyspan-remove.patch
++ debian/dfsg/sound-pci.patch
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 a6486830ae178e50de0a51c8465a886b00559b9f 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-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,136 @@
+From 0f4f774503413fc363a5768068cd5786e31853d5 Mon Sep 17 00:00:00 2001
+From: Ben Hutchings <ben@decadent.org.uk>
+Date: Wed, 15 Oct 2008 01:19:57 +0100
+Subject: [PATCH] r128: Use request_firmware() to load CCE microcode
+
+Compile-tested only.
+---
+ drivers/char/drm/Kconfig    |    2 +-
+ drivers/char/drm/r128_cce.c |   55 ++++++++++++++++++++++++++++++++++++++----
+ 2 files changed, 50 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 04d8358..22515c5 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,7 +39,10 @@
+ 
+ #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)
+ {
+ 	drm_r128_private_t *dev_priv = dev->dev_private;
+@@ -178,20 +185,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
+@@ -352,6 +389,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");
+ 
+@@ -578,13 +616,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 a7ef166ed99982e5057092c7b6a2ee2274d1701a 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 e842718..2370f6f 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;
+@@ -1189,40 +1193,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
+ *
+@@ -1282,42 +1252,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 */
+@@ -1437,7 +1464,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-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 9ce5bd7f0c17353296cc8f761899018fa3268095 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 8a669c62fa50b0ade7a938998b6459eab262a682 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
+
+Compile-tested only.
+---
+ 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/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 4a9db1ecc7c6163f5c87507c545623e9074ffa8d 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 6e8650c..eb2e377 100644
+--- a/drivers/net/cassini.h
++++ b/drivers/net/cassini.h
+@@ -4391,6 +4391,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
+

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


Reply to: