xref: /illumos-gate/usr/src/uts/common/io/1394/adapters/hci1394_attach.c (revision dd72704bd9e794056c558153663c739e2012d721)
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
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
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
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
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
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
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
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
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
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
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
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
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