2 * Copyright (c) 1997,1998 Maxim Bolotin and Oleg Sharoiko.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice unmodified, this list of conditions, and the following
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * $FreeBSD: src/sys/dev/cs/if_cs.c,v 1.19.2.1 2001/01/25 20:13:48 imp Exp $
31 * Device driver for Crystal Semiconductor CS8920 based ethernet
32 * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/interrupt.h>
42 #include <sys/malloc.h>
44 #include <sys/socket.h>
45 #include <sys/sockio.h>
46 #include <sys/kernel.h>
47 #include <sys/sysctl.h>
48 #include <sys/syslog.h>
49 #include <sys/module.h>
52 #include <sys/thread2.h>
53 #include <sys/machintr.h>
55 #include <machine/clock.h>
58 #include <net/ifq_var.h>
59 #include <net/if_arp.h>
60 #include <net/if_media.h>
61 #include <net/ethernet.h>
68 #define CS_DMA_BUFFER_SIZE 65536
70 #define CS_DMA_BUFFER_SIZE 16384
73 static int cs_recv_delay
= 570;
74 SYSCTL_INT(_machdep
, OID_AUTO
, cs_recv_delay
, CTLFLAG_RW
, &cs_recv_delay
, 0, "");
76 static void cs_init(void *);
77 static int cs_ioctl(struct ifnet
*, u_long
, caddr_t
, struct ucred
*);
78 static void cs_start(struct ifnet
*, struct ifaltq_subque
*);
79 static void cs_stop(struct cs_softc
*);
80 static void cs_reset(struct cs_softc
*);
81 static void cs_watchdog(struct ifnet
*);
82 static void csintr(void *);
84 static int cs_mediachange(struct ifnet
*);
85 static void cs_mediastatus(struct ifnet
*, struct ifmediareq
*);
86 static int cs_mediaset(struct cs_softc
*, int);
88 static void cs_write_mbufs(struct cs_softc
*, struct mbuf
*);
89 static void cs_xmit_buf(struct cs_softc
*);
90 static int cs_get_packet(struct cs_softc
*);
91 static void cs_setmode(struct cs_softc
*);
93 static int get_eeprom_data(device_t
, int, int, int *);
94 static int get_eeprom_cksum(int, int, int *);
95 static int wait_eeprom_ready( struct cs_softc
*);
96 static void control_dc_dc(struct cs_softc
*, int );
97 static int send_test_pkt(struct cs_softc
* );
98 static int enable_tp(struct cs_softc
*);
99 static int enable_aui(struct cs_softc
*);
100 static int enable_bnc(struct cs_softc
*);
101 static int cs_duplex_auto(struct cs_softc
*);
103 devclass_t cs_devclass
;
105 DECLARE_DUMMY_MODULE(if_cs
);
108 get_eeprom_data(device_t dev
, int off
, int len
, int *buffer
)
113 sc
= device_get_softc(dev
);
116 device_printf(dev
, "EEPROM data from %x for %x:\n", off
, len
);
119 for (i
=0;i
<len
;i
++) {
120 if (wait_eeprom_ready(sc
) < 0) return -1;
121 /* Send command to EEPROM to read */
122 cs_writereg(sc
->nic_addr
, PP_EECMD
, (off
+i
)|EEPROM_READ_CMD
);
123 if (wait_eeprom_ready(sc
)<0)
125 buffer
[i
] = cs_readreg (sc
->nic_addr
, PP_EEData
);
128 kprintf("%02x %02x ",(unsigned char)buffer
[i
],
129 (unsigned char)buffer
[i
+1]);
141 get_eeprom_cksum(int off
, int len
, int *buffer
)
154 wait_eeprom_ready(struct cs_softc
*sc
)
156 DELAY ( 30000 ); /* XXX should we do some checks here ? */
161 control_dc_dc(struct cs_softc
*sc
, int on_not_off
)
163 unsigned int self_control
= HCB1_ENBL
;
165 if (((sc
->adapter_cnf
& A_CNF_DC_DC_POLARITY
)!=0) ^ on_not_off
)
166 self_control
|= HCB1
;
168 self_control
&= ~HCB1
;
169 cs_writereg( sc
->nic_addr
, PP_SelfCTL
, self_control
);
176 cs_duplex_auto(struct cs_softc
*sc
)
180 cs_writereg(sc
->nic_addr
, PP_AutoNegCTL
,
181 RE_NEG_NOW
| ALLOW_FDX
| AUTO_NEG_ENABLE
);
182 for (i
=0; cs_readreg(sc
->nic_addr
,PP_AutoNegST
)&AUTO_NEG_BUSY
; i
++) {
184 if_printf(&sc
->arpcom
.ac_if
, "full/half duplex "
185 "auto negotiation timeout\n");
196 enable_tp(struct cs_softc
*sc
)
198 cs_writereg(sc
->nic_addr
, PP_LineCTL
, sc
->line_ctl
& ~AUI_ONLY
);
199 control_dc_dc(sc
, 0);
202 if ((cs_readreg(sc
->nic_addr
, PP_LineST
) & LINK_OK
)==0) {
203 if_printf(&sc
->arpcom
.ac_if
, "failed to enable TP\n");
211 * XXX This was rewritten from Linux driver without any tests.
214 send_test_pkt(struct cs_softc
*sc
)
216 char test_packet
[] = { 0,0,0,0,0,0, 0,0,0,0,0,0,
217 0, 46, /* A 46 in network order */
218 0, 0, /* DSAP=0 & SSAP=0 fields */
219 0xf3, 0 /* Control (Test Req + P bit set) */ };
221 u_char ether_address_backup
[ETHER_ADDR_LEN
];
223 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++) {
224 ether_address_backup
[i
] = sc
->arpcom
.ac_enaddr
[i
];
227 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
228 cs_readreg(sc
->nic_addr
, PP_LineCTL
) | SERIAL_TX_ON
);
230 sc
->arpcom
.ac_enaddr
, ETHER_ADDR_LEN
);
231 bcopy(test_packet
+ETHER_ADDR_LEN
,
232 sc
->arpcom
.ac_enaddr
, ETHER_ADDR_LEN
);
233 outw(sc
->nic_addr
+ TX_CMD_PORT
, sc
->send_cmd
);
234 outw(sc
->nic_addr
+ TX_LEN_PORT
, sizeof(test_packet
));
236 /* Wait for chip to allocate memory */
238 if (!(cs_readreg(sc
->nic_addr
, PP_BusST
) & READY_FOR_TX_NOW
)) {
239 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++) {
240 sc
->arpcom
.ac_enaddr
[i
] = ether_address_backup
[i
];
245 outsw(sc
->nic_addr
+ TX_FRAME_PORT
, test_packet
, sizeof(test_packet
));
249 if ((cs_readreg(sc
->nic_addr
,PP_TxEvent
) & TX_SEND_OK_BITS
) == TX_OK
) {
250 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++) {
251 sc
->arpcom
.ac_enaddr
[i
] = ether_address_backup
[i
];
255 for (i
= 0; i
< ETHER_ADDR_LEN
; i
++) {
256 sc
->arpcom
.ac_enaddr
[i
] = ether_address_backup
[i
];
262 * XXX This was rewritten from Linux driver without any tests.
265 enable_aui(struct cs_softc
*sc
)
267 control_dc_dc(sc
, 0);
268 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
269 (sc
->line_ctl
& ~AUTO_AUI_10BASET
) | AUI_ONLY
);
271 if (!send_test_pkt(sc
)) {
272 if_printf(&sc
->arpcom
.ac_if
, "failed to enable AUI\n");
279 * XXX This was rewritten from Linux driver without any tests.
282 enable_bnc(struct cs_softc
*sc
)
284 control_dc_dc(sc
, 1);
285 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
286 (sc
->line_ctl
& ~AUTO_AUI_10BASET
) | AUI_ONLY
);
288 if (!send_test_pkt(sc
)) {
289 if_printf(&sc
->arpcom
.ac_if
, "failed to enable BNC\n");
296 cs_cs89x0_probe(device_t dev
)
304 struct cs_softc
*sc
= device_get_softc(dev
);
306 unsigned rev_type
= 0;
308 int eeprom_buff
[CHKSUM_LEN
];
309 int chip_type
, pp_isaint
;
310 #if 0 /* Temporary disabled */
314 error
= cs_alloc_port(dev
, 0, CS_89x0_IO_PORTS
);
318 iobase
=rman_get_start(sc
->port_res
);
320 if ((inw(iobase
+ADD_PORT
) & ADD_MASK
) != ADD_SIG
) {
321 /* Chip not detected. Let's try to reset it */
323 device_printf(dev
, "trying to reset the chip.\n");
324 outw(iobase
+ADD_PORT
, PP_SelfCTL
);
325 i
= inw(iobase
+DATA_PORT
);
326 outw(iobase
+ADD_PORT
, PP_SelfCTL
);
327 outw(iobase
+DATA_PORT
, i
| POWER_ON_RESET
);
328 if ((inw(iobase
+ADD_PORT
) & ADD_MASK
) != ADD_SIG
)
332 outw(iobase
+ADD_PORT
, PP_ChipID
);
333 if (inw(iobase
+DATA_PORT
) != CHIP_EISA_ID_SIG
)
336 rev_type
= cs_readreg(iobase
, PRODUCT_ID_ADD
);
337 chip_type
= rev_type
& ~REVISON_BITS
;
338 chip_revision
= ((rev_type
& REVISON_BITS
) >> 8) + 'A';
340 sc
->nic_addr
= iobase
;
341 sc
->chip_type
= chip_type
;
343 if(chip_type
==CS8900
) {
344 pp_isaint
= PP_CS8900_ISAINT
;
345 #if 0 /* Temporary disabled */
346 pp_isadma
= PP_CS8900_ISADMA
;
348 sc
->send_cmd
= TX_CS8900_AFTER_ALL
;
350 pp_isaint
= PP_CS8920_ISAINT
;
351 #if 0 /* Temporary disabled */
352 pp_isadma
= PP_CS8920_ISADMA
;
354 sc
->send_cmd
= TX_CS8920_AFTER_ALL
;
358 * Clear some fields so that fail of EEPROM will left them clean
360 sc
->auto_neg_cnf
= 0;
365 * If no interrupt specified (or "?"), use what the board tells us.
367 error
= bus_get_resource(dev
, SYS_RES_IRQ
, 0, &irq
, &junk
);
370 * Get data from EEPROM
372 if((cs_readreg(iobase
, PP_SelfST
) & EEPROM_PRESENT
) == 0) {
373 device_printf(dev
, "No EEPROM, assuming defaults.\n");
375 if (get_eeprom_data(dev
, START_EEPROM_DATA
, CHKSUM_LEN
,
377 device_printf(dev
, "EEPROM read failed, "
378 "assuming defaults.\n");
380 if (get_eeprom_cksum(START_EEPROM_DATA
,CHKSUM_LEN
, eeprom_buff
)<0) {
381 device_printf(dev
, "EEPROM cheksum bad, "
382 "assuming defaults.\n");
385 eeprom_buff
[AUTO_NEG_CNF_OFFSET
/2];
387 eeprom_buff
[ADAPTER_CNF_OFFSET
/2];
389 eeprom_buff
[ISA_CNF_OFFSET
/2];
391 for (i
=0; i
<ETHER_ADDR_LEN
/2; i
++) {
392 sc
->arpcom
.ac_enaddr
[i
*2]=
394 sc
->arpcom
.ac_enaddr
[i
*2+1]=
399 * If no interrupt specified (or "?"),
400 * use what the board tells us.
403 irq
= sc
->isa_config
& INT_NO_MASK
;
404 if (chip_type
==CS8900
) {
423 device_printf(dev
, "invalid irq in EEPROM.\n");
427 if (irq
>CS8920_NO_INTS
) {
428 device_printf(dev
, "invalid irq in EEPROM.\n");
436 bus_set_resource(dev
, SYS_RES_IRQ
, 0,
437 irq
, 1, machintr_legacy_intr_cpuid(irq
));
445 if (chip_type
== CS8900
) {
463 if (irq
> CS8920_NO_INTS
) {
470 cs_writereg(iobase
, pp_isaint
, irq
);
472 device_printf(dev
, "Unknown or invalid irq\n");
476 #if 0 /* Temporary disabled */
478 cs_writereg(iobase
, pp_isadma
, drq
);
480 device_printf(dev
, "incorrect drq\n");
486 device_printf(dev
, "CS89%c0%s rev %c media%s%s%s\n",
487 chip_type
==CS8900
? '0' : '2',
488 chip_type
==CS8920M
? "M" : "",
490 (sc
->adapter_cnf
& A_CNF_10B_T
) ? " TP" : "",
491 (sc
->adapter_cnf
& A_CNF_AUI
) ? " AUI" : "",
492 (sc
->adapter_cnf
& A_CNF_10B_2
) ? " BNC" : "");
494 if ((sc
->adapter_cnf
& A_CNF_EXTND_10B_2
) &&
495 (sc
->adapter_cnf
& A_CNF_LOW_RX_SQUELCH
))
496 sc
->line_ctl
= LOW_RX_SQUELCH
;
505 * Allocate a port resource with the given resource id.
508 cs_alloc_port(device_t dev
, int rid
, int size
)
510 struct cs_softc
*sc
= device_get_softc(dev
);
511 struct resource
*res
;
513 res
= bus_alloc_resource(dev
, SYS_RES_IOPORT
, &rid
,
514 0ul, ~0ul, size
, RF_ACTIVE
);
518 sc
->port_used
= size
;
526 * Allocate a memory resource with the given resource id.
529 cs_alloc_memory(device_t dev
, int rid
, int size
)
531 struct cs_softc
*sc
= device_get_softc(dev
);
532 struct resource
*res
;
534 res
= bus_alloc_resource(dev
, SYS_RES_MEMORY
, &rid
,
535 0ul, ~0ul, size
, RF_ACTIVE
);
547 * Allocate an irq resource with the given resource id.
550 cs_alloc_irq(device_t dev
, int rid
, int flags
)
552 struct cs_softc
*sc
= device_get_softc(dev
);
553 struct resource
*res
;
555 res
= bus_alloc_resource_any(dev
, SYS_RES_IRQ
, &rid
,
556 (RF_ACTIVE
| flags
));
567 * Release all resources
570 cs_release_resources(device_t dev
)
572 struct cs_softc
*sc
= device_get_softc(dev
);
575 bus_release_resource(dev
, SYS_RES_IOPORT
,
576 sc
->port_rid
, sc
->port_res
);
580 bus_release_resource(dev
, SYS_RES_MEMORY
,
581 sc
->mem_rid
, sc
->mem_res
);
585 bus_release_resource(dev
, SYS_RES_IRQ
,
586 sc
->irq_rid
, sc
->irq_res
);
592 * Install the interface into kernel networking data structures
595 cs_attach(device_t dev
)
597 struct cs_softc
*sc
= device_get_softc(dev
);
598 int media
= 0, error
;
599 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
602 * Initialize the media structures.
604 ifmedia_init(&sc
->media
, 0, cs_mediachange
, cs_mediastatus
);
606 KASSERT(sc
->port_used
> 0 || sc
->mem_used
> 0,
607 ("%s: either I/O port or I/O memory should be used",
608 device_get_nameunit(dev
)));
609 if (sc
->port_used
> 0)
610 cs_alloc_port(dev
, sc
->port_rid
, sc
->port_used
);
611 if (sc
->mem_used
> 0)
612 cs_alloc_memory(dev
, sc
->mem_rid
, sc
->mem_used
);
614 error
= cs_alloc_irq(dev
, sc
->irq_rid
, 0);
616 device_printf(dev
, "Couldn't allocate irq");
623 if_initname(ifp
, device_get_name(dev
), device_get_unit(dev
));
624 ifp
->if_start
=cs_start
;
625 ifp
->if_ioctl
=cs_ioctl
;
626 ifp
->if_watchdog
=cs_watchdog
;
627 ifp
->if_init
=cs_init
;
628 ifq_set_maxlen(&ifp
->if_snd
, IFQ_MAXLEN
);
629 ifq_set_ready(&ifp
->if_snd
);
635 ifp
->if_linkmib
=&sc
->mibdata
;
636 ifp
->if_linkmiblen
=sizeof sc
->mibdata
;
639 ifp
->if_flags
=(IFF_BROADCAST
| IFF_SIMPLEX
| IFF_MULTICAST
);
643 * this code still in progress (DMA support)
645 sc
->recv_ring
=kmalloc(CS_DMA_BUFFER_SIZE
<<1, M_DEVBUF
, M_WAITOK
);
646 if ((sc
->recv_ring
-(sc
->recv_ring
& 0x1FFFF))
647 < (128*1024-CS_DMA_BUFFER_SIZE
))
648 sc
->recv_ring
+=16*1024;
651 sc
->buffer
=kmalloc(ETHER_MAX_LEN
-ETHER_CRC_LEN
,M_DEVBUF
,M_WAITOK
);
653 if (sc
->adapter_cnf
& A_CNF_10B_T
) {
654 ifmedia_add(&sc
->media
, IFM_ETHER
|IFM_10_T
, 0, NULL
);
655 if (sc
->chip_type
!= CS8900
) {
656 ifmedia_add(&sc
->media
,
657 IFM_ETHER
|IFM_10_T
|IFM_FDX
, 0, NULL
);
658 ifmedia_add(&sc
->media
,
659 IFM_ETHER
|IFM_10_T
|IFM_HDX
, 0, NULL
);
663 if (sc
->adapter_cnf
& A_CNF_10B_2
)
664 ifmedia_add(&sc
->media
, IFM_ETHER
|IFM_10_2
, 0, NULL
);
666 if (sc
->adapter_cnf
& A_CNF_AUI
)
667 ifmedia_add(&sc
->media
, IFM_ETHER
|IFM_10_5
, 0, NULL
);
669 if (sc
->adapter_cnf
& A_CNF_MEDIA
)
670 ifmedia_add(&sc
->media
, IFM_ETHER
|IFM_AUTO
, 0, NULL
);
672 /* Set default media from EEPROM */
673 switch (sc
->adapter_cnf
& A_CNF_MEDIA_TYPE
) {
674 case A_CNF_MEDIA_AUTO
: media
= IFM_ETHER
|IFM_AUTO
; break;
675 case A_CNF_MEDIA_10B_T
: media
= IFM_ETHER
|IFM_10_T
; break;
676 case A_CNF_MEDIA_10B_2
: media
= IFM_ETHER
|IFM_10_2
; break;
677 case A_CNF_MEDIA_AUI
: media
= IFM_ETHER
|IFM_10_5
; break;
678 default: device_printf(dev
, "adapter has no media\n");
680 ifmedia_set(&sc
->media
, media
);
681 cs_mediaset(sc
, media
);
683 ether_ifattach(ifp
, sc
->arpcom
.ac_enaddr
, NULL
);
685 ifq_set_cpuid(&ifp
->if_snd
, rman_get_cpuid(sc
->irq_res
));
687 error
= bus_setup_intr(dev
, sc
->irq_res
, INTR_MPSAFE
,
688 csintr
, sc
, &sc
->irq_handle
,
691 device_printf(dev
, "Couldn't set up irq");
704 cs_detach(device_t dev
)
706 struct cs_softc
*sc
= device_get_softc(dev
);
707 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
709 if (device_is_attached(dev
)) {
710 lwkt_serialize_enter(ifp
->if_serializer
);
712 bus_teardown_intr(dev
, sc
->irq_res
, sc
->irq_handle
);
713 lwkt_serialize_exit(ifp
->if_serializer
);
715 ether_ifdetach(&sc
->arpcom
.ac_if
);
720 * this code still in progress (DMA support)
722 if (sc
->recv_ring
!= NULL
)
723 kfree(sc
->recv_ring
, M_DEVBUF
);
726 if (sc
->buffer
!= NULL
)
727 kfree(sc
->buffer
, M_DEVBUF
);
728 cs_release_resources(dev
);
729 ifmedia_removeall(&sc
->media
);
735 * Initialize the board
740 struct cs_softc
*sc
=(struct cs_softc
*)xsc
;
741 struct ifnet
*ifp
= &sc
->arpcom
.ac_if
;
745 * reset whatchdog timer
751 * Hardware initialization of cs
754 /* Enable receiver and transmitter */
755 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
756 cs_readreg( sc
->nic_addr
, PP_LineCTL
) |
757 SERIAL_RX_ON
| SERIAL_TX_ON
);
759 /* Configure the receiver mode */
763 * This defines what type of frames will cause interrupts
764 * Bad frames should generate interrupts so that the driver
765 * could track statistics of discarded packets
767 rx_cfg
= RX_OK_ENBL
| RX_CRC_ERROR_ENBL
| RX_RUNT_ENBL
|
769 if (sc
->isa_config
& STREAM_TRANSFER
)
770 rx_cfg
|= RX_STREAM_ENBL
;
771 cs_writereg(sc
->nic_addr
, PP_RxCFG
, rx_cfg
);
773 cs_writereg(sc
->nic_addr
, PP_TxCFG
, TX_LOST_CRS_ENBL
|
774 TX_SQE_ERROR_ENBL
| TX_OK_ENBL
| TX_LATE_COL_ENBL
|
775 TX_JBR_ENBL
| TX_ANY_COL_ENBL
| TX_16_COL_ENBL
);
777 cs_writereg(sc
->nic_addr
, PP_BufCFG
, READY_FOR_TX_ENBL
|
778 RX_MISS_COUNT_OVRFLOW_ENBL
| TX_COL_COUNT_OVRFLOW_ENBL
|
779 TX_UNDERRUN_ENBL
/*| RX_DMA_ENBL*/);
781 /* Write MAC address into IA filter */
782 for (i
=0; i
<ETHER_ADDR_LEN
/2; i
++)
783 cs_writereg(sc
->nic_addr
, PP_IA
+i
*2,
784 sc
->arpcom
.ac_enaddr
[i
*2] |
785 (sc
->arpcom
.ac_enaddr
[i
*2+1] << 8) );
788 * Now enable everything
791 #ifdef CS_USE_64K_DMA
792 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
795 cs_writereg(sc->nic_addr, PP_BusCTL, ENABLE_IRQ);
798 cs_writereg(sc
->nic_addr
, PP_BusCTL
, ENABLE_IRQ
);
801 * Set running and clear output active flags
803 sc
->arpcom
.ac_if
.if_flags
|= IFF_RUNNING
;
804 ifq_clr_oactive(&sc
->arpcom
.ac_if
.if_snd
);
807 * Start sending process
809 if_devstart(&sc
->arpcom
.ac_if
);
813 * Get the packet from the board and send it to the upper layer
817 cs_get_packet(struct cs_softc
*sc
)
819 struct ifnet
*ifp
= &(sc
->arpcom
.ac_if
);
820 int iobase
= sc
->nic_addr
, status
, length
;
827 status
= inw(iobase
+ RX_FRAME_PORT
);
828 length
= inw(iobase
+ RX_FRAME_PORT
);
831 if_printf(ifp
, "rcvd: stat %x, len %d\n", status
, length
);
834 if (!(status
& RX_OK
)) {
836 if_printf(ifp
, "bad pkt stat %x\n", status
);
838 IFNET_STAT_INC(ifp
, ierrors
, 1);
842 MGETHDR(m
, M_NOWAIT
, MT_DATA
);
846 if (length
> MHLEN
) {
848 if (!(m
->m_flags
& M_EXT
)) {
854 /* Initialize packet's header info */
855 m
->m_pkthdr
.rcvif
= ifp
;
856 m
->m_pkthdr
.len
= length
;
860 insw(iobase
+ RX_FRAME_PORT
, m
->m_data
, (length
+1)>>1);
863 for (i
=0;i
<length
;i
++)
864 kprintf(" %02x",(unsigned char)*((char *)(m
->m_data
+i
)));
868 if (status
& (RX_IA
| RX_BROADCAST
) ||
869 (ifp
->if_flags
& IFF_MULTICAST
&& status
& RX_HASHED
)) {
870 ifp
->if_input(ifp
, m
, NULL
, -1);
872 IFNET_STAT_INC(ifp
, ipackets
, 1);
874 if (length
==ETHER_MAX_LEN
-ETHER_CRC_LEN
)
875 DELAY( cs_recv_delay
);
889 struct cs_softc
*sc
= (struct cs_softc
*) arg
;
890 struct ifnet
*ifp
= &(sc
->arpcom
.ac_if
);
894 if_printf(ifp
, "Interrupt.\n");
897 while ((status
=cs_readword(sc
->nic_addr
, ISQ_PORT
))) {
900 if_printf(ifp
, "from ISQ: %04x\n", status
);
903 switch (status
& ISQ_EVENT_MASK
) {
904 case ISQ_RECEIVER_EVENT
:
908 case ISQ_TRANSMITTER_EVENT
:
910 IFNET_STAT_INC(ifp
, opackets
, 1);
912 IFNET_STAT_INC(ifp
, oerrors
, 1);
913 ifq_clr_oactive(&ifp
->if_snd
);
917 case ISQ_BUFFER_EVENT
:
918 if (status
& READY_FOR_TX
) {
919 ifq_clr_oactive(&ifp
->if_snd
);
923 if (status
& TX_UNDERRUN
) {
924 ifq_clr_oactive(&ifp
->if_snd
);
926 IFNET_STAT_INC(ifp
, oerrors
, 1);
930 case ISQ_RX_MISS_EVENT
:
931 IFNET_STAT_INC(ifp
, ierrors
, (status
>>6));
934 case ISQ_TX_COL_EVENT
:
935 IFNET_STAT_INC(ifp
, collisions
, (status
>>6));
940 if (!ifq_is_oactive(&ifp
->if_snd
))
945 * Save the data in buffer
949 cs_write_mbufs( struct cs_softc
*sc
, struct mbuf
*m
)
953 unsigned char *data
, *buf
;
955 for (mp
=m
, buf
=sc
->buffer
, sc
->buf_len
=0; mp
!= NULL
; mp
=mp
->m_next
) {
965 * Find actual data address
967 data
= mtod(mp
, caddr_t
);
969 bcopy((caddr_t
) data
, (caddr_t
) buf
, len
);
977 cs_xmit_buf( struct cs_softc
*sc
)
979 outsw(sc
->nic_addr
+TX_FRAME_PORT
, sc
->buffer
, (sc
->buf_len
+1)>>1);
984 cs_start(struct ifnet
*ifp
, struct ifaltq_subque
*ifsq
)
988 struct cs_softc
*sc
= ifp
->if_softc
;
990 ASSERT_ALTQ_SQ_DEFAULT(ifp
, ifsq
);
994 length
= sc
->buf_len
;
996 m
= ifq_dequeue(&ifp
->if_snd
);
1002 for (length
=0, mp
=m
; mp
!= NULL
; mp
=mp
->m_next
)
1003 length
+= mp
->m_len
;
1005 /* Skip zero-length packets */
1011 cs_write_mbufs(sc
, m
);
1019 * Issue a SEND command
1021 outw(sc
->nic_addr
+TX_CMD_PORT
, sc
->send_cmd
);
1022 outw(sc
->nic_addr
+TX_LEN_PORT
, length
);
1025 * If there's no free space in the buffer then leave
1026 * this packet for the next time: indicate output active
1029 if (!(cs_readreg(sc
->nic_addr
, PP_BusST
) & READY_FOR_TX_NOW
)) {
1030 ifp
->if_timer
= sc
->buf_len
;
1031 ifq_set_oactive(&ifp
->if_snd
);
1038 * Set the watchdog timer in case we never hear
1039 * from board again. (I don't know about correct
1040 * value for this timeout)
1042 ifp
->if_timer
= length
;
1044 ifq_set_oactive(&ifp
->if_snd
);
1050 * Stop everything on the interface
1053 cs_stop(struct cs_softc
*sc
)
1055 cs_writereg(sc
->nic_addr
, PP_RxCFG
, 0);
1056 cs_writereg(sc
->nic_addr
, PP_TxCFG
, 0);
1057 cs_writereg(sc
->nic_addr
, PP_BufCFG
, 0);
1058 cs_writereg(sc
->nic_addr
, PP_BusCTL
, 0);
1060 sc
->arpcom
.ac_if
.if_flags
&= ~IFF_RUNNING
;
1061 ifq_clr_oactive(&sc
->arpcom
.ac_if
.if_snd
);
1062 sc
->arpcom
.ac_if
.if_timer
= 0;
1066 * Reset the interface
1069 cs_reset(struct cs_softc
*sc
)
1076 cs_setmode(struct cs_softc
*sc
)
1078 struct ifnet
*ifp
= &(sc
->arpcom
.ac_if
);
1081 /* Stop the receiver while changing filters */
1082 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
1083 cs_readreg(sc
->nic_addr
, PP_LineCTL
) & ~SERIAL_RX_ON
);
1085 if (ifp
->if_flags
& IFF_PROMISC
) {
1086 /* Turn on promiscuous mode. */
1087 rx_ctl
= RX_OK_ACCEPT
| RX_PROM_ACCEPT
;
1089 if (ifp
->if_flags
& IFF_MULTICAST
) {
1090 /* Allow receiving frames with multicast addresses */
1091 rx_ctl
= RX_IA_ACCEPT
| RX_BROADCAST_ACCEPT
|
1092 RX_OK_ACCEPT
| RX_MULTCAST_ACCEPT
;
1094 * Here the reconfiguration of chip's multicast
1095 * filters should be done but I've no idea about
1096 * hash transformation in this chip. If you can
1097 * add this code or describe me the transformation
1102 * Receive only good frames addressed for us and
1105 rx_ctl
= RX_IA_ACCEPT
| RX_BROADCAST_ACCEPT
|
1110 /* Set up the filter */
1111 cs_writereg(sc
->nic_addr
, PP_RxCTL
, RX_DEF_ACCEPT
| rx_ctl
);
1113 /* Turn on receiver */
1114 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
1115 cs_readreg(sc
->nic_addr
, PP_LineCTL
) | SERIAL_RX_ON
);
1119 cs_ioctl(struct ifnet
*ifp
, u_long command
, caddr_t data
, struct ucred
*cr
)
1121 struct cs_softc
*sc
=ifp
->if_softc
;
1122 struct ifreq
*ifr
= (struct ifreq
*)data
;
1126 if_printf(ifp
, "ioctl(%lx)\n", command
);
1132 * Switch interface state between "running" and
1133 * "stopped", reflecting the UP flag.
1135 if (sc
->arpcom
.ac_if
.if_flags
& IFF_UP
) {
1136 if ((sc
->arpcom
.ac_if
.if_flags
& IFF_RUNNING
)==0) {
1140 if ((sc
->arpcom
.ac_if
.if_flags
& IFF_RUNNING
)!=0) {
1145 * Promiscuous and/or multicast flags may have changed,
1146 * so reprogram the multicast filter and/or receive mode.
1148 * See note about multicasts in cs_setmode
1156 * Multicast list has changed; set the hardware filter
1159 * See note about multicasts in cs_setmode
1167 error
= ifmedia_ioctl(ifp
, ifr
, &sc
->media
, command
);
1170 error
= ether_ioctl(ifp
, command
, data
);
1178 * Device timeout/watchdog routine. Entered if the device neglects to
1179 * generate an interrupt after a transmit has been started on it.
1182 cs_watchdog(struct ifnet
*ifp
)
1184 struct cs_softc
*sc
= ifp
->if_softc
;
1186 IFNET_STAT_INC(ifp
, oerrors
, 1);
1187 log(LOG_ERR
, "%s: device timeout\n", ifp
->if_xname
);
1189 /* Reset the interface */
1190 if (ifp
->if_flags
& IFF_UP
)
1197 cs_mediachange(struct ifnet
*ifp
)
1199 struct cs_softc
*sc
= ifp
->if_softc
;
1200 struct ifmedia
*ifm
= &sc
->media
;
1202 if (IFM_TYPE(ifm
->ifm_media
) != IFM_ETHER
)
1205 return cs_mediaset(sc
, ifm
->ifm_media
);
1209 cs_mediastatus(struct ifnet
*ifp
, struct ifmediareq
*ifmr
)
1212 struct cs_softc
*sc
= ifp
->if_softc
;
1214 ifmr
->ifm_active
= IFM_ETHER
;
1215 line_status
= cs_readreg(sc
->nic_addr
, PP_LineST
);
1216 if (line_status
& TENBASET_ON
) {
1217 ifmr
->ifm_active
|= IFM_10_T
;
1218 if (sc
->chip_type
!= CS8900
) {
1219 if (cs_readreg(sc
->nic_addr
, PP_AutoNegST
) & FDX_ACTIVE
)
1220 ifmr
->ifm_active
|= IFM_FDX
;
1221 if (cs_readreg(sc
->nic_addr
, PP_AutoNegST
) & HDX_ACTIVE
)
1222 ifmr
->ifm_active
|= IFM_HDX
;
1224 ifmr
->ifm_status
= IFM_AVALID
;
1225 if (line_status
& LINK_OK
)
1226 ifmr
->ifm_status
|= IFM_ACTIVE
;
1228 if (line_status
& AUI_ON
) {
1229 cs_writereg(sc
->nic_addr
, PP_SelfCTL
,
1230 cs_readreg(sc
->nic_addr
, PP_SelfCTL
) |
1232 if (((sc
->adapter_cnf
& A_CNF_DC_DC_POLARITY
)!=0)^
1233 (cs_readreg(sc
->nic_addr
, PP_SelfCTL
)&HCB1
))
1234 ifmr
->ifm_active
|= IFM_10_2
;
1236 ifmr
->ifm_active
|= IFM_10_5
;
1242 cs_mediaset(struct cs_softc
*sc
, int media
)
1246 /* Stop the receiver & transmitter */
1247 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
1248 cs_readreg(sc
->nic_addr
, PP_LineCTL
) &
1249 ~(SERIAL_RX_ON
| SERIAL_TX_ON
));
1252 if_printf(&sc
->arpcom
.ac_if
, "cs_setmedia(%x)\n", media
);
1255 switch (IFM_SUBTYPE(media
)) {
1258 if ((error
=enable_tp(sc
))==0)
1259 error
= cs_duplex_auto(sc
);
1260 else if ((error
=enable_bnc(sc
)) != 0)
1261 error
= enable_aui(sc
);
1264 if ((error
=enable_tp(sc
)) != 0)
1266 if (media
& IFM_FDX
)
1268 else if (media
& IFM_HDX
)
1271 error
= cs_duplex_auto(sc
);
1274 error
= enable_bnc(sc
);
1277 error
= enable_aui(sc
);
1282 * Turn the transmitter & receiver back on
1284 cs_writereg(sc
->nic_addr
, PP_LineCTL
,
1285 cs_readreg( sc
->nic_addr
, PP_LineCTL
) |
1286 SERIAL_RX_ON
| SERIAL_TX_ON
);