Blame view

drivers/net/stnic.c 7.02 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
  /* stnic.c : A SH7750 specific part of driver for NS DP83902A ST-NIC.
   *
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file "COPYING" in the main directory of this archive
   * for more details.
   *
   * Copyright (C) 1999 kaz Kojima
   */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
9
10
11
12
13
14
15
16
17
18
19
20
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/ioport.h>
  #include <linux/netdevice.h>
  #include <linux/etherdevice.h>
  #include <linux/init.h>
  #include <linux/delay.h>
  
  #include <asm/system.h>
  #include <asm/io.h>
26a8ef532   Paul Mundt   net: stnic: Fix u...
21
  #include <mach-se/mach/se.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
22
  #include <asm/machvec.h>
6aa20a223   Jeff Garzik   drivers/net: Trim...
23
  #ifdef CONFIG_SH_STANDARD_BIOS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
  #include <asm/sh_bios.h>
  #endif
  
  #include "8390.h"
  
  #define DRV_NAME "stnic"
  
  #define byte	unsigned char
  #define half	unsigned short
  #define word	unsigned int
  #define vbyte	volatile unsigned char
  #define vhalf	volatile unsigned short
  #define vword	volatile unsigned int
  
  #define STNIC_RUN	0x01	/* 1 == Run, 0 == reset. */
  
  #define START_PG	0	/* First page of TX buffer */
  #define STOP_PG		128	/* Last page +1 of RX ring */
  
  /* Alias */
  #define STNIC_CR	E8390_CMD
  #define PG0_RSAR0	EN0_RSARLO
  #define PG0_RSAR1	EN0_RSARHI
  #define PG0_RBCR0	EN0_RCNTLO
  #define PG0_RBCR1	EN0_RCNTHI
  
  #define CR_RRD		E8390_RREAD
  #define CR_RWR		E8390_RWRITE
  #define CR_PG0		E8390_PAGE0
  #define CR_STA		E8390_START
  #define CR_RDMA		E8390_NODMA
  
  /* FIXME! YOU MUST SET YOUR OWN ETHER ADDRESS.  */
  static byte stnic_eadr[6] =
  {0x00, 0xc0, 0x6e, 0x00, 0x00, 0x07};
  
  static struct net_device *stnic_dev;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
  static void stnic_reset (struct net_device *dev);
  static void stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
  			   int ring_page);
  static void stnic_block_input (struct net_device *dev, int count,
  			       struct sk_buff *skb , int ring_offset);
  static void stnic_block_output (struct net_device *dev, int count,
  				const unsigned char *buf, int start_page);
  
  static void stnic_init (struct net_device *dev);
  
  /* SH7750 specific read/write io. */
  static inline void
  STNIC_DELAY (void)
  {
    vword trash;
    trash = *(vword *) 0xa0000000;
    trash = *(vword *) 0xa0000000;
    trash = *(vword *) 0xa0000000;
  }
  
  static inline byte
  STNIC_READ (int reg)
  {
    byte val;
  
    val = (*(vhalf *) (PA_83902 + ((reg) << 1)) >> 8) & 0xff;
    STNIC_DELAY ();
    return val;
  }
  
  static inline void
  STNIC_WRITE (int reg, byte val)
  {
    *(vhalf *) (PA_83902 + ((reg) << 1)) = ((half) (val) << 8);
    STNIC_DELAY ();
  }
