1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21static const char version[] =
22"hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
23
24#include <linux/module.h>
25
26#include <linux/string.h>
27#include <linux/kernel.h>
28#include <linux/errno.h>
29#include <linux/ioport.h>
30#include <linux/netdevice.h>
31#include <linux/etherdevice.h>
32#include <linux/init.h>
33#include <linux/delay.h>
34
35#include <asm/system.h>
36#include <asm/io.h>
37
38#include "8390.h"
39
40#define DRV_NAME "hp-plus"
41
42
43static unsigned int hpplus_portlist[] __initdata =
44{0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71#define HP_ID 0x00
72#define HP_PAGING 0x02
73#define HPP_OPTION 0x04
74#define HPP_OUT_ADDR 0x08
75#define HPP_IN_ADDR 0x0A
76#define HP_DATAPORT 0x0c
77#define NIC_OFFSET 0x10
78#define HP_IO_EXTENT 32
79
80#define HP_START_PG 0x00
81#define HP_STOP_PG 0x80
82
83
84enum PageName {
85 Perf_Page = 0,
86 MAC_Page = 1,
87 HW_Page = 2,
88 LAN_Page = 4,
89 ID_Page = 6 };
90
91
92enum HP_Option {
93 NICReset = 1, ChipReset = 2,
94 EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
95 MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
96
97static int hpp_probe1(struct net_device *dev, int ioaddr);
98
99static void hpp_reset_8390(struct net_device *dev);
100static int hpp_open(struct net_device *dev);
101static int hpp_close(struct net_device *dev);
102static void hpp_mem_block_input(struct net_device *dev, int count,
103 struct sk_buff *skb, int ring_offset);
104static void hpp_mem_block_output(struct net_device *dev, int count,
105 const unsigned char *buf, int start_page);
106static void hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
107 int ring_page);
108static void hpp_io_block_input(struct net_device *dev, int count,
109 struct sk_buff *skb, int ring_offset);
110static void hpp_io_block_output(struct net_device *dev, int count,
111 const unsigned char *buf, int start_page);
112static void hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr,
113 int ring_page);
114
115
116
117
118
119static int __init do_hpp_probe(struct net_device *dev)
120{
121 int i;
122 int base_addr = dev->base_addr;
123 int irq = dev->irq;
124
125 if (base_addr > 0x1ff)
126 return hpp_probe1(dev, base_addr);
127 else if (base_addr != 0)
128 return -ENXIO;
129
130 for (i = 0; hpplus_portlist[i]; i++) {
131 if (hpp_probe1(dev, hpplus_portlist[i]) == 0)
132 return 0;
133 dev->irq = irq;
134 }
135
136 return -ENODEV;
137}
138
139#ifndef MODULE
140struct net_device * __init hp_plus_probe(int unit)
141{
142 struct net_device *dev = alloc_eip_netdev();
143 int err;
144
145 if (!dev)
146 return ERR_PTR(-ENOMEM);
147
148 sprintf(dev->name, "eth%d", unit);
149 netdev_boot_setup_check(dev);
150
151 err = do_hpp_probe(dev);
152 if (err)
153 goto out;
154 return dev;
155out:
156 free_netdev(dev);
157 return ERR_PTR(err);
158}
159#endif
160
161static const struct net_device_ops hpp_netdev_ops = {
162 .ndo_open = hpp_open,
163 .ndo_stop = hpp_close,
164 .ndo_start_xmit = eip_start_xmit,
165 .ndo_tx_timeout = eip_tx_timeout,
166 .ndo_get_stats = eip_get_stats,
167 .ndo_set_multicast_list = eip_set_multicast_list,
168 .ndo_validate_addr = eth_validate_addr,
169 .ndo_set_mac_address = eth_mac_addr,
170 .ndo_change_mtu = eth_change_mtu,
171#ifdef CONFIG_NET_POLL_CONTROLLER
172 .ndo_poll_controller = eip_poll,
173#endif
174};
175
176
177
178static int __init hpp_probe1(struct net_device *dev, int ioaddr)
179{
180 int i, retval;
181 unsigned char checksum = 0;
182 const char name[] = "HP-PC-LAN+";
183 int mem_start;
184 static unsigned version_printed;
185
186 if (!request_region(ioaddr, HP_IO_EXTENT, DRV_NAME))
187 return -EBUSY;
188
189
190 if (inw(ioaddr + HP_ID) != 0x4850 ||
191 (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300) {
192 retval = -ENODEV;
193 goto out;
194 }
195
196 if (ei_debug && version_printed++ == 0)
197 printk(version);
198
199 printk("%s: %s at %#3x, ", dev->name, name, ioaddr);
200
201
202 outw(MAC_Page, ioaddr + HP_PAGING);
203
204 for(i = 0; i < ETHER_ADDR_LEN; i++) {
205 unsigned char inval = inb(ioaddr + 8 + i);
206 dev->dev_addr[i] = inval;
207 checksum += inval;
208 }
209 checksum += inb(ioaddr + 14);
210
211 printk("%pM", dev->dev_addr);
212
213 if (checksum != 0xff) {
214 printk(" bad checksum %2.2x.\n", checksum);
215 retval = -ENODEV;
216 goto out;
217 } else {
218
219 outw(ID_Page, ioaddr + HP_PAGING);
220 printk(" ID %4.4x", inw(ioaddr + 12));
221 }
222
223
224 outw(HW_Page, ioaddr + HP_PAGING);
225 {
226 int irq = inb(ioaddr + 13) & 0x0f;
227 int option = inw(ioaddr + HPP_OPTION);
228
229 dev->irq = irq;
230 if (option & MemEnable) {
231 mem_start = inw(ioaddr + 9) << 8;
232 printk(", IRQ %d, memory address %#x.\n", irq, mem_start);
233 } else {
234 mem_start = 0;
235 printk(", IRQ %d, programmed-I/O mode.\n", irq);
236 }
237 }
238
239
240 outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
241
242
243 dev->base_addr = ioaddr + NIC_OFFSET;
244
245 dev->netdev_ops = &hpp_netdev_ops;
246
247 ei_status.name = name;
248 ei_status.word16 = 0;
249 ei_status.tx_start_page = HP_START_PG;
250 ei_status.rx_start_page = HP_START_PG + TX_PAGES/2;
251 ei_status.stop_page = HP_STOP_PG;
252
253 ei_status.reset_8390 = &hpp_reset_8390;
254 ei_status.block_input = &hpp_io_block_input;
255 ei_status.block_output = &hpp_io_block_output;
256 ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
257
258
259 if (mem_start) {
260 ei_status.block_input = &hpp_mem_block_input;
261 ei_status.block_output = &hpp_mem_block_output;
262 ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
263 dev->mem_start = mem_start;
264 ei_status.mem = ioremap(mem_start,
265 (HP_STOP_PG - HP_START_PG)*256);
266 if (!ei_status.mem) {
267 retval = -ENOMEM;
268 goto out;
269 }
270 ei_status.rmem_start = dev->mem_start + TX_PAGES/2*256;
271 dev->mem_end = ei_status.rmem_end
272 = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
273 }
274
275 outw(Perf_Page, ioaddr + HP_PAGING);
276 NS8390p_init(dev, 0);
277
278 outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
279
280 retval = register_netdev(dev);
281 if (retval)
282 goto out1;
283 return 0;
284out1:
285 iounmap(ei_status.mem);
286out:
287 release_region(ioaddr, HP_IO_EXTENT);
288 return retval;
289}
290
291static int
292hpp_open(struct net_device *dev)
293{
294 int ioaddr = dev->base_addr - NIC_OFFSET;
295 int option_reg;
296 int retval;
297
298 if ((retval = request_irq(dev->irq, eip_interrupt, 0, dev->name, dev))) {
299 return retval;
300 }
301
302
303 option_reg = inw(ioaddr + HPP_OPTION);
304 outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
305 udelay(5);
306
307 outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
308
309
310 outw(HW_Page, ioaddr + HP_PAGING);
311 outw((HP_START_PG + TX_PAGES/2) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
312
313
314 outw(Perf_Page, ioaddr + HP_PAGING);
315
316 return eip_open(dev);
317}
318
319static int
320hpp_close(struct net_device *dev)
321{
322 int ioaddr = dev->base_addr - NIC_OFFSET;
323 int option_reg = inw(ioaddr + HPP_OPTION);
324
325 free_irq(dev->irq, dev);
326 eip_close(dev);
327 outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
328 ioaddr + HPP_OPTION);
329
330 return 0;
331}
332
333static void
334hpp_reset_8390(struct net_device *dev)
335{
336 int ioaddr = dev->base_addr - NIC_OFFSET;
337 int option_reg = inw(ioaddr + HPP_OPTION);
338
339 if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
340
341 outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
342
343 udelay(5);
344 ei_status.txing = 0;
345 outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
346
347 udelay(5);
348
349
350 if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
351 printk("%s: hp_reset_8390() did not complete.\n", dev->name);
352
353 if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
354}
355
356
357
358
359static void
360hpp_io_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
361{
362 int ioaddr = dev->base_addr - NIC_OFFSET;
363
364 outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
365 insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
366}
367
368
369
370static void
371hpp_io_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
372{
373 int ioaddr = dev->base_addr - NIC_OFFSET;
374 char *buf = skb->data;
375
376 outw(ring_offset, ioaddr + HPP_IN_ADDR);
377 insw(ioaddr + HP_DATAPORT, buf, count>>1);
378 if (count & 0x01)
379 buf[count-1] = inw(ioaddr + HP_DATAPORT);
380}
381
382
383
384static void
385hpp_mem_get_8390_hdr(struct net_device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
386{
387 int ioaddr = dev->base_addr - NIC_OFFSET;
388 int option_reg = inw(ioaddr + HPP_OPTION);
389
390 outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
391 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
392 memcpy_fromio(hdr, ei_status.mem, sizeof(struct e8390_pkt_hdr));
393 outw(option_reg, ioaddr + HPP_OPTION);
394 hdr->count = (le16_to_cpu(hdr->count) + 3) & ~3;
395}
396
397static void
398hpp_mem_block_input(struct net_device *dev, int count, struct sk_buff *skb, int ring_offset)
399{
400 int ioaddr = dev->base_addr - NIC_OFFSET;
401 int option_reg = inw(ioaddr + HPP_OPTION);
402
403 outw(ring_offset, ioaddr + HPP_IN_ADDR);
404
405 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
406
407
408
409
410
411 memcpy_fromio(skb->data, ei_status.mem, count);
412 outw(option_reg, ioaddr + HPP_OPTION);
413}
414
415
416
417static void
418hpp_io_block_output(struct net_device *dev, int count,
419 const unsigned char *buf, int start_page)
420{
421 int ioaddr = dev->base_addr - NIC_OFFSET;
422 outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
423 outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2);
424}
425
426static void
427hpp_mem_block_output(struct net_device *dev, int count,
428 const unsigned char *buf, int start_page)
429{
430 int ioaddr = dev->base_addr - NIC_OFFSET;
431 int option_reg = inw(ioaddr + HPP_OPTION);
432
433 outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
434 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
435 memcpy_toio(ei_status.mem, buf, (count + 3) & ~3);
436 outw(option_reg, ioaddr + HPP_OPTION);
437}
438
439
440#ifdef MODULE
441#define MAX_HPP_CARDS 4
442static struct net_device *dev_hpp[MAX_HPP_CARDS];
443static int io[MAX_HPP_CARDS];
444static int irq[MAX_HPP_CARDS];
445
446module_param_array(io, int, NULL, 0);
447module_param_array(irq, int, NULL, 0);
448MODULE_PARM_DESC(io, "I/O port address(es)");
449MODULE_PARM_DESC(irq, "IRQ number(s); ignored if properly detected");
450MODULE_DESCRIPTION("HP PC-LAN+ ISA ethernet driver");
451MODULE_LICENSE("GPL");
452
453
454
455int __init
456init_module(void)
457{
458 struct net_device *dev;
459 int this_dev, found = 0;
460
461 for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
462 if (io[this_dev] == 0) {
463 if (this_dev != 0) break;
464 printk(KERN_NOTICE "hp-plus.c: Presently autoprobing (not recommended) for a single card.\n");
465 }
466 dev = alloc_eip_netdev();
467 if (!dev)
468 break;
469 dev->irq = irq[this_dev];
470 dev->base_addr = io[this_dev];
471 if (do_hpp_probe(dev) == 0) {
472 dev_hpp[found++] = dev;
473 continue;
474 }
475 free_netdev(dev);
476 printk(KERN_WARNING "hp-plus.c: No HP-Plus card found (i/o = 0x%x).\n", io[this_dev]);
477 break;
478 }
479 if (found)
480 return 0;
481 return -ENXIO;
482}
483
484static void cleanup_card(struct net_device *dev)
485{
486
487 iounmap(ei_status.mem);
488 release_region(dev->base_addr - NIC_OFFSET, HP_IO_EXTENT);
489}
490
491void __exit
492cleanup_module(void)
493{
494 int this_dev;
495
496 for (this_dev = 0; this_dev < MAX_HPP_CARDS; this_dev++) {
497 struct net_device *dev = dev_hpp[this_dev];
498 if (dev) {
499 unregister_netdev(dev);
500 cleanup_card(dev);
501 free_netdev(dev);
502 }
503 }
504}
505#endif
506