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