Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,65 @@
#
# Apple device configuration
#
config NET_VENDOR_APPLE
bool "Apple devices"
default y
depends on (PPC_PMAC && PPC32) || MAC
---help---
If you have a network (Ethernet) card belonging to this class, say Y
and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
Note that the answer to this question doesn't directly affect the
kernel: saying N will just cause the configurator to skip all
the questions about IBM devices. If you say Y, you will be asked for
your specific card in the following questions.
if NET_VENDOR_APPLE
config MACE
tristate "MACE (Power Mac ethernet) support"
depends on PPC_PMAC && PPC32
select CRC32
---help---
Power Macintoshes and clones with Ethernet built-in on the
motherboard will usually use a MACE (Medium Access Control for
Ethernet) interface. Say Y to include support for the MACE chip.
To compile this driver as a module, choose M here: the module
will be called mace.
config MACE_AAUI_PORT
bool "Use AAUI port instead of TP by default"
depends on MACE
---help---
Some Apple machines (notably the Apple Network Server) which use the
MACE ethernet chip have an Apple AUI port (small 15-pin connector),
instead of an 8-pin RJ45 connector for twisted-pair ethernet. Say
Y here if you have such a machine. If unsure, say N.
The driver will default to AAUI on ANS anyway, and if you use it as
a module, you can provide the port_aaui=0|1 to force the driver.
config BMAC
tristate "BMAC (G3 ethernet) support"
depends on PPC_PMAC && PPC32
select CRC32
---help---
Say Y for support of BMAC Ethernet interfaces. These are used on G3
computers.
To compile this driver as a module, choose M here: the module
will be called bmac.
config MACMACE
bool "Macintosh (AV) onboard MACE ethernet"
depends on MAC
select CRC32
---help---
Support for the onboard AMD 79C940 MACE Ethernet controller used in
the 660AV and 840AV Macintosh. If you have one of these Macintoshes
say Y and read the Ethernet-HOWTO, available from
<http://www.tldp.org/docs.html#howto>.
endif # NET_VENDOR_APPLE

View file

