blob: fbc7cf1f1e47552fb83e466dd57a4b306133028f [file] [log] [blame]
<
stevel3db86aa2006-06-29 14:43:12 -07001/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21
22/*
rw14856111c2b4c2008-07-21 16:51:53 -070023 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
stevel3db86aa2006-06-29 14:43:12 -070024 * Use is subject to license terms.
Daniel Hoffman48bbca82017-02-17 11:48:20 -080025 * Copyright (c) 2016 by Delphix. All rights reserved.
stevel3db86aa2006-06-29 14:43:12 -070026 */
27
stevel3db86aa2006-06-29 14:43:12 -070028/*
29 * PCIC device/interrupt handler
30 * The "pcic" driver handles the Intel 82365SL, Cirrus Logic
31 * and Toshiba (and possibly other clones) PCMCIA adapter chip
32 * sets. It implements a subset of Socket Services as defined
33 * in the Solaris PCMCIA design documents
34 */
35
36/*
37 * currently defined "properties"
38 *
39 * clock-frequency bus clock frequency
40 * smi system management interrupt override
41 * need-mult-irq need status IRQ for each pair of sockets
42 * disable-audio don't route audio signal to speaker
43 */
44
45
46#include <sys/types.h>
47#include <sys/inttypes.h>
48#include <sys/param.h>
49#include <sys/systm.h>
50#include <sys/user.h>
51#include <sys/buf.h>
52#include <sys/file.h>
53#include <sys/uio.h>
54#include <sys/conf.h>
55#include <sys/stat.h>
56#include <sys/autoconf.h>
57#include <sys/vtoc.h>
58#include <sys/dkio.h>
59#include <sys/ddi.h>
60#include <sys/sunddi.h>
61#include <sys/sunndi.h>
62#include <sys/var.h>
63#include <sys/callb.h>
64#include <sys/open.h>
65#include <sys/ddidmareq.h>
66#include <sys/dma_engine.h>
67#include <sys/kstat.h>
68#include <sys/kmem.h>
69#include <sys/modctl.h>
70#include <sys/pci.h>
71#include <sys/pci_impl.h>
72
73#include <sys/pctypes.h>
74#include <sys/pcmcia.h>
75#include <sys/sservice.h>
76
77#include <sys/note.h>
78
79#include <sys/pcic_reg.h>
80#include <sys/pcic_var.h>
81
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +080082#if defined(__i386) || defined(__amd64)
83#include <sys/pci_cfgspace.h>
84#endif
85
stevel3db86aa2006-06-29 14:43:12 -070086#if defined(__sparc)
87#include <sys/pci/pci_nexus.h>
88#endif
89
rw1485610d282d12006-07-27 03:07:55 -070090#include <sys/hotplug/hpcsvc.h>
stevel3db86aa2006-06-29 14:43:12 -070091#include "cardbus/cardbus.h"
92
93#define SOFTC_SIZE (sizeof (anp_t))
94
95static int pcic_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
96static int pcic_attach(dev_info_t *, ddi_attach_cmd_t);
97static int pcic_detach(dev_info_t *, ddi_detach_cmd_t);
Quaker Fang56441432008-11-13 09:48:41 +080098static int32_t pcic_quiesce(dev_info_t *);
stevel3db86aa2006-06-29 14:43:12 -070099static uint_t pcic_intr(caddr_t, caddr_t);
100static int pcic_do_io_intr(pcicdev_t *, uint32_t);
101static int pcic_probe(dev_info_t *);
102
103static int pcic_open(dev_t *, int, int, cred_t *);
104static int pcic_close(dev_t, int, int, cred_t *);
105static int pcic_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
106
107typedef struct pcm_regs pcm_regs_t;
108
109static void pcic_init_assigned(dev_info_t *);
110static int pcic_apply_avail_ranges(dev_info_t *, pcm_regs_t *,
111 pci_regspec_t *, int);
112int pci_resource_setup_avail(dev_info_t *, pci_regspec_t *, int);
113
114/*
115 * On x86 platforms the ddi_iobp_alloc(9F) and ddi_mem_alloc(9F) calls
116 * are xlated into DMA ctlops. To make this nexus work on x86, we
117 * need to have the default ddi_dma_mctl ctlops in the bus_ops
118 * structure, just to pass the request to the parent. The correct
119 * ctlops should be ddi_no_dma_mctl because so far we don't do DMA.
120 */
121static
122struct bus_ops pcmciabus_ops = {
123 BUSO_REV,
124 pcmcia_bus_map,
125 NULL,
126 NULL,
127 NULL,
128 i_ddi_map_fault,
129 ddi_no_dma_map,
130 ddi_no_dma_allochdl,
131 ddi_no_dma_freehdl,
132 ddi_no_dma_bindhdl,
133 ddi_no_dma_unbindhdl,
134 ddi_no_dma_flush,
135 ddi_no_dma_win,
136 ddi_dma_mctl,
137 pcmcia_ctlops,
138 pcmcia_prop_op,
139 NULL, /* (*bus_get_eventcookie)(); */
140 NULL, /* (*bus_add_eventcall)(); */
141 NULL, /* (*bus_remove_eventcall)(); */
142 NULL, /* (*bus_post_event)(); */
143 NULL, /* (*bus_intr_ctl)(); */
144 NULL, /* (*bus_config)(); */
145 NULL, /* (*bus_unconfig)(); */
146 NULL, /* (*bus_fm_init)(); */
147 NULL, /* (*bus_fm_fini)(); */
148 NULL, /* (*bus_enter)() */
149 NULL, /* (*bus_exit)() */
150 NULL, /* (*bus_power)() */
151 pcmcia_intr_ops /* (*bus_intr_op)(); */
152};
153
154static struct cb_ops pcic_cbops = {
155 pcic_open,
156 pcic_close,
157 nodev,
158 nodev,
159 nodev,
160 nodev,
161 nodev,
162 pcic_ioctl,
163 nodev,
164 nodev,
165 nodev,
166 nochpoll,
167 ddi_prop_op,
168 NULL,
169#ifdef CARDBUS
170 D_NEW | D_MP | D_HOTPLUG
171#else
172 D_NEW | D_MP
173#endif
174};
175
176static struct dev_ops pcic_devops = {
177 DEVO_REV,
178 0,
179 pcic_getinfo,
180 nulldev,
181 pcic_probe,
182 pcic_attach,
183 pcic_detach,
184 nulldev,
185 &pcic_cbops,
186 &pcmciabus_ops,
Sherry Moore19397402008-09-22 16:30:26 -0700187 NULL,
Quaker Fang56441432008-11-13 09:48:41 +0800188 pcic_quiesce, /* devo_quiesce */
stevel3db86aa2006-06-29 14:43:12 -0700189};
190
191void *pcic_soft_state_p = NULL;
192static int pcic_maxinst = -1;
stevel3db86aa2006-06-29 14:43:12 -0700193
194int pcic_do_insertion = 1;
195int pcic_do_removal = 1;
196
197struct irqmap {
198 int irq;
199 int count;
200} pcic_irq_map[16];
201
202
203int pcic_debug = 0x0;
204static void pcic_err(dev_info_t *dip, int level, const char *fmt, ...);
205extern void cardbus_dump_pci_config(dev_info_t *dip);
206extern void cardbus_dump_socket(dev_info_t *dip);
207extern int cardbus_validate_iline(dev_info_t *dip, ddi_acc_handle_t handle);
208static void pcic_dump_debqueue(char *msg);
209
210#if defined(PCIC_DEBUG)
211static void xxdmp_all_regs(pcicdev_t *, int, uint32_t);
212
213#define pcic_mutex_enter(a) \
214 { \
215 pcic_err(NULL, 10, "Set lock at %d\n", __LINE__); \
216 mutex_enter(a); \
217 };
218
219#define pcic_mutex_exit(a) \
220 { \
221 pcic_err(NULL, 10, "Clear lock at %d\n", __LINE__); \
222 mutex_exit(a); \
223 };
224
225#else
226#define pcic_mutex_enter(a) mutex_enter(a)
227#define pcic_mutex_exit(a) mutex_exit(a)
228#endif
229
230#define PCIC_VCC_3VLEVEL 1
231#define PCIC_VCC_5VLEVEL 2
232#define PCIC_VCC_12LEVEL 3
233
234/* bit patterns to select voltage levels */
235int pcic_vpp_levels[13] = {
236 0, 0, 0,
237 1, /* 3.3V */
238 0,
239 1, /* 5V */
240 0, 0, 0, 0, 0, 0,
241 2 /* 12V */
242};
243
244uint8_t pcic_cbv_levels[13] = {
245 0, 0, 0,
246 3, /* 3.3V */
247 0,
248 2, /* 5V */
249 0, 0, 0, 0, 0, 0,
250 1 /* 12V */
251};
252
253struct power_entry pcic_power[4] = {
254 {
255 0, VCC|VPP1|VPP2
256 },
257 {
258 33, /* 3.3Volt */
259 VCC|VPP1|VPP2
260 },
261 {
262 5*10, /* 5Volt */
263 VCC|VPP1|VPP2 /* currently only know about this */
264 },
265 {
266 12*10, /* 12Volt */
267 VPP1|VPP2
268 }
269};
270
271/*
272 * Base used to allocate ranges of PCI memory on x86 systems
273 * Each instance gets a chunk above the base that is used to map
274 * in the memory and I/O windows for that device.
275 * Pages below the base are also allocated for the EXCA registers,
276 * one per instance.
277 */
278#define PCIC_PCI_MEMCHUNK 0x1000000
279
280static int pcic_wait_insert_time = 5000000; /* In micro-seconds */
281static int pcic_debounce_time = 200000; /* In micro-seconds */
282
283struct debounce {
284 pcic_socket_t *pcs;
285 clock_t expire;
286 struct debounce *next;
287};
288
stevel3db86aa2006-06-29 14:43:12 -0700289static struct debounce *pcic_deb_queue = NULL;
290static kmutex_t pcic_deb_mtx;
291static kcondvar_t pcic_deb_cv;
292static kthread_t *pcic_deb_threadid;
293
294static inthandler_t *pcic_handlers;
295
296static void pcic_setup_adapter(pcicdev_t *);
297static int pcic_change(pcicdev_t *, int);
298static int pcic_ll_reset(pcicdev_t *, int);
299static void pcic_mswait(pcicdev_t *, int, int);
300static boolean_t pcic_check_ready(pcicdev_t *, int);
301static void pcic_set_cdtimers(pcicdev_t *, int, uint32_t, int);
302static void pcic_ready_wait(pcicdev_t *, int);
303extern int pcmcia_get_intr(dev_info_t *, int);
304extern int pcmcia_return_intr(dev_info_t *, int);
rw14856111c2b4c2008-07-21 16:51:53 -0700305extern void pcmcia_cb_suspended(int);
306extern void pcmcia_cb_resumed(int);
stevel3db86aa2006-06-29 14:43:12 -0700307
308static int pcic_callback(dev_info_t *, int (*)(), int);
309static int pcic_inquire_adapter(dev_info_t *, inquire_adapter_t *);
310static int pcic_get_adapter(dev_info_t *, get_adapter_t *);
311static int pcic_get_page(dev_info_t *, get_page_t *);
312static int pcic_get_socket(dev_info_t *, get_socket_t *);
313static int pcic_get_status(dev_info_t *, get_ss_status_t *);
314static int pcic_get_window(dev_info_t *, get_window_t *);
315static int pcic_inquire_socket(dev_info_t *, inquire_socket_t *);
316static int pcic_inquire_window(dev_info_t *, inquire_window_t *);
317static int pcic_reset_socket(dev_info_t *, int, int);
318static int pcic_set_page(dev_info_t *, set_page_t *);
319static int pcic_set_window(dev_info_t *, set_window_t *);
320static int pcic_set_socket(dev_info_t *, set_socket_t *);
321static int pcic_set_interrupt(dev_info_t *, set_irq_handler_t *);
322static int pcic_clear_interrupt(dev_info_t *, clear_irq_handler_t *);
323static void pcic_pm_detection(void *);
324static void pcic_iomem_pci_ctl(ddi_acc_handle_t, uchar_t *, unsigned);
325static int clext_reg_read(pcicdev_t *, int, uchar_t);
326static void clext_reg_write(pcicdev_t *, int, uchar_t, uchar_t);
327static int pcic_calc_speed(pcicdev_t *, uint32_t);
328static int pcic_card_state(pcicdev_t *, pcic_socket_t *);
329static int pcic_find_pci_type(pcicdev_t *);
330static void pcic_82092_smiirq_ctl(pcicdev_t *, int, int, int);
331static void pcic_handle_cd_change(pcicdev_t *, pcic_socket_t *, uint8_t);
332static uint_t pcic_cd_softint(caddr_t, caddr_t);
333static uint8_t pcic_getb(pcicdev_t *, int, int);
334static void pcic_putb(pcicdev_t *, int, int, int8_t);
335static int pcic_set_vcc_level(pcicdev_t *, set_socket_t *);
336static uint_t pcic_softintr(caddr_t, caddr_t);
337
338static void pcic_debounce(pcic_socket_t *);
rw14856111c2b4c2008-07-21 16:51:53 -0700339static void pcic_do_resume(pcicdev_t *);
stevel3db86aa2006-06-29 14:43:12 -0700340static void *pcic_add_debqueue(pcic_socket_t *, int);
341static void pcic_rm_debqueue(void *);
342static void pcic_deb_thread();
343
344static boolean_t pcic_load_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp);
345static void pcic_unload_cardbus(pcicdev_t *pcic, const pcic_socket_t *sockp);
346static uint32_t pcic_getcb(pcicdev_t *pcic, int reg);
347static void pcic_putcb(pcicdev_t *pcic, int reg, uint32_t value);
348static void pcic_cb_enable_intr(dev_info_t *);
349static void pcic_cb_disable_intr(dev_info_t *);
350static void pcic_enable_io_intr(pcicdev_t *pcic, int socket, int irq);
351static void pcic_disable_io_intr(pcicdev_t *pcic, int socket);
352
353static cb_nexus_cb_t pcic_cbnexus_ops = {
354 pcic_cb_enable_intr,
355 pcic_cb_disable_intr
356};
357
358static int pcic_exca_powerctl(pcicdev_t *pcic, int socket, int powerlevel);
359static int pcic_cbus_powerctl(pcicdev_t *pcic, int socket);
360
stevel3db86aa2006-06-29 14:43:12 -0700361#if defined(__sparc)
362static int pcic_fault(enum pci_fault_ops op, void *arg);
363#endif
364
stevel3db86aa2006-06-29 14:43:12 -0700365
366/*
367 * pcmcia interface operations structure
368 * this is the private interface that is exported to the nexus
369 */
370pcmcia_if_t pcic_if_ops = {
371 PCIF_MAGIC,
372 PCIF_VERSION,
373 pcic_callback,
374 pcic_get_adapter,
375 pcic_get_page,
376 pcic_get_socket,
377 pcic_get_status,
378 pcic_get_window,
379 pcic_inquire_adapter,
380 pcic_inquire_socket,
381 pcic_inquire_window,
382 pcic_reset_socket,
383 pcic_set_page,
384 pcic_set_window,
385 pcic_set_socket,
386 pcic_set_interrupt,
387 pcic_clear_interrupt,
388 NULL,
389};
390
391/*
392 * chip type identification routines
393 * this list of functions is searched until one of them succeeds
394 * or all fail. i82365SL is assumed if failed.
395 */
396static int pcic_ci_cirrus(pcicdev_t *);
397static int pcic_ci_vadem(pcicdev_t *);
398static int pcic_ci_ricoh(pcicdev_t *);
399
400int (*pcic_ci_funcs[])(pcicdev_t *) = {
401 pcic_ci_cirrus,
402 pcic_ci_vadem,
403 pcic_ci_ricoh,
404 NULL
405};
406
407static struct modldrv modldrv = {
408 &mod_driverops, /* Type of module. This one is a driver */
rh87107903a11e2008-07-31 15:02:18 -0700409 "PCIC PCMCIA adapter driver", /* Name of the module. */
stevel3db86aa2006-06-29 14:43:12 -0700410 &pcic_devops, /* driver ops */
411};
412
413static struct modlinkage modlinkage = {
414 MODREV_1, (void *)&modldrv, NULL
415};
416
417int
418_init()
419{
420 int stat;
421
422 /* Allocate soft state */
423 if ((stat = ddi_soft_state_init(&pcic_soft_state_p,
424 SOFTC_SIZE, 2)) != DDI_SUCCESS)
425 return (stat);
426
427 if ((stat = mod_install(&modlinkage)) != 0)
428 ddi_soft_state_fini(&pcic_soft_state_p);
429
430 return (stat);
431}
432
433int
434_fini()
435{
436 int stat = 0;
437
438 if ((stat = mod_remove(&modlinkage)) != 0)
439 return (stat);
440
441 if (pcic_deb_threadid) {
442 mutex_enter(&pcic_deb_mtx);
443 pcic_deb_threadid = 0;
444 while (!pcic_deb_threadid)
445 cv_wait(&pcic_deb_cv, &pcic_deb_mtx);
446 pcic_deb_threadid = 0;
447 mutex_exit(&pcic_deb_mtx);
448
449 mutex_destroy(&pcic_deb_mtx);
450 cv_destroy(&pcic_deb_cv);
451 }
452
453 ddi_soft_state_fini(&pcic_soft_state_p);
454
455 return (stat);
456}
457
458int
459_info(struct modinfo *modinfop)
460{
461 return (mod_info(&modlinkage, modinfop));
462}
463
464/*
465 * pcic_getinfo()
466 * provide instance/device information about driver
467 */
468/*ARGSUSED*/
469static int
470pcic_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **result)
471{
472 anp_t *anp;
473 int error = DDI_SUCCESS;
474 minor_t minor;
475
476 switch (cmd) {
Sherry Moore19397402008-09-22 16:30:26 -0700477 case DDI_INFO_DEVT2DEVINFO:
stevel3db86aa2006-06-29 14:43:12 -0700478 minor = getminor((dev_t)arg);
gd78059459fbba2007-04-06 08:29:38 -0700479 minor &= 0x7f;
stevel3db86aa2006-06-29 14:43:12 -0700480 if (!(anp = ddi_get_soft_state(pcic_soft_state_p, minor)))
481 *result = NULL;
482 else
483 *result = anp->an_dip;
484 break;
Sherry Moore19397402008-09-22 16:30:26 -0700485 case DDI_INFO_DEVT2INSTANCE:
stevel3db86aa2006-06-29 14:43:12 -0700486 minor = getminor((dev_t)arg);
gd78059459fbba2007-04-06 08:29:38 -0700487 minor &= 0x7f;
stevel3db86aa2006-06-29 14:43:12 -0700488 *result = (void *)((long)minor);
489 break;
Sherry Moore19397402008-09-22 16:30:26 -0700490 default:
stevel3db86aa2006-06-29 14:43:12 -0700491 error = DDI_FAILURE;
492 break;
493 }
494 return (error);
495}
496
497static int
498pcic_probe(dev_info_t *dip)
499{
500 int value;
501 ddi_device_acc_attr_t attr;
502 ddi_acc_handle_t handle;
503 uchar_t *index, *data;
504
505 if (ddi_dev_is_sid(dip) == DDI_SUCCESS)
Sherry Moore19397402008-09-22 16:30:26 -0700506 return (DDI_PROBE_DONTCARE);
stevel3db86aa2006-06-29 14:43:12 -0700507
508 /*
509 * find a PCIC device (any vendor)
510 * while there can be up to 4 such devices in
511 * a system, we currently only look for 1
512 * per probe. There will be up to 2 chips per
513 * instance since they share I/O space
514 */
515 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
516 attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
517 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
518
519 if (ddi_regs_map_setup(dip, PCIC_ISA_CONTROL_REG_NUM,
Sherry Moore19397402008-09-22 16:30:26 -0700520 (caddr_t *)&index,
521 PCIC_ISA_CONTROL_REG_OFFSET,
522 PCIC_ISA_CONTROL_REG_LENGTH,
523 &attr, &handle) != DDI_SUCCESS)
524 return (DDI_PROBE_FAILURE);
stevel3db86aa2006-06-29 14:43:12 -0700525
526 data = index + 1;
527
528#if defined(PCIC_DEBUG)
529 if (pcic_debug)
530 cmn_err(CE_CONT, "pcic_probe: entered\n");
531 if (pcic_debug)
532 cmn_err(CE_CONT, "\tindex=%p\n", (void *)index);
533#endif
534 ddi_put8(handle, index, PCIC_CHIP_REVISION);
535 ddi_put8(handle, data, 0);
536 value = ddi_get8(handle, data);
537#if defined(PCIC_DEBUG)
538 if (pcic_debug)
539 cmn_err(CE_CONT, "\tchip revision register = %x\n", value);
540#endif
541 if ((value & PCIC_REV_MASK) >= PCIC_REV_LEVEL_LOW &&
542 (value & 0x30) == 0) {
543 /*
544 * we probably have a PCIC chip in the system
545 * do a little more checking. If we find one,
546 * reset everything in case of softboot
547 */
548 ddi_put8(handle, index, PCIC_MAPPING_ENABLE);
549 ddi_put8(handle, data, 0);
550 value = ddi_get8(handle, data);
551#if defined(PCIC_DEBUG)
552 if (pcic_debug)
553 cmn_err(CE_CONT, "\tzero test = %x\n", value);
554#endif
555 /* should read back as zero */
556 if (value == 0) {
557 /*
558 * we do have one and it is off the bus
559 */
560#if defined(PCIC_DEBUG)
561 if (pcic_debug)
562 cmn_err(CE_CONT, "pcic_probe: success\n");
563#endif
564 ddi_regs_map_free(&handle);
565 return (DDI_PROBE_SUCCESS);
566 }
567 }
568#if defined(PCIC_DEBUG)
569 if (pcic_debug)
570 cmn_err(CE_CONT, "pcic_probe: failed\n");
571#endif
572 ddi_regs_map_free(&handle);
573 return (DDI_PROBE_FAILURE);
574}
575
576/*
577 * These are just defaults they can also be changed via a property in the
578 * conf file.
579 */
580static int pci_config_reg_num = PCIC_PCI_CONFIG_REG_NUM;
581static int pci_control_reg_num = PCIC_PCI_CONTROL_REG_NUM;
rw14856111c2b4c2008-07-21 16:51:53 -0700582static int pcic_do_pcmcia_sr = 1;
stevel3db86aa2006-06-29 14:43:12 -0700583static int pcic_use_cbpwrctl = PCF_CBPWRCTL;
584
585/*
586 * enable insertion/removal interrupt for 32bit cards
587 */
588static int
589cardbus_enable_cd_intr(dev_info_t *dip)
590{
591 ddi_acc_handle_t iohandle;
592 caddr_t ioaddr;
593 ddi_device_acc_attr_t attr;
594 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
595 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
596 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
597 (void) ddi_regs_map_setup(dip, 1,
Sherry Moore19397402008-09-22 16:30:26 -0700598 (caddr_t *)&ioaddr,
599 0,
600 4096,
601 &attr, &iohandle);
stevel3db86aa2006-06-29 14:43:12 -0700602
603 /* CSC Interrupt: Card detect interrupt on */
604 ddi_put32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_MASK),
Sherry Moore19397402008-09-22 16:30:26 -0700605 ddi_get32(iohandle,
606 (uint32_t *)(ioaddr+CB_STATUS_MASK)) | CB_SE_CCDMASK);
stevel3db86aa2006-06-29 14:43:12 -0700607
608 ddi_put32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_EVENT),
Sherry Moore19397402008-09-22 16:30:26 -0700609 ddi_get32(iohandle, (uint32_t *)(ioaddr+CB_STATUS_EVENT)));
stevel3db86aa2006-06-29 14:43:12 -0700610
611 ddi_regs_map_free(&iohandle);
612 return (1);
613}
614
615/*
Quaker Fang56441432008-11-13 09:48:41 +0800616 * quiesce(9E) entry point.
617 *
618 * This function is called when the system is single-threaded at high
619 * PIL with preemption disabled. Therefore, this function must not be
620 * blocked.
621 *
622 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
623 * DDI_FAILURE indicates an error condition and should almost never happen.
624 */
625static int32_t
626pcic_quiesce(dev_info_t *dip)
627{
628 anp_t *anp = ddi_get_driver_private(dip);
629 pcicdev_t *pcic = anp->an_private;
630 int i;
631
632 for (i = 0; i < pcic->pc_numsockets; i++) {
633 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT, 0);
634 pcic_putb(pcic, i, PCIC_CARD_DETECT, 0);
635 pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
636 /* disable interrupts and put card into RESET */
637 pcic_putb(pcic, i, PCIC_INTERRUPT, 0);
638 /* poweroff socket */
639 pcic_putb(pcic, i, PCIC_POWER_CONTROL, 0);
640 pcic_putcb(pcic, CB_CONTROL, 0);
641 }
642
643 return (DDI_SUCCESS);
644}
645
646/*
stevel3db86aa2006-06-29 14:43:12 -0700647 * pcic_attach()
648 * attach the PCIC (Intel 82365SL/CirrusLogic/Toshiba) driver
649 * to the system. This is a child of "sysbus" since that is where
650 * the hardware lives, but it provides services to the "pcmcia"
651 * nexus driver. It gives a pointer back via its private data
652 * structure which contains both the dip and socket services entry
653 * points
654 */
655static int
656pcic_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
657{
658 anp_t *pcic_nexus;
659 pcicdev_t *pcic;
660 int irqlevel, value;
661 int pci_cfrn, pci_ctrn;
662 int i, j, smi, actual;
663 char *typename;
664 char bus_type[16] = "(unknown)";
665 int len = sizeof (bus_type);
666 ddi_device_acc_attr_t attr;
667 anp_t *anp = ddi_get_driver_private(dip);
668 uint_t pri;
stevel3db86aa2006-06-29 14:43:12 -0700669
670#if defined(PCIC_DEBUG)
671 if (pcic_debug) {
672 cmn_err(CE_CONT, "pcic_attach: entered\n");
673 }
674#endif
675 switch (cmd) {
676 case DDI_ATTACH:
677 break;
678 case DDI_RESUME:
679 pcic = anp->an_private;
680 /*
681 * for now, this is a simulated resume.
682 * a real one may need different things.
683 */
684 if (pcic != NULL && pcic->pc_flags & PCF_SUSPENDED) {
685 mutex_enter(&pcic->pc_lock);
686 /* should probe for new sockets showing up */
687 pcic_setup_adapter(pcic);
stevel3db86aa2006-06-29 14:43:12 -0700688 pcic->pc_flags &= ~PCF_SUSPENDED;
689 mutex_exit(&pcic->pc_lock);
690 (void) pcmcia_begin_resume(dip);
rw14856111c2b4c2008-07-21 16:51:53 -0700691
692 pcic_do_resume(pcic);
693#ifdef CARDBUS
694 cardbus_restore_children(ddi_get_child(dip));
695#endif
stevel3db86aa2006-06-29 14:43:12 -0700696
697 /*
698 * for complete implementation need END_RESUME (later)
699 */
700 return (DDI_SUCCESS);
701
702 }
703 return (DDI_SUCCESS);
704 default:
705 return (DDI_FAILURE);
706 }
707
708 /*
709 * Allocate soft state associated with this instance.
710 */
711 if (ddi_soft_state_zalloc(pcic_soft_state_p,
Sherry Moore19397402008-09-22 16:30:26 -0700712 ddi_get_instance(dip)) != DDI_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -0700713 cmn_err(CE_CONT, "pcic%d: Unable to alloc state\n",
Sherry Moore19397402008-09-22 16:30:26 -0700714 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700715 return (DDI_FAILURE);
716 }
717
718 pcic_nexus = ddi_get_soft_state(pcic_soft_state_p,
719 ddi_get_instance(dip));
720
721 pcic = kmem_zalloc(sizeof (pcicdev_t), KM_SLEEP);
722
723 pcic->dip = dip;
724 pcic_nexus->an_dip = dip;
725 pcic_nexus->an_if = &pcic_if_ops;
726 pcic_nexus->an_private = pcic;
727 pcic->pc_numpower = sizeof (pcic_power)/sizeof (pcic_power[0]);
728 pcic->pc_power = pcic_power;
729
730 pci_ctrn = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
731 "pci-control-reg-number", pci_control_reg_num);
732 pci_cfrn = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
733 "pci-config-reg-number", pci_config_reg_num);
734
735 ddi_set_driver_private(dip, pcic_nexus);
736
737 /*
738 * pcic->pc_irq is really the IPL level we want to run at
739 * set the default values here and override from intr spec
740 */
741 pcic->pc_irq = ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
Sherry Moore19397402008-09-22 16:30:26 -0700742 "interrupt-priorities", -1);
stevel3db86aa2006-06-29 14:43:12 -0700743
744 if (pcic->pc_irq == -1) {
745 int actual;
746 uint_t pri;
747 ddi_intr_handle_t hdl;
748
749 /* see if intrspec tells us different */
750 if (ddi_intr_alloc(dip, &hdl, DDI_INTR_TYPE_FIXED,
751 0, 1, &actual, DDI_INTR_ALLOC_NORMAL) == DDI_SUCCESS) {
752 if (ddi_intr_get_pri(hdl, &pri) == DDI_SUCCESS)
753 pcic->pc_irq = pri;
754 else
755 pcic->pc_irq = LOCK_LEVEL + 1;
756 (void) ddi_intr_free(hdl);
757 }
758 }
759 pcic_nexus->an_ipl = pcic->pc_irq;
760
761 /*
762 * Check our parent bus type. We do different things based on which
763 * bus we're on.
764 */
765 if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
Sherry Moore19397402008-09-22 16:30:26 -0700766 PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP,
767 "device_type", (caddr_t)&bus_type[0], &len) !=
768 DDI_PROP_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -0700769 if (ddi_prop_op(DDI_DEV_T_ANY, ddi_get_parent(dip),
Sherry Moore19397402008-09-22 16:30:26 -0700770 PROP_LEN_AND_VAL_BUF, DDI_PROP_CANSLEEP,
771 "bus-type", (caddr_t)&bus_type[0], &len) !=
772 DDI_PROP_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -0700773
774 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -0700775 "pcic%d: can't find parent bus type\n",
776 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700777
778 kmem_free(pcic, sizeof (pcicdev_t));
rw148561b8a60a52007-03-20 22:22:30 -0700779 ddi_soft_state_free(pcic_soft_state_p,
Sherry Moore19397402008-09-22 16:30:26 -0700780 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700781 return (DDI_FAILURE);
782 }
783 } /* ddi_prop_op("device_type") */
784
rw1485618134ee02007-02-16 00:52:01 -0800785 if (strcmp(bus_type, DEVI_PCI_NEXNAME) == 0 ||
Sherry Moore19397402008-09-22 16:30:26 -0700786 strcmp(bus_type, DEVI_PCIEX_NEXNAME) == 0) {
stevel3db86aa2006-06-29 14:43:12 -0700787 pcic->pc_flags = PCF_PCIBUS;
788 } else {
rw148561b8a60a52007-03-20 22:22:30 -0700789 cmn_err(CE_WARN, "!pcic%d: non-pci mode (%s) not supported, "
Sherry Moore19397402008-09-22 16:30:26 -0700790 "set BIOS to yenta mode if applicable\n",
791 ddi_get_instance(dip), bus_type);
stevel3db86aa2006-06-29 14:43:12 -0700792 kmem_free(pcic, sizeof (pcicdev_t));
rw148561b8a60a52007-03-20 22:22:30 -0700793 ddi_soft_state_free(pcic_soft_state_p,
Sherry Moore19397402008-09-22 16:30:26 -0700794 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700795 return (DDI_FAILURE);
stevel3db86aa2006-06-29 14:43:12 -0700796 }
797
798 if ((pcic->bus_speed = ddi_getprop(DDI_DEV_T_ANY, ddi_get_parent(dip),
Sherry Moore19397402008-09-22 16:30:26 -0700799 DDI_PROP_CANSLEEP,
800 "clock-frequency", 0)) == 0) {
stevel3db86aa2006-06-29 14:43:12 -0700801 if (pcic->pc_flags & PCF_PCIBUS)
802 pcic->bus_speed = PCIC_PCI_DEF_SYSCLK;
803 else
804 pcic->bus_speed = PCIC_ISA_DEF_SYSCLK;
805 } else {
806 /*
807 * OBP can declare the speed in Hz...
808 */
809 if (pcic->bus_speed > 1000000)
810 pcic->bus_speed /= 1000000;
811 } /* ddi_prop_op("clock-frequency") */
812
813 pcic->pc_io_type = PCIC_IO_TYPE_82365SL; /* default mode */
814
815#ifdef PCIC_DEBUG
816 if (pcic_debug) {
817 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -0700818 "pcic%d: parent bus type = [%s], speed = %d MHz\n",
819 ddi_get_instance(dip),
820 bus_type, pcic->bus_speed);
stevel3db86aa2006-06-29 14:43:12 -0700821 }
822#endif
823
824 /*
825 * The reg properties on a PCI node are different than those
826 * on a non-PCI node. Handle that difference here.
827 * If it turns out to be a CardBus chip, we have even more
828 * differences.
829 */
830 if (pcic->pc_flags & PCF_PCIBUS) {
831 int class_code;
832#if defined(__i386) || defined(__amd64)
833 pcic->pc_base = 0x1000000;
834 pcic->pc_bound = (uint32_t)~0;
835 pcic->pc_iobase = 0x1000;
836 pcic->pc_iobound = 0xefff;
837#elif defined(__sparc)
838 pcic->pc_base = 0x0;
839 pcic->pc_bound = (uint32_t)~0;
840 pcic->pc_iobase = 0x00000;
841 pcic->pc_iobound = 0xffff;
842#endif
843
844 /* usually need to get at config space so map first */
845 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
846 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
847 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
848
849 if (ddi_regs_map_setup(dip, pci_cfrn,
Sherry Moore19397402008-09-22 16:30:26 -0700850 (caddr_t *)&pcic->cfgaddr,
851 PCIC_PCI_CONFIG_REG_OFFSET,
852 PCIC_PCI_CONFIG_REG_LENGTH,
853 &attr,
854 &pcic->cfg_handle) !=
stevel3db86aa2006-06-29 14:43:12 -0700855 DDI_SUCCESS) {
856 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -0700857 "pcic%d: unable to map config space"
858 "regs\n",
859 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700860
861 kmem_free(pcic, sizeof (pcicdev_t));
862 return (DDI_FAILURE);
863 } /* ddi_regs_map_setup */
864
865 class_code = ddi_getprop(DDI_DEV_T_ANY, dip,
Sherry Moore19397402008-09-22 16:30:26 -0700866 DDI_PROP_CANSLEEP|DDI_PROP_DONTPASS,
867 "class-code", -1);
stevel3db86aa2006-06-29 14:43:12 -0700868#ifdef PCIC_DEBUG
869 if (pcic_debug) {
870 cmn_err(CE_CONT, "pcic_attach class_code=%x\n",
871 class_code);
872 }
873#endif
874
875 switch (class_code) {
876 case PCIC_PCI_CARDBUS:
877 pcic->pc_flags |= PCF_CARDBUS;
878 pcic->pc_io_type = PCIC_IO_TYPE_YENTA;
879 /*
880 * Get access to the adapter registers on the
881 * PCI bus. A 4K memory page
882 */
883#if defined(PCIC_DEBUG)
884 pcic_err(dip, 8, "Is Cardbus device\n");
885 if (pcic_debug) {
886 int nr;
887 long rs;
888 (void) ddi_dev_nregs(dip, &nr);
889 pcic_err(dip, 9, "\tdev, cfgaddr 0x%p,"
890 "cfghndl 0x%p nregs %d",
891 (void *)pcic->cfgaddr,
892 (void *)pcic->cfg_handle, nr);
893
894 (void) ddi_dev_regsize(dip,
895 PCIC_PCI_CONTROL_REG_NUM, &rs);
896
897 pcic_err(dip, 9, "\tsize of reg %d is 0x%x\n",
898 PCIC_PCI_CONTROL_REG_NUM, (int)rs);
899 }
900#endif
901 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
902 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
903 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
904
905 if (ddi_regs_map_setup(dip, pci_ctrn,
Sherry Moore19397402008-09-22 16:30:26 -0700906 (caddr_t *)&pcic->ioaddr,
907 PCIC_PCI_CONTROL_REG_OFFSET,
908 PCIC_CB_CONTROL_REG_LENGTH,
909 &attr, &pcic->handle) !=
stevel3db86aa2006-06-29 14:43:12 -0700910 DDI_SUCCESS) {
911 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -0700912 "pcic%d: unable to map PCI regs\n",
913 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700914 ddi_regs_map_free(&pcic->cfg_handle);
915 kmem_free(pcic, sizeof (pcicdev_t));
916 return (DDI_FAILURE);
917 } /* ddi_regs_map_setup */
918
919 /*
920 * Find out the chip type - If we're on a PCI bus,
921 * the adapter has that information in the PCI
922 * config space.
923 * Note that we call pcic_find_pci_type here since
924 * it needs a valid mapped pcic->handle to
925 * access some of the adapter registers in
926 * some cases.
927 */
928 if (pcic_find_pci_type(pcic) != DDI_SUCCESS) {
929 ddi_regs_map_free(&pcic->handle);
930 ddi_regs_map_free(&pcic->cfg_handle);
931 kmem_free(pcic, sizeof (pcicdev_t));
932 cmn_err(CE_WARN, "pcic: %s: unsupported "
Sherry Moore19397402008-09-22 16:30:26 -0700933 "bridge\n", ddi_get_name_addr(dip));
stevel3db86aa2006-06-29 14:43:12 -0700934 return (DDI_FAILURE);
935 }
936 break;
937
938 default:
939 case PCIC_PCI_PCMCIA:
940 /*
941 * Get access to the adapter IO registers on the
942 * PCI bus config space.
943 */
944 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
945 attr.devacc_attr_endian_flags = DDI_STRUCTURE_LE_ACC;
946 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
947
948 /*
949 * We need a default mapping to the adapter's IO
950 * control register space. For most adapters
951 * that are of class PCIC_PCI_PCMCIA (or of
952 * a default class) the control registers
953 * will be using the 82365-type control/data
954 * format.
955 */
956 if (ddi_regs_map_setup(dip, pci_ctrn,
Sherry Moore19397402008-09-22 16:30:26 -0700957 (caddr_t *)&pcic->ioaddr,
958 PCIC_PCI_CONTROL_REG_OFFSET,
959 PCIC_PCI_CONTROL_REG_LENGTH,
960 &attr,
961 &pcic->handle) != DDI_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -0700962 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -0700963 "pcic%d: unable to map PCI regs\n",
964 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -0700965 ddi_regs_map_free(&pcic->cfg_handle);
966 kmem_free(pcic, sizeof (pcicdev_t));
967 return (DDI_FAILURE);
968 } /* ddi_regs_map_setup */
969
970 /*
971 * Find out the chip type - If we're on a PCI bus,
972 * the adapter has that information in the PCI
973 * config space.
974 * Note that we call pcic_find_pci_type here since
975 * it needs a valid mapped pcic->handle to
976 * access some of the adapter registers in
977 * some cases.
978 */
979 if (pcic_find_pci_type(pcic) != DDI_SUCCESS) {
980 ddi_regs_map_free(&pcic->handle);
981 ddi_regs_map_free(&pcic->cfg_handle);
982 kmem_free(pcic, sizeof (pcicdev_t));
983 cmn_err(CE_WARN, "pcic: %s: unsupported "
Sherry Moore19397402008-09-22 16:30:26 -0700984 "bridge\n",
985 ddi_get_name_addr(dip));
stevel3db86aa2006-06-29 14:43:12 -0700986 return (DDI_FAILURE);
987 }
988
989 /*
990 * Some PCI-PCMCIA(R2) adapters are Yenta-compliant
991 * for extended registers even though they are
992 * not CardBus adapters. For those adapters,
993 * re-map pcic->handle to be large enough to
994 * encompass the Yenta registers.
995 */
996 switch (pcic->pc_type) {
Sherry Moore19397402008-09-22 16:30:26 -0700997 case PCIC_TI_PCI1031:
stevel3db86aa2006-06-29 14:43:12 -0700998 ddi_regs_map_free(&pcic->handle);
999
1000 if (ddi_regs_map_setup(dip,
Sherry Moore19397402008-09-22 16:30:26 -07001001 PCIC_PCI_CONTROL_REG_NUM,
1002 (caddr_t *)&pcic->ioaddr,
1003 PCIC_PCI_CONTROL_REG_OFFSET,
1004 PCIC_CB_CONTROL_REG_LENGTH,
1005 &attr,
1006 &pcic->handle) != DDI_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -07001007 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001008 "pcic%d: unable to map "
1009 "PCI regs\n",
1010 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -07001011 ddi_regs_map_free(&pcic->cfg_handle);
1012 kmem_free(pcic, sizeof (pcicdev_t));
1013 return (DDI_FAILURE);
1014 } /* ddi_regs_map_setup */
1015 break;
Sherry Moore19397402008-09-22 16:30:26 -07001016 default:
stevel3db86aa2006-06-29 14:43:12 -07001017 break;
1018 } /* switch (pcic->pc_type) */
1019 break;
1020 } /* switch (class_code) */
1021 } else {
1022 /*
1023 * We're not on a PCI bus, so assume an ISA bus type
1024 * register property. Get access to the adapter IO
1025 * registers on a non-PCI bus.
1026 */
1027 attr.devacc_attr_version = DDI_DEVICE_ATTR_V0;
1028 attr.devacc_attr_endian_flags = DDI_NEVERSWAP_ACC;
1029 attr.devacc_attr_dataorder = DDI_STRICTORDER_ACC;
1030 pcic->mem_reg_num = PCIC_ISA_MEM_REG_NUM;
1031 pcic->io_reg_num = PCIC_ISA_IO_REG_NUM;
1032
1033 if (ddi_regs_map_setup(dip, PCIC_ISA_CONTROL_REG_NUM,
Sherry Moore19397402008-09-22 16:30:26 -07001034 (caddr_t *)&pcic->ioaddr,
1035 PCIC_ISA_CONTROL_REG_OFFSET,
1036 PCIC_ISA_CONTROL_REG_LENGTH,
1037 &attr,
1038 &pcic->handle) != DDI_SUCCESS) {
stevel3db86aa2006-06-29 14:43:12 -07001039 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001040 "pcic%d: unable to map ISA registers\n",
1041 ddi_get_instance(dip));
stevel3db86aa2006-06-29 14:43:12 -07001042
1043 kmem_free(pcic, sizeof (pcicdev_t));
1044 return (DDI_FAILURE);
1045 } /* ddi_regs_map_setup */
1046
1047 /* ISA bus is limited to 24-bits, but not first 640K */
1048 pcic->pc_base = 0xd0000;
1049 pcic->pc_bound = (uint32_t)~0;
1050 pcic->pc_iobase = 0x1000;
1051 pcic->pc_iobound = 0xefff;
1052 } /* !PCF_PCIBUS */
1053
1054#ifdef PCIC_DEBUG
1055 if (pcic_debug) {
1056 cmn_err(CE_CONT, "pcic_attach pc_flags=%x pc_type=%x\n",
1057 pcic->pc_flags, pcic->pc_type);
1058 }
1059#endif
1060
1061 /*
1062 * Setup various adapter registers for the PCI case. For the
1063 * non-PCI case, find out the chip type.
1064 */
1065 if (pcic->pc_flags & PCF_PCIBUS) {
1066 int iline;
1067#if defined(__sparc)
1068 iline = 0;
1069#else
1070 iline = cardbus_validate_iline(dip, pcic->cfg_handle);
1071#endif
1072
1073 /* set flags and socket counts based on chip type */
1074 switch (pcic->pc_type) {
1075 uint32_t cfg;
1076 case PCIC_INTEL_i82092:
1077 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001078 pcic->cfgaddr + PCIC_82092_PCICON);
stevel3db86aa2006-06-29 14:43:12 -07001079 /* we can only support 4 Socket version */
1080 if (cfg & PCIC_82092_4_SOCKETS) {
Sherry Moore19397402008-09-22 16:30:26 -07001081 pcic->pc_numsockets = 4;
1082 pcic->pc_type = PCIC_INTEL_i82092;
1083 if (iline != 0xFF)
1084 pcic->pc_intr_mode =
1085 PCIC_INTR_MODE_PCI_1;
1086 else
1087 pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
stevel3db86aa2006-06-29 14:43:12 -07001088 } else {
Sherry Moore19397402008-09-22 16:30:26 -07001089 cmn_err(CE_CONT,
stevel3db86aa2006-06-29 14:43:12 -07001090 "pcic%d: Intel 82092 adapter "
1091 "in unsupported configuration: 0x%x",
1092 ddi_get_instance(pcic->dip), cfg);
Sherry Moore19397402008-09-22 16:30:26 -07001093 pcic->pc_numsockets = 0;
stevel3db86aa2006-06-29 14:43:12 -07001094 } /* PCIC_82092_4_SOCKETS */
1095 break;
1096 case PCIC_CL_PD6730:
1097 case PCIC_CL_PD6729:
1098 pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1099 cfg = ddi_getprop(DDI_DEV_T_ANY, dip,
Sherry Moore19397402008-09-22 16:30:26 -07001100 DDI_PROP_CANSLEEP,
1101 "interrupts", 0);
stevel3db86aa2006-06-29 14:43:12 -07001102 /* if not interrupt pin then must use ISA style IRQs */
1103 if (cfg == 0 || iline == 0xFF)
1104 pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
1105 else {
1106 /*
1107 * we have the option to use PCI interrupts.
1108 * this might not be optimal but in some cases
1109 * is the only thing possible (sparc case).
1110 * we now deterine what is possible.
1111 */
1112 pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1113 }
1114 pcic->pc_numsockets = 2;
1115 pcic->pc_flags |= PCF_IO_REMAP;
1116 break;
1117 case PCIC_TI_PCI1031:
1118 /* this chip doesn't do CardBus but looks like one */
1119 pcic->pc_flags &= ~PCF_CARDBUS;
1120 /* FALLTHROUGH */
1121 default:
1122 pcic->pc_flags |= PCF_IO_REMAP;
1123 /* FALLTHROUGH */
1124 /* indicate feature even if not supported */
1125 pcic->pc_flags |= PCF_DMA | PCF_ZV;
1126 /* Not sure if these apply to all these chips */
1127 pcic->pc_flags |= (PCF_VPPX|PCF_33VCAP);
1128 pcic->pc_flags |= pcic_use_cbpwrctl;
1129
1130 pcic->pc_numsockets = 1; /* one per function */
1131 if (iline != 0xFF) {
1132 uint8_t cfg;
1133 pcic->pc_intr_mode = PCIC_INTR_MODE_PCI_1;
1134
1135 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001136 (pcic->cfgaddr + PCIC_BRIDGE_CTL_REG));
stevel3db86aa2006-06-29 14:43:12 -07001137 cfg &= (~PCIC_FUN_INT_MOD_ISA);
1138 ddi_put8(pcic->cfg_handle, (pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07001139 PCIC_BRIDGE_CTL_REG), cfg);
stevel3db86aa2006-06-29 14:43:12 -07001140 }
1141 else
1142 pcic->pc_intr_mode = PCIC_INTR_MODE_ISA;
1143 pcic->pc_io_type = PCIC_IOTYPE_YENTA;
1144 break;
1145 }
1146 } else {
1147 /*
1148 * We're not on a PCI bus so do some more
1149 * checking for adapter type here.
1150 * For the non-PCI bus case:
1151 * It could be any one of a number of different chips
1152 * If we can't determine anything else, it is assumed
1153 * to be an Intel 82365SL. The Cirrus Logic PD6710
1154 * has an extension register that provides unique
1155 * identification. Toshiba chip isn't detailed as yet.
1156 */
1157
1158 /* Init the CL id mode */
1159 pcic_putb(pcic, 0, PCIC_CHIP_INFO, 0);
1160 value = pcic_getb(pcic, 0, PCIC_CHIP_INFO);
1161
1162 /* default to Intel i82365SL and then refine */
1163 pcic->pc_type = PCIC_I82365SL;
1164 pcic->pc_chipname = PCIC_TYPE_I82365SL;
1165 for (value = 0; pcic_ci_funcs[value] != NULL; value++) {
1166 /* go until one succeeds or none left */
1167 if (pcic_ci_funcs[value](pcic))
1168 break;
1169 }
1170
1171 /* any chip specific flags get set here */
1172 switch (pcic->pc_type) {
1173 case PCIC_CL_PD6722:
1174 pcic->pc_flags |= PCF_DMA;
1175 }
1176
1177 for (i = 0; i < PCIC_MAX_SOCKETS; i++) {
1178 /*
1179 * look for total number of sockets.
1180 * basically check each possible socket for
1181 * presence like in probe
1182 */
1183
1184 /* turn all windows off */
1185 pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1186 value = pcic_getb(pcic, i, PCIC_MAPPING_ENABLE);
1187
1188 /*
1189 * if a zero is read back, then this socket
1190 * might be present. It would be except for
1191 * some systems that map the secondary PCIC
1192 * chip space back to the first.
1193 */
1194 if (value != 0) {
1195 /* definitely not so skip */
1196 /* note: this is for Compaq support */
1197 continue;
1198 }
1199
1200 /* further tests */
1201 value = pcic_getb(pcic, i, PCIC_CHIP_REVISION) &
Sherry Moore19397402008-09-22 16:30:26 -07001202 PCIC_REV_MASK;
stevel3db86aa2006-06-29 14:43:12 -07001203 if (!(value >= PCIC_REV_LEVEL_LOW &&
Sherry Moore19397402008-09-22 16:30:26 -07001204 value <= PCIC_REV_LEVEL_HI))
stevel3db86aa2006-06-29 14:43:12 -07001205 break;
1206
1207 pcic_putb(pcic, i, PCIC_SYSMEM_0_STARTLOW, 0xaa);
1208 pcic_putb(pcic, i, PCIC_SYSMEM_1_STARTLOW, 0x55);
1209 value = pcic_getb(pcic, i, PCIC_SYSMEM_0_STARTLOW);
1210
1211 j = pcic_getb(pcic, i, PCIC_SYSMEM_1_STARTLOW);
1212 if (value != 0xaa || j != 0x55)
1213 break;
1214
1215 /*
1216 * at this point we know if we have hardware
1217 * of some type and not just the bus holding
1218 * a pattern for us. We still have to determine
1219 * the case where more than 2 sockets are
1220 * really the same due to peculiar mappings of
1221 * hardware.
1222 */
1223 j = pcic->pc_numsockets++;
1224 pcic->pc_sockets[j].pcs_flags = 0;
1225 pcic->pc_sockets[j].pcs_io = pcic->ioaddr;
1226 pcic->pc_sockets[j].pcs_socket = i;
1227
1228 /* put PC Card into RESET, just in case */
1229 value = pcic_getb(pcic, i, PCIC_INTERRUPT);
1230 pcic_putb(pcic, i, PCIC_INTERRUPT,
Sherry Moore19397402008-09-22 16:30:26 -07001231 value & ~PCIC_RESET);
stevel3db86aa2006-06-29 14:43:12 -07001232 }
1233
1234#if defined(PCIC_DEBUG)
1235 if (pcic_debug)
1236 cmn_err(CE_CONT, "num sockets = %d\n",
Sherry Moore19397402008-09-22 16:30:26 -07001237 pcic->pc_numsockets);
stevel3db86aa2006-06-29 14:43:12 -07001238#endif
1239 if (pcic->pc_numsockets == 0) {
1240 ddi_regs_map_free(&pcic->handle);
1241 kmem_free(pcic, sizeof (pcicdev_t));
1242 return (DDI_FAILURE);
1243 }
1244
1245 /*
1246 * need to think this through again in light of
1247 * Compaq not following the model that all the
1248 * chip vendors recommend. IBM 755 seems to be
1249 * afflicted as well. Basically, if the vendor
1250 * wired things wrong, socket 0 responds for socket 2
1251 * accesses, etc.
1252 */
1253 if (pcic->pc_numsockets > 2) {
1254 int count = pcic->pc_numsockets / 4;
1255 for (i = 0; i < count; i++) {
1256 /* put pattern into socket 0 */
1257 pcic_putb(pcic, i,
Sherry Moore19397402008-09-22 16:30:26 -07001258 PCIC_SYSMEM_0_STARTLOW, 0x11);
stevel3db86aa2006-06-29 14:43:12 -07001259
1260 /* put pattern into socket 2 */
1261 pcic_putb(pcic, i + 2,
Sherry Moore19397402008-09-22 16:30:26 -07001262 PCIC_SYSMEM_0_STARTLOW, 0x33);
stevel3db86aa2006-06-29 14:43:12 -07001263
1264 /* read back socket 0 */
1265 value = pcic_getb(pcic, i,
Sherry Moore19397402008-09-22 16:30:26 -07001266 PCIC_SYSMEM_0_STARTLOW);
stevel3db86aa2006-06-29 14:43:12 -07001267
1268 /* read back chip 1 socket 0 */
1269 j = pcic_getb(pcic, i + 2,
Sherry Moore19397402008-09-22 16:30:26 -07001270 PCIC_SYSMEM_0_STARTLOW);
stevel3db86aa2006-06-29 14:43:12 -07001271 if (j == value) {
1272 pcic->pc_numsockets -= 2;
1273 }
1274 }
1275 }
1276
1277 smi = 0xff; /* no more override */
1278
1279 if (ddi_getprop(DDI_DEV_T_NONE, dip,
Sherry Moore19397402008-09-22 16:30:26 -07001280 DDI_PROP_DONTPASS, "need-mult-irq",
1281 0xffff) != 0xffff)
stevel3db86aa2006-06-29 14:43:12 -07001282 pcic->pc_flags |= PCF_MULT_IRQ;
1283
1284 } /* !PCF_PCIBUS */
1285
1286 /*
1287 * some platforms/busses need to have resources setup
1288 * this is temporary until a real resource allocator is
1289 * implemented.
1290 */
1291
1292 pcic_init_assigned(dip);
1293
1294 typename = pcic->pc_chipname;
1295
1296#ifdef PCIC_DEBUG
1297 if (pcic_debug) {
1298 int nregs, nintrs;
1299
1300 if (ddi_dev_nregs(dip, &nregs) != DDI_SUCCESS)
1301 nregs = 0;
1302
1303 if (ddi_dev_nintrs(dip, &nintrs) != DDI_SUCCESS)
1304 nintrs = 0;
1305
1306 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001307 "pcic%d: %d register sets, %d interrupts\n",
1308 ddi_get_instance(dip), nregs, nintrs);
stevel3db86aa2006-06-29 14:43:12 -07001309
1310 nintrs = 0;
1311 while (nregs--) {
1312 off_t size;
1313
1314 if (ddi_dev_regsize(dip, nintrs, &size) ==
1315 DDI_SUCCESS) {
1316 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001317 "\tregnum %d size %ld (0x%lx)"
1318 "bytes",
1319 nintrs, size, size);
stevel3db86aa2006-06-29 14:43:12 -07001320 if (nintrs ==
1321 (pcic->pc_io_type == PCIC_IO_TYPE_82365SL ?
1322 PCIC_ISA_CONTROL_REG_NUM :
1323 PCIC_PCI_CONTROL_REG_NUM))
1324 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001325 " mapped at: 0x%p\n",
1326 (void *)pcic->ioaddr);
stevel3db86aa2006-06-29 14:43:12 -07001327 else
1328 cmn_err(CE_CONT, "\n");
1329 } else {
1330 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07001331 "\tddi_dev_regsize(rnumber"
1332 "= %d) returns DDI_FAILURE\n",
1333 nintrs);
stevel3db86aa2006-06-29 14:43:12 -07001334 }
1335 nintrs++;
1336 } /* while */
1337 } /* if (pcic_debug) */
1338#endif
1339
1340 cv_init(&pcic->pm_cv, NULL, CV_DRIVER, NULL);
1341
1342 if (!ddi_getprop(DDI_DEV_T_NONE, dip, DDI_PROP_DONTPASS,
Sherry Moore19397402008-09-22 16:30:26 -07001343 "disable-audio", 0))
stevel3db86aa2006-06-29 14:43:12 -07001344 pcic->pc_flags |= PCF_AUDIO;
1345
1346 if (ddi_getprop(DDI_DEV_T_ANY, dip, DDI_PROP_CANSLEEP,
1347 "disable-cardbus", 0))
1348 pcic->pc_flags &= ~PCF_CARDBUS;
1349
1350 (void) ddi_prop_update_string(DDI_DEV_T_NONE, dip, PCICPROP_CTL,
1351 typename);
1352
1353 /*
1354 * Init all socket SMI levels to 0 (no SMI)
1355 */
1356 for (i = 0; i < PCIC_MAX_SOCKETS; i++) {
Sherry Moore19397402008-09-22 16:30:26 -07001357 pcic->pc_sockets[i].pcs_smi = 0;
1358 pcic->pc_sockets[i].pcs_debounce_id = 0;
1359 pcic->pc_sockets[i].pcs_pcic = pcic;
stevel3db86aa2006-06-29 14:43:12 -07001360 }
1361 pcic->pc_lastreg = -1; /* just to make sure we are in sync */
1362
1363 /*
1364 * Setup the IRQ handler(s)
1365 */
1366 switch (pcic->pc_intr_mode) {
1367 int xx;
1368 case PCIC_INTR_MODE_ISA:
1369 /*
1370 * On a non-PCI bus, we just use whatever SMI IRQ level was
1371 * specified above, and the IO IRQ levels are allocated
1372 * dynamically.
1373 */
1374 for (xx = 15, smi = 0; xx >= 0; xx--) {
1375 if (PCIC_IRQ(xx) &
1376 PCIC_AVAIL_IRQS) {
1377 smi = pcmcia_get_intr(dip, xx);
1378 if (smi >= 0)
1379 break;
1380 }
1381 }
1382#if defined(PCIC_DEBUG)
1383 if (pcic_debug)
1384 cmn_err(CE_NOTE, "\tselected IRQ %d as SMI\n", smi);
1385#endif
1386 /* init to same so share is easy */
1387 for (i = 0; i < pcic->pc_numsockets; i++)
1388 pcic->pc_sockets[i].pcs_smi = smi;
1389 /* any special handling of IRQ levels */
1390 if (pcic->pc_flags & PCF_MULT_IRQ) {
1391 for (i = 2; i < pcic->pc_numsockets; i++) {
1392 if ((i & 1) == 0) {
1393 int xx;
1394 for (xx = 15, smi = 0; xx >= 0; xx--) {
1395 if (PCIC_IRQ(xx) &
1396 PCIC_AVAIL_IRQS) {
1397 smi =
1398 pcmcia_get_intr(dip,
Sherry Moore19397402008-09-22 16:30:26 -07001399 xx);
stevel3db86aa2006-06-29 14:43:12 -07001400 if (smi >= 0)
1401 break;
1402 }
1403 }
1404 }
1405 if (smi >= 0)
1406 pcic->pc_sockets[i].pcs_smi = smi;
1407 }
1408 }
1409 pcic->pc_intr_htblp = kmem_alloc(pcic->pc_numsockets *
1410 sizeof (ddi_intr_handle_t), KM_SLEEP);
1411 for (i = 0, irqlevel = -1; i < pcic->pc_numsockets; i++) {
1412 struct intrspec *ispecp;
1413 struct ddi_parent_private_data *pdp;
1414
1415 if (irqlevel == pcic->pc_sockets[i].pcs_smi)
1416 continue;
1417 else {
1418 irqlevel = pcic->pc_sockets[i].pcs_smi;
1419 }
1420 /*
1421 * now convert the allocated IRQ into an intrspec
1422 * and ask our parent to add it. Don't use
1423 * the ddi_add_intr since we don't have a
1424 * default intrspec in all cases.
1425 *
1426 * note: this sort of violates DDI but we don't
1427 * get hardware intrspecs for many of the devices.
1428 * at the same time, we know how to allocate them
1429 * so we do the right thing.
1430 */
1431 if (ddi_intr_alloc(dip, &pcic->pc_intr_htblp[i],
1432 DDI_INTR_TYPE_FIXED, 0, 1, &actual,
1433 DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS) {
1434 cmn_err(CE_WARN, "%s: ddi_intr_alloc failed",
1435 ddi_get_name(dip));
1436 goto isa_exit1;
1437 }
1438
1439 /*
1440 * See earlier note:
1441 * Since some devices don't have 'intrspec'
1442 * we make one up in rootnex.
1443 *
1444 * However, it is not properly initialized as
1445 * the data it needs is present in this driver
1446 * and there is no interface to pass that up.
1447 * Specially 'irqlevel' is very important and
1448 * it is part of pcic struct.
1449 *
1450 * Set 'intrspec' up here; otherwise adding the
1451 * interrupt will fail.
1452 */
1453 pdp = ddi_get_parent_data(dip);
1454 ispecp = (struct intrspec *)&pdp->par_intr[0];
1455 ispecp->intrspec_vec = irqlevel;
1456 ispecp->intrspec_pri = pcic->pc_irq;
1457
1458 /* Stay compatible w/ PCMCIA */
1459 pcic->pc_pri = (ddi_iblock_cookie_t)
1460 (uintptr_t)pcic->pc_irq;
1461 pcic->pc_dcookie.idev_priority =
1462 (uintptr_t)pcic->pc_pri;
1463 pcic->pc_dcookie.idev_vector = (ushort_t)irqlevel;
1464
1465 (void) ddi_intr_set_pri(pcic->pc_intr_htblp[i],
1466 pcic->pc_irq);
1467
1468 if (i == 0) {
1469 mutex_init(&pcic->intr_lock, NULL, MUTEX_DRIVER,
1470 DDI_INTR_PRI(pcic->pc_irq));
1471 mutex_init(&pcic->pc_lock, NULL, MUTEX_DRIVER,
1472 NULL);
1473 }
1474
1475 if (ddi_intr_add_handler(pcic->pc_intr_htblp[i],
1476 pcic_intr, (caddr_t)pcic, NULL)) {
1477 cmn_err(CE_WARN,
1478 "%s: ddi_intr_add_handler failed",
1479 ddi_get_name(dip));
1480 goto isa_exit2;
1481 }
1482
1483 if (ddi_intr_enable(pcic->pc_intr_htblp[i])) {
1484 cmn_err(CE_WARN, "%s: ddi_intr_enable failed",
1485 ddi_get_name(dip));
1486 for (j = i; j < 0; j--)
1487 (void) ddi_intr_remove_handler(
1488 pcic->pc_intr_htblp[j]);
1489 goto isa_exit2;
1490 }
1491 }
1492 break;
1493 case PCIC_INTR_MODE_PCI_1:
1494 case PCIC_INTR_MODE_PCI:
1495 /*
1496 * If we're on a PCI bus, we route all interrupts, both SMI
1497 * and IO interrupts, through a single interrupt line.
1498 * Assign the SMI IRQ level to the IO IRQ level here.
1499 */
1500 pcic->pc_pci_intr_hdlp = kmem_alloc(sizeof (ddi_intr_handle_t),
1501 KM_SLEEP);
1502 if (ddi_intr_alloc(dip, pcic->pc_pci_intr_hdlp,
1503 DDI_INTR_TYPE_FIXED, 0, 1, &actual,
1504 DDI_INTR_ALLOC_NORMAL) != DDI_SUCCESS)
1505 goto pci_exit1;
1506
1507 if (ddi_intr_get_pri(pcic->pc_pci_intr_hdlp[0],
1508 &pri) != DDI_SUCCESS) {
1509 (void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1510 goto pci_exit1;
1511 }
1512
1513 pcic->pc_pri = (void *)(uintptr_t)pri;
1514 mutex_init(&pcic->intr_lock, NULL, MUTEX_DRIVER, pcic->pc_pri);
1515 mutex_init(&pcic->pc_lock, NULL, MUTEX_DRIVER, NULL);
1516
1517 if (ddi_intr_add_handler(pcic->pc_pci_intr_hdlp[0],
1518 pcic_intr, (caddr_t)pcic, NULL))
1519 goto pci_exit2;
1520
1521 if (ddi_intr_enable(pcic->pc_pci_intr_hdlp[0])) {
1522 (void) ddi_intr_remove_handler(
1523 pcic->pc_pci_intr_hdlp[0]);
1524 goto pci_exit2;
1525 }
1526
1527 /* Stay compatible w/ PCMCIA */
1528 pcic->pc_dcookie.idev_priority = (ushort_t)pri;
1529
1530 /* init to same (PCI) so share is easy */
1531 for (i = 0; i < pcic->pc_numsockets; i++)
1532 pcic->pc_sockets[i].pcs_smi = 0xF; /* any valid */
1533 break;
1534 }
1535
1536 /*
1537 * Setup the adapter hardware to some reasonable defaults.
1538 */
1539 mutex_enter(&pcic->pc_lock);
1540 /* mark the driver state as attached */
1541 pcic->pc_flags |= PCF_ATTACHED;
1542 pcic_setup_adapter(pcic);
1543
1544 for (j = 0; j < pcic->pc_numsockets; j++)
1545 if (ddi_intr_add_softint(dip,
1546 &pcic->pc_sockets[j].pcs_cd_softint_hdl,
1547 PCIC_SOFTINT_PRI_VAL, pcic_cd_softint,
1548 (caddr_t)&pcic->pc_sockets[j]) != DDI_SUCCESS)
1549 goto pci_exit2;
1550
1551#if defined(PCIC_DEBUG)
1552 if (pcic_debug)
1553 cmn_err(CE_CONT, "type = %s sockets = %d\n", typename,
Sherry Moore19397402008-09-22 16:30:26 -07001554 pcic->pc_numsockets);
stevel3db86aa2006-06-29 14:43:12 -07001555#endif
1556
1557 pcic_nexus->an_iblock = &pcic->pc_pri;
1558 pcic_nexus->an_idev = &pcic->pc_dcookie;
1559
1560 mutex_exit(&pcic->pc_lock);
1561
1562#ifdef CARDBUS
1563 (void) cardbus_enable_cd_intr(dip);
1564 if (pcic_debug) {
1565
1566 cardbus_dump_pci_config(dip);
1567 cardbus_dump_socket(dip);
1568 }
1569
1570 /*
1571 * Give the Cardbus misc module a chance to do it's per-adapter
1572 * instance setup. Note that there is no corresponding detach()
1573 * call.
1574 */
1575 if (pcic->pc_flags & PCF_CARDBUS)
1576 if (cardbus_attach(dip, &pcic_cbnexus_ops) != DDI_SUCCESS) {
1577 cmn_err(CE_CONT,
1578 "pcic_attach: cardbus_attach failed\n");
1579 goto pci_exit2;
1580 }
1581#endif
1582
1583 /*
1584 * Give the PCMCIA misc module a chance to do it's per-adapter
1585 * instance setup.
1586 */
1587 if ((i = pcmcia_attach(dip, pcic_nexus)) != DDI_SUCCESS)
1588 goto pci_exit2;
1589
stevel3db86aa2006-06-29 14:43:12 -07001590 if (pcic_maxinst == -1) {
1591 /* This assumes that all instances run at the same IPL. */
1592 mutex_init(&pcic_deb_mtx, NULL, MUTEX_DRIVER, NULL);
1593 cv_init(&pcic_deb_cv, NULL, CV_DRIVER, NULL);
1594 pcic_deb_threadid = thread_create((caddr_t)NULL, 0,
1595 pcic_deb_thread, (caddr_t)NULL, 0, &p0, TS_RUN,
1596 v.v_maxsyspri - 2);
1597 }
1598 pcic_maxinst = max(pcic_maxinst, ddi_get_instance(dip));
1599 /*
1600 * Setup a debounce timeout to do an initial card detect
1601 * and enable interrupts.
1602 */
1603 for (j = 0; j < pcic->pc_numsockets; j++) {
stevel3db86aa2006-06-29 14:43:12 -07001604 pcic->pc_sockets[j].pcs_debounce_id =
1605 pcic_add_debqueue(&pcic->pc_sockets[j],
Sherry Moore19397402008-09-22 16:30:26 -07001606 drv_usectohz(pcic_debounce_time));
stevel3db86aa2006-06-29 14:43:12 -07001607 }
1608
1609 return (i);
1610
1611isa_exit2:
1612 mutex_destroy(&pcic->intr_lock);
1613 mutex_destroy(&pcic->pc_lock);
1614 for (j = i; j < 0; j--)
1615 (void) ddi_intr_free(pcic->pc_intr_htblp[j]);
1616isa_exit1:
1617 (void) pcmcia_return_intr(dip, pcic->pc_sockets[i].pcs_smi);
1618 ddi_regs_map_free(&pcic->handle);
1619 if (pcic->pc_flags & PCF_PCIBUS)
1620 ddi_regs_map_free(&pcic->cfg_handle);
1621 kmem_free(pcic->pc_intr_htblp, pcic->pc_numsockets *
1622 sizeof (ddi_intr_handle_t));
1623 kmem_free(pcic, sizeof (pcicdev_t));
1624 return (DDI_FAILURE);
1625
1626pci_exit2:
1627 mutex_destroy(&pcic->intr_lock);
1628 mutex_destroy(&pcic->pc_lock);
1629 (void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1630pci_exit1:
1631 ddi_regs_map_free(&pcic->handle);
1632 if (pcic->pc_flags & PCF_PCIBUS)
1633 ddi_regs_map_free(&pcic->cfg_handle);
1634 kmem_free(pcic->pc_pci_intr_hdlp, sizeof (ddi_intr_handle_t));
1635 kmem_free(pcic, sizeof (pcicdev_t));
1636 return (DDI_FAILURE);
1637}
1638
1639/*
1640 * pcic_detach()
1641 * request to detach from the system
1642 */
1643static int
1644pcic_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
1645{
1646 anp_t *anp = ddi_get_driver_private(dip);
1647 pcicdev_t *pcic = anp->an_private;
1648 int i;
1649
1650 switch (cmd) {
1651 case DDI_DETACH:
1652 /* don't detach if the nexus still talks to us */
1653 if (pcic->pc_callback != NULL)
1654 return (DDI_FAILURE);
stevel3db86aa2006-06-29 14:43:12 -07001655
1656 /* kill off the pm simulation */
1657 if (pcic->pc_pmtimer)
1658 (void) untimeout(pcic->pc_pmtimer);
1659
1660 /* turn everything off for all sockets and chips */
1661 for (i = 0; i < pcic->pc_numsockets; i++) {
1662 if (pcic->pc_sockets[i].pcs_debounce_id)
1663 pcic_rm_debqueue(
1664 pcic->pc_sockets[i].pcs_debounce_id);
1665 pcic->pc_sockets[i].pcs_debounce_id = 0;
1666
1667 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT, 0);
1668 pcic_putb(pcic, i, PCIC_CARD_DETECT, 0);
1669 pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1670 /* disable interrupts and put card into RESET */
1671 pcic_putb(pcic, i, PCIC_INTERRUPT, 0);
1672 }
1673 (void) ddi_intr_disable(pcic->pc_pci_intr_hdlp[0]);
1674 (void) ddi_intr_remove_handler(pcic->pc_pci_intr_hdlp[0]);
1675 (void) ddi_intr_free(pcic->pc_pci_intr_hdlp[0]);
1676 kmem_free(pcic->pc_pci_intr_hdlp, sizeof (ddi_intr_handle_t));
1677 pcic->pc_flags = 0;
1678 mutex_destroy(&pcic->pc_lock);
1679 mutex_destroy(&pcic->intr_lock);
1680 cv_destroy(&pcic->pm_cv);
1681 if (pcic->pc_flags & PCF_PCIBUS)
Sherry Moore19397402008-09-22 16:30:26 -07001682 ddi_regs_map_free(&pcic->cfg_handle);
stevel3db86aa2006-06-29 14:43:12 -07001683 if (pcic->handle)
Sherry Moore19397402008-09-22 16:30:26 -07001684 ddi_regs_map_free(&pcic->handle);
stevel3db86aa2006-06-29 14:43:12 -07001685 kmem_free(pcic, sizeof (pcicdev_t));
1686 ddi_soft_state_free(pcic_soft_state_p, ddi_get_instance(dip));
1687 return (DDI_SUCCESS);
1688
1689 case DDI_SUSPEND:
1690 case DDI_PM_SUSPEND:
1691 /*
1692 * we got a suspend event (either real or imagined)
1693 * so notify the nexus proper that all existing cards
1694 * should go away.
1695 */
1696 mutex_enter(&pcic->pc_lock);
1697#ifdef CARDBUS
rw14856111c2b4c2008-07-21 16:51:53 -07001698 if (pcic->pc_flags & PCF_CARDBUS) {
1699 for (i = 0; i < pcic->pc_numsockets; i++) {
stevel3db86aa2006-06-29 14:43:12 -07001700 if ((pcic->pc_sockets[i].pcs_flags &
1701 (PCS_CARD_PRESENT|PCS_CARD_ISCARDBUS)) ==
rw14856111c2b4c2008-07-21 16:51:53 -07001702 (PCS_CARD_PRESENT|PCS_CARD_ISCARDBUS)) {
1703
1704 pcmcia_cb_suspended(
Sherry Moore19397402008-09-22 16:30:26 -07001705 pcic->pc_sockets[i].pcs_socket);
rw14856111c2b4c2008-07-21 16:51:53 -07001706 }
1707 }
1708
1709 cardbus_save_children(ddi_get_child(dip));
1710 }
stevel3db86aa2006-06-29 14:43:12 -07001711#endif
1712 /* turn everything off for all sockets and chips */
1713 for (i = 0; i < pcic->pc_numsockets; i++) {
1714 if (pcic->pc_sockets[i].pcs_debounce_id)
1715 pcic_rm_debqueue(
1716 pcic->pc_sockets[i].pcs_debounce_id);
1717 pcic->pc_sockets[i].pcs_debounce_id = 0;
1718
1719 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT, 0);
1720 pcic_putb(pcic, i, PCIC_CARD_DETECT, 0);
1721 pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1722 /* disable interrupts and put card into RESET */
1723 pcic_putb(pcic, i, PCIC_INTERRUPT, 0);
1724 pcic_putb(pcic, i, PCIC_POWER_CONTROL, 0);
1725 if (pcic->pc_flags & PCF_CBPWRCTL)
1726 pcic_putcb(pcic, CB_CONTROL, 0);
1727
1728 if (pcic->pc_sockets[i].pcs_flags & PCS_CARD_PRESENT) {
1729 pcic->pc_sockets[i].pcs_flags = PCS_STARTING;
1730 /*
1731 * Because we are half way through a save
1732 * all this does is schedule a removal event
1733 * to cs for when the system comes back.
1734 * This doesn't actually matter.
1735 */
1736 if (!pcic_do_pcmcia_sr && pcic_do_removal &&
1737 pcic->pc_callback) {
1738 PC_CALLBACK(pcic->dip, pcic->pc_cb_arg,
1739 PCE_CARD_REMOVAL,
1740 pcic->pc_sockets[i].pcs_socket);
1741 }
1742 }
1743 }
1744
1745 pcic->pc_flags |= PCF_SUSPENDED;
1746 mutex_exit(&pcic->pc_lock);
stevel3db86aa2006-06-29 14:43:12 -07001747
1748 /*
1749 * when true power management exists, save the adapter
1750 * state here to enable a recovery. For the emulation
1751 * condition, the state is gone
1752 */
1753 return (DDI_SUCCESS);
1754
1755 default:
1756 return (EINVAL);
1757 }
1758}
1759
1760static uint32_t pcic_tisysctl_onbits = ((1<<27) | (1<<15) | (1<<14));
1761static uint32_t pcic_tisysctl_offbits = 0;
1762static uint32_t pcic_default_latency = 0x40;
1763
1764static void
1765pcic_setup_adapter(pcicdev_t *pcic)
1766{
1767 int i;
1768 int value, flags;
1769
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001770#if defined(__i386) || defined(__amd64)
1771 pci_regspec_t *reg;
1772 uchar_t bus, dev, func;
1773 uint_t classcode;
1774 int length;
1775#endif
1776
stevel3db86aa2006-06-29 14:43:12 -07001777 if (pcic->pc_flags & PCF_PCIBUS) {
1778 /*
1779 * all PCI-to-PCMCIA bus bridges need memory and I/O enabled
1780 */
1781 flags = (PCIC_ENABLE_IO | PCIC_ENABLE_MEM);
1782 pcic_iomem_pci_ctl(pcic->cfg_handle, pcic->cfgaddr, flags);
1783 }
1784 /* enable each socket */
1785 for (i = 0; i < pcic->pc_numsockets; i++) {
1786 pcic->pc_sockets[i].pcs_flags = 0;
1787 /* find out the socket capabilities (I/O vs memory) */
1788 value = pcic_getb(pcic, i,
Sherry Moore19397402008-09-22 16:30:26 -07001789 PCIC_CHIP_REVISION) & PCIC_REV_ID_MASK;
stevel3db86aa2006-06-29 14:43:12 -07001790 if (value == PCIC_REV_ID_IO || value == PCIC_REV_ID_BOTH)
1791 pcic->pc_sockets[i].pcs_flags |= PCS_SOCKET_IO;
1792
1793 /* disable all windows just in case */
1794 pcic_putb(pcic, i, PCIC_MAPPING_ENABLE, 0);
1795
1796 switch (pcic->pc_type) {
1797 uint32_t cfg32;
1798 uint16_t cfg16;
1799 uint8_t cfg;
1800
1801 /* enable extended registers for Vadem */
Sherry Moore19397402008-09-22 16:30:26 -07001802 case PCIC_VADEM_VG469:
1803 case PCIC_VADEM:
stevel3db86aa2006-06-29 14:43:12 -07001804
1805 /* enable card status change interrupt for socket */
1806 break;
1807
Sherry Moore19397402008-09-22 16:30:26 -07001808 case PCIC_I82365SL:
stevel3db86aa2006-06-29 14:43:12 -07001809 break;
1810
Sherry Moore19397402008-09-22 16:30:26 -07001811 case PCIC_CL_PD6710:
stevel3db86aa2006-06-29 14:43:12 -07001812 pcic_putb(pcic, 0, PCIC_MISC_CTL_2, PCIC_LED_ENABLE);
1813 break;
1814
1815 /*
1816 * On the CL_6730, we need to set up the interrupt
1817 * signalling mode (PCI mode) and set the SMI and
1818 * IRQ interrupt lines to PCI/level-mode.
1819 */
Sherry Moore19397402008-09-22 16:30:26 -07001820 case PCIC_CL_PD6730:
stevel3db86aa2006-06-29 14:43:12 -07001821 switch (pcic->pc_intr_mode) {
1822 case PCIC_INTR_MODE_PCI_1:
1823 clext_reg_write(pcic, i, PCIC_CLEXT_MISC_CTL_3,
Sherry Moore19397402008-09-22 16:30:26 -07001824 ((clext_reg_read(pcic, i,
1825 PCIC_CLEXT_MISC_CTL_3) &
1826 ~PCIC_CLEXT_INT_PCI) |
1827 PCIC_CLEXT_INT_PCI));
stevel3db86aa2006-06-29 14:43:12 -07001828 clext_reg_write(pcic, i, PCIC_CLEXT_EXT_CTL_1,
Sherry Moore19397402008-09-22 16:30:26 -07001829 (PCIC_CLEXT_IRQ_LVL_MODE |
1830 PCIC_CLEXT_SMI_LVL_MODE));
stevel3db86aa2006-06-29 14:43:12 -07001831 cfg = PCIC_CL_LP_DYN_MODE;
1832 pcic_putb(pcic, i, PCIC_MISC_CTL_2, cfg);
1833 break;
1834 case PCIC_INTR_MODE_ISA:
1835 break;
1836 }
1837 break;
1838 /*
1839 * On the CL_6729, we set the SMI and IRQ interrupt
1840 * lines to PCI/level-mode. as well as program the
1841 * correct clock speed divider bit.
1842 */
Sherry Moore19397402008-09-22 16:30:26 -07001843 case PCIC_CL_PD6729:
stevel3db86aa2006-06-29 14:43:12 -07001844 switch (pcic->pc_intr_mode) {
1845 case PCIC_INTR_MODE_PCI_1:
1846 clext_reg_write(pcic, i, PCIC_CLEXT_EXT_CTL_1,
Sherry Moore19397402008-09-22 16:30:26 -07001847 (PCIC_CLEXT_IRQ_LVL_MODE |
1848 PCIC_CLEXT_SMI_LVL_MODE));
stevel3db86aa2006-06-29 14:43:12 -07001849
1850 break;
1851 case PCIC_INTR_MODE_ISA:
1852 break;
1853 }
1854 if (pcic->bus_speed > PCIC_PCI_25MHZ && i == 0) {
1855 cfg = 0;
1856 cfg |= PCIC_CL_TIMER_CLK_DIV;
1857 pcic_putb(pcic, i, PCIC_MISC_CTL_2, cfg);
1858 }
1859 break;
Sherry Moore19397402008-09-22 16:30:26 -07001860 case PCIC_INTEL_i82092:
stevel3db86aa2006-06-29 14:43:12 -07001861 cfg = PCIC_82092_EN_TIMING;
1862 if (pcic->bus_speed < PCIC_SYSCLK_33MHZ)
Sherry Moore19397402008-09-22 16:30:26 -07001863 cfg |= PCIC_82092_PCICLK_25MHZ;
stevel3db86aa2006-06-29 14:43:12 -07001864 ddi_put8(pcic->cfg_handle, pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07001865 PCIC_82092_PCICON, cfg);
stevel3db86aa2006-06-29 14:43:12 -07001866 break;
Sherry Moore19397402008-09-22 16:30:26 -07001867 case PCIC_TI_PCI1130:
1868 case PCIC_TI_PCI1131:
1869 case PCIC_TI_PCI1250:
1870 case PCIC_TI_PCI1031:
stevel3db86aa2006-06-29 14:43:12 -07001871 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001872 pcic->cfgaddr + PCIC_DEVCTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07001873 cfg &= ~PCIC_DEVCTL_INTR_MASK;
1874 switch (pcic->pc_intr_mode) {
1875 case PCIC_INTR_MODE_ISA:
1876 cfg |= PCIC_DEVCTL_INTR_ISA;
1877 break;
1878 }
1879#ifdef PCIC_DEBUG
1880 if (pcic_debug) {
1881 cmn_err(CE_CONT, "pcic_setup_adapter: "
1882 "write reg 0x%x=%x \n",
1883 PCIC_DEVCTL_REG, cfg);
1884 }
1885#endif
1886 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001887 pcic->cfgaddr + PCIC_DEVCTL_REG,
1888 cfg);
stevel3db86aa2006-06-29 14:43:12 -07001889
1890 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001891 pcic->cfgaddr + PCIC_CRDCTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07001892 cfg &= ~(PCIC_CRDCTL_PCIINTR|PCIC_CRDCTL_PCICSC|
Sherry Moore19397402008-09-22 16:30:26 -07001893 PCIC_CRDCTL_PCIFUNC);
stevel3db86aa2006-06-29 14:43:12 -07001894 switch (pcic->pc_intr_mode) {
1895 case PCIC_INTR_MODE_PCI_1:
1896 cfg |= PCIC_CRDCTL_PCIINTR |
Sherry Moore19397402008-09-22 16:30:26 -07001897 PCIC_CRDCTL_PCICSC |
1898 PCIC_CRDCTL_PCIFUNC;
stevel3db86aa2006-06-29 14:43:12 -07001899 pcic->pc_flags |= PCF_USE_SMI;
1900 break;
1901 }
1902#ifdef PCIC_DEBUG
1903 if (pcic_debug) {
1904 cmn_err(CE_CONT, "pcic_setup_adapter: "
1905 " write reg 0x%x=%x \n",
1906 PCIC_CRDCTL_REG, cfg);
1907 }
1908#endif
1909 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001910 pcic->cfgaddr + PCIC_CRDCTL_REG,
1911 cfg);
stevel3db86aa2006-06-29 14:43:12 -07001912 break;
Sherry Moore19397402008-09-22 16:30:26 -07001913 case PCIC_TI_PCI1221:
1914 case PCIC_TI_PCI1225:
stevel3db86aa2006-06-29 14:43:12 -07001915 cfg = ddi_get8(pcic->cfg_handle,
1916 pcic->cfgaddr + PCIC_DEVCTL_REG);
1917 cfg |= (PCIC_DEVCTL_INTR_DFLT | PCIC_DEVCTL_3VCAPABLE);
1918#ifdef PCIC_DEBUG
1919 if (pcic_debug) {
1920 cmn_err(CE_CONT, "pcic_setup_adapter: "
1921 " write reg 0x%x=%x \n",
1922 PCIC_DEVCTL_REG, cfg);
1923 }
1924#endif
1925 ddi_put8(pcic->cfg_handle,
1926 pcic->cfgaddr + PCIC_DEVCTL_REG, cfg);
1927
1928 cfg = ddi_get8(pcic->cfg_handle,
1929 pcic->cfgaddr + PCIC_DIAG_REG);
1930 if (pcic->pc_type == PCIC_TI_PCI1225) {
1931 cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
1932 } else {
1933 cfg |= PCIC_DIAG_ASYNC;
1934 }
1935 pcic->pc_flags |= PCF_USE_SMI;
1936#ifdef PCIC_DEBUG
1937 if (pcic_debug) {
1938 cmn_err(CE_CONT, "pcic_setup_adapter: "
1939 " write reg 0x%x=%x \n",
1940 PCIC_DIAG_REG, cfg);
1941 }
1942#endif
1943 ddi_put8(pcic->cfg_handle,
1944 pcic->cfgaddr + PCIC_DIAG_REG, cfg);
1945 break;
Sherry Moore19397402008-09-22 16:30:26 -07001946 case PCIC_TI_PCI1520:
1947 case PCIC_TI_PCI1510:
1948 case PCIC_TI_VENDOR:
stevel3db86aa2006-06-29 14:43:12 -07001949 if (pcic->pc_intr_mode == PCIC_INTR_MODE_ISA) {
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001950 /* functional intr routed by ExCA register */
stevel3db86aa2006-06-29 14:43:12 -07001951 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001952 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07001953 cfg |= PCIC_FUN_INT_MOD_ISA;
1954 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001955 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
1956 cfg);
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001957
1958 /* IRQ serialized interrupts */
1959 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001960 pcic->cfgaddr + PCIC_DEVCTL_REG);
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001961 cfg &= ~PCIC_DEVCTL_INTR_MASK;
1962 cfg |= PCIC_DEVCTL_INTR_ISA;
1963 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07001964 pcic->cfgaddr + PCIC_DEVCTL_REG,
1965 cfg);
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001966 break;
stevel3db86aa2006-06-29 14:43:12 -07001967 }
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001968
1969 /* CSC interrupt routed to PCI */
1970 cfg = ddi_get8(pcic->cfg_handle,
1971 pcic->cfgaddr + PCIC_DIAG_REG);
1972 cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
1973 ddi_put8(pcic->cfg_handle,
1974 pcic->cfgaddr + PCIC_DIAG_REG, cfg);
1975
1976#if defined(__i386) || defined(__amd64)
1977 /*
1978 * Some TI chips have 2 cardbus slots(function0 and
1979 * function1), and others may have just 1 cardbus slot.
1980 * The interrupt routing register is shared between the
1981 * 2 functions and can only be accessed through
1982 * function0. Here we check the presence of the second
1983 * cardbus slot and do the right thing.
1984 */
1985
1986 if (ddi_getlongprop(DDI_DEV_T_ANY, pcic->dip,
1987 DDI_PROP_DONTPASS, "reg", (caddr_t)&reg,
1988 &length) != DDI_PROP_SUCCESS) {
Sherry Moore19397402008-09-22 16:30:26 -07001989 cmn_err(CE_WARN,
1990 "pcic_setup_adapter(), failed to"
1991 " read reg property\n");
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08001992 break;
1993 }
1994
1995 bus = PCI_REG_BUS_G(reg->pci_phys_hi);
1996 dev = PCI_REG_DEV_G(reg->pci_phys_hi);
1997 func = PCI_REG_FUNC_G(reg->pci_phys_hi);
1998 kmem_free((caddr_t)reg, length);
1999
2000 if (func != 0) {
2001 break;
2002 }
2003
2004 classcode = (*pci_getl_func)(bus, dev, 1,
Sherry Moore19397402008-09-22 16:30:26 -07002005 PCI_CONF_REVID);
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08002006 classcode >>= 8;
2007 if (classcode != 0x060700 &&
2008 classcode != 0x060500) {
2009 break;
2010 }
2011
2012 /* Parallel PCI interrupts only */
stevel3db86aa2006-06-29 14:43:12 -07002013 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002014 pcic->cfgaddr + PCIC_DEVCTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002015 cfg &= ~PCIC_DEVCTL_INTR_MASK;
stevel3db86aa2006-06-29 14:43:12 -07002016 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002017 pcic->cfgaddr + PCIC_DEVCTL_REG,
2018 cfg);
stevel3db86aa2006-06-29 14:43:12 -07002019
2020 /* tie INTA and INTB together */
2021 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002022 (pcic->cfgaddr + PCIC_SYSCTL_REG + 3));
stevel3db86aa2006-06-29 14:43:12 -07002023 cfg |= PCIC_SYSCTL_INTRTIE;
2024 ddi_put8(pcic->cfg_handle, (pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07002025 PCIC_SYSCTL_REG + 3), cfg);
rui wang - Sun Microsystems - Beijing Chinae12b4692008-09-05 15:05:56 +08002026#endif
2027
stevel3db86aa2006-06-29 14:43:12 -07002028 break;
Sherry Moore19397402008-09-22 16:30:26 -07002029 case PCIC_TI_PCI1410:
stevel3db86aa2006-06-29 14:43:12 -07002030 cfg = ddi_get8(pcic->cfg_handle,
2031 pcic->cfgaddr + PCIC_DIAG_REG);
2032 cfg |= (PCIC_DIAG_CSC | PCIC_DIAG_ASYNC);
2033 ddi_put8(pcic->cfg_handle,
2034 pcic->cfgaddr + PCIC_DIAG_REG, cfg);
2035 break;
Sherry Moore19397402008-09-22 16:30:26 -07002036 case PCIC_TOSHIBA_TOPIC100:
2037 case PCIC_TOSHIBA_TOPIC95:
2038 case PCIC_TOSHIBA_VENDOR:
stevel3db86aa2006-06-29 14:43:12 -07002039 cfg = ddi_get8(pcic->cfg_handle, pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07002040 PCIC_TOSHIBA_SLOT_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002041 cfg |= (PCIC_TOSHIBA_SCR_SLOTON |
Sherry Moore19397402008-09-22 16:30:26 -07002042 PCIC_TOSHIBA_SCR_SLOTEN);
stevel3db86aa2006-06-29 14:43:12 -07002043 cfg &= (~PCIC_TOSHIBA_SCR_PRT_MASK);
2044 cfg |= PCIC_TOSHIBA_SCR_PRT_3E2;
2045 ddi_put8(pcic->cfg_handle, pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07002046 PCIC_TOSHIBA_SLOT_CTL_REG, cfg);
stevel3db86aa2006-06-29 14:43:12 -07002047 cfg = ddi_get8(pcic->cfg_handle, pcic->cfgaddr +
Sherry Moore19397402008-09-22 16:30:26 -07002048 PCIC_TOSHIBA_INTR_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002049 switch (pcic->pc_intr_mode) {
2050 case PCIC_INTR_MODE_ISA:
2051 cfg &= ~PCIC_TOSHIBA_ICR_SRC;
2052 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002053 pcic->cfgaddr +
2054 PCIC_TOSHIBA_INTR_CTL_REG, cfg);
stevel3db86aa2006-06-29 14:43:12 -07002055
2056 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002057 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002058 cfg |= PCIC_FUN_INT_MOD_ISA;
2059 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002060 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2061 cfg);
stevel3db86aa2006-06-29 14:43:12 -07002062 break;
2063 case PCIC_INTR_MODE_PCI_1:
2064 cfg |= PCIC_TOSHIBA_ICR_SRC;
2065 cfg &= (~PCIC_TOSHIBA_ICR_PIN_MASK);
2066 cfg |= PCIC_TOSHIBA_ICR_PIN_INTA;
2067 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002068 pcic->cfgaddr +
2069 PCIC_TOSHIBA_INTR_CTL_REG, cfg);
stevel3db86aa2006-06-29 14:43:12 -07002070 break;
2071 }
2072 break;
Sherry Moore19397402008-09-22 16:30:26 -07002073 case PCIC_O2MICRO_VENDOR:
stevel3db86aa2006-06-29 14:43:12 -07002074 cfg32 = ddi_get32(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002075 (uint32_t *)(pcic->cfgaddr +
2076 PCIC_O2MICRO_MISC_CTL));
stevel3db86aa2006-06-29 14:43:12 -07002077 switch (pcic->pc_intr_mode) {
2078 case PCIC_INTR_MODE_ISA:
2079 cfg32 |= (PCIC_O2MICRO_ISA_LEGACY |
Sherry Moore19397402008-09-22 16:30:26 -07002080 PCIC_O2MICRO_INT_MOD_PCI);
stevel3db86aa2006-06-29 14:43:12 -07002081 ddi_put32(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002082 (uint32_t *)(pcic->cfgaddr +
2083 PCIC_O2MICRO_MISC_CTL),
2084 cfg32);
stevel3db86aa2006-06-29 14:43:12 -07002085 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002086 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002087 cfg |= PCIC_FUN_INT_MOD_ISA;
2088 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002089 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2090 cfg);
stevel3db86aa2006-06-29 14:43:12 -07002091 break;
2092 case PCIC_INTR_MODE_PCI_1:
2093 cfg32 &= ~PCIC_O2MICRO_ISA_LEGACY;
2094 cfg32 |= PCIC_O2MICRO_INT_MOD_PCI;
2095 ddi_put32(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002096 (uint32_t *)(pcic->cfgaddr +
2097 PCIC_O2MICRO_MISC_CTL),
2098 cfg32);
stevel3db86aa2006-06-29 14:43:12 -07002099 break;
2100 }
2101 break;
Sherry Moore19397402008-09-22 16:30:26 -07002102 case PCIC_RICOH_VENDOR:
stevel3db86aa2006-06-29 14:43:12 -07002103 if (pcic->pc_intr_mode == PCIC_INTR_MODE_ISA) {
2104 cfg16 = ddi_get16(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002105 (uint16_t *)(pcic->cfgaddr +
2106 PCIC_RICOH_MISC_CTL_2));
stevel3db86aa2006-06-29 14:43:12 -07002107 cfg16 |= (PCIC_RICOH_CSC_INT_MOD |
Sherry Moore19397402008-09-22 16:30:26 -07002108 PCIC_RICOH_FUN_INT_MOD);
stevel3db86aa2006-06-29 14:43:12 -07002109 ddi_put16(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002110 (uint16_t *)(pcic->cfgaddr +
2111 PCIC_RICOH_MISC_CTL_2),
2112 cfg16);
stevel3db86aa2006-06-29 14:43:12 -07002113
2114 cfg16 = ddi_get16(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002115 (uint16_t *)(pcic->cfgaddr +
2116 PCIC_RICOH_MISC_CTL));
stevel3db86aa2006-06-29 14:43:12 -07002117 cfg16 |= PCIC_RICOH_SIRQ_EN;
2118 ddi_put16(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002119 (uint16_t *)(pcic->cfgaddr +
2120 PCIC_RICOH_MISC_CTL),
2121 cfg16);
stevel3db86aa2006-06-29 14:43:12 -07002122
2123 cfg = ddi_get8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002124 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG);
stevel3db86aa2006-06-29 14:43:12 -07002125 cfg |= PCIC_FUN_INT_MOD_ISA;
2126 ddi_put8(pcic->cfg_handle,
Sherry Moore19397402008-09-22 16:30:26 -07002127 pcic->cfgaddr + PCIC_BRIDGE_CTL_REG,
2128 cfg);
stevel3db86aa2006-06-29 14:43:12 -07002129 }
2130 break;
Sherry Moore19397402008-09-22 16:30:26 -07002131 default:
stevel3db86aa2006-06-29 14:43:12 -07002132 break;
2133 } /* switch */
2134
rw148561bb3a0482006-11-12 07:43:43 -08002135 /*
2136 * The default value in the EEPROM (loaded on reset) for
2137 * MFUNC0/MFUNC1 may be incorrect. Here we make sure that
2138 * MFUNC0 is connected to INTA, and MFUNC1 is connected to
2139 * INTB. This applies to all TI CardBus controllers.
2140 */
2141 if ((pcic->pc_type >> 16) == PCIC_TI_VENDORID &&
Sherry Moore19397402008-09-22 16:30:26 -07002142 pcic->pc_intr_mode == PCIC_INTR_MODE_PCI_1) {
rw148561bb3a0482006-11-12 07:43:43 -08002143 value = ddi_get32(pcic->cfg_handle,
2144 (uint32_t *)(pcic->cfgaddr + PCIC_MFROUTE_REG));
2145 value &= ~0xff;
2146 ddi_put32(pcic->cfg_handle, (uint32_t *)(pcic->cfgaddr +
rw1485618134ee02007-02-16 00:52:01 -08002147 PCIC_MFROUTE_REG), value|PCIC_TI_MFUNC_SEL);
rw148561bb3a0482006-11-12 07:43:43 -08002148 }
2149
stevel3db86aa2006-06-29 14:43:12 -07002150 /* setup general card status change interrupt */
2151 switch (pcic->pc_type) {
2152 case PCIC_TI_PCI1225:
2153 case PCIC_TI_PCI1221:
2154 case PCIC_TI_PCI1031:
2155 case PCIC_TI_PCI1520:
2156 case PCIC_TI_PCI1410:
2157 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
2158 PCIC_CHANGE_DEFAULT);
2159 break;
2160 default:
2161 if (pcic->pc_intr_mode ==
Sherry Moore19397402008-09-22 16:30:26 -07002162 PCIC_INTR_MODE_PCI_1) {
stevel3db86aa2006-06-29 14:43:12 -07002163 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
Sherry Moore19397402008-09-22 16:30:26 -07002164 PCIC_CHANGE_DEFAULT);
stevel3db86aa2006-06-29 14:43:12 -07002165 break;
2166 } else {
2167 pcic_putb(pcic, i, PCIC_MANAGEMENT_INT,
Sherry Moore19397402008-09-22 16:30:26 -07002168 PCIC_CHANGE_DEFAULT |
2169 (pcic->pc_sockets[i].pcs_smi << 4));
stevel3db86aa2006-06-29 14:43:12 -07002170 break;
2171 }
2172 }
2173
2174 pcic->pc_flags |= PCF_INTRENAB;
2175
2176 /* take card out of RESET */
2177 pcic_putb(pcic, i, PCIC_INTERRUPT, PCIC_RESET);
2178 /* turn power off and let CS do this */
2179 pcic_putb(pcic, i, PCIC_POWER_CONTROL, 0);
2180
2181 /* final chip specific initialization */
2182 switch (pcic->pc_type) {
Sherry Moore19397402008-09-22 16:30:26 -07002183 case PCIC_VADEM:
stevel3db86aa2006-06-29 14:43:12 -07002184 pcic_putb(pcic, i, PCIC_VG_CONTROL,
Sherry Moore19397402008-09-22 16:30:26 -07002185 PCIC_VC_DELAYENABLE);
stevel3db86aa2006-06-29 14:43:12 -07002186 pcic->pc_flags |= PCF_DEBOUNCE;
2187 /* FALLTHROUGH */
Sherry Moore19397402008-09-22 16:30:26 -07002188 case PCIC_I82365SL:
stevel3db86aa2006-06-29 14:43:12 -07002189 pcic_putb(pcic, i, PCIC_GLOBAL_CONTROL,
Sherry Moore19397402008-09-22 16:30:26 -07002190 PCIC_GC_CSC_WRITE);
stevel3db86aa2006-06-29 14:43:12 -07002191 /* clear any pending interrupts */
2192 value = pcic_getb(pcic, i, PCIC_CARD_STATUS_CHANGE);
2193 pcic_putb(pcic, i, PCIC_CARD_STATUS_CHANGE, value);
2194 break;
2195 /* The 82092 uses PCI config space to enable interrupts */
Sherry Moore19397402008-09-22 16:30:26 -07002196 case PCIC_INTEL_i82092:
stevel3db86aa2006-06-29 14:43:12 -07002197 pcic_82092_smiirq_ctl(pcic, i, PCIC_82092_CTL_SMI,
Sherry Moore19397402008-09-22 16:30:26 -07002198 PCIC_82092_INT_ENABLE);
stevel3db86aa2006-06-29 14:43:12 -07002199 break;
Sherry Moore19397402008-09-22 16:30:26 -07002200 case PCIC_CL_PD6729:
stevel3db86aa2006-06-29 14:43:12 -07002201 if (pcic->bus_speed >= PCIC_PCI_DEF_SYSCLK && i == 0) {
2202 value = pcic_getb(pcic, i, PCIC_MISC_CTL_2);
2203 pcic_putb(pcic, i, PCIC_MISC_CTL_2,
Sherry Moore19397402008-09-22 16:30:26 -07002204 value | PCIC_CL_TIMER_CLK_DIV);
stevel3db86aa2006-06-29 14:43:12 -07002205 }
2206 break;
2207 } /* switch */
2208
2209#if defined(PCIC_DEBUG)
2210 if (pcic_debug)
2211 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07002212 "socket %d value=%x, flags = %x (%s)\n",
2213 i, value, pcic->pc_sockets[i].pcs_flags,
2214 (pcic->pc_sockets[i].pcs_flags &
2215 PCS_CARD_PRESENT) ?
2216 "card present" : "no card");
stevel3db86aa2006-06-29 14:43:12 -07002217#endif
2218 }
2219}
2220
2221/*
2222 * pcic_intr(caddr_t, caddr_t)
2223 * interrupt handler for the PCIC style adapter
2224 * handles all basic interrupts and also checks
2225 * for status changes and notifies the nexus if
2226 * necessary
2227 *
2228 * On PCI bus adapters, also handles all card
2229 * IO interrupts.
2230 */
2231/*ARGSUSED*/
2232uint32_t
2233pcic_intr(caddr_t arg1, caddr_t arg2)
2234{
2235 pcicdev_t *pcic = (pcicdev_t *)arg1;
2236 int value = 0, i, ret = DDI_INTR_UNCLAIMED;
2237 uint8_t status;
2238 uint_t io_ints;
2239
2240#if defined(PCIC_DEBUG)
2241 pcic_err(pcic->dip, 0xf,
Sherry Moore19397402008-09-22 16:30:26 -07002242 "pcic_intr: enter pc_flags=0x%x PCF_ATTACHED=0x%x"
2243 " pc_numsockets=%d \n",
2244 pcic->pc_flags, PCF_ATTACHED, pcic->pc_numsockets);
stevel3db86aa2006-06-29 14:43:12 -07002245#endif
2246
2247 if (!(pcic->pc_flags & PCF_ATTACHED))
Sherry Moore19397402008-09-22 16:30:26 -07002248 return (DDI_INTR_UNCLAIMED);
stevel3db86aa2006-06-29 14:43:12 -07002249
2250 mutex_enter(&pcic->intr_lock);
2251
2252 if (pcic->pc_flags & PCF_SUSPENDED) {
2253 mutex_exit(&pcic->intr_lock);
2254 return (ret);
2255 }
2256
2257 /*
2258 * need to change to only ACK and touch the slot that
2259 * actually caused the interrupt. Currently everything
2260 * is acked
2261 *
2262 * we need to look at all known sockets to determine
2263 * what might have happened, so step through the list
2264 * of them
2265 */
stevel3db86aa2006-06-29 14:43:12 -07002266
2267 /*
2268 * Set the bitmask for IO interrupts to initially include all sockets
2269 */
2270 io_ints = (1 << pcic->pc_numsockets) - 1;
2271
2272 for (i = 0; i < pcic->pc_numsockets; i++) {
2273 int card_type;
2274 pcic_socket_t *sockp;
2275 int value_cb = 0;
2276
2277 sockp = &pcic->pc_sockets[i];
2278 /* get the socket's I/O addresses */
2279
2280 if (sockp->pcs_flags & PCS_WAITING) {
2281 io_ints &= ~(1 << i);
2282 continue;
2283 }
2284
2285 if (sockp->pcs_flags & PCS_CARD_IO)
2286 card_type = IF_IO;
2287 else
2288 card_type = IF_MEMORY;
2289
2290 if (pcic->pc_io_type == PCIC_IO_TYPE_YENTA)
2291 value_cb = pcic_getcb(pcic, CB_STATUS_EVENT);
2292
2293 value = pcic_change(pcic, i);
2294
2295 if ((value != 0) || (value_cb != 0)) {
2296 int x = pcic->pc_cb_arg;
2297
2298 ret = DDI_INTR_CLAIMED;
2299
2300#if defined(PCIC_DEBUG)
2301 pcic_err(pcic->dip, 0x9,
2302 "card_type = %d, value_cb = 0x%x\n",
2303 card_type,
2304 value_cb ? value_cb :
Sherry Moore19397402008-09-22 16:30:26 -07002305 pcic_getcb(pcic, CB_STATUS_EVENT));
stevel3db86aa2006-06-29 14:43:12 -07002306 if (pcic_debug)
2307 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07002308 "\tchange on socket %d (%x)\n", i,
2309 value);
stevel3db86aa2006-06-29 14:43:12 -07002310#endif
2311 /* find out what happened */
2312 status = pcic_getb(pcic, i, PCIC_INTERFACE_STATUS);
2313
2314 /* acknowledge the interrupt */
2315 if (value_cb)
2316 pcic_putcb(pcic, CB_STATUS_EVENT, value_cb);
2317
2318 if (value)
2319 pcic_putb(pcic, i, PCIC_CARD_STATUS_CHANGE,
2320 value);
2321
2322 if (pcic->pc_callback == NULL) {
2323 /* if not callback handler, nothing to do */
2324 continue;
2325 }
2326
2327 /* Card Detect */
2328 if (value & PCIC_CD_DETECT ||
2329 value_cb & CB_PS_CCDMASK) {
2330 uint8_t irq;
2331#if defined(PCIC_DEBUG)
2332 if (pcic_debug)
2333 cmn_err(CE_CONT,
Sherry Moore19397402008-09-22 16:30:26 -07002334 "\tcd_detect: status=%x,"
2335 " flags=%x\n",
2336 status, sockp->pcs_flags);
stevel3db86aa2006-06-29 14:43:12 -07002337#else
2338#ifdef lint
2339 if (status == 0)
Sherry Moore19397402008-09-22 16:30:26 -07002340 status++;
stevel3db86aa2006-06-29 14:43:12 -07002341#endif
2342#endif
2343 /*
2344 * Turn off all interrupts for this socket here.
2345 */
2346 irq = pcic_getb(pcic, sockp->pcs_socket,
2347 PCIC_MANAGEMENT_INT);
2348 irq &= ~PCIC_CHANGE_MASK;
2349 pcic_putb(pcic, sockp->pcs_socket,
2350 PCIC_MANAGEMENT_INT, irq);
2351
2352 pcic_putcb(pcic, CB_STATUS_MASK, 0x0);
2353
rw1485610d282d12006-07-27 03:07:55 -07002354 /*
2355 * Put the socket in debouncing state so that
2356 * the leaf driver won't receive interrupts.
2357 * Crucial for handling surprise-removal.
2358 */
2359 sockp->pcs_flags |= PCS_DEBOUNCING;
2360
stevel3db86aa2006-06-29 14:43:12 -07002361 if (!sockp->pcs_cd_softint_flg) {
2362 sockp->pcs_cd_softint_flg = 1;
2363 (void) ddi_intr_trigger_softint(
2364 sockp->pcs_cd_softint_hdl, NULL);
2365 }
2366
2367 io_ints &= ~(1 << i);
2368 } /* PCIC_CD_DETECT */
2369
2370 /* Ready/Change Detect */
2371 sockp->pcs_state ^= SBM_RDYBSY;
2372 if (card_type == IF_MEMORY && value & PCIC_RD_DETECT) {
2373 sockp->pcs_flags |= PCS_READY;
2374 PC_CALLBACK(pcic->dip, x, PCE_CARD_READY, i);
2375 }
2376
2377 /* Battery Warn Detect */
2378 if (card_type == IF_MEMORY &&
2379 value & PCIC_BW_DETECT &&
2380 !(sockp->pcs_state & SBM_BVD2)) {
2381 sockp->pcs_state |= SBM_BVD2;
2382 PC_CALLBACK(pcic->dip, x,
Sherry Moore19397402008-09-22 16:30:26 -07002383 PCE_CARD_BATTERY_WARN, i);
stevel3db86aa2006-06-29 14:43:12 -07002384 }
2385
2386 /* Battery Dead Detect */
2387 if (value & PCIC_BD_DETECT) {
2388 /*
2389 * need to work out event if RI not enabled
2390 * and card_type == IF_IO
2391 */
2392 if (card_type == IF_MEMORY &&
Sherry Moore19397402008-09-22 16:30:26 -07002393 !(sockp->pcs_state & SBM_BVD1)) {
stevel3db86aa2006-06-29 14:43:12 -07002394 sockp->pcs_state |= SBM_BVD1;
2395 PC_CALLBACK(pcic->dip, x,