Beispiel #1
0
/*
 * Initialises the CMOS RTC driver.
 */
static void* rtc_init(device_t *dev) {
    // Read initial RTC values
    rtc_read();

    // Enable the periodic IRQ
    IRQ_OFF();

    io_outb(CMOS_REG_PORT, 0x8B);
    uint8_t reg = io_inb(CMOS_DATA_PORT);

    io_outb(CMOS_REG_PORT, 0x8B);
    io_outb(CMOS_DATA_PORT, reg | 0x40);

    // Rate is 2 Hz
    io_outb(CMOS_REG_PORT, 0x8A);
    reg = io_inb(CMOS_DATA_PORT);

    io_outb(CMOS_REG_PORT, 0x8A);
    io_outb(CMOS_DATA_PORT, (reg & 0xF0) | 0x0F);

    // Install IRQ handler
    hal_register_irq_handler(8, rtc_sys_tick, NULL);

    // Re-enable IRQs
    IRQ_RES();

    return BUS_NO_INIT_DATA;
}
Beispiel #2
0
void tasking_install(void) {
	IRQ_OFF();

	/* Install the pit callback, which is acting as a callback service: */
	MOD_IOCTL("pit_driver", 1, (uintptr_t)"pit_switch_task", (uintptr_t)pit_switch_task);

	/* Initialize the very first task, which is the main thread that was already running: */
	current_task = main_task =
			task_create((char*)"rootproc", 0, Kernel::CPU::read_reg(Kernel::CPU::eflags), (uint32_t)Kernel::Memory::Man::curr_dir->table_entries);

	/* Initialize task list and tree: */
	tasklist = list_create();
	tasktree = tree_create();
	tree_set_root(tasktree, main_task);
	list_insert(tasklist, main_task);

	tasking_enable(1); /* Allow tasking to work */
	is_tasking_initialized = 1;
	IRQ_RES(); /* Kickstart tasking */

	/* Test tasking: */
	task_t * t1 = task_create_and_run((char*)"task1", task1, current_task->regs->eflags, current_task->regs->cr3);
	task_t * t2 = task_create_and_run((char*)"task2", task2, current_task->regs->eflags, current_task->regs->cr3);
	task_set_ttl_mode(t1->pid, 0);
	task_set_ttl_mode(t2->pid, 1);

	task_set_ttl_fscale(t1, 1000);

	task_set_ttl(t1, 80);
	task_set_ttl(t2, 10);
}
Beispiel #3
0
/* Duty cycle is expressed from 0% to 100% */
void task_set_ttl(int pid, int duty_cycle_or_preload) {
	IRQ_OFF();
	task_t * task = (task_t*)list_get(tasklist, pid)->value;
	if(task)
		task_set_ttl(task, duty_cycle_or_preload);
	IRQ_RES();
}
Beispiel #4
0
void task_set_ttl_mode(int pid, char pwm_or_pulse_mode) {
	IRQ_OFF();
	task_t * task = (task_t*)list_get(tasklist, pid)->value;
	if(task)
		task_set_ttl_mode(task, pwm_or_pulse_mode);
	IRQ_RES();
}
Beispiel #5
0
void task_set_ttl_fscale(int pid, int fscale) {
	IRQ_OFF();
	task_t * task = (task_t*)list_get(tasklist, pid)->value;
	if(task)
		task_set_ttl_fscale(task->pid, fscale);
	IRQ_RES();
}
Beispiel #6
0
void task_set_ttl_fscale(task_t * task, int fscale) {
	IRQ_OFF();
	if(task) {
		task->ttl_fscale = fscale <= 0 ? MAX_TTL : (fscale >= MAX_TTL ? MAX_TTL : fscale);
		task_set_ttl(task, 100); /* Set default duty cycle to 100% */
	}
	IRQ_RES();
}
Beispiel #7
0
static void task2(void) {
	for(;;) {
		IRQ_OFF();
		Point p = Kernel::term.go_to(50, 1);
		Kernel::term.printf("TASK2 (pwm) %d      ", ctr2++);
		Kernel::term.go_to(p.X, p.Y);
		IRQ_RES();
	}
}
Beispiel #8
0
static void task1(void) {
	for(;;) {
		IRQ_OFF();
		Point p = Kernel::term.go_to(50, 0);
		Kernel::term.printf("TASK1 (pulse) %d      ", ctr1++);
		Kernel::term.go_to(p.X, p.Y);
		IRQ_RES();
	}
}
Beispiel #9
0
task_t * task_create_and_run(char * task_name, task_t * parent_task, void (*entry)(void), uint32_t eflags, uint32_t pagedir) {
	/* Create task: */
	task_t * new_task = task_create(task_name, entry, eflags, pagedir);
	IRQ_OFF(); /* Keep IRQs off */

	/* Add it to the tree (and by adding, the switcher function will now switch to this process): */
	task_run(parent_task, new_task);

	IRQ_RES();
	return new_task;
}
Beispiel #10
0
/* Duty cycle is expressed from 0% to 100% */
void task_set_ttl(task_t * task, int duty_cycle_or_preload) {
	IRQ_OFF();
	if(task){
		if(task->ttl_pwm_mode) {
			task->ttl_start = task->ttl_fscale - ((duty_cycle_or_preload * task->ttl_fscale) / 100); /* Duty cycle */
			task->ttl = 0;
		} else {
			task->ttl_start = task->ttl = ((duty_cycle_or_preload * task->ttl_fscale) / 100); /* Preload value */
		}
	}
	IRQ_RES();
}
Beispiel #11
0
void task_set_ttl_mode(task_t * task, char pwm_or_pulse_mode) {
	IRQ_OFF();
	if(task) {
		if(pwm_or_pulse_mode) {
			task->ttl_pwm_mode = 1;
			task->ttl = task->ttl_start = 0;
		} else {
			task->ttl_pwm_mode = 0;
			task->ttl = task->ttl_start = task->ttl_fscale;
		}
	}
	IRQ_RES();
}
Beispiel #12
0
/****************************** Task creation ******************************/
task_t * task_create(char * task_name, void (*entry)(void), uint32_t eflags, uint32_t pagedir) {
	IRQ_OFF();

	task_t * task = new task_t;
	task->regs = new regs_t;
	task->syscall_regs = new regs_t;

	task->regs->eflags = eflags;
	task->regs->cr3 = pagedir;
	task->state = TASKST_CRADLE;
	task->name = task_name;
	task->regs->eax = task->regs->ebx = task->regs->ecx = task->regs->edx = task->regs->esi = task->regs->edi = 0;
	task->next = 0;
	task->ttl = task->ttl_start = 0;
	task->ttl_fscale = MAX_TTL;
	task->ttl_pwm_mode = 1;

	if(entry) {
		task->regs->eip = (uint32_t) entry;
		task->regs->esp = (uint32_t) malloc(TASK_STACK_SIZE) + TASK_STACK_SIZE;

		/* Set next pid: */
		task->pid = ++next_pid;

		/* Prepare X86 stack: */
		uint32_t * stack_ptr = (uint32_t*)(task->regs->esp);
		/* Parse it and configure it: */
		Kernel::CPU::x86_stack_t * stack = (Kernel::CPU::x86_stack_t*)stack_ptr;
		stack->regs2.ebp = (uint32_t)(stack_ptr + 28);
		stack->old_ebp = (uint32_t)(stack_ptr + 32);
		stack->old_addr = (unsigned)task_return_grave;
		stack->ds = X86_SEGMENT_USER_DATA;
		stack->cs = X86_SEGMENT_USER_CODE;
		stack->eip = task->regs->eip;
		stack->eflags.interrupt = 1;
		stack->eflags.iopl = 3;
		stack->esp = task->regs->esp;
		stack->ss = X86_SEGMENT_USER_DATA;
		stack->regs2.eax = (uint32_t)task_return_grave; /* Return address of a task */
	} else {
		if(!is_tasking_initialized) {
			/* If entry is null, then we're allocating the very first process, which is the main core task */
			task->pid = next_pid;
		} /* else we ignore it, we don't want to run a normal task with an entry point of address 0! */
	}

	IRQ_RES();
	return task;
}
Beispiel #13
0
void task_kill(int pid) {
	if(!pid) return; /* Do not let the main task kill itself */
	if(!irq_already_off)
		IRQ_OFF();

	kprintf("\nKILLED PID: %d\n", pid);

	/* Remove the task from the list, then cleanup the rest (remove process from tree, deallocate task's stack and more) */
	task_t * task_to_kill = (task_t*)list_get(tasklist, pid)->value; /* Store it first so we can clean up everything */
	list_remove(tasklist, pid);
	tasklist_size--;

	/* Remove from tree: */

	/* Cleanup everything else: */
	task_free(task_to_kill);

	irq_already_off = 0;
	IRQ_RES(); /* Resume switching */
}
Beispiel #14
0
	}
}

