mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-09-09 01:28:05 -04:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
65
drivers/net/ethernet/apple/Kconfig
Normal file
65
drivers/net/ethernet/apple/Kconfig
Normal 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
|
7
drivers/net/ethernet/apple/Makefile
Normal file
7
drivers/net/ethernet/apple/Makefile
Normal 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
|
1679
drivers/net/ethernet/apple/bmac.c
Normal file
1679
drivers/net/ethernet/apple/bmac.c
Normal file
File diff suppressed because it is too large
Load diff
164
drivers/net/ethernet/apple/bmac.h
Normal file
164
drivers/net/ethernet/apple/bmac.h
Normal 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 */
|
1028
drivers/net/ethernet/apple/mace.c
Normal file
1028
drivers/net/ethernet/apple/mace.c
Normal file
File diff suppressed because it is too large
Load diff
173
drivers/net/ethernet/apple/mace.h
Normal file
173
drivers/net/ethernet/apple/mace.h
Normal 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 */
|
789
drivers/net/ethernet/apple/macmace.c
Normal file
789
drivers/net/ethernet/apple/macmace.c
Normal 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);
|
Loading…
Add table
Add a link
Reference in a new issue