Restructuring of ibm_ocp_enet driver

David Gibson david at gibson.dropbear.id.au
Wed Aug 21 14:36:27 EST 2002


The patch below make some first steps to restructuring the
ibm_ocp_enet driver to separate drivers for the EMAC and MAL
components.  This is necessary to sanely allocate the various IRQs.
It will also be necessary to sanely incorporate the driver into the
unified device model.

diff -urN /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_debug.c linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_debug.c
--- /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_debug.c	2002-08-09 07:27:41.000000000 +1000
+++ linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_debug.c	2002-08-21 13:21:08.000000000 +1000
@@ -109,47 +109,47 @@

 	printk(KERN_DEBUG " MAL DEBUG ********** \n");
 	printk(KERN_DEBUG " MCR      ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALCR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALCR));
 	printk(KERN_DEBUG " ESR      ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALESR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALESR));
 	printk(KERN_DEBUG " IER      ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALIER));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALIER));
 #ifdef CONFIG_40x
 	printk(KERN_DEBUG " DBR      ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALDBR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALDBR));
 #endif				/* CONFIG_40x */
 	printk(KERN_DEBUG " TXCASR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCASR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCASR));
 	printk(KERN_DEBUG " TXCARR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCARR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCARR));
 	printk(KERN_DEBUG " TXEOBISR ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXEOBISR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXEOBISR));
 	printk(KERN_DEBUG " TXDEIR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXDEIR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXDEIR));
 	printk(KERN_DEBUG " RXCASR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXCASR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXCASR));
 	printk(KERN_DEBUG " RXCARR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXCARR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXCARR));
 	printk(KERN_DEBUG " RXEOBISR ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXEOBISR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXEOBISR));
 	printk(KERN_DEBUG " RXDEIR   ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXDEIR));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXDEIR));
 	printk(KERN_DEBUG " TXCTP0R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCTP0R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCTP0R));
 	printk(KERN_DEBUG " TXCTP1R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCTP1R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCTP1R));
 	printk(KERN_DEBUG " TXCTP2R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCTP2R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCTP2R));
 	printk(KERN_DEBUG " TXCTP3R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALTXCTP3R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALTXCTP3R));
 	printk(KERN_DEBUG " RXCTP0R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXCTP0R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXCTP0R));
 	printk(KERN_DEBUG " RXCTP1R  ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRXCTP1R));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRXCTP1R));
 	printk(KERN_DEBUG " RCBS0    ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRCBS0));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRCBS0));
 	printk(KERN_DEBUG " RCBS1    ==> 0x%x\n",
-	       (unsigned int) get_mal_dcrn(fep, DCRN_MALRCBS1));
+	       (unsigned int) get_mal_dcrn(fep->mal, DCRN_MALRCBS1));
 }

 void
@@ -158,7 +158,7 @@
 	struct ocp_enet_private *fep = dev->priv;
 	unsigned long int mal_error, plb_error, plb_addr;

-	mal_error = get_mal_dcrn(fep, DCRN_MALESR);
+	mal_error = get_mal_dcrn(fep->mal, DCRN_MALESR);
 	printk(KERN_DEBUG "ppc405_eth_serr: %s channel %ld \n",
 	       (mal_error & 0x40000000) ? "Receive" :
 	       "Transmit", (mal_error & 0x3e000000) >> 25);
@@ -189,7 +189,7 @@
 ppc405_serr_dump_1(struct net_device *dev)
 {
 	struct ocp_enet_private *fep = dev->priv;
-	int mal_error = get_mal_dcrn(fep, DCRN_MALESR);
+	int mal_error = get_mal_dcrn(fep->mal, DCRN_MALESR);

 	printk(KERN_DEBUG "  -----  cumulative errors  -----\n");
 	if (mal_error & MALESR_DEI)
diff -urN /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_enet.c linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_enet.c
--- /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_enet.c	2002-08-09 07:27:41.000000000 +1000
+++ linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_enet.c	2002-08-21 14:13:43.000000000 +1000
@@ -198,7 +198,6 @@

 #include "ocp_zmii.h"
 #include "ibm_ocp_enet.h"
-#include "ibm_ocp_mal.h"

 /* Forward declarations of some structures to support different PHYs */

@@ -224,10 +223,6 @@

 static struct net_device *emac_dev[EMAC_NUMS];

-dma_addr_t rx_phys_addr = 0;
-dma_addr_t tx_phys_addr = 0;
-static mal_desc_t *rx_virt_addr = 0;
-static mal_desc_t *tx_virt_addr = 0;
 mii_list_t mii_cmds[NMII];

 int emac_max;
@@ -239,15 +234,67 @@
 		 "this can help if you are routing to a tunnel or a\n"
 		 "device that needs aligned data");

+
+static void disable_mal_chan(struct ocp_enet_private *fep)
+{
+	set_mal_dcrn(fep->mal, DCRN_MALRXCARR, fep->rxchan);
+	set_mal_dcrn(fep->mal, DCRN_MALTXCARR, fep->txchan);
+
+}
+
+static void enable_mal_chan(struct ocp_enet_private *fep)
+{
+	set_mal_dcrn(fep->mal, DCRN_MALRXCASR,
+		     get_mal_dcrn(fep->mal, DCRN_MALRXCASR) | fep->rxchan);
+	set_mal_dcrn(fep->mal, DCRN_MALTXCASR,
+		     get_mal_dcrn(fep->mal, DCRN_MALTXCASR) | fep->txchan);
+	set_mal_dcrn(fep->mal, DCRN_MALIER, MALIER_DE |
+		     MALIER_NE | MALIER_TE | MALIER_OPBE | MALIER_PLBE);
+
+
+}
+
+static void set_mal_chan_addr(struct ocp_enet_private *fep)
+{
+	unsigned long txaddr, rxaddr;
+
+	txaddr = fep->mal->tx_phys_addr + (fep->emac_num * PAGE_SIZE);
+	rxaddr = fep->mal->rx_phys_addr + (fep->emac_num * PAGE_SIZE);
+
+#if EMAFC_NUMS > 2
+	/* setup MAL tx and rx channel pointers */
+	if (fep->emac_num == 3) {
+		set_mal_dcrn(fep->mal, DCRN_MALTXCTP6R, txaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRXCTP3R, rxaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRCBS3, DESC_BUF_SIZE_REG);
+
+	} else if (fep->emac_num == 2) {
+		set_mal_dcrn(fep->mal, DCRN_MALTXCTP4R, txaddr);
+		set_mal_dcrn(fep, DCRN_MALRXCTP2R, rxaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRCBS2, DESC_BUF_SIZE_REG);
+
+	} else
+#endif	/* EMAC_NUMS > 2 */
+	if (fep->emac_num == 1) {
+		set_mal_dcrn(fep->mal, DCRN_MALTXCTP2R, txaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRXCTP1R, rxaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRCBS1, DESC_BUF_SIZE_REG);
+	} else if (fep->emac_num == 0) {
+		set_mal_dcrn(fep->mal, DCRN_MALTXCTP0R, txaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRXCTP0R, rxaddr);
+		set_mal_dcrn(fep->mal, DCRN_MALRCBS0, DESC_BUF_SIZE_REG);
+	}
+}
+
 static void
 init_rings(struct net_device *dev)
 {
 	struct ocp_enet_private *ep = dev->priv;
 	int loop;

-	ep->tx_desc = (mal_desc_t *) ((char *) tx_virt_addr +
+	ep->tx_desc = (struct mal_descriptor *) ((char *) ep->mal->tx_virt_addr +
 				      (ep->emac_num * PAGE_SIZE));
-	ep->rx_desc = (mal_desc_t *) ((char *) rx_virt_addr +
+	ep->rx_desc = (struct mal_descriptor *) ((char *) ep->mal->rx_virt_addr +
 				      (ep->emac_num * PAGE_SIZE));

 	/* Fill in the transmit descriptor ring. */
@@ -356,7 +403,7 @@

 	request_irq(ocp_get_irq(EMAC,fep->emac_num), ppc405_eth_mac, 0, "OCP EMAC MAC", dev);

-	if (!(get_mal_dcrn(fep, DCRN_MALTXCASR))) {
+	if (!(get_mal_dcrn(fep->mal, DCRN_MALTXCASR))) {
  		request_irq(BL_MAC_WOL,ppc405_eth_wakeup,0,"OCP EMAC Wakeup",dev);
 		request_irq(BL_MAL_SERR,ppc405_eth_serr,0,"OCP EMAC MAL SERR",dev);
 		request_irq(BL_MAL_TXDE,ppc405_eth_txde,0,"OCP EMAC TX DE ",dev);
@@ -448,7 +495,7 @@
 	/* Free the irq's */
 	free_irq(ocp_get_irq(EMAC,fep->emac_num), dev);

-	if (!(get_mal_dcrn(fep, DCRN_MALTXCASR))) {
+	if (!(get_mal_dcrn(fep->mal, DCRN_MALTXCASR))) {
  		free_irq(BL_MAC_WOL,dev);
 		free_irq(BL_MAL_SERR,dev);
 		free_irq(BL_MAL_TXDE,dev);
@@ -543,6 +590,8 @@
 	struct ocp_enet_private *ep;
 	struct ocp_dev *emac_driver;

+	printk(KERN_DEBUG "ocp_enet_probe(%d)\n", curr_emac);
+
 	dev = init_etherdev(NULL, sizeof (struct ocp_enet_private));
 	if (dev == NULL) {
 		printk(KERN_ERR
@@ -551,9 +600,11 @@
 	}
 	ep = dev->priv;
 	ep->emac_num = curr_emac;
-	ep->mal = DCRN_MAL_BASE;
+	ep->mal = &mal_table[0];
 	ep->sequence_done = 0;

+	printk(KERN_DEBUG "ep->mal = %p\n", ep->mal);
+
 	emac_driver = &ep->ocpdev;
 	emac_driver->type = EMAC;
 	ocp_register(emac_driver);
@@ -595,7 +646,7 @@
 		       dev->name);
 		return -1;
 	}
-	config_mal(ep);
+	config_mal(ep->mal);

 	return (ret);

@@ -607,21 +658,10 @@

 	emac_max = ocp_get_max(EMAC);

-	/* Allocate memory for the transmit descriptors and save its physical
-	 * address.  EMACs share the upper 13 bits of address lines, so
-	 * allocate one buffer big enough for everybody.
-	 * FIXME: How to ensure aligned on 32768-byte boundary?
-	 */
-
-	tx_virt_addr = (mal_desc_t *)
-	    consistent_alloc(GFP_KERNEL, PAGE_SIZE * emac_max, &tx_phys_addr);
-
-	rx_virt_addr = (mal_desc_t *)
-	    consistent_alloc(GFP_KERNEL, PAGE_SIZE * emac_max, &rx_phys_addr);
+	printk(KERN_DEBUG "init_ppc405_enet\n");
 	for (curr_emac = 0; curr_emac < emac_max; curr_emac++) {
 		ocp_enet_probe(curr_emac);
 	}
-
 	for (i = 0; i < NMII - 1; i++)
 		mii_cmds[i].mii_next = &mii_cmds[i + 1];
 	mii_free = mii_cmds;
@@ -827,7 +867,7 @@
 	 * it against the first EMAC registered for the MAL.
 	 */

-	mal_error = get_mal_dcrn(fep, DCRN_MALESR);
+	mal_error = get_mal_dcrn(fep->mal, DCRN_MALESR);

 	if (mal_error & MALESR_EVB) {

@@ -848,7 +888,7 @@

 	ppc405_serr_dump_1(dev);
 	/* Clear the error status register */
-	set_mal_dcrn(fep, DCRN_MALESR, mal_error);
+	set_mal_dcrn(fep->mal, DCRN_MALESR, mal_error);
 }

 static void
@@ -886,10 +926,10 @@
 	struct ocp_enet_private *fep = dev->priv;

 	for (count = 0; count < 2; ++count) {
-		isr = get_mal_dcrn(fep, DCRN_MALTXEOBISR);
+		isr = get_mal_dcrn(fep->mal, DCRN_MALTXEOBISR);
 		if (isr == 0)
 			break;
-		set_mal_dcrn(fep, DCRN_MALTXEOBISR, isr);
+		set_mal_dcrn(fep->mal, DCRN_MALTXEOBISR, isr);

 		for (i = 0; i < emac_max; i++) {
 			if (isr & 0x80000000 >> i*2) {
@@ -1031,8 +1071,8 @@

 	disable_irq(BL_MAL_RXDE);

-	isr = get_mal_dcrn(fep, DCRN_MALRXEOBISR);
-	set_mal_dcrn(fep, DCRN_MALRXEOBISR, isr);
+	isr = get_mal_dcrn(fep->mal, DCRN_MALRXEOBISR);
+	set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, isr);

 	/* This determines which emac is sending the interrupt */
 	for (i = 0; i < emac_max; i++) {
@@ -1064,7 +1104,7 @@
 	ppc405_eth_mal_dump(dev);

 	/* Reenable the transmit channel */
-	set_mal_dcrn(fep, DCRN_MALTXCASR, get_mal_dcrn(fep, DCRN_MALTXCASR));
+	set_mal_dcrn(fep->mal, DCRN_MALTXCASR, get_mal_dcrn(fep->mal, DCRN_MALTXCASR));
 	return;
 }

@@ -1087,7 +1127,7 @@
 	/*
 	 * This really is needed.  This case encountered in stress testing.
 	 */
-	if (get_mal_dcrn(fep, DCRN_MALRXDEIR) == 0)
+	if (get_mal_dcrn(fep->mal, DCRN_MALRXDEIR) == 0)
 		return;

 	//printk(KERN_WARNING "%s: receive descriptor error\n", dev->name);
@@ -1108,7 +1148,7 @@

 	disable_irq(BL_MAL_RXEOB);
 	for (i = 0; i < emac_max; i++) {
-		isr = get_mal_dcrn(fep, DCRN_MALRXEOBISR);
+		isr = get_mal_dcrn(fep->mal, DCRN_MALRXEOBISR);
 		if (isr & 0x80000000 >> i) {
 			dev = emac_dev[i];
 			fep = dev->priv;
@@ -1125,17 +1165,17 @@
 			fep->rx_slot = 0;
 			ppc405_rx_fill(dev, 0);

-			set_mal_dcrn(fep, DCRN_MALRXEOBISR, 0x80000000 >> i);
+			set_mal_dcrn(fep->mal, DCRN_MALRXEOBISR, 0x80000000 >> i);
 		}
 	}

 	/* Clear the interrupt */
-	set_mal_dcrn(fep, DCRN_MALRXDEIR, get_mal_dcrn(fep, DCRN_MALRXDEIR));
+	set_mal_dcrn(fep->mal, DCRN_MALRXDEIR, get_mal_dcrn(fep->mal, DCRN_MALRXDEIR));

 	enable_irq(BL_MAL_RXEOB);

 	/* Reenable the receive channels */
-	set_mal_dcrn(fep, DCRN_MALRXCASR, get_mal_dcrn(fep, DCRN_MALRXCASR));
+	set_mal_dcrn(fep->mal, DCRN_MALRXCASR, get_mal_dcrn(fep->mal, DCRN_MALRXCASR));
 }

 static void
@@ -1153,7 +1193,7 @@
 		fep->stats.tx_errors++;

 		/* Reenable the transmit channel */
-		set_mal_dcrn(fep, DCRN_MALTXCASR, fep->txchan);
+		set_mal_dcrn(fep->mal, DCRN_MALTXCASR, fep->txchan);

 	} else {
 		fep->stats.rx_errors++;
@@ -1193,12 +1233,6 @@
 static void __exit
 exit_ppc405_enet(void)
 {
-	/*
-	 * Unmap the non cached memory space.
-	 */
-	consistent_free((void *) tx_virt_addr);
-	consistent_free((void *) rx_virt_addr);
-
 }

 module_init(init_ppc405_enet);
diff -urN /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_enet.h linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_enet.h
--- /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_enet.h	2002-08-09 07:27:41.000000000 +1000
+++ linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_enet.h	2002-08-21 13:12:03.000000000 +1000
@@ -57,6 +57,7 @@
 #include <asm/mmu.h>		/* For phys_addr_t */
 #include "ibm_ocp_emac.h"
 #include "ibm_ocp_phy.h"
+#include "ibm_ocp_mal.h"

 #ifndef CONFIG_IBM_OCP_ENET_TX_BUFF
 #define NUM_TX_BUFF		6
@@ -119,24 +120,15 @@
 						~EMAC_STACR_CLK_100MHZ) | \
 						((VAL & 0xffff) << 16))

-/* MAL Buffer Descriptor structure */
-typedef struct {
-	volatile unsigned short ctrl;	/* MAL / Commac status control bits */
-	volatile short data_len;	/* Max length is 4K-1 (12 bits)     */
-	unsigned char *data_ptr;	/* pointer to actual data buffer    */
-} mal_desc_t;
-
-
-
 struct ocp_enet_private {
 	uint emac_num;
 	uint txchan;
 	uint rxchan;
 	struct sk_buff *tx_skb[NUM_TX_BUFF];
 	struct sk_buff *rx_skb[NUM_RX_BUFF];
-	mal_desc_t *tx_desc;
-	mal_desc_t *rx_desc;
-	mal_desc_t *rx_dirty;
+	struct mal_descriptor *tx_desc;
+	struct mal_descriptor *rx_desc;
+	struct mal_descriptor *rx_dirty;
 	struct net_device_stats stats;
 	int tx_cnt;
 	int rx_slot;
@@ -157,7 +149,7 @@
 	int full_duplex;
 	zmii_t *zmii_base;
 	int zmii_mode;
-	int mal;
+	struct ibm_ocp_mal *mal;
 	volatile emac_t *emacp;
 	struct ocp_dev ocpdev;
 };
diff -urN /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_mal.c linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_mal.c
--- /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_mal.c	2002-08-09 07:27:41.000000000 +1000
+++ linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_mal.c	2002-08-21 14:10:47.000000000 +1000
@@ -42,84 +42,115 @@
 #include <linux/ptrace.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
+#include <linux/init.h>

 #include <asm/io.h>

-#include "ibm_ocp_enet.h"
-#include "ibm_ocp_mal.h"
+#include <asm/ocp.h>

-extern dma_addr_t rx_phys_addr;
-extern dma_addr_t tx_phys_addr;
+#include "ibm_ocp_mal.h"

 void
-config_mal(struct ocp_enet_private *fep)
+config_mal(struct ibm_ocp_mal *mal)
 {
+	printk(KERN_DEBUG "config_mal(%p):  dcrbase = %x\n",
+	       mal, mal->dcrbase);
+	set_mal_dcrn(mal, DCRN_MALRXCARR, 0xFFFFFFFF);
+	set_mal_dcrn(mal, DCRN_MALTXCARR, 0xFFFFFFFF);

-	set_mal_dcrn(fep, DCRN_MALRXCARR, 0xFFFFFFFF);
-	set_mal_dcrn(fep, DCRN_MALTXCARR, 0xFFFFFFFF);
-
-	set_mal_dcrn(fep, DCRN_MALCR, MALCR_MMSR);	/* 384 */
+	set_mal_dcrn(mal, DCRN_MALCR, MALCR_MMSR);	/* 384 */
 	/* FIXME: Add delay */

 	/* Set the MAL configuration register */
-	set_mal_dcrn(fep, DCRN_MALCR,
+	set_mal_dcrn(mal, DCRN_MALCR,
 		     MALCR_PLBB | MALCR_OPBBL | MALCR_LEA |
 		     MALCR_PLBLT_DEFAULT);

 }

-void
-disable_mal_chan(struct ocp_enet_private *fep)
+struct ibm_ocp_mal mal_table[NUM_MALS]; /* = 0 */
+
+static int __init init_mal(int n)
 {
-	set_mal_dcrn(fep, DCRN_MALRXCARR, fep->rxchan);
-	set_mal_dcrn(fep, DCRN_MALTXCARR, fep->txchan);
+	struct ibm_ocp_mal *mal;
+	int emac_max;
+
+	mal = &mal_table[n];
+
+
+	switch (n) {
+	case 0:
+		mal->dcrbase = DCRN_MAL_BASE;
+		break;
+#ifdef DCRN_MAL1_BASE
+	case 1:
+		mal->dcrbase = DCRN_MAL1_BASE;
+		break;
+#endif
+	default:
+		BUG();
+	}
+
+	printk(KERN_DEBUG "init_mal(%d):  mal=%p,  dcrbase=%x\n",
+	       n, mal, mal->dcrbase);
+
+	emac_max = ocp_get_max(EMAC);
+
+	/* Allocate memory for the transmit descriptors and save its physical
+	 * address.  EMACs share the upper 13 bits of address lines, so
+	 * allocate one buffer big enough for everybody.
+	 * FIXME: How to ensure aligned on 32768-byte boundary?
+	 */
+
+	mal->tx_virt_addr = (struct mal_descriptor *)
+	    consistent_alloc(GFP_KERNEL, PAGE_SIZE * emac_max, &mal->tx_phys_addr);
+
+	printk(KERN_DEBUG "Tx ring allocated:  tx_virt_addr = %p tx_phys_addr = %lx\n",
+	       mal->tx_virt_addr, mal->tx_phys_addr);
+
+	mal->rx_virt_addr = (struct mal_descriptor *)
+	    consistent_alloc(GFP_KERNEL, PAGE_SIZE * emac_max, &mal->rx_phys_addr);
+
+	printk(KERN_DEBUG "Rx ring allocated:  rx_virt_addr = %p rx_phys_addr = %lx\n",
+	       mal->rx_virt_addr, mal->rx_phys_addr);

+	return 0;
 }

-void
-enable_mal_chan(struct ocp_enet_private *fep)
+static void __exit exit_mal(struct ibm_ocp_mal *mal)
 {
-	set_mal_dcrn(fep, DCRN_MALRXCASR,
-		     get_mal_dcrn(fep, DCRN_MALRXCASR) | fep->rxchan);
-	set_mal_dcrn(fep, DCRN_MALTXCASR,
-		     get_mal_dcrn(fep, DCRN_MALTXCASR) | fep->txchan);
-	set_mal_dcrn(fep, DCRN_MALIER, MALIER_DE |
-		     MALIER_NE | MALIER_TE | MALIER_OPBE | MALIER_PLBE);
-
+	/*
+	 * Unmap the non cached memory space.
+	 */
+	consistent_free(mal->tx_virt_addr);
+	consistent_free(mal->rx_virt_addr);

+	memset(mal, 0, sizeof(*mal));
 }

-void
-set_mal_chan_addr(struct ocp_enet_private *fep)
+static int __init init_mals(void)
 {
-#ifdef CONFIG_NP405H
-	/* setup MAL tx and rx channel pointers */
-	if (fep->emac_num == 3) {
-		set_mal_dcrn(fep, DCRN_MALTXCTP6R,
-			     tx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRXCTP3R,
-			     rx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRCBS3, DESC_BUF_SIZE_REG);
-
-	} else if (fep->emac_num == 2) {
-		set_mal_dcrn(fep, DCRN_MALTXCTP4R,
-			     tx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRXCTP2R,
-			     rx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRCBS2, DESC_BUF_SIZE_REG);
-
-	} else
-#endif				/* CONFIG_440 */
-	if (fep->emac_num == 1) {
-		set_mal_dcrn(fep, DCRN_MALTXCTP2R,
-			     tx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRXCTP1R,
-			     rx_phys_addr + (fep->emac_num * PAGE_SIZE));
-		set_mal_dcrn(fep, DCRN_MALRCBS1, DESC_BUF_SIZE_REG);
-
-	} else if (fep->emac_num == 0) {
-		set_mal_dcrn(fep, DCRN_MALTXCTP0R, tx_phys_addr);
-		set_mal_dcrn(fep, DCRN_MALRXCTP0R, rx_phys_addr);
-		set_mal_dcrn(fep, DCRN_MALRCBS0, DESC_BUF_SIZE_REG);
+	int i;
+	int err;
+
+	printk(KERN_DEBUG "init_mals()\n");
+
+	for (i = 0; i < NUM_MALS; i++) {
+		err = init_mal(i);
+		if (err)
+			return err; /* FIXME: cleanup initalized MALs */
 	}
+
+	return 0;
 }
+
+static void __exit exit_mals(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_MALS; i++)
+		exit_mal(&mal_table[i]);
+}
+
+module_init(init_mals);
+module_exit(exit_mals);
diff -urN /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_mal.h linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_mal.h
--- /home/dgibson/kernel/linuxppc-2.5/drivers/net/ibm_ocp/ibm_ocp_mal.h	2002-08-09 07:27:41.000000000 +1000
+++ linux-bluefish/drivers/net/ibm_ocp/ibm_ocp_mal.h	2002-08-21 13:17:51.000000000 +1000
@@ -6,6 +6,29 @@
 #ifndef _IBM_OCP_MAL_H
 #define _IBM_OCP_MAL_H

+/* MAL Buffer Descriptor structure */
+struct mal_descriptor {
+	volatile unsigned short ctrl;	/* MAL / Commac status control bits */
+	volatile short data_len;	/* Max length is 4K-1 (12 bits)     */
+	unsigned char *data_ptr;	/* pointer to actual data buffer    */
+} __attribute__((packed));
+
+struct ibm_ocp_mal {
+	int dcrbase;
+	dma_addr_t rx_phys_addr;
+	dma_addr_t tx_phys_addr;
+	struct mal_descriptor *rx_virt_addr;
+	struct mal_descriptor *tx_virt_addr;
+};
+
+#ifdef DCRN_MAL1_BASE
+#define NUM_MALS	2
+#else
+#define	NUM_MALS	1
+#endif
+
+extern struct ibm_ocp_mal mal_table[NUM_MALS];
+
 #define GET_MAL_STANZA(base,dcrn) \
 	case base: \
 		x = mfdcr(dcrn(base)); \
@@ -28,9 +51,9 @@
 #endif


-#define get_mal_dcrn(fep, dcrn) ({ \
+#define get_mal_dcrn(mal, dcrn) ({ \
 	u32 x; \
-	switch ((fep)->mal) { \
+	switch ((mal)->dcrbase) { \
 		GET_MAL0_STANZA(dcrn) \
 		GET_MAL1_STANZA(dcrn) \
 	default: \
@@ -38,8 +61,8 @@
 	} \
 x; })

-#define set_mal_dcrn(fep, dcrn, val) do { \
-	switch ((fep)->mal) { \
+#define set_mal_dcrn(mal, dcrn, val) do { \
+	switch ((mal)->dcrbase) { \
 		SET_MAL0_STANZA(dcrn,val) \
 		SET_MAL1_STANZA(dcrn,val) \
 	default: \
@@ -47,11 +70,7 @@
 	} } while (0)


-extern void config_mal(struct ocp_enet_private *fep);
-extern void disable_mal_chan(struct ocp_enet_private *fep);
-extern void enable_mal_chan(struct ocp_enet_private *fep);
-extern void set_mal_chan_addr(struct ocp_enet_private *fep);
-
+extern void config_mal(struct ibm_ocp_mal *mal);

 /* the following defines are for the MadMAL status and control registers. */
 /* MADMAL transmit and receive status/control bits  */


--
David Gibson			| For every complex problem there is a
david at gibson.dropbear.id.au	| solution which is simple, neat and
				| wrong.
http://www.ozlabs.org/people/dgibson

** Sent via the linuxppc-embedded mail list. See http://lists.linuxppc.org/





More information about the Linuxppc-embedded mailing list