2 * usbgem.c: General USB to Fast Ethernet mac driver framework
4 * Copyright (c) 2002-2012 Masayuki Murayama. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. Neither the name of the author nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
40 * implement DELAYED_START
44 * System Header files.
46 #include <sys/types.h>
48 #include <sys/debug.h>
50 #include <sys/vtrace.h>
51 #include <sys/ethernet.h>
52 #include <sys/modctl.h>
53 #include <sys/errno.h>
55 #include <sys/sunddi.h>
56 #ifndef USBGEM_CONFIG_GLDv3
58 #include <sys/strsubr.h>
60 #include <sys/stream.h> /* required for MBLK* */
61 #include <sys/strsun.h> /* required for mionack() */
62 #include <sys/byteorder.h>
64 #include <sys/usb/usba.h>
65 #ifdef USBGEM_CONFIG_GLDv3
66 #include <inet/common.h>
72 /* supplement definitions */
73 extern const char *usb_str_cr(usb_cr_t
);
75 #ifndef USBGEM_CONFIG_GLDv3
76 #pragma weak gld_linkstate
80 #include "usbgem_mii.h"
84 char ident
[] = "usb general ethernet mac driver v" VERSION
;
89 /* Debugging support */
90 #ifdef USBGEM_DEBUG_LEVEL
91 static int usbgem_debug
= USBGEM_DEBUG_LEVEL
;
92 #define DPRINTF(n, args) if (usbgem_debug > (n)) cmn_err args
94 #define DPRINTF(n, args)
98 * Useful macros and typedefs
100 #define ROUNDUP(x, a) (((x) + (a) - 1) & ~((a) - 1))
101 #define DEFAULT_PIPE(dp) ((dp)->reg_data->dev_default_ph)
103 #define BOOLEAN(x) ((x) != 0)
105 * configuration parameters
107 #define USBDRV_MAJOR_VER 2
108 #define USBDRV_MINOR_VER 0
110 #define ETHERHEADERL (sizeof (struct ether_header))
111 #define MAXPKTLEN(dp) ((dp)->mtu + ETHERHEADERL)
112 #define MAXPKTBUF(dp) ((dp)->mtu + ETHERHEADERL + ETHERFCSL)
114 #define WATCH_INTERVAL_FAST drv_usectohz(100*1000)
116 #define STOP_GRACEFUL B_TRUE
121 static int usbgem_open_pipes(struct usbgem_dev
*dp
);
122 static int usbgem_close_pipes(struct usbgem_dev
*dp
);
123 static void usbgem_intr_cb(usb_pipe_handle_t
, usb_intr_req_t
*);
124 static void usbgem_bulkin_cb(usb_pipe_handle_t
, usb_bulk_req_t
*);
125 static void usbgem_bulkout_cb(usb_pipe_handle_t
, usb_bulk_req_t
*);
127 static int usbgem_mii_start(struct usbgem_dev
*);
128 static void usbgem_mii_stop(struct usbgem_dev
*);
130 /* local buffer management */
131 static int usbgem_init_rx_buf(struct usbgem_dev
*);
133 /* internal mac interfaces */
134 static void usbgem_tx_timeout(struct usbgem_dev
*);
135 static void usbgem_mii_link_watcher(struct usbgem_dev
*);
136 static int usbgem_mac_init(struct usbgem_dev
*);
137 static int usbgem_mac_start(struct usbgem_dev
*);
138 static int usbgem_mac_stop(struct usbgem_dev
*, int, boolean_t
);
139 static void usbgem_mac_ioctl(struct usbgem_dev
*, queue_t
*, mblk_t
*);
141 int usbgem_speed_value
[] = {10, 100, 1000};
143 static int usbgem_ctrl_retry
= 5;
145 /* usb event support */
146 static int usbgem_disconnect_cb(dev_info_t
*dip
);
147 static int usbgem_reconnect_cb(dev_info_t
*dip
);
148 int usbgem_suspend(dev_info_t
*dip
);
149 int usbgem_resume(dev_info_t
*dip
);
151 static uint8_t usbgem_bcastaddr
[] = {
152 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
156 extern struct mod_ops mod_miscops
;
158 static struct modlmisc modlmisc
= {
163 static struct modlinkage modlinkage
= {
164 MODREV_1
, &modlmisc
, NULL
175 DPRINTF(2, (CE_CONT
, "!usbgem: _init: called"));
176 status
= mod_install(&modlinkage
);
189 DPRINTF(2, (CE_CONT
, "!usbgem: _fini: called"));
190 status
= mod_remove(&modlinkage
);
195 _info(struct modinfo
*modinfop
)
197 return (mod_info(&modlinkage
, modinfop
));
201 /* ============================================================== */
203 * Ether CRC calculation utilities
205 /* ============================================================== */
207 * Ether CRC calculation according to 21143 data sheet
209 #define CRC32_POLY_LE 0xedb88320
211 usbgem_ether_crc_le(const uint8_t *addr
)
216 uint32_t crc
= 0xffffffff;
219 for (idx
= 0; idx
< ETHERADDRL
; idx
++) {
220 for (data
= *addr
++, bit
= 0; bit
< 8; bit
++, data
>>= 1) {
222 (((crc
^ data
) & 1) ? CRC32_POLY_LE
: 0);
228 #define CRC32_POLY_BE 0x04c11db7
230 usbgem_ether_crc_be(const uint8_t *addr
)
238 for (idx
= 0; idx
< ETHERADDRL
; idx
++) {
239 for (data
= *addr
++, bit
= 0; bit
< 8; bit
++, data
>>= 1) {
241 ((((crc
>> 31) ^ data
) & 1) ? CRC32_POLY_BE
: 0);
248 usbgem_prop_get_int(struct usbgem_dev
*dp
, char *prop_template
, int def_val
)
252 (void) sprintf(propname
, prop_template
, dp
->name
);
254 return (ddi_prop_get_int(DDI_DEV_T_ANY
, dp
->dip
,
255 DDI_PROP_DONTPASS
, propname
, def_val
));
259 usbgem_population(uint32_t x
)
265 for (i
= 0; i
< 32; i
++) {
274 usbgem_timestamp_nz()
277 now
= ddi_get_lbolt();
278 return (now
? now
: (clock_t)1);
281 #ifdef USBGEM_DEBUG_LEVEL
282 #ifdef USBGEM_DEBUG_VLAN
284 #include <netinet/in.h>
287 usbgem_dump_packet(struct usbgem_dev
*dp
, char *title
, mblk_t
*mp
,
288 boolean_t check_cksum
)
291 uint8_t buf
[18+20+20];
306 extern uint_t
ip_cksum(mblk_t
*, int, uint32_t);
313 for (tp
= mp
; tp
; tp
= tp
->b_cont
) {
314 len
= tp
->b_wptr
- tp
->b_rptr
;
315 len
= min(rest
, len
);
316 bcopy(tp
->b_rptr
, &buf
[offset
], len
);
327 /* ethernet address */
329 "ether: %02x:%02x:%02x:%02x:%02x:%02x"
330 " -> %02x:%02x:%02x:%02x:%02x:%02x",
331 p
[6], p
[7], p
[8], p
[9], p
[10], p
[11],
332 p
[0], p
[1], p
[2], p
[3], p
[4], p
[5]);
333 bp
= &msg
[strlen(msg
)];
335 /* vlag tag and etherrtype */
336 ethertype
= GET_ETHERTYPE(p
);
337 if (ethertype
== VTAG_TPID
) {
338 sprintf(bp
, " vtag:0x%04x", GET_NET16(&p
[14]));
339 bp
= &msg
[strlen(msg
)];
343 ethertype
= GET_ETHERTYPE(p
);
345 sprintf(bp
, " type:%04x", ethertype
);
346 bp
= &msg
[strlen(msg
)];
348 /* ethernet packet length */
349 sprintf(bp
, " mblklen:%d", msgdsize(mp
));
350 bp
= &msg
[strlen(msg
)];
353 bp
= &msg
[strlen(msg
)];
354 for (tp
= mp
; tp
; tp
= tp
->b_cont
) {
356 sprintf(bp
, "%d", tp
->b_wptr
- tp
->b_rptr
);
358 sprintf(bp
, "+%d", tp
->b_wptr
- tp
->b_rptr
);
360 bp
= &msg
[strlen(msg
)];
363 bp
= &msg
[strlen(msg
)];
366 if (ethertype
!= ETHERTYPE_IP
) {
371 offset
+= sizeof (struct ether_header
);
374 iplen
= GET_NET16(&p
[2]);
375 sprintf(bp
, ", ip: %d.%d.%d.%d -> %d.%d.%d.%d proto:%d iplen:%d",
376 p
[12], p
[13], p
[14], p
[15],
377 p
[16], p
[17], p
[18], p
[19],
379 bp
= (void *)&msg
[strlen(msg
)];
381 iphlen
= (p
[0] & 0xf) * 4;
383 /* cksum for psuedo header */
384 cksum
= *(uint16_t *)&p
[12];
385 cksum
+= *(uint16_t *)&p
[14];
386 cksum
+= *(uint16_t *)&p
[16];
387 cksum
+= *(uint16_t *)&p
[18];
388 cksum
+= BE_16(ipproto
);
390 /* tcp or udp protocol header */
393 if (ipproto
== IPPROTO_TCP
) {
394 tcplen
= iplen
- iphlen
;
395 sprintf(bp
, ", tcp: len:%d cksum:%x",
396 tcplen
, GET_NET16(&p
[16]));
397 bp
= (void *)&msg
[strlen(msg
)];
400 cksum
+= BE_16(tcplen
);
401 cksum
= (uint16_t)ip_cksum(mp
, offset
, cksum
);
403 (cksum
== 0 || cksum
== 0xffff) ? "ok" : "ng");
404 bp
= (void *)&msg
[strlen(msg
)];
406 } else if (ipproto
== IPPROTO_UDP
) {
407 udplen
= GET_NET16(&p
[4]);
408 sprintf(bp
, ", udp: len:%d cksum:%x",
409 udplen
, GET_NET16(&p
[6]));
410 bp
= (void *)&msg
[strlen(msg
)];
412 if (GET_NET16(&p
[6]) && check_cksum
) {
413 cksum
+= *(uint16_t *)&p
[4];
414 cksum
= (uint16_t)ip_cksum(mp
, offset
, cksum
);
416 (cksum
== 0 || cksum
== 0xffff) ? "ok" : "ng");
417 bp
= (void *)&msg
[strlen(msg
)];
421 cmn_err(CE_CONT
, "!%s: %s: %s", dp
->name
, title
, msg
);
423 #endif /* USBGEM_DEBUG_VLAN */
424 #endif /* USBGEM_DEBUG_LEVEL */
426 #ifdef GEM_GCC_RUNTIME
428 * gcc3 runtime routines
432 memcmp(const void *s1
, const void *s2
, size_t n
)
438 for (i
= 0; i
< n
; i
++) {
439 ret
= (int)((uint8_t *)s1
)[i
] - (int)((uint8_t *)s2
)[i
];
449 memset(void *s
, int c
, size_t n
)
451 if ((c
& 0xff) == 0) {
455 ((uint8_t *)s
)[n
] = c
;
461 #pragma weak _memcpy = memcpy
464 memcpy(void *s1
, const void *s2
, size_t n
)
469 #endif /* GEM_GCC_RUNTIME */
470 /* ============================================================== */
472 * hardware operations
474 /* ============================================================== */
476 usbgem_hal_reset_chip(struct usbgem_dev
*dp
)
480 sema_p(&dp
->hal_op_lock
);
481 err
= (*dp
->ugc
.usbgc_reset_chip
)(dp
);
482 sema_v(&dp
->hal_op_lock
);
487 usbgem_hal_init_chip(struct usbgem_dev
*dp
)
491 sema_p(&dp
->hal_op_lock
);
492 err
= (*dp
->ugc
.usbgc_init_chip
)(dp
);
493 sema_v(&dp
->hal_op_lock
);
498 usbgem_hal_attach_chip(struct usbgem_dev
*dp
)
502 sema_p(&dp
->hal_op_lock
);
503 err
= (*dp
->ugc
.usbgc_attach_chip
)(dp
);
504 sema_v(&dp
->hal_op_lock
);
509 usbgem_hal_set_rx_filter(struct usbgem_dev
*dp
)
513 sema_p(&dp
->hal_op_lock
);
514 err
= (*dp
->ugc
.usbgc_set_rx_filter
)(dp
);
515 sema_v(&dp
->hal_op_lock
);
520 usbgem_hal_set_media(struct usbgem_dev
*dp
)
524 sema_p(&dp
->hal_op_lock
);
525 err
= (*dp
->ugc
.usbgc_set_media
)(dp
);
526 sema_v(&dp
->hal_op_lock
);
531 usbgem_hal_start_chip(struct usbgem_dev
*dp
)
535 sema_p(&dp
->hal_op_lock
);
536 err
= (*dp
->ugc
.usbgc_start_chip
)(dp
);
537 sema_v(&dp
->hal_op_lock
);
542 usbgem_hal_stop_chip(struct usbgem_dev
*dp
)
546 sema_p(&dp
->hal_op_lock
);
547 err
= (*dp
->ugc
.usbgc_stop_chip
)(dp
);
548 sema_v(&dp
->hal_op_lock
);
553 usbgem_hal_get_stats(struct usbgem_dev
*dp
)
557 sema_p(&dp
->hal_op_lock
);
558 err
= (*dp
->ugc
.usbgc_get_stats
)(dp
);
559 sema_v(&dp
->hal_op_lock
);
564 /* ============================================================== */
566 * USB pipe management
568 /* ============================================================== */
570 usbgem_rx_start_unit(struct usbgem_dev
*dp
, usb_bulk_req_t
*req
)
578 mp
= allocb(dp
->rx_buf_len
, BPRI_MED
);
580 cmn_err(CE_WARN
, "!%s: %s: failed to allocate mblk",
585 req
->bulk_len
= dp
->rx_buf_len
;
587 req
->bulk_client_private
= (usb_opaque_t
)dp
;
588 req
->bulk_timeout
= 0;
589 req
->bulk_attributes
= USB_ATTRS_SHORT_XFER_OK
;
590 req
->bulk_cb
= usbgem_bulkin_cb
;
591 req
->bulk_exc_cb
= usbgem_bulkin_cb
;
592 req
->bulk_completion_reason
= 0;
593 req
->bulk_cb_flags
= 0;
596 err
= usb_pipe_bulk_xfer(dp
->bulkin_pipe
, req
, flags
);
598 if (err
!= USB_SUCCESS
) {
599 cmn_err(CE_WARN
, "%s: failed to bulk_xfer for rx, err:%d",
602 /* free req and mp */
603 usb_free_bulk_req(req
);
611 /* ============================================================== */
613 * Rx/Tx buffer management
615 /* ============================================================== */
617 usbgem_init_rx_buf(struct usbgem_dev
*dp
)
622 ASSERT(dp
->mac_state
== MAC_STATE_ONLINE
);
624 for (i
= 0; i
< dp
->ugc
.usbgc_rx_list_max
; i
++) {
625 req
= usb_alloc_bulk_req(dp
->dip
, 0, USB_FLAGS_SLEEP
);
628 "!%s: %s: failed to allocate bulkreq for rx",
630 return (USB_FAILURE
);
632 if (!usbgem_rx_start_unit(dp
, req
)) {
633 return (USB_FAILURE
);
635 mutex_enter(&dp
->rxlock
);
637 mutex_exit(&dp
->rxlock
);
639 return (USB_SUCCESS
);
642 /* ============================================================== */
644 * memory resource management
646 /* ============================================================== */
648 usbgem_free_memory(struct usbgem_dev
*dp
)
652 /* free all tx requst structure */
653 while ((req
= dp
->tx_free_list
) != NULL
) {
655 (usb_bulk_req_t
*)req
->bulk_client_private
;
656 req
->bulk_data
= NULL
;
657 usb_free_bulk_req(req
);
659 return (USB_SUCCESS
);
663 usbgem_alloc_memory(struct usbgem_dev
*dp
)
668 /* allocate tx requests */
669 dp
->tx_free_list
= NULL
;
670 for (i
= 0; i
< dp
->ugc
.usbgc_tx_list_max
; i
++) {
671 req
= usb_alloc_bulk_req(dp
->dip
, 0, USB_FLAGS_SLEEP
);
674 "%s:%s failed to allocate tx requests",
677 /* free partially allocated tx requests */
678 (void) usbgem_free_memory(dp
);
679 return (USB_FAILURE
);
682 /* add the new one allocated into tx free list */
683 req
->bulk_client_private
= (usb_opaque_t
)dp
->tx_free_list
;
684 dp
->tx_free_list
= req
;
687 return (USB_SUCCESS
);
690 /* ========================================================== */
692 * Start transmission.
693 * Return zero on success,
695 /* ========================================================== */
697 #ifdef TXTIMEOUT_TEST
698 static int usbgem_send_cnt
= 0;
702 * usbgem_send is used only to send data packet into ethernet line.
705 usbgem_send_common(struct usbgem_dev
*dp
, mblk_t
*mp
, uint32_t flags
)
714 usb_flags_t usb_flags
= 0;
715 #ifdef USBGEM_DEBUG_LEVEL
716 usb_pipe_state_t p_state
;
718 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
720 intr
= (flags
& 1) != 0;
724 if (mp
->b_rptr
[0] & 1) {
725 if (bcmp(mp
->b_rptr
, &usbgem_bcastaddr
, ETHERADDRL
) == 0) {
731 new = (*dp
->ugc
.usbgc_tx_make_packet
)(dp
, mp
);
734 * no memory resource. we don't stop downstream,
735 * we just discard the packet.
737 DPRINTF(0, (CE_CONT
, "!%s: %s: no memory",
738 dp
->name
, __func__
));
741 mutex_enter(&dp
->txlock
);
742 dp
->stats
.noxmtbuf
++;
744 mutex_exit(&dp
->txlock
);
749 ASSERT(new->b_cont
== NULL
);
751 mutex_enter(&dp
->txlock
);
752 if (dp
->tx_free_list
== NULL
) {
756 ASSERT(dp
->tx_busy_cnt
== dp
->ugc
.usbgc_tx_list_max
);
757 mutex_exit(&dp
->txlock
);
759 DPRINTF(4, (CE_CONT
, "!%s: %s: no free slot",
760 dp
->name
, __func__
));
761 if (new && new != mp
) {
762 /* free reallocated message */
767 req
= dp
->tx_free_list
;
768 dp
->tx_free_list
= (usb_bulk_req_t
*)req
->bulk_client_private
;
771 if (dp
->tx_free_list
== NULL
) {
775 dp
->tx_intr_pended
++;
778 #ifdef USBGEM_DEBUG_LEVEL
779 new->b_datap
->db_cksum32
= dp
->tx_seq_num
;
782 dp
->stats
.obytes
+= len
;
783 dp
->stats
.opackets
++;
785 dp
->stats
.obcast
+= bcast
;
786 dp
->stats
.omcast
+= mcast
;
788 mutex_exit(&dp
->txlock
);
790 DPRINTF(2, (CE_CONT
, "!%s: %s: sending", dp
->name
, __func__
));
792 req
->bulk_len
= (long)new->b_wptr
- (long)new->b_rptr
;
793 req
->bulk_data
= new;
794 req
->bulk_client_private
= (usb_opaque_t
)dp
;
795 req
->bulk_timeout
= dp
->bulkout_timeout
; /* in second */
796 req
->bulk_attributes
= 0;
797 req
->bulk_cb
= usbgem_bulkout_cb
;
798 req
->bulk_exc_cb
= usbgem_bulkout_cb
;
799 req
->bulk_completion_reason
= 0;
800 req
->bulk_cb_flags
= 0;
803 usb_flags
= USB_FLAGS_SLEEP
;
805 if ((err
= usb_pipe_bulk_xfer(dp
->bulkout_pipe
, req
, usb_flags
))
808 /* failed to transfer the packet, discard it. */
810 req
->bulk_data
= NULL
;
812 /* recycle the request block */
813 mutex_enter(&dp
->txlock
);
815 req
->bulk_client_private
= (usb_opaque_t
)dp
->tx_free_list
;
816 dp
->tx_free_list
= req
;
817 mutex_exit(&dp
->txlock
);
820 "%s: %s: usb_pipe_bulk_xfer: failed: err:%d",
821 dp
->name
, __func__
, err
);
823 /* we use another flag to indicate error state. */
824 if (dp
->fatal_error
== (clock_t)0) {
825 dp
->fatal_error
= usbgem_timestamp_nz();
828 /* record the start time */
829 dp
->tx_start_time
= ddi_get_lbolt();
832 if (err
== USB_SUCCESS
&& (usb_flags
& USB_FLAGS_SLEEP
)) {
833 usbgem_bulkout_cb(dp
->bulkout_pipe
, req
);
843 usbgem_restart_nic(struct usbgem_dev
*dp
)
848 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
850 ASSERT(dp
->mac_state
!= MAC_STATE_DISCONNECTED
);
853 * ensure to stop the nic
855 if (dp
->mac_state
== MAC_STATE_ONLINE
) {
856 (void) usbgem_mac_stop(dp
, MAC_STATE_STOPPED
, STOP_GRACEFUL
);
859 /* now the nic become quiescent, reset the chip */
860 if (usbgem_hal_reset_chip(dp
) != USB_SUCCESS
) {
861 cmn_err(CE_WARN
, "%s: %s: failed to reset chip",
867 * restore the nic state step by step
869 if (dp
->nic_state
< NIC_STATE_INITIALIZED
) {
873 if (usbgem_mac_init(dp
) != USB_SUCCESS
) {
874 cmn_err(CE_WARN
, "%s: %s: failed to initialize chip",
879 /* setup mac address and enable rx filter */
880 sema_p(&dp
->rxfilter_lock
);
881 dp
->rxmode
|= RXMODE_ENABLE
;
882 ret
= usbgem_hal_set_rx_filter(dp
);
883 sema_v(&dp
->rxfilter_lock
);
884 if (ret
!= USB_SUCCESS
) {
889 * update the link state asynchronously
891 cv_signal(&dp
->link_watcher_wait_cv
);
894 * XXX - a panic happened because of linkdown.
895 * We must check mii_state here, because the link can be down just
896 * before the restart event happen. If the link is down now,
897 * gem_mac_start() will be called from gem_mii_link_check() when
898 * the link become up later.
900 if (dp
->mii_state
== MII_STATE_LINKUP
) {
901 if (usbgem_hal_set_media(dp
) != USB_SUCCESS
) {
904 if (dp
->nic_state
< NIC_STATE_ONLINE
) {
908 (void) usbgem_mac_start(dp
);
912 return (USB_SUCCESS
);
914 #ifdef GEM_CONFIG_FMA
915 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
917 return (USB_FAILURE
);
921 usbgem_tx_timeout(struct usbgem_dev
*dp
)
927 mutex_enter(&dp
->tx_watcher_lock
);
928 (void) cv_timedwait(&dp
->tx_watcher_cv
, &dp
->tx_watcher_lock
,
929 dp
->tx_watcher_interval
+ ddi_get_lbolt());
930 mutex_exit(&dp
->tx_watcher_lock
);
932 if (dp
->tx_watcher_stop
) {
936 now
= ddi_get_lbolt();
940 rw_enter(&dp
->dev_state_lock
, rwlock
);
942 if ((dp
->mac_state
!= MAC_STATE_DISCONNECTED
&&
944 now
- dp
->fatal_error
>= dp
->ugc
.usbgc_tx_timeout
) ||
945 (dp
->mac_state
== MAC_STATE_ONLINE
&&
946 dp
->mii_state
== MII_STATE_LINKUP
&&
947 dp
->tx_busy_cnt
!= 0 &&
948 now
- dp
->tx_start_time
>= dp
->ugc
.usbgc_tx_timeout
)) {
949 if (rwlock
== RW_READER
) {
951 * Upgrade dev_state_lock from shared mode
952 * to exclusive mode to restart nic
955 rw_exit(&dp
->dev_state_lock
);
958 cmn_err(CE_WARN
, "%s: %s: restarting the nic:"
959 " fatal_error:%ld nic_state:%d"
960 " mac_state:%d starttime:%ld",
962 dp
->fatal_error
? now
- dp
->fatal_error
: 0,
963 dp
->nic_state
, dp
->mac_state
,
964 dp
->tx_busy_cnt
? now
- dp
->tx_start_time
: 0);
966 (void) usbgem_restart_nic(dp
);
969 rw_exit(&dp
->dev_state_lock
);
974 usbgem_tx_watcher_start(struct usbgem_dev
*dp
)
979 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
981 /* make a first call of uwgem_lw_link_check() */
982 dp
->tx_watcher_stop
= 0;
983 dp
->tx_watcher_interval
= drv_usectohz(1000*1000);
985 wdth
= thread_create(NULL
, 0, usbgem_tx_timeout
, dp
, 0, &p0
,
986 TS_RUN
, minclsyspri
);
989 "!%s: %s: failed to create a tx_watcher thread",
991 return (USB_FAILURE
);
993 dp
->tx_watcher_did
= wdth
->t_did
;
995 return (USB_SUCCESS
);
999 usbgem_tx_watcher_stop(struct usbgem_dev
*dp
)
1001 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
1002 if (dp
->tx_watcher_did
) {
1003 /* Ensure timer routine stopped */
1004 dp
->tx_watcher_stop
= 1;
1005 cv_signal(&dp
->tx_watcher_cv
);
1006 thread_join(dp
->tx_watcher_did
);
1007 dp
->tx_watcher_did
= 0;
1011 /* ================================================================== */
1015 /* ================================================================== */
1017 usbgem_bulkin_cb(usb_pipe_handle_t pipe
, usb_bulk_req_t
*req
)
1027 struct usbgem_dev
*dp
;
1029 dp
= (struct usbgem_dev
*)req
->bulk_client_private
;
1030 mp
= req
->bulk_data
;
1031 req
->bulk_data
= NULL
;
1033 DPRINTF(2, (CE_CONT
, "!%s: %s: mp:%p, cr:%s(%d)",
1034 dp
->name
, __func__
, mp
,
1035 usb_str_cr(req
->bulk_completion_reason
),
1036 req
->bulk_completion_reason
));
1039 * we cannot acquire dev_state_lock because the routine
1040 * must be executed during usbgem_mac_stop() to avoid
1042 * we use a simle membar operation to get the state correctly.
1046 if (req
->bulk_completion_reason
== USB_CR_OK
&&
1047 dp
->nic_state
== NIC_STATE_ONLINE
) {
1048 newmp
= (*dp
->ugc
.usbgc_rx_make_packet
)(dp
, mp
);
1051 /* the message has been reallocated, free old one */
1055 /* the message may includes one or more ethernet packets */
1056 for (tp
= newmp
; tp
; tp
= tp
->b_next
) {
1057 len
+= (uintptr_t)tp
->b_wptr
- (uintptr_t)tp
->b_rptr
;
1059 if (tp
->b_rptr
[0] & 1) {
1060 if (bcmp(tp
->b_rptr
, &usbgem_bcastaddr
,
1069 /* send up if it is a valid packet */
1070 #ifdef USBGEM_CONFIG_GLDv3
1071 mac_rx(dp
->mh
, NULL
, newmp
);
1075 newmp
= newmp
->b_next
;
1077 gld_recv(dp
->macinfo
, tp
);
1085 mutex_enter(&dp
->rxlock
);
1086 /* update rx_active */
1087 if (dp
->rx_active
) {
1088 dp
->rx_active
= dp
->mac_state
== MAC_STATE_ONLINE
;
1091 dp
->stats
.rbytes
+= len
;
1092 dp
->stats
.rpackets
+= pkts
;
1093 if (bcast
| mcast
) {
1094 dp
->stats
.rbcast
+= bcast
;
1095 dp
->stats
.rmcast
+= mcast
;
1097 mutex_exit(&dp
->rxlock
);
1099 if (dp
->rx_active
) {
1100 /* prepare to receive the next packets */
1101 if (usbgem_rx_start_unit(dp
, req
)) {
1106 "!%s: %s: failed to fill next rx packet",
1107 dp
->name
, __func__
);
1109 * we use another flag to indicate error state.
1110 * if we acquire dev_state_lock for RW_WRITER here,
1111 * usbgem_mac_stop() may hang.
1113 if (dp
->fatal_error
== (clock_t)0) {
1114 dp
->fatal_error
= usbgem_timestamp_nz();
1117 /* no need to prepare the next packets */
1118 usb_free_bulk_req(req
);
1121 mutex_enter(&dp
->rxlock
);
1122 dp
->rx_active
= B_FALSE
;
1124 if (dp
->rx_busy_cnt
== 0) {
1125 /* wake up someone waits for me */
1126 cv_broadcast(&dp
->rx_drain_cv
);
1128 mutex_exit(&dp
->rxlock
);
1134 usbgem_bulkout_cb(usb_pipe_handle_t pipe
, usb_bulk_req_t
*req
)
1138 struct usbgem_dev
*dp
;
1140 dp
= (struct usbgem_dev
*)req
->bulk_client_private
;
1143 DPRINTF(2, (CE_CONT
,
1144 "!%s: %s: cr:%s(%d) cb_flags:0x%x head:%d tail:%d",
1146 usb_str_cr(req
->bulk_completion_reason
),
1147 req
->bulk_completion_reason
,
1151 /* we have finished to transfer the packet into tx fifo */
1152 intr
= DB_TCI(req
->bulk_data
);
1153 freemsg(req
->bulk_data
);
1155 if (req
->bulk_completion_reason
!= USB_CR_OK
&&
1156 dp
->fatal_error
== (clock_t)0) {
1157 dp
->fatal_error
= usbgem_timestamp_nz();
1160 mutex_enter(&dp
->txlock
);
1163 ASSERT(dp
->tx_intr_pended
> 0);
1164 /* find the last interrupt we have scheduled */
1165 if (--(dp
->tx_intr_pended
) == 0) {
1170 ASSERT(dp
->tx_busy_cnt
> 0);
1171 req
->bulk_client_private
= (usb_opaque_t
)dp
->tx_free_list
;
1172 dp
->tx_free_list
= req
;
1175 #ifdef CONFIG_TX_LIMITER
1177 dp
->tx_max_packets
=
1178 min(dp
->tx_max_packets
+ 1, dp
->ugc
.usbgc_tx_list_max
);
1181 if (dp
->mac_state
!= MAC_STATE_ONLINE
&& dp
->tx_busy_cnt
== 0) {
1182 cv_broadcast(&dp
->tx_drain_cv
);
1185 mutex_exit(&dp
->txlock
);
1188 #ifdef USBGEM_CONFIG_GLDv3
1189 mac_tx_update(dp
->mh
);
1191 gld_sched(dp
->macinfo
);
1197 usbgem_intr_cb(usb_pipe_handle_t ph
, usb_intr_req_t
*req
)
1199 struct usbgem_dev
*dp
;
1201 dp
= (struct usbgem_dev
*)req
->intr_client_private
;
1204 if (req
->intr_completion_reason
== USB_CR_OK
) {
1205 (*dp
->ugc
.usbgc_interrupt
)(dp
, req
->intr_data
);
1208 /* free the request and data */
1209 usb_free_intr_req(req
);
1212 /* ======================================================================== */
1214 * MII support routines
1216 /* ======================================================================== */
1218 usbgem_choose_forcedmode(struct usbgem_dev
*dp
)
1220 /* choose media mode */
1221 if (dp
->anadv_1000fdx
|| dp
->anadv_1000hdx
) {
1222 dp
->speed
= USBGEM_SPD_1000
;
1223 dp
->full_duplex
= dp
->anadv_1000fdx
;
1224 } else if (dp
->anadv_100fdx
|| dp
->anadv_100t4
) {
1225 dp
->speed
= USBGEM_SPD_100
;
1226 dp
->full_duplex
= B_TRUE
;
1227 } else if (dp
->anadv_100hdx
) {
1228 dp
->speed
= USBGEM_SPD_100
;
1229 dp
->full_duplex
= B_FALSE
;
1231 dp
->speed
= USBGEM_SPD_10
;
1232 dp
->full_duplex
= dp
->anadv_10fdx
;
1237 usbgem_mii_read(struct usbgem_dev
*dp
, uint_t reg
, int *errp
)
1241 sema_p(&dp
->hal_op_lock
);
1242 val
= (*dp
->ugc
.usbgc_mii_read
)(dp
, reg
, errp
);
1243 sema_v(&dp
->hal_op_lock
);
1249 usbgem_mii_write(struct usbgem_dev
*dp
, uint_t reg
, uint16_t val
, int *errp
)
1251 sema_p(&dp
->hal_op_lock
);
1252 (*dp
->ugc
.usbgc_mii_write
)(dp
, reg
, val
, errp
);
1253 sema_v(&dp
->hal_op_lock
);
1257 usbgem_mii_probe(struct usbgem_dev
*dp
)
1261 err
= (*dp
->ugc
.usbgc_mii_probe
)(dp
);
1266 usbgem_mii_init(struct usbgem_dev
*dp
)
1270 err
= (*dp
->ugc
.usbgc_mii_init
)(dp
);
1274 #define fc_cap_decode(x) \
1275 ((((x) & MII_ABILITY_PAUSE) != 0 ? 1 : 0) | \
1276 (((x) & MII_ABILITY_ASM_DIR) != 0 ? 2 : 0))
1279 usbgem_mii_config_default(struct usbgem_dev
*dp
, int *errp
)
1284 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
1287 * Configure bits in advertisement register
1289 mii_stat
= dp
->mii_status
;
1291 DPRINTF(1, (CE_CONT
, "!%s: %s: MII_STATUS reg:%b",
1292 dp
->name
, __func__
, mii_stat
, MII_STATUS_BITS
));
1294 if ((mii_stat
& MII_STATUS_ABILITY_TECH
) == 0) {
1296 cmn_err(CE_WARN
, "!%s: wrong ability bits: mii_status:%b",
1297 dp
->name
, mii_stat
, MII_STATUS_BITS
);
1298 return (USB_FAILURE
);
1301 /* Do not change the rest of ability bits in advert reg */
1302 val
= usbgem_mii_read(dp
, MII_AN_ADVERT
, errp
) & ~MII_ABILITY_ALL
;
1303 if (*errp
!= USB_SUCCESS
) {
1307 DPRINTF(0, (CE_CONT
,
1308 "!%s: %s: 100T4:%d 100F:%d 100H:%d 10F:%d 10H:%d",
1310 dp
->anadv_100t4
, dp
->anadv_100fdx
, dp
->anadv_100hdx
,
1311 dp
->anadv_10fdx
, dp
->anadv_10hdx
));
1313 /* set technology bits */
1314 if (dp
->anadv_100t4
) {
1315 val
|= MII_ABILITY_100BASE_T4
;
1317 if (dp
->anadv_100fdx
) {
1318 val
|= MII_ABILITY_100BASE_TX_FD
;
1320 if (dp
->anadv_100hdx
) {
1321 val
|= MII_ABILITY_100BASE_TX
;
1323 if (dp
->anadv_10fdx
) {
1324 val
|= MII_ABILITY_10BASE_T_FD
;
1326 if (dp
->anadv_10hdx
) {
1327 val
|= MII_ABILITY_10BASE_T
;
1330 /* set flow control capabilities */
1331 if (dp
->anadv_pause
) {
1332 val
|= MII_ABILITY_PAUSE
;
1334 if (dp
->anadv_asmpause
) {
1335 val
|= MII_ABILITY_ASM_DIR
;
1338 DPRINTF(0, (CE_CONT
,
1339 "!%s: %s: setting MII_AN_ADVERT reg:%b, pause:%d, asmpause:%d",
1340 dp
->name
, __func__
, val
, MII_ABILITY_BITS
,
1341 dp
->anadv_pause
, dp
->anadv_asmpause
));
1343 usbgem_mii_write(dp
, MII_AN_ADVERT
, val
, errp
);
1344 if (*errp
!= USB_SUCCESS
) {
1348 if (dp
->mii_status
& MII_STATUS_XSTATUS
) {
1350 * 1000Base-T GMII support
1352 if (!dp
->anadv_autoneg
) {
1353 /* enable manual configuration */
1354 val
= MII_1000TC_CFG_EN
;
1355 if (dp
->anadv_1000t_ms
== 2) {
1356 val
|= MII_1000TC_CFG_VAL
;
1360 if (dp
->anadv_1000fdx
) {
1361 val
|= MII_1000TC_ADV_FULL
;
1363 if (dp
->anadv_1000hdx
) {
1364 val
|= MII_1000TC_ADV_HALF
;
1366 switch (dp
->anadv_1000t_ms
) {
1369 val
|= MII_1000TC_CFG_EN
;
1374 val
|= MII_1000TC_CFG_EN
| MII_1000TC_CFG_VAL
;
1378 /* auto: do nothing */
1382 DPRINTF(0, (CE_CONT
,
1383 "!%s: %s: setting MII_1000TC reg:%b",
1384 dp
->name
, __func__
, val
, MII_1000TC_BITS
));
1386 usbgem_mii_write(dp
, MII_1000TC
, val
, errp
);
1387 if (*errp
!= USB_SUCCESS
) {
1391 return (USB_SUCCESS
);
1397 static char *usbgem_fc_type
[] = {
1404 #ifdef USBGEM_CONFIG_GLDv3
1405 #define USBGEM_LINKUP(dp) mac_link_update((dp)->mh, LINK_STATE_UP)
1406 #define USBGEM_LINKDOWN(dp) mac_link_update((dp)->mh, LINK_STATE_DOWN)
1408 #define USBGEM_LINKUP(dp) \
1409 if (gld_linkstate) { \
1410 gld_linkstate((dp)->macinfo, GLD_LINKSTATE_UP); \
1412 #define USBGEM_LINKDOWN(dp) \
1413 if (gld_linkstate) { \
1414 gld_linkstate((dp)->macinfo, GLD_LINKSTATE_DOWN); \
1418 static uint8_t usbgem_fc_result
[4 /* my cap */][4 /* lp cap */] = {
1419 /* none symm tx rx/symm */
1427 FLOW_CONTROL_SYMMETRIC
,
1429 FLOW_CONTROL_SYMMETRIC
},
1434 FLOW_CONTROL_TX_PAUSE
},
1437 FLOW_CONTROL_SYMMETRIC
,
1438 FLOW_CONTROL_RX_PAUSE
,
1439 FLOW_CONTROL_SYMMETRIC
},
1443 usbgem_mii_link_check(struct usbgem_dev
*dp
, int *oldstatep
, int *newstatep
)
1445 boolean_t tx_sched
= B_FALSE
;
1455 int linkdown_action
;
1456 boolean_t fix_phy
= B_FALSE
;
1460 DPRINTF(4, (CE_CONT
, "!%s: %s: time:%d state:%d",
1461 dp
->name
, __func__
, ddi_get_lbolt(), dp
->mii_state
));
1463 if (dp
->mii_state
!= MII_STATE_LINKUP
) {
1469 rw_enter(&dp
->dev_state_lock
, rwlock
);
1471 /* save old mii state */
1472 *oldstatep
= dp
->mii_state
;
1474 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
1475 /* stop periodic execution of the link watcher */
1476 dp
->mii_interval
= 0;
1481 now
= ddi_get_lbolt();
1482 diff
= now
- dp
->mii_last_check
;
1483 dp
->mii_last_check
= now
;
1486 * For NWAM, don't show linkdown state right
1487 * when the device is attached.
1489 if (dp
->linkup_delay
> 0) {
1490 if (dp
->linkup_delay
> diff
) {
1491 dp
->linkup_delay
-= diff
;
1493 /* link up timeout */
1494 dp
->linkup_delay
= -1;
1499 switch (dp
->mii_state
) {
1500 case MII_STATE_UNKNOWN
:
1503 case MII_STATE_RESETTING
:
1504 dp
->mii_timer
-= diff
;
1505 if (dp
->mii_timer
> 0) {
1506 /* don't read phy registers in resetting */
1507 dp
->mii_interval
= WATCH_INTERVAL_FAST
;
1511 val
= usbgem_mii_read(dp
, MII_CONTROL
, &err
);
1512 if (err
!= USB_SUCCESS
) {
1515 if (val
& MII_CONTROL_RESET
) {
1517 "!%s: time:%ld resetting phy not complete."
1518 " mii_control:0x%b",
1519 dp
->name
, ddi_get_lbolt(),
1520 val
, MII_CONTROL_BITS
);
1523 /* ensure neither isolated nor pwrdown nor auto-nego mode */
1524 usbgem_mii_write(dp
, MII_CONTROL
, 0, &err
);
1525 if (err
!= USB_SUCCESS
) {
1528 #if USBGEM_DEBUG_LEVEL > 10
1529 val
= usbgem_mii_read(dp
, MII_CONTROL
, &err
);
1530 cmn_err(CE_CONT
, "!%s: readback control %b",
1531 dp
->name
, val
, MII_CONTROL_BITS
);
1533 /* As resetting PHY has completed, configure PHY registers */
1534 if ((*dp
->ugc
.usbgc_mii_config
)(dp
, &err
) != USB_SUCCESS
) {
1535 /* we failed to configure PHY */
1539 /* prepare for forced mode */
1540 usbgem_choose_forcedmode(dp
);
1545 dp
->mii_ctl1000
= 0;
1546 dp
->mii_stat1000
= 0;
1548 dp
->flow_control
= FLOW_CONTROL_NONE
;
1550 if (!dp
->anadv_autoneg
) {
1551 /* skip auto-negotiation phase */
1552 dp
->mii_state
= MII_STATE_MEDIA_SETUP
;
1553 dp
->mii_timer
= dp
->ugc
.usbgc_mii_linkdown_timeout
;
1557 /* issue an auto-negotiation command */
1560 case MII_STATE_AUTONEGOTIATING
:
1562 * Autonegotiation in progress
1564 dp
->mii_timer
-= diff
;
1566 (dp
->ugc
.usbgc_mii_an_timeout
- dp
->ugc
.usbgc_mii_an_wait
)
1568 /* wait for minimum time (2.3 - 2.5 sec) */
1569 dp
->mii_interval
= WATCH_INTERVAL_FAST
;
1573 /* read PHY status */
1574 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
1575 if (err
!= USB_SUCCESS
) {
1578 DPRINTF(4, (CE_CONT
,
1579 "!%s: %s: called: mii_state:%d MII_STATUS reg:%b",
1580 dp
->name
, __func__
, dp
->mii_state
,
1581 status
, MII_STATUS_BITS
));
1583 if (status
& MII_STATUS_REMFAULT
) {
1585 * The link parnert told me something wrong happend.
1589 "!%s: auto-negotiation failed: remote fault",
1594 if ((status
& MII_STATUS_ANDONE
) == 0) {
1595 if (dp
->mii_timer
<= 0) {
1597 * Auto-negotiation has been timed out,
1598 * Reset PHY and try again.
1600 if (!dp
->mii_supress_msg
) {
1602 "!%s: auto-negotiation failed:"
1605 dp
->mii_supress_msg
= B_TRUE
;
1610 * Auto-negotiation is in progress. Wait for a while.
1612 dp
->mii_interval
= dp
->ugc
.usbgc_mii_an_watch_interval
;
1617 * Auto-negotiation has been completed. Let's go to AN_DONE.
1619 dp
->mii_state
= MII_STATE_AN_DONE
;
1620 dp
->mii_supress_msg
= B_FALSE
;
1621 DPRINTF(0, (CE_CONT
,
1622 "!%s: auto-negotiation completed, MII_STATUS:%b",
1623 dp
->name
, status
, MII_STATUS_BITS
));
1625 if (dp
->ugc
.usbgc_mii_an_delay
> 0) {
1626 dp
->mii_timer
= dp
->ugc
.usbgc_mii_an_delay
;
1627 dp
->mii_interval
= drv_usectohz(20*1000);
1635 case MII_STATE_AN_DONE
:
1637 * Auto-negotiation has done. Now we can set up media.
1639 dp
->mii_timer
-= diff
;
1640 if (dp
->mii_timer
> 0) {
1641 /* wait for a while */
1642 dp
->mii_interval
= WATCH_INTERVAL_FAST
;
1647 * Setup speed and duplex mode according with
1648 * the result of auto negotiation.
1652 * Read registers required to determin current
1653 * duplex mode and media speed.
1655 if (dp
->ugc
.usbgc_mii_an_delay
> 0) {
1656 /* the 'status' variable is not initialized yet */
1657 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
1658 if (err
!= USB_SUCCESS
) {
1662 advert
= usbgem_mii_read(dp
, MII_AN_ADVERT
, &err
);
1663 if (err
!= USB_SUCCESS
) {
1666 lpable
= usbgem_mii_read(dp
, MII_AN_LPABLE
, &err
);
1667 if (err
!= USB_SUCCESS
) {
1670 exp
= usbgem_mii_read(dp
, MII_AN_EXPANSION
, &err
);
1671 if (err
!= USB_SUCCESS
) {
1674 if (exp
== 0xffff) {
1675 /* some phys don't have exp register */
1681 if (dp
->mii_status
& MII_STATUS_XSTATUS
) {
1682 ctl1000
= usbgem_mii_read(dp
, MII_1000TC
, &err
);
1683 if (err
!= USB_SUCCESS
) {
1686 stat1000
= usbgem_mii_read(dp
, MII_1000TS
, &err
);
1687 if (err
!= USB_SUCCESS
) {
1691 dp
->mii_lpable
= lpable
;
1692 dp
->mii_advert
= advert
;
1694 dp
->mii_ctl1000
= ctl1000
;
1695 dp
->mii_stat1000
= stat1000
;
1698 "!%s: auto-negotiation done: "
1699 "status:%b, advert:%b, lpable:%b, exp:%b",
1701 status
, MII_STATUS_BITS
,
1702 advert
, MII_ABILITY_BITS
,
1703 lpable
, MII_ABILITY_BITS
,
1704 exp
, MII_AN_EXP_BITS
);
1706 DPRINTF(0, (CE_CONT
, "!%s: MII_STATUS:%b",
1707 dp
->name
, status
, MII_STATUS_BITS
));
1709 if (dp
->mii_status
& MII_STATUS_XSTATUS
) {
1711 "! MII_1000TC reg:%b, MII_1000TS reg:%b",
1712 ctl1000
, MII_1000TC_BITS
,
1713 stat1000
, MII_1000TS_BITS
);
1716 if (usbgem_population(lpable
) <= 1 &&
1717 (exp
& MII_AN_EXP_LPCANAN
) == 0) {
1718 if ((advert
& MII_ABILITY_TECH
) != lpable
) {
1720 "!%s: but the link partner doesn't seem"
1721 " to have auto-negotiation capability."
1722 " please check the link configuration.",
1726 * it should be a result of pararell detection,
1727 * which cannot detect duplex mode.
1729 if ((advert
& lpable
) == 0 &&
1730 lpable
& MII_ABILITY_10BASE_T
) {
1731 /* no common technology, try 10M half mode */
1732 lpable
|= advert
& MII_ABILITY_10BASE_T
;
1735 } else if (lpable
== 0) {
1736 cmn_err(CE_WARN
, "!%s: wrong lpable.", dp
->name
);
1740 * configure current link mode according to AN priority.
1742 val
= advert
& lpable
;
1743 if ((ctl1000
& MII_1000TC_ADV_FULL
) &&
1744 (stat1000
& MII_1000TS_LP_FULL
)) {
1745 /* 1000BaseT & full duplex */
1746 dp
->speed
= USBGEM_SPD_1000
;
1747 dp
->full_duplex
= B_TRUE
;
1748 } else if ((ctl1000
& MII_1000TC_ADV_HALF
) &&
1749 (stat1000
& MII_1000TS_LP_HALF
)) {
1750 /* 1000BaseT & half duplex */
1751 dp
->speed
= USBGEM_SPD_1000
;
1752 dp
->full_duplex
= B_FALSE
;
1753 } else if ((val
& MII_ABILITY_100BASE_TX_FD
)) {
1754 /* 100BaseTx & fullduplex */
1755 dp
->speed
= USBGEM_SPD_100
;
1756 dp
->full_duplex
= B_TRUE
;
1757 } else if ((val
& MII_ABILITY_100BASE_T4
)) {
1758 /* 100BaseTx & fullduplex */
1759 dp
->speed
= USBGEM_SPD_100
;
1760 dp
->full_duplex
= B_TRUE
;
1761 } else if ((val
& MII_ABILITY_100BASE_TX
)) {
1762 /* 100BaseTx & half duplex */
1763 dp
->speed
= USBGEM_SPD_100
;
1764 dp
->full_duplex
= B_FALSE
;
1765 } else if ((val
& MII_ABILITY_10BASE_T_FD
)) {
1766 /* 10BaseT & full duplex */
1767 dp
->speed
= USBGEM_SPD_10
;
1768 dp
->full_duplex
= B_TRUE
;
1769 } else if ((val
& MII_ABILITY_10BASE_T
)) {
1770 /* 10BaseT & half duplex */
1771 dp
->speed
= USBGEM_SPD_10
;
1772 dp
->full_duplex
= B_FALSE
;
1775 * the link partner doesn't seem to have
1776 * auto-negotiation capability and our PHY
1777 * could not report current mode correctly.
1778 * We guess current mode by mii_control register.
1780 val
= usbgem_mii_read(dp
, MII_CONTROL
, &err
);
1781 if (err
!= USB_SUCCESS
) {
1785 /* select 100m half or 10m half */
1786 dp
->speed
= (val
& MII_CONTROL_100MB
) ?
1787 USBGEM_SPD_100
: USBGEM_SPD_10
;
1788 dp
->full_duplex
= B_FALSE
;
1792 "!%s: auto-negotiation done but "
1793 "common ability not found.\n"
1794 "PHY state: control:%b advert:%b lpable:%b\n"
1795 "guessing %d Mbps %s duplex mode",
1797 val
, MII_CONTROL_BITS
,
1798 advert
, MII_ABILITY_BITS
,
1799 lpable
, MII_ABILITY_BITS
,
1800 usbgem_speed_value
[dp
->speed
],
1801 dp
->full_duplex
? "full" : "half");
1804 if (dp
->full_duplex
) {
1806 usbgem_fc_result
[fc_cap_decode(advert
)]
1807 [fc_cap_decode(lpable
)];
1809 dp
->flow_control
= FLOW_CONTROL_NONE
;
1811 dp
->mii_state
= MII_STATE_MEDIA_SETUP
;
1812 dp
->mii_timer
= dp
->ugc
.usbgc_mii_linkdown_timeout
;
1815 case MII_STATE_MEDIA_SETUP
:
1816 DPRINTF(2, (CE_CONT
, "!%s: setup midia mode", dp
->name
));
1818 /* assume the link state is down */
1819 dp
->mii_state
= MII_STATE_LINKDOWN
;
1820 dp
->mii_supress_msg
= B_FALSE
;
1822 /* use short interval */
1823 dp
->mii_interval
= WATCH_INTERVAL_FAST
;
1825 if ((!dp
->anadv_autoneg
) ||
1826 dp
->ugc
.usbgc_mii_an_oneshot
|| fix_phy
) {
1829 * write the result of auto negotiation back.
1831 val
= usbgem_mii_read(dp
, MII_CONTROL
, &err
);
1832 if (err
!= USB_SUCCESS
) {
1835 val
&= ~(MII_CONTROL_SPEED
| MII_CONTROL_FDUPLEX
|
1836 MII_CONTROL_ANE
| MII_CONTROL_RSAN
);
1838 if (dp
->full_duplex
) {
1839 val
|= MII_CONTROL_FDUPLEX
;
1842 switch (dp
->speed
) {
1843 case USBGEM_SPD_1000
:
1844 val
|= MII_CONTROL_1000MB
;
1847 case USBGEM_SPD_100
:
1848 val
|= MII_CONTROL_100MB
;
1852 cmn_err(CE_WARN
, "%s: unknown speed:%d",
1853 dp
->name
, dp
->speed
);
1857 /* for USBGEM_SPD_10, do nothing */
1861 if (dp
->mii_status
& MII_STATUS_XSTATUS
) {
1862 usbgem_mii_write(dp
,
1863 MII_1000TC
, MII_1000TC_CFG_EN
, &err
);
1864 if (err
!= USB_SUCCESS
) {
1868 usbgem_mii_write(dp
, MII_CONTROL
, val
, &err
);
1869 if (err
!= USB_SUCCESS
) {
1874 * XXX -- nic state should be one of
1875 * NIC_STATE_DISCONNECTED
1877 * NIC_STATE_INITIALIZED
1880 if (dp
->nic_state
>= NIC_STATE_INITIALIZED
) {
1881 /* notify the result of autonegotiation to mac */
1882 if (usbgem_hal_set_media(dp
) != USB_SUCCESS
) {
1888 case MII_STATE_LINKDOWN
:
1889 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
1890 if (err
!= USB_SUCCESS
) {
1893 if (status
& MII_STATUS_LINKUP
) {
1897 dp
->mii_state
= MII_STATE_LINKUP
;
1898 dp
->mii_supress_msg
= B_FALSE
;
1900 DPRINTF(0, (CE_CONT
,
1901 "!%s: link up detected: status:%b",
1902 dp
->name
, status
, MII_STATUS_BITS
));
1905 * MII_CONTROL_100MB and MII_CONTROL_FDUPLEX are
1906 * ignored when MII_CONTROL_ANE is set.
1909 "!%s: Link up: %d Mbps %s duplex %s flow control",
1911 usbgem_speed_value
[dp
->speed
],
1912 dp
->full_duplex
? "full" : "half",
1913 usbgem_fc_type
[dp
->flow_control
]);
1916 dp
->ugc
.usbgc_mii_link_watch_interval
;
1918 if (dp
->ugc
.usbgc_mii_hw_link_detection
&&
1919 dp
->nic_state
== NIC_STATE_ONLINE
) {
1920 dp
->mii_interval
= 0;
1923 if (dp
->nic_state
== NIC_STATE_ONLINE
) {
1924 if (dp
->mac_state
== MAC_STATE_INITIALIZED
) {
1925 (void) usbgem_mac_start(dp
);
1933 dp
->mii_supress_msg
= B_TRUE
;
1934 if (dp
->anadv_autoneg
) {
1935 dp
->mii_timer
-= diff
;
1936 if (dp
->mii_timer
<= 0) {
1938 * the link down timer expired.
1939 * need to restart auto-negotiation.
1942 dp
->ugc
.usbgc_mii_linkdown_timeout_action
;
1943 goto restart_autonego
;
1946 /* don't change mii_state */
1949 case MII_STATE_LINKUP
:
1950 if (rwlock
== RW_READER
) {
1951 /* first pass, read mii status */
1952 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
1953 if (err
!= USB_SUCCESS
) {
1957 if ((status
& MII_STATUS_LINKUP
) == 0) {
1959 * Link is going down
1962 "!%s: link down detected: status:%b",
1963 dp
->name
, status
, MII_STATUS_BITS
);
1965 * Acquire exclusive lock to change mii_state
1967 if (rwlock
== RW_READER
) {
1969 rw_exit(&dp
->dev_state_lock
);
1973 dp
->mii_state
= MII_STATE_LINKDOWN
;
1974 dp
->mii_timer
= dp
->ugc
.usbgc_mii_linkdown_timeout
;
1977 * As we may change the state of the device,
1978 * let us acquire exclusive lock for the state.
1980 if (dp
->nic_state
== NIC_STATE_ONLINE
&&
1981 dp
->mac_state
== MAC_STATE_ONLINE
&&
1982 dp
->ugc
.usbgc_mii_stop_mac_on_linkdown
) {
1983 (void) usbgem_restart_nic(dp
);
1988 if (dp
->anadv_autoneg
) {
1989 /* need to restart auto-negotiation */
1991 dp
->ugc
.usbgc_mii_linkdown_action
;
1992 goto restart_autonego
;
1995 * don't use hw link down detection until the link
1996 * status become stable for a while.
1999 dp
->ugc
.usbgc_mii_link_watch_interval
;
2005 * still link up, no need to change mii_state
2007 if (dp
->ugc
.usbgc_mii_hw_link_detection
&&
2008 dp
->nic_state
== NIC_STATE_ONLINE
) {
2010 * no need to check link status periodicly
2011 * if nic can generate interrupts when link go down.
2013 dp
->mii_interval
= 0;
2018 cmn_err(CE_PANIC
, "!%s: %s: not reached", dp
->name
, __func__
);
2021 * Actions for new state.
2024 switch (linkdown_action
) {
2025 case MII_ACTION_RESET
:
2026 if (!dp
->mii_supress_msg
) {
2027 cmn_err(CE_CONT
, "!%s: resetting PHY", dp
->name
);
2029 dp
->mii_supress_msg
= B_TRUE
;
2032 case MII_ACTION_NONE
:
2033 dp
->mii_supress_msg
= B_TRUE
;
2034 if (dp
->ugc
.usbgc_mii_an_oneshot
) {
2037 /* PHY will restart autonego automatically */
2038 dp
->mii_state
= MII_STATE_AUTONEGOTIATING
;
2039 dp
->mii_timer
= dp
->ugc
.usbgc_mii_an_timeout
;
2040 dp
->mii_interval
= dp
->ugc
.usbgc_mii_an_watch_interval
;
2043 case MII_ACTION_RSA
:
2044 if (!dp
->mii_supress_msg
) {
2045 cmn_err(CE_CONT
, "!%s: restarting auto-negotiation",
2048 dp
->mii_supress_msg
= B_TRUE
;
2052 cmn_err(CE_PANIC
, "!%s: unknowm linkdown action: %d",
2053 dp
->name
, dp
->ugc
.usbgc_mii_linkdown_action
);
2054 dp
->mii_supress_msg
= B_TRUE
;
2059 if (!dp
->mii_supress_msg
) {
2060 cmn_err(CE_CONT
, "!%s: resetting PHY", dp
->name
);
2062 dp
->mii_state
= MII_STATE_RESETTING
;
2063 dp
->mii_timer
= dp
->ugc
.usbgc_mii_reset_timeout
;
2064 if (!dp
->ugc
.usbgc_mii_dont_reset
) {
2065 usbgem_mii_write(dp
, MII_CONTROL
, MII_CONTROL_RESET
, &err
);
2066 if (err
!= USB_SUCCESS
) {
2070 dp
->mii_interval
= WATCH_INTERVAL_FAST
;
2074 if (!dp
->mii_supress_msg
) {
2075 cmn_err(CE_CONT
, "!%s: auto-negotiation started", dp
->name
);
2077 dp
->mii_state
= MII_STATE_AUTONEGOTIATING
;
2078 dp
->mii_timer
= dp
->ugc
.usbgc_mii_an_timeout
;
2080 /* start/restart autoneg */
2081 val
= usbgem_mii_read(dp
, MII_CONTROL
, &err
) &
2082 ~(MII_CONTROL_ISOLATE
| MII_CONTROL_PWRDN
| MII_CONTROL_RESET
);
2083 if (err
!= USB_SUCCESS
) {
2086 if (val
& MII_CONTROL_ANE
) {
2087 val
|= MII_CONTROL_RSAN
;
2089 usbgem_mii_write(dp
, MII_CONTROL
,
2090 val
| dp
->ugc
.usbgc_mii_an_cmd
| MII_CONTROL_ANE
, &err
);
2091 if (err
!= USB_SUCCESS
) {
2095 dp
->mii_interval
= dp
->ugc
.usbgc_mii_an_watch_interval
;
2099 dp
->mii_state
= MII_STATE_UNKNOWN
;
2100 dp
->mii_interval
= dp
->ugc
.usbgc_mii_link_watch_interval
;
2104 *newstatep
= dp
->mii_state
;
2105 rw_exit(&dp
->dev_state_lock
);
2110 usbgem_mii_link_watcher(struct usbgem_dev
*dp
)
2116 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2120 mutex_enter(&dp
->link_watcher_lock
);
2121 if (dp
->mii_interval
) {
2122 (void) cv_timedwait(&dp
->link_watcher_wait_cv
,
2123 &dp
->link_watcher_lock
,
2124 dp
->mii_interval
+ ddi_get_lbolt());
2126 cv_wait(&dp
->link_watcher_wait_cv
,
2127 &dp
->link_watcher_lock
);
2129 mutex_exit(&dp
->link_watcher_lock
);
2131 if (dp
->link_watcher_stop
) {
2135 /* we block callbacks from disconnect/suspend and restart */
2136 tx_sched
= usbgem_mii_link_check(dp
,
2137 &old_mii_state
, &new_mii_state
);
2140 * gld v2 notifier functions are not able to
2141 * be called with any locks in this layer.
2144 /* kick potentially stopped downstream */
2145 #ifdef USBGEM_CONFIG_GLDv3
2146 mac_tx_update(dp
->mh
);
2148 gld_sched(dp
->macinfo
);
2152 if (old_mii_state
!= new_mii_state
) {
2153 /* notify new mii link state */
2154 if (new_mii_state
== MII_STATE_LINKUP
) {
2155 dp
->linkup_delay
= 0;
2157 } else if (dp
->linkup_delay
<= 0) {
2158 USBGEM_LINKDOWN(dp
);
2160 } else if (dp
->linkup_delay
< 0) {
2161 /* first linkup timeout */
2162 dp
->linkup_delay
= 0;
2163 USBGEM_LINKDOWN(dp
);
2171 usbgem_mii_update_link(struct usbgem_dev
*dp
)
2173 cv_signal(&dp
->link_watcher_wait_cv
);
2177 usbgem_mii_probe_default(struct usbgem_dev
*dp
)
2186 DPRINTF(3, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2193 /* Try default phy first */
2194 if (dp
->mii_phy_addr
) {
2195 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
2196 if (err
!= USB_SUCCESS
) {
2199 if (status
!= 0xffff && status
!= 0x0000) {
2203 if (dp
->mii_phy_addr
< 0) {
2205 "!%s: failed to probe default internal and/or non-MII PHY",
2207 return (USB_FAILURE
);
2211 "!%s: failed to probe default MII PHY at %d",
2212 dp
->name
, dp
->mii_phy_addr
);
2215 /* Try all possible address */
2216 for (phy
= dp
->ugc
.usbgc_mii_addr_min
; phy
< 32; phy
++) {
2217 dp
->mii_phy_addr
= phy
;
2218 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
2219 if (err
!= USB_SUCCESS
) {
2220 DPRINTF(0, (CE_CONT
,
2221 "!%s: %s: mii_read(status) failed",
2222 dp
->name
, __func__
));
2226 if (status
!= 0xffff && status
!= 0x0000) {
2227 usbgem_mii_write(dp
, MII_CONTROL
, 0, &err
);
2228 if (err
!= USB_SUCCESS
) {
2229 DPRINTF(0, (CE_CONT
,
2230 "!%s: %s: mii_write(control) failed",
2231 dp
->name
, __func__
));
2237 for (phy
= dp
->ugc
.usbgc_mii_addr_min
; phy
< 32; phy
++) {
2238 dp
->mii_phy_addr
= phy
;
2239 usbgem_mii_write(dp
, MII_CONTROL
, 0, &err
);
2240 if (err
!= USB_SUCCESS
) {
2241 DPRINTF(0, (CE_CONT
,
2242 "!%s: %s: mii_write(control) failed",
2243 dp
->name
, __func__
));
2246 status
= usbgem_mii_read(dp
, MII_STATUS
, &err
);
2247 if (err
!= USB_SUCCESS
) {
2248 DPRINTF(0, (CE_CONT
,
2249 "!%s: %s: mii_read(status) failed",
2250 dp
->name
, __func__
));
2254 if (status
!= 0xffff && status
!= 0) {
2259 cmn_err(CE_NOTE
, "!%s: no MII PHY found", dp
->name
);
2260 return (USB_FAILURE
);
2263 dp
->mii_status
= status
;
2264 dp
->mii_status_ro
= ~status
;
2265 dp
->mii_phy_id
= usbgem_mii_read(dp
, MII_PHYIDH
, &err
) << 16;
2266 if (err
!= USB_SUCCESS
) {
2267 DPRINTF(0, (CE_CONT
,
2268 "!%s: %s: mii_read(PHYIDH) failed",
2269 dp
->name
, __func__
));
2272 dp
->mii_phy_id
|= usbgem_mii_read(dp
, MII_PHYIDL
, &err
);
2273 if (err
!= USB_SUCCESS
) {
2274 DPRINTF(0, (CE_CONT
,
2275 "!%s: %s: mii_read(PHYIDL) failed",
2276 dp
->name
, __func__
));
2280 if (dp
->mii_phy_addr
< 0) {
2281 cmn_err(CE_CONT
, "!%s: using internal/non-MII PHY(0x%08x)",
2282 dp
->name
, dp
->mii_phy_id
);
2284 cmn_err(CE_CONT
, "!%s: MII PHY (0x%08x) found at %d",
2285 dp
->name
, dp
->mii_phy_id
, dp
->mii_phy_addr
);
2289 "!%s: PHY control:%b, status:%b, advert:%b, lpar:%b, exp:%b",
2291 usbgem_mii_read(dp
, MII_CONTROL
, &err
), MII_CONTROL_BITS
,
2292 status
, MII_STATUS_BITS
,
2293 usbgem_mii_read(dp
, MII_AN_ADVERT
, &err
), MII_ABILITY_BITS
,
2294 usbgem_mii_read(dp
, MII_AN_LPABLE
, &err
), MII_ABILITY_BITS
,
2295 usbgem_mii_read(dp
, MII_AN_EXPANSION
, &err
), MII_AN_EXP_BITS
);
2297 dp
->mii_xstatus
= 0;
2298 if (status
& MII_STATUS_XSTATUS
) {
2299 dp
->mii_xstatus
= usbgem_mii_read(dp
, MII_XSTATUS
, &err
);
2301 cmn_err(CE_CONT
, "!%s: xstatus:%b",
2302 dp
->name
, dp
->mii_xstatus
, MII_XSTATUS_BITS
);
2304 dp
->mii_xstatus_ro
= ~dp
->mii_xstatus
;
2306 /* check if the phy can advertize pause abilities */
2307 adv_org
= usbgem_mii_read(dp
, MII_AN_ADVERT
, &err
);
2308 if (err
!= USB_SUCCESS
) {
2312 usbgem_mii_write(dp
, MII_AN_ADVERT
,
2313 MII_ABILITY_PAUSE
| MII_ABILITY_ASM_DIR
, &err
);
2314 if (err
!= USB_SUCCESS
) {
2318 adv
= usbgem_mii_read(dp
, MII_AN_ADVERT
, &err
);
2319 if (err
!= USB_SUCCESS
) {
2323 if ((adv
& MII_ABILITY_PAUSE
) == 0) {
2324 dp
->ugc
.usbgc_flow_control
&= ~1;
2327 if ((adv
& MII_ABILITY_ASM_DIR
) == 0) {
2328 dp
->ugc
.usbgc_flow_control
&= ~2;
2331 usbgem_mii_write(dp
, MII_AN_ADVERT
, adv_org
, &err
);
2332 if (err
!= USB_SUCCESS
) {
2335 return (USB_SUCCESS
);
2338 return (USB_FAILURE
);
2342 usbgem_mii_init_default(struct usbgem_dev
*dp
)
2345 return (USB_SUCCESS
);
2349 usbgem_mii_start(struct usbgem_dev
*dp
)
2354 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2356 /* make a first call of usbgem_mii_link_check() */
2357 dp
->link_watcher_stop
= 0;
2358 dp
->mii_state
= MII_STATE_UNKNOWN
;
2359 dp
->mii_interval
= drv_usectohz(1000*1000); /* 1sec */
2360 dp
->mii_last_check
= ddi_get_lbolt();
2361 dp
->linkup_delay
= 600 * drv_usectohz(1000*1000); /* 10 minutes */
2363 lwth
= thread_create(NULL
, 0, usbgem_mii_link_watcher
, dp
, 0, &p0
,
2364 TS_RUN
, minclsyspri
);
2367 "!%s: %s: failed to create a link watcher thread",
2368 dp
->name
, __func__
);
2369 return (USB_FAILURE
);
2371 dp
->link_watcher_did
= lwth
->t_did
;
2373 return (USB_SUCCESS
);
2377 usbgem_mii_stop(struct usbgem_dev
*dp
)
2379 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2381 /* Ensure timer routine stopped */
2382 dp
->link_watcher_stop
= 1;
2383 cv_signal(&dp
->link_watcher_wait_cv
);
2384 thread_join(dp
->link_watcher_did
);
2387 /* ============================================================== */
2389 * internal mac register operation interface
2391 /* ============================================================== */
2393 * usbgem_mac_init: cold start
2396 usbgem_mac_init(struct usbgem_dev
*dp
)
2400 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2402 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
2403 /* pretend we succeeded */
2404 return (USB_SUCCESS
);
2407 ASSERT(dp
->mac_state
== MAC_STATE_STOPPED
);
2409 /* reset fatal error timestamp */
2410 dp
->fatal_error
= (clock_t)0;
2412 /* reset tx side state */
2413 mutex_enter(&dp
->txlock
);
2414 dp
->tx_busy_cnt
= 0;
2415 dp
->tx_max_packets
= dp
->ugc
.usbgc_tx_list_max
;
2416 mutex_exit(&dp
->txlock
);
2418 /* reset rx side state */
2419 mutex_enter(&dp
->rxlock
);
2420 dp
->rx_busy_cnt
= 0;
2421 mutex_exit(&dp
->rxlock
);
2423 err
= usbgem_hal_init_chip(dp
);
2424 if (err
== USB_SUCCESS
) {
2425 dp
->mac_state
= MAC_STATE_INITIALIZED
;
2432 * usbgem_mac_start: warm start
2435 usbgem_mac_start(struct usbgem_dev
*dp
)
2439 usb_flags_t flags
= 0;
2440 usb_intr_req_t
*req
;
2441 #ifdef USBGEM_DEBUG_LEVEL
2442 usb_pipe_state_t p_state
;
2444 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2446 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
2447 /* do nothing but don't return failure */
2448 return (USB_SUCCESS
);
2451 if (dp
->mac_state
!= MAC_STATE_INITIALIZED
) {
2452 /* don't return failer */
2453 DPRINTF(0, (CE_CONT
,
2454 "!%s: %s: mac_state(%d) is not MAC_STATE_INITIALIZED",
2455 dp
->name
, __func__
, dp
->mac_state
));
2459 dp
->mac_state
= MAC_STATE_ONLINE
;
2461 if (usbgem_hal_start_chip(dp
) != USB_SUCCESS
) {
2463 "!%s: %s: usb error was detected during start_chip",
2464 dp
->name
, __func__
);
2468 #ifdef USBGEM_DEBUG_LEVEL
2469 usb_pipe_get_state(dp
->intr_pipe
, &p_state
, 0);
2470 ASSERT(p_state
== USB_PIPE_STATE_IDLE
);
2471 #endif /* USBGEM_DEBUG_LEVEL */
2473 if (dp
->ugc
.usbgc_interrupt
&& dp
->intr_pipe
) {
2475 /* make a request for interrupt */
2477 req
= usb_alloc_intr_req(dp
->dip
, 0, USB_FLAGS_SLEEP
);
2479 cmn_err(CE_WARN
, "!%s: %s: failed to allocate intreq",
2480 dp
->name
, __func__
);
2483 req
->intr_data
= NULL
;
2484 req
->intr_client_private
= (usb_opaque_t
)dp
;
2485 req
->intr_timeout
= 0;
2486 req
->intr_attributes
=
2487 USB_ATTRS_SHORT_XFER_OK
| USB_ATTRS_AUTOCLEARING
;
2488 req
->intr_len
= dp
->ep_intr
->wMaxPacketSize
;
2489 req
->intr_cb
= usbgem_intr_cb
;
2490 req
->intr_exc_cb
= usbgem_intr_cb
;
2491 req
->intr_completion_reason
= 0;
2492 req
->intr_cb_flags
= 0;
2494 err
= usb_pipe_intr_xfer(dp
->intr_pipe
, req
, flags
);
2495 if (err
!= USB_SUCCESS
) {
2497 "%s: err:%d failed to start polling of intr pipe",
2503 /* kick to receive the first packet */
2504 if (usbgem_init_rx_buf(dp
) != USB_SUCCESS
) {
2507 dp
->rx_active
= B_TRUE
;
2509 return (USB_SUCCESS
);
2512 /* stop the interrupt pipe */
2513 DPRINTF(0, (CE_CONT
, "!%s: %s: FAULURE", dp
->name
, __func__
));
2514 if (dp
->ugc
.usbgc_interrupt
&& dp
->intr_pipe
) {
2515 usb_pipe_stop_intr_polling(dp
->intr_pipe
, USB_FLAGS_SLEEP
);
2518 ASSERT(dp
->mac_state
== MAC_STATE_ONLINE
);
2519 /* we use another flag to indicate error state. */
2520 if (dp
->fatal_error
== (clock_t)0) {
2521 dp
->fatal_error
= usbgem_timestamp_nz();
2523 return (USB_FAILURE
);
2527 usbgem_mac_stop(struct usbgem_dev
*dp
, int new_state
, boolean_t graceful
)
2529 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2532 * we must have writer lock for dev_state_lock
2534 ASSERT(new_state
== MAC_STATE_STOPPED
||
2535 new_state
== MAC_STATE_DISCONNECTED
);
2537 /* stop polling interrupt pipe */
2538 if (dp
->ugc
.usbgc_interrupt
&& dp
->intr_pipe
) {
2539 usb_pipe_stop_intr_polling(dp
->intr_pipe
, USB_FLAGS_SLEEP
);
2542 if (new_state
== MAC_STATE_STOPPED
|| graceful
) {
2543 /* stop the nic hardware completely */
2544 if (usbgem_hal_stop_chip(dp
) != USB_SUCCESS
) {
2545 (void) usbgem_hal_reset_chip(dp
);
2549 /* stop preparing new rx packets and sending new packets */
2550 dp
->mac_state
= new_state
;
2552 /* other processors must get mac_state correctly after here */
2555 /* cancel all requests we have sent */
2556 usb_pipe_reset(dp
->dip
, dp
->bulkin_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
2557 usb_pipe_reset(dp
->dip
, dp
->bulkout_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
2559 DPRINTF(0, (CE_CONT
,
2560 "!%s: %s: rx_busy_cnt:%d tx_busy_cnt:%d",
2561 dp
->name
, __func__
, dp
->rx_busy_cnt
, dp
->tx_busy_cnt
));
2564 * Here all rx packets has been cancelled and their call back
2565 * function has been exeuted, because we called usb_pipe_reset
2567 * So actually we just ensure rx_busy_cnt == 0.
2569 mutex_enter(&dp
->rxlock
);
2570 while (dp
->rx_busy_cnt
> 0) {
2571 cv_wait(&dp
->rx_drain_cv
, &dp
->rxlock
);
2573 mutex_exit(&dp
->rxlock
);
2575 DPRINTF(0, (CE_CONT
, "!%s: %s: rx_busy_cnt is %d now",
2576 dp
->name
, __func__
, dp
->rx_busy_cnt
));
2578 mutex_enter(&dp
->txlock
);
2579 while (dp
->tx_busy_cnt
> 0) {
2580 cv_wait(&dp
->tx_drain_cv
, &dp
->txlock
);
2582 mutex_exit(&dp
->txlock
);
2584 DPRINTF(0, (CE_CONT
, "!%s: %s: tx_busy_cnt is %d now",
2585 dp
->name
, __func__
, dp
->tx_busy_cnt
));
2587 return (USB_SUCCESS
);
2591 usbgem_add_multicast(struct usbgem_dev
*dp
, const uint8_t *ep
)
2596 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2598 sema_p(&dp
->rxfilter_lock
);
2599 if (dp
->mc_count_req
++ < USBGEM_MAXMC
) {
2600 /* append the new address at the end of the mclist */
2602 bcopy(ep
, dp
->mc_list
[cnt
].addr
.ether_addr_octet
,
2604 if (dp
->ugc
.usbgc_multicast_hash
) {
2605 dp
->mc_list
[cnt
].hash
=
2606 (*dp
->ugc
.usbgc_multicast_hash
)(dp
, ep
);
2608 dp
->mc_count
= cnt
+ 1;
2611 if (dp
->mc_count_req
!= dp
->mc_count
) {
2612 /* multicast address list overflow */
2613 dp
->rxmode
|= RXMODE_MULTI_OVF
;
2615 dp
->rxmode
&= ~RXMODE_MULTI_OVF
;
2618 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
2619 /* tell new multicast list to the hardware */
2620 err
= usbgem_hal_set_rx_filter(dp
);
2622 sema_v(&dp
->rxfilter_lock
);
2628 usbgem_remove_multicast(struct usbgem_dev
*dp
, const uint8_t *ep
)
2635 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
2637 sema_p(&dp
->rxfilter_lock
);
2640 for (i
= 0; i
< cnt
; i
++) {
2641 if (bcmp(ep
, &dp
->mc_list
[i
].addr
, ETHERADDRL
)) {
2644 /* shrink the mclist by copying forward */
2645 len
= (cnt
- (i
+ 1)) * sizeof (*dp
->mc_list
);
2647 bcopy(&dp
->mc_list
[i
+1], &dp
->mc_list
[i
], len
);
2653 if (dp
->mc_count_req
!= dp
->mc_count
) {
2654 /* multicast address list overflow */
2655 dp
->rxmode
|= RXMODE_MULTI_OVF
;
2657 dp
->rxmode
&= ~RXMODE_MULTI_OVF
;
2660 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
2661 err
= usbgem_hal_set_rx_filter(dp
);
2663 sema_v(&dp
->rxfilter_lock
);
2669 /* ============================================================== */
2673 /* ============================================================== */
2675 IOC_INVAL
= -1, /* bad, NAK with EINVAL */
2676 IOC_DONE
, /* OK, reply sent */
2677 IOC_ACK
, /* OK, just send ACK */
2678 IOC_REPLY
, /* OK, just send reply */
2679 IOC_RESTART_ACK
, /* OK, restart & ACK */
2680 IOC_RESTART_REPLY
/* OK, restart & reply */
2684 #ifdef USBGEM_CONFIG_MAC_PROP
2686 usbgem_get_def_val(struct usbgem_dev
*dp
, mac_prop_id_t pr_num
,
2687 uint_t pr_valsize
, void *pr_val
)
2692 ASSERT(pr_valsize
> 0);
2694 case MAC_PROP_AUTONEG
:
2695 *(uint8_t *)pr_val
=
2696 BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
);
2699 case MAC_PROP_FLOWCTRL
:
2700 if (pr_valsize
< sizeof (link_flowctrl_t
)) {
2703 switch (dp
->ugc
.usbgc_flow_control
) {
2704 case FLOW_CONTROL_NONE
:
2705 fl
= LINK_FLOWCTRL_NONE
;
2707 case FLOW_CONTROL_SYMMETRIC
:
2708 fl
= LINK_FLOWCTRL_BI
;
2710 case FLOW_CONTROL_TX_PAUSE
:
2711 fl
= LINK_FLOWCTRL_TX
;
2713 case FLOW_CONTROL_RX_PAUSE
:
2714 fl
= LINK_FLOWCTRL_RX
;
2717 bcopy(&fl
, pr_val
, sizeof (fl
));
2720 case MAC_PROP_ADV_1000FDX_CAP
:
2721 case MAC_PROP_EN_1000FDX_CAP
:
2722 *(uint8_t *)pr_val
=
2723 (dp
->mii_xstatus
& MII_XSTATUS_1000BASET_FD
) ||
2724 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX_FD
);
2727 case MAC_PROP_ADV_1000HDX_CAP
:
2728 case MAC_PROP_EN_1000HDX_CAP
:
2729 *(uint8_t *)pr_val
=
2730 (dp
->mii_xstatus
& MII_XSTATUS_1000BASET
) ||
2731 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX
);
2734 case MAC_PROP_ADV_100T4_CAP
:
2735 case MAC_PROP_EN_100T4_CAP
:
2736 *(uint8_t *)pr_val
=
2737 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASE_T4
);
2740 case MAC_PROP_ADV_100FDX_CAP
:
2741 case MAC_PROP_EN_100FDX_CAP
:
2742 *(uint8_t *)pr_val
=
2743 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
);
2746 case MAC_PROP_ADV_100HDX_CAP
:
2747 case MAC_PROP_EN_100HDX_CAP
:
2748 *(uint8_t *)pr_val
=
2749 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
);
2752 case MAC_PROP_ADV_10FDX_CAP
:
2753 case MAC_PROP_EN_10FDX_CAP
:
2754 *(uint8_t *)pr_val
=
2755 BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
);
2758 case MAC_PROP_ADV_10HDX_CAP
:
2759 case MAC_PROP_EN_10HDX_CAP
:
2760 *(uint8_t *)pr_val
=
2761 BOOLEAN(dp
->mii_status
& MII_STATUS_10
);
2771 #ifdef MAC_VERSION_V1
2773 usbgem_m_propinfo(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
2774 mac_prop_info_handle_t prh
)
2776 struct usbgem_dev
*dp
= arg
;
2780 * By default permissions are read/write unless specified
2781 * otherwise by the driver.
2785 case MAC_PROP_DUPLEX
:
2786 case MAC_PROP_SPEED
:
2787 case MAC_PROP_STATUS
:
2788 case MAC_PROP_ADV_1000FDX_CAP
:
2789 case MAC_PROP_ADV_1000HDX_CAP
:
2790 case MAC_PROP_ADV_100FDX_CAP
:
2791 case MAC_PROP_ADV_100HDX_CAP
:
2792 case MAC_PROP_ADV_10FDX_CAP
:
2793 case MAC_PROP_ADV_10HDX_CAP
:
2794 case MAC_PROP_ADV_100T4_CAP
:
2795 case MAC_PROP_EN_100T4_CAP
:
2796 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2799 case MAC_PROP_EN_1000FDX_CAP
:
2800 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET_FD
) == 0) {
2801 mac_prop_info_set_default_uint8(prh
,
2803 dp
->mii_xstatus
& MII_XSTATUS_1000BASET_FD
));
2804 } else if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX_FD
)
2806 mac_prop_info_set_default_uint8(prh
,
2808 dp
->mii_xstatus
& MII_XSTATUS_1000BASEX_FD
));
2810 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2814 case MAC_PROP_EN_1000HDX_CAP
:
2815 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET
) == 0) {
2816 mac_prop_info_set_default_uint8(prh
,
2818 dp
->mii_xstatus
& MII_XSTATUS_1000BASET
));
2819 } else if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX
) == 0) {
2820 mac_prop_info_set_default_uint8(prh
,
2822 dp
->mii_xstatus
& MII_XSTATUS_1000BASEX
));
2824 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2828 case MAC_PROP_EN_100FDX_CAP
:
2829 if ((dp
->mii_status_ro
& MII_STATUS_100_BASEX_FD
) == 0) {
2830 mac_prop_info_set_default_uint8(prh
,
2831 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
));
2833 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2837 case MAC_PROP_EN_100HDX_CAP
:
2838 if ((dp
->mii_status_ro
& MII_STATUS_100_BASEX
) == 0) {
2839 mac_prop_info_set_default_uint8(prh
,
2840 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
));
2842 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2846 case MAC_PROP_EN_10FDX_CAP
:
2847 if ((dp
->mii_status_ro
& MII_STATUS_10_FD
) == 0) {
2848 mac_prop_info_set_default_uint8(prh
,
2849 BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
));
2851 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2855 case MAC_PROP_EN_10HDX_CAP
:
2856 if ((dp
->mii_status_ro
& MII_STATUS_10
) == 0) {
2857 mac_prop_info_set_default_uint8(prh
,
2858 BOOLEAN(dp
->mii_status
& MII_STATUS_10
));
2860 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2864 case MAC_PROP_AUTONEG
:
2865 if ((dp
->mii_status_ro
& MII_STATUS_CANAUTONEG
) == 0) {
2866 mac_prop_info_set_default_uint8(prh
,
2867 BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
));
2869 mac_prop_info_set_perm(prh
, MAC_PROP_PERM_READ
);
2873 case MAC_PROP_FLOWCTRL
:
2874 switch (dp
->ugc
.usbgc_flow_control
) {
2875 case FLOW_CONTROL_NONE
:
2876 fl
= LINK_FLOWCTRL_NONE
;
2878 case FLOW_CONTROL_SYMMETRIC
:
2879 fl
= LINK_FLOWCTRL_BI
;
2881 case FLOW_CONTROL_TX_PAUSE
:
2882 fl
= LINK_FLOWCTRL_TX
;
2884 case FLOW_CONTROL_RX_PAUSE
:
2885 fl
= LINK_FLOWCTRL_RX
;
2888 mac_prop_info_set_default_link_flowctrl(prh
, fl
);
2892 mac_prop_info_set_range_uint32(prh
,
2893 dp
->ugc
.usbgc_min_mtu
, dp
->ugc
.usbgc_max_mtu
);
2896 case MAC_PROP_PRIVATE
:
2903 usbgem_m_setprop(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
2904 uint_t pr_valsize
, const void *pr_val
)
2906 struct usbgem_dev
*dp
= arg
;
2908 boolean_t update
= B_FALSE
;
2909 link_flowctrl_t flowctrl
;
2910 uint32_t cur_mtu
, new_mtu
;
2912 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
2914 case MAC_PROP_EN_1000FDX_CAP
:
2915 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET_FD
) == 0 ||
2916 (dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX_FD
) == 0) {
2917 if (dp
->anadv_1000fdx
!= *(uint8_t *)pr_val
) {
2918 dp
->anadv_1000fdx
= *(uint8_t *)pr_val
;
2926 case MAC_PROP_EN_1000HDX_CAP
:
2927 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET
) == 0 ||
2928 (dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX
) == 0) {
2929 if (dp
->anadv_1000hdx
!= *(uint8_t *)pr_val
) {
2930 dp
->anadv_1000hdx
= *(uint8_t *)pr_val
;
2938 case MAC_PROP_EN_100FDX_CAP
:
2939 if ((dp
->mii_status_ro
& MII_STATUS_100_BASEX_FD
) == 0) {
2940 if (dp
->anadv_100fdx
!= *(uint8_t *)pr_val
) {
2941 dp
->anadv_100fdx
= *(uint8_t *)pr_val
;
2949 case MAC_PROP_EN_100HDX_CAP
:
2950 if ((dp
->mii_status_ro
& MII_STATUS_100_BASEX
) == 0) {
2951 if (dp
->anadv_100hdx
!= *(uint8_t *)pr_val
) {
2952 dp
->anadv_100hdx
= *(uint8_t *)pr_val
;
2960 case MAC_PROP_EN_10FDX_CAP
:
2961 if ((dp
->mii_status_ro
& MII_STATUS_10_FD
) == 0) {
2962 if (dp
->anadv_10fdx
!= *(uint8_t *)pr_val
) {
2963 dp
->anadv_10fdx
= *(uint8_t *)pr_val
;
2971 case MAC_PROP_EN_10HDX_CAP
:
2972 if ((dp
->mii_status_ro
& MII_STATUS_10_FD
) == 0) {
2973 if (dp
->anadv_10hdx
!= *(uint8_t *)pr_val
) {
2974 dp
->anadv_10hdx
= *(uint8_t *)pr_val
;
2982 case MAC_PROP_AUTONEG
:
2983 if ((dp
->mii_status_ro
& MII_STATUS_CANAUTONEG
) == 0) {
2984 if (dp
->anadv_autoneg
!= *(uint8_t *)pr_val
) {
2985 dp
->anadv_autoneg
= *(uint8_t *)pr_val
;
2993 case MAC_PROP_FLOWCTRL
:
2994 bcopy(pr_val
, &flowctrl
, sizeof (flowctrl
));
3001 case LINK_FLOWCTRL_NONE
:
3002 if (dp
->flow_control
!= FLOW_CONTROL_NONE
) {
3003 dp
->flow_control
= FLOW_CONTROL_NONE
;
3008 case LINK_FLOWCTRL_RX
:
3009 if (dp
->flow_control
!= FLOW_CONTROL_RX_PAUSE
) {
3010 dp
->flow_control
= FLOW_CONTROL_RX_PAUSE
;
3015 case LINK_FLOWCTRL_TX
:
3016 if (dp
->flow_control
!= FLOW_CONTROL_TX_PAUSE
) {
3017 dp
->flow_control
= FLOW_CONTROL_TX_PAUSE
;
3022 case LINK_FLOWCTRL_BI
:
3023 if (dp
->flow_control
!= FLOW_CONTROL_SYMMETRIC
) {
3024 dp
->flow_control
= FLOW_CONTROL_SYMMETRIC
;
3031 case MAC_PROP_ADV_1000FDX_CAP
:
3032 case MAC_PROP_ADV_1000HDX_CAP
:
3033 case MAC_PROP_ADV_100FDX_CAP
:
3034 case MAC_PROP_ADV_100HDX_CAP
:
3035 case MAC_PROP_ADV_10FDX_CAP
:
3036 case MAC_PROP_ADV_10HDX_CAP
:
3037 case MAC_PROP_STATUS
:
3038 case MAC_PROP_SPEED
:
3039 case MAC_PROP_DUPLEX
:
3040 err
= ENOTSUP
; /* read-only prop. Can't set this. */
3044 bcopy(pr_val
, &new_mtu
, sizeof (new_mtu
));
3045 if (new_mtu
!= dp
->mtu
) {
3050 case MAC_PROP_PRIVATE
:
3061 usbgem_choose_forcedmode(dp
);
3062 dp
->mii_state
= MII_STATE_UNKNOWN
;
3063 cv_signal(&dp
->link_watcher_wait_cv
);
3065 rw_exit(&dp
->dev_state_lock
);
3070 #ifdef MAC_VERSION_V1
3071 usbgem_m_getprop(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
3072 uint_t pr_valsize
, void *pr_val
)
3074 usbgem_m_getprop(void *arg
, const char *pr_name
, mac_prop_id_t pr_num
,
3075 uint_t pr_flags
, uint_t pr_valsize
, void *pr_val
, uint_t
*perm
)
3078 struct usbgem_dev
*dp
= arg
;
3080 link_flowctrl_t flowctrl
;
3083 if (pr_valsize
== 0) {
3086 #ifndef MAC_VERSION_V1
3087 *perm
= MAC_PROP_PERM_RW
;
3089 bzero(pr_val
, pr_valsize
);
3090 #ifndef MAC_VERSION_V1
3091 if ((pr_flags
& MAC_PROP_DEFAULT
) && (pr_num
!= MAC_PROP_PRIVATE
)) {
3092 return (usbgem_get_def_val(dp
, pr_num
, pr_valsize
, pr_val
));
3095 rw_enter(&dp
->dev_state_lock
, RW_READER
);
3097 case MAC_PROP_DUPLEX
:
3098 #ifndef MAC_VERSION_V1
3099 *perm
= MAC_PROP_PERM_READ
;
3101 if (pr_valsize
>= sizeof (link_duplex_t
)) {
3102 if (dp
->mii_state
!= MII_STATE_LINKUP
) {
3103 *(link_duplex_t
*)pr_val
= LINK_DUPLEX_UNKNOWN
;
3104 } else if (dp
->full_duplex
) {
3105 *(link_duplex_t
*)pr_val
= LINK_DUPLEX_FULL
;
3107 *(link_duplex_t
*)pr_val
= LINK_DUPLEX_HALF
;
3113 case MAC_PROP_SPEED
:
3114 #ifndef MAC_VERSION_V1
3115 *perm
= MAC_PROP_PERM_READ
;
3117 if (pr_valsize
>= sizeof (uint64_t)) {
3118 switch (dp
->speed
) {
3119 case USBGEM_SPD_1000
:
3122 case USBGEM_SPD_100
:
3131 bcopy(&tmp
, pr_val
, sizeof (tmp
));
3137 case MAC_PROP_AUTONEG
:
3138 #ifndef MAC_VERSION_V1
3139 if (dp
->mii_status_ro
& MII_STATUS_CANAUTONEG
) {
3140 *perm
= MAC_PROP_PERM_READ
;
3143 *(uint8_t *)pr_val
= dp
->anadv_autoneg
;
3146 case MAC_PROP_FLOWCTRL
:
3147 if (pr_valsize
>= sizeof (link_flowctrl_t
)) {
3148 switch (dp
->flow_control
) {
3149 case FLOW_CONTROL_NONE
:
3150 flowctrl
= LINK_FLOWCTRL_NONE
;
3152 case FLOW_CONTROL_RX_PAUSE
:
3153 flowctrl
= LINK_FLOWCTRL_RX
;
3155 case FLOW_CONTROL_TX_PAUSE
:
3156 flowctrl
= LINK_FLOWCTRL_TX
;
3158 case FLOW_CONTROL_SYMMETRIC
:
3159 flowctrl
= LINK_FLOWCTRL_BI
;
3162 bcopy(&flowctrl
, pr_val
, sizeof (flowctrl
));
3168 case MAC_PROP_ADV_1000FDX_CAP
:
3169 case MAC_PROP_ADV_1000HDX_CAP
:
3170 case MAC_PROP_ADV_100FDX_CAP
:
3171 case MAC_PROP_ADV_100HDX_CAP
:
3172 case MAC_PROP_ADV_10FDX_CAP
:
3173 case MAC_PROP_ADV_10HDX_CAP
:
3174 case MAC_PROP_ADV_100T4_CAP
:
3175 usbgem_get_def_val(dp
, pr_num
, pr_valsize
, pr_val
);
3178 case MAC_PROP_EN_1000FDX_CAP
:
3179 #ifndef MAC_VERSION_V1
3180 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET_FD
) &&
3181 (dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX_FD
)) {
3182 *perm
= MAC_PROP_PERM_READ
;
3185 *(uint8_t *)pr_val
= dp
->anadv_1000fdx
;
3188 case MAC_PROP_EN_1000HDX_CAP
:
3189 #ifndef MAC_VERSION_V1
3190 if ((dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASET
) &&
3191 (dp
->mii_xstatus_ro
& MII_XSTATUS_1000BASEX
)) {
3192 *perm
= MAC_PROP_PERM_READ
;
3195 *(uint8_t *)pr_val
= dp
->anadv_1000hdx
;
3198 case MAC_PROP_EN_100FDX_CAP
:
3199 #ifndef MAC_VERSION_V1
3200 if (dp
->mii_status_ro
& MII_STATUS_100_BASEX_FD
) {
3201 *perm
= MAC_PROP_PERM_READ
;
3204 *(uint8_t *)pr_val
= dp
->anadv_100fdx
;
3207 case MAC_PROP_EN_100HDX_CAP
:
3208 #ifndef MAC_VERSION_V1
3209 if (dp
->mii_status_ro
& MII_STATUS_100_BASEX
) {
3210 *perm
= MAC_PROP_PERM_READ
;
3213 *(uint8_t *)pr_val
= dp
->anadv_100hdx
;
3216 case MAC_PROP_EN_10FDX_CAP
:
3217 #ifndef MAC_VERSION_V1
3218 if (dp
->mii_status_ro
& MII_STATUS_10_FD
) {
3219 *perm
= MAC_PROP_PERM_READ
;
3222 *(uint8_t *)pr_val
= dp
->anadv_10fdx
;
3225 case MAC_PROP_EN_10HDX_CAP
:
3226 #ifndef MAC_VERSION_V1
3227 if (dp
->mii_status_ro
& MII_STATUS_10
) {
3228 *perm
= MAC_PROP_PERM_READ
;
3231 *(uint8_t *)pr_val
= dp
->anadv_10hdx
;
3234 case MAC_PROP_EN_100T4_CAP
:
3235 #ifndef MAC_VERSION_V1
3236 if (dp
->mii_status_ro
& MII_STATUS_100_BASE_T4
) {
3237 *perm
= MAC_PROP_PERM_READ
;
3240 *(uint8_t *)pr_val
= dp
->anadv_100t4
;
3243 case MAC_PROP_PRIVATE
:
3247 #ifndef MAC_VERSION_V1
3248 case MAC_PROP_MTU
: {
3249 mac_propval_range_t range
;
3250 if (!(pr_flags
& MAC_PROP_POSSIBLE
)) {
3254 if (pr_valsize
< sizeof (mac_propval_range_t
)) {
3258 range
.mpr_count
= 1;
3259 range
.mpr_type
= MAC_PROPVAL_UINT32
;
3260 range
.range_uint32
[0].mpur_min
= ETHERMTU
;
3261 range
.range_uint32
[0].mpur_max
= dp
->mtu
;
3262 bcopy(&range
, pr_val
, sizeof (range
));
3271 rw_exit(&dp
->dev_state_lock
);
3274 #endif /* USBGEM_CONFIG_MAC_PROP */
3276 #ifdef USBGEM_CONFIG_ND
3277 /* ============================================================== */
3281 /* ============================================================== */
3285 PARAM_ASYM_PAUSE_CAP
,
3294 PARAM_ADV_AUTONEG_CAP
,
3295 PARAM_ADV_PAUSE_CAP
,
3296 PARAM_ADV_ASYM_PAUSE_CAP
,
3297 PARAM_ADV_1000FDX_CAP
,
3298 PARAM_ADV_1000HDX_CAP
,
3299 PARAM_ADV_100T4_CAP
,
3300 PARAM_ADV_100FDX_CAP
,
3301 PARAM_ADV_100HDX_CAP
,
3302 PARAM_ADV_10FDX_CAP
,
3303 PARAM_ADV_10HDX_CAP
,
3306 PARAM_LP_AUTONEG_CAP
,
3308 PARAM_LP_ASYM_PAUSE_CAP
,
3309 PARAM_LP_1000FDX_CAP
,
3310 PARAM_LP_1000HDX_CAP
,
3312 PARAM_LP_100FDX_CAP
,
3313 PARAM_LP_100HDX_CAP
,
3322 PARAM_LINK_RX_PAUSE
,
3323 PARAM_LINK_TX_PAUSE
,
3334 struct usbgem_nd_arg
{
3335 struct usbgem_dev
*dp
;
3340 usbgem_param_get(queue_t
*q
, mblk_t
*mp
, caddr_t arg
, cred_t
*credp
)
3342 struct usbgem_dev
*dp
= ((struct usbgem_nd_arg
*)(void *)arg
)->dp
;
3343 int item
= ((struct usbgem_nd_arg
*)(void *)arg
)->item
;
3346 DPRINTF(1, (CE_CONT
, "!%s: %s: called, item:%d",
3347 dp
->name
, __func__
, item
));
3350 case PARAM_AUTONEG_CAP
:
3351 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
);
3352 DPRINTF(1, (CE_CONT
, "autoneg_cap:%d", val
));
3355 case PARAM_PAUSE_CAP
:
3356 val
= dp
->ugc
.usbgc_flow_control
!= FLOW_CONTROL_NONE
;
3359 case PARAM_ASYM_PAUSE_CAP
:
3360 val
= dp
->ugc
.usbgc_flow_control
> FLOW_CONTROL_SYMMETRIC
;
3363 case PARAM_1000FDX_CAP
:
3364 val
= (dp
->mii_xstatus
& MII_XSTATUS_1000BASET_FD
) ||
3365 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX_FD
);
3368 case PARAM_1000HDX_CAP
:
3369 val
= (dp
->mii_xstatus
& MII_XSTATUS_1000BASET
) ||
3370 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX
);
3373 case PARAM_100T4_CAP
:
3374 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASE_T4
);
3377 case PARAM_100FDX_CAP
:
3378 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
);
3381 case PARAM_100HDX_CAP
:
3382 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
);
3385 case PARAM_10FDX_CAP
:
3386 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
);
3389 case PARAM_10HDX_CAP
:
3390 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_10
);
3393 case PARAM_ADV_AUTONEG_CAP
:
3394 val
= dp
->anadv_autoneg
;
3397 case PARAM_ADV_PAUSE_CAP
:
3398 val
= dp
->anadv_pause
;
3401 case PARAM_ADV_ASYM_PAUSE_CAP
:
3402 val
= dp
->anadv_asmpause
;
3405 case PARAM_ADV_1000FDX_CAP
:
3406 val
= dp
->anadv_1000fdx
;
3409 case PARAM_ADV_1000HDX_CAP
:
3410 val
= dp
->anadv_1000hdx
;
3413 case PARAM_ADV_100T4_CAP
:
3414 val
= dp
->anadv_100t4
;
3417 case PARAM_ADV_100FDX_CAP
:
3418 val
= dp
->anadv_100fdx
;
3421 case PARAM_ADV_100HDX_CAP
:
3422 val
= dp
->anadv_100hdx
;
3425 case PARAM_ADV_10FDX_CAP
:
3426 val
= dp
->anadv_10fdx
;
3429 case PARAM_ADV_10HDX_CAP
:
3430 val
= dp
->anadv_10hdx
;
3433 case PARAM_ADV_1000T_MS
:
3434 val
= dp
->anadv_1000t_ms
;
3437 case PARAM_LP_AUTONEG_CAP
:
3438 val
= BOOLEAN(dp
->mii_exp
& MII_AN_EXP_LPCANAN
);
3441 case PARAM_LP_PAUSE_CAP
:
3442 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_PAUSE
);
3445 case PARAM_LP_ASYM_PAUSE_CAP
:
3446 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_ASM_DIR
);
3449 case PARAM_LP_1000FDX_CAP
:
3450 val
= BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_FULL
);
3453 case PARAM_LP_1000HDX_CAP
:
3454 val
= BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_HALF
);
3457 case PARAM_LP_100T4_CAP
:
3458 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_T4
);
3461 case PARAM_LP_100FDX_CAP
:
3462 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX_FD
);
3465 case PARAM_LP_100HDX_CAP
:
3466 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX
);
3469 case PARAM_LP_10FDX_CAP
:
3470 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T_FD
);
3473 case PARAM_LP_10HDX_CAP
:
3474 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T
);
3477 case PARAM_LINK_STATUS
:
3478 val
= (dp
->mii_state
== MII_STATE_LINKUP
);
3481 case PARAM_LINK_SPEED
:
3482 val
= usbgem_speed_value
[dp
->speed
];
3485 case PARAM_LINK_DUPLEX
:
3487 if (dp
->mii_state
== MII_STATE_LINKUP
) {
3488 val
= dp
->full_duplex
? 2 : 1;
3492 case PARAM_LINK_AUTONEG
:
3493 val
= BOOLEAN(dp
->mii_exp
& MII_AN_EXP_LPCANAN
);
3496 case PARAM_LINK_RX_PAUSE
:
3497 val
= (dp
->flow_control
== FLOW_CONTROL_SYMMETRIC
) ||
3498 (dp
->flow_control
== FLOW_CONTROL_RX_PAUSE
);
3501 case PARAM_LINK_TX_PAUSE
:
3502 val
= (dp
->flow_control
== FLOW_CONTROL_SYMMETRIC
) ||
3503 (dp
->flow_control
== FLOW_CONTROL_TX_PAUSE
);
3507 case PARAM_RESUME_TEST
:
3512 cmn_err(CE_WARN
, "%s: unimplemented ndd control (%d)",
3517 (void) mi_mpprintf(mp
, "%ld", val
);
3523 usbgem_param_set(queue_t
*q
,
3524 mblk_t
*mp
, char *value
, caddr_t arg
, cred_t
*credp
)
3526 struct usbgem_dev
*dp
= ((struct usbgem_nd_arg
*)(void *)arg
)->dp
;
3527 int item
= ((struct usbgem_nd_arg
*)(void *)arg
)->item
;
3531 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
3532 if (ddi_strtol(value
, &end
, 10, &val
)) {
3540 case PARAM_ADV_AUTONEG_CAP
:
3541 if (val
!= 0 && val
!= 1) {
3544 if (val
&& (dp
->mii_status
& MII_STATUS_CANAUTONEG
) == 0) {
3547 dp
->anadv_autoneg
= (int)val
;
3550 case PARAM_ADV_PAUSE_CAP
:
3551 if (val
!= 0 && val
!= 1) {
3554 if (val
&& dp
->ugc
.usbgc_flow_control
== FLOW_CONTROL_NONE
) {
3557 dp
->anadv_pause
= (int)val
;
3560 case PARAM_ADV_ASYM_PAUSE_CAP
:
3561 if (val
!= 0 && val
!= 1) {
3565 dp
->ugc
.usbgc_flow_control
<= FLOW_CONTROL_SYMMETRIC
) {
3568 dp
->anadv_asmpause
= (int)val
;
3571 case PARAM_ADV_1000FDX_CAP
:
3572 if (val
!= 0 && val
!= 1) {
3575 if (val
&& (dp
->mii_xstatus
&
3576 (MII_XSTATUS_1000BASET_FD
|
3577 MII_XSTATUS_1000BASEX_FD
)) == 0) {
3580 dp
->anadv_1000fdx
= (int)val
;
3583 case PARAM_ADV_1000HDX_CAP
:
3584 if (val
!= 0 && val
!= 1) {
3587 if (val
&& (dp
->mii_xstatus
&
3588 (MII_XSTATUS_1000BASET
| MII_XSTATUS_1000BASEX
)) == 0) {
3591 dp
->anadv_1000hdx
= (int)val
;
3594 case PARAM_ADV_100T4_CAP
:
3595 if (val
!= 0 && val
!= 1) {
3598 if (val
&& (dp
->mii_status
& MII_STATUS_100_BASE_T4
) == 0) {
3601 dp
->anadv_100t4
= (int)val
;
3604 case PARAM_ADV_100FDX_CAP
:
3605 if (val
!= 0 && val
!= 1) {
3608 if (val
&& (dp
->mii_status
& MII_STATUS_100_BASEX_FD
) == 0) {
3611 dp
->anadv_100fdx
= (int)val
;
3614 case PARAM_ADV_100HDX_CAP
:
3615 if (val
!= 0 && val
!= 1) {
3618 if (val
&& (dp
->mii_status
& MII_STATUS_100_BASEX
) == 0) {
3621 dp
->anadv_100hdx
= (int)val
;
3624 case PARAM_ADV_10FDX_CAP
:
3625 if (val
!= 0 && val
!= 1) {
3628 if (val
&& (dp
->mii_status
& MII_STATUS_10_FD
) == 0) {
3631 dp
->anadv_10fdx
= (int)val
;
3634 case PARAM_ADV_10HDX_CAP
:
3635 if (val
!= 0 && val
!= 1) {
3638 if (val
&& (dp
->mii_status
& MII_STATUS_10
) == 0) {
3641 dp
->anadv_10hdx
= (int)val
;
3644 case PARAM_ADV_1000T_MS
:
3645 if (val
!= 0 && val
!= 1 && val
!= 2) {
3648 if (val
&& (dp
->mii_xstatus
&
3649 (MII_XSTATUS_1000BASET
| MII_XSTATUS_1000BASET_FD
)) == 0) {
3652 dp
->anadv_1000t_ms
= (int)val
;
3656 case PARAM_RESUME_TEST
:
3657 mutex_exit(&dp
->xmitlock
);
3658 mutex_exit(&dp
->intrlock
);
3659 gem_suspend(dp
->dip
);
3660 gem_resume(dp
->dip
);
3661 mutex_enter(&dp
->intrlock
);
3662 mutex_enter(&dp
->xmitlock
);
3668 usbgem_choose_forcedmode(dp
);
3670 dp
->mii_state
= MII_STATE_UNKNOWN
;
3671 if (dp
->ugc
.usbgc_mii_hw_link_detection
) {
3672 /* wake up link watcher possiblely sleeps */
3673 cv_signal(&dp
->link_watcher_wait_cv
);
3682 usbgem_nd_load(struct usbgem_dev
*dp
,
3683 char *name
, ndgetf_t gf
, ndsetf_t sf
, int item
)
3685 struct usbgem_nd_arg
*arg
;
3688 ASSERT(item
< PARAM_COUNT
);
3690 arg
= &((struct usbgem_nd_arg
*)(void *)dp
->nd_arg_p
)[item
];
3694 DPRINTF(2, (CE_CONT
, "!%s: %s: name:%s, item:%d",
3695 dp
->name
, __func__
, name
, item
));
3696 (void) nd_load(&dp
->nd_data_p
, name
, gf
, sf
, (caddr_t
)arg
);
3700 usbgem_nd_setup(struct usbgem_dev
*dp
)
3702 DPRINTF(1, (CE_CONT
, "!%s: %s: called, mii_status:0x%b",
3703 dp
->name
, __func__
, dp
->mii_status
, MII_STATUS_BITS
));
3705 ASSERT(dp
->nd_arg_p
== NULL
);
3708 kmem_zalloc(sizeof (struct usbgem_nd_arg
) * PARAM_COUNT
, KM_SLEEP
);
3710 #define SETFUNC(x) ((x) ? usbgem_param_set : NULL)
3712 usbgem_nd_load(dp
, "autoneg_cap",
3713 usbgem_param_get
, NULL
, PARAM_AUTONEG_CAP
);
3714 usbgem_nd_load(dp
, "pause_cap",
3715 usbgem_param_get
, NULL
, PARAM_PAUSE_CAP
);
3716 usbgem_nd_load(dp
, "asym_pause_cap",
3717 usbgem_param_get
, NULL
, PARAM_ASYM_PAUSE_CAP
);
3718 usbgem_nd_load(dp
, "1000fdx_cap",
3719 usbgem_param_get
, NULL
, PARAM_1000FDX_CAP
);
3720 usbgem_nd_load(dp
, "1000hdx_cap",
3721 usbgem_param_get
, NULL
, PARAM_1000HDX_CAP
);
3722 usbgem_nd_load(dp
, "100T4_cap",
3723 usbgem_param_get
, NULL
, PARAM_100T4_CAP
);
3724 usbgem_nd_load(dp
, "100fdx_cap",
3725 usbgem_param_get
, NULL
, PARAM_100FDX_CAP
);
3726 usbgem_nd_load(dp
, "100hdx_cap",
3727 usbgem_param_get
, NULL
, PARAM_100HDX_CAP
);
3728 usbgem_nd_load(dp
, "10fdx_cap",
3729 usbgem_param_get
, NULL
, PARAM_10FDX_CAP
);
3730 usbgem_nd_load(dp
, "10hdx_cap",
3731 usbgem_param_get
, NULL
, PARAM_10HDX_CAP
);
3733 /* Our advertised capabilities */
3734 usbgem_nd_load(dp
, "adv_autoneg_cap", usbgem_param_get
,
3735 SETFUNC(dp
->mii_status
& MII_STATUS_CANAUTONEG
),
3736 PARAM_ADV_AUTONEG_CAP
);
3737 usbgem_nd_load(dp
, "adv_pause_cap", usbgem_param_get
,
3738 SETFUNC(dp
->ugc
.usbgc_flow_control
& 1),
3739 PARAM_ADV_PAUSE_CAP
);
3740 usbgem_nd_load(dp
, "adv_asym_pause_cap", usbgem_param_get
,
3741 SETFUNC(dp
->ugc
.usbgc_flow_control
& 2),
3742 PARAM_ADV_ASYM_PAUSE_CAP
);
3743 usbgem_nd_load(dp
, "adv_1000fdx_cap", usbgem_param_get
,
3744 SETFUNC(dp
->mii_xstatus
&
3745 (MII_XSTATUS_1000BASEX_FD
| MII_XSTATUS_1000BASET_FD
)),
3746 PARAM_ADV_1000FDX_CAP
);
3747 usbgem_nd_load(dp
, "adv_1000hdx_cap", usbgem_param_get
,
3748 SETFUNC(dp
->mii_xstatus
&
3749 (MII_XSTATUS_1000BASEX
| MII_XSTATUS_1000BASET
)),
3750 PARAM_ADV_1000HDX_CAP
);
3751 usbgem_nd_load(dp
, "adv_100T4_cap", usbgem_param_get
,
3752 SETFUNC((dp
->mii_status
& MII_STATUS_100_BASE_T4
) &&
3753 !dp
->mii_advert_ro
),
3754 PARAM_ADV_100T4_CAP
);
3755 usbgem_nd_load(dp
, "adv_100fdx_cap", usbgem_param_get
,
3756 SETFUNC((dp
->mii_status
& MII_STATUS_100_BASEX_FD
) &&
3757 !dp
->mii_advert_ro
),
3758 PARAM_ADV_100FDX_CAP
);
3759 usbgem_nd_load(dp
, "adv_100hdx_cap", usbgem_param_get
,
3760 SETFUNC((dp
->mii_status
& MII_STATUS_100_BASEX
) &&
3761 !dp
->mii_advert_ro
),
3762 PARAM_ADV_100HDX_CAP
);
3763 usbgem_nd_load(dp
, "adv_10fdx_cap", usbgem_param_get
,
3764 SETFUNC((dp
->mii_status
& MII_STATUS_10_FD
) &&
3765 !dp
->mii_advert_ro
),
3766 PARAM_ADV_10FDX_CAP
);
3767 usbgem_nd_load(dp
, "adv_10hdx_cap", usbgem_param_get
,
3768 SETFUNC((dp
->mii_status
& MII_STATUS_10
) &&
3769 !dp
->mii_advert_ro
),
3770 PARAM_ADV_10HDX_CAP
);
3771 usbgem_nd_load(dp
, "adv_1000t_ms", usbgem_param_get
,
3772 SETFUNC(dp
->mii_xstatus
&
3773 (MII_XSTATUS_1000BASET_FD
| MII_XSTATUS_1000BASET
)),
3774 PARAM_ADV_1000T_MS
);
3777 /* Partner's advertised capabilities */
3778 usbgem_nd_load(dp
, "lp_autoneg_cap",
3779 usbgem_param_get
, NULL
, PARAM_LP_AUTONEG_CAP
);
3780 usbgem_nd_load(dp
, "lp_pause_cap",
3781 usbgem_param_get
, NULL
, PARAM_LP_PAUSE_CAP
);
3782 usbgem_nd_load(dp
, "lp_asym_pause_cap",
3783 usbgem_param_get
, NULL
, PARAM_LP_ASYM_PAUSE_CAP
);
3784 usbgem_nd_load(dp
, "lp_1000fdx_cap",
3785 usbgem_param_get
, NULL
, PARAM_LP_1000FDX_CAP
);
3786 usbgem_nd_load(dp
, "lp_1000hdx_cap",
3787 usbgem_param_get
, NULL
, PARAM_LP_1000HDX_CAP
);
3788 usbgem_nd_load(dp
, "lp_100T4_cap",
3789 usbgem_param_get
, NULL
, PARAM_LP_100T4_CAP
);
3790 usbgem_nd_load(dp
, "lp_100fdx_cap",
3791 usbgem_param_get
, NULL
, PARAM_LP_100FDX_CAP
);
3792 usbgem_nd_load(dp
, "lp_100hdx_cap",
3793 usbgem_param_get
, NULL
, PARAM_LP_100HDX_CAP
);
3794 usbgem_nd_load(dp
, "lp_10fdx_cap",
3795 usbgem_param_get
, NULL
, PARAM_LP_10FDX_CAP
);
3796 usbgem_nd_load(dp
, "lp_10hdx_cap",
3797 usbgem_param_get
, NULL
, PARAM_LP_10HDX_CAP
);
3799 /* Current operating modes */
3800 usbgem_nd_load(dp
, "link_status",
3801 usbgem_param_get
, NULL
, PARAM_LINK_STATUS
);
3802 usbgem_nd_load(dp
, "link_speed",
3803 usbgem_param_get
, NULL
, PARAM_LINK_SPEED
);
3804 usbgem_nd_load(dp
, "link_duplex",
3805 usbgem_param_get
, NULL
, PARAM_LINK_DUPLEX
);
3806 usbgem_nd_load(dp
, "link_autoneg",
3807 usbgem_param_get
, NULL
, PARAM_LINK_AUTONEG
);
3808 usbgem_nd_load(dp
, "link_rx_pause",
3809 usbgem_param_get
, NULL
, PARAM_LINK_RX_PAUSE
);
3810 usbgem_nd_load(dp
, "link_tx_pause",
3811 usbgem_param_get
, NULL
, PARAM_LINK_TX_PAUSE
);
3813 usbgem_nd_load(dp
, "resume_test",
3814 usbgem_param_get
, usbgem_param_set
, PARAM_RESUME_TEST
);
3821 usbgem_nd_ioctl(struct usbgem_dev
*dp
,
3822 queue_t
*wq
, mblk_t
*mp
, struct iocblk
*iocp
)
3826 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
3828 switch (iocp
->ioc_cmd
) {
3830 ok
= nd_getset(wq
, dp
->nd_data_p
, mp
);
3831 DPRINTF(1, (CE_CONT
,
3832 "%s: get %s", dp
->name
, ok
? "OK" : "FAIL"));
3833 return (ok
? IOC_REPLY
: IOC_INVAL
);
3836 ok
= nd_getset(wq
, dp
->nd_data_p
, mp
);
3838 DPRINTF(1, (CE_CONT
, "%s: set %s err %d",
3839 dp
->name
, ok
? "OK" : "FAIL", iocp
->ioc_error
));
3845 if (iocp
->ioc_error
) {
3849 return (IOC_RESTART_REPLY
);
3852 cmn_err(CE_WARN
, "%s: invalid cmd 0x%x", dp
->name
, iocp
->ioc_cmd
);
3858 usbgem_nd_cleanup(struct usbgem_dev
*dp
)
3860 ASSERT(dp
->nd_data_p
!= NULL
);
3861 ASSERT(dp
->nd_arg_p
!= NULL
);
3863 nd_free(&dp
->nd_data_p
);
3865 kmem_free(dp
->nd_arg_p
, sizeof (struct usbgem_nd_arg
) * PARAM_COUNT
);
3866 dp
->nd_arg_p
= NULL
;
3868 #endif /* USBGEM_CONFIG_ND */
3871 usbgem_mac_ioctl(struct usbgem_dev
*dp
, queue_t
*wq
, mblk_t
*mp
)
3873 struct iocblk
*iocp
;
3874 enum ioc_reply status
;
3876 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
3879 * Validate the command before bothering with the mutex ...
3881 iocp
= (void *)mp
->b_rptr
;
3882 iocp
->ioc_error
= 0;
3884 DPRINTF(1, (CE_CONT
, "%s: %s cmd:0x%x", dp
->name
, __func__
,
3887 #ifdef USBGEM_CONFIG_ND
3888 switch (iocp
->ioc_cmd
) {
3896 status
= usbgem_nd_ioctl(dp
, wq
, mp
, iocp
);
3901 * Finally, decide how to reply
3907 * Error, reply with a NAK and EINVAL or the specified error
3909 miocnak(wq
, mp
, 0, iocp
->ioc_error
== 0 ?
3910 EINVAL
: iocp
->ioc_error
);
3915 * OK, reply already sent
3919 case IOC_RESTART_ACK
:
3922 * OK, reply with an ACK
3924 miocack(wq
, mp
, 0, 0);
3927 case IOC_RESTART_REPLY
:
3930 * OK, send prepared reply as ACK or NAK
3932 mp
->b_datap
->db_type
=
3933 iocp
->ioc_error
== 0 ? M_IOCACK
: M_IOCNAK
;
3938 miocnak(wq
, mp
, 0, EINVAL
);
3940 #endif /* USBGEM_CONFIG_GLDv3 */
3944 #define XCVR_UNDEFINED 0
3947 #define XCVR_100T4 3
3949 #define XCVR_100T2 5
3950 #define XCVR_1000X 6
3951 #define XCVR_1000T 7
3954 usbgem_mac_xcvr_inuse(struct usbgem_dev
*dp
)
3956 int val
= XCVR_UNDEFINED
;
3958 if ((dp
->mii_status
& MII_STATUS_XSTATUS
) == 0) {
3959 if (dp
->mii_status
& MII_STATUS_100_BASE_T4
) {
3961 } else if (dp
->mii_status
&
3962 (MII_STATUS_100_BASEX_FD
|
3963 MII_STATUS_100_BASEX
)) {
3965 } else if (dp
->mii_status
&
3966 (MII_STATUS_100_BASE_T2_FD
|
3967 MII_STATUS_100_BASE_T2
)) {
3969 } else if (dp
->mii_status
&
3970 (MII_STATUS_10_FD
| MII_STATUS_10
)) {
3973 } else if (dp
->mii_xstatus
&
3974 (MII_XSTATUS_1000BASET_FD
| MII_XSTATUS_1000BASET
)) {
3976 } else if (dp
->mii_xstatus
&
3977 (MII_XSTATUS_1000BASEX_FD
| MII_XSTATUS_1000BASEX
)) {
3984 #ifdef USBGEM_CONFIG_GLDv3
3985 /* ============================================================== */
3989 /* ============================================================== */
3990 static int usbgem_m_getstat(void *, uint_t
, uint64_t *);
3991 static int usbgem_m_start(void *);
3992 static void usbgem_m_stop(void *);
3993 static int usbgem_m_setpromisc(void *, boolean_t
);
3994 static int usbgem_m_multicst(void *, boolean_t
, const uint8_t *);
3995 static int usbgem_m_unicst(void *, const uint8_t *);
3996 static mblk_t
*usbgem_m_tx(void *, mblk_t
*);
3997 static void usbgem_m_ioctl(void *, queue_t
*, mblk_t
*);
3998 #ifdef GEM_CONFIG_MAC_PROP
3999 static int usbgem_m_setprop(void *, const char *, mac_prop_id_t
,
4000 uint_t
, const void *);
4001 #ifdef MAC_VERSION_V1
4002 static int usbgem_m_getprop(void *, const char *, mac_prop_id_t
,
4005 static int usbgem_m_getprop(void *, const char *, mac_prop_id_t
,
4006 uint_t
, uint_t
, void *, uint_t
*);
4010 #ifdef _SYS_MAC_PROVIDER_H
4011 #define GEM_M_CALLBACK_FLAGS (MC_IOCTL)
4013 #define GEM_M_CALLBACK_FLAGS (MC_IOCTL)
4016 static mac_callbacks_t gem_m_callbacks
= {
4017 #ifdef USBGEM_CONFIG_MAC_PROP
4018 #ifdef MAC_VERSION_V1
4019 GEM_M_CALLBACK_FLAGS
| MC_SETPROP
| MC_GETPROP
| MC_PROPINFO
,
4021 GEM_M_CALLBACK_FLAGS
| MC_SETPROP
| MC_GETPROP
,
4024 GEM_M_CALLBACK_FLAGS
,
4029 usbgem_m_setpromisc
,
4033 #ifdef _SYS_MAC_PROVIDER_H
4034 #ifdef MAC_VERSION_V1
4038 NULL
, /* m_resources */
4041 NULL
, /* m_getcapab */
4042 #ifdef USBGEM_CONFIG_MAC_PROP
4048 #ifdef MAC_VERSION_V1
4054 usbgem_m_start(void *arg
)
4058 struct usbgem_dev
*dp
= arg
;
4060 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4064 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
4065 dp
->nic_state
= NIC_STATE_ONLINE
;
4067 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
4071 if (usbgem_mac_init(dp
) != USB_SUCCESS
) {
4075 /* initialize rx filter state */
4076 sema_p(&dp
->rxfilter_lock
);
4078 dp
->mc_count_req
= 0;
4080 bcopy(dp
->dev_addr
.ether_addr_octet
,
4081 dp
->cur_addr
.ether_addr_octet
, ETHERADDRL
);
4082 dp
->rxmode
|= RXMODE_ENABLE
;
4084 ret
= usbgem_hal_set_rx_filter(dp
);
4085 sema_v(&dp
->rxfilter_lock
);
4087 if (ret
!= USB_SUCCESS
) {
4091 if (dp
->mii_state
== MII_STATE_LINKUP
) {
4092 /* setup media mode if the link have been up */
4093 if (usbgem_hal_set_media(dp
) != USB_SUCCESS
) {
4096 if (usbgem_mac_start(dp
) != USB_SUCCESS
) {
4103 rw_exit(&dp
->dev_state_lock
);
4108 usbgem_m_stop(void *arg
)
4110 struct usbgem_dev
*dp
= arg
;
4112 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4114 /* stop rx gracefully */
4115 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4116 sema_p(&dp
->rxfilter_lock
);
4117 dp
->rxmode
&= ~RXMODE_ENABLE
;
4119 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4120 (void) usbgem_hal_set_rx_filter(dp
);
4122 sema_v(&dp
->rxfilter_lock
);
4123 rw_exit(&dp
->dev_state_lock
);
4125 /* make the nic state inactive */
4126 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
4127 dp
->nic_state
= NIC_STATE_STOPPED
;
4129 /* stop mac completely */
4130 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4131 (void) usbgem_mac_stop(dp
, MAC_STATE_STOPPED
, STOP_GRACEFUL
);
4133 rw_exit(&dp
->dev_state_lock
);
4137 usbgem_m_multicst(void *arg
, boolean_t add
, const uint8_t *ep
)
4141 struct usbgem_dev
*dp
= arg
;
4143 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4145 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4147 ret
= usbgem_add_multicast(dp
, ep
);
4149 ret
= usbgem_remove_multicast(dp
, ep
);
4151 rw_exit(&dp
->dev_state_lock
);
4154 if (ret
!= USB_SUCCESS
) {
4155 #ifdef GEM_CONFIG_FMA
4156 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4165 usbgem_m_setpromisc(void *arg
, boolean_t on
)
4168 struct usbgem_dev
*dp
= arg
;
4170 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4172 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4174 sema_p(&dp
->rxfilter_lock
);
4176 dp
->rxmode
|= RXMODE_PROMISC
;
4178 dp
->rxmode
&= ~RXMODE_PROMISC
;
4182 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4183 if (usbgem_hal_set_rx_filter(dp
) != USB_SUCCESS
) {
4187 sema_v(&dp
->rxfilter_lock
);
4189 rw_exit(&dp
->dev_state_lock
);
4191 #ifdef GEM_CONFIG_FMA
4193 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4200 usbgem_m_getstat(void *arg
, uint_t stat
, uint64_t *valp
)
4203 struct usbgem_dev
*dp
= arg
;
4204 struct usbgem_stats
*gstp
= &dp
->stats
;
4206 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4208 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4209 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
4210 rw_exit(&dp
->dev_state_lock
);
4215 if (usbgem_hal_get_stats(dp
) != USB_SUCCESS
) {
4216 #ifdef GEM_CONFIG_FMA
4217 rw_exit(&dp
->dev_state_lock
);
4218 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4222 rw_exit(&dp
->dev_state_lock
);
4225 case MAC_STAT_IFSPEED
:
4226 val
= usbgem_speed_value
[dp
->speed
] *1000000ull;
4229 case MAC_STAT_MULTIRCV
:
4233 case MAC_STAT_BRDCSTRCV
:
4237 case MAC_STAT_MULTIXMT
:
4241 case MAC_STAT_BRDCSTXMT
:
4245 case MAC_STAT_NORCVBUF
:
4246 val
= gstp
->norcvbuf
+ gstp
->missed
;
4249 case MAC_STAT_IERRORS
:
4253 case MAC_STAT_NOXMTBUF
:
4254 val
= gstp
->noxmtbuf
;
4257 case MAC_STAT_OERRORS
:
4261 case MAC_STAT_COLLISIONS
:
4262 val
= gstp
->collisions
;
4265 case MAC_STAT_RBYTES
:
4269 case MAC_STAT_IPACKETS
:
4270 val
= gstp
->rpackets
;
4273 case MAC_STAT_OBYTES
:
4277 case MAC_STAT_OPACKETS
:
4278 val
= gstp
->opackets
;
4281 case MAC_STAT_UNDERFLOWS
:
4282 val
= gstp
->underflow
;
4285 case MAC_STAT_OVERFLOWS
:
4286 val
= gstp
->overflow
;
4289 case ETHER_STAT_ALIGN_ERRORS
:
4293 case ETHER_STAT_FCS_ERRORS
:
4297 case ETHER_STAT_FIRST_COLLISIONS
:
4298 val
= gstp
->first_coll
;
4301 case ETHER_STAT_MULTI_COLLISIONS
:
4302 val
= gstp
->multi_coll
;
4305 case ETHER_STAT_SQE_ERRORS
:
4309 case ETHER_STAT_DEFER_XMTS
:
4313 case ETHER_STAT_TX_LATE_COLLISIONS
:
4314 val
= gstp
->xmtlatecoll
;
4317 case ETHER_STAT_EX_COLLISIONS
:
4321 case ETHER_STAT_MACXMT_ERRORS
:
4322 val
= gstp
->xmit_internal_err
;
4325 case ETHER_STAT_CARRIER_ERRORS
:
4326 val
= gstp
->nocarrier
;
4329 case ETHER_STAT_TOOLONG_ERRORS
:
4330 val
= gstp
->frame_too_long
;
4333 case ETHER_STAT_MACRCV_ERRORS
:
4334 val
= gstp
->rcv_internal_err
;
4337 case ETHER_STAT_XCVR_ADDR
:
4338 val
= dp
->mii_phy_addr
;
4341 case ETHER_STAT_XCVR_ID
:
4342 val
= dp
->mii_phy_id
;
4345 case ETHER_STAT_XCVR_INUSE
:
4346 val
= usbgem_mac_xcvr_inuse(dp
);
4349 case ETHER_STAT_CAP_1000FDX
:
4350 val
= (dp
->mii_xstatus
& MII_XSTATUS_1000BASET_FD
) ||
4351 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX_FD
);
4354 case ETHER_STAT_CAP_1000HDX
:
4355 val
= (dp
->mii_xstatus
& MII_XSTATUS_1000BASET
) ||
4356 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX
);
4359 case ETHER_STAT_CAP_100FDX
:
4360 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
);
4363 case ETHER_STAT_CAP_100HDX
:
4364 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
);
4367 case ETHER_STAT_CAP_10FDX
:
4368 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
);
4371 case ETHER_STAT_CAP_10HDX
:
4372 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_10
);
4375 case ETHER_STAT_CAP_ASMPAUSE
:
4376 val
= dp
->ugc
.usbgc_flow_control
> FLOW_CONTROL_SYMMETRIC
;
4379 case ETHER_STAT_CAP_PAUSE
:
4380 val
= dp
->ugc
.usbgc_flow_control
!= FLOW_CONTROL_NONE
;
4383 case ETHER_STAT_CAP_AUTONEG
:
4384 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
);
4387 case ETHER_STAT_ADV_CAP_1000FDX
:
4388 val
= dp
->anadv_1000fdx
;
4391 case ETHER_STAT_ADV_CAP_1000HDX
:
4392 val
= dp
->anadv_1000hdx
;
4395 case ETHER_STAT_ADV_CAP_100FDX
:
4396 val
= dp
->anadv_100fdx
;
4399 case ETHER_STAT_ADV_CAP_100HDX
:
4400 val
= dp
->anadv_100hdx
;
4403 case ETHER_STAT_ADV_CAP_10FDX
:
4404 val
= dp
->anadv_10fdx
;
4407 case ETHER_STAT_ADV_CAP_10HDX
:
4408 val
= dp
->anadv_10hdx
;
4411 case ETHER_STAT_ADV_CAP_ASMPAUSE
:
4412 val
= dp
->anadv_asmpause
;
4415 case ETHER_STAT_ADV_CAP_PAUSE
:
4416 val
= dp
->anadv_pause
;
4419 case ETHER_STAT_ADV_CAP_AUTONEG
:
4420 val
= dp
->anadv_autoneg
;
4423 case ETHER_STAT_LP_CAP_1000FDX
:
4424 val
= BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_FULL
);
4427 case ETHER_STAT_LP_CAP_1000HDX
:
4428 val
= BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_HALF
);
4431 case ETHER_STAT_LP_CAP_100FDX
:
4432 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX_FD
);
4435 case ETHER_STAT_LP_CAP_100HDX
:
4436 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX
);
4439 case ETHER_STAT_LP_CAP_10FDX
:
4440 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T_FD
);
4443 case ETHER_STAT_LP_CAP_10HDX
:
4444 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T
);
4447 case ETHER_STAT_LP_CAP_ASMPAUSE
:
4448 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_ASM_DIR
);
4451 case ETHER_STAT_LP_CAP_PAUSE
:
4452 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_PAUSE
);
4455 case ETHER_STAT_LP_CAP_AUTONEG
:
4456 val
= BOOLEAN(dp
->mii_exp
& MII_AN_EXP_LPCANAN
);
4459 case ETHER_STAT_LINK_ASMPAUSE
:
4460 val
= BOOLEAN(dp
->flow_control
& 2);
4463 case ETHER_STAT_LINK_PAUSE
:
4464 val
= BOOLEAN(dp
->flow_control
& 1);
4467 case ETHER_STAT_LINK_AUTONEG
:
4468 val
= dp
->anadv_autoneg
&&
4469 BOOLEAN(dp
->mii_exp
& MII_AN_EXP_LPCANAN
);
4472 case ETHER_STAT_LINK_DUPLEX
:
4473 val
= (dp
->mii_state
== MII_STATE_LINKUP
) ?
4474 (dp
->full_duplex
? 2 : 1) : 0;
4477 case ETHER_STAT_TOOSHORT_ERRORS
:
4480 #ifdef NEVER /* it doesn't make sense */
4481 case ETHER_STAT_CAP_REMFAULT
:
4485 case ETHER_STAT_ADV_REMFAULT
:
4486 val
= dp
->anadv_remfault
;
4489 case ETHER_STAT_LP_REMFAULT
:
4490 val
= BOOLEAN(dp
->mii_lpable
& MII_AN_ADVERT_REMFAULT
);
4493 case ETHER_STAT_JABBER_ERRORS
:
4497 case ETHER_STAT_CAP_100T4
:
4498 val
= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASE_T4
);
4501 case ETHER_STAT_ADV_CAP_100T4
:
4502 val
= dp
->anadv_100t4
;
4505 case ETHER_STAT_LP_CAP_100T4
:
4506 val
= BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_T4
);
4510 #if GEM_DEBUG_LEVEL > 2
4512 "%s: unrecognized parameter value = %d",
4525 usbgem_m_unicst(void *arg
, const uint8_t *mac
)
4528 struct usbgem_dev
*dp
= arg
;
4530 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4532 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4534 sema_p(&dp
->rxfilter_lock
);
4535 bcopy(mac
, dp
->cur_addr
.ether_addr_octet
, ETHERADDRL
);
4536 dp
->rxmode
|= RXMODE_ENABLE
;
4539 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4540 if (usbgem_hal_set_rx_filter(dp
) != USB_SUCCESS
) {
4544 sema_v(&dp
->rxfilter_lock
);
4545 rw_exit(&dp
->dev_state_lock
);
4547 #ifdef GEM_CONFIG_FMA
4549 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4556 * usbgem_m_tx is used only for sending data packets into ethernet wire.
4559 usbgem_m_tx(void *arg
, mblk_t
*mp_head
)
4564 struct usbgem_dev
*dp
= arg
;
4566 DPRINTF(4, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4570 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4572 if (dp
->mii_state
!= MII_STATE_LINKUP
||
4573 dp
->mac_state
!= MAC_STATE_ONLINE
) {
4574 /* some nics hate to send packets during the link is down */
4575 for (; mp
; mp
= nmp
) {
4583 ASSERT(dp
->nic_state
== NIC_STATE_ONLINE
);
4585 limit
= dp
->tx_max_packets
;
4586 for (; limit
-- && mp
; mp
= nmp
) {
4589 if (usbgem_send_common(dp
, mp
,
4590 (limit
== 0 && nmp
) ? 1 : 0)) {
4595 #ifdef CONFIG_TX_LIMITER
4596 if (mp
== mp_head
) {
4597 /* no packets were sent, descrease allocation limit */
4598 mutex_enter(&dp
->txlock
);
4599 dp
->tx_max_packets
= max(dp
->tx_max_packets
- 1, 1);
4600 mutex_exit(&dp
->txlock
);
4604 rw_exit(&dp
->dev_state_lock
);
4610 usbgem_m_ioctl(void *arg
, queue_t
*wq
, mblk_t
*mp
)
4612 struct usbgem_dev
*dp
= arg
;
4614 DPRINTF(1, (CE_CONT
, "!%s: %s: called",
4615 ((struct usbgem_dev
*)arg
)->name
, __func__
));
4617 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4618 usbgem_mac_ioctl((struct usbgem_dev
*)arg
, wq
, mp
);
4619 rw_exit(&dp
->dev_state_lock
);
4623 usbgem_gld3_init(struct usbgem_dev
*dp
, mac_register_t
*macp
)
4625 macp
->m_type_ident
= MAC_PLUGIN_IDENT_ETHER
;
4626 macp
->m_driver
= dp
;
4627 macp
->m_dip
= dp
->dip
;
4628 macp
->m_src_addr
= dp
->dev_addr
.ether_addr_octet
;
4629 macp
->m_callbacks
= &gem_m_callbacks
;
4630 macp
->m_min_sdu
= 0;
4631 macp
->m_max_sdu
= dp
->mtu
;
4633 if (dp
->misc_flag
& USBGEM_VLAN
) {
4634 macp
->m_margin
= VTAG_SIZE
;
4638 /* ============================================================== */
4642 /* ============================================================== */
4643 static int usbgem_gld_reset(gld_mac_info_t
*);
4644 static int usbgem_gld_start(gld_mac_info_t
*);
4645 static int usbgem_gld_stop(gld_mac_info_t
*);
4646 static int usbgem_gld_set_mac_address(gld_mac_info_t
*, uint8_t *);
4647 static int usbgem_gld_set_multicast(gld_mac_info_t
*, uint8_t *, int);
4648 static int usbgem_gld_set_promiscuous(gld_mac_info_t
*, int);
4649 static int usbgem_gld_get_stats(gld_mac_info_t
*, struct gld_stats
*);
4650 static int usbgem_gld_send(gld_mac_info_t
*, mblk_t
*);
4651 static int usbgem_gld_send_tagged(gld_mac_info_t
*, mblk_t
*, uint32_t);
4654 usbgem_gld_reset(gld_mac_info_t
*macinfo
)
4657 struct usbgem_dev
*dp
;
4660 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4662 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4664 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
4665 if (usbgem_mac_init(dp
) != USB_SUCCESS
) {
4670 dp
->nic_state
= NIC_STATE_INITIALIZED
;
4672 /* setup media mode if the link have been up */
4673 if (dp
->mii_state
== MII_STATE_LINKUP
) {
4674 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4675 (void) usbgem_hal_set_media(dp
);
4679 rw_exit(&dp
->dev_state_lock
);
4684 usbgem_gld_start(gld_mac_info_t
*macinfo
)
4687 struct usbgem_dev
*dp
;
4689 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4691 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4693 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
4695 dp
->nic_state
= NIC_STATE_ONLINE
;
4697 if (dp
->mii_state
== MII_STATE_LINKUP
) {
4698 if (usbgem_mac_start(dp
) != USB_SUCCESS
) {
4699 /* sema_v(&dp->mii_lock); */
4706 * XXX - don't call gld_linkstate() here,
4707 * otherwise it cause recursive mutex call.
4711 rw_exit(&dp
->dev_state_lock
);
4717 usbgem_gld_stop(gld_mac_info_t
*macinfo
)
4719 int err
= GLD_SUCCESS
;
4720 struct usbgem_dev
*dp
;
4722 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4724 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4726 /* try to stop rx gracefully */
4727 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4728 sema_p(&dp
->rxfilter_lock
);
4729 dp
->rxmode
&= ~RXMODE_ENABLE
;
4731 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4732 (void) usbgem_hal_set_rx_filter(dp
);
4734 sema_v(&dp
->rxfilter_lock
);
4735 rw_exit(&dp
->dev_state_lock
);
4737 /* make the nic state inactive */
4738 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
4739 dp
->nic_state
= NIC_STATE_STOPPED
;
4741 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4742 if (usbgem_mac_stop(dp
, MAC_STATE_STOPPED
, STOP_GRACEFUL
)
4747 rw_exit(&dp
->dev_state_lock
);
4753 usbgem_gld_set_multicast(gld_mac_info_t
*macinfo
, uint8_t *ep
, int flag
)
4757 struct usbgem_dev
*dp
;
4759 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4761 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4763 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4764 if (flag
== GLD_MULTI_ENABLE
) {
4765 ret
= usbgem_add_multicast(dp
, ep
);
4767 ret
= usbgem_remove_multicast(dp
, ep
);
4769 rw_exit(&dp
->dev_state_lock
);
4772 if (ret
!= USB_SUCCESS
) {
4773 #ifdef GEM_CONFIG_FMA
4774 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4782 usbgem_gld_set_promiscuous(gld_mac_info_t
*macinfo
, int flag
)
4784 boolean_t need_to_change
= B_TRUE
;
4785 struct usbgem_dev
*dp
;
4787 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4789 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4791 sema_p(&dp
->rxfilter_lock
);
4792 if (flag
== GLD_MAC_PROMISC_NONE
) {
4793 dp
->rxmode
&= ~(RXMODE_PROMISC
| RXMODE_ALLMULTI_REQ
);
4794 } else if (flag
== GLD_MAC_PROMISC_MULTI
) {
4795 dp
->rxmode
|= RXMODE_ALLMULTI_REQ
;
4796 } else if (flag
== GLD_MAC_PROMISC_PHYS
) {
4797 dp
->rxmode
|= RXMODE_PROMISC
;
4799 /* mode unchanged */
4800 need_to_change
= B_FALSE
;
4803 if (need_to_change
) {
4804 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4805 (void) usbgem_hal_set_rx_filter(dp
);
4808 sema_v(&dp
->rxfilter_lock
);
4810 return (GLD_SUCCESS
);
4814 usbgem_gld_set_mac_address(gld_mac_info_t
*macinfo
, uint8_t *mac
)
4816 struct usbgem_dev
*dp
;
4817 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4819 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
4821 sema_p(&dp
->rxfilter_lock
);
4822 bcopy(mac
, dp
->cur_addr
.ether_addr_octet
, ETHERADDRL
);
4823 dp
->rxmode
|= RXMODE_ENABLE
;
4825 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
) {
4826 (void) usbgem_hal_set_rx_filter(dp
);
4828 sema_v(&dp
->rxfilter_lock
);
4830 return (GLD_SUCCESS
);
4834 usbgem_gld_get_stats(gld_mac_info_t
*macinfo
, struct gld_stats
*gs
)
4836 struct usbgem_dev
*dp
;
4837 struct usbgem_stats
*vs
;
4839 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4841 if ((*dp
->ugc
.usbgc_get_stats
)(dp
) != USB_SUCCESS
) {
4842 #ifdef GEM_CONFIG_FMA
4843 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4845 return (USB_FAILURE
);
4850 gs
->glds_errxmt
= vs
->errxmt
;
4851 gs
->glds_errrcv
= vs
->errrcv
;
4852 gs
->glds_collisions
= vs
->collisions
;
4854 gs
->glds_excoll
= vs
->excoll
;
4855 gs
->glds_defer
= vs
->defer
;
4856 gs
->glds_frame
= vs
->frame
;
4857 gs
->glds_crc
= vs
->crc
;
4859 gs
->glds_overflow
= vs
->overflow
; /* fifo err,underrun,rbufovf */
4860 gs
->glds_underflow
= vs
->underflow
;
4861 gs
->glds_short
= vs
->runt
;
4862 gs
->glds_missed
= vs
->missed
; /* missed pkts while rbuf ovf */
4863 gs
->glds_xmtlatecoll
= vs
->xmtlatecoll
;
4864 gs
->glds_nocarrier
= vs
->nocarrier
;
4865 gs
->glds_norcvbuf
= vs
->norcvbuf
; /* OS resource exaust */
4866 gs
->glds_intr
= vs
->intr
;
4868 /* all before here must be kept in place for v0 compatibility */
4869 gs
->glds_speed
= usbgem_speed_value
[dp
->speed
] * 1000000;
4870 gs
->glds_media
= GLDM_PHYMII
;
4871 gs
->glds_duplex
= dp
->full_duplex
? GLD_DUPLEX_FULL
: GLD_DUPLEX_HALF
;
4873 /* gs->glds_media_specific */
4874 gs
->glds_dot3_first_coll
= vs
->first_coll
;
4875 gs
->glds_dot3_multi_coll
= vs
->multi_coll
;
4876 gs
->glds_dot3_sqe_error
= 0;
4877 gs
->glds_dot3_mac_xmt_error
= 0;
4878 gs
->glds_dot3_mac_rcv_error
= 0;
4879 gs
->glds_dot3_frame_too_long
= vs
->frame_too_long
;
4881 return (GLD_SUCCESS
);
4885 usbgem_gld_ioctl(gld_mac_info_t
*macinfo
, queue_t
*wq
, mblk_t
*mp
)
4887 struct usbgem_dev
*dp
;
4889 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4890 usbgem_mac_ioctl(dp
, wq
, mp
);
4892 return (GLD_SUCCESS
);
4896 * gem_gld_send is used only for sending data packets into ethernet wire.
4899 usbgem_gld_send(gld_mac_info_t
*macinfo
, mblk_t
*mp
)
4903 struct usbgem_dev
*dp
;
4905 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4907 /* nic state must be online of suspended */
4908 rw_enter(&dp
->dev_state_lock
, RW_READER
);
4910 ASSERT(dp
->nic_state
== NIC_STATE_ONLINE
);
4911 ASSERT(mp
->b_next
== NULL
);
4913 if (dp
->mii_state
!= MII_STATE_LINKUP
) {
4914 /* Some nics hate to send packets while the link is down. */
4915 /* we discard the untransmitted packets silently */
4916 rw_exit(&dp
->dev_state_lock
);
4919 #ifdef GEM_CONFIG_FMA
4920 /* FIXME - should we ignore the error? */
4921 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_DEGRADED
);
4923 return (GLD_SUCCESS
);
4926 ret
= (usbgem_send_common(dp
, mp
, flags
) == NULL
)
4927 ? GLD_SUCCESS
: GLD_NORESOURCES
;
4928 rw_exit(&dp
->dev_state_lock
);
4934 * usbgem_gld_send is used only for sending data packets into ethernet wire.
4937 usbgem_gld_send_tagged(gld_mac_info_t
*macinfo
, mblk_t
*mp
, uint32_t vtag
)
4940 struct usbgem_dev
*dp
;
4942 dp
= (struct usbgem_dev
*)macinfo
->gldm_private
;
4945 * Some nics hate to send packets while the link is down.
4947 if (dp
->mii_state
!= MII_STATE_LINKUP
) {
4948 /* we dicard the untransmitted packets silently */
4950 #ifdef GEM_CONFIG_FMA
4951 /* FIXME - should we ignore the error? */
4952 ddi_fm_service_impact(dp
->dip
, DDI_SERVICE_UNAFFECTED
);
4954 return (GLD_SUCCESS
);
4957 flags
= GLD_VTAG_TCI(vtag
) << GEM_SEND_VTAG_SHIFT
;
4959 return ((usbgem_send_common(dp
, mp
, 0) == NULL
) ?
4960 GLD_SUCCESS
: GLD_NORESOURCES
);
4964 usbgem_gld_init(struct usbgem_dev
*dp
, gld_mac_info_t
*macinfo
, char *ident
)
4969 macinfo
->gldm_devinfo
= dp
->dip
;
4970 macinfo
->gldm_private
= (caddr_t
)dp
;
4972 macinfo
->gldm_reset
= usbgem_gld_reset
;
4973 macinfo
->gldm_start
= usbgem_gld_start
;
4974 macinfo
->gldm_stop
= usbgem_gld_stop
;
4975 macinfo
->gldm_set_mac_addr
= usbgem_gld_set_mac_address
;
4976 macinfo
->gldm_send
= usbgem_gld_send
;
4977 macinfo
->gldm_set_promiscuous
= usbgem_gld_set_promiscuous
;
4978 macinfo
->gldm_get_stats
= usbgem_gld_get_stats
;
4979 macinfo
->gldm_ioctl
= usbgem_gld_ioctl
;
4980 macinfo
->gldm_set_multicast
= usbgem_gld_set_multicast
;
4981 macinfo
->gldm_intr
= NULL
;
4982 macinfo
->gldm_mctl
= NULL
;
4984 macinfo
->gldm_ident
= ident
;
4985 macinfo
->gldm_type
= DL_ETHER
;
4986 macinfo
->gldm_minpkt
= 0;
4987 macinfo
->gldm_maxpkt
= dp
->mtu
;
4988 macinfo
->gldm_addrlen
= ETHERADDRL
;
4989 macinfo
->gldm_saplen
= -2;
4990 macinfo
->gldm_ppa
= ddi_get_instance(dp
->dip
);
4991 #ifdef GLD_CAP_LINKSTATE
4992 macinfo
->gldm_capabilities
= GLD_CAP_LINKSTATE
;
4994 macinfo
->gldm_vendor_addr
= dp
->dev_addr
.ether_addr_octet
;
4995 macinfo
->gldm_broadcast_addr
= usbgem_bcastaddr
;
4997 #endif /* USBGEM_CONFIG_GLDv3 */
5000 /* ======================================================================== */
5004 /* ======================================================================== */
5006 usbgem_generate_macaddr(struct usbgem_dev
*dp
, uint8_t *mac
)
5008 extern char hw_serial
[];
5015 "!%s: using temp ether address,"
5016 " do not use this for long time",
5019 /* prefer a fixed address for DHCP */
5020 hw_serial_p
= &hw_serial
[0];
5021 val
= stoi(&hw_serial_p
);
5024 for (i
= 0; i
< USBGEM_NAME_LEN
; i
++) {
5025 if (dp
->name
[i
] == 0) {
5030 key
^= ddi_get_instance(dp
->dip
);
5033 /* generate a local address */
5035 mac
[1] = (uint8_t)(val
>> 32);
5036 mac
[2] = (uint8_t)(val
>> 24);
5037 mac
[3] = (uint8_t)(val
>> 16);
5038 mac
[4] = (uint8_t)(val
>> 8);
5039 mac
[5] = (uint8_t)val
;
5043 usbgem_get_mac_addr_conf(struct usbgem_dev
*dp
)
5047 uint8_t mac
[ETHERADDRL
];
5056 DPRINTF(3, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
5058 * Get ethernet address from .conf file
5060 (void) sprintf(propname
, "mac-addr");
5061 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY
, dp
->dip
,
5062 DDI_PROP_DONTPASS
, propname
, &valstr
)) != DDI_PROP_SUCCESS
) {
5066 if (strlen(valstr
) != ETHERADDRL
*3-1) {
5075 for (i
= 0; i
< 2; i
++) {
5078 if (c
>= 'a' && c
<= 'f') {
5080 } else if (c
>= 'A' && c
<= 'F') {
5082 } else if (c
>= '0' && c
<= '9') {
5092 if (j
== ETHERADDRL
) {
5104 usbgem_generate_macaddr(dp
, mac
);
5106 for (i
= 0; i
< ETHERADDRL
; i
++) {
5107 dp
->dev_addr
.ether_addr_octet
[i
] = mac
[i
];
5109 ddi_prop_free(valstr
);
5114 "!%s: read mac addr: trying .conf: syntax err %s",
5116 ddi_prop_free(valstr
);
5122 usbgem_read_conf(struct usbgem_dev
*dp
)
5126 DPRINTF(1, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
5129 * Get media mode infomation from .conf file
5131 dp
->anadv_autoneg
= usbgem_prop_get_int(dp
, "adv_autoneg_cap", 1) != 0;
5132 dp
->anadv_1000fdx
= usbgem_prop_get_int(dp
, "adv_1000fdx_cap", 1) != 0;
5133 dp
->anadv_1000hdx
= usbgem_prop_get_int(dp
, "adv_1000hdx_cap", 1) != 0;
5134 dp
->anadv_100t4
= usbgem_prop_get_int(dp
, "adv_100T4_cap", 1) != 0;
5135 dp
->anadv_100fdx
= usbgem_prop_get_int(dp
, "adv_100fdx_cap", 1) != 0;
5136 dp
->anadv_100hdx
= usbgem_prop_get_int(dp
, "adv_100hdx_cap", 1) != 0;
5137 dp
->anadv_10fdx
= usbgem_prop_get_int(dp
, "adv_10fdx_cap", 1) != 0;
5138 dp
->anadv_10hdx
= usbgem_prop_get_int(dp
, "adv_10hdx_cap", 1) != 0;
5139 dp
->anadv_1000t_ms
= usbgem_prop_get_int(dp
, "adv_1000t_ms", 0);
5141 if ((ddi_prop_exists(DDI_DEV_T_ANY
, dp
->dip
,
5142 DDI_PROP_DONTPASS
, "full-duplex"))) {
5144 usbgem_prop_get_int(dp
, "full-duplex", 1) != 0;
5145 dp
->anadv_autoneg
= B_FALSE
;
5146 if (dp
->full_duplex
) {
5147 dp
->anadv_1000hdx
= B_FALSE
;
5148 dp
->anadv_100hdx
= B_FALSE
;
5149 dp
->anadv_10hdx
= B_FALSE
;
5151 dp
->anadv_1000fdx
= B_FALSE
;
5152 dp
->anadv_100fdx
= B_FALSE
;
5153 dp
->anadv_10fdx
= B_FALSE
;
5157 if ((val
= usbgem_prop_get_int(dp
, "speed", 0)) > 0) {
5158 dp
->anadv_autoneg
= B_FALSE
;
5161 dp
->speed
= USBGEM_SPD_1000
;
5162 dp
->anadv_100t4
= B_FALSE
;
5163 dp
->anadv_100fdx
= B_FALSE
;
5164 dp
->anadv_100hdx
= B_FALSE
;
5165 dp
->anadv_10fdx
= B_FALSE
;
5166 dp
->anadv_10hdx
= B_FALSE
;
5169 dp
->speed
= USBGEM_SPD_100
;
5170 dp
->anadv_1000fdx
= B_FALSE
;
5171 dp
->anadv_1000hdx
= B_FALSE
;
5172 dp
->anadv_10fdx
= B_FALSE
;
5173 dp
->anadv_10hdx
= B_FALSE
;
5176 dp
->speed
= USBGEM_SPD_10
;
5177 dp
->anadv_1000fdx
= B_FALSE
;
5178 dp
->anadv_1000hdx
= B_FALSE
;
5179 dp
->anadv_100t4
= B_FALSE
;
5180 dp
->anadv_100fdx
= B_FALSE
;
5181 dp
->anadv_100hdx
= B_FALSE
;
5185 "!%s: property %s: illegal value:%d",
5186 dp
->name
, "speed", val
);
5187 dp
->anadv_autoneg
= B_TRUE
;
5191 val
= usbgem_prop_get_int(dp
,
5192 "adv_pause", dp
->ugc
.usbgc_flow_control
& 1);
5193 val
|= usbgem_prop_get_int(dp
,
5194 "adv_asmpause", BOOLEAN(dp
->ugc
.usbgc_flow_control
& 2)) << 1;
5195 if (val
> FLOW_CONTROL_RX_PAUSE
|| val
< FLOW_CONTROL_NONE
) {
5197 "!%s: property %s: illegal value:%d",
5198 dp
->name
, "flow-control", val
);
5200 val
= min(val
, dp
->ugc
.usbgc_flow_control
);
5202 dp
->anadv_pause
= BOOLEAN(val
& 1);
5203 dp
->anadv_asmpause
= BOOLEAN(val
& 2);
5205 dp
->mtu
= usbgem_prop_get_int(dp
, "mtu", dp
->mtu
);
5206 dp
->txthr
= usbgem_prop_get_int(dp
, "txthr", dp
->txthr
);
5207 dp
->rxthr
= usbgem_prop_get_int(dp
, "rxthr", dp
->rxthr
);
5208 dp
->txmaxdma
= usbgem_prop_get_int(dp
, "txmaxdma", dp
->txmaxdma
);
5209 dp
->rxmaxdma
= usbgem_prop_get_int(dp
, "rxmaxdma", dp
->rxmaxdma
);
5210 #ifdef GEM_CONFIG_POLLING
5211 dp
->poll_pkt_delay
=
5212 usbgem_prop_get_int(dp
, "pkt_delay", dp
->poll_pkt_delay
);
5214 dp
->max_poll_interval
[GEM_SPD_10
] =
5215 usbgem_prop_get_int(dp
, "max_poll_interval_10",
5216 dp
->max_poll_interval
[GEM_SPD_10
]);
5217 dp
->max_poll_interval
[GEM_SPD_100
] =
5218 usbgem_prop_get_int(dp
, "max_poll_interval_100",
5219 dp
->max_poll_interval
[GEM_SPD_100
]);
5220 dp
->max_poll_interval
[GEM_SPD_1000
] =
5221 usbgem_prop_get_int(dp
, "max_poll_interval_1000",
5222 dp
->max_poll_interval
[GEM_SPD_1000
]);
5224 dp
->min_poll_interval
[GEM_SPD_10
] =
5225 usbgem_prop_get_int(dp
, "min_poll_interval_10",
5226 dp
->min_poll_interval
[GEM_SPD_10
]);
5227 dp
->min_poll_interval
[GEM_SPD_100
] =
5228 usbgem_prop_get_int(dp
, "min_poll_interval_100",
5229 dp
->min_poll_interval
[GEM_SPD_100
]);
5230 dp
->min_poll_interval
[GEM_SPD_1000
] =
5231 usbgem_prop_get_int(dp
, "min_poll_interval_1000",
5232 dp
->min_poll_interval
[GEM_SPD_1000
]);
5237 * usbem kstat support
5239 #ifndef GEM_CONFIG_GLDv3
5240 /* kstat items based from dmfe driver */
5242 struct usbgem_kstat_named
{
5243 struct kstat_named ks_xcvr_addr
;
5244 struct kstat_named ks_xcvr_id
;
5245 struct kstat_named ks_xcvr_inuse
;
5246 struct kstat_named ks_link_up
;
5247 struct kstat_named ks_link_duplex
; /* 0:unknwon, 1:half, 2:full */
5248 struct kstat_named ks_cap_1000fdx
;
5249 struct kstat_named ks_cap_1000hdx
;
5250 struct kstat_named ks_cap_100fdx
;
5251 struct kstat_named ks_cap_100hdx
;
5252 struct kstat_named ks_cap_10fdx
;
5253 struct kstat_named ks_cap_10hdx
;
5255 struct kstat_named ks_cap_remfault
;
5257 struct kstat_named ks_cap_autoneg
;
5259 struct kstat_named ks_adv_cap_1000fdx
;
5260 struct kstat_named ks_adv_cap_1000hdx
;
5261 struct kstat_named ks_adv_cap_100fdx
;
5262 struct kstat_named ks_adv_cap_100hdx
;
5263 struct kstat_named ks_adv_cap_10fdx
;
5264 struct kstat_named ks_adv_cap_10hdx
;
5266 struct kstat_named ks_adv_cap_remfault
;
5268 struct kstat_named ks_adv_cap_autoneg
;
5269 struct kstat_named ks_lp_cap_1000fdx
;
5270 struct kstat_named ks_lp_cap_1000hdx
;
5271 struct kstat_named ks_lp_cap_100fdx
;
5272 struct kstat_named ks_lp_cap_100hdx
;
5273 struct kstat_named ks_lp_cap_10fdx
;
5274 struct kstat_named ks_lp_cap_10hdx
;
5275 struct kstat_named ks_lp_cap_remfault
;
5276 struct kstat_named ks_lp_cap_autoneg
;
5280 usbgem_kstat_update(kstat_t
*ksp
, int rw
)
5282 struct usbgem_kstat_named
*knp
;
5283 struct usbgem_dev
*dp
= (struct usbgem_dev
*)ksp
->ks_private
;
5285 if (rw
!= KSTAT_READ
) {
5289 knp
= (struct usbgem_kstat_named
*)ksp
->ks_data
;
5291 knp
->ks_xcvr_addr
.value
.ul
= dp
->mii_phy_addr
;
5292 knp
->ks_xcvr_id
.value
.ul
= dp
->mii_phy_id
;
5293 knp
->ks_xcvr_inuse
.value
.ul
= usbgem_mac_xcvr_inuse(dp
);
5294 knp
->ks_link_up
.value
.ul
= dp
->mii_state
== MII_STATE_LINKUP
;
5295 knp
->ks_link_duplex
.value
.ul
=
5296 (dp
->mii_state
== MII_STATE_LINKUP
) ?
5297 (dp
->full_duplex
? 2 : 1) : 0;
5299 knp
->ks_cap_1000fdx
.value
.ul
=
5300 (dp
->mii_xstatus
& MII_XSTATUS_1000BASET_FD
) ||
5301 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX_FD
);
5302 knp
->ks_cap_1000hdx
.value
.ul
=
5303 (dp
->mii_xstatus
& MII_XSTATUS_1000BASET
) ||
5304 (dp
->mii_xstatus
& MII_XSTATUS_1000BASEX
);
5305 knp
->ks_cap_100fdx
.value
.ul
=
5306 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
);
5307 knp
->ks_cap_100hdx
.value
.ul
=
5308 BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
);
5309 knp
->ks_cap_10fdx
.value
.ul
=
5310 BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
);
5311 knp
->ks_cap_10hdx
.value
.ul
=
5312 BOOLEAN(dp
->mii_status
& MII_STATUS_10
);
5314 knp
->ks_cap_remfault
.value
.ul
= B_TRUE
;
5316 knp
->ks_cap_autoneg
.value
.ul
=
5317 BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
);
5319 knp
->ks_adv_cap_1000fdx
.value
.ul
= dp
->anadv_1000fdx
;
5320 knp
->ks_adv_cap_1000hdx
.value
.ul
= dp
->anadv_1000hdx
;
5321 knp
->ks_adv_cap_100fdx
.value
.ul
= dp
->anadv_100fdx
;
5322 knp
->ks_adv_cap_100hdx
.value
.ul
= dp
->anadv_100hdx
;
5323 knp
->ks_adv_cap_10fdx
.value
.ul
= dp
->anadv_10fdx
;
5324 knp
->ks_adv_cap_10hdx
.value
.ul
= dp
->anadv_10hdx
;
5326 knp
->ks_adv_cap_remfault
.value
.ul
= 0;
5328 knp
->ks_adv_cap_autoneg
.value
.ul
= dp
->anadv_autoneg
;
5330 knp
->ks_lp_cap_1000fdx
.value
.ul
=
5331 BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_FULL
);
5332 knp
->ks_lp_cap_1000hdx
.value
.ul
=
5333 BOOLEAN(dp
->mii_stat1000
& MII_1000TS_LP_HALF
);
5334 knp
->ks_lp_cap_100fdx
.value
.ul
=
5335 BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX_FD
);
5336 knp
->ks_lp_cap_100hdx
.value
.ul
=
5337 BOOLEAN(dp
->mii_lpable
& MII_ABILITY_100BASE_TX
);
5338 knp
->ks_lp_cap_10fdx
.value
.ul
=
5339 BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T_FD
);
5340 knp
->ks_lp_cap_10hdx
.value
.ul
=
5341 BOOLEAN(dp
->mii_lpable
& MII_ABILITY_10BASE_T
);
5342 knp
->ks_lp_cap_remfault
.value
.ul
=
5343 BOOLEAN(dp
->mii_exp
& MII_AN_EXP_PARFAULT
);
5344 knp
->ks_lp_cap_autoneg
.value
.ul
=
5345 BOOLEAN(dp
->mii_exp
& MII_AN_EXP_LPCANAN
);
5352 usbgem_kstat_init(struct usbgem_dev
*dp
)
5356 struct usbgem_kstat_named
*knp
;
5359 (char *)ddi_driver_name(dp
->dip
), ddi_get_instance(dp
->dip
),
5360 "mii", "net", KSTAT_TYPE_NAMED
,
5361 sizeof (*knp
) / sizeof (knp
->ks_xcvr_addr
), 0);
5364 cmn_err(CE_WARN
, "%s: %s() for mii failed",
5365 dp
->name
, __func__
);
5366 return (USB_FAILURE
);
5369 knp
= (struct usbgem_kstat_named
*)ksp
->ks_data
;
5371 kstat_named_init(&knp
->ks_xcvr_addr
, "xcvr_addr",
5373 kstat_named_init(&knp
->ks_xcvr_id
, "xcvr_id",
5375 kstat_named_init(&knp
->ks_xcvr_inuse
, "xcvr_inuse",
5377 kstat_named_init(&knp
->ks_link_up
, "link_up",
5379 kstat_named_init(&knp
->ks_link_duplex
, "link_duplex",
5381 kstat_named_init(&knp
->ks_cap_1000fdx
, "cap_1000fdx",
5383 kstat_named_init(&knp
->ks_cap_1000hdx
, "cap_1000hdx",
5385 kstat_named_init(&knp
->ks_cap_100fdx
, "cap_100fdx",
5387 kstat_named_init(&knp
->ks_cap_100hdx
, "cap_100hdx",
5389 kstat_named_init(&knp
->ks_cap_10fdx
, "cap_10fdx",
5391 kstat_named_init(&knp
->ks_cap_10hdx
, "cap_10hdx",
5394 kstat_named_init(&knp
->ks_cap_remfault
, "cap_rem_fault",
5397 kstat_named_init(&knp
->ks_cap_autoneg
, "cap_autoneg",
5399 kstat_named_init(&knp
->ks_adv_cap_1000fdx
, "adv_cap_1000fdx",
5401 kstat_named_init(&knp
->ks_adv_cap_1000hdx
, "adv_cap_1000hdx",
5403 kstat_named_init(&knp
->ks_adv_cap_100fdx
, "adv_cap_100fdx",
5405 kstat_named_init(&knp
->ks_adv_cap_100hdx
, "adv_cap_100hdx",
5407 kstat_named_init(&knp
->ks_adv_cap_10fdx
, "adv_cap_10fdx",
5409 kstat_named_init(&knp
->ks_adv_cap_10hdx
, "adv_cap_10hdx",
5412 kstat_named_init(&knp
->ks_adv_cap_remfault
, "adv_rem_fault",
5415 kstat_named_init(&knp
->ks_adv_cap_autoneg
, "adv_cap_autoneg",
5418 kstat_named_init(&knp
->ks_lp_cap_1000fdx
, "lp_cap_1000fdx",
5420 kstat_named_init(&knp
->ks_lp_cap_1000hdx
, "lp_cap_1000hdx",
5422 kstat_named_init(&knp
->ks_lp_cap_100fdx
, "lp_cap_100fdx",
5424 kstat_named_init(&knp
->ks_lp_cap_100hdx
, "lp_cap_100hdx",
5426 kstat_named_init(&knp
->ks_lp_cap_10fdx
, "lp_cap_10fdx",
5428 kstat_named_init(&knp
->ks_lp_cap_10hdx
, "lp_cap_10hdx",
5430 kstat_named_init(&knp
->ks_lp_cap_remfault
, "lp_cap_rem_fault",
5432 kstat_named_init(&knp
->ks_lp_cap_autoneg
, "lp_cap_autoneg",
5435 ksp
->ks_private
= (void *) dp
;
5436 ksp
->ks_update
= usbgem_kstat_update
;
5441 return (USB_SUCCESS
);
5443 #endif /* GEM_CONFIG_GLDv3 */
5444 /* ======================================================================== */
5446 * attach/detatch/usb support
5448 /* ======================================================================== */
5450 usbgem_ctrl_out(struct usbgem_dev
*dp
,
5451 uint8_t reqt
, uint8_t req
, uint16_t val
, uint16_t ix
, uint16_t len
,
5455 usb_ctrl_setup_t setup
;
5456 usb_cr_t completion_reason
;
5457 usb_cb_flags_t cb_flags
;
5462 DPRINTF(4, (CE_CONT
, "!%s: %s "
5463 "reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x "
5464 "bp:0x%p nic_state:%d",
5465 dp
->name
, __func__
, reqt
, req
, val
, ix
, len
, bp
, dp
->nic_state
));
5467 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
5468 return (USB_PIPE_ERROR
);
5473 if ((data
= allocb(size
, 0)) == NULL
) {
5474 return (USB_FAILURE
);
5477 bcopy(bp
, data
->b_rptr
, size
);
5478 data
->b_wptr
= data
->b_rptr
+ size
;
5481 setup
.bmRequestType
= reqt
;
5482 setup
.bRequest
= req
;
5485 setup
.wLength
= len
;
5486 setup
.attrs
= 0; /* attributes */
5488 for (i
= usbgem_ctrl_retry
; i
> 0; i
--) {
5489 completion_reason
= 0;
5492 ret
= usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp
),
5493 &setup
, &data
, &completion_reason
, &cb_flags
, 0);
5495 if (ret
== USB_SUCCESS
) {
5501 "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x "
5502 "ret:%d cr:%s(%d), cb_flags:0x%x %s",
5503 dp
->name
, __func__
, reqt
, req
, val
, ix
, len
,
5504 ret
, usb_str_cr(completion_reason
),
5507 (i
> 1) ? "retrying..." : "fatal");
5519 usbgem_ctrl_in(struct usbgem_dev
*dp
,
5520 uint8_t reqt
, uint8_t req
, uint16_t val
, uint16_t ix
, uint16_t len
,
5524 usb_ctrl_setup_t setup
;
5525 usb_cr_t completion_reason
;
5526 usb_cb_flags_t cb_flags
;
5531 DPRINTF(4, (CE_CONT
,
5533 " reqt:0x%02x req:0x%02x val:0x%04x ix:0x%04x len:0x%02x"
5534 " bp:x%p mac_state:%d",
5535 dp
->name
, __func__
, reqt
, req
, val
, ix
, len
, bp
, dp
->mac_state
));
5537 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
5538 return (USB_PIPE_ERROR
);
5543 setup
.bmRequestType
= reqt
;
5544 setup
.bRequest
= req
;
5547 setup
.wLength
= len
;
5548 setup
.attrs
= USB_ATTRS_AUTOCLEARING
; /* XXX */
5550 for (i
= usbgem_ctrl_retry
; i
> 0; i
--) {
5551 completion_reason
= 0;
5553 ret
= usb_pipe_ctrl_xfer_wait(DEFAULT_PIPE(dp
), &setup
, &data
,
5554 &completion_reason
, &cb_flags
, 0);
5556 if (ret
== USB_SUCCESS
) {
5557 reclen
= msgdsize(data
);
5558 bcopy(data
->b_rptr
, bp
, min(reclen
, size
));
5564 "reqt:0x%x req:0x%x val:0x%x ix:0x%x len:0x%x "
5565 "ret:%d cr:%s(%d) cb_flags:0x%x %s",
5567 reqt
, req
, val
, ix
, len
,
5568 ret
, usb_str_cr(completion_reason
),
5571 (i
> 1) ? "retrying..." : "fatal");
5583 usbgem_ctrl_out_val(struct usbgem_dev
*dp
,
5584 uint8_t reqt
, uint8_t req
, uint16_t val
, uint16_t ix
, uint16_t len
,
5589 /* convert to little endian from native byte order */
5602 return (usbgem_ctrl_out(dp
, reqt
, req
, val
, ix
, len
, buf
, len
));
5606 usbgem_ctrl_in_val(struct usbgem_dev
*dp
,
5607 uint8_t reqt
, uint8_t req
, uint16_t val
, uint16_t ix
, uint16_t len
,
5615 bzero(buf
, sizeof (buf
));
5617 err
= usbgem_ctrl_in(dp
, reqt
, req
, val
, ix
, len
, buf
, len
);
5618 if (err
== USB_SUCCESS
) {
5634 *(uint32_t *)valp
= v
;
5637 *(uint16_t *)valp
= v
;
5640 *(uint8_t *)valp
= v
;
5648 * Attach / detach / disconnect / reconnect management
5651 usbgem_open_pipes(struct usbgem_dev
*dp
)
5657 usb_client_dev_data_t
*reg_data
;
5658 usb_ep_data_t
*ep_tree_node
;
5660 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
5662 ifnum
= dp
->ugc
.usbgc_ifnum
;
5663 alt
= dp
->ugc
.usbgc_alt
;
5665 ep_tree_node
= usb_lookup_ep_data(dp
->dip
, dp
->reg_data
, ifnum
, alt
,
5666 0, USB_EP_ATTR_BULK
, USB_EP_DIR_IN
);
5667 if (ep_tree_node
== NULL
) {
5668 cmn_err(CE_WARN
, "!%s: %s: ep_bulkin is NULL",
5669 dp
->name
, __func__
);
5672 dp
->ep_bulkin
= &ep_tree_node
->ep_descr
;
5674 ep_tree_node
= usb_lookup_ep_data(dp
->dip
, dp
->reg_data
, ifnum
, alt
,
5675 0, USB_EP_ATTR_BULK
, USB_EP_DIR_OUT
);
5676 if (ep_tree_node
== NULL
) {
5677 cmn_err(CE_WARN
, "!%s: %s: ep_bulkout is NULL",
5678 dp
->name
, __func__
);
5681 dp
->ep_bulkout
= &ep_tree_node
->ep_descr
;
5683 ep_tree_node
= usb_lookup_ep_data(dp
->dip
, dp
->reg_data
, ifnum
, alt
,
5684 0, USB_EP_ATTR_INTR
, USB_EP_DIR_IN
);
5686 dp
->ep_intr
= &ep_tree_node
->ep_descr
;
5689 DPRINTF(1, (CE_CONT
, "!%s: %s: ep_intr is NULL",
5690 dp
->name
, __func__
));
5694 /* XXX -- no need to open default pipe */
5696 /* open bulk out pipe */
5697 bzero(&dp
->policy_bulkout
, sizeof (usb_pipe_policy_t
));
5698 dp
->policy_bulkout
.pp_max_async_reqs
= 1;
5700 if ((ret
= usb_pipe_open(dp
->dip
,
5701 dp
->ep_bulkout
, &dp
->policy_bulkout
, USB_FLAGS_SLEEP
,
5702 &dp
->bulkout_pipe
)) != USB_SUCCESS
) {
5704 "!%s: %s: err:%x: failed to open bulk-out pipe",
5705 dp
->name
, __func__
, ret
);
5706 dp
->bulkout_pipe
= NULL
;
5709 DPRINTF(1, (CE_CONT
, "!%s: %s: bulkout_pipe opened successfully",
5710 dp
->name
, __func__
));
5712 /* open bulk in pipe */
5713 bzero(&dp
->policy_bulkin
, sizeof (usb_pipe_policy_t
));
5714 dp
->policy_bulkin
.pp_max_async_reqs
= 1;
5715 if ((ret
= usb_pipe_open(dp
->dip
,
5716 dp
->ep_bulkin
, &dp
->policy_bulkin
, USB_FLAGS_SLEEP
,
5717 &dp
->bulkin_pipe
)) != USB_SUCCESS
) {
5719 "!%s: %s: ret:%x failed to open bulk-in pipe",
5720 dp
->name
, __func__
, ret
);
5721 dp
->bulkin_pipe
= NULL
;
5724 DPRINTF(1, (CE_CONT
, "!%s: %s: bulkin_pipe opened successfully",
5725 dp
->name
, __func__
));
5728 /* open interrupt pipe */
5729 bzero(&dp
->policy_interrupt
, sizeof (usb_pipe_policy_t
));
5730 dp
->policy_interrupt
.pp_max_async_reqs
= 1;
5731 if ((ret
= usb_pipe_open(dp
->dip
, dp
->ep_intr
,
5732 &dp
->policy_interrupt
, USB_FLAGS_SLEEP
,
5733 &dp
->intr_pipe
)) != USB_SUCCESS
) {
5735 "!%s: %s: ret:%x failed to open interrupt pipe",
5736 dp
->name
, __func__
, ret
);
5737 dp
->intr_pipe
= NULL
;
5741 DPRINTF(1, (CE_CONT
, "!%s: %s: intr_pipe opened successfully",
5742 dp
->name
, __func__
));
5744 return (USB_SUCCESS
);
5747 if (dp
->bulkin_pipe
) {
5748 usb_pipe_close(dp
->dip
,
5749 dp
->bulkin_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5750 dp
->bulkin_pipe
= NULL
;
5752 if (dp
->bulkout_pipe
) {
5753 usb_pipe_close(dp
->dip
,
5754 dp
->bulkout_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5755 dp
->bulkout_pipe
= NULL
;
5757 if (dp
->intr_pipe
) {
5758 usb_pipe_close(dp
->dip
,
5759 dp
->intr_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5760 dp
->intr_pipe
= NULL
;
5763 return (USB_FAILURE
);
5767 usbgem_close_pipes(struct usbgem_dev
*dp
)
5769 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
5771 if (dp
->intr_pipe
) {
5772 usb_pipe_close(dp
->dip
,
5773 dp
->intr_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5774 dp
->intr_pipe
= NULL
;
5776 DPRINTF(1, (CE_CONT
, "!%s: %s: 1", dp
->name
, __func__
));
5778 ASSERT(dp
->bulkin_pipe
);
5779 usb_pipe_close(dp
->dip
, dp
->bulkin_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5780 dp
->bulkin_pipe
= NULL
;
5781 DPRINTF(1, (CE_CONT
, "!%s: %s: 2", dp
->name
, __func__
));
5783 ASSERT(dp
->bulkout_pipe
);
5784 usb_pipe_close(dp
->dip
, dp
->bulkout_pipe
, USB_FLAGS_SLEEP
, NULL
, 0);
5785 dp
->bulkout_pipe
= NULL
;
5786 DPRINTF(1, (CE_CONT
, "!%s: %s: 3", dp
->name
, __func__
));
5788 return (USB_SUCCESS
);
5791 #define FREEZE_GRACEFUL (B_TRUE)
5792 #define FREEZE_NO_GRACEFUL (B_FALSE)
5794 usbgem_freeze_device(struct usbgem_dev
*dp
, boolean_t graceful
)
5796 DPRINTF(0, (CE_NOTE
, "!%s: %s: called", dp
->name
, __func__
));
5798 /* stop nic activity */
5799 (void) usbgem_mac_stop(dp
, MAC_STATE_DISCONNECTED
, graceful
);
5802 * Here we free all memory resource allocated, because it will
5803 * cause to panic the system that we free usb_bulk_req objects
5804 * during the usb device is disconnected.
5806 (void) usbgem_free_memory(dp
);
5808 return (USB_SUCCESS
);
5812 usbgem_disconnect_cb(dev_info_t
*dip
)
5815 struct usbgem_dev
*dp
;
5817 dp
= USBGEM_GET_DEV(dip
);
5819 cmn_err(CE_NOTE
, "!%s: the usb device was disconnected (dp=%p)",
5820 dp
->name
, (void *)dp
);
5822 /* start serialize */
5823 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
5825 ret
= usbgem_freeze_device(dp
, 0);
5827 /* end of serialize */
5828 rw_exit(&dp
->dev_state_lock
);
5834 usbgem_recover_device(struct usbgem_dev
*dp
)
5838 DPRINTF(0, (CE_NOTE
, "!%s: %s: called", dp
->name
, __func__
));
5842 /* reinitialize the usb connection */
5843 usbgem_close_pipes(dp
);
5844 if ((err
= usbgem_open_pipes(dp
)) != USB_SUCCESS
) {
5848 /* initialize nic state */
5849 dp
->mac_state
= MAC_STATE_STOPPED
;
5850 dp
->mii_state
= MII_STATE_UNKNOWN
;
5852 /* allocate memory resources again */
5853 if ((err
= usbgem_alloc_memory(dp
)) != USB_SUCCESS
) {
5857 /* restart nic and recover state */
5858 (void) usbgem_restart_nic(dp
);
5860 usbgem_mii_init(dp
);
5862 /* kick potentially stopped house keeping thread */
5863 cv_signal(&dp
->link_watcher_wait_cv
);
5869 usbgem_reconnect_cb(dev_info_t
*dip
)
5871 int err
= USB_SUCCESS
;
5872 struct usbgem_dev
*dp
;
5874 dp
= USBGEM_GET_DEV(dip
);
5875 DPRINTF(0, (CE_CONT
, "!%s: dp=%p", ddi_get_name(dip
), dp
));
5877 /* check device changes after disconnect */
5878 if (usb_check_same_device(dp
->dip
, NULL
, USB_LOG_L2
, -1,
5879 USB_CHK_BASIC
| USB_CHK_CFG
, NULL
) != USB_SUCCESS
) {
5881 "!%s: no or different device installed", dp
->name
);
5882 return (DDI_SUCCESS
);
5885 cmn_err(CE_NOTE
, "%s: the usb device was reconnected", dp
->name
);
5887 /* start serialize */
5888 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
5890 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
5891 err
= usbgem_recover_device(dp
);
5894 /* end of serialize */
5895 rw_exit(&dp
->dev_state_lock
);
5897 return (err
== USB_SUCCESS
? DDI_SUCCESS
: DDI_FAILURE
);
5901 usbgem_suspend(dev_info_t
*dip
)
5903 int err
= USB_SUCCESS
;
5904 struct usbgem_dev
*dp
;
5906 dp
= USBGEM_GET_DEV(dip
);
5908 DPRINTF(0, (CE_CONT
, "!%s: %s: callded", dp
->name
, __func__
));
5910 /* start serialize */
5911 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
5913 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
5914 err
= usbgem_freeze_device(dp
, STOP_GRACEFUL
);
5917 /* end of serialize */
5918 rw_exit(&dp
->dev_state_lock
);
5920 return (err
== USB_SUCCESS
? DDI_SUCCESS
: DDI_FAILURE
);
5924 usbgem_resume(dev_info_t
*dip
)
5926 int err
= USB_SUCCESS
;
5927 struct usbgem_dev
*dp
;
5929 dp
= USBGEM_GET_DEV(dip
);
5931 DPRINTF(0, (CE_CONT
, "!%s: %s: callded", dp
->name
, __func__
));
5933 /* check device changes after disconnect */
5934 if (usb_check_same_device(dp
->dip
, NULL
, USB_LOG_L2
, -1,
5935 USB_CHK_BASIC
| USB_CHK_CFG
, NULL
) != USB_SUCCESS
) {
5937 "!%s: no or different device installed", dp
->name
);
5938 return (DDI_SUCCESS
);
5941 /* start serialize */
5942 rw_enter(&dp
->dev_state_lock
, RW_WRITER
);
5944 if (dp
->mac_state
== MAC_STATE_DISCONNECTED
) {
5945 err
= usbgem_recover_device(dp
);
5948 /* end of serialize */
5949 rw_exit(&dp
->dev_state_lock
);
5951 return (err
== USB_SUCCESS
? DDI_SUCCESS
: DDI_FAILURE
);
5954 #define USBGEM_LOCAL_DATA_SIZE(gc) \
5955 (sizeof (struct usbgem_dev) + USBGEM_MCALLOC)
5958 usbgem_do_attach(dev_info_t
*dip
,
5959 struct usbgem_conf
*gc
, void *lp
, int lmsize
)
5961 struct usbgem_dev
*dp
;
5963 #ifdef USBGEM_CONFIG_GLDv3
5964 mac_register_t
*macp
= NULL
;
5966 gld_mac_info_t
*macinfo
;
5973 unit
= ddi_get_instance(dip
);
5975 DPRINTF(2, (CE_CONT
, "!usbgem%d: %s: called", unit
, __func__
));
5978 * Allocate soft data structure
5980 dp
= kmem_zalloc(USBGEM_LOCAL_DATA_SIZE(gc
), KM_SLEEP
);
5982 #ifndef USBGEM_CONFIG_GLDv3
5983 gld_mac_free(macinfo
);
5987 #ifdef USBGEM_CONFIG_GLDv3
5988 if ((macp
= mac_alloc(MAC_VERSION
)) == NULL
) {
5989 cmn_err(CE_WARN
, "!gem%d: %s: mac_alloc failed",
5994 macinfo
= gld_mac_alloc(dip
);
5995 dp
->macinfo
= macinfo
;
5998 /* link to private area */
6000 dp
->priv_size
= lmsize
;
6001 dp
->mc_list
= (struct mcast_addr
*)&dp
[1];
6004 bcopy(gc
->usbgc_name
, dp
->name
, USBGEM_NAME_LEN
);
6007 * register with usb service
6009 if (usb_client_attach(dip
, USBDRV_VERSION
, 0) != USB_SUCCESS
) {
6011 "%s: %s: usb_client_attach failed",
6012 dp
->name
, __func__
);
6013 goto err_free_private
;
6016 if (usb_get_dev_data(dip
, &dp
->reg_data
,
6017 USB_PARSE_LVL_ALL
, 0) != USB_SUCCESS
) {
6018 dp
->reg_data
= NULL
;
6019 goto err_unregister_client
;
6021 #ifdef USBGEM_DEBUG_LEVEL
6022 usb_print_descr_tree(dp
->dip
, dp
->reg_data
);
6025 if (usbgem_open_pipes(dp
) != USB_SUCCESS
) {
6026 /* failed to open pipes */
6027 cmn_err(CE_WARN
, "!%s: %s: failed to open pipes",
6028 dp
->name
, __func__
);
6029 goto err_unregister_client
;
6033 * Initialize mutexs and condition variables
6035 mutex_init(&dp
->rxlock
, NULL
, MUTEX_DRIVER
, NULL
);
6036 mutex_init(&dp
->txlock
, NULL
, MUTEX_DRIVER
, NULL
);
6037 cv_init(&dp
->rx_drain_cv
, NULL
, CV_DRIVER
, NULL
);
6038 cv_init(&dp
->tx_drain_cv
, NULL
, CV_DRIVER
, NULL
);
6039 rw_init(&dp
->dev_state_lock
, NULL
, RW_DRIVER
, NULL
);
6040 mutex_init(&dp
->link_watcher_lock
, NULL
, MUTEX_DRIVER
, NULL
);
6041 cv_init(&dp
->link_watcher_wait_cv
, NULL
, CV_DRIVER
, NULL
);
6042 sema_init(&dp
->hal_op_lock
, 1, NULL
, SEMA_DRIVER
, NULL
);
6043 sema_init(&dp
->rxfilter_lock
, 1, NULL
, SEMA_DRIVER
, NULL
);
6046 * Initialize configuration
6052 dp
->speed
= USBGEM_SPD_10
; /* default is 10Mbps */
6053 dp
->full_duplex
= B_FALSE
; /* default is half */
6054 dp
->flow_control
= FLOW_CONTROL_NONE
;
6056 dp
->nic_state
= NIC_STATE_STOPPED
;
6057 dp
->mac_state
= MAC_STATE_STOPPED
;
6058 dp
->mii_state
= MII_STATE_UNKNOWN
;
6060 /* performance tuning parameters */
6061 dp
->txthr
= ETHERMAX
; /* tx fifo threshoold */
6062 dp
->txmaxdma
= 16*4; /* tx max dma burst size */
6063 dp
->rxthr
= 128; /* rx fifo threshoold */
6064 dp
->rxmaxdma
= 16*4; /* rx max dma burst size */
6067 * Get media mode infomation from .conf file
6069 usbgem_read_conf(dp
);
6071 /* rx_buf_len depend on MTU */
6072 dp
->rx_buf_len
= MAXPKTBUF(dp
) + dp
->ugc
.usbgc_rx_header_len
;
6077 if (usbgem_hal_reset_chip(dp
) != USB_SUCCESS
) {
6079 "!%s: %s: failed to reset the usb device",
6080 dp
->name
, __func__
);
6081 goto err_destroy_locks
;
6085 * HW dependant paremeter initialization
6087 if (usbgem_hal_attach_chip(dp
) != USB_SUCCESS
) {
6089 "!%s: %s: failed to attach the usb device",
6090 dp
->name
, __func__
);
6091 goto err_destroy_locks
;
6094 /* allocate resources */
6095 if (usbgem_alloc_memory(dp
) != USB_SUCCESS
) {
6096 goto err_destroy_locks
;
6099 DPRINTF(0, (CE_CONT
,
6100 "!%s: %02x:%02x:%02x:%02x:%02x:%02x",
6102 dp
->dev_addr
.ether_addr_octet
[0],
6103 dp
->dev_addr
.ether_addr_octet
[1],
6104 dp
->dev_addr
.ether_addr_octet
[2],
6105 dp
->dev_addr
.ether_addr_octet
[3],
6106 dp
->dev_addr
.ether_addr_octet
[4],
6107 dp
->dev_addr
.ether_addr_octet
[5]));
6109 /* copy mac address */
6110 dp
->cur_addr
= dp
->dev_addr
;
6112 /* pre-calculated tx timeout in second for performance */
6113 dp
->bulkout_timeout
=
6114 dp
->ugc
.usbgc_tx_timeout
/ drv_usectohz(1000*1000);
6116 #ifdef USBGEM_CONFIG_GLDv3
6117 usbgem_gld3_init(dp
, macp
);
6119 usbgem_gld_init(dp
, macinfo
, ident
);
6122 /* Probe MII phy (scan phy) */
6126 dp
->mii_ctl1000
= 0;
6127 dp
->mii_stat1000
= 0;
6129 dp
->mii_status_ro
= 0;
6130 dp
->mii_xstatus_ro
= 0;
6132 if (usbgem_mii_probe(dp
) != USB_SUCCESS
) {
6133 cmn_err(CE_WARN
, "!%s: %s: mii_probe failed",
6134 dp
->name
, __func__
);
6135 goto err_free_memory
;
6138 /* mask unsupported abilities */
6139 dp
->anadv_autoneg
&= BOOLEAN(dp
->mii_status
& MII_STATUS_CANAUTONEG
);
6140 dp
->anadv_1000fdx
&=
6141 BOOLEAN(dp
->mii_xstatus
&
6142 (MII_XSTATUS_1000BASEX_FD
| MII_XSTATUS_1000BASET_FD
));
6143 dp
->anadv_1000hdx
&=
6144 BOOLEAN(dp
->mii_xstatus
&
6145 (MII_XSTATUS_1000BASEX
| MII_XSTATUS_1000BASET
));
6146 dp
->anadv_100t4
&= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASE_T4
);
6147 dp
->anadv_100fdx
&= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX_FD
);
6148 dp
->anadv_100hdx
&= BOOLEAN(dp
->mii_status
& MII_STATUS_100_BASEX
);
6149 dp
->anadv_10fdx
&= BOOLEAN(dp
->mii_status
& MII_STATUS_10_FD
);
6150 dp
->anadv_10hdx
&= BOOLEAN(dp
->mii_status
& MII_STATUS_10
);
6152 if (usbgem_mii_init(dp
) != USB_SUCCESS
) {
6153 cmn_err(CE_WARN
, "!%s: %s: mii_init failed",
6154 dp
->name
, __func__
);
6155 goto err_free_memory
;
6159 * initialize kstats including mii statistics
6161 #ifdef USBGEM_CONFIG_GLDv3
6162 #ifdef USBGEM_CONFIG_ND
6163 usbgem_nd_setup(dp
);
6166 if (usbgem_kstat_init(dp
) != USB_SUCCESS
) {
6167 goto err_free_memory
;
6172 * Add interrupt to system.
6174 #ifdef USBGEM_CONFIG_GLDv3
6175 if (ret
= mac_register(macp
, &dp
->mh
)) {
6176 cmn_err(CE_WARN
, "!%s: mac_register failed, error:%d",
6178 goto err_release_stats
;
6183 /* gld_register will corrupts driver_private */
6184 tmp
= ddi_get_driver_private(dip
);
6185 if (gld_register(dip
,
6186 (char *)ddi_driver_name(dip
), macinfo
) != DDI_SUCCESS
) {
6187 cmn_err(CE_WARN
, "!%s: %s: gld_register failed",
6188 dp
->name
, __func__
);
6189 ddi_set_driver_private(dip
, tmp
);
6190 goto err_release_stats
;
6192 /* restore driver private */
6193 ddi_set_driver_private(dip
, tmp
);
6194 #endif /* USBGEM_CONFIG_GLDv3 */
6195 if (usb_register_hotplug_cbs(dip
,
6196 usbgem_suspend
, usbgem_resume
) != USB_SUCCESS
) {
6198 "!%s: %s: failed to register hotplug cbs",
6199 dp
->name
, __func__
);
6200 goto err_unregister_gld
;
6203 /* reset mii and start mii link watcher */
6204 if (usbgem_mii_start(dp
) != USB_SUCCESS
) {
6205 goto err_unregister_hotplug
;
6208 /* start tx watchdow watcher */
6209 if (usbgem_tx_watcher_start(dp
)) {
6210 goto err_usbgem_mii_stop
;
6213 ddi_set_driver_private(dip
, (caddr_t
)dp
);
6215 DPRINTF(2, (CE_CONT
, "!%s: %s: return: success", dp
->name
, __func__
));
6219 err_usbgem_mii_stop
:
6220 usbgem_mii_stop(dp
);
6222 err_unregister_hotplug
:
6223 usb_unregister_hotplug_cbs(dip
);
6226 #ifdef USBGEM_CONFIG_GLDv3
6227 mac_unregister(dp
->mh
);
6229 gld_unregister(macinfo
);
6233 #ifdef USBGEM_CONFIG_GLDv3
6234 #ifdef USBGEM_CONFIG_ND
6235 /* release NDD resources */
6236 usbgem_nd_cleanup(dp
);
6239 kstat_delete(dp
->ksp
);
6243 usbgem_free_memory(dp
);
6246 cv_destroy(&dp
->tx_drain_cv
);
6247 cv_destroy(&dp
->rx_drain_cv
);
6248 mutex_destroy(&dp
->txlock
);
6249 mutex_destroy(&dp
->rxlock
);
6250 rw_destroy(&dp
->dev_state_lock
);
6251 mutex_destroy(&dp
->link_watcher_lock
);
6252 cv_destroy(&dp
->link_watcher_wait_cv
);
6253 sema_destroy(&dp
->hal_op_lock
);
6254 sema_destroy(&dp
->rxfilter_lock
);
6257 (void) usbgem_close_pipes(dp
);
6259 err_unregister_client
:
6260 usb_client_detach(dp
->dip
, dp
->reg_data
);
6263 #ifdef USBGEM_CONFIG_GLDv3
6268 gld_mac_free(macinfo
);
6270 kmem_free((caddr_t
)dp
, USBGEM_LOCAL_DATA_SIZE(gc
));
6276 usbgem_do_detach(dev_info_t
*dip
)
6278 struct usbgem_dev
*dp
;
6280 dp
= USBGEM_GET_DEV(dip
);
6282 #ifdef USBGEM_CONFIG_GLDv3
6283 /* unregister with gld v3 */
6284 if (mac_unregister(dp
->mh
) != DDI_SUCCESS
) {
6285 return (DDI_FAILURE
);
6288 /* unregister with gld v2 */
6289 if (gld_unregister(dp
->macinfo
) != DDI_SUCCESS
) {
6290 return (DDI_FAILURE
);
6293 /* unregister with hotplug service */
6294 usb_unregister_hotplug_cbs(dip
);
6296 /* stop tx watchdog watcher */
6297 usbgem_tx_watcher_stop(dp
);
6299 /* stop the link manager */
6300 usbgem_mii_stop(dp
);
6302 /* unregister with usb service */
6303 (void) usbgem_free_memory(dp
);
6304 (void) usbgem_close_pipes(dp
);
6305 usb_client_detach(dp
->dip
, dp
->reg_data
);
6306 dp
->reg_data
= NULL
;
6308 /* unregister with kernel statistics */
6309 #ifdef USBGEM_CONFIG_GLDv3
6310 #ifdef USBGEM_CONFIG_ND
6311 /* release ndd resources */
6312 usbgem_nd_cleanup(dp
);
6315 /* destroy kstat objects */
6316 kstat_delete(dp
->ksp
);
6319 /* release locks and condition variables */
6320 mutex_destroy(&dp
->txlock
);
6321 mutex_destroy(&dp
->rxlock
);
6322 cv_destroy(&dp
->tx_drain_cv
);
6323 cv_destroy(&dp
->rx_drain_cv
);
6324 rw_destroy(&dp
->dev_state_lock
);
6325 mutex_destroy(&dp
->link_watcher_lock
);
6326 cv_destroy(&dp
->link_watcher_wait_cv
);
6327 sema_destroy(&dp
->hal_op_lock
);
6328 sema_destroy(&dp
->rxfilter_lock
);
6330 /* release basic memory resources */
6331 #ifndef USBGEM_CONFIG_GLDv3
6332 gld_mac_free(dp
->macinfo
);
6334 kmem_free((caddr_t
)(dp
->private), dp
->priv_size
);
6335 kmem_free((caddr_t
)dp
, USBGEM_LOCAL_DATA_SIZE(&dp
->ugc
));
6337 DPRINTF(2, (CE_CONT
, "!%s: %s: return: success",
6338 ddi_driver_name(dip
), __func__
));
6340 return (DDI_SUCCESS
);
6344 usbgem_mod_init(struct dev_ops
*dop
, char *name
)
6346 #ifdef USBGEM_CONFIG_GLDv3
6348 major
= ddi_name_to_major(name
);
6349 if (major
== DDI_MAJOR_T_NONE
) {
6350 return (DDI_FAILURE
);
6352 mac_init_ops(dop
, name
);
6354 return (DDI_SUCCESS
);
6358 usbgem_mod_fini(struct dev_ops
*dop
)
6360 #ifdef USBGEM_CONFIG_GLDv3
6366 usbgem_quiesce(dev_info_t
*dip
)
6368 struct usbgem_dev
*dp
;
6370 dp
= USBGEM_GET_DEV(dip
);
6374 if (dp
->mac_state
!= MAC_STATE_DISCONNECTED
&&
6375 dp
->mac_state
!= MAC_STATE_STOPPED
) {
6376 if (usbgem_hal_stop_chip(dp
) != USB_SUCCESS
) {
6377 (void) usbgem_hal_reset_chip(dp
);
6381 /* devo_quiesce() must return DDI_SUCCESS always */
6382 return (DDI_SUCCESS
);