6aa20a223   Jeff Garzik   drivers/net: Trim...
97

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
99
100
101
102
103
104
105
106
107
108
109
110
  static int __init stnic_probe(void)
  {
    struct net_device *dev;
    int i, err;
  
    /* If we are not running on a SolutionEngine, give up now */
    if (! MACH_SE)
      return -ENODEV;
  
    /* New style probing API */
    dev = alloc_ei_netdev();
    if (!dev)
    	return -ENOMEM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
111

6aa20a223   Jeff Garzik   drivers/net: Trim...
112
  #ifdef CONFIG_SH_STANDARD_BIOS
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
113
114
115
116
117
118
119
120
    sh_bios_get_node_addr (stnic_eadr);
  #endif
    for (i = 0; i < ETHER_ADDR_LEN; i++)
      dev->dev_addr[i] = stnic_eadr[i];
  
    /* Set the base address to point to the NIC, not the "real" base! */
    dev->base_addr = 0x1000;
    dev->irq = IRQ_STNIC;
e0b8cb0e0   Stephen Hemminger   stnic: convert to...
121
    dev->netdev_ops = &ei_netdev_ops;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
123
124
125
126
127
128
129
130
131
132
133
134
  
    /* Snarf the interrupt now.  There's no point in waiting since we cannot
       share and the board will usually be enabled. */
    err = request_irq (dev->irq, ei_interrupt, 0, DRV_NAME, dev);
    if (err)  {
        printk (KERN_EMERG " unable to get IRQ %d.
  ", dev->irq);
        free_netdev(dev);
        return err;
      }
  
    ei_status.name = dev->name;
    ei_status.word16 = 1;
6aa20a223   Jeff Garzik   drivers/net: Trim...
135
  #ifdef __LITTLE_ENDIAN__
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
    ei_status.bigendian = 0;
  #else
    ei_status.bigendian = 1;
  #endif
    ei_status.tx_start_page = START_PG;
    ei_status.rx_start_page = START_PG + TX_PAGES;
    ei_status.stop_page = STOP_PG;
  
    ei_status.reset_8390 = &stnic_reset;
    ei_status.get_8390_hdr = &stnic_get_hdr;
    ei_status.block_input = &stnic_block_input;
    ei_status.block_output = &stnic_block_output;
  
    stnic_init (dev);
  
    err = register_netdev(dev);
    if (err) {
      free_irq(dev->irq, dev);
      free_netdev(dev);
      return err;
    }
    stnic_dev = dev;
  
    printk (KERN_INFO "NS ST-NIC 83902A
  ");
  
    return 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
  static void
  stnic_reset (struct net_device *dev)
  {
    *(vhalf *) PA_83902_RST = 0;
    udelay (5);
    if (ei_debug > 1)
      printk (KERN_WARNING "8390 reset done (%ld).
  ", jiffies);
    *(vhalf *) PA_83902_RST = ~0;
    udelay (5);
  }
  
  static void
  stnic_get_hdr (struct net_device *dev, struct e8390_pkt_hdr *hdr,
  	       int ring_page)
  {
    half buf[2];
  
    STNIC_WRITE (PG0_RSAR0, 0);
    STNIC_WRITE (PG0_RSAR1, ring_page);
    STNIC_WRITE (PG0_RBCR0, 4);
    STNIC_WRITE (PG0_RBCR1, 0);
    STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
  
    buf[0] = *(vhalf *) PA_83902_IF;
    STNIC_DELAY ();
    buf[1] = *(vhalf *) PA_83902_IF;
    STNIC_DELAY ();
    hdr->next = buf[0] >> 8;
    hdr->status = buf[0] & 0xff;
  #ifdef __LITTLE_ENDIAN__
    hdr->count = buf[1];
  #else
    hdr->count = ((buf[1] >> 8) & 0xff) | (buf[1] << 8);
  #endif
  
    if (ei_debug > 1)
      printk (KERN_DEBUG "ring %x status %02x next %02x count %04x.
  ",
  	    ring_page, hdr->status, hdr->next, hdr->count);
  
    STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
  }
  
  /* Block input and output, similar to the Crynwr packet driver. If you are
     porting to a new ethercard look at the packet driver source for hints.
     The HP LAN doesn't use shared memory -- we put the packet
     out through the "remote DMA" dataport. */
  
  static void
  stnic_block_input (struct net_device *dev, int length, struct sk_buff *skb,
  		   int offset)
  {
    char *buf = skb->data;
    half val;
  
    STNIC_WRITE (PG0_RSAR0, offset & 0xff);
    STNIC_WRITE (PG0_RSAR1, offset >> 8);
    STNIC_WRITE (PG0_RBCR0, length & 0xff);
    STNIC_WRITE (PG0_RBCR1, length >> 8);
    STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
  
    if (length & 1)
      length++;
  
    while (length > 0)
      {
        val = *(vhalf *) PA_83902_IF;
  #ifdef __LITTLE_ENDIAN__
        *buf++ = val & 0xff;
        *buf++ = val >> 8;
  #else
        *buf++ = val >> 8;
        *buf++ = val & 0xff;
  #endif
        STNIC_DELAY ();
        length -= sizeof (half);
      }
  
    STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
  }
  
  static void
  stnic_block_output (struct net_device *dev, int length,
  		    const unsigned char *buf, int output_page)
  {
    STNIC_WRITE (PG0_RBCR0, 1);	/* Write non-zero value */
    STNIC_WRITE (STNIC_CR, CR_RRD | CR_PG0 | CR_STA);
    STNIC_DELAY ();
  
    STNIC_WRITE (PG0_RBCR0, length & 0xff);
    STNIC_WRITE (PG0_RBCR1, length >> 8);
    STNIC_WRITE (PG0_RSAR0, 0);
    STNIC_WRITE (PG0_RSAR1, output_page);
    STNIC_WRITE (STNIC_CR, CR_RWR | CR_PG0 | CR_STA);
  
    if (length & 1)
      length++;
  
    while (length > 0)
      {
  #ifdef __LITTLE_ENDIAN__
        *(vhalf *) PA_83902_IF = ((half) buf[1] << 8) | buf[0];
  #else
        *(vhalf *) PA_83902_IF = ((half) buf[0] << 8) | buf[1];
  #endif
        STNIC_DELAY ();
        buf += sizeof (half);
        length -= sizeof (half);
      }
  
    STNIC_WRITE (STNIC_CR, CR_RDMA | CR_PG0 | CR_STA);
  }
  
  /* This function resets the STNIC if something screws up.  */
  static void
  stnic_init (struct net_device *dev)
  {
    stnic_reset (dev);
    NS8390_init (dev, 0);
    return;
  }
  
  static void __exit stnic_cleanup(void)
  {
  	unregister_netdev(stnic_dev);
  	free_irq(stnic_dev->irq, stnic_dev);
  	free_netdev(stnic_dev);
  }
  
  module_init(stnic_probe);
  module_exit(stnic_cleanup);
  MODULE_LICENSE("GPL");