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