1*8bc54e5bSmsaitoh /* $NetBSD: if_ex_cardbus.c,v 1.56 2016/07/07 06:55:41 msaitoh Exp $ */
24eee1111Shaya
34eee1111Shaya /*
44eee1111Shaya * Copyright (c) 1998 and 1999
54eee1111Shaya * HAYAKAWA Koichi. All rights reserved.
64eee1111Shaya *
74eee1111Shaya * Redistribution and use in source and binary forms, with or without
84eee1111Shaya * modification, are permitted provided that the following conditions
94eee1111Shaya * are met:
104eee1111Shaya * 1. Redistributions of source code must retain the above copyright
114eee1111Shaya * notice, this list of conditions and the following disclaimer.
124eee1111Shaya * 2. Redistributions in binary form must reproduce the above copyright
134eee1111Shaya * notice, this list of conditions and the following disclaimer in the
144eee1111Shaya * documentation and/or other materials provided with the distribution.
154eee1111Shaya *
164eee1111Shaya * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
174eee1111Shaya * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184eee1111Shaya * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194eee1111Shaya * ARE DISCLAIMED. IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
204eee1111Shaya * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
214eee1111Shaya * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
224eee1111Shaya * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234eee1111Shaya * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
244eee1111Shaya * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
254eee1111Shaya * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
264eee1111Shaya * SUCH DAMAGE.
27be360188Ssnj */
28be360188Ssnj
29be360188Ssnj /*
30be360188Ssnj * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
314eee1111Shaya */
324eee1111Shaya
33f61cbe74Slukem #include <sys/cdefs.h>
34*8bc54e5bSmsaitoh __KERNEL_RCSID(0, "$NetBSD: if_ex_cardbus.c,v 1.56 2016/07/07 06:55:41 msaitoh Exp $");
35f61cbe74Slukem
361bc6d2ceSwiz /* #define EX_DEBUG 4 */ /* define to report information for debugging */
374eee1111Shaya
384eee1111Shaya #include <sys/param.h>
394eee1111Shaya #include <sys/systm.h>
404eee1111Shaya #include <sys/mbuf.h>
414eee1111Shaya #include <sys/socket.h>
424eee1111Shaya #include <sys/ioctl.h>
43ce254079Sthorpej #include <sys/errno.h>
44ce254079Sthorpej #include <sys/syslog.h>
454eee1111Shaya #include <sys/select.h>
46ce254079Sthorpej #include <sys/device.h>
474eee1111Shaya
484eee1111Shaya #include <net/if.h>
494eee1111Shaya #include <net/if_dl.h>
504eee1111Shaya #include <net/if_ether.h>
51ce254079Sthorpej #include <net/if_media.h>
524eee1111Shaya
53a2a38285Sad #include <sys/cpu.h>
54a2a38285Sad #include <sys/bus.h>
5591b09f5bShaya
564eee1111Shaya #include <dev/cardbus/cardbusvar.h>
57eed3298aSmycroft #include <dev/pci/pcidevs.h>
584eee1111Shaya
594eee1111Shaya #include <dev/mii/miivar.h>
604eee1111Shaya
614eee1111Shaya #include <dev/ic/elink3var.h>
624eee1111Shaya #include <dev/ic/elink3reg.h>
634eee1111Shaya #include <dev/ic/elinkxlreg.h>
644eee1111Shaya #include <dev/ic/elinkxlvar.h>
654eee1111Shaya
664eee1111Shaya #if defined DEBUG && !defined EX_DEBUG
674eee1111Shaya #define EX_DEBUG
684eee1111Shaya #endif
694eee1111Shaya
704eee1111Shaya #if defined EX_DEBUG
714eee1111Shaya #define DPRINTF(a) printf a
724eee1111Shaya #else
734eee1111Shaya #define DPRINTF(a)
744eee1111Shaya #endif
754eee1111Shaya
76508883c1Sdyoung #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG PCI_BAR2 /* means 0x18 */
774eee1111Shaya #define EX_CB_INTR 4 /* intr acknowledge reg. CardBus only */
784eee1111Shaya #define EX_CB_INTR_ACK 0x8000 /* intr acknowledge bit */
794eee1111Shaya
80123ed98aSspz int ex_cardbus_match(device_t, cfdata_t, void *);
81123ed98aSspz void ex_cardbus_attach(device_t, device_t, void *);
82123ed98aSspz int ex_cardbus_detach(device_t, int);
8318db93c7Sperry void ex_cardbus_intr_ack(struct ex_softc *);
844eee1111Shaya
8518db93c7Sperry int ex_cardbus_enable(struct ex_softc *);
8618db93c7Sperry void ex_cardbus_disable(struct ex_softc *);
874eee1111Shaya
884eee1111Shaya struct ex_cardbus_softc {
894eee1111Shaya struct ex_softc sc_softc;
904eee1111Shaya
914eee1111Shaya cardbus_devfunc_t sc_ct;
921b5ffa90Scegger uint8_t sc_cardbus_flags;
934eee1111Shaya #define EX_REATTACH 0x01
944eee1111Shaya #define EX_ABSENT 0x02
951b5ffa90Scegger uint8_t sc_cardtype;
9641711571Shaya #define EX_CB_BOOMERANG 1
9741711571Shaya #define EX_CB_CYCLONE 2
984eee1111Shaya
994eee1111Shaya /* CardBus function status space. 575B requests it. */
1004eee1111Shaya bus_space_tag_t sc_funct;
1014eee1111Shaya bus_space_handle_t sc_funch;
102494c9affSaugustss bus_size_t sc_funcsize;
103494c9affSaugustss
104494c9affSaugustss bus_size_t sc_mapsize; /* the size of mapped bus space region */
1059710d432Sthorpej
1068089c2dcSdyoung pcitag_t sc_tag;
1079710d432Sthorpej
10851d6f75dSdyoung pcireg_t sc_csr;
1099710d432Sthorpej int sc_bar_reg; /* which BAR to use */
1109710d432Sthorpej pcireg_t sc_bar_val; /* value of the BAR */
1119710d432Sthorpej int sc_bar_reg1; /* which BAR to use */
1129710d432Sthorpej pcireg_t sc_bar_val1; /* value of the BAR */
1139710d432Sthorpej
1144eee1111Shaya };
1154eee1111Shaya
116fa492e58Sdyoung CFATTACH_DECL3_NEW(ex_cardbus, sizeof(struct ex_cardbus_softc),
117fa492e58Sdyoung ex_cardbus_match, ex_cardbus_attach, ex_cardbus_detach, ex_activate,
118fa492e58Sdyoung NULL, NULL, DVF_DETACH_SHUTDOWN);
1194eee1111Shaya
120ce254079Sthorpej const struct ex_cardbus_product {
1211b5ffa90Scegger uint32_t ecp_prodid; /* CardBus product ID */
122ce254079Sthorpej int ecp_flags; /* initial softc flags */
123ce254079Sthorpej pcireg_t ecp_csr; /* PCI CSR flags */
124ce254079Sthorpej int ecp_cardtype; /* card type */
125ce254079Sthorpej const char *ecp_name; /* device name */
126ce254079Sthorpej } ex_cardbus_products[] = {
127eed3298aSmycroft { PCI_PRODUCT_3COM_3C575TX,
128d9e2aff0Sfvdl EX_CONF_MII | EX_CONF_EEPROM_OFF | EX_CONF_EEPROM_8BIT,
129508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MASTER_ENABLE,
13041711571Shaya EX_CB_BOOMERANG,
131ce254079Sthorpej "3c575-TX Ethernet" },
1324eee1111Shaya
133eed3298aSmycroft { PCI_PRODUCT_3COM_3C575BTX,
134d9e2aff0Sfvdl EX_CONF_90XB|EX_CONF_MII|EX_CONF_INV_LED_POLARITY |
135d9e2aff0Sfvdl EX_CONF_EEPROM_OFF | EX_CONF_EEPROM_8BIT,
136508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
137508883c1Sdyoung PCI_COMMAND_MASTER_ENABLE,
13841711571Shaya EX_CB_CYCLONE,
139ce254079Sthorpej "3c575B-TX Ethernet" },
1404eee1111Shaya
141eed3298aSmycroft { PCI_PRODUCT_3COM_3C575CTX,
142d9e2aff0Sfvdl EX_CONF_90XB | EX_CONF_PHY_POWER | EX_CONF_EEPROM_OFF |
143d9e2aff0Sfvdl EX_CONF_EEPROM_8BIT,
144508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
145508883c1Sdyoung PCI_COMMAND_MASTER_ENABLE,
14641711571Shaya EX_CB_CYCLONE,
14725147761Shaya "3c575CT Ethernet" },
14825147761Shaya
149eed3298aSmycroft { PCI_PRODUCT_3COM_3C656_E,
150bb1bff39Smycroft EX_CONF_90XB | EX_CONF_PHY_POWER | EX_CONF_EEPROM_OFF |
151bb76bd93Smycroft EX_CONF_EEPROM_8BIT | EX_CONF_INV_LED_POLARITY,
152508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
153508883c1Sdyoung PCI_COMMAND_MASTER_ENABLE,
154bb1bff39Smycroft EX_CB_CYCLONE,
155bb1bff39Smycroft "3c656-TX Ethernet" },
156bb1bff39Smycroft
157eed3298aSmycroft { PCI_PRODUCT_3COM_3C656B_E,
158bb1bff39Smycroft EX_CONF_90XB | EX_CONF_PHY_POWER | EX_CONF_EEPROM_OFF |
159bb76bd93Smycroft EX_CONF_EEPROM_8BIT | EX_CONF_INV_LED_POLARITY,
160508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
161508883c1Sdyoung PCI_COMMAND_MASTER_ENABLE,
162bb1bff39Smycroft EX_CB_CYCLONE,
163bb1bff39Smycroft "3c656B-TX Ethernet" },
164bb1bff39Smycroft
165eed3298aSmycroft { PCI_PRODUCT_3COM_3C656C_E,
166bb1bff39Smycroft EX_CONF_90XB | EX_CONF_PHY_POWER | EX_CONF_EEPROM_OFF |
167bb1bff39Smycroft EX_CONF_EEPROM_8BIT,
168508883c1Sdyoung PCI_COMMAND_IO_ENABLE | PCI_COMMAND_MEM_ENABLE |
169508883c1Sdyoung PCI_COMMAND_MASTER_ENABLE,
170bb1bff39Smycroft EX_CB_CYCLONE,
171bb1bff39Smycroft "3c656C-TX Ethernet" },
172bb1bff39Smycroft
173ce254079Sthorpej { 0,
174ce254079Sthorpej 0,
175ce254079Sthorpej 0,
1761cff94b8Sthorpej 0,
177ce254079Sthorpej NULL },
178ce254079Sthorpej };
179ce254079Sthorpej
1809710d432Sthorpej
18118db93c7Sperry void ex_cardbus_setup(struct ex_cardbus_softc *);
1829710d432Sthorpej
183ce254079Sthorpej const struct ex_cardbus_product *ex_cardbus_lookup
18418db93c7Sperry (const struct cardbus_attach_args *);
185ce254079Sthorpej
186ce254079Sthorpej const struct ex_cardbus_product *
ex_cardbus_lookup(const struct cardbus_attach_args * ca)1871b5ffa90Scegger ex_cardbus_lookup(const struct cardbus_attach_args *ca)
188ce254079Sthorpej {
189ce254079Sthorpej const struct ex_cardbus_product *ecp;
190ce254079Sthorpej
191508883c1Sdyoung if (PCI_VENDOR(ca->ca_id) != PCI_VENDOR_3COM)
192ce254079Sthorpej return (NULL);
193ce254079Sthorpej
194ce254079Sthorpej for (ecp = ex_cardbus_products; ecp->ecp_name != NULL; ecp++)
195508883c1Sdyoung if (PCI_PRODUCT(ca->ca_id) == ecp->ecp_prodid)
196ce254079Sthorpej return (ecp);
197ce254079Sthorpej return (NULL);
198ce254079Sthorpej }
199ce254079Sthorpej
200ce254079Sthorpej int
ex_cardbus_match(device_t parent,cfdata_t cf,void * aux)201123ed98aSspz ex_cardbus_match(device_t parent, cfdata_t cf, void *aux)
2024eee1111Shaya {
2034eee1111Shaya struct cardbus_attach_args *ca = aux;
2044eee1111Shaya
205ce254079Sthorpej if (ex_cardbus_lookup(ca) != NULL)
206ce254079Sthorpej return (1);
207ce254079Sthorpej
208ce254079Sthorpej return (0);
2094eee1111Shaya }
2104eee1111Shaya
211ce254079Sthorpej void
ex_cardbus_attach(device_t parent,device_t self,void * aux)212123ed98aSspz ex_cardbus_attach(device_t parent, device_t self, void *aux)
2134eee1111Shaya {
2140bb04182Sthorpej struct ex_cardbus_softc *csc = device_private(self);
2156502a2efShaya struct ex_softc *sc = &csc->sc_softc;
2164eee1111Shaya struct cardbus_attach_args *ca = aux;
2174eee1111Shaya cardbus_devfunc_t ct = ca->ca_ct;
218ce254079Sthorpej const struct ex_cardbus_product *ecp;
2199710d432Sthorpej bus_addr_t adr, adr1;
2204eee1111Shaya
221123ed98aSspz sc->sc_dev = self;
222123ed98aSspz
2239710d432Sthorpej sc->sc_dmat = ca->ca_dmat;
2249710d432Sthorpej csc->sc_ct = ca->ca_ct;
2259710d432Sthorpej csc->sc_tag = ca->ca_tag;
226ce254079Sthorpej
227ce254079Sthorpej ecp = ex_cardbus_lookup(ca);
228ce254079Sthorpej if (ecp == NULL) {
229ce254079Sthorpej printf("\n");
230ce254079Sthorpej panic("ex_cardbus_attach: impossible");
231ce254079Sthorpej }
232ce254079Sthorpej
233123ed98aSspz aprint_normal(": 3Com %s\n", ecp->ecp_name);
234ce254079Sthorpej
235ce254079Sthorpej sc->ex_conf = ecp->ecp_flags;
2369710d432Sthorpej csc->sc_cardtype = ecp->ecp_cardtype;
2379710d432Sthorpej csc->sc_csr = ecp->ecp_csr;
238ce254079Sthorpej
239508883c1Sdyoung if (Cardbus_mapreg_map(ct, PCI_BAR0, PCI_MAPREG_TYPE_IO, 0,
2409710d432Sthorpej &sc->sc_iot, &sc->sc_ioh, &adr, &csc->sc_mapsize) == 0) {
241508883c1Sdyoung csc->sc_bar_reg = PCI_BAR0;
242508883c1Sdyoung csc->sc_bar_val = adr | PCI_MAPREG_TYPE_IO;
2434eee1111Shaya
2446502a2efShaya if (csc->sc_cardtype == EX_CB_CYCLONE) {
245ce254079Sthorpej /* Map CardBus function status window. */
2469710d432Sthorpej if (Cardbus_mapreg_map(ct,
2479710d432Sthorpej CARDBUS_3C575BTX_FUNCSTAT_PCIREG,
248508883c1Sdyoung PCI_MAPREG_TYPE_MEM, 0,
2499710d432Sthorpej &csc->sc_funct, &csc->sc_funch,
2509710d432Sthorpej &adr1, &csc->sc_funcsize) == 0) {
2519710d432Sthorpej
2529710d432Sthorpej csc->sc_bar_reg1 =
2539710d432Sthorpej CARDBUS_3C575BTX_FUNCSTAT_PCIREG;
2549710d432Sthorpej csc->sc_bar_val1 =
255508883c1Sdyoung adr1 | PCI_MAPREG_TYPE_MEM;
2569710d432Sthorpej
2579710d432Sthorpej } else {
258*8bc54e5bSmsaitoh aprint_error_dev(self,
259*8bc54e5bSmsaitoh "unable to map function status window\n");
260ce254079Sthorpej return;
2614eee1111Shaya }
2624eee1111Shaya
2634eee1111Shaya /* Setup interrupt acknowledge hook */
2644eee1111Shaya sc->intr_ack = ex_cardbus_intr_ack;
2654eee1111Shaya }
266*8bc54e5bSmsaitoh } else {
267123ed98aSspz aprint_naive(": can't map i/o space\n");
2684eee1111Shaya return;
2694eee1111Shaya }
2709710d432Sthorpej
2719710d432Sthorpej /* Power management hooks. */
2729710d432Sthorpej sc->enable = ex_cardbus_enable;
2739710d432Sthorpej sc->disable = ex_cardbus_disable;
2749710d432Sthorpej
2759710d432Sthorpej /*
2769710d432Sthorpej * Handle power management nonsense and
27703941a12Skanaoka * initialize the configuration registers.
2789710d432Sthorpej */
2799710d432Sthorpej ex_cardbus_setup(csc);
2804eee1111Shaya
281ce254079Sthorpej ex_config(sc);
2824eee1111Shaya
2836502a2efShaya if (csc->sc_cardtype == EX_CB_CYCLONE)
2846502a2efShaya bus_space_write_4(csc->sc_funct, csc->sc_funch,
285ce254079Sthorpej EX_CB_INTR, EX_CB_INTR_ACK);
2864eee1111Shaya
2879710d432Sthorpej Cardbus_function_disable(csc->sc_ct);
2884eee1111Shaya }
2894eee1111Shaya
290ce254079Sthorpej void
ex_cardbus_intr_ack(struct ex_softc * sc)2911b5ffa90Scegger ex_cardbus_intr_ack(struct ex_softc *sc)
2924eee1111Shaya {
2936502a2efShaya struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
294ce254079Sthorpej
2956502a2efShaya bus_space_write_4(csc->sc_funct, csc->sc_funch, EX_CB_INTR,
296ce254079Sthorpej EX_CB_INTR_ACK);
2974eee1111Shaya }
2984eee1111Shaya
299ce254079Sthorpej int
ex_cardbus_detach(device_t self,int flags)300f4de9422Sdyoung ex_cardbus_detach(device_t self, int flags)
3014eee1111Shaya {
3020bb04182Sthorpej struct ex_cardbus_softc *csc = device_private(self);
3036502a2efShaya struct ex_softc *sc = &csc->sc_softc;
3046502a2efShaya struct cardbus_devfunc *ct = csc->sc_ct;
305494c9affSaugustss int rv;
3064eee1111Shaya
307494c9affSaugustss #if defined(DIAGNOSTIC)
308494c9affSaugustss if (ct == NULL) {
309123ed98aSspz panic("%s: data structure lacks", device_xname(self));
310494c9affSaugustss }
311494c9affSaugustss #endif
312494c9affSaugustss
313f4de9422Sdyoung if ((rv = ex_detach(sc)) != 0)
314f4de9422Sdyoung return rv;
315f4de9422Sdyoung
3164eee1111Shaya /*
317494c9affSaugustss * Unhook the interrupt handler.
3184eee1111Shaya */
3194b936f66Sdyoung Cardbus_intr_disestablish(ct, sc->sc_ih);
3204eee1111Shaya
3216502a2efShaya if (csc->sc_cardtype == EX_CB_CYCLONE) {
32208483fcdSthorpej Cardbus_mapreg_unmap(ct,
32308483fcdSthorpej CARDBUS_3C575BTX_FUNCSTAT_PCIREG,
3246502a2efShaya csc->sc_funct, csc->sc_funch, csc->sc_funcsize);
325494c9affSaugustss }
326653eefc8Shaya
327508883c1Sdyoung Cardbus_mapreg_unmap(ct, PCI_BAR0, sc->sc_iot,
3286502a2efShaya sc->sc_ioh, csc->sc_mapsize);
329f4de9422Sdyoung return 0;
3304eee1111Shaya }
3314eee1111Shaya
332ce254079Sthorpej int
ex_cardbus_enable(struct ex_softc * sc)3331b5ffa90Scegger ex_cardbus_enable(struct ex_softc *sc)
3344eee1111Shaya {
3354eee1111Shaya struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
3364eee1111Shaya
33788f1d44cShaya Cardbus_function_enable(csc->sc_ct);
3389710d432Sthorpej ex_cardbus_setup(csc);
3394eee1111Shaya
3401ca3ef38Sdrochner sc->sc_ih = Cardbus_intr_establish(csc->sc_ct, IPL_NET, ex_intr, sc);
3414eee1111Shaya if (NULL == sc->sc_ih) {
342123ed98aSspz aprint_error_dev(sc->sc_dev, "couldn't establish interrupt\n");
343ce254079Sthorpej return (1);
3444eee1111Shaya }
3454eee1111Shaya
346ce254079Sthorpej return (0);
3474eee1111Shaya }
3484eee1111Shaya
349ce254079Sthorpej void
ex_cardbus_disable(struct ex_softc * sc)3501b5ffa90Scegger ex_cardbus_disable(struct ex_softc *sc)
3514eee1111Shaya {
3524eee1111Shaya struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
3534eee1111Shaya
354f4de9422Sdyoung if (sc->sc_ih != NULL) {
355f4de9422Sdyoung Cardbus_intr_disestablish(csc->sc_ct, sc->sc_ih);
3569710d432Sthorpej sc->sc_ih = NULL;
357f4de9422Sdyoung }
3584eee1111Shaya
35988f1d44cShaya Cardbus_function_disable(csc->sc_ct);
3604eee1111Shaya
3614eee1111Shaya }
3629710d432Sthorpej
3639710d432Sthorpej void
ex_cardbus_setup(struct ex_cardbus_softc * csc)3641b5ffa90Scegger ex_cardbus_setup(struct ex_cardbus_softc *csc)
3659710d432Sthorpej {
3669710d432Sthorpej cardbus_devfunc_t ct = csc->sc_ct;
3678089c2dcSdyoung pcireg_t reg;
3689710d432Sthorpej
3694c1d81b2Sjmcneill (void)cardbus_set_powerstate(ct, csc->sc_tag, PCI_PWR_D0);
3709710d432Sthorpej
371ba82a9e7Smycroft /* Program the BAR */
372508883c1Sdyoung Cardbus_conf_write(ct, csc->sc_tag, csc->sc_bar_reg, csc->sc_bar_val);
3739710d432Sthorpej /* Make sure the right access type is on the CardBus bridge. */
3749710d432Sthorpej if (csc->sc_cardtype == EX_CB_CYCLONE) {
375ba82a9e7Smycroft /* Program the BAR */
376508883c1Sdyoung Cardbus_conf_write(ct, csc->sc_tag,
377ba82a9e7Smycroft csc->sc_bar_reg1, csc->sc_bar_val1);
3789710d432Sthorpej /*
3799710d432Sthorpej * Make sure CardBus brigde can access memory space. Usually
3809710d432Sthorpej * memory access is enabled by BIOS, but some BIOSes do not
3819710d432Sthorpej * enable it.
3829710d432Sthorpej */
3839710d432Sthorpej }
3849710d432Sthorpej
3859710d432Sthorpej /* Enable the appropriate bits in the CARDBUS CSR. */
386508883c1Sdyoung reg = Cardbus_conf_read(ct, csc->sc_tag, PCI_COMMAND_STATUS_REG);
3879710d432Sthorpej reg |= csc->sc_csr;
388508883c1Sdyoung Cardbus_conf_write(ct, csc->sc_tag, PCI_COMMAND_STATUS_REG, reg);
3899710d432Sthorpej
3909710d432Sthorpej /*
391c0177219Swiz * set latency timer
3929710d432Sthorpej */
393508883c1Sdyoung reg = Cardbus_conf_read(ct, csc->sc_tag, PCI_BHLC_REG);
394508883c1Sdyoung if (PCI_LATTIMER(reg) < 0x20) {
3959710d432Sthorpej /* at least the value of latency timer should 0x20. */
3969710d432Sthorpej DPRINTF(("if_ex_cardbus: lattimer 0x%x -> 0x20\n",
397508883c1Sdyoung PCI_LATTIMER(reg)));
398508883c1Sdyoung reg &= ~(PCI_LATTIMER_MASK << PCI_LATTIMER_SHIFT);
399508883c1Sdyoung reg |= (0x20 << PCI_LATTIMER_SHIFT);
400508883c1Sdyoung Cardbus_conf_write(ct, csc->sc_tag, PCI_BHLC_REG, reg);
4019710d432Sthorpej }
4029710d432Sthorpej }
403