예제 #1
0
static status_t
acpi_namespace_open(void *_cookie, const char* path, int flags, void** cookie)
{
	acpi_ns_device_info *device = (acpi_ns_device_info *)_cookie;

	dprintf("\nacpi_ns_dump: device_open\n");

	*cookie = device;

	RingBuffer *ringBuffer = new RingBuffer(1024);
	if (ringBuffer == NULL)
		return B_NO_MEMORY;

	device->read_sem = create_sem(0, "read_sem");
	if (device->read_sem < B_OK) {
		delete ringBuffer;
		return device->read_sem;
	}

	device->thread = spawn_kernel_thread(acpi_namespace_dump, "acpi dumper",
		 B_NORMAL_PRIORITY, device);
	if (device->thread < 0) {
		delete ringBuffer;
		delete_sem(device->read_sem);
		return device->thread;
	}

	device->buffer = ringBuffer;

	resume_thread(device->thread);

	return B_OK;
}
예제 #2
0
status_t
JoystickProtocolHandler::Open(uint32 flags, uint32 *cookie)
{
	if (fCurrentValues.data == NULL)
		return B_NO_INIT;

	status_t result = mutex_lock(&fUpdateLock);
	if (result != B_OK)
		return result;

	if (fUpdateThread < 0) {
		fUpdateThread = spawn_kernel_thread(_UpdateThread, "joystick update",
			B_NORMAL_PRIORITY, (void *)this);

		if (fUpdateThread < 0)
			result = fUpdateThread;
		else
			resume_thread(fUpdateThread);
	}

	if (result == B_OK)
		fOpenCount++;

	mutex_unlock(&fUpdateLock);
	if (result != B_OK)
		return result;

	return ProtocolHandler::Open(flags, cookie);
}
예제 #3
0
void __attribute__((noreturn)) kernel_main(unsigned int _memory_size)
{
    struct vm_translation_map *init_map;
    struct process *init_proc;

    vm_page_init(_memory_size);
    init_map = vm_translation_map_init();
    boot_init_heap((char*) KERNEL_HEAP_BASE + PAGE_STRUCTURES_SIZE(_memory_size));
    vm_address_space_init(init_map);
    bootstrap_vm_cache();
    bool_init_kernel_process();
    boot_init_thread();

    // Start other threads
    REGISTERS[REG_THREAD_RESUME] = 0xffffffff;

    spawn_kernel_thread("Grim Reaper", grim_reaper, 0);

    init_proc = exec_program("program.elf");

    // Idle task
    for (;;)
    {
        if (list_is_empty(&init_proc->thread_list))
        {
            kprintf("init process has exited, shutting down\n");
            REGISTERS[REG_THREAD_HALT] = 0xffffffff;
        }

        reschedule();
    }
}
예제 #4
0
status_t
ps2_service_init(void)
{
	TRACE("ps2: ps2_service_init\n");
	sServiceCmdBuffer = create_packet_buffer(sizeof(ps2_service_cmd) * 50);
	if (sServiceCmdBuffer == NULL)
		goto err1;
	sServiceSem = create_sem(0, "ps2 service");
	if (sServiceSem < B_OK)
		goto err2;
	sServiceThread = spawn_kernel_thread(ps2_service_thread, "ps2 service", 20, NULL);
	if (sServiceThread < B_OK)
		goto err3;
	sServiceTerminate = false;
	resume_thread(sServiceThread);

#ifdef DEBUG_PUBLISHING
	add_debugger_command("ps2republish", &ps2_republish, "republish a ps2 device (0-3 mouse, 4 keyb (default))");
#endif

	TRACE("ps2: ps2_service_init done\n");
	return B_OK;

err3:
	delete_sem(sServiceSem);
err2:
	delete_packet_buffer(sServiceCmdBuffer);
err1:
	TRACE("ps2: ps2_service_init failed\n");
	return B_ERROR;
}
예제 #5
0
status_t
init_callout(void)
{
    list_init(&sTimers);
    sTimeout = B_INFINITE_TIMEOUT;

    status_t status = B_OK;
    mutex_init(&sLock, "fbsd callout");

    sWaitSem = create_sem(0, "fbsd callout wait");
    if (sWaitSem < 0) {
        status = sWaitSem;
        goto err1;
    }

    sThread = spawn_kernel_thread(callout_thread, "fbsd callout",
                                  B_DISPLAY_PRIORITY, NULL);
    if (sThread < 0) {
        status = sThread;
        goto err2;
    }

    return resume_thread(sThread);

err1:
    mutex_destroy(&sLock);
err2:
    delete_sem(sWaitSem);
    return status;
}
예제 #6
0
// _InitBroadcastListener
status_t
ServerManager::_InitBroadcastListener()
{
	// create a socket
	fBroadcastListenerSocket = socket(AF_INET, SOCK_DGRAM, 0);
	if (fBroadcastListenerSocket < 0)
		return errno;
	// bind it to the port
	sockaddr_in addr;
	addr.sin_family = AF_INET;
	addr.sin_port = htons(kDefaultBroadcastPort);
	addr.sin_addr.s_addr = INADDR_ANY;
	if (bind(fBroadcastListenerSocket, (sockaddr*)&addr, sizeof(addr)) < 0) {
		ERROR("ServerManager::_InitBroadcastListener(): ERROR: bind()ing the "
			"broadcasting socket failed: %s\n", strerror(errno));
		safe_closesocket(fBroadcastListenerSocket);
		return errno;
	}
	// spawn the thread
	#if USER
		fBroadcastListener = spawn_thread(&_BroadcastListenerEntry,
			"broadcast listener", B_NORMAL_PRIORITY, this);
	#else
		fBroadcastListener = spawn_kernel_thread(&_BroadcastListenerEntry,
			"broadcast listener", B_NORMAL_PRIORITY, this);
	#endif
	if (fBroadcastListener < 0)
		return fBroadcastListener;
	return B_OK;
}
예제 #7
0
static status_t
std_ops(int32 op, ...)
{
	if (op == B_MODULE_INIT) {
		sRequestSem = create_sem(0, "run_on_exit_request");
		if (sRequestSem < B_OK)
			return sRequestSem;

		thread_id thread = spawn_kernel_thread(&run_on_exit_loop,
			"run_on_exit_loop", B_NORMAL_PRIORITY, NULL);
		if (thread < B_OK)
			return thread;

		send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE);

		add_debugger_command_etc("on_exit", &add_run_on_exit_command,
			"Adds a command to be run when leaving the kernel debugger",
			"<command> [<arguments>]\n"
			"Adds a command to be run when leaving the kernel debugger.\n", 0);

		return B_OK;
	} else if (op == B_MODULE_UNINIT) {
		remove_debugger_command("on_exit", &add_run_on_exit_command);
		// deleting the sem will also cause the thread to exit
		delete_sem(sRequestSem);
		sRequestSem = -1;
		return B_OK;
	}

	return B_BAD_VALUE;
}
예제 #8
0
파일: ethernet.cpp 프로젝트: luciang/haiku
status_t
ethernet_up(net_device *_device)
{
	ethernet_device *device = (ethernet_device *)_device;

	device->fd = open(device->name, O_RDWR);
	if (device->fd < 0)
		return errno;

	uint64 dummy;
	if (ioctl(device->fd, ETHER_INIT, &dummy, sizeof(dummy)) < 0)
		goto err;

	if (ioctl(device->fd, ETHER_GETADDR, device->address.data, ETHER_ADDRESS_LENGTH) < 0)
		goto err;

	if (ioctl(device->fd, ETHER_GETFRAMESIZE, &device->frame_size, sizeof(uint32)) < 0) {
		// this call is obviously optional
		device->frame_size = ETHER_MAX_FRAME_SIZE;
	}

	if (update_link_state(device, false) == B_OK) {
		// device supports retrieval of the link state

		// Set the change notification semaphore; doesn't matter
		// if this is supported by the device or not
		ioctl(device->fd, ETHER_SET_LINK_STATE_SEM, &sLinkChangeSemaphore,
			sizeof(sem_id));

		MutexLocker _(&sListLock);

		if (sCheckList.IsEmpty()) {
			// start thread
			sLinkCheckerThread = spawn_kernel_thread(ethernet_link_checker,
				"ethernet link state checker", B_LOW_PRIORITY, NULL);
			if (sLinkCheckerThread >= B_OK)
				resume_thread(sLinkCheckerThread);
		}

		sCheckList.Add(device);
	}

	device->address.length = ETHER_ADDRESS_LENGTH;
	device->mtu = device->frame_size - device->header_length;
	return B_OK;

err:
	close(device->fd);
	device->fd = -1;
	return errno;
}
예제 #9
0
DECLHIDDEN(int) rtThreadNativeCreate(PRTTHREADINT pThreadInt, PRTNATIVETHREAD pNativeThread)
{
    thread_id NativeThread;
    RT_ASSERT_PREEMPTIBLE();

    NativeThread = spawn_kernel_thread(rtThreadNativeMain, pThreadInt->szName, B_NORMAL_PRIORITY, pThreadInt);
    if (NativeThread >= B_OK)
    {
        resume_thread(NativeThread);
        *pNativeThread = (RTNATIVETHREAD)NativeThread;
        return VINF_SUCCESS;
    }
    return RTErrConvertFromHaikuKernReturn(NativeThread);
}
예제 #10
0
status_t
low_resource_manager_init_post_thread(void)
{
	sLowResourceWaitSem = create_sem(0, "low resource wait");
	if (sLowResourceWaitSem < B_OK)
		return sLowResourceWaitSem;

	thread_id thread = spawn_kernel_thread(&low_resource_manager,
		"low resource manager", B_LOW_PRIORITY, NULL);
	send_signal_etc(thread, SIGCONT, B_DO_NOT_RESCHEDULE);

	add_debugger_command("low_resource", &dump_handlers,
		"Dump list of low resource handlers");
	return B_OK;
}
예제 #11
0
// Run
status_t
Task::Run()
{
	const char* name = (fName.GetLength() > 0 ? fName.GetString() : "task");
#if USER
	fThread = spawn_thread(&_ThreadEntry, name, B_NORMAL_PRIORITY, this);
#else
	fThread = spawn_kernel_thread(&_ThreadEntry, name, B_NORMAL_PRIORITY, this);
#endif
	if (fThread < 0)
		return fThread;
	fDone = false;
	resume_thread(fThread);
	return B_OK;
}
예제 #12
0
status_t
SerialDevice::Open(uint32 flags)
{
	if (fDeviceOpen)
		return B_BUSY;

	if (fDeviceRemoved)
		return B_DEV_NOT_READY;

	gTTYModule->ttyinit(&fTTY, true);
	fTTYFile.tty = &fTTY;
	fTTYFile.flags = flags;
	ResetDevice();

	struct ddrover *ddr = gTTYModule->ddrstart(NULL);
	if (!ddr)
		return B_NO_MEMORY;

	gTTYModule->ddacquire(ddr, &gSerialDomain);
	status_t status = gTTYModule->ttyopen(&fTTYFile, ddr, usb_serial_service);
	gTTYModule->ddrdone(ddr);

	if (status < B_OK) {
		TRACE_ALWAYS("open: failed to open tty\n");
		return status;
	}

	fDeviceThread = spawn_kernel_thread(DeviceThread, "usb_serial device thread",
		B_NORMAL_PRIORITY, this);

	if (fDeviceThread < B_OK) {
		TRACE_ALWAYS("open: failed to spawn kernel thread\n");
		return fDeviceThread;
	}

	resume_thread(fDeviceThread);

	fControlOut = CLS_LINE_DTR | CLS_LINE_RTS;
	SetControlLineState(fControlOut);

	status = gUSBModule->queue_interrupt(fControlPipe, fInterruptBuffer,
		fInterruptBufferSize, InterruptCallbackFunction, this);
	if (status < B_OK)
		TRACE_ALWAYS("failed to queue initial interrupt\n");

	fDeviceOpen = true;
	return B_OK;
}
예제 #13
0
void
slab_init_post_thread()
{
	new(&sMaintenanceQueue) MaintenanceQueue;
	sMaintenanceCondition.Init(&sMaintenanceQueue, "object cache maintainer");

	thread_id objectCacheResizer = spawn_kernel_thread(object_cache_maintainer,
		"object cache resizer", B_URGENT_PRIORITY, NULL);
	if (objectCacheResizer < 0) {
		panic("slab_init_post_thread(): failed to spawn object cache resizer "
			"thread\n");
		return;
	}

	resume_thread(objectCacheResizer);
}
예제 #14
0
status_t
Worker::Init()
{
	if (fThreadCount > 0) {
		fThreads = new(std::nothrow) thread_id[fThreadCount];
		if (fThreads == NULL)
			return B_NO_MEMORY;

		for (int32 i = 0; i < fThreadCount; i++) {
			fThreads[i] = spawn_kernel_thread(&_Worker, "worker",
				B_NORMAL_PRIORITY, this);
			resume_thread(fThreads[i]);
		}
	}
	return B_OK;
}
예제 #15
0
status_t
InitializeConnectionPurgeThread()
{
	port_id fPort = find_port(BLUETOOTH_CONNECTION_SCHED_PORT);
	if (fPort == B_NAME_NOT_FOUND) {
		TRACE("%s: Creating connection purge port\n", __func__);
		fPort = create_port(16, BLUETOOTH_CONNECTION_SCHED_PORT);
	}

	// This thread has to catch up connections before first package is sent.
	sConnectionThread = spawn_kernel_thread(connection_thread,
				"bluetooth connection purge", B_URGENT_DISPLAY_PRIORITY, NULL);

	if (sConnectionThread >= B_OK)
		return resume_thread(sConnectionThread);
	else
		return B_ERROR;
}
예제 #16
0
/*!	\brief Send the given report message to the given thread.
	
	\param thread The report receiver.
	\param report The report message.
	
	\return \c false on error.
*/
bool
KPPPReportManager::SendReport(thread_id thread, const ppp_report_packet *report)
{
	if (!report)
		return false;
	
	if (thread == find_thread(NULL)) {
		report_sender_info *info = new report_sender_info;
		info->thread = thread;
		memcpy(&info->report, report, sizeof(ppp_report_packet));
		resume_thread(spawn_kernel_thread(report_sender_thread, "PPP: ReportSender",
			B_NORMAL_PRIORITY, info));
		return true;
	}
	
	send_data_with_timeout(thread, PPP_REPORT_CODE, &report, sizeof(report),
		PPP_REPORT_TIMEOUT);
	return true;
}
예제 #17
0
파일: osl.c 프로젝트: PyroOS/Pyro
acpi_status
acpi_os_execute(
	u32			priority,
	acpi_osd_exec_callback	function,
	void			*context)
{
	acpi_status 		status = AE_OK;
	struct acpi_os_dpc	*dpc;
	thread_id id;
	

	ACPI_FUNCTION_TRACE ("os_queue_for_execution");

	ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context));

	if (!function)
		return_ACPI_STATUS (AE_BAD_PARAMETER);

	/*
	 * Allocate/initialize DPC structure.  Note that this memory will be
	 * freed by the callee.  The kernel handles the tq_struct list  in a
	 * way that allows us to also free its memory inside the callee.
	 * Because we may want to schedule several tasks with different
	 * parameters we can't use the approach some kernel code uses of
	 * having a static tq_struct.
	 * We can save time and code by allocating the DPC and tq_structs
	 * from the same memory.
	 */

	dpc = kmalloc(sizeof(struct acpi_os_dpc), MEMF_KERNEL | MEMF_CLEAR );
	if (!dpc)
		return_ACPI_STATUS (AE_NO_MEMORY);

	dpc->function = function;
	dpc->context = context;
	
	id = spawn_kernel_thread( "acpi_task", acpi_os_execute_deferred,
				     0, 4096, dpc );
	wakeup_thread( id, false );

	return_ACPI_STATUS ( status );
}
예제 #18
0
파일: timer.cpp 프로젝트: AmirAbrams/haiku
status_t
initialize_timer(void)
{
	sTimerCount = 0;
	sTimerNextId = 1;
	B_INITIALIZE_SPINLOCK(&sTimerSpinlock);
	
	sTimerThread = spawn_kernel_thread(timer_thread, "firewire timer", 80, 0);
	sTimerSem = create_sem(0, "firewire timer");
	set_sem_owner(sTimerSem, B_SYSTEM_TEAM);
	
	if (sTimerSem < 0 || sTimerThread < 0) {
		delete_sem(sTimerSem);
		kill_thread(sTimerThread);
		return B_ERROR;
	}
	
	resume_thread(sTimerThread);
	return B_OK;
}
예제 #19
0
status_t
DPCQueue::Init(const char* name, int32 priority, uint32 reservedSlots)
{
	// create function callbacks
	for (uint32 i = 0; i < reservedSlots; i++) {
		FunctionDPCCallback* callback
			= new(std::nothrow) FunctionDPCCallback(this);
		if (callback == NULL)
			return B_NO_MEMORY;

		fUnusedFunctionCallbacks.Add(callback);
	}

	// spawn the thread
	fThreadID = spawn_kernel_thread(&_ThreadEntry, name, priority, this);
	if (fThreadID < 0)
		return fThreadID;

	resume_thread(fThreadID);

	return B_OK;
}
예제 #20
0
WorkQueue::WorkQueue()
	:
	fQueueSemaphore(create_sem(0, NULL)),
	fThreadCancel(create_sem(0, NULL))
{
	mutex_init(&fQueueLock, NULL);

	fThread = spawn_kernel_thread(&WorkQueue::LaunchWorkingThread,
		"NFSv4 Work Queue", B_NORMAL_PRIORITY, this);
	if (fThread < B_OK) {
		fInitError = fThread;
		return;
	}

	status_t result = resume_thread(fThread);
	if (result != B_OK) {
		kill_thread(fThread);
		fInitError = result;
		return;
	}

	fInitError = B_OK;
}
예제 #21
0
static status_t
std_ops(int32 op, ...)
{
	if (op == B_MODULE_INIT) {
		sRequestSem = create_sem(0, "invalidate_loop_request");
		if (sRequestSem < B_OK)
			return sRequestSem;

		thread_id thread = spawn_kernel_thread(&invalidate_loop,
			"invalidate_loop", B_NORMAL_PRIORITY, NULL);
		if (thread < B_OK)
			return thread;

		resume_thread(thread);
		return B_OK;
	} else if (op == B_MODULE_UNINIT) {
		// deleting the sem will also cause the thread to exit
		delete_sem(sRequestSem);
		sRequestSem = -1;
		return B_OK;
	}

	return B_BAD_VALUE;
}
예제 #22
0
// MountRootVolume
status_t
VolumeManager::MountRootVolume(const char* device,
	const char* parameters, int32 len, Volume** volume)
{
	// Store the uid/gid of the mounting user -- when running in userland
	// this is always the owner of the UserlandFS server, but we can't help
	// that.
	fMountUID = geteuid();
	fMountGID = getegid();

	// create the query manager
	fQueryManager = new(std::nothrow) QueryManager(this);
	if (!fQueryManager)
		return B_NO_MEMORY;
	status_t error = fQueryManager->Init();
	if (error != B_OK)
		return error;

	// create volumes set
	fVolumes = new(std::nothrow) VolumeSet;
	if (!fVolumes)
		return B_NO_MEMORY;
	error = fVolumes->InitCheck();
	if (error != B_OK)
		return error;

	// create node ID to volumes map
	fNodeIDs2Volumes = new(std::nothrow) NodeIDVolumeMap;
	if (!fNodeIDs2Volumes)
		return B_NO_MEMORY;
	error = fNodeIDs2Volumes->InitCheck();
	if (error != B_OK)
		return error;

	// create the volume event queue
	fVolumeEvents = new VolumeEventQueue;
	if (!fVolumeEvents)
		return B_NO_MEMORY;
	error = fVolumeEvents->InitCheck();
	if (error != B_OK)
		return error;

	// spawn the event deliverer
	#if USER
		fEventDeliverer = spawn_thread(&_EventDelivererEntry,
			"volume event deliverer", B_NORMAL_PRIORITY, this);
	#else
		fEventDeliverer = spawn_kernel_thread(&_EventDelivererEntry,
			"volume event deliverer", B_NORMAL_PRIORITY, this);
	#endif
	if (fEventDeliverer < 0)
		return fEventDeliverer;

	// create the root volume
	RootVolume* rootVolume = new(std::nothrow) RootVolume(this);
	if (!rootVolume)
		return B_NO_MEMORY;
	error = rootVolume->Init();
	if (error != B_OK) {
		delete rootVolume;
		return error;
	}
	fRootID = rootVolume->GetRootID();

	// add the root volume
	error = AddVolume(rootVolume);
	if (error != B_OK) {
		delete rootVolume;
		return error;
	}

	// mount the root volume
	error = rootVolume->Mount(device, fMountFlags, (const char*)parameters,
		len);
	if (error != B_OK) {
		rootVolume->SetUnmounting(true);
		PutVolume(rootVolume);
		return error;
	}
	rootVolume->AcquireReference();
	*volume = rootVolume;

	// run the event deliverer
	resume_thread(fEventDeliverer);

	return B_OK;
}
예제 #23
0
파일: main.cpp 프로젝트: mariuz/haiku
extern "C" int
_start(kernel_args *bootKernelArgs, int currentCPU)
{
	if (bootKernelArgs->kernel_args_size != sizeof(kernel_args)
		|| bootKernelArgs->version != CURRENT_KERNEL_ARGS_VERSION) {
		// This is something we cannot handle right now - release kernels
		// should always be able to handle the kernel_args of earlier
		// released kernels.
		debug_early_boot_message("Version mismatch between boot loader and "
			"kernel!\n");
		return -1;
	}

	smp_set_num_cpus(bootKernelArgs->num_cpus);

	// wait for all the cpus to get here
	smp_cpu_rendezvous(&sCpuRendezvous, currentCPU);

	// the passed in kernel args are in a non-allocated range of memory
	if (currentCPU == 0)
		memcpy(&sKernelArgs, bootKernelArgs, sizeof(kernel_args));

	smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);

	// do any pre-booting cpu config
	cpu_preboot_init_percpu(&sKernelArgs, currentCPU);
	thread_preboot_init_percpu(&sKernelArgs, currentCPU);

	// if we're not a boot cpu, spin here until someone wakes us up
	if (smp_trap_non_boot_cpus(currentCPU, &sCpuRendezvous3)) {
		// init platform
		arch_platform_init(&sKernelArgs);

		// setup debug output
		debug_init(&sKernelArgs);
		set_dprintf_enabled(true);
		dprintf("Welcome to kernel debugger output!\n");
		dprintf("Haiku revision: %lu\n", get_haiku_revision());

		// init modules
		TRACE("init CPU\n");
		cpu_init(&sKernelArgs);
		cpu_init_percpu(&sKernelArgs, currentCPU);
		TRACE("init interrupts\n");
		int_init(&sKernelArgs);

		TRACE("init VM\n");
		vm_init(&sKernelArgs);
			// Before vm_init_post_sem() is called, we have to make sure that
			// the boot loader allocated region is not used anymore
		boot_item_init();
		debug_init_post_vm(&sKernelArgs);
		low_resource_manager_init();

		// now we can use the heap and create areas
		arch_platform_init_post_vm(&sKernelArgs);
		lock_debug_init();
		TRACE("init driver_settings\n");
		driver_settings_init(&sKernelArgs);
		debug_init_post_settings(&sKernelArgs);
		TRACE("init notification services\n");
		notifications_init();
		TRACE("init teams\n");
		team_init(&sKernelArgs);
		TRACE("init ELF loader\n");
		elf_init(&sKernelArgs);
		TRACE("init modules\n");
		module_init(&sKernelArgs);
		TRACE("init semaphores\n");
		haiku_sem_init(&sKernelArgs);
		TRACE("init interrupts post vm\n");
		int_init_post_vm(&sKernelArgs);
		cpu_init_post_vm(&sKernelArgs);
		commpage_init();
		TRACE("init system info\n");
		system_info_init(&sKernelArgs);

		TRACE("init SMP\n");
		smp_init(&sKernelArgs);
		TRACE("init timer\n");
		timer_init(&sKernelArgs);
		TRACE("init real time clock\n");
		rtc_init(&sKernelArgs);

		TRACE("init condition variables\n");
		condition_variable_init();

		// now we can create and use semaphores
		TRACE("init VM semaphores\n");
		vm_init_post_sem(&sKernelArgs);
		TRACE("init generic syscall\n");
		generic_syscall_init();
		smp_init_post_generic_syscalls();
		TRACE("init scheduler\n");
		scheduler_init();
		TRACE("init threads\n");
		thread_init(&sKernelArgs);
		TRACE("init kernel daemons\n");
		kernel_daemon_init();
		arch_platform_init_post_thread(&sKernelArgs);

		TRACE("init I/O interrupts\n");
		int_init_io(&sKernelArgs);
		TRACE("init VM threads\n");
		vm_init_post_thread(&sKernelArgs);
		low_resource_manager_init_post_thread();
		TRACE("init VFS\n");
		vfs_init(&sKernelArgs);
#if ENABLE_SWAP_SUPPORT
		TRACE("init swap support\n");
		swap_init();
#endif
		TRACE("init POSIX semaphores\n");
		realtime_sem_init();
		xsi_sem_init();
		xsi_msg_init();

		// Start a thread to finish initializing the rest of the system. Note,
		// it won't be scheduled before calling scheduler_start() (on any CPU).
		TRACE("spawning main2 thread\n");
		thread_id thread = spawn_kernel_thread(&main2, "main2",
			B_NORMAL_PRIORITY, NULL);
		resume_thread(thread);

		// We're ready to start the scheduler and enable interrupts on all CPUs.
		scheduler_enable_scheduling();

		// bring up the AP cpus in a lock step fashion
		TRACE("waking up AP cpus\n");
		sCpuRendezvous = sCpuRendezvous2 = 0;
		smp_wake_up_non_boot_cpus();
		smp_cpu_rendezvous(&sCpuRendezvous, 0); // wait until they're booted

		// exit the kernel startup phase (mutexes, etc work from now on out)
		TRACE("exiting kernel startup\n");
		gKernelStartup = false;

		smp_cpu_rendezvous(&sCpuRendezvous2, 0);
			// release the AP cpus to go enter the scheduler

		TRACE("starting scheduler on cpu 0 and enabling interrupts\n");
		scheduler_start();
		enable_interrupts();
	} else {
		// lets make sure we're in sync with the main cpu
		// the boot processor has probably been sending us
		// tlb sync messages all along the way, but we've
		// been ignoring them
		arch_cpu_global_TLB_invalidate();

		// this is run for each non boot processor after they've been set loose
		cpu_init_percpu(&sKernelArgs, currentCPU);
		smp_per_cpu_init(&sKernelArgs, currentCPU);

		// wait for all other AP cpus to get to this point
		smp_cpu_rendezvous(&sCpuRendezvous, currentCPU);
		smp_cpu_rendezvous(&sCpuRendezvous2, currentCPU);

		// welcome to the machine
		scheduler_start();
		enable_interrupts();
	}