@ -0,0 +1,7 @@
#
# Makefile for the Apple network device drivers.
#
obj-$(CONFIG_MACE) += mace.o
obj-$(CONFIG_BMAC) += bmac.o
obj-$(CONFIG_MACMACE) += macmace.o

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,164 @@
/*
* mace.h - definitions for the registers in the "Big Mac"
* Ethernet controller found in PowerMac G3 models.
*
* Copyright (C) 1998 Randy Gobbel.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
/* The "Big MAC" appears to have some parts in common with the Sun "Happy Meal"
* (HME) controller. See sunhme.h
*/
/* register offsets */
/* global status and control */
#define XIFC 0x000 /* low-level interface control */
# define TxOutputEnable 0x0001 /* output driver enable */
# define XIFLoopback 0x0002 /* Loopback-mode XIF enable */
# define MIILoopback 0x0004 /* Loopback-mode MII enable */
# define MIILoopbackBits 0x0006
# define MIIBuffDisable 0x0008 /* MII receive buffer disable */
# define SQETestEnable 0x0010 /* SQE test enable */
# define SQETimeWindow 0x03e0 /* SQE time window */
# define XIFLanceMode 0x0010 /* Lance mode enable */
# define XIFLanceIPG0 0x03e0 /* Lance mode IPG0 */
#define TXFIFOCSR 0x100 /* transmit FIFO control */
# define TxFIFOEnable 0x0001
#define TXTH 0x110 /* transmit threshold */
# define TxThreshold 0x0004
#define RXFIFOCSR 0x120 /* receive FIFO control */
# define RxFIFOEnable 0x0001
#define MEMADD 0x130 /* memory address, unknown function */
#define MEMDATAHI 0x140 /* memory data high, presently unused in driver */
#define MEMDATALO 0x150 /* memory data low, presently unused in driver */
#define XCVRIF 0x160 /* transceiver interface control */
# define COLActiveLow 0x0002
# define SerialMode 0x0004
# define ClkBit 0x0008
# define LinkStatus 0x0100
#define CHIPID 0x170 /* chip ID */
#define MIFCSR 0x180 /* ??? */
#define SROMCSR 0x190 /* SROM control */
# define ChipSelect 0x0001
# define Clk 0x0002
#define TXPNTR 0x1a0 /* transmit pointer */
#define RXPNTR 0x1b0 /* receive pointer */
#define STATUS 0x200 /* status--reading this clears it */
#define INTDISABLE 0x210 /* interrupt enable/disable control */
/* bits below are the same in both STATUS and INTDISABLE registers */
# define FrameReceived 0x00000001 /* Received a frame */
# define RxFrameCntExp 0x00000002 /* Receive frame counter expired */
# define RxAlignCntExp 0x00000004 /* Align-error counter expired */
# define RxCRCCntExp 0x00000008 /* CRC-error counter expired */
# define RxLenCntExp 0x00000010 /* Length-error counter expired */
# define RxOverFlow 0x00000020 /* Receive FIFO overflow */
# define RxCodeViolation 0x00000040 /* Code-violation counter expired */
# define SQETestError 0x00000080 /* Test error in XIF for SQE */
# define FrameSent 0x00000100 /* Transmitted a frame */
# define TxUnderrun 0x00000200 /* Transmit FIFO underrun */
# define TxMaxSizeError 0x00000400 /* Max-packet size error */
# define TxNormalCollExp 0x00000800 /* Normal-collision counter expired */
# define TxExcessCollExp 0x00001000 /* Excess-collision counter expired */
# define TxLateCollExp 0x00002000 /* Late-collision counter expired */
# define TxNetworkCollExp 0x00004000 /* First-collision counter expired */
# define TxDeferTimerExp 0x00008000 /* Defer-timer expired */
# define RxFIFOToHost 0x00010000 /* Data moved from FIFO to host */
# define RxNoDescriptors 0x00020000 /* No more receive descriptors */
# define RxDMAError 0x00040000 /* Error during receive DMA */
# define RxDMALateErr 0x00080000 /* Receive DMA, data late */
# define RxParityErr 0x00100000 /* Parity error during receive DMA */
# define RxTagError 0x00200000 /* Tag error during receive DMA */
# define TxEOPError 0x00400000 /* Tx descriptor did not have EOP set */
# define MIFIntrEvent 0x00800000 /* MIF is signaling an interrupt */
# define TxHostToFIFO 0x01000000 /* Data moved from host to FIFO */
# define TxFIFOAllSent 0x02000000 /* Transmitted all packets in FIFO */
# define TxDMAError 0x04000000 /* Error during transmit DMA */
# define TxDMALateError 0x08000000 /* Late error during transmit DMA */
# define TxParityError 0x10000000 /* Parity error during transmit DMA */
# define TxTagError 0x20000000 /* Tag error during transmit DMA */
# define PIOError 0x40000000 /* PIO access got an error */
# define PIOParityError 0x80000000 /* PIO access got a parity error */
# define DisableAll 0xffffffff
# define EnableAll 0x00000000
/* # define NormalIntEvents ~(FrameReceived | FrameSent | TxUnderrun) */
# define EnableNormal ~(FrameReceived | FrameSent)
# define EnableErrors (FrameReceived | FrameSent)
# define RxErrorMask (RxFrameCntExp | RxAlignCntExp | RxCRCCntExp | \
RxLenCntExp | RxOverFlow | RxCodeViolation)
# define TxErrorMask (TxUnderrun | TxMaxSizeError | TxExcessCollExp | \
TxLateCollExp | TxNetworkCollExp | TxDeferTimerExp)
/* transmit control */
#define TXRST 0x420 /* transmit reset */
# define TxResetBit 0x0001
#define TXCFG 0x430 /* transmit configuration control*/
# define TxMACEnable 0x0001 /* output driver enable */
# define TxSlowMode 0x0020 /* enable slow mode */
# define TxIgnoreColl 0x0040 /* ignore transmit collisions */
# define TxNoFCS 0x0080 /* do not emit FCS */
# define TxNoBackoff 0x0100 /* no backoff in case of collisions */
# define TxFullDuplex 0x0200 /* enable full-duplex */
# define TxNeverGiveUp 0x0400 /* don't give up on transmits */
#define IPG1 0x440 /* Inter-packet gap 1 */
#define IPG2 0x450 /* Inter-packet gap 2 */
#define ALIMIT 0x460 /* Transmit attempt limit */
#define SLOT 0x470 /* Transmit slot time */
#define PALEN 0x480 /* Size of transmit preamble */
#define PAPAT 0x490 /* Pattern for transmit preamble */
#define TXSFD 0x4a0 /* Transmit frame delimiter */
#define JAM 0x4b0 /* Jam size */
#define TXMAX 0x4c0 /* Transmit max pkt size */
#define TXMIN 0x4d0 /* Transmit min pkt size */
#define PAREG 0x4e0 /* Count of transmit peak attempts */
#define DCNT 0x4f0 /* Transmit defer timer */
#define NCCNT 0x500 /* Transmit normal-collision counter */
#define NTCNT 0x510 /* Transmit first-collision counter */
#define EXCNT 0x520 /* Transmit excess-collision counter */
#define LTCNT 0x530 /* Transmit late-collision counter */
#define RSEED 0x540 /* Transmit random number seed */
#define TXSM 0x550 /* Transmit state machine */
/* receive control */
#define RXRST 0x620 /* receive reset */
# define RxResetValue 0x0000
#define RXCFG 0x630 /* receive configuration control */
# define RxMACEnable 0x0001 /* receiver overall enable */
# define RxCFGReserved 0x0004
# define RxPadStripEnab 0x0020 /* enable pad byte stripping */
# define RxPromiscEnable 0x0040 /* turn on promiscuous mode */
# define RxNoErrCheck 0x0080 /* disable receive error checking */
# define RxCRCNoStrip 0x0100 /* disable auto-CRC-stripping */
# define RxRejectOwnPackets 0x0200 /* don't receive our own packets */
# define RxGrpPromisck 0x0400 /* enable group promiscuous mode */
# define RxHashFilterEnable 0x0800 /* enable hash filter */
# define RxAddrFilterEnable 0x1000 /* enable address filter */
#define RXMAX 0x640 /* Max receive packet size */
#define RXMIN 0x650 /* Min receive packet size */
#define MADD2 0x660 /* our enet address, high part */
#define MADD1 0x670 /* our enet address, middle part */
#define MADD0 0x680 /* our enet address, low part */
#define FRCNT 0x690 /* receive frame counter */
#define LECNT 0x6a0 /* Receive excess length error counter */
#define AECNT 0x6b0 /* Receive misaligned error counter */
#define FECNT 0x6c0 /* Receive CRC error counter */
#define RXSM 0x6d0 /* Receive state machine */
#define RXCV 0x6e0 /* Receive code violation */
#define BHASH3 0x700 /* multicast hash register */
#define BHASH2 0x710 /* multicast hash register */
#define BHASH1 0x720 /* multicast hash register */
#define BHASH0 0x730 /* multicast hash register */
#define AFR2 0x740 /* address filtering setup? */
#define AFR1 0x750 /* address filtering setup? */
#define AFR0 0x760 /* address filtering setup? */
#define AFCR 0x770 /* address filter compare register? */
# define EnableAllCompares 0x0fff
/* bits in XIFC */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,173 @@
/*
* mace.h - definitions for the registers in the Am79C940 MACE
* (Medium Access Control for Ethernet) controller.
*
* Copyright (C) 1996 Paul Mackerras.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*/
#define REG(x) volatile unsigned char x; char x ## _pad[15]
struct mace {
REG(rcvfifo); /* receive FIFO */
REG(xmtfifo); /* transmit FIFO */
REG(xmtfc); /* transmit frame control */
REG(xmtfs); /* transmit frame status */
REG(xmtrc); /* transmit retry count */
REG(rcvfc); /* receive frame control */
REG(rcvfs); /* receive frame status (4 bytes) */
REG(fifofc); /* FIFO frame count */
REG(ir); /* interrupt register */
REG(imr); /* interrupt mask register */
REG(pr); /* poll register */
REG(biucc); /* bus interface unit config control */
REG(fifocc); /* FIFO configuration control */
REG(maccc); /* medium access control config control */
REG(plscc); /* phys layer signalling config control */
REG(phycc); /* physical configuration control */
REG(chipid_lo); /* chip ID, lsb */
REG(chipid_hi); /* chip ID, msb */
REG(iac); /* internal address config */
REG(reg19);
REG(ladrf); /* logical address filter (8 bytes) */
REG(padr); /* physical address (6 bytes) */
REG(reg22);
REG(reg23);
REG(mpc); /* missed packet count (clears when read) */
REG(reg25);
REG(rntpc); /* runt packet count (clears when read) */
REG(rcvcc); /* recv collision count (clears when read) */
REG(reg28);
REG(utr); /* user test reg */
REG(reg30);
REG(reg31);
};
/* Bits in XMTFC */
#define DRTRY 0x80 /* don't retry transmission after collision */
#define DXMTFCS 0x08 /* don't append FCS to transmitted frame */
#define AUTO_PAD_XMIT 0x01 /* auto-pad short packets on transmission */
/* Bits in XMTFS: only valid when XMTSV is set in PR and XMTFS */
#define XMTSV 0x80 /* transmit status (i.e. XMTFS) valid */
#define UFLO 0x40 /* underflow - xmit fifo ran dry */
#define LCOL 0x20 /* late collision (transmission aborted) */
#define MORE 0x10 /* 2 or more retries needed to xmit frame */
#define ONE 0x08 /* 1 retry needed to xmit frame */
#define DEFER 0x04 /* MACE had to defer xmission (enet busy) */
#define LCAR 0x02 /* loss of carrier (transmission aborted) */
#define RTRY 0x01 /* too many retries (transmission aborted) */
/* Bits in XMTRC: only valid when XMTSV is set in PR (and XMTFS) */
#define EXDEF 0x80 /* had to defer for excessive time */
#define RETRY_MASK 0x0f /* number of retries (0 - 15) */
/* Bits in RCVFC */
#define LLRCV 0x08 /* low latency receive: early DMA request */
#define M_RBAR 0x04 /* sets function of EAM/R pin */
#define AUTO_STRIP_RCV 0x01 /* auto-strip short LLC frames on recv */
/*
* Bits in RCVFS. After a frame is received, four bytes of status
* are automatically read from this register and appended to the frame
* data in memory. These are:
* Byte 0 and 1: message byte count and frame status
* Byte 2: runt packet count
* Byte 3: receive collision count
*/
#define RS_OFLO 0x8000 /* receive FIFO overflowed */
#define RS_CLSN 0x4000 /* received frame suffered (late) collision */
#define RS_FRAMERR 0x2000 /* framing error flag */
#define RS_FCSERR 0x1000 /* frame had FCS error */
#define RS_COUNT 0x0fff /* mask for byte count field */
/* Bits (fields) in FIFOFC */
#define RCVFC_SH 4 /* receive frame count in FIFO */
#define RCVFC_MASK 0x0f
#define XMTFC_SH 0 /* transmit frame count in FIFO */
#define XMTFC_MASK 0x0f
/*
* Bits in IR and IMR. The IR clears itself when read.
* Setting a bit in the IMR will disable the corresponding interrupt.
*/
#define JABBER 0x80 /* jabber error - 10baseT xmission too long */
#define BABBLE 0x40 /* babble - xmitter xmitting for too long */
#define CERR 0x20 /* collision err - no SQE test (heartbeat) */
#define RCVCCO 0x10 /* RCVCC overflow */
#define RNTPCO 0x08 /* RNTPC overflow */
#define MPCO 0x04 /* MPC overflow */
#define RCVINT 0x02 /* receive interrupt */
#define XMTINT 0x01 /* transmitter interrupt */
/* Bits in PR */
#define XMTSV 0x80 /* XMTFS valid (same as in XMTFS) */
#define TDTREQ 0x40 /* set when xmit fifo is requesting data */
#define RDTREQ 0x20 /* set when recv fifo requests data xfer */
/* Bits in BIUCC */
#define BSWP 0x40 /* byte swap, i.e. big-endian bus */
#define XMTSP_4 0x00 /* start xmitting when 4 bytes in FIFO */
#define XMTSP_16 0x10 /* start xmitting when 16 bytes in FIFO */
#define XMTSP_64 0x20 /* start xmitting when 64 bytes in FIFO */
#define XMTSP_112 0x30 /* start xmitting when 112 bytes in FIFO */
#define SWRST 0x01 /* software reset */
/* Bits in FIFOCC */
#define XMTFW_8 0x00 /* xmit fifo watermark = 8 words free */
#define XMTFW_16 0x40 /* 16 words free */
#define XMTFW_32 0x80 /* 32 words free */
#define RCVFW_16 0x00 /* recv fifo watermark = 16 bytes avail */
#define RCVFW_32 0x10 /* 32 bytes avail */
#define RCVFW_64 0x20 /* 64 bytes avail */
#define XMTFWU 0x08 /* xmit fifo watermark update enable */
#define RCVFWU 0x04 /* recv fifo watermark update enable */
#define XMTBRST 0x02 /* enable transmit burst mode */
#define RCVBRST 0x01 /* enable receive burst mode */
/* Bits in MACCC */
#define PROM 0x80 /* promiscuous mode */
#define DXMT2PD 0x40 /* disable xmit two-part deferral algorithm */
#define EMBA 0x20 /* enable modified backoff algorithm */
#define DRCVPA 0x08 /* disable receiving physical address */
#define DRCVBC 0x04 /* disable receiving broadcasts */
#define ENXMT 0x02 /* enable transmitter */
#define ENRCV 0x01 /* enable receiver */
/* Bits in PLSCC */
#define XMTSEL 0x08 /* select DO+/DO- state when idle */
#define PORTSEL_AUI 0x00 /* select AUI port */
#define PORTSEL_10T 0x02 /* select 10Base-T port */
#define PORTSEL_DAI 0x04 /* select DAI port */
#define PORTSEL_GPSI 0x06 /* select GPSI port */
#define ENPLSIO 0x01 /* enable optional PLS I/O pins */
/* Bits in PHYCC */
#define LNKFL 0x80 /* reports 10Base-T link failure */
#define DLNKTST 0x40 /* disable 10Base-T link test */
#define REVPOL 0x20 /* 10Base-T receiver polarity reversed */
#define DAPC 0x10 /* disable auto receiver polarity correction */
#define LRT 0x08 /* low receive threshold for long links */
#define ASEL 0x04 /* auto-select AUI or 10Base-T port */
#define RWAKE 0x02 /* remote wake function */
#define AWAKE 0x01 /* auto wake function */
/* Bits in IAC */
#define ADDRCHG 0x80 /* request address change */
#define PHYADDR 0x04 /* access physical address */
#define LOGADDR 0x02 /* access multicast filter */
/* Bits in UTR */
#define RTRE 0x80 /* reserved test register enable. DON'T SET. */
#define RTRD 0x40 /* reserved test register disable. Sticky */
#define RPAC 0x20 /* accept runt packets */
#define FCOLL 0x10 /* force collision */
#define RCVFCSE 0x08 /* receive FCS enable */
#define LOOP_NONE 0x00 /* no loopback */
#define LOOP_EXT 0x02 /* external loopback */
#define LOOP_INT 0x04 /* internal loopback, excludes MENDEC */
#define LOOP_MENDEC 0x06 /* internal loopback, includes MENDEC */