/* serial to parallel conversion */
static struct resource ltq_stp_resource =
	MEM_RES("stp", LTQ_STP_BASE_ADDR, LTQ_STP_SIZE);

void __init ltq_register_gpio_stp(void)
{
	platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
}

/* asc ports - amazon se has its own serial mapping */
static struct resource ltq_ase_asc_resources[] = {
	MEM_RES("asc0", LTQ_ASC1_BASE_ADDR, LTQ_ASC_SIZE),
	IRQ_RES(tx, LTQ_ASC_ASE_TIR),
	IRQ_RES(rx, LTQ_ASC_ASE_RIR),
	IRQ_RES(err, LTQ_ASC_ASE_EIR),
};

void __init ltq_register_ase_asc(void)
{
	platform_device_register_simple("ltq_asc", 0,
		ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
}

/* ethernet */
static struct resource ltq_etop_resources[] = {
	MEM_RES("etop", LTQ_ETOP_BASE_ADDR, LTQ_ETOP_SIZE),
	MEM_RES("gbit", LTQ_GBIT_BASE_ADDR, LTQ_GBIT_SIZE),
};
Beispiel #15
0
/****************************** Task control ******************************/
void tasking_enable(char enable) {
	IRQ_OFF();
	is_tasking = enable ? 1 : 0;
	IRQ_RES();
}
Beispiel #16
0
Datei: ata.c Projekt: UIKit0/TSOS
/*
 * Initialises the driver, based on the base addresses from the PCI controller
 */
ata_driver_t* ata_init_pci(uint32_t BAR0, uint32_t BAR1, uint32_t BAR2, uint32_t BAR3, uint32_t BAR4) {
	int i, j, k, count = 0;
	int channel, device;

	// Set up memory for the driver
	ata_driver_t* driver = (ata_driver_t *) kmalloc(sizeof(ata_driver_t));

	// Initialise memory if needed
	if(driver) {
		memclr(driver, sizeof(ata_driver_t));
	} else {
		return NULL;
	}

	IRQ_OFF();

	// Allocate some buffer memory
	uint8_t *ide_buf = (uint8_t *) kmalloc(2048);
	memclr(ide_buf, 2048);

	// Copy the BAR addresses
	driver->BAR0 = BAR0;
	driver->BAR1 = BAR1;
	driver->BAR2 = BAR2;
	driver->BAR3 = BAR3;
	driver->BAR4 = BAR4;

	// Set up IO ports to control the IDE controller with
	driver->channels[ATA_PRIMARY].base = (BAR0 & 0xFFFFFFFC) + 0x1F0 * (!BAR0);
	driver->channels[ATA_PRIMARY].ctrl = (BAR1 & 0xFFFFFFFC) + 0x3F6 * (!BAR1);
	driver->channels[ATA_PRIMARY].bmide = (BAR4 & 0xFFFFFFFC) + 0; // Bus Master IDE
	driver->channels[ATA_SECONDARY].base = (BAR2 & 0xFFFFFFFC) + 0x170 * (!BAR2);
	driver->channels[ATA_SECONDARY].ctrl = (BAR3 & 0xFFFFFFFC) + 0x376 * (!BAR3);
	driver->channels[ATA_SECONDARY].bmide = (BAR4 & 0xFFFFFFFC) + 8; // Bus Master IDE

	// Disable IRQs for both channels
	driver->channels[ATA_PRIMARY].nIEN = 0x02;
	driver->channels[ATA_SECONDARY].nIEN = 0x02;

	ata_reg_write(driver, ATA_PRIMARY, ATA_REG_CONTROL, driver->channels[ATA_PRIMARY].nIEN);
	ata_reg_write(driver, ATA_SECONDARY, ATA_REG_CONTROL, driver->channels[ATA_SECONDARY].nIEN);

	// Probe for devices
	for(channel = 0; channel < 2; channel++) {
		// Disable for the channel
		driver->channels[channel].nIEN = 2;

		// Check each device on the channel
		for(device = 0; device < 2; device++) {
			uint8_t type = ATA_DEVICE_TYPE_ATA, status;
			bool isATAPI = false;

			// Set up some initial state
			driver->devices[count].drive_exists = false;
			driver->devices[count].dma_enabled = false;
 
 			// Select drive
			ata_reg_write(driver, channel, ATA_REG_HDDEVSEL, 0xA0 | (device << 4));
 
			// Send IDENTIFY command
			ata_reg_write(driver, channel, ATA_REG_COMMAND, ATA_CMD_IDENTIFY);

			// Wait a while by writing to a bogus IO port
 			io_wait();
 			io_wait();

 			// If the status register is 0, there is no device
			if(ata_reg_read(driver, channel, ATA_REG_STATUS) == 0) continue;
 
 			// Wait until we read an error or DREQ
			for(;;) {
				// Read status register
				status = ata_reg_read(driver, channel, ATA_REG_STATUS);

				// If the error bit is set, we don't have an ATA device
				if ((status & ATA_SR_ERR)) {
					isATAPI = true;
					break;
				}

				// If BSY is clear and DREQ is set, we can read data
				if(!(status & ATA_SR_BSY) && (status & ATA_SR_DRQ)) break;
			}
 
			// If the drive is an ATAPI drive, send IDENTIFY PACKET command
			if(isATAPI) {
				uint8_t cl = ata_reg_read(driver, channel, ATA_REG_LBA1);
				uint8_t ch = ata_reg_read(driver, channel, ATA_REG_LBA2);
 
				if (cl == 0x14 && ch ==0xEB)
					type = ATA_DEVICE_TYPE_ATAPI;
				else if (cl == 0x69 && ch == 0x96)
					type = ATA_DEVICE_TYPE_ATAPI;
				else
					continue; // Unknown Type (may not be a device).
 
				ata_reg_write(driver, channel, ATA_REG_COMMAND, ATA_CMD_IDENTIFY_PACKET);

				// Initialise ATAPI buffer for thsi packet
				driver->devices[count].atapi_buffer[0] = 0xA8;
			}
 
			// Read Device identification block (512 bytes)
			ata_do_pio_read(driver, ide_buf, 256, channel);
 
			// Allocate a page of memory for the ATA output memory
			ata_info_t *info = (ata_info_t *) kmalloc(sizeof(ata_info_t));
			memclr(info, sizeof(ata_info_t));
			driver->devices[count].ata_info = info;

			// Save a copy of the device identification block
			memcpy(&info->ata_identify, ide_buf, 512);

			// Read device parameters
			driver->devices[count].drive_exists = true;
			driver->devices[count].type = type;
			driver->devices[count].channel = channel;
			driver->devices[count].drive = device;
			driver->devices[count].signature = *((uint16_t *) (ide_buf + ATA_IDENT_DEVICETYPE));
			driver->devices[count].capabilities = *((uint16_t *) (ide_buf + ATA_IDENT_CAPABILITIES));
			driver->devices[count].commandSets = *((uint32_t *) (ide_buf + ATA_IDENT_COMMANDSETS));
 
			// Get size of drive
			if (driver->devices[count].commandSets & (1 << 26)) { // 48-bit LBA
				driver->devices[count].size	= *((uint32_t *) (ide_buf + ATA_IDENT_MAX_LBA_EXT));
			} else { // CHS or 28 bit addressing
				driver->devices[count].size	= *((uint32_t *) (ide_buf + ATA_IDENT_MAX_LBA));
			}
 
			// Convert model string
			char *model_read = (char *) (ide_buf + ATA_IDENT_MODEL);
			for(k = 0; k < 40; k += 2) {
				driver->devices[count].model[k] = model_read[k+1];
				driver->devices[count].model[k+1] = model_read[k];
			}

			// Trim the model string (remove space padding)
			for(int k = 42; k > 0; k--) {
				if(driver->devices[count].model[k] == 0x20 || driver->devices[count].model[k] == 0x00) {
					driver->devices[count].model[k] = 0x00;
				} else {
					break;
				}
			}

			// Does the drive support DMA?
			if(*((uint16_t *) (ide_buf + ATA_IDENT_FIELDVALID))) {
				// Get supported UDMA modes
				uint16_t udma_modes = *((uint16_t *) (ide_buf + ATA_IDENT_UDMASUPPORT));
				if(udma_modes & 0x01) {
					driver->devices[count].udma_supported = kATA_UDMA0;
				} if(udma_modes & 0x02) {
					driver->devices[count].udma_supported = kATA_UDMA1;
				} if(udma_modes & 0x04) {
					driver->devices[count].udma_supported = kATA_UDMA2;
				} if(udma_modes & 0x08) {
					driver->devices[count].udma_supported = kATA_UDMA3;
				} if(udma_modes & 0x10) {
					driver->devices[count].udma_supported = kATA_UDMA4;
				} if(udma_modes & 0x20) {
					driver->devices[count].udma_supported = kATA_UDMA5;
				}

				// No UDMA support
				if (!(udma_modes & 0x2F)) {
					driver->devices[count].udma_supported = kATA_UDMANone;
				}


				// Get supported multiword DMA modes
				uint16_t mwdma_modes = *((uint16_t *) (ide_buf + ATA_IDENT_MWDMASUPPORT));
				if(mwdma_modes & 0x01) {
					driver->devices[count].mwdma_supported = kATA_MWDMA0;
				} if(mwdma_modes & 0x02) {
					driver->devices[count].mwdma_supported = kATA_MWDMA1;
				} if(mwdma_modes & 0x04) {
					driver->devices[count].mwdma_supported = kATA_MWDMA2;
				} 

				// No multiword DMA modes supported
				if (!(mwdma_modes & 0x07)) {
					driver->devices[count].mwdma_supported = kATA_MWDMANone;
				}


				// Get supported singleword DMA modes
				uint16_t swdma_modes = *((uint16_t *) (ide_buf + ATA_IDENT_SWDMASUPPORT));
				if(swdma_modes & 0x01) {
					driver->devices[count].swdma_supported = kATA_SWDMA0;
				} if(swdma_modes & 0x02) {
					driver->devices[count].swdma_supported = kATA_SWDMA1;
				} if(swdma_modes & 0x04) {
					driver->devices[count].swdma_supported = kATA_SWDMA2;
				} 

				// No singleword DMA modes supported
				if (!(swdma_modes & 0x07)) {
					driver->devices[count].swdma_supported = kATA_SWDMANone;
				}


				// Get supported PIO modes with flow control
				uint16_t pio_modes = *((uint16_t *) (ide_buf + ATA_IDENT_PIOSUPPORT));
				if(pio_modes & 0x01) {
					driver->devices[count].pio_supported = kATA_PIO3;
				} if(pio_modes & 0x02) {
					driver->devices[count].pio_supported = kATA_PIO4;
				} else { // If there's no flow control support, fall back to PIO0
					driver->devices[count].pio_supported = kATA_PIO0;					
				}

				// Read PIO transfer cycle lengths
				driver->devices[count].pio_cycle_len = *((uint16_t *) (ide_buf + ATA_IDENT_PIOCYC));
				driver->devices[count].pio_cycle_len_iordy = *((uint16_t *) (ide_buf + ATA_IDENT_PIOCYCIORDY));

				/*
				 * Multiword and singleword DMA are supported regardless of the
				 * cable used, so the best mode the drive supports is the one
				 * we prefer.
				 */
				driver->devices[count].mwdma_preferred = driver->devices[count].mwdma_supported;
				driver->devices[count].swdma_preferred = driver->devices[count].swdma_supported;
				driver->devices[count].pio_preferred = driver->devices[count].pio_supported;
			} else {
					driver->devices[count].udma_supported = kATA_UDMANone;
					driver->devices[count].mwdma_supported = kATA_MWDMANone;
			}

			// Set up a disk structure
			hal_disk_t *disk = hal_disk_alloc();
			ASSERT(disk);

			disk->f = ata_hal_disk_functions;
			disk->drive_number = count;
			disk->driver = driver;
			disk->interface = kDiskInterfacePATA;

			// If the drive is a hard disk, we know that it's got media loaded
			if(!isATAPI) {
				disk->type = kDiskTypeHardDrive;
				disk->media_loaded = true;
			} else {
				disk->type = kDiskTypeOptical;
			}

			// Get sleep status from ATA IDENTIFY response
			disk->sleep_enabled = false;

			// Register with volume manager
			hal_disk_register(disk);

			count++;
		}
	}

	for (int i = 0; i < 4; i++) {
		if (driver->devices[i].drive_exists == true) {
			if(driver->devices[i].type == ATA_DEVICE_TYPE_ATA) {
				KDEBUG("Found ATA drive (%s) of %u sectors (Multiword DMA %u, UDMA %u, PIO %u)", driver->devices[i].model, (unsigned int)(driver->devices[i].size & 0xFFFFFFFF), driver->devices[i].mwdma_supported, driver->devices[i].udma_supported, driver->devices[count].pio_supported);
			} else {
				KDEBUG("Found ATAPI drive (%s) of %u sectors", driver->devices[i].model, (unsigned int)(driver->devices[i].size & 0xFFFFFFFF));
			}
		}
	}

	// Clean up allocated memory
	kfree(ide_buf);

	IRQ_RES();
	ata_drivers_loaded++;
	return driver;
}