#ifdef TRACE_BOOT
	// We disable interrupts for this dprintf(), since otherwise dprintf()
	// would acquires a mutex, which is something we must not do in an idle
	// thread, or otherwise the scheduler would be seriously unhappy.
	disable_interrupts();
	TRACE("main: done... begin idle loop on cpu %d\n", currentCPU);
	enable_interrupts();
#endif

	for (;;)
		arch_cpu_idle();

	return 0;
}
예제 #24
0
status_t
SerialDevice::Open(uint32 flags)
{
	if (fDeviceOpen)
		return B_BUSY;

	if (fDeviceRemoved)
		return B_DEV_NOT_READY;

	fMasterTTY = gTTYModule->tty_create(usb_serial_service, true);
	if (fMasterTTY == NULL) {
		TRACE_ALWAYS("open: failed to init master tty\n");
		return B_NO_MEMORY;
	}

	fSlaveTTY = gTTYModule->tty_create(usb_serial_service, false);
	if (fSlaveTTY == NULL) {
		TRACE_ALWAYS("open: failed to init slave tty\n");
		gTTYModule->tty_destroy(fMasterTTY);
		return B_NO_MEMORY;
	}

	fSystemTTYCookie = gTTYModule->tty_create_cookie(fMasterTTY, fSlaveTTY,
		O_RDWR);
	if (fSystemTTYCookie == NULL) {
		TRACE_ALWAYS("open: failed to init system tty cookie\n");
		gTTYModule->tty_destroy(fMasterTTY);
		gTTYModule->tty_destroy(fSlaveTTY);
		return B_NO_MEMORY;
	}

	fDeviceTTYCookie = gTTYModule->tty_create_cookie(fSlaveTTY, fMasterTTY,
		O_RDWR);
	if (fDeviceTTYCookie == NULL) {
		TRACE_ALWAYS("open: failed to init device tty cookie\n");
		gTTYModule->tty_destroy_cookie(fSystemTTYCookie);
		gTTYModule->tty_destroy(fMasterTTY);
		gTTYModule->tty_destroy(fSlaveTTY);
		return B_NO_MEMORY;
	}

	ResetDevice();

	fStopThreads = false;

	fInputThread = spawn_kernel_thread(_InputThread,
		"usb_serial input thread", B_NORMAL_PRIORITY, this);
	if (fInputThread < 0) {
		TRACE_ALWAYS("open: failed to spawn input thread\n");
		return fInputThread;
	}

	resume_thread(fInputThread);

	fControlOut = USB_CDC_CONTROL_SIGNAL_STATE_DTR
		| USB_CDC_CONTROL_SIGNAL_STATE_RTS;
	SetControlLineState(fControlOut);

	status_t status = gUSBModule->queue_interrupt(fControlPipe,
		fInterruptBuffer, fInterruptBufferSize, _InterruptCallbackFunction,
		this);
	if (status < B_OK)
		TRACE_ALWAYS("failed to queue initial interrupt\n");

	// set our config (will propagate to the slave config as well in SetModes()
	gTTYModule->tty_control(fSystemTTYCookie, TCSETA, &fTTYConfig,
		sizeof(termios));

	fDeviceOpen = true;
	return B_OK;
}
예제 #25
0
파일: Stack.cpp 프로젝트: mmanley/Antares
Stack::Stack()
    :	fExploreThread(-1),
      fFirstExploreDone(false),
      fStopThreads(false),
      fObjectIndex(1),
      fObjectMaxCount(1024),
      fObjectArray(NULL),
      fDriverList(NULL)
{
    TRACE("stack init\n");

    mutex_init(&fStackLock, "usb stack lock");
    mutex_init(&fExploreLock, "usb explore lock");

    size_t objectArraySize = fObjectMaxCount * sizeof(Object *);
    fObjectArray = (Object **)malloc(objectArraySize);
    if (fObjectArray == NULL) {
        TRACE_ERROR("failed to allocate object array\n");
        return;
    }

    memset(fObjectArray, 0, objectArraySize);

    fAllocator = new(std::nothrow) PhysicalMemoryAllocator("USB Stack Allocator",
            8, B_PAGE_SIZE * 4, 64);
    if (!fAllocator || fAllocator->InitCheck() < B_OK) {
        TRACE_ERROR("failed to allocate the allocator\n");
        delete fAllocator;
        fAllocator = NULL;
        return;
    }

    // Check for host controller modules
    // While using a fixed list of names is inflexible it allows us to control
    // the order in which we try modules. There are controllers/BIOSes that
    // require UHCI/OHCI to be initialized before EHCI or otherwise they
    // refuse to publish any high-speed devices.
    // On other systems the ordering is probably ensured because the EHCI
    // controller is required to have a higher PCI function number than the
    // companion host controllers (per the EHCI specs) and it would therefore
    // be enumerated as the last item. As this does not apply to us we have to
    // ensure ordering using another method.
    const char *moduleNames[] = {
        "busses/usb/uhci",
        "busses/usb/ohci",
        "busses/usb/ehci",
        NULL
    };

    TRACE("looking for host controller modules\n");
    for (uint32 i = 0; moduleNames[i]; i++) {
        TRACE("looking for module %s\n", moduleNames[i]);

        usb_host_controller_info *module = NULL;
        if (get_module(moduleNames[i], (module_info **)&module) != B_OK)
            continue;

        TRACE("adding module %s\n", moduleNames[i]);
        if (module->add_to(this) < B_OK) {
            put_module(moduleNames[i]);
            continue;
        }

        TRACE("module %s successfully loaded\n", moduleNames[i]);
    }

    if (fBusManagers.Count() == 0) {
        TRACE_ERROR("no bus managers available\n");
        return;
    }

    fExploreThread = spawn_kernel_thread(ExploreThread, "usb explore",
                                         B_LOW_PRIORITY, this);
    resume_thread(fExploreThread);

    // wait for the first explore to complete. this ensures that a driver that
    // is opening the module does not get rescanned while or before installing
    // its hooks.
    while (!fFirstExploreDone)
        snooze(100000);
}
예제 #26
0
파일: ohci.cpp 프로젝트: mmanley/Antares
OHCI::OHCI(pci_info *info, Stack *stack)
	:	BusManager(stack),
		fPCIInfo(info),
		fStack(stack),
		fOperationalRegisters(NULL),
		fRegisterArea(-1),
		fHccaArea(-1),
		fHcca(NULL),
		fInterruptEndpoints(NULL),
		fDummyControl(NULL),
		fDummyBulk(NULL),
		fDummyIsochronous(NULL),
		fFirstTransfer(NULL),
		fLastTransfer(NULL),
		fFinishTransfersSem(-1),
		fFinishThread(-1),
		fStopFinishThread(false),
		fProcessingPipe(NULL),
		fRootHub(NULL),
		fRootHubAddress(0),
		fPortCount(0)
{
	if (!fInitOK) {
		TRACE_ERROR("bus manager failed to init\n");
		return;
	}

	TRACE("constructing new OHCI host controller driver\n");
	fInitOK = false;

	mutex_init(&fEndpointLock, "ohci endpoint lock");

	// enable busmaster and memory mapped access
	uint16 command = sPCIModule->read_pci_config(fPCIInfo->bus,
		fPCIInfo->device, fPCIInfo->function, PCI_command, 2);
	command &= ~PCI_command_io;
	command |= PCI_command_master | PCI_command_memory;

	sPCIModule->write_pci_config(fPCIInfo->bus, fPCIInfo->device,
		fPCIInfo->function, PCI_command, 2, command);

	// map the registers
	uint32 offset = sPCIModule->read_pci_config(fPCIInfo->bus,
		fPCIInfo->device, fPCIInfo->function, PCI_base_registers, 4);
	offset &= PCI_address_memory_32_mask;
	TRACE_ALWAYS("iospace offset: 0x%lx\n", offset);
	fRegisterArea = map_physical_memory("OHCI memory mapped registers",
		(void *)offset,	B_PAGE_SIZE, B_ANY_KERNEL_BLOCK_ADDRESS,
		B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA | B_READ_AREA | B_WRITE_AREA,
		(void **)&fOperationalRegisters);
	if (fRegisterArea < B_OK) {
		TRACE_ERROR("failed to map register memory\n");
		return;
	}

	TRACE("mapped operational registers: %p\n", fOperationalRegisters);

	// Check the revision of the controller, which should be 10h
	uint32 revision = _ReadReg(OHCI_REVISION) & 0xff;
	TRACE("version %ld.%ld%s\n", OHCI_REVISION_HIGH(revision),
		OHCI_REVISION_LOW(revision), OHCI_REVISION_LEGACY(revision)
		? ", legacy support" : "");
	if (OHCI_REVISION_HIGH(revision) != 1 || OHCI_REVISION_LOW(revision) != 0) {
		TRACE_ERROR("unsupported OHCI revision\n");
		return;
	}

	void *hccaPhysicalAddress;
	fHccaArea = fStack->AllocateArea((void **)&fHcca, &hccaPhysicalAddress,
		sizeof(ohci_hcca), "USB OHCI Host Controller Communication Area");

	if (fHccaArea < B_OK) {
		TRACE_ERROR("unable to create the HCCA block area\n");
		return;
	}

	memset(fHcca, 0, sizeof(ohci_hcca));

	// Set Up Host controller
	// Dummy endpoints
	fDummyControl = _AllocateEndpoint();
	if (!fDummyControl)
		return;

	fDummyBulk = _AllocateEndpoint();
	if (!fDummyBulk) {
		_FreeEndpoint(fDummyControl);
		return;
	}

	fDummyIsochronous = _AllocateEndpoint();
	if (!fDummyIsochronous) {
		_FreeEndpoint(fDummyControl);
		_FreeEndpoint(fDummyBulk);
		return;
	}

	// Static endpoints that get linked in the HCCA
	fInterruptEndpoints = new(std::nothrow)
		ohci_endpoint_descriptor *[OHCI_STATIC_ENDPOINT_COUNT];
	if (!fInterruptEndpoints) {
		TRACE_ERROR("failed to allocate memory for interrupt endpoints\n");
		_FreeEndpoint(fDummyControl);
		_FreeEndpoint(fDummyBulk);
		_FreeEndpoint(fDummyIsochronous);
		return;
	}

	for (int32 i = 0; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
		fInterruptEndpoints[i] = _AllocateEndpoint();
		if (!fInterruptEndpoints[i]) {
			TRACE_ERROR("failed to allocate interrupt endpoint %ld", i);
			while (--i >= 0)
				_FreeEndpoint(fInterruptEndpoints[i]);
			_FreeEndpoint(fDummyBulk);
			_FreeEndpoint(fDummyControl);
			_FreeEndpoint(fDummyIsochronous);
			return;
		}
	}

	// build flat tree so that at each of the static interrupt endpoints
	// fInterruptEndpoints[i] == interrupt endpoint for interval 2^i
	uint32 interval = OHCI_BIGGEST_INTERVAL;
	uint32 intervalIndex = OHCI_STATIC_ENDPOINT_COUNT - 1;
	while (interval > 1) {
		uint32 insertIndex = interval / 2;
		while (insertIndex < OHCI_BIGGEST_INTERVAL) {
			fHcca->interrupt_table[insertIndex]
				= fInterruptEndpoints[intervalIndex]->physical_address;
			insertIndex += interval;
		}

		intervalIndex--;
		interval /= 2;
	}

	// setup the empty slot in the list and linking of all -> first
	fHcca->interrupt_table[0] = fInterruptEndpoints[0]->physical_address;
	for (int32 i = 1; i < OHCI_STATIC_ENDPOINT_COUNT; i++) {
		fInterruptEndpoints[i]->next_physical_endpoint
			= fInterruptEndpoints[0]->physical_address;
		fInterruptEndpoints[i]->next_logical_endpoint
			= fInterruptEndpoints[0];
	}

	// Now link the first endpoint to the isochronous endpoint
	fInterruptEndpoints[0]->next_physical_endpoint
		= fDummyIsochronous->physical_address;

	// Determine in what context we are running (Kindly copied from FreeBSD)
	uint32 control = _ReadReg(OHCI_CONTROL);
	if (control & OHCI_INTERRUPT_ROUTING) {
		TRACE_ALWAYS("smm is in control of the host controller\n");
		uint32 status = _ReadReg(OHCI_COMMAND_STATUS);
		_WriteReg(OHCI_COMMAND_STATUS, status | OHCI_OWNERSHIP_CHANGE_REQUEST);
		for (uint32 i = 0; i < 100 && (control & OHCI_INTERRUPT_ROUTING); i++) {
			snooze(1000);
			control = _ReadReg(OHCI_CONTROL);
		}

		if ((control & OHCI_INTERRUPT_ROUTING) != 0) {
			TRACE_ERROR("smm does not respond. resetting...\n");
			_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
			snooze(USB_DELAY_BUS_RESET);
		} else
			TRACE_ALWAYS("ownership change successful\n");
	} else {
		TRACE("cold started\n");
		snooze(USB_DELAY_BUS_RESET);
	}

	// This reset should not be necessary according to the OHCI spec, but
	// without it some controllers do not start.
	_WriteReg(OHCI_CONTROL, OHCI_HC_FUNCTIONAL_STATE_RESET);
	snooze(USB_DELAY_BUS_RESET);

	// We now own the host controller and the bus has been reset
	uint32 frameInterval = _ReadReg(OHCI_FRAME_INTERVAL);
	uint32 intervalValue = OHCI_GET_INTERVAL_VALUE(frameInterval);

	// Disable interrupts right before we reset
	_WriteReg(OHCI_COMMAND_STATUS, OHCI_HOST_CONTROLLER_RESET);
	// Nominal time for a reset is 10 us
	uint32 reset = 0;
	for (uint32 i = 0; i < 10; i++) {
		spin(10);
		reset = _ReadReg(OHCI_COMMAND_STATUS) & OHCI_HOST_CONTROLLER_RESET;
		if (reset == 0)
			break;
	}

	if (reset) {
		TRACE_ERROR("error resetting the host controller (timeout)\n");
		return;
	}

	// The controller is now in SUSPEND state, we have 2ms to go OPERATIONAL.
	// Interrupts are disabled.

	// Set up host controller register
	_WriteReg(OHCI_HCCA, (uint32)hccaPhysicalAddress);
	_WriteReg(OHCI_CONTROL_HEAD_ED, (uint32)fDummyControl->physical_address);
	_WriteReg(OHCI_BULK_HEAD_ED, (uint32)fDummyBulk->physical_address);
	// Disable all interrupts
	_WriteReg(OHCI_INTERRUPT_DISABLE, OHCI_ALL_INTERRUPTS);
	// Switch on desired functional features
	control = _ReadReg(OHCI_CONTROL);
	control &= ~(OHCI_CONTROL_BULK_SERVICE_RATIO_MASK | OHCI_ENABLE_LIST
		| OHCI_HC_FUNCTIONAL_STATE_MASK | OHCI_INTERRUPT_ROUTING);
	control |= OHCI_ENABLE_LIST | OHCI_CONTROL_BULK_RATIO_1_4
		| OHCI_HC_FUNCTIONAL_STATE_OPERATIONAL;
	// And finally start the controller
	_WriteReg(OHCI_CONTROL, control);

	// The controller is now OPERATIONAL.
	frameInterval = (_ReadReg(OHCI_FRAME_INTERVAL) & OHCI_FRAME_INTERVAL_TOGGLE)
		^ OHCI_FRAME_INTERVAL_TOGGLE;
	frameInterval |= OHCI_FSMPS(intervalValue) | intervalValue;
	_WriteReg(OHCI_FRAME_INTERVAL, frameInterval);
	// 90% periodic
	uint32 periodic = OHCI_PERIODIC(intervalValue);
	_WriteReg(OHCI_PERIODIC_START, periodic);

	// Fiddle the No Over Current Protection bit to avoid chip bug
	uint32 desca = _ReadReg(OHCI_RH_DESCRIPTOR_A);
	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca | OHCI_RH_NO_OVER_CURRENT_PROTECTION);
	_WriteReg(OHCI_RH_STATUS, OHCI_RH_LOCAL_POWER_STATUS_CHANGE);
	snooze(OHCI_ENABLE_POWER_DELAY);
	_WriteReg(OHCI_RH_DESCRIPTOR_A, desca);

	// The AMD756 requires a delay before re-reading the register,
	// otherwise it will occasionally report 0 ports.
	uint32 numberOfPorts = 0;
	for (uint32 i = 0; i < 10 && numberOfPorts == 0; i++) {
		snooze(OHCI_READ_DESC_DELAY);
		uint32 descriptor = _ReadReg(OHCI_RH_DESCRIPTOR_A);
		numberOfPorts = OHCI_RH_GET_PORT_COUNT(descriptor);
	}
	if (numberOfPorts > OHCI_MAX_PORT_COUNT)
		numberOfPorts = OHCI_MAX_PORT_COUNT;
	fPortCount = numberOfPorts;
	TRACE("port count is %d\n", fPortCount);

	// Create semaphore the finisher thread will wait for
	fFinishTransfersSem = create_sem(0, "OHCI Finish Transfers");
	if (fFinishTransfersSem < B_OK) {
		TRACE_ERROR("failed to create semaphore\n");
		return;
	}

	// Create the finisher service thread
	fFinishThread = spawn_kernel_thread(_FinishThread, "ohci finish thread",
		B_URGENT_DISPLAY_PRIORITY, (void *)this);
	resume_thread(fFinishThread);

	// Install the interrupt handler
	TRACE("installing interrupt handler\n");
	install_io_interrupt_handler(fPCIInfo->u.h0.interrupt_line,
		_InterruptHandler, (void *)this, 0);

	// Enable interesting interrupts now that the handler is in place
	_WriteReg(OHCI_INTERRUPT_ENABLE, OHCI_NORMAL_INTERRUPTS
		| OHCI_MASTER_INTERRUPT_ENABLE);

	TRACE("OHCI host controller driver constructed\n");
	fInitOK = true;
}