View file

@ -0,0 +1,789 @@
/*
* Driver for the Macintosh 68K onboard MACE controller with PSC
* driven DMA. The MACE driver code is derived from mace.c. The
* Mac68k theory of operation is courtesy of the MacBSD wizards.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* Copyright (C) 1996 Paul Mackerras.
* Copyright (C) 1998 Alan Cox <alan@lxorguk.ukuu.org.uk>
*
* Modified heavily by Joshua M. Thompson based on Dave Huang's NetBSD driver
*
* Copyright (C) 2007 Finn Thain
*
* Converted to DMA API, converted to unified driver model,
* sync'd some routines with mace.c and fixed various bugs.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <linux/delay.h>
#include <linux/string.h>
#include <linux/crc32.h>
#include <linux/bitrev.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/gfp.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <asm/macints.h>
#include <asm/mac_psc.h>
#include <asm/page.h>
#include "mace.h"
static char mac_mace_string[] = "macmace";
#define N_TX_BUFF_ORDER 0
#define N_TX_RING (1 << N_TX_BUFF_ORDER)
#define N_RX_BUFF_ORDER 3
#define N_RX_RING (1 << N_RX_BUFF_ORDER)
#define TX_TIMEOUT HZ
#define MACE_BUFF_SIZE 0x800
/* Chip rev needs workaround on HW & multicast addr change */
#define BROKEN_ADDRCHG_REV 0x0941
/* The MACE is simply wired down on a Mac68K box */
#define MACE_BASE (void *)(0x50F1C000)
#define MACE_PROM (void *)(0x50F08001)
struct mace_data {
volatile struct mace *mace;
unsigned char *tx_ring;
dma_addr_t tx_ring_phys;
unsigned char *rx_ring;
dma_addr_t rx_ring_phys;
int dma_intr;
int rx_slot, rx_tail;
int tx_slot, tx_sloti, tx_count;
int chipid;
struct device *device;
};
struct mace_frame {
u8 rcvcnt;
u8 pad1;
u8 rcvsts;
u8 pad2;
u8 rntpc;
u8 pad3;
u8 rcvcc;
u8 pad4;
u32 pad5;
u32 pad6;
u8 data[1];
/* And frame continues.. */
};
#define PRIV_BYTES sizeof(struct mace_data)
static int mace_open(struct net_device *dev);
static int mace_close(struct net_device *dev);
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev);
static void mace_set_multicast(struct net_device *dev);
static int mace_set_address(struct net_device *dev, void *addr);
static void mace_reset(struct net_device *dev);
static irqreturn_t mace_interrupt(int irq, void *dev_id);
static irqreturn_t mace_dma_intr(int irq, void *dev_id);
static void mace_tx_timeout(struct net_device *dev);
static void __mace_set_address(struct net_device *dev, void *addr);
/*
* Load a receive DMA channel with a base address and ring length
*/
static void mace_load_rxdma_base(struct net_device *dev, int set)
{
struct mace_data *mp = netdev_priv(dev);
psc_write_word(PSC_ENETRD_CMD + set, 0x0100);
psc_write_long(PSC_ENETRD_ADDR + set, (u32) mp->rx_ring_phys);
psc_write_long(PSC_ENETRD_LEN + set, N_RX_RING);
psc_write_word(PSC_ENETRD_CMD + set, 0x9800);
mp->rx_tail = 0;
}
/*
* Reset the receive DMA subsystem
*/
static void mace_rxdma_reset(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mace = mp->mace;
u8 maccc = mace->maccc;
mace->maccc = maccc & ~ENRCV;
psc_write_word(PSC_ENETRD_CTL, 0x8800);
mace_load_rxdma_base(dev, 0x00);
psc_write_word(PSC_ENETRD_CTL, 0x0400);
psc_write_word(PSC_ENETRD_CTL, 0x8800);
mace_load_rxdma_base(dev, 0x10);
psc_write_word(PSC_ENETRD_CTL, 0x0400);
mace->maccc = maccc;
mp->rx_slot = 0;
psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x9800);
psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x9800);
}
/*
* Reset the transmit DMA subsystem
*/
static void mace_txdma_reset(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mace = mp->mace;
u8 maccc;
psc_write_word(PSC_ENETWR_CTL, 0x8800);
maccc = mace->maccc;
mace->maccc = maccc & ~ENXMT;
mp->tx_slot = mp->tx_sloti = 0;
mp->tx_count = N_TX_RING;
psc_write_word(PSC_ENETWR_CTL, 0x0400);
mace->maccc = maccc;
}
/*
* Disable DMA
*/
static void mace_dma_off(struct net_device *dev)
{
psc_write_word(PSC_ENETRD_CTL, 0x8800);
psc_write_word(PSC_ENETRD_CTL, 0x1000);
psc_write_word(PSC_ENETRD_CMD + PSC_SET0, 0x1100);
psc_write_word(PSC_ENETRD_CMD + PSC_SET1, 0x1100);
psc_write_word(PSC_ENETWR_CTL, 0x8800);
psc_write_word(PSC_ENETWR_CTL, 0x1000);
psc_write_word(PSC_ENETWR_CMD + PSC_SET0, 0x1100);
psc_write_word(PSC_ENETWR_CMD + PSC_SET1, 0x1100);
}
static const struct net_device_ops mace_netdev_ops = {
.ndo_open = mace_open,
.ndo_stop = mace_close,
.ndo_start_xmit = mace_xmit_start,
.ndo_tx_timeout = mace_tx_timeout,
.ndo_set_rx_mode = mace_set_multicast,
.ndo_set_mac_address = mace_set_address,
.ndo_change_mtu = eth_change_mtu,
.ndo_validate_addr = eth_validate_addr,
};
/*
* Not really much of a probe. The hardware table tells us if this
* model of Macintrash has a MACE (AV macintoshes)
*/
static int mace_probe(struct platform_device *pdev)
{
int j;
struct mace_data *mp;
unsigned char *addr;
struct net_device *dev;
unsigned char checksum = 0;
int err;
dev = alloc_etherdev(PRIV_BYTES);
if (!dev)
return -ENOMEM;
mp = netdev_priv(dev);
mp->device = &pdev->dev;
platform_set_drvdata(pdev, dev);
SET_NETDEV_DEV(dev, &pdev->dev);
dev->base_addr = (u32)MACE_BASE;
mp->mace = MACE_BASE;
dev->irq = IRQ_MAC_MACE;
mp->dma_intr = IRQ_MAC_MACE_DMA;
mp->chipid = mp->mace->chipid_hi << 8 | mp->mace->chipid_lo;
/*
* The PROM contains 8 bytes which total 0xFF when XOR'd
* together. Due to the usual peculiar apple brain damage
* the bytes are spaced out in a strange boundary and the
* bits are reversed.
*/
addr = MACE_PROM;
for (j = 0; j < 6; ++j) {
u8 v = bitrev8(addr[j<<4]);
checksum ^= v;
dev->dev_addr[j] = v;
}
for (; j < 8; ++j) {
checksum ^= bitrev8(addr[j<<4]);
}
if (checksum != 0xFF) {
free_netdev(dev);
return -ENODEV;
}
dev->netdev_ops = &mace_netdev_ops;
dev->watchdog_timeo = TX_TIMEOUT;
printk(KERN_INFO "%s: 68K MACE, hardware address %pM\n",
dev->name, dev->dev_addr);
err = register_netdev(dev);
if (!err)
return 0;
free_netdev(dev);
return err;
}
/*
* Reset the chip.
*/
static void mace_reset(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
int i;
/* soft-reset the chip */
i = 200;
while (--i) {
mb->biucc = SWRST;
if (mb->biucc & SWRST) {
udelay(10);
continue;
}
break;
}
if (!i) {
printk(KERN_ERR "macmace: cannot reset chip!\n");
return;
}
mb->maccc = 0; /* turn off tx, rx */
mb->imr = 0xFF; /* disable all intrs for now */
i = mb->ir;
mb->biucc = XMTSP_64;
mb->utr = RTRD;
mb->fifocc = XMTFW_8 | RCVFW_64 | XMTFWU | RCVFWU;
mb->xmtfc = AUTO_PAD_XMIT; /* auto-pad short frames */
mb->rcvfc = 0;
/* load up the hardware address */
__mace_set_address(dev, dev->dev_addr);
/* clear the multicast filter */
if (mp->chipid == BROKEN_ADDRCHG_REV)
mb->iac = LOGADDR;
else {
mb->iac = ADDRCHG | LOGADDR;
while ((mb->iac & ADDRCHG) != 0)
;
}
for (i = 0; i < 8; ++i)
mb->ladrf = 0;
/* done changing address */
if (mp->chipid != BROKEN_ADDRCHG_REV)
mb->iac = 0;
mb->plscc = PORTSEL_AUI;
}
/*
* Load the address on a mace controller.
*/
static void __mace_set_address(struct net_device *dev, void *addr)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
unsigned char *p = addr;
int i;
/* load up the hardware address */
if (mp->chipid == BROKEN_ADDRCHG_REV)
mb->iac = PHYADDR;
else {
mb->iac = ADDRCHG | PHYADDR;
while ((mb->iac & ADDRCHG) != 0)
;
}
for (i = 0; i < 6; ++i)
mb->padr = dev->dev_addr[i] = p[i];
if (mp->chipid != BROKEN_ADDRCHG_REV)
mb->iac = 0;
}
static int mace_set_address(struct net_device *dev, void *addr)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
unsigned long flags;
u8 maccc;
local_irq_save(flags);
maccc = mb->maccc;
__mace_set_address(dev, addr);
mb->maccc = maccc;
local_irq_restore(flags);
return 0;
}
/*
* Open the Macintosh MACE. Most of this is playing with the DMA
* engine. The ethernet chip is quite friendly.
*/
static int mace_open(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
/* reset the chip */
mace_reset(dev);
if (request_irq(dev->irq, mace_interrupt, 0, dev->name, dev)) {
printk(KERN_ERR "%s: can't get irq %d\n", dev->name, dev->irq);
return -EAGAIN;
}
if (request_irq(mp->dma_intr, mace_dma_intr, 0, dev->name, dev)) {
printk(KERN_ERR "%s: can't get irq %d\n", dev->name, mp->dma_intr);
free_irq(dev->irq, dev);
return -EAGAIN;
}
/* Allocate the DMA ring buffers */
mp->tx_ring = dma_alloc_coherent(mp->device,
N_TX_RING * MACE_BUFF_SIZE,
&mp->tx_ring_phys, GFP_KERNEL);
if (mp->tx_ring == NULL)
goto out1;
mp->rx_ring = dma_alloc_coherent(mp->device,
N_RX_RING * MACE_BUFF_SIZE,
&mp->rx_ring_phys, GFP_KERNEL);
if (mp->rx_ring == NULL)
goto out2;
mace_dma_off(dev);
/* Not sure what these do */
psc_write_word(PSC_ENETWR_CTL, 0x9000);
psc_write_word(PSC_ENETRD_CTL, 0x9000);
psc_write_word(PSC_ENETWR_CTL, 0x0400);
psc_write_word(PSC_ENETRD_CTL, 0x0400);
mace_rxdma_reset(dev);
mace_txdma_reset(dev);
/* turn it on! */
mb->maccc = ENXMT | ENRCV;
/* enable all interrupts except receive interrupts */
mb->imr = RCVINT;
return 0;
out2:
dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
mp->tx_ring, mp->tx_ring_phys);
out1:
free_irq(dev->irq, dev);
free_irq(mp->dma_intr, dev);
return -ENOMEM;
}
/*
* Shut down the mace and its interrupt channel
*/
static int mace_close(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
mb->maccc = 0; /* disable rx and tx */
mb->imr = 0xFF; /* disable all irqs */
mace_dma_off(dev); /* disable rx and tx dma */
return 0;
}
/*
* Transmit a frame
*/
static int mace_xmit_start(struct sk_buff *skb, struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
unsigned long flags;
/* Stop the queue since there's only the one buffer */
local_irq_save(flags);
netif_stop_queue(dev);
if (!mp->tx_count) {
printk(KERN_ERR "macmace: tx queue running but no free buffers.\n");
local_irq_restore(flags);
return NETDEV_TX_BUSY;
}
mp->tx_count--;
local_irq_restore(flags);
dev->stats.tx_packets++;
dev->stats.tx_bytes += skb->len;
/* We need to copy into our xmit buffer to take care of alignment and caching issues */
skb_copy_from_linear_data(skb, mp->tx_ring, skb->len);
/* load the Tx DMA and fire it off */
psc_write_long(PSC_ENETWR_ADDR + mp->tx_slot, (u32) mp->tx_ring_phys);
psc_write_long(PSC_ENETWR_LEN + mp->tx_slot, skb->len);
psc_write_word(PSC_ENETWR_CMD + mp->tx_slot, 0x9800);
mp->tx_slot ^= 0x10;
dev_kfree_skb(skb);
return NETDEV_TX_OK;
}
static void mace_set_multicast(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
int i;
u32 crc;
u8 maccc;
unsigned long flags;
local_irq_save(flags);
maccc = mb->maccc;
mb->maccc &= ~PROM;
if (dev->flags & IFF_PROMISC) {
mb->maccc |= PROM;
} else {
unsigned char multicast_filter[8];
struct netdev_hw_addr *ha;
if (dev->flags & IFF_ALLMULTI) {
for (i = 0; i < 8; i++) {
multicast_filter[i] = 0xFF;
}
} else {
for (i = 0; i < 8; i++)
multicast_filter[i] = 0;
netdev_for_each_mc_addr(ha, dev) {
crc = ether_crc_le(6, ha->addr);
/* bit number in multicast_filter */
i = crc >> 26;
multicast_filter[i >> 3] |= 1 << (i & 7);
}
}
if (mp->chipid == BROKEN_ADDRCHG_REV)
mb->iac = LOGADDR;
else {
mb->iac = ADDRCHG | LOGADDR;
while ((mb->iac & ADDRCHG) != 0)
;
}
for (i = 0; i < 8; ++i)
mb->ladrf = multicast_filter[i];
if (mp->chipid != BROKEN_ADDRCHG_REV)
mb->iac = 0;
}
mb->maccc = maccc;
local_irq_restore(flags);
}
static void mace_handle_misc_intrs(struct net_device *dev, int intr)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
static int mace_babbles, mace_jabbers;
if (intr & MPCO)
dev->stats.rx_missed_errors += 256;
dev->stats.rx_missed_errors += mb->mpc; /* reading clears it */
if (intr & RNTPCO)
dev->stats.rx_length_errors += 256;
dev->stats.rx_length_errors += mb->rntpc; /* reading clears it */
if (intr & CERR)
++dev->stats.tx_heartbeat_errors;
if (intr & BABBLE)
if (mace_babbles++ < 4)
printk(KERN_DEBUG "macmace: babbling transmitter\n");
if (intr & JABBER)
if (mace_jabbers++ < 4)
printk(KERN_DEBUG "macmace: jabbering transceiver\n");
}
static irqreturn_t mace_interrupt(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
int intr, fs;
unsigned long flags;
/* don't want the dma interrupt handler to fire */
local_irq_save(flags);
intr = mb->ir; /* read interrupt register */
mace_handle_misc_intrs(dev, intr);
if (intr & XMTINT) {
fs = mb->xmtfs;
if ((fs & XMTSV) == 0) {
printk(KERN_ERR "macmace: xmtfs not valid! (fs=%x)\n", fs);
mace_reset(dev);
/*
* XXX mace likes to hang the machine after a xmtfs error.
* This is hard to reproduce, reseting *may* help
*/
}
/* dma should have finished */
if (!mp->tx_count) {
printk(KERN_DEBUG "macmace: tx ring ran out? (fs=%x)\n", fs);
}
/* Update stats */
if (fs & (UFLO|LCOL|LCAR|RTRY)) {
++dev->stats.tx_errors;
if (fs & LCAR)
++dev->stats.tx_carrier_errors;
else if (fs & (UFLO|LCOL|RTRY)) {
++dev->stats.tx_aborted_errors;
if (mb->xmtfs & UFLO) {
printk(KERN_ERR "%s: DMA underrun.\n", dev->name);
dev->stats.tx_fifo_errors++;
mace_txdma_reset(dev);
}
}
}
}
if (mp->tx_count)
netif_wake_queue(dev);
local_irq_restore(flags);
return IRQ_HANDLED;
}
static void mace_tx_timeout(struct net_device *dev)
{
struct mace_data *mp = netdev_priv(dev);
volatile struct mace *mb = mp->mace;
unsigned long flags;
local_irq_save(flags);
/* turn off both tx and rx and reset the chip */
mb->maccc = 0;
printk(KERN_ERR "macmace: transmit timeout - resetting\n");
mace_txdma_reset(dev);
mace_reset(dev);
/* restart rx dma */
mace_rxdma_reset(dev);
mp->tx_count = N_TX_RING;
netif_wake_queue(dev);
/* turn it on! */
mb->maccc = ENXMT | ENRCV;
/* enable all interrupts except receive interrupts */
mb->imr = RCVINT;
local_irq_restore(flags);
}
/*
* Handle a newly arrived frame
*/
static void mace_dma_rx_frame(struct net_device *dev, struct mace_frame *mf)
{
struct sk_buff *skb;
unsigned int frame_status = mf->rcvsts;
if (frame_status & (RS_OFLO | RS_CLSN | RS_FRAMERR | RS_FCSERR)) {
dev->stats.rx_errors++;
if (frame_status & RS_OFLO) {
printk(KERN_DEBUG "%s: fifo overflow.\n", dev->name);
dev->stats.rx_fifo_errors++;
}
if (frame_status & RS_CLSN)
dev->stats.collisions++;
if (frame_status & RS_FRAMERR)
dev->stats.rx_frame_errors++;
if (frame_status & RS_FCSERR)
dev->stats.rx_crc_errors++;
} else {
unsigned int frame_length = mf->rcvcnt + ((frame_status & 0x0F) << 8 );
skb = netdev_alloc_skb(dev, frame_length + 2);
if (!skb) {
dev->stats.rx_dropped++;
return;
}
skb_reserve(skb, 2);
memcpy(skb_put(skb, frame_length), mf->data, frame_length);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
dev->stats.rx_packets++;
dev->stats.rx_bytes += frame_length;
}
}
/*
* The PSC has passed us a DMA interrupt event.
*/
static irqreturn_t mace_dma_intr(int irq, void *dev_id)
{
struct net_device *dev = (struct net_device *) dev_id;
struct mace_data *mp = netdev_priv(dev);
int left, head;
u16 status;
u32 baka;
/* Not sure what this does */
while ((baka = psc_read_long(PSC_MYSTERY)) != psc_read_long(PSC_MYSTERY));
if (!(baka & 0x60000000)) return IRQ_NONE;
/*
* Process the read queue
*/
status = psc_read_word(PSC_ENETRD_CTL);
if (status & 0x2000) {
mace_rxdma_reset(dev);
} else if (status & 0x0100) {
psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x1100);
left = psc_read_long(PSC_ENETRD_LEN + mp->rx_slot);
head = N_RX_RING - left;
/* Loop through the ring buffer and process new packages */
while (mp->rx_tail < head) {
mace_dma_rx_frame(dev, (struct mace_frame*) (mp->rx_ring
+ (mp->rx_tail * MACE_BUFF_SIZE)));
mp->rx_tail++;
}
/* If we're out of buffers in this ring then switch to */
/* the other set, otherwise just reactivate this one. */
if (!left) {
mace_load_rxdma_base(dev, mp->rx_slot);
mp->rx_slot ^= 0x10;
} else {
psc_write_word(PSC_ENETRD_CMD + mp->rx_slot, 0x9800);
}
}
/*
* Process the write queue
*/
status = psc_read_word(PSC_ENETWR_CTL);
if (status & 0x2000) {
mace_txdma_reset(dev);
} else if (status & 0x0100) {
psc_write_word(PSC_ENETWR_CMD + mp->tx_sloti, 0x0100);
mp->tx_sloti ^= 0x10;
mp->tx_count++;
}
return IRQ_HANDLED;
}
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Macintosh MACE ethernet driver");
MODULE_ALIAS("platform:macmace");
static int mac_mace_device_remove(struct platform_device *pdev)
{
struct net_device *dev = platform_get_drvdata(pdev);
struct mace_data *mp = netdev_priv(dev);
unregister_netdev(dev);
free_irq(dev->irq, dev);
free_irq(IRQ_MAC_MACE_DMA, dev);
dma_free_coherent(mp->device, N_RX_RING * MACE_BUFF_SIZE,
mp->rx_ring, mp->rx_ring_phys);
dma_free_coherent(mp->device, N_TX_RING * MACE_BUFF_SIZE,
mp->tx_ring, mp->tx_ring_phys);
free_netdev(dev);
return 0;
}
static struct platform_driver mac_mace_driver = {
.probe = mace_probe,
.remove = mac_mace_device_remove,
.driver = {
.name = mac_mace_string,
.owner = THIS_MODULE,
},
};
static int __init mac_mace_init_module(void)
{
if (!MACH_IS_MAC)
return -ENODEV;
return platform_driver_register(&mac_mace_driver);
}
static void __exit mac_mace_cleanup_module(void)
{
platform_driver_unregister(&mac_mace_driver);
}
module_init(mac_mace_init_module);
module_exit(mac_mace_cleanup_module);