xref: /OK3568_Linux_fs/kernel/drivers/net/ethernet/8390/stnic.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
2*4882a593Smuzhiyun  *
3*4882a593Smuzhiyun  * This file is subject to the terms and conditions of the GNU General Public
4*4882a593Smuzhiyun  * License.  See the file "COPYING" in the main directory of this archive
5*4882a593Smuzhiyun  * for more details.
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  * Copyright (C) 1999 kaz Kojima
8*4882a593Smuzhiyun  */
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/kernel.h>
12*4882a593Smuzhiyun #include <linux/errno.h>
13*4882a593Smuzhiyun #include <linux/interrupt.h>
14*4882a593Smuzhiyun #include <linux/ioport.h>
15*4882a593Smuzhiyun #include <linux/netdevice.h>
16*4882a593Smuzhiyun #include <linux/etherdevice.h>
17*4882a593Smuzhiyun #include <linux/init.h>
18*4882a593Smuzhiyun #include <linux/delay.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include <asm/io.h>
21*4882a593Smuzhiyun #include <mach-se/mach/se.h>
22*4882a593Smuzhiyun #include <asm/machvec.h>
23*4882a593Smuzhiyun #ifdef CONFIG_SH_STANDARD_BIOS
24*4882a593Smuzhiyun #include <asm/sh_bios.h>
25*4882a593Smuzhiyun #endif
26*4882a593Smuzhiyun 
27*4882a593Smuzhiyun #include "8390.h"
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define DRV_NAME "stnic"
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun #define byte	unsigned char
32*4882a593Smuzhiyun #define half	unsigned short
33*4882a593Smuzhiyun #define word	unsigned int
34*4882a593Smuzhiyun #define vbyte	volatile unsigned char
35*4882a593Smuzhiyun #define vhalf	volatile unsigned short
36*4882a593Smuzhiyun #define vword	volatile unsigned int
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #define STNIC_RUN	0x01	/* 1 == Run, 0 == reset. */
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define START_PG	0	/* First page of TX buffer */
41*4882a593Smuzhiyun #define STOP_PG		128	/* Last page +1 of RX ring */
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun /* Alias */
44*4882a593Smuzhiyun #define STNIC_CR	E8390_CMD
45*4882a593Smuzhiyun #define PG0_RSAR0	EN0_RSARLO
46*4882a593Smuzhiyun #define PG0_RSAR1	EN0_RSARHI
47*4882a593Smuzhiyun #define PG0_RBCR0	EN0_RCNTLO
48*4882a593Smuzhiyun #define PG0_RBCR1	EN0_RCNTHI
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #define CR_RRD		E8390_RREAD
51*4882a593Smuzhiyun #define CR_RWR		E8390_RWRITE
52*4882a593Smuzhiyun #define CR_PG0		E8390_PAGE0
53*4882a593Smuzhiyun #define CR_STA		E8390_START
54*4882a593Smuzhiyun #define CR_RDMA		E8390_NODMA
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun /* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
57*4882a593Smuzhiyun static byte stnic_eadr[6] =
58*4882a593Smuzhiyun {0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun static struct net_device *stnic_dev;
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun static void stnic_reset (struct net_device *dev);
63*4882a593Smuzhiyun static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
64*4882a593Smuzhiyun 			   int ring_page);
65*4882a593Smuzhiyun static void stnic_block_input (struct net_device *dev, int count,
66*4882a593Smuzhiyun 			       struct sk_buff *skb , int ring_offset);
67*4882a593Smuzhiyun static void stnic_block_output (struct net_device *dev, int count,
68*4882a593Smuzhiyun 				const unsigned char *buf, int start_page);
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun static void stnic_init (struct net_device *dev);
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun static u32 stnic_msg_enable;
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun module_param_named(msg_enable, stnic_msg_enable, uint, 0444);
75*4882a593Smuzhiyun MODULE_PARM_DESC(msg_enable, "Debug message level (see linux/netdevice.h for bitmap)");
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /* SH7750 specific read/write io. */
78*4882a593Smuzhiyun static inline void
STNIC_DELAY(void)79*4882a593Smuzhiyun STNIC_DELAY (void)
80*4882a593Smuzhiyun {
81*4882a593Smuzhiyun   vword trash;
82*4882a593Smuzhiyun   trash = *(vword *) 0xa0000000;
83*4882a593Smuzhiyun   trash = *(vword *) 0xa0000000;
84*4882a593Smuzhiyun   trash = *(vword *) 0xa0000000;
85*4882a593Smuzhiyun }
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun static inline byte
STNIC_READ(int reg)88*4882a593Smuzhiyun STNIC_READ (int reg)
89*4882a593Smuzhiyun {
90*4882a593Smuzhiyun   byte val;
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun   val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
93*4882a593Smuzhiyun   STNIC_DELAY ();
94*4882a593Smuzhiyun   return val;
95*4882a593Smuzhiyun }
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun static inline void
STNIC_WRITE(int reg,byte val)98*4882a593Smuzhiyun STNIC_WRITE (int reg, byte val)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun   *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
101*4882a593Smuzhiyun   STNIC_DELAY ();
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun 
stnic_probe(void)104*4882a593Smuzhiyun static int __init stnic_probe(void)
105*4882a593Smuzhiyun {
106*4882a593Smuzhiyun   struct net_device *dev;
107*4882a593Smuzhiyun   int i, err;
108*4882a593Smuzhiyun   struct ei_device *ei_local;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun   /* If we are not running on a SolutionEngine, give up now */
111*4882a593Smuzhiyun   if (! MACH_SE)
112*4882a593Smuzhiyun     return -ENODEV;
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun   /* New style probing API */
115*4882a593Smuzhiyun   dev = alloc_ei_netdev();
116*4882a593Smuzhiyun   if (!dev)
117*4882a593Smuzhiyun   	return -ENOMEM;
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #ifdef CONFIG_SH_STANDARD_BIOS
120*4882a593Smuzhiyun   sh_bios_get_node_addr (stnic_eadr);
121*4882a593Smuzhiyun #endif
122*4882a593Smuzhiyun   for (i = 0; i < ETH_ALEN; i++)
123*4882a593Smuzhiyun     dev->dev_addr[i] = stnic_eadr[i];
124*4882a593Smuzhiyun 
125*4882a593Smuzhiyun   /* Set the base address to point to the NIC, not the "real" base! */
126*4882a593Smuzhiyun   dev->base_addr = 0x1000;
127*4882a593Smuzhiyun   dev->irq = IRQ_STNIC;
128*4882a593Smuzhiyun   dev->netdev_ops = &ei_netdev_ops;
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun   /* Snarf the interrupt now.  There's no point in waiting since we cannot
131*4882a593Smuzhiyun      share and the board will usually be enabled. */
132*4882a593Smuzhiyun   err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
133*4882a593Smuzhiyun   if (err)  {
134*4882a593Smuzhiyun 	netdev_emerg(dev, " unable to get IRQ %d.\n", dev->irq);
135*4882a593Smuzhiyun 	free_netdev(dev);
136*4882a593Smuzhiyun 	return err;
137*4882a593Smuzhiyun   }
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun   ei_status.name = dev->name;
140*4882a593Smuzhiyun   ei_status.word16 = 1;
141*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN__
142*4882a593Smuzhiyun   ei_status.bigendian = 0;
143*4882a593Smuzhiyun #else
144*4882a593Smuzhiyun   ei_status.bigendian = 1;
145*4882a593Smuzhiyun #endif
146*4882a593Smuzhiyun   ei_status.tx_start_page = START_PG;
147*4882a593Smuzhiyun   ei_status.rx_start_page = START_PG + TX_PAGES;
148*4882a593Smuzhiyun   ei_status.stop_page = STOP_PG;
149*4882a593Smuzhiyun 
150*4882a593Smuzhiyun   ei_status.reset_8390 = &stnic_reset;
151*4882a593Smuzhiyun   ei_status.get_8390_hdr = &stnic_get_hdr;
152*4882a593Smuzhiyun   ei_status.block_input = &stnic_block_input;
153*4882a593Smuzhiyun   ei_status.block_output = &stnic_block_output;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun   stnic_init (dev);
156*4882a593Smuzhiyun   ei_local = netdev_priv(dev);
157*4882a593Smuzhiyun   ei_local->msg_enable = stnic_msg_enable;
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun   err = register_netdev(dev);
160*4882a593Smuzhiyun   if (err) {
161*4882a593Smuzhiyun     free_irq(dev->irq, dev);
162*4882a593Smuzhiyun     free_netdev(dev);
163*4882a593Smuzhiyun     return err;
164*4882a593Smuzhiyun   }
165*4882a593Smuzhiyun   stnic_dev = dev;
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun   netdev_info(dev, "NS ST-NIC 83902A\n");
168*4882a593Smuzhiyun 
169*4882a593Smuzhiyun   return 0;
170*4882a593Smuzhiyun }
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun static void
stnic_reset(struct net_device * dev)173*4882a593Smuzhiyun stnic_reset (struct net_device *dev)
174*4882a593Smuzhiyun {
175*4882a593Smuzhiyun   struct ei_device *ei_local = netdev_priv(dev);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun   *(vhalf *) PA_83902_RST = 0;
178*4882a593Smuzhiyun   udelay (5);
179*4882a593Smuzhiyun   netif_warn(ei_local, hw, dev, "8390 reset done (%ld).\n", jiffies);
180*4882a593Smuzhiyun   *(vhalf *) PA_83902_RST = ~0;
181*4882a593Smuzhiyun   udelay (5);
182*4882a593Smuzhiyun }
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun static void
stnic_get_hdr(struct net_device * dev,struct e8390_pkt_hdr * hdr,int ring_page)185*4882a593Smuzhiyun stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
186*4882a593Smuzhiyun 	       int ring_page)
187*4882a593Smuzhiyun {
188*4882a593Smuzhiyun   struct ei_device *ei_local = netdev_priv(dev);
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun   half buf[2];
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR0, 0);
193*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR1, ring_page);
194*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR0, 4);
195*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR1, 0);
196*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun   buf[0] = *(vhalf *) PA_83902_IF;
199*4882a593Smuzhiyun   STNIC_DELAY ();
200*4882a593Smuzhiyun   buf[1] = *(vhalf *) PA_83902_IF;
201*4882a593Smuzhiyun   STNIC_DELAY ();
202*4882a593Smuzhiyun   hdr->next = buf[0] >> 8;
203*4882a593Smuzhiyun   hdr->status = buf[0] & 0xff;
204*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN__
205*4882a593Smuzhiyun   hdr->count = buf[1];
206*4882a593Smuzhiyun #else
207*4882a593Smuzhiyun   hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
208*4882a593Smuzhiyun #endif
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun   netif_dbg(ei_local, probe, dev, "ring %x status %02x next %02x count %04x.\n",
211*4882a593Smuzhiyun 	    ring_page, hdr->status, hdr->next, hdr->count);
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
214*4882a593Smuzhiyun }
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun /* Block input and output, similar to the Crynwr packet driver. If you are
217*4882a593Smuzhiyun    porting to a new ethercard look at the packet driver source for hints.
218*4882a593Smuzhiyun    The HP LAN doesn't use shared memory -- we put the packet
219*4882a593Smuzhiyun    out through the "remote DMA" dataport. */
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun static void
stnic_block_input(struct net_device * dev,int length,struct sk_buff * skb,int offset)222*4882a593Smuzhiyun stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
223*4882a593Smuzhiyun 		   int offset)
224*4882a593Smuzhiyun {
225*4882a593Smuzhiyun   char *buf = skb->data;
226*4882a593Smuzhiyun   half val;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR0, offset & 0xff);
229*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR1, offset >> 8);
230*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR0, length & 0xff);
231*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR1, length >> 8);
232*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun   if (length & 1)
235*4882a593Smuzhiyun     length++;
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun   while (length > 0)
238*4882a593Smuzhiyun     {
239*4882a593Smuzhiyun       val = *(vhalf *) PA_83902_IF;
240*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN__
241*4882a593Smuzhiyun       *buf++ = val & 0xff;
242*4882a593Smuzhiyun       *buf++ = val >> 8;
243*4882a593Smuzhiyun #else
244*4882a593Smuzhiyun       *buf++ = val >> 8;
245*4882a593Smuzhiyun       *buf++ = val & 0xff;
246*4882a593Smuzhiyun #endif
247*4882a593Smuzhiyun       STNIC_DELAY ();
248*4882a593Smuzhiyun       length -= sizeof (half);
249*4882a593Smuzhiyun     }
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
252*4882a593Smuzhiyun }
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun static void
stnic_block_output(struct net_device * dev,int length,const unsigned char * buf,int output_page)255*4882a593Smuzhiyun stnic_block_output (struct net_device *dev, int length,
256*4882a593Smuzhiyun 		    const unsigned char *buf, int output_page)
257*4882a593Smuzhiyun {
258*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR0, 1);	/* Write non-zero value */
259*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
260*4882a593Smuzhiyun   STNIC_DELAY ();
261*4882a593Smuzhiyun 
262*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR0, length & 0xff);
263*4882a593Smuzhiyun   STNIC_WRITE (PG0_RBCR1, length >> 8);
264*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR0, 0);
265*4882a593Smuzhiyun   STNIC_WRITE (PG0_RSAR1, output_page);
266*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun   if (length & 1)
269*4882a593Smuzhiyun     length++;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun   while (length > 0)
272*4882a593Smuzhiyun     {
273*4882a593Smuzhiyun #ifdef __LITTLE_ENDIAN__
274*4882a593Smuzhiyun       *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
275*4882a593Smuzhiyun #else
276*4882a593Smuzhiyun       *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
277*4882a593Smuzhiyun #endif
278*4882a593Smuzhiyun       STNIC_DELAY ();
279*4882a593Smuzhiyun       buf += sizeof (half);
280*4882a593Smuzhiyun       length -= sizeof (half);
281*4882a593Smuzhiyun     }
282*4882a593Smuzhiyun 
283*4882a593Smuzhiyun   STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
284*4882a593Smuzhiyun }
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun /* This function resets the STNIC if something screws up.  */
287*4882a593Smuzhiyun static void
stnic_init(struct net_device * dev)288*4882a593Smuzhiyun stnic_init (struct net_device *dev)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun   stnic_reset (dev);
291*4882a593Smuzhiyun   NS8390_init (dev, 0);
292*4882a593Smuzhiyun }
293*4882a593Smuzhiyun 
stnic_cleanup(void)294*4882a593Smuzhiyun static void __exit stnic_cleanup(void)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun 	unregister_netdev(stnic_dev);
297*4882a593Smuzhiyun 	free_irq(stnic_dev->irq, stnic_dev);
298*4882a593Smuzhiyun 	free_netdev(stnic_dev);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
301*4882a593Smuzhiyun module_init(stnic_probe);
302*4882a593Smuzhiyun module_exit(stnic_cleanup);
303*4882a593Smuzhiyun MODULE_LICENSE("GPL");
304