2 * urf_usbgem.c : Realtek RTL8150 USB to Fast Ethernet Driver for Solaris
4 * Copyright (c) 2003-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/usb/usba.h>
67 #include "usbgem_mii.h"
68 #include "rtl8150reg.h"
70 char ident
[] = "rtl8150 usbnic driver v" VERSION
;
75 #define ROUNDUP2(x, y) (((x)+(y)-1) & ~((y)-1))
76 #define CHECK_AND_JUMP(err, label) if (err != USB_SUCCESS) goto label
82 static int urf_debug
= DEBUG_LEVEL
;
83 #define DPRINTF(n, args) if (urf_debug > (n)) cmn_err args
85 #define DPRINTF(n, args)
89 * Our configration for rtl8150
92 #define ONESEC (drv_usectohz(1*1000000))
95 * Local device definitions
103 #define CHIPTABLESIZE (sizeof (chiptbl_8150) / sizeof (struct chip_info))
107 * Misc HW information
109 struct chip_info
*chip
;
121 static uint16_t urf_mii_read(struct usbgem_dev
*, uint_t
, int *errp
);
122 static void urf_mii_write(struct usbgem_dev
*, uint_t
, uint16_t, int *errp
);
125 static int urf_attach_chip(struct usbgem_dev
*);
126 static int urf_reset_chip(struct usbgem_dev
*);
127 static int urf_init_chip(struct usbgem_dev
*);
128 static int urf_start_chip(struct usbgem_dev
*);
129 static int urf_stop_chip(struct usbgem_dev
*);
130 static int urf_set_media(struct usbgem_dev
*);
131 static int urf_set_rx_filter(struct usbgem_dev
*);
132 static int urf_get_stats(struct usbgem_dev
*);
134 /* packet operations */
135 static mblk_t
*urf_tx_make_packet(struct usbgem_dev
*, mblk_t
*);
136 static mblk_t
*urf_rx_make_packet(struct usbgem_dev
*, mblk_t
*);
138 /* =============================================================== */
142 /* =============================================================== */
143 #define OUTB(dp, p, v, errp, label) \
144 if ((*(errp) = usbgem_ctrl_out_val((dp), \
145 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
146 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
147 /* bRequest */ USB_REQ_SET_ADDRESS, \
151 /* value */ (v))) != USB_SUCCESS) goto label
153 #define OUTW(dp, p, v, errp, label) \
154 if ((*(errp) = usbgem_ctrl_out_val((dp), \
155 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
156 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
157 /* bRequest */ USB_REQ_SET_ADDRESS, \
161 /* value */ (v))) != USB_SUCCESS) goto label
164 #define OUTS(dp, p, buf, len, errp, label) \
165 if ((*(errp) = usbgem_ctrl_out((dp), \
166 /* bmRequestType */ USB_DEV_REQ_HOST_TO_DEV \
167 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
168 /* bRequest */ USB_REQ_SET_ADDRESS, \
171 /* wLength */ (len), \
173 /* size */ (len))) != USB_SUCCESS) goto label
176 #define IN(dp, p, vp, errp, label) \
177 if ((*(errp) = usbgem_ctrl_in_val((dp), \
178 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
179 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
180 /* bRequest */ USB_REQ_SET_ADDRESS, \
183 /* wLength */ sizeof ((*vp)), \
184 /* valuep */ (vp))) != USB_SUCCESS) goto label
186 #define INS(dp, p, buf, len, errp, label) \
187 if ((*(errp) = usbgem_ctrl_in((dp), \
188 /* bmRequestType */ USB_DEV_REQ_DEV_TO_HOST \
189 | USB_DEV_REQ_TYPE_VENDOR | USB_DEV_REQ_RCPT_DEV, \
190 /* bRequest */ USB_REQ_SET_ADDRESS, \
193 /* wLength */ (len), \
194 /* valuep */ (buf), \
195 /* size */ (len))) != USB_SUCCESS) goto label
197 /* =============================================================== */
201 /* =============================================================== */
202 static int urf_ppa
= 0;
204 /* =============================================================== */
206 * Hardware manupilation
208 /* =============================================================== */
210 urf_reset_chip(struct usbgem_dev
*dp
)
215 struct urf_dev
*lp
= dp
->private;
217 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
220 OUTB(dp
, CR
, lp
->cr
| CR_SOFT_RST
, &err
, usberr
);
222 for (i
= 0; i
< 100; i
++) {
223 IN(dp
, CR
, ®
, &err
, usberr
);
224 if ((reg
& CR_SOFT_RST
) == 0) {
225 return (USB_SUCCESS
);
229 cmn_err(CE_WARN
, "%s: failed to reset: timeout", dp
->name
);
230 return (USB_FAILURE
);
233 cmn_err(CE_NOTE
, "!%s: %s: usberr detected", dp
->name
, __func__
);
234 return (USB_FAILURE
);
241 urf_init_chip(struct usbgem_dev
*dp
)
246 struct urf_dev
*lp
= dp
->private;
248 DPRINTF(0, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
250 /* ID registers: set later by urf_set_rx_filter */
252 /* Multicast registers: set later by urf_set_rx_filter */
254 /* Command register : Enable Tx and Rx before writing TCR and RCR */
255 lp
->cr
|= CR_RE
| CR_TE
;
256 OUTB(dp
, CR
, lp
->cr
, &err
, usberr
);
258 /* Transmit configration register : */
259 OUTB(dp
, TCR
, TCR_IFG_802_3
, &err
, usberr
);
261 /* Receive configuration register : disable rx filter */
262 lp
->rcr
= RCR_TAIL
| RCR_AER
| RCR_AR
;
263 OUTW(dp
, RCR
, lp
->rcr
, &err
, usberr
);
265 /* Media status register */
266 err
= urf_set_media(dp
);
267 CHECK_AND_JUMP(err
, usberr
);
269 /* Configuration register 0: no need to change */
271 DPRINTF(2, (CE_CONT
, "!%s: %s: end (success)", dp
->name
, __func__
));
272 return (USB_SUCCESS
);
275 cmn_err(CE_NOTE
, "!%s: %s: usberr detected", dp
->name
, __func__
);
276 return (USB_FAILURE
);
280 urf_start_chip(struct usbgem_dev
*dp
)
282 struct urf_dev
*lp
= dp
->private;
285 return (USB_SUCCESS
);
289 urf_stop_chip(struct usbgem_dev
*dp
)
291 return (urf_reset_chip(dp
));
295 urf_get_stats(struct usbgem_dev
*dp
)
298 return (USB_SUCCESS
);
302 urf_mcast_hash(struct usbgem_dev
*dp
, const uint8_t *addr
)
304 return (usbgem_ether_crc_be(addr
));
308 urf_set_rx_filter(struct usbgem_dev
*dp
)
315 struct urf_dev
*lp
= dp
->private;
317 DPRINTF(2, (CE_CONT
, "!%s: %s: called, rxmode:%x",
318 dp
->name
, __func__
, dp
->rxmode
));
320 if (lp
->rcr
& (RCR_AB
| RCR_AD
| RCR_AAM
| RCR_AAP
| RCR_AM
)) {
322 /* disable rx filter before changing it. */
323 lp
->rcr
&= ~(RCR_AB
| RCR_AD
| RCR_AAM
| RCR_AAP
| RCR_AM
);
324 OUTW(dp
, RCR
, lp
->rcr
, &err
, usberr
);
326 /* receive all packets while we change rx filter */
327 OUTW(dp
, RCR
, lp
->rcr
| RCR_AAM
| RCR_AAP
, &err
, usberr
);
331 mode
= RCR_AB
/* accept broadcast */
332 | RCR_AD
; /* accept physical match */
333 bzero(mhash
, sizeof (mhash
));
335 if (dp
->rxmode
& RXMODE_PROMISC
) {
336 /* promiscious mode implies all multicast and all physical */
337 mode
|= RCR_AAM
| RCR_AAP
;
338 } else if ((dp
->rxmode
& RXMODE_ALLMULTI
) || dp
->mc_count
> 64/2) {
339 /* accept all multicast packets */
341 } else if (dp
->mc_count
> 0) {
343 * make hash table to select interresting
344 * multicast address only.
347 for (i
= 0; i
< dp
->mc_count
; i
++) {
349 /* hash table is 64 = 2^6 bit width */
350 h
= dp
->mc_list
[i
].hash
>> (32 - 6);
351 mhash
[h
/ 8] |= 1 << (h
% 8);
356 /* set mac address */
357 OUTS(dp
, IDR
, dp
->cur_addr
.ether_addr_octet
, ETHERADDRL
, &err
, usberr
);
359 /* set multicast hash table */
361 /* need to set up multicast hash table */
362 OUTS(dp
, MAR
, mhash
, sizeof (mhash
), &err
, usberr
);
365 OUTW(dp
, RCR
, lp
->rcr
, &err
, usberr
);
368 IN(dp
, RCR
, &rcr
, &err
, usberr
);
369 cmn_err(CE_CONT
, "!%s: %s: rcr:%b returned",
370 dp
->name
, __func__
, rcr
, RCR_BITS
);
372 return (USB_SUCCESS
);
375 cmn_err(CE_NOTE
, "!%s: %s: usberr detected", dp
->name
, __func__
);
376 return (USB_FAILURE
);
380 urf_set_media(struct usbgem_dev
*dp
)
385 struct urf_dev
*lp
= dp
->private;
387 DPRINTF(2, (CE_CONT
, "!%s: %s: called", dp
->name
, __func__
));
389 /* select duplex: do nothing */
391 /* select speed: do nothing */
394 IN(dp
, MSR
, &old
, &err
, usberr
);
397 /* setup flow control */
398 new = old
& ~(MSR_TXFCE
| MSR_RXFCE
);
399 switch (dp
->flow_control
) {
400 case FLOW_CONTROL_SYMMETRIC
:
401 new |= MSR_TXFCE
| MSR_RXFCE
;
404 case FLOW_CONTROL_TX_PAUSE
:
408 case FLOW_CONTROL_RX_PAUSE
:
412 case FLOW_CONTROL_NONE
:
418 OUTB(dp
, MSR
, new, &err
, usberr
);
420 DPRINTF(2, (CE_CONT
, "!%s: %s: returned", dp
->name
, __func__
));
421 return (USB_SUCCESS
);
424 cmn_err(CE_NOTE
, "!%s: %s: usberr detected", dp
->name
, __func__
);
425 return (USB_FAILURE
);
429 * send/receive packet check
432 urf_tx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
442 if (len
< ETHERMIN
|| mp
->b_cont
!= NULL
|| (len
& 0x3f) == 0) {
446 len
= max(len
, ETHERMIN
);
448 if ((len
& 0x3f) == 0) {
449 /* workaround for buggy USB hba */
453 if ((new = allocb(len
, 0)) == NULL
) {
457 /* copy contents of the buffer */
458 new->b_wptr
= new->b_rptr
+ len
;
460 for (tp
= mp
; tp
; tp
= tp
->b_cont
) {
461 len
= (uintptr_t)tp
->b_wptr
- (uintptr_t)tp
->b_rptr
;
462 bcopy(tp
->b_rptr
, bp
, len
);
466 last_pos
= new->b_wptr
;
467 while (bp
< last_pos
) {
478 urf_dump_packet(struct usbgem_dev
*dp
, uint8_t *bp
, int n
)
482 for (i
= 0; i
< n
; i
+= 8, bp
+= 8) {
483 cmn_err(CE_CONT
, "%02x %02x %02x %02x %02x %02x %02x %02x",
484 bp
[0], bp
[1], bp
[2], bp
[3], bp
[4], bp
[5], bp
[6], bp
[7]);
489 urf_rx_make_packet(struct usbgem_dev
*dp
, mblk_t
*mp
)
498 DPRINTF(2, (CE_CONT
, "!%s: time:%d %s: len:%d cont:%p",
499 dp
->name
, ddi_get_lbolt(), __func__
, len
, mp
->b_cont
));
502 urf_dump_packet(dp
, mp
->b_rptr
, max(6, len
));
505 if (len
< ETHERMIN
+ ETHERFCSL
) {
512 /* get Rx header which is placed at tail of the packet. */
514 rxhd
= (p
[1] << 8) | p
[0];
515 len
= rxhd
& RXHD_BYTECNT
;
517 DPRINTF(2, (CE_CONT
, "!%s: %s: rsr:%b len:%d",
518 dp
->name
, __func__
, rxhd
, RXHD_BITS
, len
));
520 /* check if error happen */
521 if ((rxhd
& (RXHD_VALID
)) == 0) {
522 DPRINTF(-1, (CE_CONT
, "!%s: %s: rxhd:%b",
523 dp
->name
, __func__
, rxhd
, RXHD_BITS
));
524 if (rxhd
& RXHD_RUNT
) {
532 /* check packet size */
533 if (len
> ETHERMAX
+ ETHERFCSL
) {
535 dp
->stats
.frame_too_long
++;
538 } else if (len
< ETHERMIN
+ ETHERFCSL
) {
544 /* remove tailing crc field */
545 mp
->b_wptr
-= ETHERFCSL
;
553 urf_mii_read(struct usbgem_dev
*dp
, uint_t index
, int *errp
)
558 DPRINTF(4, (CE_CONT
, "!%s: %s: called, ix:%d",
559 dp
->name
, __func__
, index
));
580 case MII_AN_EXPANSION
:
588 IN(dp
, reg
, &val
, errp
, usberr
);
590 if (index
== MII_STATUS
) {
593 * Fix MII status register as it does't have LINKUP and
596 IN(dp
, MSR
, &msr
, errp
, usberr
);
598 val
|= (MII_STATUS_MFPRMBLSUPR
| MII_STATUS_LINKUP
);
599 if ((msr
& MSR_LINK
) == 0) {
600 val
&= ~MII_STATUS_LINKUP
;
608 "!%s: %s: usberr(%d) detected", dp
->name
, __func__
, *errp
);
614 urf_mii_write(struct usbgem_dev
*dp
, uint_t index
, uint16_t val
, int *errp
)
618 DPRINTF(5, (CE_CONT
, "!%s: %s called", dp
->name
, __func__
));
639 case MII_AN_EXPANSION
:
647 OUTW(dp
, reg
, val
, errp
, usberr
);
652 /* ======================================================== */
654 * OS depend (device driver DKI) routine
656 /* ======================================================== */
658 urf_eeprom_dump(struct usbgem_dev
*dp
, int size
)
662 uint16_t w0
, w1
, w2
, w3
;
664 cmn_err(CE_CONT
, "!%s: eeprom dump:", dp
->name
);
665 for (i
= URF_EEPROM_BASE
; i
< size
+ URF_EEPROM_BASE
; i
+= 8) {
666 IN(dp
, i
+ 0, &w0
, &err
, usberr
);
667 IN(dp
, i
+ 2, &w1
, &err
, usberr
);
668 IN(dp
, i
+ 4, &w2
, &err
, usberr
);
669 IN(dp
, i
+ 6, &w3
, &err
, usberr
);
670 cmn_err(CE_CONT
, "!0x%02x: 0x%04x 0x%04x 0x%04x 0x%04x",
671 i
- URF_EEPROM_BASE
, w0
, w1
, w2
, w3
);
678 urf_attach_chip(struct usbgem_dev
*dp
)
685 struct urf_dev
*lp
= dp
->private;
688 * setup flow control bit in eeprom
690 IN(dp
, URF_EEPROM_BASE
+ 9, &old
, &err
, usberr
);
692 DPRINTF(0, (CE_CONT
, "!%s: eeprom offset 9: %02x", dp
->name
, old
));
694 if (dp
->ugc
.usbgc_flow_control
!= FLOW_CONTROL_NONE
) {
695 /* enable PAUSE bit */
698 /* clear PAUSE bit */
702 /* make eeprom writable */
703 OUTB(dp
, CR
, lp
->cr
| CR_WEPROM
, &err
, usberr
);
705 /* eerom allows only word access for writing */
706 IN(dp
, URF_EEPROM_BASE
+ 8, ®
, &err
, usberr
);
707 new = (new << 8) | reg
;
709 OUTW(dp
, URF_EEPROM_BASE
+ 8, new, &err
, usberr
);
711 /* make eeprom non-writable */
712 OUTB(dp
, CR
, lp
->cr
, &err
, usberr
);
716 * load EEPROM contents into nic
718 OUTB(dp
, CR
, lp
->cr
| CR_AUTOLOAD
, &err
, usberr
);
719 CHECK_AND_JUMP(err
, usberr
);
721 for (i
= 0; i
< 100; i
++) {
722 IN(dp
, CR
, ®
, &err
, usberr
);
723 if ((reg
& CR_AUTOLOAD
) == 0) {
728 cmn_err(CE_WARN
, "%s: %s: failed to autoload: timeout",
734 * mac address in EEPROM has loaded to ID registers.
736 INS(dp
, IDR
, dp
->dev_addr
.ether_addr_octet
, ETHERADDRL
, &err
, usberr
);
738 /* no need to scan phy */
739 dp
->mii_phy_addr
= -1;
742 urf_eeprom_dump(dp
, 0x80);
746 dp
->misc_flag
= USBGEM_VLAN
;
748 return (USB_SUCCESS
);
751 cmn_err(CE_WARN
, "%s: urf_attach_chip: usb error detected", dp
->name
);
752 return (USB_FAILURE
);
756 urfattach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
759 ddi_iblock_cookie_t c
;
763 const char *drv_name
;
764 struct usbgem_dev
*dp
;
766 struct usbgem_conf
*ugcp
;
769 unit
= ddi_get_instance(dip
);
770 drv_name
= ddi_driver_name(dip
);
772 DPRINTF(3, (CE_CONT
, "!%s%d: %s: called, cmd:%d",
773 drv_name
, __func__
, unit
, cmd
));
775 if (cmd
== DDI_ATTACH
) {
777 * Check if the chip is supported.
781 * Check the chip if it is really realtek rtl8150
785 * construct usbgem configration
787 ugcp
= kmem_zalloc(sizeof (*ugcp
), KM_SLEEP
);
790 (void) sprintf(ugcp
->usbgc_name
,
791 "%s%d(ppa=%d)", drv_name
, unit
, urf_ppa
);
792 #ifdef USBGEM_CONFIG_GLDv3
793 ugcp
->usbgc_ppa
= urf_ppa
;
795 ugcp
->usbgc_ppa
= unit
;
797 ugcp
->usbgc_ifnum
= 0;
800 ugcp
->usbgc_tx_list_max
= 16;
802 /* the rx status partially replaces FCS */
803 ugcp
->usbgc_rx_header_len
= 0;
804 ugcp
->usbgc_rx_list_max
= 64;
806 /* time out parameters */
807 ugcp
->usbgc_tx_timeout
= USBGEM_TX_TIMEOUT
;
808 ugcp
->usbgc_tx_timeout_interval
= ONESEC
;
811 ugcp
->usbgc_flow_control
= FLOW_CONTROL_RX_PAUSE
;
813 /* MII timeout parameters */
814 ugcp
->usbgc_mii_link_watch_interval
= ONESEC
;
815 ugcp
->usbgc_mii_an_watch_interval
= ONESEC
/5;
816 ugcp
->usbgc_mii_reset_timeout
= MII_RESET_TIMEOUT
; /* 1 sec */
817 ugcp
->usbgc_mii_an_timeout
= MII_AN_TIMEOUT
; /* 5 sec */
818 ugcp
->usbgc_mii_an_wait
= (25*ONESEC
)/10;
819 ugcp
->usbgc_mii_linkdown_timeout
= MII_LINKDOWN_TIMEOUT
;
821 ugcp
->usbgc_mii_an_delay
= ONESEC
/10;
822 ugcp
->usbgc_mii_linkdown_action
= MII_ACTION_RSA
;
823 ugcp
->usbgc_mii_linkdown_timeout_action
= MII_ACTION_RESET
;
824 ugcp
->usbgc_mii_dont_reset
= B_FALSE
;
829 ugcp
->usbgc_attach_chip
= &urf_attach_chip
;
830 ugcp
->usbgc_reset_chip
= &urf_reset_chip
;
831 ugcp
->usbgc_init_chip
= &urf_init_chip
;
832 ugcp
->usbgc_start_chip
= &urf_start_chip
;
833 ugcp
->usbgc_stop_chip
= &urf_stop_chip
;
834 ugcp
->usbgc_multicast_hash
= &urf_mcast_hash
;
836 ugcp
->usbgc_set_rx_filter
= &urf_set_rx_filter
;
837 ugcp
->usbgc_set_media
= &urf_set_media
;
838 ugcp
->usbgc_get_stats
= &urf_get_stats
;
840 ugcp
->usbgc_interrupt
= &urf_interrupt
;
842 ugcp
->usbgc_interrupt
= NULL
;
844 /* packet operation */
845 ugcp
->usbgc_tx_make_packet
= &urf_tx_make_packet
;
846 ugcp
->usbgc_rx_make_packet
= &urf_rx_make_packet
;
849 ugcp
->usbgc_mii_probe
= &usbgem_mii_probe_default
;
850 ugcp
->usbgc_mii_init
= &usbgem_mii_init_default
;
851 ugcp
->usbgc_mii_config
= &usbgem_mii_config_default
;
852 ugcp
->usbgc_mii_read
= &urf_mii_read
;
853 ugcp
->usbgc_mii_write
= &urf_mii_write
;
856 ugcp
->usbgc_min_mtu
= ETHERMTU
;
857 ugcp
->usbgc_max_mtu
= ETHERMTU
;
858 ugcp
->usbgc_default_mtu
= ETHERMTU
;
860 lp
= kmem_zalloc(sizeof (struct urf_dev
), KM_SLEEP
);
863 ddi_set_driver_private(dip
, NULL
);
865 dp
= usbgem_do_attach(dip
, ugcp
, lp
, sizeof (struct urf_dev
));
867 kmem_free(ugcp
, sizeof (*ugcp
));
871 return (DDI_SUCCESS
);
875 kmem_free(lp
, sizeof (struct urf_dev
));
878 return (DDI_FAILURE
);
880 if (cmd
== DDI_RESUME
) {
881 return (usbgem_resume(dip
));
883 return (DDI_FAILURE
);
887 urfdetach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
891 if (cmd
== DDI_DETACH
) {
892 ret
= usbgem_do_detach(dip
);
893 if (ret
!= DDI_SUCCESS
) {
894 return (DDI_FAILURE
);
897 return (DDI_SUCCESS
);
899 if (cmd
== DDI_SUSPEND
) {
900 return (usbgem_suspend(dip
));
902 return (DDI_FAILURE
);
905 /* ======================================================== */
907 * OS depend (loadable streams driver) routine
909 /* ======================================================== */
910 #ifdef USBGEM_CONFIG_GLDv3
911 USBGEM_STREAM_OPS(urf_ops
, urfattach
, urfdetach
);
913 static struct module_info urfminfo
= {
915 "urf", /* mi_idname */
917 ETHERMTU
, /* mi_maxpsz */
918 ETHERMTU
*128, /* mi_hiwat */
922 static struct qinit urfrinit
= {
923 (int (*)()) NULL
, /* qi_putp */
924 usbgem_rsrv
, /* qi_srvp */
925 usbgem_open
, /* qi_qopen */
926 usbgem_close
, /* qi_qclose */
927 (int (*)()) NULL
, /* qi_qadmin */
928 &urfminfo
, /* qi_minfo */
932 static struct qinit urfwinit
= {
933 usbgem_wput
, /* qi_putp */
934 usbgem_wsrv
, /* qi_srvp */
935 (int (*)()) NULL
, /* qi_qopen */
936 (int (*)()) NULL
, /* qi_qclose */
937 (int (*)()) NULL
, /* qi_qadmin */
938 &urfminfo
, /* qi_minfo */
942 static struct streamtab urf_info
= {
943 &urfrinit
, /* st_rdinit */
944 &urfwinit
, /* st_wrinit */
945 NULL
, /* st_muxrinit */
946 NULL
/* st_muxwrinit */
949 static struct cb_ops cb_urf_ops
= {
950 nulldev
, /* cb_open */
951 nulldev
, /* cb_close */
952 nodev
, /* cb_strategy */
953 nodev
, /* cb_print */
956 nodev
, /* cb_write */
957 nodev
, /* cb_ioctl */
958 nodev
, /* cb_devmap */
960 nodev
, /* cb_segmap */
961 nochpoll
, /* cb_chpoll */
962 ddi_prop_op
, /* cb_prop_op */
963 &urf_info
, /* cb_stream */
964 D_NEW
|D_MP
/* cb_flag */
967 static struct dev_ops urf_ops
= {
968 DEVO_REV
, /* devo_rev */
970 usbgem_getinfo
, /* devo_getinfo */
971 nulldev
, /* devo_identify */
972 nulldev
, /* devo_probe */
973 urfattach
, /* devo_attach */
974 urfdetach
, /* devo_detach */
975 nodev
, /* devo_reset */
976 &cb_urf_ops
, /* devo_cb_ops */
977 NULL
, /* devo_bus_ops */
978 usbgem_power
, /* devo_power */
980 usbgem_quiesce
, /* devo_quiesce */
986 static struct modldrv modldrv
= {
987 &mod_driverops
, /* Type of module. This one is a driver */
989 &urf_ops
, /* driver ops */
992 static struct modlinkage modlinkage
= {
993 MODREV_1
, &modldrv
, NULL
996 /* ======================================================== */
1000 /* ======================================================== */
1006 DPRINTF(2, (CE_CONT
, "!urf: _init: called"));
1008 status
= usbgem_mod_init(&urf_ops
, "urf");
1009 if (status
!= DDI_SUCCESS
) {
1012 status
= mod_install(&modlinkage
);
1013 if (status
!= DDI_SUCCESS
) {
1014 usbgem_mod_fini(&urf_ops
);
1027 DPRINTF(2, (CE_CONT
, "!urf: _fini: called"));
1028 status
= mod_remove(&modlinkage
);
1029 if (status
== DDI_SUCCESS
) {
1030 usbgem_mod_fini(&urf_ops
);
1036 _info(struct modinfo
*modinfop
)
1038 return (mod_info(&modlinkage
, modinfop
));