xref: /illumos-gate/usr/src/uts/common/io/1394/s1394_csr.c (revision 2570281c)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 /*
28  * s1394_csr.c
29  *    1394 Services Layer CSR and Config ROM Routines
30  *    Contains all of the CSR callback routines for various required
31  *    CSR registers.  Also contains routines for their initialization
32  *    and destruction, as well as routines to handle the processing
33  *    of Config ROM update requests.
34  */
35 
36 #include <sys/conf.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/types.h>
40 #include <sys/kmem.h>
41 #include <sys/1394/t1394.h>
42 #include <sys/1394/s1394.h>
43 #include <sys/1394/h1394.h>
44 #include <sys/1394/ieee1394.h>
45 #include <sys/1394/ieee1212.h>
46 
47 static void s1394_CSR_state_clear(cmd1394_cmd_t *req);
48 
49 static void s1394_CSR_state_set(cmd1394_cmd_t *req);
50 
51 static void s1394_CSR_node_ids(cmd1394_cmd_t *req);
52 
53 static void s1394_CSR_reset_start(cmd1394_cmd_t *req);
54 
55 static void s1394_CSR_split_timeout(cmd1394_cmd_t *req);
56 
57 static void s1394_CSR_argument_regs(cmd1394_cmd_t *req);
58 
59 static void s1394_CSR_test_regs(cmd1394_cmd_t *req);
60 
61 static void s1394_CSR_interrupt_regs(cmd1394_cmd_t *req);
62 
63 static void s1394_CSR_clock_regs(cmd1394_cmd_t *req);
64 
65 static void s1394_CSR_message_regs(cmd1394_cmd_t *req);
66 
67 static void s1394_CSR_cycle_time(cmd1394_cmd_t *req);
68 
69 static void s1394_CSR_bus_time(cmd1394_cmd_t *req);
70 
71 static void s1394_CSR_busy_timeout(cmd1394_cmd_t *req);
72 
73 static void s1394_CSR_IRM_regs(cmd1394_cmd_t *req);
74 
75 static void s1394_CSR_topology_map(cmd1394_cmd_t *req);
76 
77 static void s1394_common_CSR_routine(s1394_hal_t *hal, cmd1394_cmd_t *req);
78 
79 static int s1394_init_config_rom_structures(s1394_hal_t *hal);
80 
81 static int s1394_destroy_config_rom_structures(s1394_hal_t *hal);
82 
83 /*
84  * s1394_setup_CSR_space()
85  *    setups up the local host's CSR registers and callback routines.
86  */
87 int
s1394_setup_CSR_space(s1394_hal_t * hal)88 s1394_setup_CSR_space(s1394_hal_t *hal)
89 {
90 	s1394_addr_space_blk_t	*curr_blk;
91 	t1394_alloc_addr_t	addr;
92 	t1394_addr_enable_t	rw_flags;
93 	int			result;
94 
95 	/*
96 	 * Although they are not freed up in this routine, if
97 	 * one of the s1394_claim_addr_blk() routines fails,
98 	 * all of the previously successful claims will be
99 	 * freed up in s1394_destroy_addr_space() upon returning
100 	 * DDI_FAILURE from this routine.
101 	 */
102 
103 	rw_flags = T1394_ADDR_RDENBL | T1394_ADDR_WRENBL;
104 
105 	/*
106 	 * STATE_CLEAR
107 	 *    see IEEE 1394-1995, Section 8.3.2.2.1 or
108 	 *    IEEE 1212-1994, Section 7.4.1
109 	 */
110 	addr.aa_address	= IEEE1394_CSR_STATE_CLEAR;
111 	addr.aa_length	= IEEE1394_QUADLET;
112 	addr.aa_enable	= rw_flags;
113 	addr.aa_type	= T1394_ADDR_FIXED;
114 	addr.aa_evts.recv_read_request	= s1394_CSR_state_clear;
115 	addr.aa_evts.recv_write_request	= s1394_CSR_state_clear;
116 	addr.aa_evts.recv_lock_request	= NULL;
117 	addr.aa_kmem_bufp = NULL;
118 	addr.aa_arg	  = hal;
119 	result = s1394_claim_addr_blk(hal, &addr);
120 	if (result != DDI_SUCCESS) {
121 		return (DDI_FAILURE);
122 	}
123 
124 	/*
125 	 * STATE_SET
126 	 *    see IEEE 1394-1995, Section 8.3.2.2.2 or
127 	 *    IEEE 1212-1994, Section 7.4.2
128 	 */
129 	addr.aa_address	= IEEE1394_CSR_STATE_SET;
130 	addr.aa_length	= IEEE1394_QUADLET;
131 	addr.aa_enable	= T1394_ADDR_WRENBL;
132 	addr.aa_type	= T1394_ADDR_FIXED;
133 	addr.aa_evts.recv_read_request	= NULL;
134 	addr.aa_evts.recv_write_request	= s1394_CSR_state_set;
135 	addr.aa_evts.recv_lock_request	= NULL;
136 	addr.aa_kmem_bufp = NULL;
137 	addr.aa_arg	  = hal;
138 	result = s1394_claim_addr_blk(hal, &addr);
139 	if (result != DDI_SUCCESS) {
140 		return (DDI_FAILURE);
141 	}
142 
143 	/*
144 	 * NODE_IDS
145 	 *    see IEEE 1394-1995, Section 8.3.2.2.3 or
146 	 *    IEEE 1212-1994, Section 7.4.3
147 	 */
148 	addr.aa_address	= IEEE1394_CSR_NODE_IDS;
149 	addr.aa_length	= IEEE1394_QUADLET;
150 	addr.aa_enable	= rw_flags;
151 	addr.aa_type	= T1394_ADDR_FIXED;
152 	addr.aa_evts.recv_read_request	= s1394_CSR_node_ids;
153 	addr.aa_evts.recv_write_request = s1394_CSR_node_ids;
154 	addr.aa_evts.recv_lock_request	= NULL;
155 	addr.aa_kmem_bufp = NULL;
156 	addr.aa_arg	  = hal;
157 	result = s1394_claim_addr_blk(hal, &addr);
158 	if (result != DDI_SUCCESS) {
159 		return (DDI_FAILURE);
160 	}
161 
162 	/*
163 	 * RESET_START
164 	 *    see IEEE 1394-1995, Section 8.3.2.2.4 or
165 	 *    IEEE 1212-1994, Section 7.4.4
166 	 */
167 	addr.aa_address	= IEEE1394_CSR_RESET_START;
168 	addr.aa_length	= IEEE1394_QUADLET;
169 	addr.aa_enable	= T1394_ADDR_WRENBL;
170 	addr.aa_type	= T1394_ADDR_FIXED;
171 	addr.aa_evts.recv_read_request	= NULL;
172 	addr.aa_evts.recv_write_request	= s1394_CSR_reset_start;
173 	addr.aa_evts.recv_lock_request	= NULL;
174 	addr.aa_kmem_bufp = NULL;
175 	addr.aa_arg	  = hal;
176 	result = s1394_claim_addr_blk(hal, &addr);
177 	if (result != DDI_SUCCESS) {
178 		return (DDI_FAILURE);
179 	}
180 
181 	/*
182 	 * SPLIT_TIMEOUT
183 	 *    see IEEE 1394-1995, Section 8.3.2.2.6 or
184 	 *    IEEE 1212-1994, Section 7.4.7
185 	 */
186 	addr.aa_address	= IEEE1394_CSR_SPLIT_TIMEOUT_HI;
187 	addr.aa_length	= IEEE1394_OCTLET;
188 	addr.aa_enable	= rw_flags;
189 	addr.aa_type = T1394_ADDR_FIXED;
190 	addr.aa_evts.recv_read_request	= s1394_CSR_split_timeout;
191 	addr.aa_evts.recv_write_request	= s1394_CSR_split_timeout;
192 	addr.aa_evts.recv_lock_request	= NULL;
193 	addr.aa_kmem_bufp = NULL;
194 	addr.aa_arg	  = hal;
195 	result = s1394_claim_addr_blk(hal, &addr);
196 	if (result != DDI_SUCCESS) {
197 		return (DDI_FAILURE);
198 	}
199 
200 	/*
201 	 * ARGUMENT_HI and ARGUMENT_LO
202 	 *    see IEEE 1394-1995, Section 8.3.2.2.7 or
203 	 *    IEEE 1212-1994, Section 7.4.8
204 	 */
205 	addr.aa_address	= IEEE1394_CSR_ARG_HI;
206 	addr.aa_length	= 2 * (IEEE1394_QUADLET);
207 	addr.aa_enable	= rw_flags;
208 	addr.aa_type	= T1394_ADDR_FIXED;
209 	addr.aa_evts.recv_read_request	= s1394_CSR_argument_regs;
210 	addr.aa_evts.recv_write_request	= s1394_CSR_argument_regs;
211 	addr.aa_evts.recv_lock_request	= NULL;
212 	addr.aa_kmem_bufp = NULL;
213 	addr.aa_arg	  = hal;
214 	result = s1394_claim_addr_blk(hal, &addr);
215 	if (result != DDI_SUCCESS) {
216 		return (DDI_FAILURE);
217 	}
218 
219 	/*
220 	 * TEST_START and TEST_STATUS
221 	 *    see IEEE 1394-1995, Section 8.3.2.2.7 or
222 	 *    IEEE 1212-1994, Section 7.4.9 - 7.4.10
223 	 */
224 	addr.aa_address	= IEEE1394_CSR_TEST_START;
225 	addr.aa_length	= 2 * (IEEE1394_QUADLET);
226 	addr.aa_enable	= rw_flags;
227 	addr.aa_type	= T1394_ADDR_FIXED;
228 	addr.aa_evts.recv_read_request	= s1394_CSR_test_regs;
229 	addr.aa_evts.recv_write_request	= s1394_CSR_test_regs;
230 	addr.aa_evts.recv_lock_request	= NULL;
231 	addr.aa_kmem_bufp = NULL;
232 	addr.aa_arg	  = hal;
233 	result = s1394_claim_addr_blk(hal, &addr);
234 	if (result != DDI_SUCCESS) {
235 		return (DDI_FAILURE);
236 	}
237 
238 	/*
239 	 * INTERRUPT_TARGET and INTERRUPT_MASK
240 	 *    see IEEE 1394-1995, Section 8.3.2.2.9 or
241 	 *    IEEE 1212-1994, Section 7.4.15 - 7.4.16
242 	 */
243 	addr.aa_address	= IEEE1394_CSR_INTERRUPT_TARGET;
244 	addr.aa_length	= 2 * (IEEE1394_QUADLET);
245 	addr.aa_enable	= rw_flags;
246 	addr.aa_type	= T1394_ADDR_FIXED;
247 	addr.aa_evts.recv_read_request	= s1394_CSR_interrupt_regs;
248 	addr.aa_evts.recv_write_request	= s1394_CSR_interrupt_regs;
249 	addr.aa_evts.recv_lock_request	= NULL;
250 	addr.aa_kmem_bufp = NULL;
251 	addr.aa_arg	  = hal;
252 	result = s1394_claim_addr_blk(hal, &addr);
253 	if (result != DDI_SUCCESS) {
254 		return (DDI_FAILURE);
255 	}
256 
257 	/*
258 	 * CLOCK_VALUE, CLOCK_TICK_PERIOD, CLOCK_INFO, etc.
259 	 *    see IEEE 1394-1995, Section 8.3.2.2.10 or
260 	 *    IEEE 1212-1994, Section 7.4.17 - 7.4.20
261 	 */
262 	addr.aa_address	= IEEE1394_CSR_CLOCK_VALUE;
263 	addr.aa_length	= IEEE1394_CSR_CLOCK_VALUE_SZ;
264 	addr.aa_enable	= rw_flags;
265 	addr.aa_type	= T1394_ADDR_FIXED;
266 	addr.aa_evts.recv_read_request	= s1394_CSR_clock_regs;
267 	addr.aa_evts.recv_write_request	= s1394_CSR_clock_regs;
268 	addr.aa_evts.recv_lock_request	= NULL;
269 	addr.aa_kmem_bufp = NULL;
270 	addr.aa_arg	  = hal;
271 	result = s1394_claim_addr_blk(hal, &addr);
272 	if (result != DDI_SUCCESS) {
273 		return (DDI_FAILURE);
274 	}
275 
276 	/*
277 	 * MESSAGE_REQUEST and MESSAGE_RESPONSE
278 	 *    see IEEE 1394-1995, Section 8.3.2.2.11 or
279 	 *    IEEE 1212-1994, Section 7.4.21
280 	 */
281 	addr.aa_address	= IEEE1394_CSR_MESSAGE_REQUEST;
282 	addr.aa_length	= IEEE1394_CSR_MESSAGE_REQUEST_SZ;
283 	addr.aa_enable	= rw_flags;
284 	addr.aa_type	= T1394_ADDR_FIXED;
285 	addr.aa_evts.recv_read_request	= s1394_CSR_message_regs;
286 	addr.aa_evts.recv_write_request	= s1394_CSR_message_regs;
287 	addr.aa_evts.recv_lock_request	= NULL;
288 	addr.aa_kmem_bufp = NULL;
289 	addr.aa_arg	  = hal;
290 	result = s1394_claim_addr_blk(hal, &addr);
291 	if (result != DDI_SUCCESS) {
292 		return (DDI_FAILURE);
293 	}
294 
295 	/*
296 	 * CYCLE_TIME
297 	 *    see IEEE 1394-1995, Section 8.3.2.3.1
298 	 */
299 	addr.aa_address	= IEEE1394_SCSR_CYCLE_TIME;
300 	addr.aa_length	= IEEE1394_QUADLET;
301 	addr.aa_enable	= rw_flags;
302 	addr.aa_type	= T1394_ADDR_FIXED;
303 	addr.aa_evts.recv_read_request	= s1394_CSR_cycle_time;
304 	addr.aa_evts.recv_write_request	= s1394_CSR_cycle_time;
305 	addr.aa_evts.recv_lock_request	= NULL;
306 	addr.aa_kmem_bufp = NULL;
307 	addr.aa_arg	  = hal;
308 	result = s1394_claim_addr_blk(hal, &addr);
309 	if (result != DDI_SUCCESS) {
310 		return (DDI_FAILURE);
311 	}
312 
313 	/*
314 	 * BUS_TIME
315 	 *    see IEEE 1394-1995, Section 8.3.2.3.2
316 	 */
317 	addr.aa_address = IEEE1394_SCSR_BUS_TIME;
318 	addr.aa_length	= IEEE1394_QUADLET;
319 	addr.aa_enable	= rw_flags;
320 	addr.aa_type	= T1394_ADDR_FIXED;
321 	addr.aa_evts.recv_read_request	= s1394_CSR_bus_time;
322 	addr.aa_evts.recv_write_request	= s1394_CSR_bus_time;
323 	addr.aa_evts.recv_lock_request	= NULL;
324 	addr.aa_kmem_bufp = NULL;
325 	addr.aa_arg	  = hal;
326 	result = s1394_claim_addr_blk(hal, &addr);
327 	if (result != DDI_SUCCESS) {
328 		return (DDI_FAILURE);
329 	}
330 
331 	/*
332 	 * BUSY_TIMEOUT
333 	 *    see IEEE 1394-1995, Section 8.3.2.3.5
334 	 */
335 	addr.aa_address	= IEEE1394_SCSR_BUSY_TIMEOUT;
336 	addr.aa_length	= IEEE1394_QUADLET;
337 	addr.aa_enable	= rw_flags;
338 	addr.aa_type	= T1394_ADDR_FIXED;
339 	addr.aa_evts.recv_read_request	= s1394_CSR_busy_timeout;
340 	addr.aa_evts.recv_write_request	= s1394_CSR_busy_timeout;
341 	addr.aa_evts.recv_lock_request	= NULL;
342 	addr.aa_kmem_bufp = NULL;
343 	addr.aa_arg	  = hal;
344 	result = s1394_claim_addr_blk(hal, &addr);
345 	if (result != DDI_SUCCESS) {
346 		return (DDI_FAILURE);
347 	}
348 
349 	/*
350 	 * BUS_MANAGER_ID
351 	 * BANDWIDTH_AVAILABLE
352 	 * CHANNELS_AVAILABLE
353 	 *    see IEEE 1394-1995, Section 8.3.2.3.6 - 8.3.2.3.8
354 	 */
355 	addr.aa_address	= IEEE1394_SCSR_BUSMGR_ID;
356 	addr.aa_length	= 3 * (IEEE1394_QUADLET);
357 	addr.aa_enable	= T1394_ADDR_RDENBL | T1394_ADDR_LKENBL;
358 	addr.aa_type	= T1394_ADDR_FIXED;
359 	addr.aa_evts.recv_read_request	= s1394_CSR_IRM_regs;
360 	addr.aa_evts.recv_write_request	= NULL;
361 	addr.aa_evts.recv_lock_request	= s1394_CSR_IRM_regs;
362 	addr.aa_kmem_bufp = NULL;
363 	addr.aa_arg	  = hal;
364 	result = s1394_claim_addr_blk(hal, &addr);
365 	if (result != DDI_SUCCESS) {
366 		return (DDI_FAILURE);
367 	}
368 
369 	/*
370 	 * Reserved for Configuration ROM
371 	 *    see IEEE 1394-1995, Section 8.3.2.5.3
372 	 */
373 	addr.aa_address	= IEEE1394_CONFIG_ROM_ADDR;
374 	addr.aa_length	= IEEE1394_CONFIG_ROM_SZ;
375 	result = s1394_reserve_addr_blk(hal, &addr);
376 	if (result != DDI_SUCCESS) {
377 		return (DDI_FAILURE);
378 	}
379 
380 	/*
381 	 * TOPOLOGY_MAP
382 	 *    see IEEE 1394-1995, Section 8.3.2.4.1
383 	 */
384 	hal->CSR_topology_map = kmem_zalloc(IEEE1394_UCSR_TOPOLOGY_MAP_SZ,
385 	    KM_SLEEP);
386 	addr.aa_address	= IEEE1394_UCSR_TOPOLOGY_MAP;
387 	addr.aa_length	= IEEE1394_UCSR_TOPOLOGY_MAP_SZ;
388 	addr.aa_enable	= T1394_ADDR_RDENBL;
389 	addr.aa_type	= T1394_ADDR_FIXED;
390 	addr.aa_evts.recv_read_request	= s1394_CSR_topology_map;
391 	addr.aa_evts.recv_write_request	= NULL;
392 	addr.aa_evts.recv_lock_request	= NULL;
393 	addr.aa_kmem_bufp = (caddr_t)hal->CSR_topology_map;
394 	addr.aa_arg	  = hal;
395 	result = s1394_claim_addr_blk(hal, &addr);
396 	if (result != DDI_SUCCESS) {
397 		kmem_free((void *)hal->CSR_topology_map,
398 		    IEEE1394_UCSR_TOPOLOGY_MAP_SZ);
399 		return (DDI_FAILURE);
400 	}
401 	curr_blk = (s1394_addr_space_blk_t *)(addr.aa_hdl);
402 	/* Set up the block so that we free kmem_bufp at detach */
403 	curr_blk->free_kmem_bufp = B_TRUE;
404 
405 	/*
406 	 * Reserve the SPEED_MAP
407 	 *    see IEEE 1394-1995, Section 8.3.2.4.1
408 	 *    (obsoleted in P1394A)
409 	 */
410 	addr.aa_address	= IEEE1394_UCSR_SPEED_MAP;
411 	addr.aa_length	= IEEE1394_UCSR_SPEED_MAP_SZ;
412 	result = s1394_reserve_addr_blk(hal, &addr);
413 	if (result != DDI_SUCCESS) {
414 		return (DDI_FAILURE);
415 	}
416 
417 	/*
418 	 * Reserved - Boundary between reserved Serial Bus
419 	 * dependent registers and other CSR register space.
420 	 * See IEEE 1394-1995, Table 8-4 for this address.
421 	 *
422 	 * This quadlet is reserved as a way of preventing
423 	 * the inadvertant allocation of a part of CSR space
424 	 * that will likely be used by future specifications
425 	 */
426 	addr.aa_address	= IEEE1394_UCSR_RESERVED_BOUNDARY;
427 	addr.aa_length	= IEEE1394_QUADLET;
428 	result = s1394_reserve_addr_blk(hal, &addr);
429 	if (result != DDI_SUCCESS) {
430 		return (DDI_FAILURE);
431 	}
432 
433 	return (DDI_SUCCESS);
434 }
435 
436 /*
437  * s1394_CSR_state_clear()
438  *    handles all requests to the STATE_CLEAR CSR register.  It enforces
439  *    that certain bits that can be twiddled only by a given node (IRM or
440  *    Bus Manager).
441  */
442 static void
s1394_CSR_state_clear(cmd1394_cmd_t * req)443 s1394_CSR_state_clear(cmd1394_cmd_t *req)
444 {
445 	s1394_hal_t	*hal;
446 	uint32_t	data;
447 	uint_t		offset;
448 	uint_t		is_from;
449 	uint_t		should_be_from;
450 	int		result;
451 
452 	hal = (s1394_hal_t *)req->cmd_callback_arg;
453 
454 	/* Register offset */
455 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
456 
457 	/* Verify that request is quadlet aligned */
458 	if ((offset & 0x3) != 0) {
459 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
460 		(void) s1394_send_response(hal, req);
461 		return;
462 	}
463 
464 	/* Only writes from IRM or Bus Mgr allowed (in some cases) */
465 	mutex_enter(&hal->topology_tree_mutex);
466 	is_from = IEEE1394_NODE_NUM(req->nodeID);
467 	if (hal->bus_mgr_node != -1)
468 		should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
469 	else if (hal->IRM_node != -1)
470 		should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
471 	else
472 		should_be_from = S1394_INVALID_NODE_NUM;
473 	mutex_exit(&hal->topology_tree_mutex);
474 
475 	switch (req->cmd_type) {
476 	case CMD1394_ASYNCH_RD_QUAD:
477 		/*
478 		 * The csr_read() call can return DDI_FAILURE if the HAL
479 		 * is shutdown or if the register at "offset" is
480 		 * unimplemented. But although the STATE_CLEAR register
481 		 * is required to be implemented and readable, we will
482 		 * return IEEE1394_RESP_ADDRESS_ERROR in the response if
483 		 * we ever see this error.
484 		 */
485 		result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
486 		    offset, &data);
487 		if (result == DDI_SUCCESS) {
488 			req->cmd_u.q.quadlet_data = data;
489 			req->cmd_result = IEEE1394_RESP_COMPLETE;
490 		} else {
491 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
492 		}
493 		break;
494 
495 	case CMD1394_ASYNCH_WR_QUAD:
496 		data = req->cmd_u.q.quadlet_data;
497 
498 		/* CMSTR bit - request must be from bus_mgr/IRM */
499 		if (is_from != should_be_from) {
500 			data = data & ~IEEE1394_CSR_STATE_CMSTR;
501 		}
502 
503 		mutex_enter(&hal->topology_tree_mutex);
504 		/* DREQ bit - disabling DREQ can come from anyone */
505 		if (data & IEEE1394_CSR_STATE_DREQ) {
506 			hal->disable_requests_bit = 0;
507 			if (hal->hal_state == S1394_HAL_DREQ)
508 				hal->hal_state = S1394_HAL_NORMAL;
509 		}
510 
511 		/* ABDICATE bit */
512 		if (data & IEEE1394_CSR_STATE_ABDICATE) {
513 			hal->abdicate_bus_mgr_bit = 0;
514 		}
515 		mutex_exit(&hal->topology_tree_mutex);
516 		/*
517 		 * The csr_write() call can return DDI_FAILURE if the HAL
518 		 * is shutdown or if the register at "offset" is
519 		 * unimplemented. But although the STATE_CLEAR register
520 		 * is required to be implemented and writeable, we will
521 		 * return IEEE1394_RESP_ADDRESS_ERROR in the response if
522 		 * we ever see this error.
523 		 */
524 		result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
525 		    offset, data);
526 		if (result == DDI_SUCCESS) {
527 			req->cmd_result = IEEE1394_RESP_COMPLETE;
528 		} else {
529 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
530 		}
531 		break;
532 
533 	default:
534 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
535 	}
536 
537 	(void) s1394_send_response(hal, req);
538 }
539 
540 /*
541  * s1394_CSR_state_set()
542  *    handles all requests to the STATE_SET CSR register. It enforces that
543  *    certain bits that can be twiddled only by a given node (IRM or Bus
544  *    Manager).
545  */
546 static void
s1394_CSR_state_set(cmd1394_cmd_t * req)547 s1394_CSR_state_set(cmd1394_cmd_t *req)
548 {
549 	s1394_hal_t	*hal;
550 	uint32_t	data;
551 	uint_t		offset;
552 	uint_t		is_from;
553 	uint_t		should_be_from;
554 	uint_t		hal_node_num;
555 	uint_t		hal_number_of_nodes;
556 	int		result;
557 
558 	hal = (s1394_hal_t *)req->cmd_callback_arg;
559 
560 	/* Register offset */
561 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
562 
563 	/* Verify that request is quadlet aligned */
564 	if ((offset & 0x3) != 0) {
565 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
566 		(void) s1394_send_response(hal, req);
567 		return;
568 	}
569 
570 	/* Only writes from IRM or Bus Mgr allowed (in some cases) */
571 	mutex_enter(&hal->topology_tree_mutex);
572 	is_from = IEEE1394_NODE_NUM(req->nodeID);
573 	if (hal->bus_mgr_node != -1)
574 		should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
575 	else if (hal->IRM_node != -1)
576 		should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
577 	else
578 		should_be_from = S1394_INVALID_NODE_NUM;
579 	hal_node_num = IEEE1394_NODE_NUM(hal->node_id);
580 	hal_number_of_nodes = hal->number_of_nodes;
581 	mutex_exit(&hal->topology_tree_mutex);
582 
583 	switch (req->cmd_type) {
584 	case CMD1394_ASYNCH_WR_QUAD:
585 		data = req->cmd_u.q.quadlet_data;
586 
587 		/* CMSTR bit - request must be from bus_mgr/IRM */
588 		/*		& must be root to have bit set */
589 		if ((is_from != should_be_from) ||
590 		    (hal_node_num != (hal_number_of_nodes - 1))) {
591 			data = data & ~IEEE1394_CSR_STATE_CMSTR;
592 		}
593 
594 		mutex_enter(&hal->topology_tree_mutex);
595 		/* DREQ bit - only bus_mgr/IRM can set this bit */
596 		if (is_from != should_be_from) {
597 			data = data & ~IEEE1394_CSR_STATE_DREQ;
598 
599 		} else if (data & IEEE1394_CSR_STATE_DREQ) {
600 			hal->disable_requests_bit = 1;
601 			if (hal->hal_state == S1394_HAL_NORMAL)
602 				hal->hal_state = S1394_HAL_DREQ;
603 		}
604 		/* ABDICATE bit */
605 		if (data & IEEE1394_CSR_STATE_ABDICATE) {
606 			hal->abdicate_bus_mgr_bit = 1;
607 		}
608 		mutex_exit(&hal->topology_tree_mutex);
609 		/*
610 		 * The csr_write() call can return DDI_FAILURE if the HAL
611 		 * is shutdown or if the register at "offset" is
612 		 * unimplemented. But although the STATE_SET register
613 		 * is required to be implemented and writeable, we will
614 		 * return IEEE1394_RESP_ADDRESS_ERROR in the response if
615 		 * we ever see this error.
616 		 */
617 		result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
618 		    offset, data);
619 		if (result == DDI_SUCCESS) {
620 			req->cmd_result = IEEE1394_RESP_COMPLETE;
621 		} else {
622 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
623 		}
624 		break;
625 
626 	default:
627 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
628 	}
629 
630 	(void) s1394_send_response(hal, req);
631 }
632 
633 /*
634  * s1394_CSR_node_ids()
635  *    handles all requests to the NODE_IDS CSR register.  It passes all
636  *    requests to the common routine - s1394_common_CSR_routine().
637  */
638 static void
s1394_CSR_node_ids(cmd1394_cmd_t * req)639 s1394_CSR_node_ids(cmd1394_cmd_t *req)
640 {
641 	s1394_hal_t	*hal;
642 
643 	hal = (s1394_hal_t *)req->cmd_callback_arg;
644 
645 	s1394_common_CSR_routine(hal, req);
646 }
647 
648 /*
649  * s1394_CSR_reset_start()
650  *    handles all requests to the RESET_START CSR register. Only write
651  *    requests are legal, everything else gets a type_error response.
652  */
653 static void
s1394_CSR_reset_start(cmd1394_cmd_t * req)654 s1394_CSR_reset_start(cmd1394_cmd_t *req)
655 {
656 	s1394_hal_t	*hal;
657 	uint32_t	data;
658 	uint_t		offset;
659 
660 	hal = (s1394_hal_t *)req->cmd_callback_arg;
661 
662 	/* RESET_START register offset */
663 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
664 
665 	/* Verify that request is quadlet aligned */
666 	if ((offset & 0x3) != 0) {
667 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
668 		(void) s1394_send_response(hal, req);
669 		return;
670 	}
671 
672 	switch (req->cmd_type) {
673 	case CMD1394_ASYNCH_WR_QUAD:
674 		data = req->cmd_u.q.quadlet_data;
675 		/*
676 		 * The csr_write() call can return DDI_FAILURE if the HAL
677 		 * is shutdown or if the register at "offset" is
678 		 * unimplemented. Because we don't do any thing with
679 		 * the RESET_START register we will ignore failures and
680 		 * return IEEE1394_RESP_COMPLETE regardless.
681 		 */
682 		(void) HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
683 		    offset, data);
684 		req->cmd_result = IEEE1394_RESP_COMPLETE;
685 		break;
686 
687 	default:
688 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
689 	}
690 
691 	(void) s1394_send_response(hal, req);
692 }
693 
694 /*
695  * s1394_CSR_split_timeout()
696  *    handles all requests to the SPLIT_TIMEOUT CSR register.  It passes all
697  *    requests to the common routine - s1394_common_CSR_routine().
698  */
699 static void
s1394_CSR_split_timeout(cmd1394_cmd_t * req)700 s1394_CSR_split_timeout(cmd1394_cmd_t *req)
701 {
702 	s1394_hal_t	*hal;
703 
704 	hal = (s1394_hal_t *)req->cmd_callback_arg;
705 
706 	s1394_common_CSR_routine(hal, req);
707 }
708 
709 /*
710  * s1394_CSR_argument_regs()
711  *    handles all requests to the ARGUMENT CSR registers.  It passes all
712  *    requests to the common routine - s1394_common_CSR_routine().
713  */
714 static void
s1394_CSR_argument_regs(cmd1394_cmd_t * req)715 s1394_CSR_argument_regs(cmd1394_cmd_t *req)
716 {
717 	s1394_hal_t	*hal;
718 
719 	hal = (s1394_hal_t *)req->cmd_callback_arg;
720 
721 	s1394_common_CSR_routine(hal, req);
722 }
723 
724 /*
725  * s1394_CSR_test_regs()
726  *    handles all requests to the TEST CSR registers. It passes all requests
727  *    to the common routine - s1394_common_CSR_routine().
728  */
729 static void
s1394_CSR_test_regs(cmd1394_cmd_t * req)730 s1394_CSR_test_regs(cmd1394_cmd_t *req)
731 {
732 	s1394_hal_t	*hal;
733 	uint_t		offset;
734 
735 	hal = (s1394_hal_t *)req->cmd_callback_arg;
736 
737 	/* TEST register offset */
738 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
739 
740 	/* TEST_STATUS is Read-Only */
741 	if ((offset == (IEEE1394_CSR_TEST_STATUS & IEEE1394_CSR_OFFSET_MASK)) &&
742 	    (req->cmd_type == CMD1394_ASYNCH_WR_QUAD)) {
743 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
744 		(void) s1394_send_response(hal, req);
745 	} else {
746 		s1394_common_CSR_routine(hal, req);
747 	}
748 }
749 
750 /*
751  * s1394_CSR_interrupt_regs()
752  *    handles all requests to the INTERRUPT CSR registers.  It passes all
753  *    requests to the common routine - s1394_common_CSR_routine().
754  */
755 static void
s1394_CSR_interrupt_regs(cmd1394_cmd_t * req)756 s1394_CSR_interrupt_regs(cmd1394_cmd_t *req)
757 {
758 	s1394_hal_t	*hal;
759 
760 	hal = (s1394_hal_t *)req->cmd_callback_arg;
761 
762 	s1394_common_CSR_routine(hal, req);
763 }
764 
765 /*
766  * s1394_CSR_clock_regs()
767  *    handles all requests to the CLOCK CSR registers.  It passes all
768  *    requests to the common routine - s1394_common_CSR_routine().
769  */
770 static void
s1394_CSR_clock_regs(cmd1394_cmd_t * req)771 s1394_CSR_clock_regs(cmd1394_cmd_t *req)
772 {
773 	s1394_hal_t	*hal;
774 
775 	hal = (s1394_hal_t *)req->cmd_callback_arg;
776 
777 	s1394_common_CSR_routine(hal, req);
778 }
779 
780 /*
781  * s1394_CSR_message_regs()
782  *    handles all requests to the MESSAGE CSR registers.  It passes all
783  *    requests to the common routine - s1394_common_CSR_routine().
784  */
785 static void
s1394_CSR_message_regs(cmd1394_cmd_t * req)786 s1394_CSR_message_regs(cmd1394_cmd_t *req)
787 {
788 	s1394_hal_t	*hal;
789 
790 	hal = (s1394_hal_t *)req->cmd_callback_arg;
791 
792 	s1394_common_CSR_routine(hal, req);
793 }
794 
795 /*
796  * s1394_CSR_cycle_time()
797  *    handles all requests to the CYCLE_TIME CSR register.
798  */
799 static void
s1394_CSR_cycle_time(cmd1394_cmd_t * req)800 s1394_CSR_cycle_time(cmd1394_cmd_t *req)
801 {
802 	s1394_hal_t	*hal;
803 	uint32_t	data;
804 	uint_t		offset;
805 	int		result;
806 
807 	hal = (s1394_hal_t *)req->cmd_callback_arg;
808 
809 	/* CYCLE_TIME register offset */
810 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
811 
812 	/* Verify that request is quadlet aligned */
813 	if ((offset & 0x3) != 0) {
814 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
815 		(void) s1394_send_response(hal, req);
816 		return;
817 	}
818 
819 	switch (req->cmd_type) {
820 	case CMD1394_ASYNCH_RD_QUAD:
821 		/*
822 		 * The csr_read() call can return DDI_FAILURE if the HAL
823 		 * is shutdown or if the register at "offset" is
824 		 * unimplemented. But although the CYCLE_TIME register
825 		 * is required to be implemented on devices capable of
826 		 * providing isochronous services (like us), we will
827 		 * return IEEE1394_RESP_ADDRESS_ERROR in the response
828 		 * if we ever see this error.
829 		 */
830 		result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
831 		    offset, &data);
832 		if (result == DDI_SUCCESS) {
833 			req->cmd_u.q.quadlet_data = data;
834 			req->cmd_result = IEEE1394_RESP_COMPLETE;
835 		} else {
836 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
837 		}
838 		break;
839 
840 	case CMD1394_ASYNCH_WR_QUAD:
841 		data = req->cmd_u.q.quadlet_data;
842 		/*
843 		 * The csr_write() call can return DDI_FAILURE if the HAL
844 		 * is shutdown or if the register at "offset" is
845 		 * unimplemented. But although the CYCLE_TIME register
846 		 * is required to be implemented on devices capable of
847 		 * providing isochronous services (like us), the effects
848 		 * of a write are "node-dependent" so we will return
849 		 * IEEE1394_RESP_ADDRESS_ERROR in the response if we
850 		 * ever see this error.
851 		 */
852 		result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
853 		    offset, data);
854 		if (result == DDI_SUCCESS) {
855 			req->cmd_result = IEEE1394_RESP_COMPLETE;
856 		} else {
857 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
858 		}
859 		break;
860 
861 	default:
862 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
863 	}
864 
865 	(void) s1394_send_response(hal, req);
866 }
867 
868 /*
869  * s1394_CSR_bus_time()
870  *    handles all requests to the BUS_TIME CSR register.  It enforces that
871  *    only a broadcast write request from the IRM or Bus Manager can change
872  *    its value.
873  */
874 static void
s1394_CSR_bus_time(cmd1394_cmd_t * req)875 s1394_CSR_bus_time(cmd1394_cmd_t *req)
876 {
877 	s1394_hal_t	*hal;
878 	uint32_t	data;
879 	uint_t		offset;
880 	uint_t		is_from;
881 	uint_t		should_be_from;
882 	int		result;
883 
884 	hal = (s1394_hal_t *)req->cmd_callback_arg;
885 
886 	/* BUS_TIME register offset */
887 	offset = req->cmd_addr & IEEE1394_CSR_OFFSET_MASK;
888 
889 	/* Verify that request is quadlet aligned */
890 	if ((offset & 0x3) != 0) {
891 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
892 		(void) s1394_send_response(hal, req);
893 		return;
894 	}
895 
896 	switch (req->cmd_type) {
897 	case CMD1394_ASYNCH_RD_QUAD:
898 		/*
899 		 * The csr_read() call can return DDI_FAILURE if the HAL
900 		 * is shutdown or if the register at "offset" is
901 		 * unimplemented. But although the BUS_TIME register
902 		 * is required to be implemented by devices capable of
903 		 * being cycle master (like us), we will return
904 		 * IEEE1394_RESP_ADDRESS_ERROR in the response if we
905 		 * ever see this error.
906 		 */
907 		result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
908 		    offset, &data);
909 		if (result == DDI_SUCCESS) {
910 			req->cmd_u.q.quadlet_data = data;
911 			req->cmd_result = IEEE1394_RESP_COMPLETE;
912 		} else {
913 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
914 		}
915 		break;
916 
917 	case CMD1394_ASYNCH_WR_QUAD:
918 		/* Only broadcast writes from IRM or Bus Mgr allowed */
919 		mutex_enter(&hal->topology_tree_mutex);
920 		is_from = IEEE1394_NODE_NUM(req->nodeID);
921 		if (hal->bus_mgr_node != -1)
922 			should_be_from = IEEE1394_NODE_NUM(hal->bus_mgr_node);
923 		else if (hal->IRM_node != -1)
924 			should_be_from = IEEE1394_NODE_NUM(hal->IRM_node);
925 		else
926 			should_be_from = S1394_INVALID_NODE_NUM;
927 		mutex_exit(&hal->topology_tree_mutex);
928 
929 		if ((req->broadcast != 1) || (is_from != should_be_from)) {
930 			req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
931 			break;
932 		}
933 
934 		data = req->cmd_u.q.quadlet_data;
935 		/*
936 		 * The csr_write() call can return DDI_FAILURE if the HAL
937 		 * is shutdown or if the register at "offset" is
938 		 * unimplemented. But although the BUS_TIME register
939 		 * is required to be implemented on devices capable of
940 		 * being cycle master (like us), we will return
941 		 * IEEE1394_RESP_ADDRESS_ERROR in the response if we
942 		 * ever see this error.
943 		 */
944 		result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
945 		    offset, data);
946 		if (result == DDI_SUCCESS) {
947 			req->cmd_result = IEEE1394_RESP_COMPLETE;
948 		} else {
949 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
950 		}
951 		break;
952 
953 	default:
954 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
955 	}
956 
957 	(void) s1394_send_response(hal, req);
958 }
959 
960 /*
961  * s1394_CSR_busy_timeout()
962  *    handles all requests to the BUSY_TIMEOUT CSR register.  It passes all
963  *    requests to the common routine - s1394_common_CSR_routine().
964  */
965 static void
s1394_CSR_busy_timeout(cmd1394_cmd_t * req)966 s1394_CSR_busy_timeout(cmd1394_cmd_t *req)
967 {
968 	s1394_hal_t	*hal;
969 
970 	hal = (s1394_hal_t *)req->cmd_callback_arg;
971 
972 	s1394_common_CSR_routine(hal, req);
973 }
974 
975 /*
976  * s1394_CSR_IRM_regs()
977  *    handles all requests to the IRM registers, including BANDWIDTH_AVAILABLE,
978  *    CHANNELS_AVAILABLE, and the BUS_MANAGER_ID.  Only quadlet read and lock
979  *    requests are allowed.
980  */
981 static void
s1394_CSR_IRM_regs(cmd1394_cmd_t * req)982 s1394_CSR_IRM_regs(cmd1394_cmd_t *req)
983 {
984 	s1394_hal_t	*hal;
985 	uint32_t	generation;
986 	uint32_t	data;
987 	uint32_t	compare;
988 	uint32_t	swap;
989 	uint32_t	old;
990 	uint_t		offset;
991 	int		result;
992 
993 	hal = (s1394_hal_t *)req->cmd_callback_arg;
994 
995 	/* IRM register offset */
996 	offset = (req->cmd_addr & IEEE1394_CSR_OFFSET_MASK);
997 
998 	/* Verify that request is quadlet aligned */
999 	if ((offset & 0x3) != 0) {
1000 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1001 		(void) s1394_send_response(hal, req);
1002 		return;
1003 	}
1004 
1005 	switch (req->cmd_type) {
1006 	case CMD1394_ASYNCH_RD_QUAD:
1007 		/*
1008 		 * The csr_read() call can return DDI_FAILURE if the HAL
1009 		 * is shutdown or if the register at "offset" is
1010 		 * unimplemented.  In many cases these registers will
1011 		 * have been implemented in HW.  We are not likely to ever
1012 		 * receive this callback.  If we do, though, we will
1013 		 * return IEEE1394_RESP_ADDRESS_ERROR when we get an error
1014 		 * and IEEE1394_RESP_COMPLETE for success.
1015 		 */
1016 		result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
1017 		    offset, &data);
1018 		if (result == DDI_SUCCESS) {
1019 			req->cmd_u.q.quadlet_data = data;
1020 			req->cmd_result = IEEE1394_RESP_COMPLETE;
1021 		} else {
1022 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1023 		}
1024 		break;
1025 
1026 	case CMD1394_ASYNCH_LOCK_32:
1027 		mutex_enter(&hal->topology_tree_mutex);
1028 		generation = hal->generation_count;
1029 		mutex_exit(&hal->topology_tree_mutex);
1030 		if (req->cmd_u.l32.lock_type == CMD1394_LOCK_COMPARE_SWAP) {
1031 			compare = req->cmd_u.l32.arg_value;
1032 			swap = req->cmd_u.l32.data_value;
1033 			/*
1034 			 * The csr_cswap32() call can return DDI_FAILURE if
1035 			 * the HAL is shutdown, if the register at "offset"
1036 			 * is unimplemented, or if the generation has changed.
1037 			 * In the last case, it shouldn't matter because the
1038 			 * call to s1394_send_response will fail on a bad
1039 			 * generation and the command will be freed.
1040 			 */
1041 			result = HAL_CALL(hal).csr_cswap32(
1042 			    hal->halinfo.hal_private, generation,
1043 			    offset, compare, swap, &old);
1044 			if (result == DDI_SUCCESS) {
1045 				req->cmd_u.l32.old_value = old;
1046 				req->cmd_result = IEEE1394_RESP_COMPLETE;
1047 			} else {
1048 				req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1049 			}
1050 			break;
1051 		} else {
1052 			req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1053 		}
1054 
1055 		break;
1056 
1057 	default:
1058 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1059 	}
1060 
1061 	(void) s1394_send_response(hal, req);
1062 }
1063 
1064 /*
1065  * s1394_CSR_topology_map()
1066  *    handles all request for the TOPOLOGY_MAP[].  Since it is implemented
1067  *    with backing store, there isn't much to do besides return success or
1068  *    failure.
1069  */
1070 static void
s1394_CSR_topology_map(cmd1394_cmd_t * req)1071 s1394_CSR_topology_map(cmd1394_cmd_t *req)
1072 {
1073 	s1394_hal_t	*hal;
1074 
1075 	hal = (s1394_hal_t *)req->cmd_callback_arg;
1076 
1077 	/* Make sure it's a quadlet read request */
1078 	if (req->cmd_type == CMD1394_ASYNCH_RD_QUAD)
1079 		req->cmd_result = IEEE1394_RESP_COMPLETE;
1080 	else
1081 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1082 
1083 	(void) s1394_send_response(hal, req);
1084 }
1085 
1086 /*
1087  * s1394_CSR_topology_map_update()
1088  *    is used to update the local host's TOPOLOGY_MAP[] buffer.  It copies in
1089  *    the SelfID packets, updates the generation and other fields, and
1090  *    computes the necessary CRC values before returning.
1091  *    Callers must be holding the topology_tree_mutex.
1092  */
1093 void
s1394_CSR_topology_map_update(s1394_hal_t * hal)1094 s1394_CSR_topology_map_update(s1394_hal_t *hal)
1095 {
1096 	s1394_selfid_pkt_t *selfid_packet;
1097 	uint32_t	   *tm_ptr;
1098 	uint32_t	   *data_ptr;
1099 	uint32_t	   node_count;
1100 	uint32_t	   self_id_count;
1101 	uint_t		   CRC;
1102 	uint32_t	   length;
1103 	int		   i, j, c;
1104 
1105 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1106 
1107 	tm_ptr = (uint32_t *)hal->CSR_topology_map;
1108 	data_ptr = (uint32_t *)&(tm_ptr[3]);
1109 
1110 	c = 0;
1111 	for (i = 0; i < hal->number_of_nodes; i++) {
1112 		j = -1;
1113 		selfid_packet = hal->selfid_ptrs[i];
1114 
1115 		do {
1116 			j++;
1117 			data_ptr[c++] = selfid_packet[j].spkt_data;
1118 		}
1119 		while (IEEE1394_SELFID_ISMORE(&selfid_packet[j]));
1120 	}
1121 
1122 	/* Update Topology Map Generation */
1123 	tm_ptr[1] = tm_ptr[1] + 1;
1124 
1125 	/* Update Node_Count and Self_Id_Count */
1126 	node_count = (i & IEEE1394_TOP_MAP_LEN_MASK);
1127 	self_id_count = (c & IEEE1394_TOP_MAP_LEN_MASK);
1128 	tm_ptr[2] = (node_count << IEEE1394_TOP_MAP_LEN_SHIFT) |
1129 	    (self_id_count);
1130 
1131 	/* Calculate CRC-16 */
1132 	length = self_id_count + 2;
1133 	CRC = s1394_CRC16(&(tm_ptr[1]), length);
1134 	tm_ptr[0] = (length << IEEE1394_TOP_MAP_LEN_SHIFT) | CRC;
1135 }
1136 
1137 /*
1138  * s1394_CSR_topology_map_disable()
1139  *    is used to disable the local host's TOPOLOGY_MAP[] buffer (during bus
1140  *    reset processing).  It sets the topology map's length to zero to
1141  *    indicate that it is invalid.
1142  */
1143 void
s1394_CSR_topology_map_disable(s1394_hal_t * hal)1144 s1394_CSR_topology_map_disable(s1394_hal_t *hal)
1145 {
1146 	uint32_t *tm_ptr;
1147 
1148 	ASSERT(MUTEX_HELD(&hal->topology_tree_mutex));
1149 
1150 	tm_ptr = (uint32_t *)hal->CSR_topology_map;
1151 
1152 	/* Set length = 0 */
1153 	tm_ptr[0] = tm_ptr[0] & IEEE1394_TOP_MAP_LEN_MASK;
1154 }
1155 
1156 /*
1157  * s1394_common_CSR_routine()
1158  *    is used to handle most of the CSR register requests.  They are passed
1159  *    to the appropriate HAL entry point for further processing.  Then they
1160  *    are filled in with an appropriate response code, and the response is sent.
1161  */
1162 static void
s1394_common_CSR_routine(s1394_hal_t * hal,cmd1394_cmd_t * req)1163 s1394_common_CSR_routine(s1394_hal_t *hal, cmd1394_cmd_t *req)
1164 {
1165 	uint32_t data;
1166 	uint_t	 offset;
1167 	int	 result;
1168 
1169 	/* Register offset */
1170 	offset = (req->cmd_addr & IEEE1394_CSR_OFFSET_MASK);
1171 
1172 	/* Verify that request is quadlet aligned */
1173 	if ((offset & 0x3) != 0) {
1174 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1175 		(void) s1394_send_response(hal, req);
1176 	}
1177 
1178 	switch (req->cmd_type) {
1179 	case CMD1394_ASYNCH_RD_QUAD:
1180 		/*
1181 		 * The csr_read() call can return DDI_FAILURE if the HAL
1182 		 * is shutdown or if the register at "offset" is
1183 		 * unimplemented.  We will return IEEE1394_RESP_ADDRESS_ERROR
1184 		 * in the response if we see this error.
1185 		 */
1186 		result = HAL_CALL(hal).csr_read(hal->halinfo.hal_private,
1187 		    offset, &data);
1188 		if (result == DDI_SUCCESS) {
1189 			req->cmd_u.q.quadlet_data = data;
1190 			req->cmd_result = IEEE1394_RESP_COMPLETE;
1191 		} else {
1192 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1193 		}
1194 		break;
1195 
1196 	case CMD1394_ASYNCH_WR_QUAD:
1197 		data = req->cmd_u.q.quadlet_data;
1198 		/*
1199 		 * The csr_read() call can return DDI_FAILURE if the HAL
1200 		 * is shutdown or if the register at "offset" is
1201 		 * unimplemented.  We will return IEEE1394_RESP_ADDRESS_ERROR
1202 		 * in the response if we see this error.
1203 		 */
1204 		result = HAL_CALL(hal).csr_write(hal->halinfo.hal_private,
1205 		    offset, data);
1206 		if (result == DDI_SUCCESS) {
1207 			req->cmd_result = IEEE1394_RESP_COMPLETE;
1208 		} else {
1209 			req->cmd_result = IEEE1394_RESP_ADDRESS_ERROR;
1210 		}
1211 		break;
1212 
1213 	default:
1214 		req->cmd_result = IEEE1394_RESP_TYPE_ERROR;
1215 	}
1216 
1217 	(void) s1394_send_response(hal, req);
1218 }
1219 
1220 /*
1221  * s1394_init_local_config_rom()
1222  *    is called in the HAL attach routine - h1394_attach() - to setup the
1223  *    initial Config ROM entries on the local host, including the
1224  *    bus_info_block and the root and unit directories.
1225  */
1226 int
s1394_init_local_config_rom(s1394_hal_t * hal)1227 s1394_init_local_config_rom(s1394_hal_t *hal)
1228 {
1229 	uint32_t *config_rom;
1230 	uint32_t *node_unique_id_leaf;
1231 	uint32_t *unit_dir;
1232 	uint32_t *text_leaf;
1233 	void	 *n_handle;
1234 	uint64_t guid;
1235 	uint32_t guid_hi, guid_lo;
1236 	uint32_t bus_capabilities;
1237 	uint32_t irmc, g;
1238 	uint32_t module_vendor_id;
1239 	uint32_t node_capabilities;
1240 	uint32_t root_dir_len;
1241 	uint32_t CRC;
1242 	int	 status, i, ret;
1243 
1244 	/* Setup Config ROM mutex */
1245 	mutex_init(&hal->local_config_rom_mutex,
1246 	    NULL, MUTEX_DRIVER, hal->halinfo.hw_interrupt);
1247 
1248 	/* Allocate 1K for the Config ROM buffer */
1249 	hal->local_config_rom = (uint32_t *)kmem_zalloc(IEEE1394_CONFIG_ROM_SZ,
1250 	    KM_SLEEP);
1251 
1252 	/* Allocate 1K for the temporary buffer */
1253 	hal->temp_config_rom_buf = (uint32_t *)kmem_zalloc(
1254 	    IEEE1394_CONFIG_ROM_SZ, KM_SLEEP);
1255 
1256 	config_rom = hal->local_config_rom;
1257 
1258 	/* Lock the Config ROM buffer */
1259 	mutex_enter(&hal->local_config_rom_mutex);
1260 
1261 	/* Build the config ROM structures */
1262 	ret = s1394_init_config_rom_structures(hal);
1263 	if (ret != DDI_SUCCESS) {
1264 		/* Unlock the Config ROM buffer */
1265 		mutex_exit(&hal->local_config_rom_mutex);
1266 		kmem_free((void *)hal->temp_config_rom_buf,
1267 		    IEEE1394_CONFIG_ROM_SZ);
1268 		kmem_free((void *)hal->local_config_rom,
1269 		    IEEE1394_CONFIG_ROM_SZ);
1270 		mutex_destroy(&hal->local_config_rom_mutex);
1271 		return (DDI_FAILURE);
1272 	}
1273 	/* Build the Bus_Info_Block - see IEEE 1394-1995, Section 8.3.2.5.4 */
1274 	bus_capabilities = hal->halinfo.bus_capabilities;
1275 
1276 	/*
1277 	 * If we are Isoch Resource Manager capable then we are
1278 	 * Bus Manager capable too.
1279 	 */
1280 	irmc = (bus_capabilities & IEEE1394_BIB_IRMC_MASK) >>
1281 	    IEEE1394_BIB_IRMC_SHIFT;
1282 	if (irmc)
1283 		bus_capabilities = bus_capabilities | IEEE1394_BIB_BMC_MASK;
1284 
1285 	/*
1286 	 * Set generation to P1394a valid (but changeable)
1287 	 * Even if we have a 1995 PHY, we will still provide
1288 	 * certain P1394A functionality (especially with respect
1289 	 * to Config ROM updates).  So we must publish this
1290 	 * information.
1291 	 */
1292 	g = 2 << IEEE1394_BIB_GEN_SHIFT;
1293 	bus_capabilities = bus_capabilities | g;
1294 
1295 	/* Get the GUID */
1296 	guid = hal->halinfo.guid;
1297 	guid_hi = (uint32_t)(guid >> 32);
1298 	guid_lo = (uint32_t)(guid & 0x00000000FFFFFFFF);
1299 
1300 	config_rom[1] = 0x31333934;	/* "1394" */
1301 	config_rom[2] = bus_capabilities;
1302 	config_rom[3] = guid_hi;
1303 	config_rom[4] = guid_lo;
1304 
1305 	/* The CRC covers only our Bus_Info_Block */
1306 	CRC = s1394_CRC16(&config_rom[1], 4);
1307 	config_rom[0] = (0x04040000) | CRC;
1308 
1309 	/* Do byte-swapping if necessary (x86) */
1310 	for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
1311 		config_rom[i] = T1394_DATA32(config_rom[i]);
1312 
1313 	/* Build the Root_Directory - see IEEE 1394-1995, Section 8.3.2.5.5 */
1314 
1315 	/* MODULE_VENDOR_ID - see IEEE 1394-1995, Section 8.3.2.5.5.1 */
1316 	module_vendor_id = S1394_SUNW_OUI;
1317 
1318 	/* NODE_CAPABILITIES - see IEEE 1394-1995, Section 8.3.2.5.5.2 */
1319 	node_capabilities = hal->halinfo.node_capabilities &
1320 	    IEEE1212_NODE_CAPABILITIES_MASK;
1321 	root_dir_len = 2;
1322 
1323 	config_rom[6] = (IEEE1212_MODULE_VENDOR_ID <<
1324 	    IEEE1212_KEY_VALUE_SHIFT) | module_vendor_id;
1325 	config_rom[7] = (IEEE1212_NODE_CAPABILITIES <<
1326 	    IEEE1212_KEY_VALUE_SHIFT) | node_capabilities;
1327 
1328 	CRC = s1394_CRC16(&config_rom[6], root_dir_len);
1329 	config_rom[IEEE1394_BIB_QUAD_SZ] =
1330 	    (root_dir_len << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
1331 
1332 	/* Do byte-swapping if necessary (x86) */
1333 	for (i = IEEE1394_BIB_QUAD_SZ; i < 8; i++)
1334 		config_rom[i] = T1394_DATA32(config_rom[i]);
1335 
1336 	/* Build the Root Text leaf - see IEEE 1394-1995, Section 8.3.2.5.7 */
1337 	text_leaf = (uint32_t *)kmem_zalloc(S1394_ROOT_TEXT_LEAF_SZ, KM_SLEEP);
1338 	text_leaf[1] = 0x00000000;
1339 	text_leaf[2] = 0x00000000;
1340 	text_leaf[3] = 0x53756e20;	/* "Sun " */
1341 	text_leaf[4] = 0x4d696372;	/* "Micr" */
1342 	text_leaf[5] = 0x6f737973;	/* "osys" */
1343 	text_leaf[6] = 0x74656d73;	/* "tems" */
1344 	text_leaf[7] = 0x2c20496e;	/* ", In" */
1345 	text_leaf[8] = 0x632e0000;	/* "c."   */
1346 	CRC = s1394_CRC16(&text_leaf[1], S1394_ROOT_TEXT_LEAF_QUAD_SZ - 1);
1347 	text_leaf[0] = (0x00080000) | CRC;
1348 
1349 	/* Do byte-swapping if necessary (x86) */
1350 	for (i = 0; i < 9; i++)
1351 		text_leaf[i] = T1394_DATA32(text_leaf[i]);
1352 
1353 	ret = s1394_add_config_rom_entry(hal, S1394_ROOT_TEXT_KEY, text_leaf,
1354 	    S1394_ROOT_TEXT_LEAF_QUAD_SZ, &n_handle, &status);
1355 	if (ret != DDI_SUCCESS) {
1356 		kmem_free((void *)text_leaf, S1394_ROOT_TEXT_LEAF_SZ);
1357 		/* Destroy the config_rom structures */
1358 		(void) s1394_destroy_config_rom_structures(hal);
1359 		/* Unlock the Config ROM buffer */
1360 		mutex_exit(&hal->local_config_rom_mutex);
1361 		kmem_free((void *)hal->temp_config_rom_buf,
1362 		    IEEE1394_CONFIG_ROM_SZ);
1363 		kmem_free((void *)hal->local_config_rom,
1364 		    IEEE1394_CONFIG_ROM_SZ);
1365 		mutex_destroy(&hal->local_config_rom_mutex);
1366 		return (DDI_FAILURE);
1367 	}
1368 	kmem_free((void *)text_leaf, S1394_ROOT_TEXT_LEAF_SZ);
1369 
1370 	/* Build the Node_Unique_Id leaf - IEEE 1394-1995, Sect. 8.3.2.5.7.1 */
1371 	node_unique_id_leaf = (uint32_t *)kmem_zalloc(S1394_NODE_UNIQUE_ID_SZ,
1372 	    KM_SLEEP);
1373 	node_unique_id_leaf[1] = guid_hi;
1374 	node_unique_id_leaf[2] = guid_lo;
1375 	CRC = s1394_CRC16(&node_unique_id_leaf[1],
1376 	    S1394_NODE_UNIQUE_ID_QUAD_SZ - 1);
1377 	node_unique_id_leaf[0] = (0x00020000) | CRC;
1378 
1379 	/* Do byte-swapping if necessary (x86) */
1380 	for (i = 0; i < S1394_NODE_UNIQUE_ID_QUAD_SZ; i++)
1381 		node_unique_id_leaf[i] = T1394_DATA32(node_unique_id_leaf[i]);
1382 
1383 	ret = s1394_add_config_rom_entry(hal, S1394_NODE_UNIQUE_ID_KEY,
1384 	    node_unique_id_leaf, S1394_NODE_UNIQUE_ID_QUAD_SZ, &n_handle,
1385 	    &status);
1386 	if (ret != DDI_SUCCESS) {
1387 		kmem_free((void *)node_unique_id_leaf,
1388 		    S1394_NODE_UNIQUE_ID_SZ);
1389 		/* Destroy the config_rom structures */
1390 		(void) s1394_destroy_config_rom_structures(hal);
1391 		/* Unlock the Config ROM buffer */
1392 		mutex_exit(&hal->local_config_rom_mutex);
1393 		kmem_free((void *)hal->temp_config_rom_buf,
1394 		    IEEE1394_CONFIG_ROM_SZ);
1395 		kmem_free((void *)hal->local_config_rom,
1396 		    IEEE1394_CONFIG_ROM_SZ);
1397 		mutex_destroy(&hal->local_config_rom_mutex);
1398 		return (DDI_FAILURE);
1399 	}
1400 	kmem_free((void *)node_unique_id_leaf, S1394_NODE_UNIQUE_ID_SZ);
1401 
1402 	/* Build the Unit_Directory for 1394 Framework */
1403 	unit_dir = (uint32_t *)kmem_zalloc(S1394_UNIT_DIR_SZ, KM_SLEEP);
1404 	unit_dir[1] = 0x12080020;	/* Sun Microsystems */
1405 	unit_dir[2] = 0x13000001;	/* Version 1 */
1406 	unit_dir[3] = 0x81000001;	/* offset to the text leaf */
1407 	CRC = s1394_CRC16(&unit_dir[1], 3);
1408 	unit_dir[0] = (0x00030000) | CRC;
1409 
1410 	/* Do byte-swapping if necessary (x86) */
1411 	for (i = 0; i < 4; i++)
1412 		unit_dir[i] = T1394_DATA32(unit_dir[i]);
1413 
1414 	/* Build the Unit Directory text leaf */
1415 	unit_dir[5] = 0x00000000;
1416 	unit_dir[6] = 0x00000000;
1417 	unit_dir[7] = 0x536f6c61;	/* "Sola" */
1418 	unit_dir[8] = 0x72697320;	/* "ris " */
1419 	unit_dir[9] = 0x31333934;	/* "1394" */
1420 	unit_dir[10] = 0x20535720;	/* " SW " */
1421 	unit_dir[11] = 0x4672616d;	/* "Fram" */
1422 	unit_dir[12] = 0x65576f72;	/* "ewor" */
1423 	unit_dir[13] = 0x6b000000;	/* "k"    */
1424 	CRC = s1394_CRC16(&unit_dir[5], 9);
1425 	unit_dir[4] = (0x00090000) | CRC;
1426 
1427 	/* Do byte-swapping if necessary (x86) */
1428 	for (i = 4; i < S1394_UNIT_DIR_QUAD_SZ; i++)
1429 		unit_dir[i] = T1394_DATA32(unit_dir[i]);
1430 
1431 	ret = s1394_add_config_rom_entry(hal, S1394_UNIT_DIR_KEY, unit_dir,
1432 	    S1394_UNIT_DIR_QUAD_SZ, &n_handle, &status);
1433 	if (ret != DDI_SUCCESS) {
1434 		kmem_free((void *)unit_dir, S1394_UNIT_DIR_SZ);
1435 		/* Destroy the config_rom structures */
1436 		(void) s1394_destroy_config_rom_structures(hal);
1437 		/* Unlock the Config ROM buffer */
1438 		mutex_exit(&hal->local_config_rom_mutex);
1439 		kmem_free((void *)hal->temp_config_rom_buf,
1440 		    IEEE1394_CONFIG_ROM_SZ);
1441 		/* Free the 1K for the Config ROM buffer */
1442 		kmem_free((void *)hal->local_config_rom,
1443 		    IEEE1394_CONFIG_ROM_SZ);
1444 		mutex_destroy(&hal->local_config_rom_mutex);
1445 		return (DDI_FAILURE);
1446 	}
1447 	kmem_free((void *)unit_dir, S1394_UNIT_DIR_SZ);
1448 
1449 	hal->config_rom_update_amount = (IEEE1394_CONFIG_ROM_QUAD_SZ -
1450 	    hal->free_space);
1451 
1452 	/* Unlock the Config ROM buffer */
1453 	mutex_exit(&hal->local_config_rom_mutex);
1454 
1455 	/*
1456 	 * The update_config_rom() call can return DDI_FAILURE if the
1457 	 * HAL is shutdown.
1458 	 */
1459 	(void) HAL_CALL(hal).update_config_rom(hal->halinfo.hal_private,
1460 	    config_rom, IEEE1394_CONFIG_ROM_QUAD_SZ);
1461 
1462 	return (DDI_SUCCESS);
1463 }
1464 
1465 /*
1466  * s1394_destroy_local_config_rom()
1467  *    is necessary for h1394_detach().  It undoes all the work that
1468  *    s1394_init_local_config_rom() had setup and more.  By pulling
1469  *    everything out of the conig rom structures and freeing them and their
1470  *    associated mutexes, the Config ROM is completely cleaned up.
1471  */
1472 void
s1394_destroy_local_config_rom(s1394_hal_t * hal)1473 s1394_destroy_local_config_rom(s1394_hal_t *hal)
1474 {
1475 	/* Lock the Config ROM buffer */
1476 	mutex_enter(&hal->local_config_rom_mutex);
1477 
1478 	/* Destroy the config_rom structures */
1479 	(void) s1394_destroy_config_rom_structures(hal);
1480 
1481 	/* Unlock the Config ROM buffer */
1482 	mutex_exit(&hal->local_config_rom_mutex);
1483 
1484 	/* Free the 1K for the temporary buffer */
1485 	kmem_free((void *)hal->temp_config_rom_buf, IEEE1394_CONFIG_ROM_SZ);
1486 	/* Free the 1K for the Config ROM buffer */
1487 	kmem_free((void *)hal->local_config_rom, IEEE1394_CONFIG_ROM_SZ);
1488 
1489 	/* Setup Config ROM mutex */
1490 	mutex_destroy(&hal->local_config_rom_mutex);
1491 }
1492 
1493 /*
1494  * s1394_init_config_rom_structures()
1495  *    initializes the structures that are used to maintain the local Config ROM.
1496  *    Callers must be holding the local_config_rom_mutex.
1497  */
1498 static int
s1394_init_config_rom_structures(s1394_hal_t * hal)1499 s1394_init_config_rom_structures(s1394_hal_t *hal)
1500 {
1501 	s1394_config_rom_t *root_directory;
1502 	s1394_config_rom_t *rest_of_config_rom;
1503 
1504 	ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
1505 
1506 	root_directory = (s1394_config_rom_t *)kmem_zalloc(
1507 	    sizeof (s1394_config_rom_t), KM_SLEEP);
1508 
1509 	root_directory->cfgrom_used = B_TRUE;
1510 	root_directory->cfgrom_addr_lo = IEEE1394_BIB_QUAD_SZ;
1511 	root_directory->cfgrom_addr_hi = IEEE1394_BIB_QUAD_SZ + 2;
1512 
1513 	rest_of_config_rom = (s1394_config_rom_t *)kmem_zalloc(
1514 	    sizeof (s1394_config_rom_t), KM_SLEEP);
1515 
1516 	rest_of_config_rom->cfgrom_used = B_FALSE;
1517 	rest_of_config_rom->cfgrom_addr_lo = root_directory->cfgrom_addr_hi + 1;
1518 	rest_of_config_rom->cfgrom_addr_hi = IEEE1394_CONFIG_ROM_QUAD_SZ - 1;
1519 
1520 	root_directory->cfgrom_next = rest_of_config_rom;
1521 	root_directory->cfgrom_prev = NULL;
1522 	rest_of_config_rom->cfgrom_next = NULL;
1523 	rest_of_config_rom->cfgrom_prev = root_directory;
1524 
1525 	hal->root_directory = root_directory;
1526 	hal->free_space = IEEE1394_CONFIG_ROM_QUAD_SZ -
1527 	    (rest_of_config_rom->cfgrom_addr_lo);
1528 
1529 	return (DDI_SUCCESS);
1530 }
1531 
1532 /*
1533  * s1394_destroy_config_rom_structures()
1534  *    is used to destroy the structures that maintain the local Config ROM.
1535  *    Callers must be holding the local_config_rom_mutex.
1536  */
1537 static int
s1394_destroy_config_rom_structures(s1394_hal_t * hal)1538 s1394_destroy_config_rom_structures(s1394_hal_t *hal)
1539 {
1540 	s1394_config_rom_t *curr_blk;
1541 	s1394_config_rom_t *next_blk;
1542 
1543 	ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
1544 
1545 	curr_blk = hal->root_directory;
1546 
1547 	while (curr_blk != NULL) {
1548 		next_blk = curr_blk->cfgrom_next;
1549 		kmem_free(curr_blk, sizeof (s1394_config_rom_t));
1550 		curr_blk = next_blk;
1551 	}
1552 
1553 	return (DDI_SUCCESS);
1554 }
1555 
1556 /*
1557  * s1394_add_config_rom_entry()
1558  *    is used to add a new entry to the local host's config ROM.  By
1559  *    specifying a key and a buffer, it is possible to update the Root
1560  *    Directory to point to the new entry (in buffer).  Additionally, all
1561  *    of the relevant CRCs, lengths, and generations are updated as well.
1562  *    By returning a Config ROM "handle", we can allow targets to remove
1563  *    the corresponding entry.
1564  *    Callers must be holding the local_config_rom_mutex.
1565  */
1566 int
s1394_add_config_rom_entry(s1394_hal_t * hal,uint8_t key,uint32_t * buffer,uint_t size,void ** handle,int * status)1567 s1394_add_config_rom_entry(s1394_hal_t *hal, uint8_t key, uint32_t *buffer,
1568     uint_t size, void **handle, int *status)
1569 {
1570 	s1394_config_rom_t *curr_blk;
1571 	s1394_config_rom_t *new_blk;
1572 	uint32_t	   *config_rom;
1573 	uint32_t	   *temp_buf;
1574 	uint32_t	   CRC;
1575 	uint_t		   tmp_offset;
1576 	uint_t		   tmp_size, temp;
1577 	uint_t		   last_entry_offset;
1578 	int		   i;
1579 
1580 	ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
1581 
1582 	if (size > hal->free_space) {
1583 		/* Out of space */
1584 		*status = CMD1394_ERSRC_CONFLICT;
1585 		return (DDI_FAILURE);
1586 	}
1587 
1588 	config_rom = hal->local_config_rom;
1589 	temp_buf = hal->temp_config_rom_buf;
1590 
1591 	/* Copy the Bus_Info_Block */
1592 	bcopy(&config_rom[0], &temp_buf[0], IEEE1394_BIB_SZ);
1593 
1594 	/* Copy and add to the Root_Directory */
1595 	tmp_offset = hal->root_directory->cfgrom_addr_lo;
1596 	tmp_size = (hal->root_directory->cfgrom_addr_hi - tmp_offset) + 1;
1597 	tmp_size = tmp_size + 1;	/* For the new entry */
1598 	bcopy(&config_rom[tmp_offset], &temp_buf[tmp_offset], tmp_size << 2);
1599 	last_entry_offset = hal->root_directory->cfgrom_addr_hi + 1;
1600 
1601 	curr_blk = hal->root_directory;
1602 	curr_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi + 1;
1603 	while (curr_blk->cfgrom_next != NULL) {
1604 		if (curr_blk->cfgrom_next->cfgrom_used == B_TRUE) {
1605 			tmp_offset = curr_blk->cfgrom_next->cfgrom_addr_lo;
1606 			tmp_size = (curr_blk->cfgrom_next->cfgrom_addr_hi -
1607 			    tmp_offset) + 1;
1608 
1609 			bcopy(&config_rom[tmp_offset],
1610 			    &temp_buf[tmp_offset + 1], tmp_size << 2);
1611 			curr_blk->cfgrom_next->cfgrom_addr_lo++;
1612 			curr_blk->cfgrom_next->cfgrom_addr_hi++;
1613 			last_entry_offset =
1614 			    curr_blk->cfgrom_next->cfgrom_addr_hi;
1615 
1616 			tmp_offset = curr_blk->cfgrom_next->root_dir_offset;
1617 
1618 			/* Swap... add one... then unswap */
1619 			temp = T1394_DATA32(temp_buf[tmp_offset]);
1620 			temp++;
1621 			temp_buf[tmp_offset] = T1394_DATA32(temp);
1622 		} else {
1623 			curr_blk->cfgrom_next->cfgrom_addr_lo++;
1624 			hal->free_space--;
1625 			break;
1626 		}
1627 
1628 		curr_blk = curr_blk->cfgrom_next;
1629 	}
1630 
1631 	/* Get the pointer to the "free" space */
1632 	curr_blk = curr_blk->cfgrom_next;
1633 
1634 	/* Is it an exact fit? */
1635 	if (hal->free_space == size) {
1636 		curr_blk->cfgrom_used = B_TRUE;
1637 
1638 	} else {		/* Must break this piece */
1639 		new_blk = (s1394_config_rom_t *)kmem_zalloc(
1640 		    sizeof (s1394_config_rom_t), KM_SLEEP);
1641 		if (new_blk == NULL) {
1642 			return (DDI_FAILURE);
1643 		}
1644 
1645 		new_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi;
1646 		new_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo + size;
1647 		curr_blk->cfgrom_addr_hi = new_blk->cfgrom_addr_lo - 1;
1648 		new_blk->cfgrom_next = curr_blk->cfgrom_next;
1649 		curr_blk->cfgrom_next = new_blk;
1650 		new_blk->cfgrom_prev = curr_blk;
1651 		curr_blk->cfgrom_used = B_TRUE;
1652 		last_entry_offset = curr_blk->cfgrom_addr_hi;
1653 	}
1654 	hal->free_space = hal->free_space - size;
1655 
1656 	/* Copy in the new entry */
1657 	tmp_offset = curr_blk->cfgrom_addr_lo;
1658 	bcopy(buffer, &temp_buf[tmp_offset], size << 2);
1659 
1660 	/* Update root directory */
1661 	tmp_offset = hal->root_directory->cfgrom_addr_hi;
1662 	tmp_size = tmp_offset - hal->root_directory->cfgrom_addr_lo;
1663 	curr_blk->root_dir_offset = tmp_offset;
1664 	tmp_offset = curr_blk->cfgrom_addr_lo - tmp_offset;
1665 
1666 	temp_buf[hal->root_directory->cfgrom_addr_hi] =
1667 	    T1394_DATA32((((uint32_t)key) << IEEE1212_KEY_VALUE_SHIFT) |
1668 	    tmp_offset);
1669 	tmp_offset = hal->root_directory->cfgrom_addr_lo;
1670 
1671 	/* Do byte-swapping if necessary (x86) */
1672 	for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
1673 	    i++)
1674 		temp_buf[i] = T1394_DATA32(temp_buf[i]);
1675 
1676 	CRC = s1394_CRC16(&temp_buf[tmp_offset + 1], tmp_size);
1677 	temp_buf[tmp_offset] = (tmp_size << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
1678 
1679 	/* Redo byte-swapping if necessary (x86) */
1680 	for (i = tmp_offset; i <= hal->root_directory->cfgrom_addr_hi; i++)
1681 		temp_buf[i] = T1394_DATA32(temp_buf[i]);
1682 
1683 	/* Copy it back to config_rom buffer */
1684 	last_entry_offset++;
1685 	bcopy(&temp_buf[0], &config_rom[0], last_entry_offset << 2);
1686 
1687 	/* Return a handle to this block */
1688 	*handle = curr_blk;
1689 
1690 	*status = T1394_NOERROR;
1691 
1692 	return (DDI_SUCCESS);
1693 }
1694 
1695 /*
1696  * s1394_remove_config_rom_entry()
1697  *    is used to remove an entry from the local host's config ROM.  By
1698  *    specifying the Config ROM "handle" that was given in the allocation,
1699  *    it is possible to remove the entry.  Subsequently, the Config ROM is
1700  *    updated again.
1701  *    Callers must be holding the local_config_rom_mutex.
1702  */
1703 int
s1394_remove_config_rom_entry(s1394_hal_t * hal,void ** handle,int * status)1704 s1394_remove_config_rom_entry(s1394_hal_t *hal, void **handle, int *status)
1705 {
1706 	s1394_config_rom_t *del_blk;
1707 	s1394_config_rom_t *curr_blk;
1708 	s1394_config_rom_t *last_blk;
1709 	s1394_config_rom_t *free_blk;
1710 	uint32_t	   *config_rom;
1711 	uint32_t	   *temp_buf;
1712 	uint32_t	   entry;
1713 	uint_t		   CRC;
1714 	uint_t		   root_offset;
1715 	uint_t		   del_offset;
1716 	uint_t		   tmp_offset;
1717 	uint_t		   tmp_size;
1718 	int		   i;
1719 
1720 	ASSERT(MUTEX_HELD(&hal->local_config_rom_mutex));
1721 
1722 	del_blk = (s1394_config_rom_t *)(*handle);
1723 
1724 	config_rom = hal->local_config_rom;
1725 	temp_buf = hal->temp_config_rom_buf;
1726 
1727 	/* Copy the Bus_Info_Block */
1728 	bcopy(&config_rom[0], &temp_buf[0], IEEE1394_BIB_SZ);
1729 
1730 	root_offset = hal->root_directory->cfgrom_addr_lo;
1731 	del_offset = del_blk->root_dir_offset;
1732 
1733 	/* Update Root_Directory entries before the deleted one */
1734 	for (i = root_offset; i < del_offset; i++) {
1735 		entry = T1394_DATA32(config_rom[i]);
1736 
1737 		/* If entry is an offset address - update it */
1738 		if (entry & 0x80000000)
1739 			temp_buf[i] = T1394_DATA32(entry - 1);
1740 		else
1741 			temp_buf[i] = T1394_DATA32(entry);
1742 	}
1743 
1744 	/* Move all Unit_Directories prior to the deleted one */
1745 	curr_blk = hal->root_directory->cfgrom_next;
1746 
1747 	while (curr_blk != del_blk) {
1748 		tmp_offset = curr_blk->cfgrom_addr_lo;
1749 		tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
1750 
1751 		bcopy(&config_rom[tmp_offset], &temp_buf[tmp_offset - 1],
1752 		    tmp_size << 2);
1753 		curr_blk->cfgrom_addr_lo--;
1754 		curr_blk->cfgrom_addr_hi--;
1755 		curr_blk = curr_blk->cfgrom_next;
1756 	}
1757 
1758 	/* Move all Unit_Directories after the deleted one */
1759 	curr_blk = del_blk->cfgrom_next;
1760 	last_blk = del_blk->cfgrom_prev;
1761 
1762 	del_offset = (del_blk->cfgrom_addr_hi - del_blk->cfgrom_addr_lo) + 1;
1763 
1764 	while ((curr_blk != NULL) && (curr_blk->cfgrom_used == B_TRUE)) {
1765 		tmp_offset = curr_blk->cfgrom_addr_lo;
1766 		tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
1767 
1768 		bcopy(&config_rom[tmp_offset],
1769 		    &temp_buf[tmp_offset - (del_offset + 1)], tmp_size << 2);
1770 
1771 		root_offset = curr_blk->root_dir_offset;
1772 		temp_buf[root_offset - 1] =
1773 		    config_rom[root_offset] - del_offset;
1774 		curr_blk->root_dir_offset--;
1775 		curr_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo -
1776 		    (del_offset + 1);
1777 		curr_blk->cfgrom_addr_hi = curr_blk->cfgrom_addr_hi -
1778 		    (del_offset + 1);
1779 
1780 		last_blk = curr_blk;
1781 		curr_blk = curr_blk->cfgrom_next;
1782 	}
1783 
1784 	/* Remove del_blk from the list */
1785 	if (del_blk->cfgrom_prev != NULL)
1786 		del_blk->cfgrom_prev->cfgrom_next = del_blk->cfgrom_next;
1787 
1788 	if (del_blk->cfgrom_next != NULL)
1789 		del_blk->cfgrom_next->cfgrom_prev = del_blk->cfgrom_prev;
1790 
1791 	del_blk->cfgrom_prev = NULL;
1792 	del_blk->cfgrom_next = NULL;
1793 	kmem_free((void *)del_blk, sizeof (s1394_config_rom_t));
1794 
1795 	/* Update and zero out the "free" block */
1796 	if (curr_blk != NULL) {
1797 		curr_blk->cfgrom_addr_lo = curr_blk->cfgrom_addr_lo -
1798 		    (del_offset + 1);
1799 
1800 	} else {
1801 		free_blk = (s1394_config_rom_t *)kmem_zalloc(
1802 		    sizeof (s1394_config_rom_t), KM_SLEEP);
1803 		if (free_blk == NULL) {
1804 			return (DDI_FAILURE);
1805 		}
1806 
1807 		free_blk->cfgrom_used = B_FALSE;
1808 		free_blk->cfgrom_addr_lo = (IEEE1394_CONFIG_ROM_QUAD_SZ - 1) -
1809 		    (del_offset + 1);
1810 		free_blk->cfgrom_addr_hi = (IEEE1394_CONFIG_ROM_QUAD_SZ - 1);
1811 
1812 		free_blk->cfgrom_prev = last_blk;
1813 		free_blk->cfgrom_next = NULL;
1814 		curr_blk = free_blk;
1815 	}
1816 	hal->free_space = hal->free_space + (del_offset + 1);
1817 	tmp_offset = curr_blk->cfgrom_addr_lo;
1818 	tmp_size = (curr_blk->cfgrom_addr_hi - tmp_offset) + 1;
1819 	bzero(&temp_buf[tmp_offset], tmp_size << 2);
1820 
1821 
1822 	/* Update root directory */
1823 	hal->root_directory->cfgrom_addr_hi--;
1824 	tmp_offset = hal->root_directory->cfgrom_addr_lo;
1825 	tmp_size = hal->root_directory->cfgrom_addr_hi - tmp_offset;
1826 
1827 	/* Do byte-swapping if necessary (x86) */
1828 	for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
1829 	    i++)
1830 		temp_buf[i] = T1394_DATA32(temp_buf[i]);
1831 
1832 	CRC = s1394_CRC16(&temp_buf[tmp_offset + 1], tmp_size);
1833 	temp_buf[tmp_offset] = (tmp_size << IEEE1394_CFG_ROM_LEN_SHIFT) | CRC;
1834 
1835 	/* Do byte-swapping if necessary (x86) */
1836 	for (i = (tmp_offset + 1); i <= hal->root_directory->cfgrom_addr_hi;
1837 	    i++)
1838 		temp_buf[i] = T1394_DATA32(temp_buf[i]);
1839 
1840 	/* Copy it back to config_rom buffer */
1841 	tmp_size = IEEE1394_CONFIG_ROM_SZ - (hal->free_space << 2);
1842 	bcopy(&temp_buf[0], &config_rom[0], tmp_size);
1843 
1844 	/* Return a handle to this block */
1845 	*handle = NULL;
1846 
1847 	*status = T1394_NOERROR;
1848 
1849 	return (DDI_SUCCESS);
1850 }
1851 
1852 /*
1853  * s1394_update_config_rom_callback()
1854  *    is the callback used by t1394_add_cfgrom_entry() and
1855  *    t1394_rem_cfgrom_entry().  After a target updates the Config ROM, a
1856  *    timer is set with this as its callback function.  This is to reduce
1857  *    the number of bus resets that would be necessary if many targets
1858  *    wished to update the Config ROM simultaneously.
1859  */
1860 void
s1394_update_config_rom_callback(void * arg)1861 s1394_update_config_rom_callback(void *arg)
1862 {
1863 	s1394_hal_t	*hal;
1864 	uint32_t	*config_rom;
1865 	uint32_t	bus_capabilities;
1866 	uint32_t	g;
1867 	uint_t		CRC;
1868 	uint_t		last_entry_offset;
1869 	int		i;
1870 
1871 	hal = (s1394_hal_t *)arg;
1872 
1873 	/* Lock the Config ROM buffer */
1874 	mutex_enter(&hal->local_config_rom_mutex);
1875 
1876 	config_rom = hal->local_config_rom;
1877 
1878 	/* Update Generation and CRC for Bus_Info_Block */
1879 
1880 	/* Do byte-swapping if necessary (x86) */
1881 	for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
1882 		config_rom[i] = T1394_DATA32(config_rom[i]);
1883 
1884 	bus_capabilities = config_rom[IEEE1212_NODE_CAP_QUAD];
1885 	g = ((bus_capabilities & IEEE1394_BIB_GEN_MASK) >>
1886 	    IEEE1394_BIB_GEN_SHIFT) + 1;
1887 	if (g > 15)
1888 		g = 2;
1889 	g = g << IEEE1394_BIB_GEN_SHIFT;
1890 
1891 	bus_capabilities = (bus_capabilities & (~IEEE1394_BIB_GEN_MASK)) | g;
1892 	config_rom[IEEE1212_NODE_CAP_QUAD] = bus_capabilities;
1893 
1894 	CRC = s1394_CRC16(&config_rom[1], IEEE1394_BIB_QUAD_SZ - 1);
1895 	config_rom[0] = (0x04040000) | CRC;
1896 
1897 	/* Do byte-swapping if necessary (x86) */
1898 	for (i = 0; i < IEEE1394_BIB_QUAD_SZ; i++)
1899 		config_rom[i] = T1394_DATA32(config_rom[i]);
1900 
1901 	/* Make sure we update only what is necessary */
1902 	last_entry_offset = (IEEE1394_CONFIG_ROM_QUAD_SZ - hal->free_space);
1903 	if (last_entry_offset < hal->config_rom_update_amount)
1904 		last_entry_offset = hal->config_rom_update_amount;
1905 
1906 	hal->config_rom_update_amount = (IEEE1394_CONFIG_ROM_QUAD_SZ -
1907 	    hal->free_space);
1908 
1909 	/* Clear the timer flag */
1910 	hal->config_rom_timer_set = B_FALSE;
1911 
1912 	/* Unlock the Config ROM buffer */
1913 	mutex_exit(&hal->local_config_rom_mutex);
1914 
1915 	/*
1916 	 * The update_config_rom() call can return DDI_FAILURE if the
1917 	 * HAL is shutdown.
1918 	 */
1919 	(void) HAL_CALL(hal).update_config_rom(hal->halinfo.hal_private,\
1920 	    config_rom, last_entry_offset);
1921 
1922 	/* Initiate a bus reset */
1923 	(void) HAL_CALL(hal).bus_reset(hal->halinfo.hal_private);
1924 }
1925