1 /*
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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * hci1394_attach.c
28 * HBA attach() routine with associated funtions.
29 */
30
31 #include <sys/types.h>
32 #include <sys/kmem.h>
33 #include <sys/conf.h>
34 #include <sys/ddi.h>
35 #include <sys/modctl.h>
36 #include <sys/stat.h>
37 #include <sys/sunddi.h>
38 #include <sys/cmn_err.h>
39 #include <sys/pci.h>
40
41 #include <sys/1394/h1394.h>
42 #include <sys/1394/adapters/hci1394.h>
43 #include <sys/1394/adapters/hci1394_extern.h>
44
45
46 /*
47 * Attach State Information. These states are used to track the status of the
48 * attach. They are bit offsets.
49 */
50 #define STATE_ZALLOC 0
51 #define STATE_ISR_INIT 1
52 #define STATE_MINOR_NODE 2
53 #define STATE_HW_INIT 3
54 #define STATE_PHASE2 4
55 #define STATE_POWER_INIT 5
56 #define STATE_H1394_ATTACH 6
57 #define STATE_ISR_HANDLER 7
58 #define STATE_STARTUP 8
59
60 static void hci1394_statebit_set(uint64_t *state, uint_t statebit);
61 static boolean_t hci1394_statebit_tst(uint64_t state, uint_t statebit);
62
63 static void hci1394_cleanup(hci1394_state_t *soft_state, uint64_t attach_state);
64
65 static int hci1394_hardware_init(hci1394_state_t *soft_state);
66 static int hci1394_hardware_resume(hci1394_state_t *soft_state);
67
68 static int hci1394_pci_init(hci1394_state_t *soft_state);
69 static void hci1394_pci_resume(hci1394_state_t *soft_state);
70
71 static void hci1394_soft_state_phase1_init(hci1394_state_t *soft_state,
72 dev_info_t *dip, int instance);
73 static void hci1394_soft_state_phase2_init(hci1394_state_t *soft_state);
74
75 static int hci1394_resmap_get(hci1394_state_t *soft_state);
76 static void hci1394_resmap_free(hci1394_state_t *soft_state);
77
78
79
80 int
hci1394_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)81 hci1394_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
82 {
83 hci1394_state_t *soft_state;
84 uint64_t attach_state = 0;
85 int instance;
86 int status;
87
88 switch (cmd) {
89 case DDI_ATTACH:
90 instance = ddi_get_instance(dip);
91 status = ddi_soft_state_zalloc(hci1394_statep, instance);
92 if (status != DDI_SUCCESS) {
93 return (DDI_FAILURE);
94 }
95 soft_state = ddi_get_soft_state(hci1394_statep, instance);
96 if (soft_state == NULL) {
97 ddi_soft_state_free(hci1394_statep, instance);
98 return (DDI_FAILURE);
99 }
100 hci1394_statebit_set(&attach_state, STATE_ZALLOC);
101
102 hci1394_soft_state_phase1_init(soft_state, dip, instance);
103
104 /* get iblock cookie, other interrupt init stuff */
105 status = hci1394_isr_init(soft_state);
106 if (status != DDI_SUCCESS) {
107 hci1394_cleanup(soft_state, attach_state);
108 return (DDI_FAILURE);
109 }
110 hci1394_statebit_set(&attach_state, STATE_ISR_INIT);
111
112 status = ddi_create_minor_node(dip, "devctl", S_IFCHR,
113 instance, DDI_NT_NEXUS, 0);
114 if (status != DDI_SUCCESS) {
115 hci1394_cleanup(soft_state, attach_state);
116 return (DDI_FAILURE);
117 }
118 hci1394_statebit_set(&attach_state, STATE_MINOR_NODE);
119
120 status = hci1394_hardware_init(soft_state);
121 if (status != DDI_SUCCESS) {
122 hci1394_cleanup(soft_state, attach_state);
123 return (DDI_FAILURE);
124 }
125 hci1394_statebit_set(&attach_state, STATE_HW_INIT);
126
127 hci1394_soft_state_phase2_init(soft_state);
128 hci1394_statebit_set(&attach_state, STATE_PHASE2);
129
130 /* build up the reserved addresses map */
131 status = hci1394_resmap_get(soft_state);
132 if (status != DDI_SUCCESS) {
133 hci1394_cleanup(soft_state, attach_state);
134 return (DDI_FAILURE);
135 }
136
137 /* "attach" to the Services Layer */
138 status = h1394_attach(&soft_state->halinfo, DDI_ATTACH,
139 &soft_state->drvinfo.di_sl_private);
140 if (status != DDI_SUCCESS) {
141 hci1394_resmap_free(soft_state);
142 hci1394_cleanup(soft_state, attach_state);
143 return (DDI_FAILURE);
144 }
145 /* free the reserved addresses map */
146 hci1394_resmap_free(soft_state);
147
148 hci1394_statebit_set(&attach_state, STATE_H1394_ATTACH);
149 status = hci1394_isr_handler_init(soft_state);
150 if (status != DDI_SUCCESS) {
151 hci1394_cleanup(soft_state, attach_state);
152 return (DDI_FAILURE);
153 }
154 hci1394_statebit_set(&attach_state, STATE_ISR_HANDLER);
155
156 /* Report that driver was loaded */
157 ddi_report_dev(dip);
158
159 /*
160 * Turn on link, Reset Bus, enable interrupts. Should be the
161 * last routine called in attach. The statebit for starup must
162 * be set before startup is called since startup enables
163 * interrupts.
164 */
165 hci1394_statebit_set(&attach_state, STATE_STARTUP);
166 status = hci1394_ohci_startup(soft_state->ohci);
167 if (status != DDI_SUCCESS) {
168 hci1394_cleanup(soft_state, attach_state);
169 return (DDI_FAILURE);
170 }
171
172 return (DDI_SUCCESS);
173
174 case DDI_RESUME:
175 instance = ddi_get_instance(dip);
176 soft_state = ddi_get_soft_state(hci1394_statep, instance);
177 if (soft_state == NULL) {
178 return (DDI_FAILURE);
179 }
180
181 status = hci1394_hardware_resume(soft_state);
182 if (status != DDI_SUCCESS) {
183 return (DDI_FAILURE);
184 }
185
186 /*
187 * set our state back to initial. The next bus reset were
188 * about to generate will set us in motion.
189 */
190 soft_state->drvinfo.di_drvstate.ds_state = HCI1394_INITIAL;
191
192 /* turn on the link, enable interrupts, reset the bus */
193 status = hci1394_ohci_startup(soft_state->ohci);
194 if (status != DDI_SUCCESS) {
195 return (DDI_FAILURE);
196 }
197
198 /* tell the Services Layer that we are resuming */
199 status = h1394_attach(&soft_state->halinfo, DDI_RESUME,
200 &soft_state->drvinfo.di_sl_private);
201 if (status != DDI_SUCCESS) {
202 return (DDI_FAILURE);
203 }
204
205 return (DDI_SUCCESS);
206
207 default:
208 break;
209 }
210
211 return (DDI_FAILURE);
212 }
213
214
215 /*
216 * hci1394_soft_state_phase1_init()
217 * First part soft_state initialization. This should be called before any
218 * other initialization routines are called. Anything that requires cleanup
219 * on detach or after an attach failure should be setup in phase2 init (i.e.
220 * mutex's, cv's, etc.)
221 */
222 static void
hci1394_soft_state_phase1_init(hci1394_state_t * soft_state,dev_info_t * dip,int instance)223 hci1394_soft_state_phase1_init(hci1394_state_t *soft_state, dev_info_t *dip,
224 int instance)
225 {
226 ASSERT(soft_state != NULL);
227
228 soft_state->drvinfo.di_dip = dip;
229 soft_state->drvinfo.di_instance = instance;
230
231 /* current bus generation */
232 soft_state->drvinfo.di_gencnt = 0;
233
234 soft_state->drvinfo.di_sl_private = NULL;
235
236 /* initialize statistics */
237 soft_state->drvinfo.di_stats.st_bus_reset_count = 0;
238 soft_state->drvinfo.di_stats.st_selfid_count = 0;
239 soft_state->drvinfo.di_stats.st_phy_isr = 0;
240 soft_state->drvinfo.di_stats.st_phy_loop_err = 0;
241 soft_state->drvinfo.di_stats.st_phy_pwrfail_err = 0;
242 soft_state->drvinfo.di_stats.st_phy_timeout_err = 0;
243 soft_state->drvinfo.di_stats.st_phy_portevt_err = 0;
244
245 soft_state->swap_data = B_FALSE;
246 soft_state->sl_selfid_buf = NULL;
247
248 /* halinfo is what is passed up to the Services Layer */
249 soft_state->halinfo.hal_private = soft_state;
250 soft_state->halinfo.dip = soft_state->drvinfo.di_dip;
251 soft_state->halinfo.hal_events = hci1394_evts;
252 soft_state->halinfo.max_generation = OHCI_BUSGEN_MAX;
253 soft_state->halinfo.addr_map_num_entries = HCI1394_ADDR_MAP_SIZE;
254 soft_state->halinfo.addr_map = hci1394_addr_map;
255 hci1394_buf_attr_get(&soft_state->halinfo.dma_attr);
256 }
257
258
259 /*
260 * hci1394_soft_state_phase2_init()
261 * Second part of soft_state initialization. This should be called after a
262 * successful hardware_init() and before the call to h1394_attach().
263 */
264 static void
hci1394_soft_state_phase2_init(hci1394_state_t * soft_state)265 hci1394_soft_state_phase2_init(hci1394_state_t *soft_state)
266 {
267 ASSERT(soft_state != NULL);
268
269 /*
270 * Setup our initial driver state. This requires the HW iblock
271 * cookie so this must be setup in phase2_init()
272 */
273 soft_state->drvinfo.di_drvstate.ds_state = HCI1394_INITIAL;
274 mutex_init(&soft_state->drvinfo.di_drvstate.ds_mutex, NULL,
275 MUTEX_DRIVER, soft_state->drvinfo.di_iblock_cookie);
276
277 /*
278 * halinfo.acc_attr tells the services layer what our buffer access
279 * attributes are. drvinfo.di_buf_attr it initialized in pci_init so
280 * this must be setup in phase2_init()
281 */
282 soft_state->halinfo.acc_attr = soft_state->drvinfo.di_buf_attr;
283
284 /*
285 * halinfo.hw_interrupt tells the services layer what our
286 * iblock_cookie is. drvinfo.di_iblock_cookie is setup in isr_init so
287 * this must be setup in phase2_init()
288 */
289 soft_state->halinfo.hw_interrupt = soft_state->drvinfo.di_iblock_cookie;
290
291 /*
292 * Read in our node capabilities. Since we are calling into csr
293 * we must have first called hardware_init(). Therefore, this must
294 * be in phase2_init().
295 */
296 hci1394_csr_node_capabilities(soft_state->csr,
297 &soft_state->halinfo.node_capabilities);
298
299 /*
300 * Read in our bus capabilities. Since we are calling into ohci
301 * we must have first called hardware_init(). Therefore, this must
302 * be in phase2_init().
303 */
304 hci1394_ohci_bus_capabilities(soft_state->ohci,
305 &soft_state->halinfo.bus_capabilities);
306
307 /*
308 * Setup our async command overhead. When a target driver or the ARREQ
309 * engine allocates a command, the services layer will tack on space
310 * for itself and the HAL so we do not have to manage memory for every
311 * command. hal_overhead is how much memory the hal requires to track
312 * an async command. Since we are calling into async we must have first
313 * called hardware_init(). Therefore, this must be in phase2_init().
314 */
315 soft_state->halinfo.hal_overhead = hci1394_async_cmd_overhead();
316 }
317
318
319 /*
320 * hci1394_hardware_init()
321 * Initialize the adapter hardware. This should be called during
322 * the initial attach().
323 */
324 static int
hci1394_hardware_init(hci1394_state_t * soft_state)325 hci1394_hardware_init(hci1394_state_t *soft_state)
326 {
327 int status;
328
329
330 ASSERT(soft_state != NULL);
331
332 /* Initialize PCI config registers */
333 status = hci1394_pci_init(soft_state);
334 if (status != DDI_SUCCESS) {
335 return (DDI_FAILURE);
336 }
337
338 /* Initialize the OpenHCI Hardware */
339 status = hci1394_ohci_init(soft_state, &soft_state->drvinfo,
340 &soft_state->ohci);
341 if (status != DDI_SUCCESS) {
342 hci1394_pci_fini(soft_state);
343 return (DDI_FAILURE);
344 }
345
346 /* Initialize SW based CSR registers */
347 hci1394_csr_init(&soft_state->drvinfo, soft_state->ohci,
348 &soft_state->csr);
349
350 /* Initialize the Asynchronous Q's */
351 status = hci1394_async_init(&soft_state->drvinfo, soft_state->ohci,
352 soft_state->csr, &soft_state->async);
353 if (status != DDI_SUCCESS) {
354 hci1394_csr_fini(&soft_state->csr);
355 hci1394_ohci_fini(&soft_state->ohci);
356 hci1394_pci_fini(soft_state);
357 return (DDI_FAILURE);
358 }
359
360 /* Initialize the Isochronous logic */
361 hci1394_isoch_init(&soft_state->drvinfo, soft_state->ohci,
362 &soft_state->isoch);
363
364 /* Initialize any Vendor Specific Registers */
365 status = hci1394_vendor_init(&soft_state->drvinfo, soft_state->ohci,
366 &soft_state->vendor_info, &soft_state->vendor);
367 if (status != DDI_SUCCESS) {
368 hci1394_isoch_fini(&soft_state->isoch);
369 hci1394_async_fini(&soft_state->async);
370 hci1394_csr_fini(&soft_state->csr);
371 hci1394_ohci_fini(&soft_state->ohci);
372 hci1394_pci_fini(soft_state);
373 return (DDI_FAILURE);
374 }
375
376 return (DDI_SUCCESS);
377 }
378
379
380 /*
381 * hci1394_hardware_resume()
382 * Resume the adapter HW. This routine will be called during resume after
383 * a successful system suspend. All memory should be in the state it was
384 * before the suspend. All we have to do is re-setup the HW.
385 */
386 static int
hci1394_hardware_resume(hci1394_state_t * soft_state)387 hci1394_hardware_resume(hci1394_state_t *soft_state)
388 {
389 int status;
390
391
392 ASSERT(soft_state != NULL);
393
394 /* re-enable global byte swap (if we using it) */
395 hci1394_pci_resume(soft_state);
396
397 /* Re-init the OpenHCI HW */
398 status = hci1394_ohci_resume(soft_state->ohci);
399 if (status != DDI_SUCCESS) {
400 return (DDI_FAILURE);
401 }
402
403 /* re-setup our SW based CSR registers */
404 hci1394_csr_resume(soft_state->csr);
405
406 /* Re-setup the Async Q's */
407 status = hci1394_async_resume(soft_state->async);
408 if (status != DDI_SUCCESS) {
409 return (DDI_FAILURE);
410 }
411
412 /* Re-setup any Vendor Specific Registers */
413 status = hci1394_vendor_resume(soft_state->vendor);
414 if (status != DDI_SUCCESS) {
415 return (DDI_FAILURE);
416 }
417
418 return (DDI_SUCCESS);
419 }
420
421
422 /*
423 * hci1394_pci_init()
424 * Map in PCI config space and initialize PCI config space registers.
425 */
426 static int
hci1394_pci_init(hci1394_state_t * soft_state)427 hci1394_pci_init(hci1394_state_t *soft_state)
428 {
429 int status;
430 #ifndef _LITTLE_ENDIAN
431 uint32_t global_swap;
432 #endif
433
434
435 ASSERT(soft_state != NULL);
436
437 /* Setup PCI configuration space */
438 status = pci_config_setup(soft_state->drvinfo.di_dip,
439 &soft_state->pci_config);
440 if (status != DDI_SUCCESS) {
441 return (DDI_FAILURE);
442 }
443
444
445 #ifdef _LITTLE_ENDIAN
446 /* Start of little endian specific code */
447 soft_state->drvinfo.di_reg_attr.devacc_attr_version =
448 DDI_DEVICE_ATTR_V0;
449 soft_state->drvinfo.di_reg_attr.devacc_attr_endian_flags =
450 DDI_STRUCTURE_LE_ACC;
451 soft_state->drvinfo.di_reg_attr.devacc_attr_dataorder =
452 DDI_STRICTORDER_ACC;
453 soft_state->drvinfo.di_buf_attr.devacc_attr_version =
454 DDI_DEVICE_ATTR_V0;
455 soft_state->drvinfo.di_buf_attr.devacc_attr_endian_flags =
456 DDI_STRUCTURE_LE_ACC;
457 soft_state->drvinfo.di_buf_attr.devacc_attr_dataorder =
458 DDI_STRICTORDER_ACC;
459 soft_state->swap_data = B_TRUE;
460 /* End of little endian specific code */
461 #else
462 /* Start of big endian specific code */
463 /* If PCI_Global_Swap bit is not set, try to set it */
464 global_swap = pci_config_get32(soft_state->pci_config,
465 OHCI_PCI_HCI_CONTROL_REG);
466
467 /* Lets see if the global byte swap feature is supported */
468 if ((global_swap & OHCI_PCI_GLOBAL_SWAP) == 0) {
469 global_swap = global_swap | OHCI_PCI_GLOBAL_SWAP;
470 pci_config_put32(soft_state->pci_config,
471 OHCI_PCI_HCI_CONTROL_REG, global_swap);
472 }
473
474 global_swap = pci_config_get32(soft_state->pci_config,
475 OHCI_PCI_HCI_CONTROL_REG);
476
477 /* If PCI_Global_Swap bit is not set, it is unsupported */
478 if ((global_swap & OHCI_PCI_GLOBAL_SWAP) == 0) {
479 soft_state->drvinfo.di_reg_attr.devacc_attr_version =
480 DDI_DEVICE_ATTR_V0;
481 soft_state->drvinfo.di_reg_attr.devacc_attr_endian_flags =
482 DDI_STRUCTURE_LE_ACC;
483 soft_state->drvinfo.di_reg_attr.devacc_attr_dataorder =
484 DDI_STRICTORDER_ACC;
485 soft_state->drvinfo.di_buf_attr.devacc_attr_version =
486 DDI_DEVICE_ATTR_V0;
487 soft_state->drvinfo.di_buf_attr.devacc_attr_endian_flags =
488 DDI_STRUCTURE_LE_ACC;
489 soft_state->drvinfo.di_buf_attr.devacc_attr_dataorder =
490 DDI_STRICTORDER_ACC;
491 soft_state->swap_data = B_TRUE;
492 /*
493 * global byte swap is supported. This should be the case
494 * for almost all of the adapters.
495 */
496 } else {
497 soft_state->drvinfo.di_reg_attr.devacc_attr_version =
498 DDI_DEVICE_ATTR_V0;
499 soft_state->drvinfo.di_reg_attr.devacc_attr_endian_flags =
500 DDI_STRUCTURE_BE_ACC;
501 soft_state->drvinfo.di_reg_attr.devacc_attr_dataorder =
502 DDI_STRICTORDER_ACC;
503 soft_state->drvinfo.di_buf_attr.devacc_attr_version =
504 DDI_DEVICE_ATTR_V0;
505 soft_state->drvinfo.di_buf_attr.devacc_attr_endian_flags =
506 DDI_STRUCTURE_BE_ACC;
507 soft_state->drvinfo.di_buf_attr.devacc_attr_dataorder =
508 DDI_STRICTORDER_ACC;
509 soft_state->swap_data = B_FALSE;
510 }
511 /* End of big endian specific code */
512 #endif
513
514 /* read in vendor Information */
515 soft_state->vendor_info.vendor_id =
516 (uint_t)pci_config_get16(soft_state->pci_config, PCI_CONF_VENID);
517 soft_state->vendor_info.device_id =
518 (uint_t)pci_config_get16(soft_state->pci_config, PCI_CONF_DEVID);
519 soft_state->vendor_info.revision_id =
520 (uint_t)pci_config_get8(soft_state->pci_config, PCI_CONF_REVID);
521
522 return (DDI_SUCCESS);
523 }
524
525
526 /*
527 * hci1394_pci_resume()
528 * Re-Initialize PCI config space registers during a resume.
529 */
530 /* ARGSUSED */
531 static void
hci1394_pci_resume(hci1394_state_t * soft_state)532 hci1394_pci_resume(hci1394_state_t *soft_state)
533 {
534 #ifndef _LITTLE_ENDIAN
535 uint32_t global_swap;
536 #endif
537
538
539 ASSERT(soft_state != NULL);
540
541 #ifdef _LITTLE_ENDIAN
542 /* Start of little endian specific code */
543 /* nothing to do here yet. Maybe later?? */
544 /* End of little endian specific code */
545 #else
546 /* Start of big endian specific code */
547 /* If PCI_Global_Swap bit is not set, try to set it */
548 global_swap = pci_config_get32(soft_state->pci_config,
549 OHCI_PCI_HCI_CONTROL_REG);
550 /* Try and set GlobalByteSwap */
551 if ((global_swap & OHCI_PCI_GLOBAL_SWAP) == 0) {
552 global_swap = global_swap | OHCI_PCI_GLOBAL_SWAP;
553 pci_config_put32(soft_state->pci_config,
554 OHCI_PCI_HCI_CONTROL_REG, global_swap);
555 }
556 /* End of big endian specific code */
557 #endif
558 }
559
560
561 /*
562 * hci1394_resmap_get()
563 * Look for adapter property "reserved-addresses". This property is used to
564 * reserve 1394 address space so that it will not randomly be given to a
565 * target driver during a 1394 address space alloc. Some protocols hard
566 * code addresses which make us do this. The target driver must specifically
567 * ask for these addresses. This routine should be called before the
568 * call to h1394_attach().
569 */
570 static int
hci1394_resmap_get(hci1394_state_t * soft_state)571 hci1394_resmap_get(hci1394_state_t *soft_state)
572 {
573 h1394_addr_map_t *resv_map;
574 int resv_num;
575 int status;
576 int reslen;
577 uint32_t *resptr;
578 int rescnt;
579 int mapcnt;
580
581
582 ASSERT(soft_state != NULL);
583
584 /*
585 * See if the "reserved-addresses" property is defined. The format
586 * should be:
587 *
588 * reserved-addresses= 0x0000ffff,0xf0000B00,0x200,
589 * 0x0000ffff,0xf0000D00,0x200,
590 * 0x0000ffff,0xf0000234,0x4;
591 * You can have multiple reserved addresses. Each reserved address
592 * takes up 3 integers.
593 * MSWofAddr,LSWofAddr,ByteCount
594 */
595 status = ddi_prop_lookup_int_array(DDI_DEV_T_ANY,
596 soft_state->drvinfo.di_dip, DDI_PROP_DONTPASS, "reserved-addresses",
597 (int **)&resptr, (uint_t *)&reslen);
598 if (status != DDI_PROP_SUCCESS) {
599 /* the property is not defined, 0 reserved addresses */
600 soft_state->halinfo.resv_map_num_entries = 0;
601 soft_state->halinfo.resv_map = NULL;
602 return (DDI_SUCCESS);
603 } else if ((reslen < 3) || ((reslen % 3) != 0)) {
604 /*
605 * the property is defined but the correct number of integers
606 * is not present.
607 */
608 resv_num = 0;
609 resv_map = NULL;
610 cmn_err(CE_NOTE, "!%s(%d): Invalid reserved-addresses property."
611 " Property ignored", ddi_node_name(
612 soft_state->drvinfo.di_dip), ddi_get_instance(
613 soft_state->drvinfo.di_dip));
614 } else {
615 /* the property is defined. Alloc space to copy data into */
616 resv_num = reslen / 3;
617 resv_map = kmem_alloc((sizeof (h1394_addr_map_t) * (resv_num)),
618 KM_SLEEP);
619
620 /* read in the address, length, and set the type to reserved */
621 rescnt = 0;
622 mapcnt = 0;
623 while (rescnt < reslen) {
624 resv_map[mapcnt].address =
625 (uint64_t)resptr[rescnt] << 32;
626 rescnt++;
627 resv_map[mapcnt].address |= (uint64_t)resptr[rescnt];
628 rescnt++;
629 resv_map[mapcnt].length = (uint64_t)resptr[rescnt];
630 rescnt++;
631 resv_map[mapcnt].addr_type = H1394_ADDR_RESERVED;
632 mapcnt++;
633 }
634 }
635
636 ddi_prop_free(resptr);
637
638 /*
639 * copy the number of reserved address ranges and a pointer to the map
640 * into halinfo so we can tell the services layer about them in
641 * h1394_attach()
642 */
643 soft_state->halinfo.resv_map_num_entries = resv_num;
644 soft_state->halinfo.resv_map = resv_map;
645
646 return (DDI_SUCCESS);
647 }
648
649
650 /*
651 * hci1394_resmap_free()
652 * Free up the space alloced in hci1394_resmap_get(). This routine should
653 * be called after h1394_attach(). The HAL does not need this information
654 * and the services layer only uses it for a calculation during attach and
655 * should not refer to the pointer after it returns from h1394_attach().
656 */
657 static void
hci1394_resmap_free(hci1394_state_t * soft_state)658 hci1394_resmap_free(hci1394_state_t *soft_state)
659 {
660 ASSERT(soft_state != NULL);
661
662 /*
663 * if we have one or more reserved map entries, free up the space that
664 * was allocated to store them
665 */
666 if (soft_state->halinfo.resv_map_num_entries > 0) {
667 ASSERT(soft_state->halinfo.resv_map != NULL);
668 kmem_free(soft_state->halinfo.resv_map,
669 (sizeof (h1394_addr_map_t) *
670 soft_state->halinfo.resv_map_num_entries));
671 }
672 }
673
674
675 /*
676 * hci1394_statebit_set()
677 * Set bit "statebit" in "state"
678 */
679 static void
hci1394_statebit_set(uint64_t * state,uint_t statebit)680 hci1394_statebit_set(uint64_t *state, uint_t statebit)
681 {
682 ASSERT(state != NULL);
683 ASSERT(statebit < 64);
684 *state |= (uint64_t)0x1 << statebit;
685 }
686
687
688 /*
689 * hci1394_statebit_tst()
690 * Return status of bit "statebit". Is it set or not?
691 */
692 static boolean_t
hci1394_statebit_tst(uint64_t state,uint_t statebit)693 hci1394_statebit_tst(uint64_t state, uint_t statebit)
694 {
695 uint64_t bitset;
696 int status;
697
698
699 ASSERT(statebit < 64);
700 bitset = state & ((uint64_t)0x1 << statebit);
701 if (bitset == 0) {
702 status = B_FALSE;
703 } else {
704 status = B_TRUE;
705 }
706 return (status);
707 }
708
709
710 /*
711 * hci1394_cleanup()
712 * Cleanup after a failed attach
713 */
714 static void
hci1394_cleanup(hci1394_state_t * soft_state,uint64_t attach_state)715 hci1394_cleanup(hci1394_state_t *soft_state, uint64_t attach_state)
716 {
717 int status;
718
719
720 ASSERT(soft_state != NULL);
721
722 status = hci1394_statebit_tst(attach_state, STATE_STARTUP);
723 if (status == B_TRUE) {
724 /* Don't allow the HW to generate any more interrupts */
725 hci1394_ohci_intr_master_disable(soft_state->ohci);
726
727 /* don't accept anymore commands from services layer */
728 (void) hci1394_state_set(&soft_state->drvinfo,
729 HCI1394_SHUTDOWN);
730
731 /* Reset the chip */
732 (void) hci1394_ohci_soft_reset(soft_state->ohci);
733
734 /* Flush out async DMA Q's (cancels pendingQ timeouts too) */
735 hci1394_async_flush(soft_state->async);
736 }
737
738 status = hci1394_statebit_tst(attach_state, STATE_ISR_HANDLER);
739 if (status == B_TRUE) {
740 hci1394_isr_handler_fini(soft_state);
741 }
742
743 status = hci1394_statebit_tst(attach_state, STATE_H1394_ATTACH);
744 if (status == B_TRUE) {
745 (void) h1394_detach(&soft_state->drvinfo.di_sl_private,
746 DDI_DETACH);
747 }
748
749 status = hci1394_statebit_tst(attach_state, STATE_HW_INIT);
750 if (status == B_TRUE) {
751 hci1394_detach_hardware(soft_state);
752 }
753
754 status = hci1394_statebit_tst(attach_state, STATE_MINOR_NODE);
755 if (status == B_TRUE) {
756 ddi_remove_minor_node(soft_state->drvinfo.di_dip, "devctl");
757 }
758
759 status = hci1394_statebit_tst(attach_state, STATE_ISR_INIT);
760 if (status == B_TRUE) {
761 hci1394_isr_fini(soft_state);
762 }
763
764 status = hci1394_statebit_tst(attach_state, STATE_PHASE2);
765 if (status == B_TRUE) {
766 hci1394_soft_state_fini(soft_state);
767 }
768
769 status = hci1394_statebit_tst(attach_state, STATE_ZALLOC);
770 if (status == B_TRUE) {
771 ddi_soft_state_free(hci1394_statep,
772 soft_state->drvinfo.di_instance);
773 }
774 }
775