1/* 2 * Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the Haiku License. 4 */ 5 6#include <new> 7 8#include <stdio.h> 9#include <stdlib.h> 10#include <string.h> 11 12#include <lock.h> 13 14#include "tty_private.h" 15 16 17//#define TTY_TRACE 18#ifdef TTY_TRACE 19# define TRACE(x) dprintf x 20#else 21# define TRACE(x) 22#endif 23 24#define DRIVER_NAME "tty" 25 26static const int kMaxCachedSemaphores = 8; 27 28int32 api_version = B_CUR_DRIVER_API_VERSION; 29 30char *gDeviceNames[kNumTTYs * 2 + 3]; 31 // reserve space for "pt/" and "tt/" entries, "ptmx", "tty", and the 32 // terminating NULL 33 34static mutex sTTYLocks[kNumTTYs]; 35 36struct mutex gGlobalTTYLock; 37struct mutex gTTYCookieLock; 38struct recursive_lock gTTYRequestLock; 39 40 41status_t 42init_hardware(void) 43{ 44 TRACE((DRIVER_NAME ": init_hardware()\n")); 45 return B_OK; 46} 47 48 49status_t 50init_driver(void) 51{ 52 TRACE((DRIVER_NAME ": init_driver()\n")); 53 54 memset(gDeviceNames, 0, sizeof(gDeviceNames)); 55 56 // create the request mutex 57 recursive_lock_init(&gTTYRequestLock, "tty requests"); 58 59 // create the global mutex 60 mutex_init(&gGlobalTTYLock, "tty global"); 61 62 // create the cookie mutex 63 mutex_init(&gTTYCookieLock, "tty cookies"); 64 65 // create driver name array and initialize basic TTY structures 66 67 char letter = 'p'; 68 int8 digit = 0; 69 70 for (uint32 i = 0; i < kNumTTYs; i++) { 71 // For compatibility, we have to create the same mess in /dev/pt and 72 // /dev/tt as BeOS does: we publish devices p0, p1, ..., pf, r1, ..., 73 // sf. It would be nice if we could drop compatibility and create 74 // something better. In fact we already don't need the master devices 75 // anymore, since "/dev/ptmx" does the job. The slaves entries could 76 // be published on the fly when a master is opened (e.g via 77 // vfs_create_special_node()). 78 char buffer[64]; 79 80 snprintf(buffer, sizeof(buffer), "pt/%c%x", letter, digit); 81 gDeviceNames[i] = strdup(buffer); 82 83 snprintf(buffer, sizeof(buffer), "tt/%c%x", letter, digit); 84 gDeviceNames[i + kNumTTYs] = strdup(buffer); 85 86 if (++digit > 15) 87 digit = 0, letter++; 88 89 mutex_init(&sTTYLocks[i], "tty lock"); 90 reset_tty(&gMasterTTYs[i], i, &sTTYLocks[i], true); 91 reset_tty(&gSlaveTTYs[i], i, &sTTYLocks[i], false); 92 reset_tty_settings(&gTTYSettings[i], i); 93 94 if (!gDeviceNames[i] || !gDeviceNames[i + kNumTTYs]) { 95 uninit_driver(); 96 return B_NO_MEMORY; 97 } 98 } 99 100 gDeviceNames[2 * kNumTTYs] = (char *)"ptmx"; 101 gDeviceNames[2 * kNumTTYs + 1] = (char *)"tty"; 102 103 tty_add_debugger_commands(); 104 105 return B_OK; 106} 107 108 109void 110uninit_driver(void) 111{ 112 TRACE((DRIVER_NAME ": uninit_driver()\n")); 113 114 tty_remove_debugger_commands(); 115 116 for (int32 i = 0; i < (int32)kNumTTYs * 2; i++) 117 free(gDeviceNames[i]); 118 119 for (int32 i = 0; i < (int32)kNumTTYs; i++) 120 mutex_destroy(&sTTYLocks[i]); 121 122 recursive_lock_destroy(&gTTYRequestLock); 123 mutex_destroy(&gTTYCookieLock); 124 mutex_destroy(&gGlobalTTYLock); 125} 126 127 128const char ** 129publish_devices(void) 130{ 131 TRACE((DRIVER_NAME ": publish_devices()\n")); 132 return const_cast<const char **>(gDeviceNames); 133} 134 135 136device_hooks * 137find_device(const char *name) 138{ 139 TRACE((DRIVER_NAME ": find_device(\"%s\")\n", name)); 140 141 for (uint32 i = 0; gDeviceNames[i] != NULL; i++) 142 if (!strcmp(name, gDeviceNames[i])) { 143 return i < kNumTTYs || i == (2 * kNumTTYs) 144 ? &gMasterTTYHooks : &gSlaveTTYHooks; 145 } 146 147 return NULL; 148} 149 150