This source file includes following definitions.
- hp_plus_probe
- hpp_probe1
- hpp_open
- hpp_close
- hpp_reset_8390
- hpp_io_get_8390_hdr
- hpp_io_block_input
- hpp_mem_get_8390_hdr
- hpp_mem_block_input
- hpp_io_block_output
- hpp_mem_block_output
- init_module
- cleanup_module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 static const char *version =
22 "hp-plus.c:v1.10 9/24/94 Donald Becker (becker@cesdis.gsfc.nasa.gov)\n";
23
24 #ifdef MODULE
25 #include <linux/module.h>
26 #include <linux/version.h>
27 #endif
28
29 #include <linux/string.h>
30 #include <linux/kernel.h>
31 #include <linux/sched.h>
32 #include <linux/errno.h>
33 #include <linux/ioport.h>
34 #include <linux/netdevice.h>
35 #include <linux/etherdevice.h>
36
37 #include <asm/system.h>
38 #include <asm/io.h>
39
40
41 #include "8390.h"
42
43
44 static unsigned int hpplus_portlist[] =
45 {0x200, 0x240, 0x280, 0x2C0, 0x300, 0x320, 0x340, 0};
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
72 #define HP_ID 0x00
73 #define HP_PAGING 0x02
74 #define HPP_OPTION 0x04
75 #define HPP_OUT_ADDR 0x08
76 #define HPP_IN_ADDR 0x0A
77 #define HP_DATAPORT 0x0c
78 #define NIC_OFFSET 0x10
79 #define HP_IO_EXTENT 32
80
81 #define HP_START_PG 0x00
82 #define HP_STOP_PG 0x80
83
84
85 enum PageName {
86 Perf_Page = 0,
87 MAC_Page = 1,
88 HW_Page = 2,
89 LAN_Page = 4,
90 ID_Page = 6 };
91
92
93 enum HP_Option {
94 NICReset = 1, ChipReset = 2,
95 EnableIRQ = 4, FakeIntr = 8, BootROMEnb = 0x10, IOEnb = 0x20,
96 MemEnable = 0x40, ZeroWait = 0x80, MemDisable = 0x1000, };
97
98 int hp_plus_probe(struct device *dev);
99 int hpp_probe1(struct device *dev, int ioaddr);
100
101 static void hpp_reset_8390(struct device *dev);
102 static int hpp_open(struct device *dev);
103 static int hpp_close(struct device *dev);
104 static void hpp_mem_block_input(struct device *dev, int count,
105 struct sk_buff *skb, int ring_offset);
106 static void hpp_mem_block_output(struct device *dev, int count,
107 const unsigned char *buf, const start_page);
108 static void hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
109 int ring_page);
110 static void hpp_io_block_input(struct device *dev, int count,
111 struct sk_buff *skb, int ring_offset);
112 static void hpp_io_block_output(struct device *dev, int count,
113 const unsigned char *buf, const start_page);
114 static void hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr,
115 int ring_page);
116
117
118
119
120 #ifdef HAVE_DEVLIST
121
122
123 struct netdev_entry hpplus_drv =
124 {"hpplus", hpp_probe1, HP_IO_EXTENT, hpplus_portlist};
125 #else
126
127 int hp_plus_probe(struct device *dev)
128 {
129 int i;
130 int base_addr = dev ? dev->base_addr : 0;
131
132 if (base_addr > 0x1ff)
133 return hpp_probe1(dev, base_addr);
134 else if (base_addr != 0)
135 return ENXIO;
136
137 for (i = 0; hpplus_portlist[i]; i++) {
138 int ioaddr = hpplus_portlist[i];
139 if (check_region(ioaddr, HP_IO_EXTENT))
140 continue;
141 if (hpp_probe1(dev, ioaddr) == 0)
142 return 0;
143 }
144
145 return ENODEV;
146 }
147 #endif
148
149
150 int hpp_probe1(struct device *dev, int ioaddr)
151 {
152 int i;
153 unsigned char checksum = 0;
154 const char *name = "HP-PC-LAN+";
155 int mem_start;
156
157
158 if (inw(ioaddr + HP_ID) != 0x4850
159 || (inw(ioaddr + HP_PAGING) & 0xfff0) != 0x5300)
160 return ENODEV;
161
162 if (dev == NULL)
163 dev = init_etherdev(0, sizeof(struct ei_device));
164
165 printk("%s: %s at %#3x,", dev->name, name, ioaddr);
166
167
168 outw(MAC_Page, ioaddr + HP_PAGING);
169
170 for(i = 0; i < ETHER_ADDR_LEN; i++) {
171 unsigned char inval = inb(ioaddr + 8 + i);
172 dev->dev_addr[i] = inval;
173 checksum += inval;
174 printk(" %2.2x", inval);
175 }
176 checksum += inb(ioaddr + 14);
177
178 if (checksum != 0xff) {
179 printk(" bad checksum %2.2x.\n", checksum);
180 return ENODEV;
181 } else {
182
183 outw(ID_Page, ioaddr + HP_PAGING);
184 printk(" ID %4.4x", inw(ioaddr + 12));
185 }
186
187
188 request_region(ioaddr, HP_IO_EXTENT,"hp-plus");
189
190
191 outw(HW_Page, ioaddr + HP_PAGING);
192 {
193 int irq = inb(ioaddr + 13) & 0x0f;
194 int option = inw(ioaddr + HPP_OPTION);
195
196 dev->irq = irq;
197 if (option & MemEnable) {
198 mem_start = inw(ioaddr + 9) << 8;
199 printk(", IRQ %d, memory address %#x.\n", irq, mem_start);
200 } else {
201 mem_start = 0;
202 printk(", IRQ %d, programmed-I/O mode.\n", irq);
203 }
204 }
205
206 printk( "%s%s", KERN_INFO, version);
207
208
209 outw((HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
210
211
212 dev->base_addr = ioaddr + NIC_OFFSET;
213
214 ethdev_init(dev);
215
216 dev->open = &hpp_open;
217 dev->stop = &hpp_close;
218
219 ei_status.name = name;
220 ei_status.word16 = 0;
221 ei_status.tx_start_page = HP_START_PG;
222 ei_status.rx_start_page = HP_START_PG + TX_2X_PAGES;
223 ei_status.stop_page = HP_STOP_PG;
224
225 ei_status.reset_8390 = &hpp_reset_8390;
226 ei_status.block_input = &hpp_io_block_input;
227 ei_status.block_output = &hpp_io_block_output;
228 ei_status.get_8390_hdr = &hpp_io_get_8390_hdr;
229
230
231 if (mem_start) {
232 ei_status.block_input = &hpp_mem_block_input;
233 ei_status.block_output = &hpp_mem_block_output;
234 ei_status.get_8390_hdr = &hpp_mem_get_8390_hdr;
235 dev->mem_start = mem_start;
236 dev->rmem_start = dev->mem_start + TX_2X_PAGES*256;
237 dev->mem_end = dev->rmem_end
238 = dev->mem_start + (HP_STOP_PG - HP_START_PG)*256;
239 }
240
241 outw(Perf_Page, ioaddr + HP_PAGING);
242 NS8390_init(dev, 0);
243
244 outw(inw(ioaddr + HPP_OPTION) & ~EnableIRQ, ioaddr + HPP_OPTION);
245
246 return 0;
247 }
248
249 static int
250 hpp_open(struct device *dev)
251 {
252 int ioaddr = dev->base_addr - NIC_OFFSET;
253 int option_reg;
254
255 if (request_irq(dev->irq, &ei_interrupt, 0, "hp-plus")) {
256 return -EAGAIN;
257 }
258
259
260 option_reg = inw(ioaddr + HPP_OPTION);
261 outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
262 SLOW_DOWN_IO; SLOW_DOWN_IO;
263
264 outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
265
266
267 outw(HW_Page, ioaddr + HP_PAGING);
268 outw((HP_START_PG + TX_2X_PAGES) | ((HP_STOP_PG - 1) << 8), ioaddr + 14);
269
270
271 outw(Perf_Page, ioaddr + HP_PAGING);
272
273 return ei_open(dev);
274 }
275
276 static int
277 hpp_close(struct device *dev)
278 {
279 int ioaddr = dev->base_addr - NIC_OFFSET;
280 int option_reg = inw(ioaddr + HPP_OPTION);
281
282 free_irq(dev->irq);
283 irq2dev_map[dev->irq] = NULL;
284 NS8390_init(dev, 0);
285 outw((option_reg & ~EnableIRQ) | MemDisable | NICReset | ChipReset,
286 ioaddr + HPP_OPTION);
287
288 return 0;
289 }
290
291 static void
292 hpp_reset_8390(struct device *dev)
293 {
294 int ioaddr = dev->base_addr - NIC_OFFSET;
295 int option_reg = inw(ioaddr + HPP_OPTION);
296
297 if (ei_debug > 1) printk("resetting the 8390 time=%ld...", jiffies);
298
299 outw(option_reg & ~(NICReset + ChipReset), ioaddr + HPP_OPTION);
300
301 SLOW_DOWN_IO;
302 SLOW_DOWN_IO;
303 ei_status.txing = 0;
304 outw(option_reg | (EnableIRQ + NICReset + ChipReset), ioaddr + HPP_OPTION);
305
306 SLOW_DOWN_IO; SLOW_DOWN_IO;
307
308
309 if ((inb_p(ioaddr+NIC_OFFSET+EN0_ISR) & ENISR_RESET) == 0)
310 printk("%s: hp_reset_8390() did not complete.\n", dev->name);
311
312 if (ei_debug > 1) printk("8390 reset done (%ld).", jiffies);
313 return;
314 }
315
316
317
318
319 static void
320 hpp_io_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
321 {
322 int ioaddr = dev->base_addr - NIC_OFFSET;
323
324 outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
325 insw(ioaddr + HP_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
326 }
327
328
329
330 static void
331 hpp_io_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
332 {
333 int ioaddr = dev->base_addr - NIC_OFFSET;
334 char *buf = skb->data;
335
336 outw(ring_offset, ioaddr + HPP_IN_ADDR);
337 insw(ioaddr + HP_DATAPORT, buf, count>>1);
338 if (count & 0x01)
339 buf[count-1] = inw(ioaddr + HP_DATAPORT);
340 }
341
342
343
344 static void
345 hpp_mem_get_8390_hdr(struct device *dev, struct e8390_pkt_hdr *hdr, int ring_page)
346 {
347 int ioaddr = dev->base_addr - NIC_OFFSET;
348 int option_reg = inw(ioaddr + HPP_OPTION);
349
350 outw((ring_page<<8), ioaddr + HPP_IN_ADDR);
351 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
352 memcpy_fromio(hdr, dev->mem_start, sizeof(struct e8390_pkt_hdr));
353 outw(option_reg, ioaddr + HPP_OPTION);
354 hdr->count = (hdr->count + 3) & ~3;
355 }
356
357 static void
358 hpp_mem_block_input(struct device *dev, int count, struct sk_buff *skb, int ring_offset)
359 {
360 int ioaddr = dev->base_addr - NIC_OFFSET;
361 int option_reg = inw(ioaddr + HPP_OPTION);
362
363 outw(ring_offset, ioaddr + HPP_IN_ADDR);
364
365 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
366
367
368
369
370
371 memcpy_fromio(skb->data, dev->mem_start, count);
372 outw(option_reg, ioaddr + HPP_OPTION);
373 }
374
375
376
377 static void
378 hpp_io_block_output(struct device *dev, int count,
379 const unsigned char *buf, const start_page)
380 {
381 int ioaddr = dev->base_addr - NIC_OFFSET;
382 outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
383 outsl(ioaddr + HP_DATAPORT, buf, (count+3)>>2);
384 return;
385 }
386
387 static void
388 hpp_mem_block_output(struct device *dev, int count,
389 const unsigned char *buf, const start_page)
390 {
391 int ioaddr = dev->base_addr - NIC_OFFSET;
392 int option_reg = inw(ioaddr + HPP_OPTION);
393
394 outw(start_page << 8, ioaddr + HPP_OUT_ADDR);
395 outw(option_reg & ~(MemDisable + BootROMEnb), ioaddr + HPP_OPTION);
396 memcpy_toio(dev->mem_start, buf, (count + 3) & ~3);
397 outw(option_reg, ioaddr + HPP_OPTION);
398
399 return;
400 }
401
402 #ifdef MODULE
403 char kernel_version[] = UTS_RELEASE;
404 static char devicename[9] = { 0, };
405 static struct device dev_hp = {
406 devicename,
407 0, 0, 0, 0,
408 0, 0,
409 0, 0, 0, NULL, hp_plus_probe };
410
411 int io = 0x200;
412 int irq = 0;
413
414 int init_module(void)
415 {
416 if (io == 0)
417 printk("HP-plus: You should not use auto-probing with insmod!\n");
418 dev_hp.base_addr = io;
419 dev_hp.irq = irq;
420 if (register_netdev(&dev_hp) != 0) {
421 printk("HP-plus: register_netdev() returned non-zero.\n");
422 return -EIO;
423 }
424 return 0;
425 }
426
427 void
428 cleanup_module(void)
429 {
430 if (MOD_IN_USE)
431 printk("HP-plus: device busy, remove delayed\n");
432 else
433 {
434 int ioaddr = dev_hp.base_addr - NIC_OFFSET;
435
436 unregister_netdev(&dev_hp);
437
438
439 release_region(ioaddr, HP_IO_EXTENT);
440 }
441 }
442 #endif
443
444
445
446
447
448
449
450
451
452