|
|
1.1 root 1: /*
2: * hp100.c: Hewlett Packard HP10/100VG ANY LAN ethernet driver for Linux.
3: *
4: * Author: Jaroslav Kysela, <[email protected]>
5: *
6: * Supports only the following Hewlett Packard cards:
7: *
8: * HP J2577 10/100 EISA card with REVA Cascade chip
9: * HP J2573 10/100 ISA card with REVA Cascade chip
10: * HP 27248B 10 only EISA card with Cascade chip
11: * HP J2577 10/100 EISA card with Cascade chip
12: * HP J2573 10/100 ISA card with Cascade chip
13: * HP J2585 10/100 PCI card
14: *
15: * Other ATT2MD01 Chip based boards might be supported in the future
16: * (there are some minor changes needed).
17: *
18: * This driver is based on the 'hpfepkt' crynwr packet driver.
19: *
20: * This source/code is public free; you can distribute it and/or modify
21: * it under terms of the GNU General Public License (published by the
22: * Free Software Foundation) either version two of this License, or any
23: * later version.
24: * ----------------------------------------------------------------------------
25: *
26: * Note: Some routines (interrupt handling, transmit) assumes that
27: * there is the PERFORMANCE page selected...
28: *
29: * ----------------------------------------------------------------------------
30: *
31: * If you are going to use the module version of this driver, you may
32: * change this values at the "insert time" :
33: *
34: * Variable Description
35: *
36: * hp100_rx_ratio Range 1-99 - onboard memory used for RX
37: * packets in %.
38: * hp100_priority_tx If this variable is nonzero - all outgoing
39: * packets will be transmitted as priority.
40: * hp100_port Adapter port (for example 0x380).
41: *
42: * ----------------------------------------------------------------------------
43: * MY BEST REGARDS GOING TO:
44: *
45: * IPEX s.r.o which lend me two HP J2573 cards and
46: * the HP AdvanceStack 100VG Hub-15 for debugging.
47: *
48: * Russel Nellson <[email protected]> for help with obtaining sources
49: * of the 'hpfepkt' packet driver.
50: *
51: * Also thanks to Abacus Electric s.r.o which let me to use their
52: * motherboard for my second computer.
53: *
54: * ----------------------------------------------------------------------------
55: *
56: * TO DO:
57: * ======
58: * - ioctl handling - some runtime setup things
59: * - 100Mb/s Voice Grade AnyLAN network adapter/hub services support
60: * - 802.5 frames
61: * - promiscuous mode
62: * - bridge mode
63: * - cascaded repeater mode
64: * - 100Mbit MAC
65: *
66: * Revision history:
67: * =================
68: *
69: * Version Date Description
70: *
71: * 0.1 14-May-95 Initial writing. ALPHA code was released.
72: * Only HP J2573 on 10Mb/s (two machines) tested.
73: * 0.11 14-Jun-95 Reset interface bug fixed?
74: * Little bug in hp100_close function fixed.
75: * 100Mb/s connection debugged.
76: * 0.12 14-Jul-95 Link down is now handled better.
77: * 0.20 01-Aug-95 Added PCI support for HP J2585A card.
78: * Statistics bug fixed.
79: * 0.21 04-Aug-95 Memory mapped access support for PCI card.
80: * Added priority transmit support for 100Mb/s
81: * Voice Grade AnyLAN network.
82: *
83: */
84:
85: #include <linux/module.h>
86:
87: #include <linux/kernel.h>
88: #include <linux/sched.h>
89: #include <linux/string.h>
90: #include <linux/errno.h>
91: #include <linux/ioport.h>
92: #include <linux/malloc.h>
93: #include <linux/interrupt.h>
94: #include <linux/pci.h>
95: #include <linux/bios32.h>
96: #include <asm/bitops.h>
97: #include <asm/io.h>
98:
99: #include <linux/netdevice.h>
100: #include <linux/etherdevice.h>
101: #include <linux/skbuff.h>
102:
103: #include <linux/types.h>
104: #include <linux/config.h> /* for CONFIG_PCI */
105:
106: #include "hp100.h"
107:
108: /*
109: * defines
110: */
111:
112: #define HP100_BUS_ISA 0
113: #define HP100_BUS_EISA 1
114: #define HP100_BUS_PCI 2
115:
116: #define HP100_REGION_SIZE 0x20
117:
118: #define HP100_MAX_PACKET_SIZE (1536+4)
119: #define HP100_MIN_PACKET_SIZE 60
120:
121: #ifndef HP100_DEFAULT_RX_RATIO
122: /* default - 65% onboard memory on the card are used for RX packets */
123: #define HP100_DEFAULT_RX_RATIO 65
124: #endif
125:
126: #ifndef HP100_DEFAULT_PRIORITY_TX
127: /* default - don't enable transmit outgoing packets as priority */
128: #define HP100_DEFAULT_PRIORITY_TX 0
129: #endif
130:
131: #ifdef MACH
132: #define HP100_IO_MAPPED
133: #endif
134:
135: /*
136: * structures
137: */
138:
139: struct hp100_eisa_id {
140: u_int id;
141: const char *name;
142: u_char bus;
143: };
144:
145: struct hp100_private {
146: struct hp100_eisa_id *id;
147: u_short soft_model;
148: u_int memory_size;
149: u_short rx_ratio; /* 1 - 99 */
150: u_short priority_tx; /* != 0 - priority tx */
151: short mem_mapped; /* memory mapped access */
152: u_char *mem_ptr_virt; /* virtual memory mapped area, maybe NULL */
153: u_char *mem_ptr_phys; /* physical memory mapped area */
154: short lan_type; /* 10Mb/s, 100Mb/s or -1 (error) */
155: int hub_status; /* login to hub was successfull? */
156: u_char mac1_mode;
157: u_char mac2_mode;
158: struct enet_statistics stats;
159: };
160:
161: /*
162: * variables
163: */
164:
165: static struct hp100_eisa_id hp100_eisa_ids[] = {
166:
167: /* 10/100 EISA card with REVA Cascade chip */
168: { 0x080F1F022, "HP J2577 rev A", HP100_BUS_EISA },
169:
170: /* 10/100 ISA card with REVA Cascade chip */
171: { 0x050F1F022, "HP J2573 rev A", HP100_BUS_ISA },
172:
173: /* 10 only EISA card with Cascade chip */
174: { 0x02019F022, "HP 27248B", HP100_BUS_EISA },
175:
176: /* 10/100 EISA card with Cascade chip */
177: { 0x04019F022, "HP J2577", HP100_BUS_EISA },
178:
179: /* 10/100 ISA card with Cascade chip */
180: { 0x05019F022, "HP J2573", HP100_BUS_ISA },
181:
182: /* 10/100 PCI card */
183: /* Note: ID for this card is same as PCI vendor/device numbers. */
184: { 0x01030103c, "HP J2585", HP100_BUS_PCI },
185: };
186:
187: int hp100_rx_ratio = HP100_DEFAULT_RX_RATIO;
188: int hp100_priority_tx = HP100_DEFAULT_PRIORITY_TX;
189:
190: /*
191: * prototypes
192: */
193:
194: static int hp100_probe1( struct device *dev, int ioaddr, int bus );
195: static int hp100_open( struct device *dev );
196: static int hp100_close( struct device *dev );
197: static int hp100_start_xmit( struct sk_buff *skb, struct device *dev );
198: static void hp100_rx( struct device *dev );
199: static struct enet_statistics *hp100_get_stats( struct device *dev );
200: static void hp100_update_stats( struct device *dev );
201: static void hp100_clear_stats( int ioaddr );
202: static void hp100_set_multicast_list( struct device *dev);
203: static void hp100_interrupt( int irq, struct pt_regs *regs );
204:
205: static void hp100_start_interface( struct device *dev );
206: static void hp100_stop_interface( struct device *dev );
207: static void hp100_load_eeprom( struct device *dev );
208: static int hp100_sense_lan( struct device *dev );
209: static int hp100_login_to_vg_hub( struct device *dev );
210: static int hp100_down_vg_link( struct device *dev );
211:
212: /*
213: * probe functions
214: */
215:
216: int hp100_probe( struct device *dev )
217: {
218: int base_addr = dev ? dev -> base_addr : 0;
219: int ioaddr;
220: #ifdef CONFIG_PCI
221: int pci_start_index = 0;
222: #endif
223:
224: if ( base_addr > 0xff ) /* Check a single specified location. */
225: {
226: if ( check_region( base_addr, HP100_REGION_SIZE ) ) return -EINVAL;
227: if ( base_addr < 0x400 )
228: return hp100_probe1( dev, base_addr, HP100_BUS_ISA );
229: else
230: return hp100_probe1( dev, base_addr, HP100_BUS_EISA );
231: }
232: else
233: #ifdef CONFIG_PCI
234: if ( base_addr > 0 && base_addr < 8 + 1 )
235: pci_start_index = 0x100 | ( base_addr - 1 );
236: else
237: #endif
238: if ( base_addr != 0 ) return -ENXIO;
239:
240: /* at first - scan PCI bus(es) */
241:
242: #ifdef CONFIG_PCI
243: if ( pcibios_present() )
244: {
245: int pci_index;
246:
247: #ifdef HP100_DEBUG_PCI
248: printk( "hp100: PCI BIOS is present, checking for devices..\n" );
249: #endif
250: for ( pci_index = pci_start_index & 7; pci_index < 8; pci_index++ )
251: {
252: u_char pci_bus, pci_device_fn;
253: u_short pci_command;
254:
255: if ( pcibios_find_device( PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_J2585A,
256: pci_index, &pci_bus,
257: &pci_device_fn ) != 0 ) break;
258: pcibios_read_config_dword( pci_bus, pci_device_fn,
259: PCI_BASE_ADDRESS_0, &ioaddr );
260:
261: ioaddr &= ~3; /* remove I/O space marker in bit 0. */
262:
263: if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
264:
265: pcibios_read_config_word( pci_bus, pci_device_fn,
266: PCI_COMMAND, &pci_command );
267: if ( !( pci_command & PCI_COMMAND_MASTER ) )
268: {
269: #ifdef HP100_DEBUG_PCI
270: printk( "hp100: PCI Master Bit has not been set. Setting...\n" );
271: #endif
272: pci_command |= PCI_COMMAND_MASTER;
273: pcibios_write_config_word( pci_bus, pci_device_fn,
274: PCI_COMMAND, pci_command );
275: }
276: #ifdef HP100_DEBUG_PCI
277: printk( "hp100: PCI adapter found at 0x%x\n", ioaddr );
278: #endif
279: if ( hp100_probe1( dev, ioaddr, HP100_BUS_PCI ) == 0 ) return 0;
280: }
281: }
282: if ( pci_start_index > 0 ) return -ENODEV;
283: #endif /* CONFIG_PCI */
284:
285: /* at second - probe all EISA possible port regions (if EISA bus present) */
286:
287: for ( ioaddr = 0x1c38; EISA_bus && ioaddr < 0x10000; ioaddr += 0x400 )
288: {
289: if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
290: if ( hp100_probe1( dev, ioaddr, HP100_BUS_EISA ) == 0 ) return 0;
291: }
292:
293: /* at third - probe all ISA possible port regions */
294:
295: for ( ioaddr = 0x100; ioaddr < 0x400; ioaddr += 0x20 )
296: {
297: if ( check_region( ioaddr, HP100_REGION_SIZE ) ) continue;
298: if ( hp100_probe1( dev, ioaddr, HP100_BUS_ISA ) == 0 ) return 0;
299: }
300:
301: return -ENODEV;
302: }
303:
304: static int hp100_probe1( struct device *dev, int ioaddr, int bus )
305: {
306: int i;
307: u_char uc, uc_1;
308: u_int eisa_id;
309: short mem_mapped;
310: u_char *mem_ptr_phys, *mem_ptr_virt;
311: struct hp100_private *lp;
312: struct hp100_eisa_id *eid;
313:
314: if ( dev == NULL )
315: {
316: #ifdef HP100_DEBUG
317: printk( "hp100_probe1: dev == NULL ?\n" );
318: #endif
319: return EIO;
320: }
321:
322: if ( bus != HP100_BUS_PCI ) /* don't check PCI cards again */
323: if ( inb( ioaddr + 0 ) != HP100_HW_ID_0 ||
324: inb( ioaddr + 1 ) != HP100_HW_ID_1 ||
325: ( inb( ioaddr + 2 ) & 0xf0 ) != HP100_HW_ID_2_REVA ||
326: inb( ioaddr + 3 ) != HP100_HW_ID_3 )
327: return -ENODEV;
328:
329: dev -> base_addr = ioaddr;
330:
331: #ifdef HP100_DEBUG_PROBE1
332: printk( "hp100_probe1: card found at port 0x%x\n", ioaddr );
333: #endif
334:
335: hp100_page( ID_MAC_ADDR );
336: for ( i = uc = eisa_id = 0; i < 4; i++ )
337: {
338: eisa_id >>= 8;
339: uc_1 = hp100_inb( BOARD_ID + i );
340: eisa_id |= uc_1 << 24;
341: uc += uc_1;
342: }
343: uc += hp100_inb( BOARD_ID + 4 );
344:
345: #ifdef HP100_DEBUG_PROBE1
346: printk( "hp100_probe1: EISA ID = 0x%08x checksum = 0x%02x\n", eisa_id, uc );
347: #endif
348:
349: if ( uc != 0xff ) /* bad checksum? */
350: {
351: printk( "hp100_probe: bad EISA ID checksum at base port 0x%x\n", ioaddr );
352: return -ENODEV;
353: }
354:
355: for ( i = 0; i < sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ); i++ )
356: if ( ( hp100_eisa_ids[ i ].id & 0xf0ffffff ) == ( eisa_id & 0xf0ffffff ) )
357: break;
358: if ( i >= sizeof( hp100_eisa_ids ) / sizeof( struct hp100_eisa_id ) )
359: {
360: printk( "hp100_probe1: card at port 0x%x isn't known (id = 0x%x)\n", ioaddr, eisa_id );
361: return -ENODEV;
362: }
363: eid = &hp100_eisa_ids[ i ];
364: if ( ( eid -> id & 0x0f000000 ) < ( eisa_id & 0x0f000000 ) )
365: {
366: printk( "hp100_probe1: newer version of card %s at port 0x%x - unsupported\n",
367: eid -> name, ioaddr );
368: return -ENODEV;
369: }
370:
371: for ( i = uc = 0; i < 7; i++ )
372: uc += hp100_inb( LAN_ADDR + i );
373: if ( uc != 0xff )
374: {
375: printk( "hp100_probe1: bad lan address checksum (card %s at port 0x%x)\n",
376: eid -> name, ioaddr );
377: return -EIO;
378: }
379:
380: #ifndef HP100_IO_MAPPED
381: hp100_page( HW_MAP );
382: mem_mapped = ( hp100_inw( OPTION_LSW ) &
383: ( HP100_MEM_EN | HP100_BM_WRITE | HP100_BM_READ ) ) != 0;
384: mem_ptr_phys = mem_ptr_virt = NULL;
385: if ( mem_mapped )
386: {
387: mem_ptr_phys = (u_char *)( hp100_inw( MEM_MAP_LSW ) |
388: ( hp100_inw( MEM_MAP_MSW ) << 16 ) );
389: (u_int)mem_ptr_phys &= ~0x1fff; /* 8k aligment */
390: if ( bus == HP100_BUS_ISA && ( (u_long)mem_ptr_phys & ~0xfffff ) != 0 )
391: {
392: mem_ptr_phys = NULL;
393: mem_mapped = 0;
394: }
395: if ( mem_mapped && bus == HP100_BUS_PCI )
396: {
397: if ( ( mem_ptr_virt = vremap( (u_long)mem_ptr_phys, 0x2000 ) ) == NULL )
398: {
399: printk( "hp100: vremap for high PCI memory at 0x%lx failed\n", (u_long)mem_ptr_phys );
400: mem_ptr_phys = NULL;
401: mem_mapped = 0;
402: }
403: }
404: }
405: #else
406: mem_mapped = 0;
407: mem_ptr_phys = mem_ptr_virt = NULL;
408: #endif
409:
410: if ( ( dev -> priv = kmalloc( sizeof( struct hp100_private ), GFP_KERNEL ) ) == NULL )
411: return -ENOMEM;
412: memset( dev -> priv, 0, sizeof( struct hp100_private ) );
413:
414: lp = (struct hp100_private *)dev -> priv;
415: lp -> id = eid;
416: lp -> mem_mapped = mem_mapped;
417: lp -> mem_ptr_phys = mem_ptr_phys;
418: lp -> mem_ptr_virt = mem_ptr_virt;
419: hp100_page( ID_MAC_ADDR );
420: lp -> soft_model = hp100_inb( SOFT_MODEL );
421: lp -> mac1_mode = HP100_MAC1MODE3;
422: lp -> mac2_mode = HP100_MAC2MODE3;
423:
424: dev -> base_addr = ioaddr;
425: hp100_page( HW_MAP );
426: dev -> irq = hp100_inb( IRQ_CHANNEL ) & HP100_IRQ_MASK;
427: if ( dev -> irq == 2 ) dev -> irq = 9;
428: lp -> memory_size = 0x200 << ( ( hp100_inb( SRAM ) & 0xe0 ) >> 5 );
429: lp -> rx_ratio = hp100_rx_ratio;
430:
431: dev -> open = hp100_open;
432: dev -> stop = hp100_close;
433: dev -> hard_start_xmit = hp100_start_xmit;
434: dev -> get_stats = hp100_get_stats;
435: dev -> set_multicast_list = &hp100_set_multicast_list;
436:
437: request_region( dev -> base_addr, HP100_REGION_SIZE, eid -> name );
438:
439: hp100_page( ID_MAC_ADDR );
440: for ( i = uc = 0; i < 6; i++ )
441: dev -> dev_addr[ i ] = hp100_inb( LAN_ADDR + i );
442:
443: hp100_clear_stats( ioaddr );
444:
445: ether_setup( dev );
446:
447: lp -> lan_type = hp100_sense_lan( dev );
448:
449: printk( "%s: %s at 0x%x, IRQ %d, ",
450: dev -> name, lp -> id -> name, ioaddr, dev -> irq );
451: switch ( bus ) {
452: case HP100_BUS_EISA: printk( "EISA" ); break;
453: case HP100_BUS_PCI: printk( "PCI" ); break;
454: default: printk( "ISA" ); break;
455: }
456: printk( " bus, %dk SRAM (rx/tx %d%%).\n",
457: lp -> memory_size >> ( 10 - 4 ), lp -> rx_ratio );
458: if ( mem_mapped )
459: {
460: printk( "%s: Memory area at 0x%lx-0x%lx",
461: dev -> name, (u_long)mem_ptr_phys, (u_long)mem_ptr_phys + 0x1fff );
462: if ( mem_ptr_virt )
463: printk( " (virtual base 0x%lx)", (u_long)mem_ptr_virt );
464: printk( ".\n" );
465: }
466: printk( "%s: ", dev -> name );
467: if ( lp -> lan_type != HP100_LAN_ERR )
468: printk( "Adapter is attached to " );
469: switch ( lp -> lan_type ) {
470: case HP100_LAN_100:
471: printk( "100Mb/s Voice Grade AnyLAN network.\n" );
472: break;
473: case HP100_LAN_10:
474: printk( "10Mb/s network.\n" );
475: break;
476: default:
477: printk( "Warning! Link down.\n" );
478: }
479:
480: hp100_stop_interface( dev );
481:
482: return 0;
483: }
484:
485: /*
486: * open/close functions
487: */
488:
489: static int hp100_open( struct device *dev )
490: {
491: int i;
492: int ioaddr = dev -> base_addr;
493: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
494:
495: if ( request_irq( dev -> irq, hp100_interrupt, SA_INTERRUPT, lp -> id -> name ) )
496: {
497: printk( "%s: unable to get IRQ %d\n", dev -> name, dev -> irq );
498: return -EAGAIN;
499: }
500: irq2dev_map[ dev -> irq ] = dev;
501:
502: MOD_INC_USE_COUNT;
503:
504: dev -> tbusy = 0;
505: dev -> trans_start = jiffies;
506: dev -> interrupt = 0;
507: dev -> start = 1;
508:
509: lp -> lan_type = hp100_sense_lan( dev );
510: lp -> mac1_mode = HP100_MAC1MODE3;
511: lp -> mac2_mode = HP100_MAC2MODE3;
512:
513: hp100_page( MAC_CTRL );
514: hp100_orw( HP100_LINK_BEAT_DIS | HP100_RESET_LB, LAN_CFG_10 );
515:
516: hp100_stop_interface( dev );
517: hp100_load_eeprom( dev );
518:
519: hp100_outw( HP100_MMAP_DIS | HP100_SET_HB |
520: HP100_IO_EN | HP100_SET_LB, OPTION_LSW );
521: hp100_outw( HP100_DEBUG_EN | HP100_RX_HDR | HP100_EE_EN | HP100_RESET_HB |
522: HP100_FAKE_INT | HP100_RESET_LB, OPTION_LSW );
523: hp100_outw( HP100_ADV_NXT_PKT | HP100_TX_CMD | HP100_RESET_LB |
524: HP100_PRIORITY_TX | ( hp100_priority_tx ? HP100_SET_HB : HP100_RESET_HB ),
525: OPTION_MSW );
526:
527: hp100_page( MAC_ADDRESS );
528: for ( i = 0; i < 6; i++ )
529: hp100_outb( dev -> dev_addr[ i ], MAC_ADDR + i );
530: for ( i = 0; i < 8; i++ ) /* setup multicast filter to receive all */
531: hp100_outb( 0xff, HASH_BYTE0 + i );
532: hp100_page( PERFORMANCE );
533: hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all ints */
534: hp100_outw( 0xffff, IRQ_STATUS ); /* ack IRQ */
535: hp100_outw( (HP100_RX_PACKET | HP100_RX_ERROR | HP100_SET_HB) |
536: (HP100_TX_ERROR | HP100_SET_LB ), IRQ_MASK );
537: /* and enable few */
538: hp100_reset_card();
539: hp100_page( MMU_CFG );
540: hp100_outw( ( lp -> memory_size * lp -> rx_ratio ) / 100, RX_MEM_STOP );
541: hp100_outw( lp -> memory_size - 1, TX_MEM_STOP );
542: hp100_unreset_card();
543:
544: if ( lp -> lan_type == HP100_LAN_100 )
545: lp -> hub_status = hp100_login_to_vg_hub( dev );
546:
547: hp100_start_interface( dev );
548:
549: return 0;
550: }
551:
552: static int hp100_close( struct device *dev )
553: {
554: int ioaddr = dev -> base_addr;
555: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
556:
557: hp100_page( PERFORMANCE );
558: hp100_outw( 0xfefe, IRQ_MASK ); /* mask off all IRQs */
559:
560: hp100_stop_interface( dev );
561:
562: if ( lp -> lan_type == HP100_LAN_100 ) /* relogin */
563: hp100_login_to_vg_hub( dev );
564:
565: dev -> tbusy = 1;
566: dev -> start = 0;
567:
568: free_irq( dev -> irq );
569: irq2dev_map[ dev -> irq ] = NULL;
570: MOD_DEC_USE_COUNT;
571: return 0;
572: }
573:
574: /*
575: * transmit
576: */
577:
578: static int hp100_start_xmit( struct sk_buff *skb, struct device *dev )
579: {
580: int i, ok_flag;
581: int ioaddr = dev -> base_addr;
582: u_short val;
583: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
584:
585: if ( lp -> lan_type < 0 )
586: {
587: hp100_stop_interface( dev );
588: if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) < 0 )
589: {
590: printk( "%s: no connection found - check wire\n", dev -> name );
591: hp100_start_interface( dev ); /* 10Mb/s RX packets maybe handled */
592: return -EIO;
593: }
594: if ( lp -> lan_type == HP100_LAN_100 )
595: lp -> hub_status = hp100_login_to_vg_hub( dev );
596: hp100_start_interface( dev );
597: }
598:
599: if ( ( i = ( hp100_inl( TX_MEM_FREE ) & ~0x7fffffff ) ) < skb -> len + 16 )
600: {
601: #ifdef HP100_DEBUG
602: printk( "hp100_start_xmit: rx free mem = 0x%x\n", i );
603: #endif
604: if ( jiffies - dev -> trans_start < 2 * HZ ) return -EAGAIN;
605: if ( lp -> lan_type == HP100_LAN_100 && lp -> hub_status < 0 )
606: /* 100Mb/s adapter isn't connected to hub */
607: {
608: printk( "%s: login to 100Mb/s hub retry\n", dev -> name );
609: hp100_stop_interface( dev );
610: lp -> hub_status = hp100_login_to_vg_hub( dev );
611: hp100_start_interface( dev );
612: }
613: else
614: {
615: hp100_ints_off();
616: i = hp100_sense_lan( dev );
617: hp100_page( PERFORMANCE );
618: hp100_ints_on();
619: if ( i == HP100_LAN_ERR )
620: printk( "%s: link down detected\n", dev -> name );
621: else
622: if ( lp -> lan_type != i )
623: {
624: /* it's very heavy - all network setting must be changed!!! */
625: printk( "%s: cable change 10Mb/s <-> 100Mb/s detected\n", dev -> name );
626: lp -> lan_type = i;
627: hp100_stop_interface( dev );
628: if ( lp -> lan_type == HP100_LAN_100 )
629: lp -> hub_status = hp100_login_to_vg_hub( dev );
630: hp100_start_interface( dev );
631: }
632: else
633: {
634: printk( "%s: interface reset\n", dev -> name );
635: hp100_stop_interface( dev );
636: hp100_start_interface( dev );
637: }
638: }
639: dev -> trans_start = jiffies;
640: return -EAGAIN;
641: }
642:
643: if ( skb == NULL )
644: {
645: dev_tint( dev );
646: return 0;
647: }
648:
649: if ( skb -> len <= 0 ) return 0;
650:
651: for ( i = 0; i < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_TX_CMD ); i++ )
652: {
653: #ifdef HP100_DEBUG_TX
654: printk( "hp100_start_xmit: busy\n" );
655: #endif
656: }
657:
658: hp100_ints_off();
659: val = hp100_inw( IRQ_STATUS );
660: hp100_outw( val & HP100_TX_COMPLETE, IRQ_STATUS );
661: #ifdef HP100_DEBUG_TX
662: printk( "hp100_start_xmit: irq_status = 0x%x, len = %d\n", val, (int)skb -> len );
663: #endif
664: ok_flag = skb -> len >= HP100_MIN_PACKET_SIZE;
665: i = ok_flag ? skb -> len : HP100_MIN_PACKET_SIZE;
666: hp100_outw( i, DATA32 ); /* length to memory manager */
667: hp100_outw( i, FRAGMENT_LEN );
668: if ( lp -> mem_mapped )
669: {
670: if ( lp -> mem_ptr_virt )
671: {
672: memcpy( lp -> mem_ptr_virt, skb -> data, skb -> len );
673: if ( !ok_flag )
674: memset( lp -> mem_ptr_virt, 0, HP100_MIN_PACKET_SIZE - skb -> len );
675: }
676: else
677: {
678: memcpy_toio( lp -> mem_ptr_phys, skb -> data, skb -> len );
679: if ( !ok_flag )
680: memset_io( lp -> mem_ptr_phys, 0, HP100_MIN_PACKET_SIZE - skb -> len );
681: }
682: }
683: else
684: {
685: outsl( ioaddr + HP100_REG_DATA32, skb -> data, ( skb -> len + 3 ) >> 2 );
686: if ( !ok_flag )
687: for ( i = ( skb -> len + 3 ) & ~3; i < HP100_MIN_PACKET_SIZE; i += 4 )
688: hp100_outl( 0, DATA32 );
689: }
690: hp100_outw( HP100_TX_CMD | HP100_SET_LB, OPTION_MSW ); /* send packet */
691: lp -> stats.tx_packets++;
692: dev -> trans_start = jiffies;
693: hp100_ints_on();
694:
695: dev_kfree_skb( skb, FREE_WRITE );
696:
697: #ifdef HP100_DEBUG_TX
698: printk( "hp100_start_xmit: end\n" );
699: #endif
700:
701: return 0;
702: }
703:
704: /*
705: * receive - called from interrupt handler
706: */
707:
708: static void hp100_rx( struct device *dev )
709: {
710: int packets, pkt_len;
711: int ioaddr = dev -> base_addr;
712: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
713: u_int header;
714: struct sk_buff *skb;
715:
716: #if 0
717: if ( lp -> lan_type < 0 )
718: {
719: if ( ( lp -> lan_type = hp100_sense_lan( dev ) ) == HP100_LAN_100 )
720: lp -> hub_status = hp100_login_to_vg_hub( dev );
721: hp100_page( PERFORMANCE );
722: }
723: #endif
724:
725: packets = hp100_inb( RX_PKT_CNT );
726: #ifdef HP100_DEBUG
727: if ( packets > 1 )
728: printk( "hp100_rx: waiting packets = %d\n", packets );
729: #endif
730: while ( packets-- > 0 )
731: {
732: for ( pkt_len = 0; pkt_len < 6000 && ( hp100_inw( OPTION_MSW ) & HP100_ADV_NXT_PKT ); pkt_len++ )
733: {
734: #ifdef HP100_DEBUG_TX
735: printk( "hp100_rx: busy, remaining packets = %d\n", packets );
736: #endif
737: }
738: if ( lp -> mem_mapped )
739: {
740: if ( lp -> mem_ptr_virt )
741: header = *(__u32 *)lp -> mem_ptr_virt;
742: else
743: header = readl( lp -> mem_ptr_phys );
744: }
745: else
746: header = hp100_inl( DATA32 );
747: pkt_len = header & HP100_PKT_LEN_MASK;
748: #ifdef HP100_DEBUG_RX
749: printk( "hp100_rx: new packet - length = %d, errors = 0x%x, dest = 0x%x\n",
750: header & HP100_PKT_LEN_MASK, ( header >> 16 ) & 0xfff8, ( header >> 16 ) & 7 );
751: #endif
752: /*
753: * NOTE! This (and the skb_put() below) depends on the skb-functions
754: * allocating more than asked (notably, aligning the request up to
755: * the next 16-byte length).
756: */
757: skb = dev_alloc_skb( pkt_len );
758: if ( skb == NULL )
759: {
760: #ifdef HP100_DEBUG
761: printk( "hp100_rx: couldn't allocate a sk_buff of size %d\n", pkt_len );
762: #endif
763: lp -> stats.rx_dropped++;
764: }
765: else
766: {
767: u_char *ptr;
768:
769: skb -> dev = dev;
770: ptr = (u_char *)skb_put( skb, pkt_len );
771: if ( lp -> mem_mapped )
772: {
773: if ( lp -> mem_ptr_virt )
774: memcpy( ptr, lp -> mem_ptr_virt, ( pkt_len + 3 ) & ~3 );
775: else
776: memcpy_fromio( ptr, lp -> mem_ptr_phys, ( pkt_len + 3 ) & ~3 );
777: }
778: else
779: insl( ioaddr + HP100_REG_DATA32, ptr, ( pkt_len + 3 ) >> 2 );
780: skb -> protocol = eth_type_trans( skb, dev );
781: netif_rx( skb );
782: lp -> stats.rx_packets++;
783: #ifdef HP100_DEBUG_RX
784: printk( "rx: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
785: ptr[ 0 ], ptr[ 1 ], ptr[ 2 ], ptr[ 3 ], ptr[ 4 ], ptr[ 5 ],
786: ptr[ 6 ], ptr[ 7 ], ptr[ 8 ], ptr[ 9 ], ptr[ 10 ], ptr[ 11 ] );
787: #endif
788: }
789: hp100_outw( HP100_ADV_NXT_PKT | HP100_SET_LB, OPTION_MSW );
790: switch ( header & 0x00070000 ) {
791: case (HP100_MULTI_ADDR_HASH<<16):
792: case (HP100_MULTI_ADDR_NO_HASH<<16):
793: lp -> stats.multicast++; break;
794: }
795: }
796: #ifdef HP100_DEBUG_RX
797: printk( "hp100_rx: end\n" );
798: #endif
799: }
800:
801: /*
802: * statistics
803: */
804:
805: static struct enet_statistics *hp100_get_stats( struct device *dev )
806: {
807: int ioaddr = dev -> base_addr;
808:
809: hp100_ints_off();
810: hp100_update_stats( dev );
811: hp100_ints_on();
812: return &((struct hp100_private *)dev -> priv) -> stats;
813: }
814:
815: static void hp100_update_stats( struct device *dev )
816: {
817: int ioaddr = dev -> base_addr;
818: u_short val;
819: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
820:
821: hp100_page( MAC_CTRL ); /* get all statistics bytes */
822: val = hp100_inw( DROPPED ) & 0x0fff;
823: lp -> stats.rx_errors += val;
824: lp -> stats.rx_over_errors += val;
825: val = hp100_inb( CRC );
826: lp -> stats.rx_errors += val;
827: lp -> stats.rx_crc_errors += val;
828: val = hp100_inb( ABORT );
829: lp -> stats.tx_errors += val;
830: lp -> stats.tx_aborted_errors += val;
831: hp100_page( PERFORMANCE );
832: }
833:
834: static void hp100_clear_stats( int ioaddr )
835: {
836: cli();
837: hp100_page( MAC_CTRL ); /* get all statistics bytes */
838: hp100_inw( DROPPED );
839: hp100_inb( CRC );
840: hp100_inb( ABORT );
841: hp100_page( PERFORMANCE );
842: sti();
843: }
844:
845: /*
846: * multicast setup
847: */
848:
849: /*
850: * Set or clear the multicast filter for this adapter.
851: */
852:
853: static void hp100_set_multicast_list( struct device *dev)
854: {
855: int ioaddr = dev -> base_addr;
856: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
857:
858: #ifdef HP100_DEBUG_MULTI
859: printk( "hp100_set_multicast_list: num_addrs = %d\n", dev->mc_count);
860: #endif
861: cli();
862: hp100_ints_off();
863: hp100_page( MAC_CTRL );
864: hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 ); /* stop rx/tx */
865:
866: if ( dev->flags&IFF_PROMISC)
867: {
868: lp -> mac2_mode = HP100_MAC2MODE6; /* promiscuous mode, all good */
869: lp -> mac1_mode = HP100_MAC1MODE6; /* packets on the net */
870: }
871: else
872: if ( dev->mc_count || dev->flags&IFF_ALLMULTI )
873: {
874: lp -> mac2_mode = HP100_MAC2MODE5; /* multicast mode, packets for me */
875: lp -> mac1_mode = HP100_MAC1MODE5; /* broadcasts and all multicasts */
876: }
877: else
878: {
879: lp -> mac2_mode = HP100_MAC2MODE3; /* normal mode, packets for me */
880: lp -> mac1_mode = HP100_MAC1MODE3; /* and broadcasts */
881: }
882:
883: hp100_outb( lp -> mac2_mode, MAC_CFG_2 );
884: hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 );
885: hp100_orb( lp -> mac1_mode |
886: HP100_RX_EN | HP100_RX_IDLE | /* enable rx */
887: HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 ); /* enable tx */
888: hp100_page( PERFORMANCE );
889: hp100_ints_on();
890: sti();
891: }
892:
893: /*
894: * hardware interrupt handling
895: */
896:
897: static void hp100_interrupt( int irq, struct pt_regs *regs )
898: {
899: struct device *dev = (struct device *)irq2dev_map[ irq ];
900: struct hp100_private *lp;
901: int ioaddr;
902: u_short val;
903:
904: if ( dev == NULL ) return;
905: ioaddr = dev -> base_addr;
906: if ( dev -> interrupt )
907: printk( "%s: re-entering the interrupt handler\n", dev -> name );
908: hp100_ints_off();
909: dev -> interrupt = 1;
910: hp100_page( PERFORMANCE );
911: val = hp100_inw( IRQ_STATUS );
912: #ifdef HP100_DEBUG_IRQ
913: printk( "hp100_interrupt: irq_status = 0x%x\n", val );
914: #endif
915: if ( val & HP100_RX_PACKET )
916: {
917: hp100_rx( dev );
918: hp100_outw( HP100_RX_PACKET, IRQ_STATUS );
919: }
920: if ( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE) )
921: {
922: hp100_outw( val & (HP100_TX_SPACE_AVAIL | HP100_TX_COMPLETE), IRQ_STATUS );
923: }
924: if ( val & ( HP100_TX_ERROR | HP100_RX_ERROR ) )
925: {
926: lp = (struct hp100_private *)dev -> priv;
927: hp100_update_stats( dev );
928: hp100_outw( val & (HP100_TX_ERROR | HP100_RX_ERROR), IRQ_STATUS );
929: }
930: #ifdef HP100_DEBUG_IRQ
931: printk( "hp100_interrupt: end\n" );
932: #endif
933: dev -> interrupt = 0;
934: hp100_ints_on();
935: }
936:
937: /*
938: * some misc functions
939: */
940:
941: static void hp100_start_interface( struct device *dev )
942: {
943: int ioaddr = dev -> base_addr;
944: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
945:
946: cli();
947: hp100_unreset_card();
948: hp100_page( MAC_CTRL );
949: hp100_outb( lp -> mac2_mode, MAC_CFG_2 );
950: hp100_andb( HP100_MAC1MODEMASK, MAC_CFG_1 );
951: hp100_orb( lp -> mac1_mode |
952: HP100_RX_EN | HP100_RX_IDLE |
953: HP100_TX_EN | HP100_TX_IDLE, MAC_CFG_1 );
954: hp100_page( PERFORMANCE );
955: hp100_outw( HP100_INT_EN | HP100_SET_LB, OPTION_LSW );
956: hp100_outw( HP100_TRI_INT | HP100_RESET_HB, OPTION_LSW );
957: if ( lp -> mem_mapped )
958: {
959: /* enable memory mapping */
960: hp100_outw( HP100_MMAP_DIS | HP100_RESET_HB, OPTION_LSW );
961: }
962: sti();
963: }
964:
965: static void hp100_stop_interface( struct device *dev )
966: {
967: int ioaddr = dev -> base_addr;
968: u_short val;
969:
970: hp100_outw( HP100_INT_EN | HP100_RESET_LB |
971: HP100_TRI_INT | HP100_MMAP_DIS | HP100_SET_HB, OPTION_LSW );
972: val = hp100_inw( OPTION_LSW );
973: hp100_page( HW_MAP );
974: hp100_andb( HP100_BM_SLAVE, BM );
975: hp100_page( MAC_CTRL );
976: hp100_andb( ~(HP100_RX_EN | HP100_TX_EN), MAC_CFG_1 );
977: if ( !(val & HP100_HW_RST) ) return;
978: for ( val = 0; val < 6000; val++ )
979: if ( ( hp100_inb( MAC_CFG_1 ) & (HP100_TX_IDLE | HP100_RX_IDLE) ) ==
980: (HP100_TX_IDLE | HP100_RX_IDLE) )
981: return;
982: printk( "%s: hp100_stop_interface - timeout\n", dev -> name );
983: }
984:
985: static void hp100_load_eeprom( struct device *dev )
986: {
987: int i;
988: int ioaddr = dev -> base_addr;
989:
990: hp100_page( EEPROM_CTRL );
991: hp100_andw( ~HP100_EEPROM_LOAD, EEPROM_CTRL );
992: hp100_orw( HP100_EEPROM_LOAD, EEPROM_CTRL );
993: for ( i = 0; i < 6000; i++ )
994: if ( !( hp100_inw( OPTION_MSW ) & HP100_EE_LOAD ) ) return;
995: printk( "%s: hp100_load_eeprom - timeout\n", dev -> name );
996: }
997:
998: /* return values: LAN_10, LAN_100 or LAN_ERR (not connected or hub is down)... */
999:
1000: static int hp100_sense_lan( struct device *dev )
1001: {
1002: int i;
1003: int ioaddr = dev -> base_addr;
1004: u_short val_VG, val_10;
1005: struct hp100_private *lp = (struct hp100_private *)dev -> priv;
1006:
1007: hp100_page( MAC_CTRL );
1008: hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
1009: val_10 = hp100_inw( LAN_CFG_10 );
1010: val_VG = hp100_inw( LAN_CFG_VG );
1011: #ifdef HP100_DEBUG_SENSE
1012: printk( "hp100_sense_lan: val_VG = 0x%04x, val_10 = 0x%04x\n", val_VG, val_10 );
1013: #endif
1014: if ( val_10 & HP100_LINK_BEAT_ST ) return HP100_LAN_10;
1015: if ( lp -> id -> id == 0x02019F022 ) /* HP J27248B doesn't have 100Mb/s interface */
1016: return HP100_LAN_ERR;
1017: for ( i = 0; i < 2500; i++ )
1018: {
1019: val_VG = hp100_inw( LAN_CFG_VG );
1020: if ( val_VG & HP100_LINK_CABLE_ST ) return HP100_LAN_100;
1021: }
1022: return HP100_LAN_ERR;
1023: }
1024:
1025: static int hp100_down_vg_link( struct device *dev )
1026: {
1027: int ioaddr = dev -> base_addr;
1028: unsigned long time;
1029: int i;
1030:
1031: hp100_page( MAC_CTRL );
1032: for ( i = 2500; i > 0; i-- )
1033: if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
1034: if ( i <= 0 ) /* not signal - not logout */
1035: return 0;
1036: hp100_andw( ~HP100_LINK_CMD, LAN_CFG_VG );
1037: time = jiffies + 10;
1038: while ( time > jiffies )
1039: if ( !( hp100_inw( LAN_CFG_VG ) & ( HP100_LINK_UP_ST |
1040: HP100_LINK_CABLE_ST |
1041: HP100_LINK_GOOD_ST ) ) )
1042: return 0;
1043: #ifdef HP100_DEBUG
1044: printk( "hp100_down_vg_link: timeout\n" );
1045: #endif
1046: return -EIO;
1047: }
1048:
1049: static int hp100_login_to_vg_hub( struct device *dev )
1050: {
1051: int i;
1052: int ioaddr = dev -> base_addr;
1053: u_short val;
1054: unsigned long time;
1055:
1056: hp100_page( MAC_CTRL );
1057: hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
1058: time = jiffies + ( HZ / 2 );
1059: do {
1060: if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
1061: } while ( time > jiffies );
1062: if ( time <= jiffies )
1063: {
1064: #ifdef HP100_DEBUG
1065: printk( "hp100_login_to_vg_hub: timeout for link\n" );
1066: #endif
1067: return -EIO;
1068: }
1069:
1070: if ( hp100_down_vg_link( dev ) < 0 ) /* if fail, try reset VG link */
1071: {
1072: hp100_andw( ~HP100_VG_RESET, LAN_CFG_VG );
1073: hp100_orw( HP100_VG_RESET, LAN_CFG_VG );
1074: }
1075: /* bring up link */
1076: hp100_orw( HP100_LOAD_ADDR | HP100_LINK_CMD, LAN_CFG_VG );
1077: for ( i = 2500; i > 0; i-- )
1078: if ( hp100_inw( LAN_CFG_VG ) & HP100_LINK_CABLE_ST ) break;
1079: if ( i <= 0 )
1080: {
1081: #ifdef HP100_DEBUG
1082: printk( "hp100_login_to_vg_hub: timeout for link (bring up)\n" );
1083: #endif
1084: goto down_link;
1085: }
1086:
1087: time = jiffies + ( HZ / 2 );
1088: do {
1089: val = hp100_inw( LAN_CFG_VG );
1090: if ( ( val & ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) ) ==
1091: ( HP100_LINK_UP_ST | HP100_LINK_GOOD_ST ) )
1092: return 0; /* success */
1093: } while ( time > jiffies );
1094: if ( val & HP100_LINK_GOOD_ST )
1095: printk( "%s: 100Mb cable training failed, check cable.\n", dev -> name );
1096: else
1097: printk( "%s: 100Mb node not accepted by hub, check frame type or security.\n", dev -> name );
1098:
1099: down_link:
1100: hp100_down_vg_link( dev );
1101: hp100_page( MAC_CTRL );
1102: hp100_andw( ~( HP100_LOAD_ADDR | HP100_PROM_MODE ), LAN_CFG_VG );
1103: hp100_orw( HP100_LINK_CMD, LAN_CFG_VG );
1104: return -EIO;
1105: }
1106:
1107: /*
1108: * module section
1109: */
1110:
1111: #ifdef MODULE
1112:
1113: static int hp100_port = -1;
1114:
1115: static char devicename[9] = { 0, };
1116: static struct device dev_hp100 = {
1117: devicename, /* device name is inserted by linux/drivers/net/net_init.c */
1118: 0, 0, 0, 0,
1119: 0, 0,
1120: 0, 0, 0, NULL, hp100_probe
1121: };
1122:
1123: int init_module( void )
1124: {
1125: if (hp100_port == 0 && !EISA_bus)
1126: printk("HP100: You should not use auto-probing with insmod!\n");
1127: if ( hp100_port > 0 )
1128: dev_hp100.base_addr = hp100_port;
1129: if ( register_netdev( &dev_hp100 ) != 0 )
1130: return -EIO;
1131: return 0;
1132: }
1133:
1134: void cleanup_module( void )
1135: {
1136: unregister_netdev( &dev_hp100 );
1137: release_region( dev_hp100.base_addr, HP100_REGION_SIZE );
1138: if ( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt )
1139: vfree( ((struct hp100_private *)dev_hp100.priv) -> mem_ptr_virt );
1140: kfree_s( dev_hp100.priv, sizeof( struct hp100_private ) );
1141: dev_hp100.priv = NULL;
1142: }
1143:
1144: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.