Merge remote-tracking branch 'origin/master'
[unleashed/lotheac.git] / usr / src / uts / common / io / 1394 / adapters / hci1394_vendor.c
blobc0e647f0b59bf91e94c7ee795b78d636ef612dcd
1 /*
2 * CDDL HEADER START
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.
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.
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]
20 * CDDL HEADER END
23 * Copyright (c) 1999-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * hci1394_vendor.c
31 * These routines provide initialization, cleanup, and general access to
32 * vendor specific features on the OpenHCI adapter.
35 #include <sys/conf.h>
36 #include <sys/ddi.h>
37 #include <sys/modctl.h>
38 #include <sys/stat.h>
39 #include <sys/sunddi.h>
40 #include <sys/cmn_err.h>
41 #include <sys/kmem.h>
43 #include <sys/1394/adapters/hci1394.h>
47 * Macro which makes sure vendor register offset is not greater that 0x7FC and
48 * that it is quadlet aligned.
50 #define VENDOR_ALIGN_ADDR(addr) (addr & 0x7FC)
54 * Patchable variable to have the driver set the GUID on a Sun RIO chip.
55 * Normally this will be done by the firmware, but for PPX cards and OBP images
56 * without 1394 support, we need to fo this. This is only used for RIO. Other
57 * vendor cards are not effected.
58 * 0 - don't set GUID (default)
59 * non zero - set GUID on RIO
61 int hci1394_set_rio_guid = 0;
64 static int hci1394_rio_init(hci1394_vendor_t *vendor);
65 static void hci1394_rio_guid_init(hci1394_vendor_t *vendor);
66 static int hci1394_rio_resume(hci1394_vendor_t *vendor);
70 * hci1394_vendor_init()
71 * Initialize the Vendor Specific portions of the OpenHCI chipset. This is
72 * not required according to the OpenHCI spec, but may be needed for
73 * performance optimizations, etc. dip, accattrp, and vendor_info are inputs.
74 * num_reg_sets and vendor_handle are outputs. num_reg_sets is the number of
75 * registers sets (or mappings) that are present for this device. This will
76 * usually be 0 or 1. vendor_handle is an opaque handle used in rest of
77 * vendor routines.
79 int
80 hci1394_vendor_init(hci1394_drvinfo_t *drvinfo, hci1394_ohci_handle_t ohci,
81 hci1394_vendor_info_t *vendor_info, hci1394_vendor_handle_t *vendor_handle)
83 int status;
84 hci1394_vendor_t *vendor;
87 ASSERT(drvinfo != NULL);
88 ASSERT(vendor_info != NULL);
89 ASSERT(vendor_handle != NULL);
92 * alloc the space to keep track of the vendor registers.
94 vendor = kmem_alloc(sizeof (hci1394_vendor_t), KM_SLEEP);
95 vendor->ve_info = *vendor_info;
96 vendor->ve_drvinfo = drvinfo;
97 vendor->ve_ohci = ohci;
99 /* setup the vendor_handle return parameter */
100 *vendor_handle = vendor;
102 /* call vendor specific initialization routine */
103 switch (vendor_info->vendor_id) {
105 /* Sun Microsystems 1394 Device */
106 case VENDOR_VID_SUN_MICROSYSTEMS:
107 switch (vendor_info->device_id) {
109 /* RIO base chip. Call the RIO specific init routine */
110 case VENDOR_DID_RIO_1394:
111 status = hci1394_rio_init(vendor);
112 if (status != DDI_SUCCESS) {
113 kmem_free(vendor,
114 sizeof (hci1394_vendor_t));
115 *vendor_handle = NULL;
116 return (DDI_FAILURE);
118 break;
119 /* VENDOR_DID_RIO_1394 */
121 /* unrecognized device - don't map any registers */
122 default:
123 vendor->ve_reg_count = 0;
124 break;
126 break;
127 /* VENDOR_VID_SUN_MICROSYSTEMS */
129 /* unrecognized vendor - don't map any registers */
130 default:
131 vendor->ve_reg_count = 0;
132 break;
135 vendor_info->vendor_reg_count = vendor->ve_reg_count;
137 return (DDI_SUCCESS);
142 * hci1394_vendor_fini()
143 * Cleanup after Vendor Specific init. This includes freeing any allocated
144 * kernel memory and freeing any mapped registers.
146 * NOTE: This routine must be called after a successful vendor_init even if the
147 * num_reg_sets = 0 during init. This routine is normally called during
148 * the detach process.
150 * NOTE: A pointer to the handle is used for the parameter. fini() will set
151 * your handle to NULL before returning.
153 void
154 hci1394_vendor_fini(hci1394_vendor_handle_t *vendor_handle)
156 uint_t index;
159 ASSERT(vendor_handle != NULL);
161 for (index = 0; index < (*vendor_handle)->ve_reg_count; index++) {
162 ddi_regs_map_free(&(*vendor_handle)->
163 ve_reg_array[index]->vr_reg_handle);
165 kmem_free(*vendor_handle, sizeof (hci1394_vendor_t));
167 /* Set the vendor_handle to NULL to help catch bugs */
168 *vendor_handle = NULL;
173 * hci1394_vendor_resume()
174 * Vendor Specific init for a power resume (DDI_RESUME). This includes
175 * re-setting up any vendor specific registers.
178 hci1394_vendor_resume(hci1394_vendor_handle_t vendor_handle)
180 int status;
181 hci1394_vendor_info_t *vendor_info;
184 ASSERT(vendor_handle != NULL);
186 vendor_info = &vendor_handle->ve_info;
188 /* call vendor specific initialization routine */
189 switch (vendor_info->vendor_id) {
191 /* Sun Microsystems 1394 Device */
192 case VENDOR_VID_SUN_MICROSYSTEMS:
193 switch (vendor_info->device_id) {
195 /* RIO base chip. Call the RIO specific resume routine */
196 case VENDOR_DID_RIO_1394:
197 status = hci1394_rio_resume(vendor_handle);
198 if (status != DDI_SUCCESS) {
199 return (DDI_FAILURE);
201 break;
202 /* VENDOR_DID_RIO_1394 */
204 /* unrecognized device - don't map any registers */
205 default:
206 break;
208 break;
209 /* VENDOR_VID_SUN_MICROSYSTEMS */
211 /* unrecognized vendor - don't map any registers */
212 default:
213 break;
216 return (DDI_SUCCESS);
221 * hci1394_vendor_reg_write()
222 * Write vendor specific register. reg_set is the register set to write. The
223 * first register set would be reg_set = 0, the second reg_set = 1, etc.
224 * offset is the offset into the vendor specific register space. An offset of
225 * 0 would be the first vendor register for that register set. data is the
226 * data to write to the vendor register.
229 hci1394_vendor_reg_write(hci1394_vendor_handle_t vendor_handle,
230 uint_t reg_set, uint_t offset, uint32_t data)
232 hci1394_vendor_reg_t *venreg;
233 uint32_t *regaddr;
236 ASSERT(vendor_handle != NULL);
238 if (vendor_handle->ve_reg_count < (reg_set + 1)) {
239 return (DDI_FAILURE);
242 venreg = vendor_handle->ve_reg_array[reg_set];
243 regaddr = (uint32_t *)((uintptr_t)venreg->vr_reg_addr +
244 (uintptr_t)VENDOR_ALIGN_ADDR(offset));
246 ddi_put32(venreg->vr_reg_handle, regaddr, data);
248 return (DDI_SUCCESS);
253 * hci1394_vendor_reg_read()
254 * Read vendor specific register. reg_set is the register set to write. The
255 * first register set would be reg_set = 0, the second reg_set = 1, etc.
256 * offset is the offset into the vendor specific register space. An offset
257 * of 0 would be the first vendor register for that register set. data is
258 * the address to put the data read.
261 hci1394_vendor_reg_read(hci1394_vendor_handle_t vendor_handle, uint_t reg_set,
262 uint_t offset, uint32_t *data)
264 hci1394_vendor_reg_t *venreg;
265 uint32_t *regaddr;
268 ASSERT(vendor_handle != NULL);
269 ASSERT(data != NULL);
271 if (vendor_handle->ve_reg_count < (reg_set + 1)) {
272 return (DDI_FAILURE);
275 venreg = vendor_handle->ve_reg_array[reg_set];
276 regaddr = (uint32_t *)((uintptr_t)venreg->vr_reg_addr +
277 (uintptr_t)VENDOR_ALIGN_ADDR(offset));
279 *data = ddi_get32(venreg->vr_reg_handle, regaddr);
281 return (DDI_SUCCESS);
285 * hci1394_rio_init()
286 * Initialize SUNW RIO vendor specific registers.
288 static int
289 hci1394_rio_init(hci1394_vendor_t *vendor)
291 int status;
294 ASSERT(vendor != NULL);
296 vendor->ve_reg_count = 1;
297 vendor->ve_reg_array[0] = kmem_alloc(sizeof (hci1394_vendor_reg_t),
298 KM_SLEEP);
300 status = ddi_regs_map_setup(vendor->ve_drvinfo->di_dip, RIOREG_REG_BASE,
301 &vendor->ve_reg_array[0]->vr_reg_addr, RIOREG_OFFSET, RIOREG_LENGTH,
302 &vendor->ve_drvinfo->di_reg_attr,
303 &vendor->ve_reg_array[0]->vr_reg_handle);
304 if (status != DDI_SUCCESS) {
305 vendor->ve_reg_count = 0;
306 kmem_free(vendor->ve_reg_array[0],
307 sizeof (hci1394_vendor_reg_t));
308 return (DDI_FAILURE);
311 /* Setup RIO Host Control Register */
312 status = hci1394_vendor_reg_write(vendor, 0, RIOREG_HOST_CONTROL,
313 RIOREG_HOST_CONTROL_SETTING);
314 if (status != DDI_SUCCESS) {
315 ddi_regs_map_free(&vendor->ve_reg_array[0]->vr_reg_handle);
316 vendor->ve_reg_count = 0;
317 kmem_free(vendor->ve_reg_array[0],
318 sizeof (hci1394_vendor_reg_t));
319 vendor->ve_reg_array[0] = NULL;
320 return (DDI_FAILURE);
323 /* Setup GUID on RIO without firmware support */
324 hci1394_rio_guid_init(vendor);
326 return (DDI_SUCCESS);
331 * hci1394_rio_resume()
332 * Re-initialize RIO. This routine should be called during a resume.
334 static int
335 hci1394_rio_resume(hci1394_vendor_t *vendor)
337 int status;
340 ASSERT(vendor != NULL);
342 /* Setup RIO Host Control Register */
343 status = hci1394_vendor_reg_write(vendor, 0, RIOREG_HOST_CONTROL,
344 RIOREG_HOST_CONTROL_SETTING);
345 if (status != DDI_SUCCESS) {
346 return (DDI_FAILURE);
349 /* Setup GUID on RIO PPX */
350 hci1394_rio_guid_init(vendor);
352 return (DDI_SUCCESS);
357 * hci1394_rio_guid_init()
358 * Setup a GUID in the RIO. Normally firmware would do this for the
359 * motherboard version. This will not hurt a RIO on the motherboard since we
360 * won't be able to write the GUID. We should not get to this code anyway in
361 * production systems. Use a timestamp for the lower 40 bits of the GUID.
363 static void
364 hci1394_rio_guid_init(hci1394_vendor_t *vendor)
366 hrtime_t guid_timestamp;
368 ASSERT(vendor != NULL);
370 if (hci1394_set_rio_guid != 0) {
371 guid_timestamp = gethrtime();
373 /* mask out the vendor field of the GUID */
374 guid_timestamp = guid_timestamp & RIOREG_GUID_MASK;
376 /* fill in Sun Microsystems */
377 guid_timestamp = guid_timestamp | RIOREG_GUID_SUN_MICROSYSTEMS;
379 /* write this to the GUID registers */
380 ddi_put32(vendor->ve_ohci->ohci_reg_handle,
381 &vendor->ve_ohci->ohci_regs->guid_hi,
382 (uint32_t)(guid_timestamp >> 32));
383 ddi_put32(vendor->ve_ohci->ohci_reg_handle,
384 &vendor->ve_ohci->ohci_regs->guid_lo,
385 (uint32_t)(guid_timestamp & 0xFFFFFFFF));