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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 #pragma ident "%Z%%M% %I% %E% SMI" 26 27 /* 28 * USBA: Solaris USB Architecture support 29 * 30 * ISSUES: 31 */ 32 #define USBA_FRAMEWORK 33 #include <sys/usb/usba.h> 34 #include <sys/usb/usba/hcdi.h> 35 #include <sys/usb/usba/genconsole.h> 36 #include <sys/usb/usba/usba_types.h> 37 #include <sys/usb/usba/usba_impl.h> 38 39 /* 40 * Initialize USB polled support. This routine calls down to the lower 41 * layers to initialize any state information. 42 */ 43 int 44 usb_console_input_init(dev_info_t *dip, 45 usb_pipe_handle_t pipe_handle, 46 uchar_t **state_buf, 47 usb_console_info_t *console_input_info) 48 { 49 int ret; 50 usba_device_t *usba_device; 51 usb_console_info_impl_t *usb_console_input = kmem_zalloc( 52 sizeof (struct usb_console_info_impl), KM_SLEEP); 53 54 /* 55 * Save the dip 56 */ 57 usb_console_input->uci_dip = dip; 58 59 /* 60 * Translate the dip into a device. 61 */ 62 usba_device = usba_get_usba_device(dip); 63 64 /* 65 * Call the lower layer to initialize any state information 66 */ 67 ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_init( 68 usba_get_ph_data(pipe_handle), state_buf, usb_console_input); 69 70 if (ret != USB_SUCCESS) { 71 kmem_free(usb_console_input, 72 sizeof (struct usb_console_info_impl)); 73 } else { 74 *console_input_info = (usb_console_info_t)usb_console_input; 75 } 76 77 return (ret); 78 } 79 80 81 /* 82 * Free up any resources that we allocated in the above initialization 83 * routine. 84 */ 85 int 86 usb_console_input_fini(usb_console_info_t console_input_info) 87 { 88 usb_console_info_impl_t *usb_console_input; 89 usba_device_t *usba_device; 90 int ret; 91 92 usb_console_input = (usb_console_info_impl_t *)console_input_info; 93 94 /* 95 * Translate the dip into a device. 96 */ 97 usba_device = usba_get_usba_device(usb_console_input->uci_dip); 98 99 /* 100 * Call the lower layer to free any state information. 101 */ 102 ret = usba_device->usb_hcdi_ops->usba_hcdi_console_input_fini( 103 usb_console_input); 104 105 if (ret == USB_FAILURE) { 106 107 return (ret); 108 } 109 110 /* 111 * We won't be needing this information anymore. 112 */ 113 kmem_free(usb_console_input, sizeof (struct usb_console_info_impl)); 114 115 return (USB_SUCCESS); 116 } 117 118 119 /* 120 * This is the routine that OBP calls to save the USB state information 121 * before using the USB keyboard as an input device. This routine, 122 * and all of the routines that it calls, are responsible for saving 123 * any state information so that it can be restored when OBP mode is 124 * over. At this layer, this code is mainly just a pass through. 125 * 126 * Warning: this code runs in polled mode. 127 */ 128 int 129 usb_console_input_enter(usb_console_info_t console_input_info) 130 { 131 usba_device_t *usba_device; 132 usb_console_info_impl_t *usb_console_input; 133 134 usb_console_input = (usb_console_info_impl_t *)console_input_info; 135 136 /* 137 * Translate the dip into a device. 138 * Do this by directly looking at the dip, do not call 139 * usba_get_usba_device() because this function calls into the DDI. 140 * The ddi then tries to acquire a mutex and the machine hard hangs. 141 */ 142 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 143 144 /* 145 * Call the lower layer to save state information. 146 */ 147 usba_device->usb_hcdi_ops->usba_hcdi_console_input_enter( 148 usb_console_input); 149 150 return (USB_SUCCESS); 151 } 152 153 154 /* 155 * This is the routine that OBP calls when it wants to read a character. 156 * We will call to the lower layers to see if there is any input data 157 * available. At this layer, this code is mainly just a pass through. 158 * 159 * Warning: This code runs in polled mode. 160 */ 161 int 162 usb_console_read(usb_console_info_t console_input_info, uint_t *num_characters) 163 { 164 usba_device_t *usba_device; 165 usb_console_info_impl_t *usb_console_input; 166 167 usb_console_input = (usb_console_info_impl_t *)console_input_info; 168 169 /* 170 * Translate the dip into a device. 171 * Do this by directly looking at the dip, do not call 172 * usba_get_usba_device() because this function calls into the DDI. 173 * The ddi then tries to acquire a mutex and the machine hard hangs. 174 */ 175 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 176 177 /* 178 * Call the lower layer to get a a character. Return the number 179 * of characters read into the buffer. 180 */ 181 return (usba_device->usb_hcdi_ops->usba_hcdi_console_read( 182 usb_console_input, num_characters)); 183 } 184 185 186 /* 187 * This is the routine that OBP calls when it is giving up control of the 188 * USB keyboard. This routine, and the lower layer routines that it calls, 189 * are responsible for restoring the controller state to the state it was 190 * in before OBP took control. At this layer, this code is mainly just a 191 * pass through. 192 * 193 * Warning: This code runs in polled mode. 194 */ 195 int 196 usb_console_input_exit(usb_console_info_t console_input_info) 197 { 198 usba_device_t *usba_device; 199 usb_console_info_impl_t *usb_console_input; 200 201 usb_console_input = (usb_console_info_impl_t *)console_input_info; 202 203 /* 204 * Translate the dip into a device. 205 * Do this by directly looking at the dip, do not call 206 * usba_get_usba_device() because this function calls into the DDI. 207 * The ddi then tries to acquire a mutex and the machine hard hangs. 208 */ 209 usba_device = usba_polled_get_usba_device(usb_console_input->uci_dip); 210 211 /* 212 * Restore the state information. 213 */ 214 usba_device->usb_hcdi_ops->usba_hcdi_console_input_exit( 215 usb_console_input); 216 217 return (USB_SUCCESS); 218 } 219 220 /* 221 * Initialize USB OBP support. This routine calls down to the lower 222 * layers to initialize any state information. 223 */ 224 int 225 usb_console_output_init( 226 dev_info_t *dip, 227 usb_pipe_handle_t pipe_handle, 228 usb_console_info_t *console_output_info) 229 { 230 usba_device_t *usb_device; 231 usb_console_info_impl_t *usb_console_output; 232 int ret; 233 234 /* Translate the dip into a device and check hcdi ops */ 235 usb_device = usba_get_usba_device(dip); 236 if (usb_device->usb_hcdi_ops->usba_hcdi_ops_version < 237 HCDI_OPS_VERSION_1 || 238 usb_device->usb_hcdi_ops->usba_hcdi_console_output_init == NULL) 239 240 return (USB_FAILURE); 241 242 usb_console_output = kmem_zalloc(sizeof (struct usb_console_info_impl), 243 KM_SLEEP); 244 usb_console_output->uci_dip = dip; 245 246 /* 247 * Call the lower layer to initialize any state information 248 */ 249 ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_init( 250 usba_get_ph_data(pipe_handle), usb_console_output); 251 252 if (ret == USB_FAILURE) { 253 kmem_free(usb_console_output, 254 sizeof (struct usb_console_info_impl)); 255 256 return (ret); 257 } 258 259 *console_output_info = (usb_console_info_t)usb_console_output; 260 261 return (USB_SUCCESS); 262 } 263 264 /* 265 * Free up any resources that we allocated in the above initialization 266 * routine. 267 */ 268 int 269 usb_console_output_fini(usb_console_info_t console_output_info) 270 { 271 usb_console_info_impl_t *usb_console_output; 272 usba_device_t *usb_device; 273 int ret; 274 275 usb_console_output = (usb_console_info_impl_t *)console_output_info; 276 277 /* 278 * Translate the dip into a device. 279 */ 280 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 281 282 /* 283 * Call the lower layer to free any state information. 284 */ 285 ret = usb_device->usb_hcdi_ops->usba_hcdi_console_output_fini( 286 usb_console_output); 287 288 if (ret == USB_FAILURE) { 289 290 return (ret); 291 } 292 293 /* 294 * We won't be needing this information anymore. 295 */ 296 kmem_free(usb_console_output, sizeof (struct usb_console_info_impl)); 297 298 return (USB_SUCCESS); 299 } 300 301 /* 302 * This is the routine that OBP calls to save the USB state information 303 * before using the USB device as an output device. This routine, 304 * and all of the routines that it calls, are responsible for saving 305 * any state information so that it can be restored when OBP mode is 306 * over. At this layer, this code is mainly just a pass through. 307 */ 308 int 309 usb_console_output_enter(usb_console_info_t console_output_info) 310 { 311 usba_device_t *usb_device; 312 usb_console_info_impl_t *usb_console_output; 313 314 usb_console_output = (usb_console_info_impl_t *)console_output_info; 315 316 /* 317 * Translate the dip into a device. 318 */ 319 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 320 321 /* 322 * Call the lower layer to save state information. 323 */ 324 usb_device->usb_hcdi_ops->usba_hcdi_console_output_enter( 325 usb_console_output); 326 327 return (USB_SUCCESS); 328 } 329 330 /* 331 * This is the routine that OBP calls when it wants to write a character. 332 * We will call to the lower layers to write any data 333 * At this layer, this code is mainly just a pass through. 334 */ 335 int 336 usb_console_write(usb_console_info_t console_output_info, 337 uchar_t *buf, uint_t num_characters, uint_t *num_characters_written) 338 { 339 usba_device_t *usb_device; 340 usb_console_info_impl_t *usb_console_output; 341 342 usb_console_output = (usb_console_info_impl_t *)console_output_info; 343 344 /* 345 * Translate the dip into a device. 346 */ 347 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 348 349 /* 350 * Call the lower layer to get a a character. Return the number 351 * of characters read into the buffer. 352 */ 353 return (usb_device->usb_hcdi_ops->usba_hcdi_console_write( 354 usb_console_output, buf, num_characters, 355 num_characters_written)); 356 } 357 358 /* 359 * This is the routine that OBP calls when it is giving up control of the 360 * USB output device. This routine, and the lower layer routines that it 361 * calls, are responsible for restoring the controller state to the state 362 * it was in before OBP took control. At this layer, this code is mainly 363 * just a pass through. 364 */ 365 int 366 usb_console_output_exit(usb_console_info_t console_output_info) 367 { 368 usba_device_t *usb_device; 369 usb_console_info_impl_t *usb_console_output; 370 371 usb_console_output = (usb_console_info_impl_t *)console_output_info; 372 373 /* 374 * Translate the dip into a device. 375 */ 376 usb_device = usba_polled_get_usba_device(usb_console_output->uci_dip); 377 378 /* 379 * Restore the state information. 380 */ 381 usb_device->usb_hcdi_ops->usba_hcdi_console_output_exit( 382 usb_console_output); 383 384 return (USB_SUCCESS); 385 } 386