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  * hci1394_vendor.c
29  *   These routines provide initialization, cleanup, and general access to
30  *   vendor specific features on the OpenHCI adapter.
31  */
32 
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/kmem.h>
40 
41 #include <sys/1394/adapters/hci1394.h>
42 
43 
44 /*
45  * Macro which makes sure vendor register offset is not greater that 0x7FC and
46  * that it is quadlet aligned.
47  */
48 #define	VENDOR_ALIGN_ADDR(addr)	(addr & 0x7FC)
49 
50 
51 /*
52  * Patchable variable to have the driver set the GUID on a Sun RIO chip.
53  * Normally this will be done by the firmware, but for PPX cards and OBP images
54  * without 1394 support, we need to fo this. This is only used for RIO.  Other
55  * vendor cards are not effected.
56  *   0 - don't set GUID (default)
57  *   non zero - set GUID on RIO
58  */
59 int hci1394_set_rio_guid = 0;
60 
61 
62 static int hci1394_rio_init(hci1394_vendor_t *vendor);
63 static void hci1394_rio_guid_init(hci1394_vendor_t *vendor);
64 static int hci1394_rio_resume(hci1394_vendor_t *vendor);
65 
66 
67 /*
68  * hci1394_vendor_init()
69  *    Initialize the Vendor Specific portions of the OpenHCI chipset. This is
70  *    not required according to the OpenHCI spec, but may be needed for
71  *    performance optimizations, etc. dip, accattrp, and vendor_info are inputs.
72  *    num_reg_sets and vendor_handle are outputs. num_reg_sets is the number of
73  *    registers sets (or mappings) that are present for this device. This will
74  *    usually be 0 or 1. vendor_handle is an opaque handle used in rest of
75  *    vendor routines.
76  */
77 int
hci1394_vendor_init(hci1394_drvinfo_t * drvinfo,hci1394_ohci_handle_t ohci,hci1394_vendor_info_t * vendor_info,hci1394_vendor_handle_t * vendor_handle)78 hci1394_vendor_init(hci1394_drvinfo_t *drvinfo,  hci1394_ohci_handle_t ohci,
79     hci1394_vendor_info_t *vendor_info, hci1394_vendor_handle_t *vendor_handle)
80 {
81 	int status;
82 	hci1394_vendor_t *vendor;
83 
84 
85 	ASSERT(drvinfo != NULL);
86 	ASSERT(vendor_info != NULL);
87 	ASSERT(vendor_handle != NULL);
88 
89 	/*
90 	 * alloc the space to keep track of the vendor registers.
91 	 */
92 	vendor = kmem_alloc(sizeof (hci1394_vendor_t), KM_SLEEP);
93 	vendor->ve_info = *vendor_info;
94 	vendor->ve_drvinfo = drvinfo;
95 	vendor->ve_ohci = ohci;
96 
97 	/* setup the vendor_handle return parameter */
98 	*vendor_handle = vendor;
99 
100 	/* call vendor specific initialization routine */
101 	switch (vendor_info->vendor_id) {
102 
103 	/* Sun Microsystems 1394 Device */
104 	case VENDOR_VID_SUN_MICROSYSTEMS:
105 		switch (vendor_info->device_id) {
106 
107 		/* RIO base chip. Call the RIO specific init routine */
108 		case VENDOR_DID_RIO_1394:
109 			status = hci1394_rio_init(vendor);
110 			if (status != DDI_SUCCESS) {
111 				kmem_free(vendor,
112 				    sizeof (hci1394_vendor_t));
113 				*vendor_handle = NULL;
114 				return (DDI_FAILURE);
115 			}
116 			break;
117 			/* VENDOR_DID_RIO_1394 */
118 
119 		/* unrecognized device - don't map any registers */
120 		default:
121 			vendor->ve_reg_count = 0;
122 			break;
123 		}
124 		break;
125 		/* VENDOR_VID_SUN_MICROSYSTEMS */
126 
127 	/* unrecognized vendor - don't map any registers */
128 	default:
129 		vendor->ve_reg_count = 0;
130 		break;
131 	}
132 
133 	vendor_info->vendor_reg_count = vendor->ve_reg_count;
134 
135 	return (DDI_SUCCESS);
136 }
137 
138 
139 /*
140  * hci1394_vendor_fini()
141  *    Cleanup after Vendor Specific init.  This includes freeing any allocated
142  *    kernel memory and freeing any mapped registers.
143  *
144  * NOTE: This routine must be called after a successful vendor_init even if the
145  *	 num_reg_sets = 0 during init.  This routine is normally called during
146  *	 the detach process.
147  *
148  * NOTE: A pointer to the handle is used for the parameter. fini() will set
149  *	 your handle to NULL before returning.
150  */
151 void
hci1394_vendor_fini(hci1394_vendor_handle_t * vendor_handle)152 hci1394_vendor_fini(hci1394_vendor_handle_t *vendor_handle)
153 {
154 	uint_t index;
155 
156 
157 	ASSERT(vendor_handle != NULL);
158 
159 	for (index = 0; index < (*vendor_handle)->ve_reg_count; index++) {
160 		ddi_regs_map_free(&(*vendor_handle)->
161 		    ve_reg_array[index]->vr_reg_handle);
162 	}
163 	kmem_free(*vendor_handle, sizeof (hci1394_vendor_t));
164 
165 	/* Set the vendor_handle to NULL to help catch bugs */
166 	*vendor_handle = NULL;
167 }
168 
169 
170 /*
171  * hci1394_vendor_resume()
172  *    Vendor Specific init for a power resume (DDI_RESUME). This includes
173  *    re-setting up any vendor specific registers.
174  */
175 int
hci1394_vendor_resume(hci1394_vendor_handle_t vendor_handle)176 hci1394_vendor_resume(hci1394_vendor_handle_t vendor_handle)
177 {
178 	int status;
179 	hci1394_vendor_info_t *vendor_info;
180 
181 
182 	ASSERT(vendor_handle != NULL);
183 
184 	vendor_info = &vendor_handle->ve_info;
185 
186 	/* call vendor specific initialization routine */
187 	switch (vendor_info->vendor_id) {
188 
189 	/* Sun Microsystems 1394 Device */
190 	case VENDOR_VID_SUN_MICROSYSTEMS:
191 		switch (vendor_info->device_id) {
192 
193 		/* RIO base chip. Call the RIO specific resume routine */
194 		case VENDOR_DID_RIO_1394:
195 			status = hci1394_rio_resume(vendor_handle);
196 			if (status != DDI_SUCCESS) {
197 				return (DDI_FAILURE);
198 			}
199 			break;
200 			/* VENDOR_DID_RIO_1394 */
201 
202 		/* unrecognized device - don't map any registers */
203 		default:
204 			break;
205 		}
206 		break;
207 		/* VENDOR_VID_SUN_MICROSYSTEMS */
208 
209 	/* unrecognized vendor - don't map any registers */
210 	default:
211 		break;
212 	}
213 
214 	return (DDI_SUCCESS);
215 }
216 
217 
218 /*
219  * hci1394_vendor_reg_write()
220  *    Write vendor specific register. reg_set is the register set to write. The
221  *    first register set would be reg_set = 0, the second reg_set = 1, etc.
222  *    offset is the offset into the vendor specific register space. An offset of
223  *    0 would be the first vendor register for that register set. data is the
224  *    data to write to the vendor register.
225  */
226 int
hci1394_vendor_reg_write(hci1394_vendor_handle_t vendor_handle,uint_t reg_set,uint_t offset,uint32_t data)227 hci1394_vendor_reg_write(hci1394_vendor_handle_t vendor_handle,
228     uint_t reg_set, uint_t offset, uint32_t data)
229 {
230 	hci1394_vendor_reg_t *venreg;
231 	uint32_t *regaddr;
232 
233 
234 	ASSERT(vendor_handle != NULL);
235 
236 	if (vendor_handle->ve_reg_count < (reg_set + 1)) {
237 		return (DDI_FAILURE);
238 	}
239 
240 	venreg = vendor_handle->ve_reg_array[reg_set];
241 	regaddr = (uint32_t *)((uintptr_t)venreg->vr_reg_addr +
242 	    (uintptr_t)VENDOR_ALIGN_ADDR(offset));
243 
244 	ddi_put32(venreg->vr_reg_handle, regaddr, data);
245 
246 	return (DDI_SUCCESS);
247 }
248 
249 
250 /*
251  * hci1394_vendor_reg_read()
252  *    Read vendor specific register. reg_set is the register set to write. The
253  *    first register set would be reg_set = 0, the second reg_set = 1, etc.
254  *    offset is the offset into the vendor specific register space. An offset
255  *    of 0 would be the first vendor register for that register set. data is
256  *    the address to put the data read.
257  */
258 int
hci1394_vendor_reg_read(hci1394_vendor_handle_t vendor_handle,uint_t reg_set,uint_t offset,uint32_t * data)259 hci1394_vendor_reg_read(hci1394_vendor_handle_t vendor_handle, uint_t reg_set,
260     uint_t offset, uint32_t *data)
261 {
262 	hci1394_vendor_reg_t *venreg;
263 	uint32_t *regaddr;
264 
265 
266 	ASSERT(vendor_handle != NULL);
267 	ASSERT(data != NULL);
268 
269 	if (vendor_handle->ve_reg_count < (reg_set + 1)) {
270 		return (DDI_FAILURE);
271 	}
272 
273 	venreg = vendor_handle->ve_reg_array[reg_set];
274 	regaddr = (uint32_t *)((uintptr_t)venreg->vr_reg_addr +
275 	    (uintptr_t)VENDOR_ALIGN_ADDR(offset));
276 
277 	*data = ddi_get32(venreg->vr_reg_handle, regaddr);
278 
279 	return (DDI_SUCCESS);
280 }
281 
282 /*
283  * hci1394_rio_init()
284  *    Initialize SUNW RIO vendor specific registers.
285  */
286 static int
hci1394_rio_init(hci1394_vendor_t * vendor)287 hci1394_rio_init(hci1394_vendor_t *vendor)
288 {
289 	int status;
290 
291 
292 	ASSERT(vendor != NULL);
293 
294 	vendor->ve_reg_count = 1;
295 	vendor->ve_reg_array[0] = kmem_alloc(sizeof (hci1394_vendor_reg_t),
296 	    KM_SLEEP);
297 
298 	status = ddi_regs_map_setup(vendor->ve_drvinfo->di_dip, RIOREG_REG_BASE,
299 	    &vendor->ve_reg_array[0]->vr_reg_addr, RIOREG_OFFSET, RIOREG_LENGTH,
300 	    &vendor->ve_drvinfo->di_reg_attr,
301 	    &vendor->ve_reg_array[0]->vr_reg_handle);
302 	if (status != DDI_SUCCESS) {
303 		vendor->ve_reg_count = 0;
304 		kmem_free(vendor->ve_reg_array[0],
305 		    sizeof (hci1394_vendor_reg_t));
306 		return (DDI_FAILURE);
307 	}
308 
309 	/* Setup RIO Host Control Register */
310 	status = hci1394_vendor_reg_write(vendor, 0, RIOREG_HOST_CONTROL,
311 	    RIOREG_HOST_CONTROL_SETTING);
312 	if (status != DDI_SUCCESS) {
313 		ddi_regs_map_free(&vendor->ve_reg_array[0]->vr_reg_handle);
314 		vendor->ve_reg_count = 0;
315 		kmem_free(vendor->ve_reg_array[0],
316 		    sizeof (hci1394_vendor_reg_t));
317 		vendor->ve_reg_array[0] = NULL;
318 		return (DDI_FAILURE);
319 	}
320 
321 	/* Setup GUID on RIO without firmware support */
322 	hci1394_rio_guid_init(vendor);
323 
324 	return (DDI_SUCCESS);
325 }
326 
327 
328 /*
329  * hci1394_rio_resume()
330  *    Re-initialize RIO.  This routine should be called during a resume.
331  */
332 static int
hci1394_rio_resume(hci1394_vendor_t * vendor)333 hci1394_rio_resume(hci1394_vendor_t *vendor)
334 {
335 	int status;
336 
337 
338 	ASSERT(vendor != NULL);
339 
340 	/* Setup RIO Host Control Register */
341 	status = hci1394_vendor_reg_write(vendor, 0, RIOREG_HOST_CONTROL,
342 	    RIOREG_HOST_CONTROL_SETTING);
343 	if (status != DDI_SUCCESS) {
344 		return (DDI_FAILURE);
345 	}
346 
347 	/* Setup GUID on RIO PPX */
348 	hci1394_rio_guid_init(vendor);
349 
350 	return (DDI_SUCCESS);
351 }
352 
353 
354 /*
355  * hci1394_rio_guid_init()
356  *    Setup a GUID in the RIO. Normally firmware would do this for the
357  *    motherboard version. This will not hurt a RIO  on the motherboard since we
358  *    won't be able to write the GUID. We should not get to this code anyway in
359  *    production systems.  Use a timestamp for the lower 40 bits of the GUID.
360  */
361 static void
hci1394_rio_guid_init(hci1394_vendor_t * vendor)362 hci1394_rio_guid_init(hci1394_vendor_t *vendor)
363 {
364 	hrtime_t guid_timestamp;
365 
366 	ASSERT(vendor != NULL);
367 
368 	if (hci1394_set_rio_guid != 0) {
369 		guid_timestamp = gethrtime();
370 
371 		/* mask out the vendor field of the GUID */
372 		guid_timestamp = guid_timestamp & RIOREG_GUID_MASK;
373 
374 		/* fill in Sun Microsystems */
375 		guid_timestamp = guid_timestamp | RIOREG_GUID_SUN_MICROSYSTEMS;
376 
377 		/* write this to the GUID registers */
378 		ddi_put32(vendor->ve_ohci->ohci_reg_handle,
379 		    &vendor->ve_ohci->ohci_regs->guid_hi,
380 		    (uint32_t)(guid_timestamp >> 32));
381 		ddi_put32(vendor->ve_ohci->ohci_reg_handle,
382 		    &vendor->ve_ohci->ohci_regs->guid_lo,
383 		    (uint32_t)(guid_timestamp & 0xFFFFFFFF));
384 	}
385 }
386