2 * udmfE_usbgem.c : Davicom DM9601E USB to Fast Ethernet Driver for Solaris
4 * Copyright (c) 2009-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
41 /* ======================================================= */
44 * Solaris system header files and macros
47 /* minimum kernel headers for drivers */
48 #include <sys/types.h>
50 #include <sys/debug.h>
52 #include <sys/modctl.h>
53 #include <sys/errno.h>
55 #include <sys/sunddi.h>
56 #include <sys/byteorder.h>
59 #include <sys/ethernet.h>
61 /* interface card depend stuff */
62 #include <sys/stropts.h>
63 #include <sys/stream.h>
64 #include <sys/strlog.h>
65 #include <sys/strsun.h>
66 #include <sys/usb/usba.h>
70 #include "usbgem_mii.h"
71 #include "dm9601reg.h"
73 char ident
[] = "dm9601 usbnic driver v" VERSION
;
78 #define CHECK_AND_JUMP(err, label) if (err != USB_SUCCESS) goto label
79 #define LE16P(p) ((((uint8_t *)(p))[1] << 8) | ((uint8_t *)(p))[0])
85 static int udmf_debug
= DEBUG_LEVEL
;
86 #define DPRINTF(n, args) if (udmf_debug > (n)) cmn_err args
88 #define DPRINTF(n, args)
92 * Our configration for dm9601
95 #define ONESEC (drv_usectohz(1*1000000))
98 * Local device definitions
102 * Misc HW information
106 uint8_t mac_addr
[ETHERADDRL
];
114 static uint16_t udmf_mii_read(struct usbgem_dev
*, uint_t
, int *errp
);
115 static void udmf_mii_write(struct usbgem_dev
*, uint_t
, uint16_t, int *errp
);
118 static int udmf_reset_chip(struct usbgem_dev
*);
119 static int udmf_init_chip(struct usbgem_dev
*);
120 static int udmf_start_chip(struct usbgem_dev
*);
121 static int udmf_stop_chip(struct usbgem_dev
*);
122 static int udmf_set_media(struct usbgem_dev
*);
123 static int udmf_set_rx_filter(struct usbgem_dev
*);
124 static int udmf_get_stats(struct usbgem_dev
*);
125 static void udmf_interrupt(struct usbgem_dev
*, mblk_t
*);
127 /* packet operations */
128 static mblk_t
*udmf_tx_make_packet(struct usbgem_dev
*, mblk_t
*);
129 static mblk_t
*udmf_rx_make_packet(struct usbgem_dev
*, mblk_t
*);
131 /* =============================================================== */
135 /* =============================================================== */
136 #define OUT(dp, ix, len, buf, errp, label) \
137 if ((*(errp) = usbgem_ctrl_out((dp), \
138 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
139 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
143 /* wLength */ (len), \
145 /* size */ (len))) != USB_SUCCESS) goto label
147 #define OUTB(dp, ix, val, errp, label) \
148 if ((*(errp) = usbgem_ctrl_out((dp), \
149 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
150 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
152 /* wValue */ (val), \
156 /* size */ 0)) != USB_SUCCESS) goto label
158 #define IN(dp, ix, len, buf, errp, label) \
159 if ((*(errp) = usbgem_ctrl_in((dp), \
160 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
161 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
165 /* wLength */ (len), \
166 /* valuep */ (buf), \
167 /* size */ (len))) != USB_SUCCESS) goto label
169 /* =============================================================== */
171 * Hardware manupilation
173 /* =============================================================== */
175 udmf_enable_phy(struct usbgem_dev
*dp
)
177 int err
= USB_SUCCESS
;
179 /* de-assert reset signal to phy */
180 OUTB(dp
, GPCR
, GPCR_OUT(0), &err
, usberr
);
181 OUTB(dp
, GPR
, 0, &err
, usberr
);
187 udmf_reset_chip(struct usbgem_dev
*dp
)
189 int err
= USB_SUCCESS
;
191 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
193 OUTB(dp
, NCR
, NCR_LBK_NORMAL
| NCR_RST
, &err
, usberr
);
203 udmf_init_chip(struct usbgem_dev
*dp
)
207 int err
= USB_SUCCESS
;
210 struct udmf_dev
*lp
= dp
->private;
212 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
214 OUTB(dp
, NCR
, NCR_LBK_NORMAL
, &err
, usberr
);
216 /* tx control regiser: enable padding and crc generation */
217 OUTB(dp
, TCR
, 0, &err
, usberr
);
219 /* rx control register: will be set later by udmf_set_rx_filer() */
222 /* back pressure threshold: */
223 OUTB(dp
, BPTR
, (2 << BPTR_BPHW_SHIFT
) | BPTR_JPT_200us
,
226 /* flow control threshold: same as default */
227 OUTB(dp
, FCTR
, (3 << FCTR_HWOT_SHIFT
) | (8 << FCTR_LWOT_SHIFT
),
230 /* usb control register */
231 OUTB(dp
, USBC
, USBC_EP3ACK
| 0x06, &err
, usberr
);
233 /* flow control: will be set later by udmf_set_media() */
235 /* wake up control register: */
236 OUTB(dp
, WCR
, 0, &err
, usberr
);
239 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
241 err
, err
== USB_SUCCESS
? "success" : "error"));
246 udmf_start_chip(struct usbgem_dev
*dp
)
248 int err
= USB_SUCCESS
;
249 struct udmf_dev
*lp
= dp
->private;
253 OUTB(dp
, RCR
, lp
->rcr
, &err
, usberr
);
256 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
258 err
, err
== USB_SUCCESS
? "success" : "error"));
263 udmf_stop_chip(struct usbgem_dev
*dp
)
265 int err
= USB_SUCCESS
;
266 struct udmf_dev
*lp
= dp
->private;
269 lp
->rcr
&= ~RCR_RXEN
;
270 OUTB(dp
, RCR
, lp
->rcr
, &err
, usberr
);
273 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
275 err
, err
== USB_SUCCESS
? "success" : "error"));
280 udmf_get_stats(struct usbgem_dev
*dp
)
283 return (USB_SUCCESS
);
287 udmf_mcast_hash(struct usbgem_dev
*dp
, const uint8_t *addr
)
289 return (usbgem_ether_crc_le(addr
) & 0x3f);
293 udmf_set_rx_filter(struct usbgem_dev
*dp
)
301 int err
= USB_SUCCESS
;
302 struct udmf_dev
*lp
= dp
->private;
303 static uint8_t invalid_mac
[ETHERADDRL
] = {0, 0, 0, 0, 0, 0};
305 DPRINTF(2, (CE_CONT
, "!%s: %s: called, rxmode:%x",
306 dp
->name
, __func__
, dp
->rxmode
));
308 if (lp
->rcr
& RCR_RXEN
) {
309 /* set promiscuous mode before changing rx filter mode */
310 OUTB(dp
, RCR
, lp
->rcr
| RCR_PRMSC
, &err
, usberr
);
313 lp
->rcr
&= ~(RCR_ALL
| RCR_PRMSC
);
315 bzero(mhash
, sizeof (mhash
));
316 mac
= dp
->cur_addr
.ether_addr_octet
;
318 if ((dp
->rxmode
& RXMODE_ENABLE
) == 0) {
320 } else if (dp
->rxmode
& RXMODE_PROMISC
) {
321 /* promiscious mode implies all multicast and all physical */
323 } else if ((dp
->rxmode
& RXMODE_ALLMULTI
) || dp
->mc_count
> 32) {
324 /* accept all multicast packets */
326 } else if (dp
->mc_count
> 0) {
328 * make hash table to select interresting
329 * multicast address only.
331 for (i
= 0; i
< dp
->mc_count
; i
++) {
332 /* hash table is 64 = 2^6 bit width */
333 h
= dp
->mc_list
[i
].hash
;
334 mhash
[h
/ 8] |= 1 << (h
% 8);
338 /* set node address */
339 if (bcmp(mac
, lp
->mac_addr
, ETHERADDRL
) != 0) {
340 OUT(dp
, PAR
, ETHERADDRL
, dp
->cur_addr
.ether_addr_octet
,
342 bcopy(mac
, lp
->mac_addr
, ETHERADDRL
);
345 /* set multicast hash table */
346 OUT(dp
, MAR
, sizeof (mhash
), &mhash
[0], &err
, usberr
);
350 OUTB(dp
, RCR
, lp
->rcr
, &err
, usberr
);
354 IN(dp
, RCR
, 1, &rcr
, &err
, usberr
);
355 cmn_err(CE_CONT
, "!%s: %s: rcr:%b returned",
356 dp
->name
, __func__
, rcr
, RCR_BITS
);
359 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
361 err
, err
== USB_SUCCESS
? "success" : "error"));
366 udmf_set_media(struct usbgem_dev
*dp
)
368 int err
= USB_SUCCESS
;
370 struct udmf_dev
*lp
= dp
->private;
372 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
374 /* setup flow control */
376 if (dp
->full_duplex
) {
377 /* select flow control */
378 switch (dp
->flow_control
) {
379 case FLOW_CONTROL_RX_PAUSE
:
383 case FLOW_CONTROL_TX_PAUSE
:
387 case FLOW_CONTROL_SYMMETRIC
:
388 fcr
|= FCR_FLCE
| FCR_TXPEN
;
393 /* update flow control register */
394 OUTB(dp
, FCR
, fcr
, &err
, usberr
);
397 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
399 err
, err
== USB_SUCCESS
? "success" : "error"));
404 * send/receive packet check
407 udmf_tx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
417 pkt_size
= msgdsize(mp
);
424 /* minimum ethernet packet size of ETHERMIN */
425 pkt_size
= max(pkt_size
, ETHERMIN
);
427 #if 0 /* CONFIG_ADD_TX_DELIMITOR_ALWAYS */
428 pkt_size
+= TX_HEADER_SIZE
;
430 if (((pkt_size
+ TX_HEADER_SIZE
) & align_mask
) == 0) {
431 /* padding is required in usb communication */
432 pkt_size
+= TX_HEADER_SIZE
;
435 if ((new = allocb(TX_HEADER_SIZE
+ pkt_size
, 0)) == NULL
) {
438 new->b_wptr
= new->b_rptr
+ TX_HEADER_SIZE
+ pkt_size
;
442 bp
[0] = (uint8_t)pkt_size
;
443 bp
[1] = (uint8_t)(pkt_size
>> 8);
444 bp
+= TX_HEADER_SIZE
;
446 /* copy contents of the buffer */
447 for (tp
= mp
; tp
; tp
= tp
->b_cont
) {
449 bcopy(tp
->b_rptr
, bp
, n
);
453 /* clear the rest including the next zero length header */
454 last_pos
= new->b_wptr
;
455 while (bp
< last_pos
) {
463 udmf_dump_packet(struct usbgem_dev
*dp
, uint8_t *bp
, int n
)
467 for (i
= 0; i
< n
; i
+= 8, bp
+= 8) {
468 cmn_err(CE_CONT
, "%02x %02x %02x %02x %02x %02x %02x %02x",
469 bp
[0], bp
[1], bp
[2], bp
[3], bp
[4], bp
[5], bp
[6], bp
[7]);
474 udmf_rx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
481 if (len
<= RX_HEADER_SIZE
) {
483 * the usb bulk-in frame doesn't include a valid
489 /* remove rx header */
490 rx_stat
= mp
->b_rptr
[0];
491 if (rx_stat
& (RSR_RF
| RSR_LCS
| RSR_RWTO
|
492 RSR_PLE
| RSR_AE
| RSR_CE
| RSR_FOE
)) {
493 if (rx_stat
& RSR_RF
) {
496 if (rx_stat
& RSR_LCS
) {
498 dp
->stats
.rcv_internal_err
++;
500 if (rx_stat
& RSR_RWTO
) {
502 dp
->stats
.rcv_internal_err
++;
504 if (rx_stat
& RSR_PLE
) {
505 /* physical layer error */
506 dp
->stats
.rcv_internal_err
++;
508 if (rx_stat
& RSR_AE
) {
509 /* alignment error */
512 if (rx_stat
& RSR_CE
) {
516 if (rx_stat
& RSR_FOE
) {
517 /* fifo overflow error */
518 dp
->stats
.overflow
++;
522 len
= LE16P(&mp
->b_rptr
[1]);
523 if (len
>= ETHERFCSL
) {
526 mp
->b_rptr
+= RX_HEADER_SIZE
;
527 mp
->b_wptr
= mp
->b_rptr
+ len
;
536 udmf_ep_read(struct usbgem_dev
*dp
, uint_t which
, uint_t addr
, int *errp
)
542 DPRINTF(4, (CE_CONT
, "!%s: %s: called, ix:%d",
543 dp
->name
, __func__
, addr
));
545 OUTB(dp
, EPAR
, addr
, errp
, usberr
);
546 OUTB(dp
, EPCR
, which
| EPCR_ERPRR
, errp
, usberr
);
548 for (i
= 0; i
< 100; i
++) {
549 IN(dp
, EPCR
, sizeof (epcr
), &epcr
, errp
, usberr
);
550 if ((epcr
& EPCR_ERRE
) == 0) {
552 IN(dp
, EPDR
, sizeof (val
), &val
, errp
, usberr
);
559 cmn_err(CE_WARN
, "!%s: %s: timeout", dp
->name
, __func__
);
562 OUTB(dp
, EPCR
, 0, errp
, usberr
);
566 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
568 *errp
, *errp
== USB_SUCCESS
? "success" : "error"));
573 udmf_ep_write(struct usbgem_dev
*dp
, uint_t which
, uint_t addr
,
574 uint16_t val
, int *errp
)
579 DPRINTF(5, (CE_CONT
, "!%s: %s called", dp
->name
, __func__
));
582 OUT(dp
, EPDR
, sizeof (val
), &val
, errp
, usberr
);
584 OUTB(dp
, EPAR
, addr
, errp
, usberr
);
586 OUTB(dp
, EPCR
, which
| EPCR_WEP
| EPCR_ERPRW
, errp
, usberr
);
588 for (i
= 0; i
< 100; i
++) {
589 IN(dp
, EPCR
, 1, &epcr
, errp
, usberr
);
590 if ((epcr
& EPCR_ERRE
) == 0) {
597 cmn_err(CE_WARN
, "!%s: %s: timeout", dp
->name
, __func__
);
599 OUTB(dp
, EPCR
, 0, errp
, usberr
);
603 DPRINTF(2, (CE_CONT
, "!%s: %s: end err:%d(%s)",
605 *errp
, *errp
== USB_SUCCESS
? "success" : "error"));
609 udmf_mii_read(struct usbgem_dev
*dp
, uint_t index
, int *errp
)
613 val
= udmf_ep_read(dp
, EPCR_EPOS
,
614 (dp
->mii_phy_addr
<< EPAR_PHYADR_SHIFT
) | index
, errp
);
620 udmf_mii_write(struct usbgem_dev
*dp
, uint_t index
, uint16_t val
, int *errp
)
622 udmf_ep_write(dp
, EPCR_EPOS
,
623 (dp
->mii_phy_addr
<< EPAR_PHYADR_SHIFT
) | index
, val
, errp
);
627 udmf_interrupt(struct usbgem_dev
*dp
, mblk_t
*mp
)
629 struct intr_msg
*imp
;
630 struct udmf_dev
*lp
= dp
->private;
632 imp
= (struct intr_msg
*)&mp
->b_rptr
[0];
635 "!%s: %s: size:%d, nsr:%b tsr1:%b tsr2:%b"
636 " rsr:%b rocr:%b rxc:%02x txc:%b gpr:%b",
637 dp
->name
, __func__
, mp
->b_wptr
- mp
->b_rptr
,
638 imp
->im_nsr
, NSR_BITS
,
639 imp
->im_tsr1
, TSR_BITS
,
640 imp
->im_tsr2
, TSR_BITS
,
641 imp
->im_rsr
, RSR_BITS
,
642 imp
->im_rocr
, ROCR_BITS
,
644 imp
->im_txc
, TUSR_BITS
,
645 imp
->im_gpr
, GPR_BITS
));
647 if ((lp
->last_nsr
^ imp
->im_nsr
) & NSR_LINKST
) {
648 usbgem_mii_update_link(dp
);
651 lp
->last_nsr
= imp
->im_nsr
;
654 /* ======================================================== */
656 * OS depend (device driver DKI) routine
658 /* ======================================================== */
660 udmf_eeprom_read(struct usbgem_dev
*dp
, uint_t index
, int *errp
)
664 val
= udmf_ep_read(dp
, 0, index
, errp
);
671 udmf_eeprom_dump(struct usbgem_dev
*dp
, int size
)
675 uint16_t w0
, w1
, w2
, w3
;
677 cmn_err(CE_CONT
, "!%s: eeprom dump:", dp
->name
);
681 for (i
= 0; i
< size
; i
+= 4) {
682 w0
= udmf_eeprom_read(dp
, i
+ 0, &err
);
683 w1
= udmf_eeprom_read(dp
, i
+ 1, &err
);
684 w2
= udmf_eeprom_read(dp
, i
+ 2, &err
);
685 w3
= udmf_eeprom_read(dp
, i
+ 3, &err
);
686 cmn_err(CE_CONT
, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
695 udmf_attach_chip(struct usbgem_dev
*dp
)
701 struct udmf_dev
*lp
= dp
->private;
703 DPRINTF(0, (CE_CONT
, "!%s: %s enter", dp
->name
, __func__
));
706 * get mac address from EEPROM
708 m
= dp
->dev_addr
.ether_addr_octet
;
709 for (i
= 0; i
< ETHERADDRL
; i
+= 2) {
710 val
= udmf_eeprom_read(dp
, i
/2, &err
);
711 m
[i
+ 0] = (uint8_t)val
;
712 m
[i
+ 1] = (uint8_t)(val
>> 8);
715 /* invalidate a private cache for mac addr */
716 bzero(lp
->mac_addr
, sizeof (lp
->mac_addr
));
718 dp
->misc_flag
= USBGEM_VLAN
;
721 udmf_eeprom_dump(dp
, /* 0x3f + 1 */ 128);
724 static uint8_t bcst
[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
725 DPRINTF(0, (CE_CONT
, "!%s: %s: hash of bcast:%x",
726 dp
->name
, __func__
, usbgem_ether_crc_be(bcst
)));
728 return (USB_SUCCESS
);
731 cmn_err(CE_WARN
, "%s: %s: usb error detected (%d)",
732 dp
->name
, __func__
, err
);
733 return (USB_FAILURE
);
737 udmf_mii_probe(struct usbgem_dev
*dp
)
739 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
742 return (usbgem_mii_probe_default(dp
));
746 udmf_mii_init(struct usbgem_dev
*dp
)
748 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
750 return (USB_SUCCESS
);
754 udmfattach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
757 ddi_iblock_cookie_t c
;
762 const char *drv_name
;
763 struct usbgem_dev
*dp
;
765 struct usbgem_conf
*ugcp
;
768 unit
= ddi_get_instance(dip
);
769 drv_name
= ddi_driver_name(dip
);
771 DPRINTF(3, (CE_CONT
, "!%s%d: %s: called, cmd:%d",
772 drv_name
, unit
, __func__
, cmd
));
774 if (cmd
== DDI_ATTACH
) {
776 * construct usbgem configration
778 ugcp
= kmem_zalloc(sizeof (*ugcp
), KM_SLEEP
);
782 * softmac requires that ppa is the instance number
783 * of the device, otherwise it hangs in seaching the device.
785 (void) sprintf(ugcp
->usbgc_name
, "%s%d", drv_name
, unit
);
786 ugcp
->usbgc_ppa
= unit
;
788 ugcp
->usbgc_ifnum
= 0;
791 ugcp
->usbgc_tx_list_max
= 64;
793 ugcp
->usbgc_rx_header_len
= RX_HEADER_SIZE
;
794 ugcp
->usbgc_rx_list_max
= 64;
796 /* time out parameters */
797 ugcp
->usbgc_tx_timeout
= USBGEM_TX_TIMEOUT
;
798 ugcp
->usbgc_tx_timeout_interval
= USBGEM_TX_TIMEOUT_INTERVAL
;
801 ugcp
->usbgc_flow_control
= FLOW_CONTROL_RX_PAUSE
;
804 * XXX - flow control caused link down frequently under
807 ugcp
->usbgc_flow_control
= FLOW_CONTROL_NONE
;
809 /* MII timeout parameters */
810 ugcp
->usbgc_mii_link_watch_interval
=
811 USBGEM_LINK_WATCH_INTERVAL
;
812 ugcp
->usbgc_mii_an_watch_interval
=
813 USBGEM_LINK_WATCH_INTERVAL
/5;
814 ugcp
->usbgc_mii_reset_timeout
= MII_RESET_TIMEOUT
; /* 1 sec */
815 ugcp
->usbgc_mii_an_timeout
= MII_AN_TIMEOUT
; /* 5 sec */
816 ugcp
->usbgc_mii_an_wait
= (25*ONESEC
)/10;
817 ugcp
->usbgc_mii_linkdown_timeout
= MII_LINKDOWN_TIMEOUT
;
819 ugcp
->usbgc_mii_an_delay
= ONESEC
/10;
820 ugcp
->usbgc_mii_linkdown_action
= MII_ACTION_RSA
;
821 ugcp
->usbgc_mii_linkdown_timeout_action
= MII_ACTION_RESET
;
822 ugcp
->usbgc_mii_dont_reset
= B_FALSE
;
823 ugcp
->usbgc_mii_hw_link_detection
= B_TRUE
;
828 ugcp
->usbgc_attach_chip
= &udmf_attach_chip
;
829 ugcp
->usbgc_reset_chip
= &udmf_reset_chip
;
830 ugcp
->usbgc_init_chip
= &udmf_init_chip
;
831 ugcp
->usbgc_start_chip
= &udmf_start_chip
;
832 ugcp
->usbgc_stop_chip
= &udmf_stop_chip
;
833 ugcp
->usbgc_multicast_hash
= &udmf_mcast_hash
;
835 ugcp
->usbgc_set_rx_filter
= &udmf_set_rx_filter
;
836 ugcp
->usbgc_set_media
= &udmf_set_media
;
837 ugcp
->usbgc_get_stats
= &udmf_get_stats
;
838 ugcp
->usbgc_interrupt
= &udmf_interrupt
;
840 /* packet operation */
841 ugcp
->usbgc_tx_make_packet
= &udmf_tx_make_packet
;
842 ugcp
->usbgc_rx_make_packet
= &udmf_rx_make_packet
;
845 ugcp
->usbgc_mii_probe
= &udmf_mii_probe
;
846 ugcp
->usbgc_mii_init
= &udmf_mii_init
;
847 ugcp
->usbgc_mii_config
= &usbgem_mii_config_default
;
848 ugcp
->usbgc_mii_read
= &udmf_mii_read
;
849 ugcp
->usbgc_mii_write
= &udmf_mii_write
;
850 ugcp
->usbgc_mii_addr_min
= 1;
853 ugcp
->usbgc_min_mtu
= ETHERMTU
;
854 ugcp
->usbgc_max_mtu
= ETHERMTU
;
855 ugcp
->usbgc_default_mtu
= ETHERMTU
;
857 lp
= kmem_zalloc(sizeof (struct udmf_dev
), KM_SLEEP
);
859 ddi_set_driver_private(dip
, NULL
);
861 dp
= usbgem_do_attach(dip
, ugcp
, lp
, sizeof (struct udmf_dev
));
863 kmem_free(ugcp
, sizeof (*ugcp
));
866 return (DDI_SUCCESS
);
870 kmem_free(lp
, sizeof (struct udmf_dev
));
873 return (DDI_FAILURE
);
876 if (cmd
== DDI_RESUME
) {
877 return (usbgem_resume(dip
));
880 return (DDI_FAILURE
);
884 udmfdetach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
888 if (cmd
== DDI_DETACH
) {
889 ret
= usbgem_do_detach(dip
);
890 if (ret
!= DDI_SUCCESS
) {
891 return (DDI_FAILURE
);
893 return (DDI_SUCCESS
);
895 if (cmd
== DDI_SUSPEND
) {
896 return (usbgem_suspend(dip
));
898 return (DDI_FAILURE
);
901 /* ======================================================== */
903 * OS depend (loadable streams driver) routine
905 /* ======================================================== */
906 #ifdef USBGEM_CONFIG_GLDv3
907 USBGEM_STREAM_OPS(udmf_ops
, udmfattach
, udmfdetach
);
909 static struct module_info udmfminfo
= {
911 "udmf", /* mi_idname */
913 ETHERMTU
, /* mi_maxpsz */
914 ETHERMTU
*128, /* mi_hiwat */
918 static struct qinit udmfrinit
= {
919 (int (*)()) NULL
, /* qi_putp */
920 usbgem_rsrv
, /* qi_srvp */
921 usbgem_open
, /* qi_qopen */
922 usbgem_close
, /* qi_qclose */
923 (int (*)()) NULL
, /* qi_qadmin */
924 &udmfminfo
, /* qi_minfo */
928 static struct qinit udmfwinit
= {
929 usbgem_wput
, /* qi_putp */
930 usbgem_wsrv
, /* qi_srvp */
931 (int (*)()) NULL
, /* qi_qopen */
932 (int (*)()) NULL
, /* qi_qclose */
933 (int (*)()) NULL
, /* qi_qadmin */
934 &udmfminfo
, /* qi_minfo */
938 static struct streamtab udmf_info
= {
939 &udmfrinit
, /* st_rdinit */
940 &udmfwinit
, /* st_wrinit */
941 NULL
, /* st_muxrinit */
942 NULL
/* st_muxwrinit */
945 static struct cb_ops cb_udmf_ops
= {
946 nulldev
, /* cb_open */
947 nulldev
, /* cb_close */
948 nodev
, /* cb_strategy */
949 nodev
, /* cb_print */
952 nodev
, /* cb_write */
953 nodev
, /* cb_ioctl */
954 nodev
, /* cb_devmap */
956 nodev
, /* cb_segmap */
957 nochpoll
, /* cb_chpoll */
958 ddi_prop_op
, /* cb_prop_op */
959 &udmf_info
, /* cb_stream */
960 D_NEW
|D_MP
/* cb_flag */
963 static struct dev_ops udmf_ops
= {
964 DEVO_REV
, /* devo_rev */
966 usbgem_getinfo
, /* devo_getinfo */
967 nulldev
, /* devo_identify */
968 nulldev
, /* devo_probe */
969 udmfattach
, /* devo_attach */
970 udmfdetach
, /* devo_detach */
971 nodev
, /* devo_reset */
972 &cb_udmf_ops
, /* devo_cb_ops */
973 NULL
, /* devo_bus_ops */
974 usbgem_power
, /* devo_power */
976 usbgem_quiesce
, /* devo_quiesce */
981 static struct modldrv modldrv
= {
982 &mod_driverops
, /* Type of module. This one is a driver */
984 &udmf_ops
, /* driver ops */
987 static struct modlinkage modlinkage
= {
988 MODREV_1
, &modldrv
, NULL
991 /* ======================================================== */
995 /* ======================================================== */
1001 DPRINTF(2, (CE_CONT
, "!udmf: _init: called"));
1003 status
= usbgem_mod_init(&udmf_ops
, "udmf");
1004 if (status
!= DDI_SUCCESS
) {
1007 status
= mod_install(&modlinkage
);
1008 if (status
!= DDI_SUCCESS
) {
1009 usbgem_mod_fini(&udmf_ops
);
1022 DPRINTF(2, (CE_CONT
, "!udmf: _fini: called"));
1023 status
= mod_remove(&modlinkage
);
1024 if (status
== DDI_SUCCESS
) {
1025 usbgem_mod_fini(&udmf_ops
);
1031 _info(struct modinfo
*modinfop
)
1033 return (mod_info(&modlinkage
, modinfop
));