Removed the drivers/ directory; it was not used anymore. All current drivers
are in src/add-ons/kernel/drivers/. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@11900 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
e17c805d8f
commit
1000949230
@ -454,6 +454,5 @@ NotFile bootfloppy ;
|
||||
SubInclude OBOS_TOP src kernel apps ;
|
||||
SubInclude OBOS_TOP src kernel boot ;
|
||||
SubInclude OBOS_TOP src kernel core ;
|
||||
SubInclude OBOS_TOP src kernel drivers ;
|
||||
SubInclude OBOS_TOP src kernel glue ;
|
||||
SubInclude OBOS_TOP src kernel libroot ;
|
||||
|
@ -1,21 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers ;
|
||||
|
||||
{
|
||||
local console_src ;
|
||||
|
||||
# console is currently x86 only
|
||||
if $(OBOS_ARCH) = x86 {
|
||||
console_src = <$(SOURCE_GRIST)>arch/$(OBOS_ARCH)/console/console.c ;
|
||||
} else {
|
||||
console_src = ;
|
||||
}
|
||||
|
||||
KernelStaticLibrary libdrivers :
|
||||
$(console_src)
|
||||
<$(SOURCE_GRIST)>fb_console/fb_console.c
|
||||
:
|
||||
-fno-pic -Wno-unused
|
||||
;
|
||||
}
|
||||
|
||||
SubInclude OBOS_TOP src kernel drivers arch ;
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch ;
|
||||
|
||||
SubInclude OBOS_TOP src kernel drivers arch $(OBOS_ARCH) ;
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch ppc ;
|
||||
|
||||
# nothing to do here
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch x86 ;
|
||||
|
||||
SubInclude OBOS_TOP src kernel drivers arch x86 console ;
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch x86 console ;
|
||||
|
||||
#KernelObjects console.c : -fnopic ;
|
@ -1,352 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <Drivers.h>
|
||||
#include <console.h>
|
||||
#include <vm.h>
|
||||
#include <devfs.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <arch/x86/console_dev.h>
|
||||
|
||||
static unsigned int origin = 0;
|
||||
|
||||
#define SCREEN_START 0xb8000
|
||||
#define SCREEN_END 0xc0000
|
||||
#define LINES 25
|
||||
#define COLUMNS 80
|
||||
#define NPAR 16
|
||||
#define TAB_SIZE 8
|
||||
#define TAB_MASK 7
|
||||
|
||||
#define TEXT_INDEX 0x3d4
|
||||
#define TEXT_DATA 0x3d5
|
||||
|
||||
#define TEXT_CURSOR_LO 0x0f
|
||||
#define TEXT_CURSOR_HI 0x0e
|
||||
|
||||
#define scr_end (origin+LINES*COLUMNS*2)
|
||||
|
||||
static unsigned int pos = 0;
|
||||
static unsigned int x = 0;
|
||||
static unsigned int y = 0;
|
||||
static unsigned int bottom=LINES;
|
||||
static unsigned int lines=LINES;
|
||||
static unsigned int columns=COLUMNS;
|
||||
static unsigned char attr=0x07;
|
||||
|
||||
static mutex console_lock;
|
||||
static int keyboard_fd = -1;
|
||||
|
||||
static void
|
||||
update_cursor(unsigned int x, unsigned int y)
|
||||
{
|
||||
short int pos = y*columns + x;
|
||||
|
||||
out8(TEXT_CURSOR_LO, TEXT_INDEX);
|
||||
out8((char)pos, TEXT_DATA);
|
||||
out8(TEXT_CURSOR_HI, TEXT_INDEX);
|
||||
out8((char)(pos >> 8), TEXT_DATA);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
gotoxy(unsigned int new_x,unsigned int new_y)
|
||||
{
|
||||
if (new_x>=columns || new_y>=lines)
|
||||
return;
|
||||
x = new_x;
|
||||
y = new_y;
|
||||
pos = origin+((y*columns+x)<<1);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scrup(void)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
// move the screen up one
|
||||
memcpy((void *)origin, (void *)(origin + 2 * COLUMNS), 2 * (LINES - 1) * COLUMNS);
|
||||
|
||||
// set the new position to the beginning of the last line
|
||||
pos = origin + (LINES-1)*COLUMNS*2;
|
||||
|
||||
// clear the bottom line
|
||||
for (i = pos; i < scr_end; i += 2) {
|
||||
*(unsigned short *)i = 0x0720;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clear_screen(void)
|
||||
{
|
||||
uint16 *base = (uint16 *)origin;
|
||||
uint32 i;
|
||||
|
||||
for (i = 0; i < COLUMNS * LINES; i++)
|
||||
base[i] = 0xf20;
|
||||
|
||||
pos = origin;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lf(void)
|
||||
{
|
||||
if (y+1<bottom) {
|
||||
y++;
|
||||
pos += columns<<1;
|
||||
return;
|
||||
}
|
||||
scrup();
|
||||
}
|
||||
|
||||
static void
|
||||
cr(void)
|
||||
{
|
||||
pos -= x<<1;
|
||||
x=0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
del(void)
|
||||
{
|
||||
if (x > 0) {
|
||||
pos -= 2;
|
||||
x--;
|
||||
*(unsigned short *)pos = 0x0720;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int saved_x = 0;
|
||||
static int saved_y = 0;
|
||||
|
||||
|
||||
static void
|
||||
save_cur(void)
|
||||
{
|
||||
saved_x=x;
|
||||
saved_y=y;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
restore_cur(void)
|
||||
{
|
||||
x=saved_x;
|
||||
y=saved_y;
|
||||
pos=origin+((y*columns+x)<<1);
|
||||
}
|
||||
|
||||
|
||||
static char
|
||||
console_putch(const char c)
|
||||
{
|
||||
if(++x>=COLUMNS) {
|
||||
cr();
|
||||
lf();
|
||||
}
|
||||
|
||||
*(char *)pos = c;
|
||||
*(char *)(pos+1) = attr;
|
||||
|
||||
pos += 2;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tab(void)
|
||||
{
|
||||
x = (x + TAB_SIZE) & ~TAB_MASK;
|
||||
if (x >= COLUMNS) {
|
||||
x -= COLUMNS;
|
||||
lf();
|
||||
}
|
||||
pos = origin + ((y * columns + x) << 1);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
// dprintf("console_open\n");
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_freecookie(void * cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_close(void * cookie)
|
||||
{
|
||||
// dprintf("console_close: entry\n");
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_read(void *cookie, off_t pos, void *buf, size_t *len)
|
||||
{
|
||||
/* XXX - optimistic!! */
|
||||
*len = read_pos(keyboard_fd, 0, buf, *len);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static ssize_t
|
||||
_console_write(const void *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
const char *c;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
c = &((const char *)buf)[i];
|
||||
switch (*c) {
|
||||
case '\n':
|
||||
cr();
|
||||
lf();
|
||||
break;
|
||||
case '\r':
|
||||
cr();
|
||||
break;
|
||||
case 0x8: // backspace
|
||||
del();
|
||||
break;
|
||||
case '\t':
|
||||
tab();
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
console_putch(*c);
|
||||
}
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_write(void * cookie, off_t pos, const void *buf, size_t *len)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
mutex_lock(&console_lock);
|
||||
|
||||
status = _console_write(buf, *len);
|
||||
if (status < 0)
|
||||
*len = 0;
|
||||
else {
|
||||
*len = status;
|
||||
status = B_OK;
|
||||
}
|
||||
|
||||
update_cursor(x, y);
|
||||
|
||||
mutex_unlock(&console_lock);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_ioctl(void * cookie, uint32 op, void *buf, size_t len)
|
||||
{
|
||||
status_t err;
|
||||
|
||||
switch(op) {
|
||||
case CONSOLE_OP_WRITEXY: {
|
||||
int x, y;
|
||||
mutex_lock(&console_lock);
|
||||
|
||||
x = ((int *)buf)[0];
|
||||
y = ((int *)buf)[1];
|
||||
|
||||
save_cur();
|
||||
gotoxy(x, y);
|
||||
if(_console_write(((char *)buf) + 2 * sizeof(int), len - 2 * sizeof(int)) > 0)
|
||||
err = 0; // we're okay
|
||||
else
|
||||
err = EIO;
|
||||
restore_cur();
|
||||
mutex_unlock(&console_lock);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
err = EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
device_hooks console_hooks = {
|
||||
&console_open,
|
||||
&console_close,
|
||||
&console_freecookie,
|
||||
&console_ioctl,
|
||||
&console_read,
|
||||
&console_write,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
console_dev_init(kernel_args *ka)
|
||||
{
|
||||
if (!ka->frame_buffer.enabled) {
|
||||
dprintf("con_init: mapping vid mem\n");
|
||||
vm_map_physical_memory(vm_get_kernel_aspace_id(), "vid_mem", (void *)&origin, B_ANY_KERNEL_ADDRESS,
|
||||
SCREEN_END - SCREEN_START, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, SCREEN_START);
|
||||
|
||||
dprintf("con_init: mapped vid mem to virtual address 0x%x\n", origin);
|
||||
|
||||
pos = origin;
|
||||
|
||||
/* XXX - this is a problem for having the console dynamically linked.
|
||||
* When dynamically linked the init_hardware and init_driver
|
||||
* routines don't take a kernel_args parameter so we don't have
|
||||
* access to this information. We probably need to find a
|
||||
* better way of doing this.
|
||||
*/
|
||||
if (ka->cons_line != 0)
|
||||
gotoxy(0, ka->cons_line);
|
||||
else
|
||||
clear_screen();
|
||||
update_cursor(x, y);
|
||||
|
||||
mutex_init(&console_lock, "console_lock");
|
||||
keyboard_fd = open("/dev/keyboard", O_RDONLY);
|
||||
if (keyboard_fd < 0)
|
||||
panic("console_dev_init: error opening /dev/keyboard\n");
|
||||
|
||||
/* As this is statically linked into the kernel we need to actually
|
||||
* publish our dev entry point.
|
||||
*/
|
||||
devfs_publish_device("console", NULL, &console_hooks);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,3 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers arch x86 ide ;
|
||||
|
||||
KernelStaticLibrary libide : ide.c ide_raw.c ;
|
@ -1,390 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Modified Sep 2001 by Rob Judd <judd@ob-wan.com>
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <kernel.h>
|
||||
#include <console.h>
|
||||
#include <debug.h>
|
||||
#include <memheap.h>
|
||||
#include <int.h>
|
||||
#include <OS.h>
|
||||
#include <vfs.h>
|
||||
#include <errors.h>
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#include <arch/int.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <arch/x86/ide_bus.h>
|
||||
|
||||
#include <devfs.h>
|
||||
|
||||
#include "ide_private.h"
|
||||
#include "ide_raw.h"
|
||||
|
||||
ide_device devices[MAX_DEVICES];
|
||||
sem_id ide_sem;
|
||||
|
||||
#define IDE_0_INTERRUPT 14
|
||||
#define IDE_1_INTERRUPT 15
|
||||
#define MAX_PARTITIONS 8
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ide_device* dev; // Pointer to entry in 'devices' table
|
||||
|
||||
// Specs for whole disk or partition
|
||||
uint32 block_start; // Number of first block
|
||||
uint32 block_count; // Number of blocks used
|
||||
uint16 block_size; // Bytes per block
|
||||
} ide_ident;
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
ide_ident* ident = (ide_ident*)kmalloc(sizeof(ide_ident));
|
||||
/* We hold our 'ident' structure as cookie, as it contains all we need */
|
||||
*cookie = ident;
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_close(void * _cookie)
|
||||
{
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_freecookie(void *cookie)
|
||||
{
|
||||
kfree(cookie);
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_seek(void * cookie, off_t pos, seek_type st)
|
||||
{
|
||||
return ERR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_get_geometry(ide_device* device, void *buf, size_t len)
|
||||
{
|
||||
drive_geometry* drive_geometry = buf;
|
||||
|
||||
if (len < sizeof(drive_geometry))
|
||||
return ERR_VFS_INSUFFICIENT_BUF;
|
||||
|
||||
drive_geometry->blocks = device->end_block - device->start_block;
|
||||
drive_geometry->heads = device->hardware_device.heads;
|
||||
drive_geometry->cylinders = device->hardware_device.cyls;
|
||||
drive_geometry->sectors = device->hardware_device.sectors;
|
||||
drive_geometry->removable = false;
|
||||
drive_geometry->bytes_per_sector = device->bytes_per_sector;
|
||||
drive_geometry->read_only = false;
|
||||
strcpy(drive_geometry->model, device->hardware_device.model);
|
||||
strcpy(drive_geometry->serial, device->hardware_device.serial);
|
||||
strcpy(drive_geometry->firmware, device->hardware_device.firmware);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_ioctl(void * _cookie, uint32 op, void *buf, size_t len)
|
||||
{
|
||||
ide_ident* cookie = (ide_ident*)_cookie;
|
||||
int err = 0;
|
||||
|
||||
acquire_sem(ide_sem);
|
||||
|
||||
switch(op) {
|
||||
case DISK_GET_GEOMETRY:
|
||||
err = ide_get_geometry(cookie->dev,buf,len);
|
||||
break;
|
||||
|
||||
case DISK_USE_DMA:
|
||||
case DISK_USE_BUS_MASTERING:
|
||||
err = ERR_UNIMPLEMENTED;
|
||||
break;
|
||||
|
||||
case DISK_USE_PIO:
|
||||
err = NO_ERROR;
|
||||
break;
|
||||
|
||||
case DISK_GET_ACCOUSTIC_LEVEL:
|
||||
if (len != sizeof(int8)) {
|
||||
err = ERR_INVALID_ARGS;
|
||||
} else {
|
||||
err = ide_get_accoustic(cookie->dev, (int8*)buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case DISK_SET_ACCOUSTIC_LEVEL:
|
||||
if (len != sizeof(int8)) {
|
||||
err = ERR_INVALID_ARGS;
|
||||
} else {
|
||||
err = ide_set_accoustic(cookie->dev,*(int8*)buf);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
err = ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
release_sem(ide_sem);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static ssize_t ide_read(void * _cookie, off_t pos, void *buf, size_t *len)
|
||||
{
|
||||
ide_ident* cookie = (ide_ident*)_cookie;
|
||||
uint32 sectors;
|
||||
uint32 currentSector;
|
||||
uint32 sectorsToRead;
|
||||
uint32 block;
|
||||
|
||||
if (cookie == NULL) {
|
||||
return ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
// Make sure noone else is doing IDE
|
||||
acquire_sem(ide_sem);
|
||||
|
||||
// Calculate start block and number of blocks to read
|
||||
block = pos / cookie->block_size;
|
||||
block += cookie->block_start;
|
||||
sectors = *len / cookie->block_size;
|
||||
|
||||
// correct len to be the actual # of bytes to read
|
||||
*len -= *len % cookie->block_size;
|
||||
|
||||
// If it goes beyond the disk/partition, exit
|
||||
if (block + sectors > cookie->block_start + cookie->block_count) {
|
||||
release_sem(ide_sem);
|
||||
*len = 0;
|
||||
/* XXX - should be returning an error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Start reading the sectors
|
||||
currentSector = 0;
|
||||
while(currentSector < sectors) {
|
||||
// Read max. of 255 sectors at a time
|
||||
sectorsToRead = (sectors - currentSector) > 255 ? 255 : sectors;
|
||||
|
||||
// If the read fails, exit with I/O error
|
||||
if (ide_read_block(cookie->dev, buf, block, sectorsToRead) != 0) {
|
||||
release_sem(ide_sem);
|
||||
return ERR_IO_ERROR;
|
||||
}
|
||||
|
||||
// Move to next block to read
|
||||
block += sectorsToRead * cookie->block_size;
|
||||
currentSector += sectorsToRead;
|
||||
}
|
||||
|
||||
// Give up
|
||||
release_sem(ide_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static ssize_t ide_write(void * _cookie, off_t pos, const void *buf, size_t *len)
|
||||
{
|
||||
int block;
|
||||
ide_ident* cookie = _cookie;
|
||||
uint32 sectors;
|
||||
uint32 currentSector;
|
||||
uint32 sectorsToWrite;
|
||||
|
||||
dprintf("ide_write: entry buf %p, pos 0x%Lx, *len %ld\n", buf, pos, *len);
|
||||
if(cookie == NULL) {
|
||||
return ERR_INVALID_ARGS;
|
||||
}
|
||||
|
||||
// Make sure no other I/O is done
|
||||
acquire_sem(ide_sem);
|
||||
|
||||
// Get the start pos and block count to write
|
||||
block = pos / cookie->block_size + cookie->block_start;
|
||||
sectors = *len / cookie->block_size;
|
||||
|
||||
// If we're writing more than the disk/partition size
|
||||
if (block + sectors > cookie->block_start + cookie->block_count) {
|
||||
// exit without writing
|
||||
release_sem(ide_sem);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Loop over sectors to write
|
||||
currentSector = 0;
|
||||
while(currentSector < sectors) {
|
||||
// Write a max of 255 sectors at a time
|
||||
sectorsToWrite = (sectors - currentSector) > 255 ? 255 : sectors;
|
||||
|
||||
// Write them
|
||||
if (ide_write_block(cookie->dev, buf, block, sectorsToWrite) != 0) {
|
||||
// dprintf("ide_write: ide_block returned %d\n", rc);
|
||||
*len = currentSector * cookie->block_size;
|
||||
release_sem(ide_sem);
|
||||
return ERR_IO_ERROR;
|
||||
}
|
||||
|
||||
block += sectorsToWrite * cookie->block_size;
|
||||
currentSector += sectorsToWrite;
|
||||
}
|
||||
|
||||
release_sem(ide_sem);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_canpage(void * ident)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static ssize_t ide_readpage(void * ident, iovecs *vecs, off_t pos)
|
||||
{
|
||||
return ERR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static ssize_t ide_writepage(void * ident, iovecs *vecs, off_t pos)
|
||||
{
|
||||
return ERR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
device_hooks ide_hooks = {
|
||||
ide_open,
|
||||
ide_close,
|
||||
ide_freecookie,
|
||||
ide_ioctl,
|
||||
ide_read,
|
||||
ide_write,
|
||||
NULL,
|
||||
NULL,
|
||||
// NULL,
|
||||
// NULL
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static int ide_interrupt_handler(void* data)
|
||||
{
|
||||
dprintf("in ide interrupt handler\n");
|
||||
return INT_RESCHEDULE;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static ide_ident* ide_create_device_ident(ide_device* dev, int16 partition)
|
||||
{
|
||||
ide_ident* ident = kmalloc(sizeof(ide_ident));
|
||||
if (ident != NULL) {
|
||||
ident->dev = dev;
|
||||
ident->block_size = dev->bytes_per_sector;
|
||||
|
||||
if (partition >= 0 && partition < MAX_PARTITIONS) {
|
||||
ident->block_start = dev->partitions[partition].starting_block;
|
||||
ident->block_count = dev->partitions[partition].sector_count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ident->block_start = 0;
|
||||
ident->block_count = dev->sector_count;
|
||||
}
|
||||
}
|
||||
|
||||
return ident;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static bool ide_attach_device(int bus, int device)
|
||||
{
|
||||
ide_device* ide = &devices[(bus*2) + device];
|
||||
ide_ident* ident = NULL;
|
||||
char devpath[256];
|
||||
int part;
|
||||
|
||||
ide->bus = bus;
|
||||
ide->device = device;
|
||||
|
||||
if (ide_identify_device(bus, device)) {
|
||||
ide->magic = IDE_MAGIC_COOKIE;
|
||||
ide->magic2 = IDE_MAGIC_COOKIE2;
|
||||
|
||||
if (ide_get_partitions(ide)) {
|
||||
for (part=0; part < NUM_PARTITIONS*2; part++) {
|
||||
if (ide->partitions[part].partition_type != 0 &&
|
||||
(ident=ide_create_device_ident(ide, part)) != NULL) {
|
||||
sprintf(devpath, "disk/ide/ata/%d/%d/%d", bus, device, part);
|
||||
devfs_publish_device(devpath, ident, &ide_hooks);
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("ide_attach_device(bus=%d,dev=%d) rc=true\n", bus, device);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
dprintf("ide_attach_device(bus=%d,dev=%d) rc=false\n", bus, device);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
static bool ide_attach_buses(unsigned int bus)
|
||||
{
|
||||
// char devpath[256];
|
||||
int found = 0;
|
||||
int dev;
|
||||
|
||||
for(dev=0; dev < 2; dev++)
|
||||
if (ide_attach_device(bus, dev))
|
||||
found++;
|
||||
|
||||
return(found > 0 ? true : false);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
|
||||
//--------------------------------------------------------------------------------
|
||||
// Don't try and attach more then one bus to the driver, as ide_raw_init
|
||||
// overwrites globals and you end up writing blocks which were meant
|
||||
// for bus #1 to bus #2 :(
|
||||
//
|
||||
// !!!!!! So, only use the one or the other, _never_ both !!!!!!
|
||||
//--------------------------------------------------------------------------------
|
||||
int ide_bus_init(kernel_args *ka)
|
||||
{
|
||||
// Create our top-level semaphore
|
||||
ide_sem = create_sem(1, "ide_sem");
|
||||
if (ide_sem < 0) {
|
||||
// We failed, so tell caller
|
||||
return ide_sem;
|
||||
}
|
||||
|
||||
// attach ide bus #1
|
||||
int_set_io_interrupt_handler(0x20 + IDE_0_INTERRUPT, &ide_interrupt_handler, NULL);
|
||||
ide_raw_init(0x1f0, 0x3f0);
|
||||
ide_attach_buses(0);
|
||||
|
||||
// attach ide bus #2
|
||||
// int_set_io_interrupt_handler(0x20 + IDE_1_INTERRUPT, &ide_interrupt_handler, NULL);
|
||||
// ide_raw_init(0x170, 0x370);
|
||||
// ide_attach_buses(1);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,718 +0,0 @@
|
||||
/*
|
||||
** Copyright 2001, Travis Geiselbrecht. All rights reserved.
|
||||
** Heavily modified by Rob Judd <judd@ob-wan.com> with
|
||||
** acknowledgements to Hale Landis <hlandis@ibm.net>
|
||||
** who wrote the reference implementation.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include "ide_private.h"
|
||||
#include <arch/cpu.h>
|
||||
#include <OS.h>
|
||||
#include <debug.h>
|
||||
#include "ide_raw.h"
|
||||
#include "partition.h"
|
||||
#include <string.h>
|
||||
#include <types.h>
|
||||
#include <ktypes.h>
|
||||
#include <errors.h>
|
||||
#include <thread.h>
|
||||
|
||||
// ATA register bits
|
||||
|
||||
// command block
|
||||
#define CB_DATA 0 // data reg in/out pio_base_addr1+0
|
||||
#define CB_ERR 1 // error reg in pio_base_addr1+1
|
||||
#define CB_FR 1 // feature reg out pio_base_addr1+1
|
||||
#define CB_SC 2 // sector count reg in/out pio_base_addr1+2
|
||||
#define CB_SN 3 // sector number reg in/out pio_base_addr1+3
|
||||
// or block address 0-7
|
||||
#define CB_CL 4 // cylinder low reg in/out pio_base_addr1+4
|
||||
// or block address 8-15
|
||||
#define CB_CH 5 // cylinder high reg in/out pio_base_addr1+5
|
||||
// or block address 16-23
|
||||
#define CB_DH 6 // drive/head reg in/out pio_base_addr1+6
|
||||
#define CB_STAT 7 // primary status reg in pio_base_addr1+7
|
||||
#define CB_CMD 7 // command reg out pio_base_addr1+7
|
||||
|
||||
// control block
|
||||
#define CB_ASTAT 8 // alternate status reg in pio_base_addr2+6
|
||||
#define CB_DC 8 // device control reg out pio_base_addr2+6
|
||||
#define CB_DA 9 // device address reg in pio_base_addr2+7
|
||||
|
||||
// error register
|
||||
#define CB_ER_NDAM 0x01 // ATA address mark not found
|
||||
#define CB_ER_NTK0 0x02 // ATA track 0 not found
|
||||
#define CB_ER_ABRT 0x04 // ATA command aborted
|
||||
#define CB_ER_MCR 0x08 // ATA media change request
|
||||
#define CB_ER_IDNF 0x10 // ATA id not found
|
||||
#define CB_ER_MC 0x20 // ATA media change
|
||||
#define CB_ER_UNC 0x40 // ATA uncorrected error
|
||||
#define CB_ER_BBK 0x80 // ATA bad block
|
||||
#define CB_ER_ICRC 0x80 // ATA Ultra DMA bad CRC
|
||||
|
||||
// drive/head register bits 7-4
|
||||
#define CB_DH_LBA 0x40 // LBA bit mask
|
||||
#define CB_DH_DEV0 0xa0 // select device 0
|
||||
#define CB_DH_DEV1 0xb0 // select device 1
|
||||
|
||||
#define DRIVE_SUPPORT_LBA 0x20 // test mask for LBA support
|
||||
|
||||
// status register bits
|
||||
#define CB_STAT_ERR 0x01 // error (ATA)
|
||||
#define CB_STAT_CHK 0x01 // check (ATAPI)
|
||||
#define CB_STAT_IDX 0x02 // index
|
||||
#define CB_STAT_CORR 0x04 // corrected
|
||||
#define CB_STAT_DRQ 0x08 // data request
|
||||
#define CB_STAT_SKC 0x10 // seek complete
|
||||
#define CB_STAT_SERV 0x10 // service
|
||||
#define CB_STAT_DF 0x20 // device fault
|
||||
#define CB_STAT_WFT 0x20 // write fault (old name)
|
||||
#define CB_STAT_RDY 0x40 // ready
|
||||
#define CB_STAT_BSY 0x80 // busy
|
||||
|
||||
// device control register bits
|
||||
#define CB_DC_NIEN 0x02 // disable interrupts
|
||||
#define CB_DC_SRST 0x04 // soft reset
|
||||
#define CB_DC_HD15 0x08 // bit should always be set to one
|
||||
|
||||
|
||||
// ATAPI commands
|
||||
|
||||
#define CB_ER_P_ILI 0x01 // ATAPI illegal length indication
|
||||
#define CB_ER_P_EOM 0x02 // ATAPI end of media
|
||||
#define CB_ER_P_ABRT 0x04 // ATAPI command abort
|
||||
#define CB_ER_P_MCR 0x08 // ATAPI media change request
|
||||
#define CB_ER_P_SNSKEY 0xf0 // ATAPI sense key mask
|
||||
|
||||
// ATAPI interrupt reason bits in the sector count register
|
||||
#define CB_SC_P_CD 0x01 // ATAPI C/D
|
||||
#define CB_SC_P_IO 0x02 // ATAPI I/O
|
||||
#define CB_SC_P_REL 0x04 // ATAPI release
|
||||
#define CB_SC_P_TAG 0xf8 // ATAPI tag (mask)
|
||||
|
||||
//**************************************************************
|
||||
|
||||
// The ATA command set
|
||||
|
||||
// Mandatory commands
|
||||
#define CMD_EXECUTE_DRIVE_DIAGNOSTIC 0x90
|
||||
#define CMD_FORMAT_TRACK 0x50
|
||||
#define CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
|
||||
#define CMD_READ_LONG 0x22 // One sector inc. ECC, with retry
|
||||
#define CMD_READ_LONG_ONCE 0x23 // One sector inc. ECC, sans retry
|
||||
#define CMD_READ_SECTORS 0x20
|
||||
#define CMD_READ_SECTORS_ONCE 0x21
|
||||
#define CMD_READ_VERIFY_SECTORS 0x40
|
||||
#define CMD_READ_VERIFY_SECTORS_ONCE 0x41
|
||||
#define CMD_RECALIBRATE 0x10 // Actually 0x10 to 0x1F
|
||||
#define CMD_SEEK 0x70 // Actually 0x70 to 0x7F
|
||||
#define CMD_WRITE_LONG 0x32
|
||||
#define CMD_WRITE_LONG_ONCE 0x33
|
||||
#define CMD_WRITE_SECTORS 0x30
|
||||
#define CMD_WRITE_SECTORS_ONCE 0x31
|
||||
|
||||
// Error codes for CMD_EXECUTE_DRIVE_DIAGNOSTICS
|
||||
#define DIAG_NO_ERROR 0x01
|
||||
#define DIAG_FORMATTER 0x02
|
||||
#define DIAG_DATA_BUFFER 0x03
|
||||
#define DIAG_ECC_CIRCUITRY 0x04
|
||||
#define DIAG_MICROPROCESSOR 0x05
|
||||
#define DIAG_SLAVE_DRIVE_MASK 0x80
|
||||
|
||||
// Accoustic Management commands
|
||||
#define CMD_SET_ACCOUSTIC_LEVEL 0x2A
|
||||
#define CMD_GET_ACCOUSTIC_LEVEL 0xAB
|
||||
|
||||
// Command codes for CMD_FORMAT_TRACK
|
||||
#define FMT_GOOD_SECTOR 0x00
|
||||
#define FMT_SUSPEND_REALLOC 0x20
|
||||
#define FMT_REALLOC_SECTOR 0x40
|
||||
#define FMT_MARK_SECTOR_DEFECTIVE 0x80
|
||||
|
||||
// Optional commands
|
||||
#define CMD_ACK_MEDIA_CHANGE 0xDB
|
||||
#define CMD_BOOT_POSTBOOT 0xDC
|
||||
#define CMD_BOOT_PREBOOT 0xDD
|
||||
#define CMD_CFA_ERASE_SECTORS 0xC0
|
||||
#define CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
|
||||
#define CMD_CFA_TRANSLATE_SECTOR 0x87
|
||||
#define CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
|
||||
#define CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
|
||||
#define CMD_CHECK_POWER_MODE 0x98
|
||||
#define CMD_DEVICE_RESET 0x08
|
||||
#define CMD_DOOR_LOCK 0xDE
|
||||
#define CMD_DOOR_UNLOCK 0xDF
|
||||
#define CMD_FLUSH_CACHE 0xE7 // CMD_REST
|
||||
#define CMD_IDENTIFY_DEVICE 0xEC
|
||||
#define CMD_IDENTIFY_DEVICE_PACKET 0xA1
|
||||
#define CMD_IDLE 0x97
|
||||
#define CMD_IDLE_IMMEDIATE 0x95
|
||||
#define CMD_NOP 0x00
|
||||
#define CMD_PACKET 0xA0
|
||||
#define CMD_READ_BUFFER 0xE4
|
||||
#define CMD_READ_DMA 0xC8
|
||||
#define CMD_READ_DMA_QUEUED 0xC7
|
||||
#define CMD_READ_MULTIPLE 0xC4
|
||||
#define CMD_RESTORE_DRIVE_STATE 0xEA
|
||||
#define CMD_SET_FEATURES 0xEF
|
||||
#define CMD_SET_MULTIPLE_MODE 0xC6
|
||||
#define CMD_SLEEP 0x99
|
||||
#define CMD_STANDBY 0x96
|
||||
#define CMD_STANDBY_IMMEDIATE 0x94
|
||||
#define CMD_WRITE_BUFFER 0xE8
|
||||
#define CMD_WRITE_DMA 0xCA
|
||||
#define CMD_WRITE_DMA_ONCE 0xCB
|
||||
#define CMD_WRITE_DMA_QUEUED 0xCC
|
||||
#define CMD_WRITE_MULTIPLE 0xC5
|
||||
#define CMD_WRITE_SAME 0xE9
|
||||
#define CMD_WRITE_VERIFY 0x3C
|
||||
|
||||
// Connor Peripherals' variations
|
||||
#define CONNOR_CHECK_POWER_MODE 0xE5
|
||||
#define CONNOR_IDLE 0xE3
|
||||
#define CONNOR_IDLE_IMMEDIATE 0xE1
|
||||
#define CONNOR_SLEEP 0xE6
|
||||
#define CONNOR_STANDBY 0xE2
|
||||
#define CONNOR_STANDBY_IMMEDIATE 0xE0
|
||||
|
||||
//**************************************************************
|
||||
|
||||
|
||||
// Waste some time by reading the alternate status a few times.
|
||||
// This gives the drive time to set BUSY in the status register on
|
||||
// really fast systems. If we don't do this, a slow drive on a fast
|
||||
// system may not set BUSY fast enough and we would think it had
|
||||
// completed the command when it really had not even started yet.
|
||||
#define DELAY400NS { pio_inbyte(CB_ASTAT); pio_inbyte(CB_ASTAT); \
|
||||
pio_inbyte(CB_ASTAT); pio_inbyte(CB_ASTAT); }
|
||||
|
||||
// Standard ide base addresses. For pc-card (pcmcia) drives, use
|
||||
// unused contiguous address block { 100H < (base1=base2) < 3F0H }
|
||||
unsigned int pio_base0_addr1 = 0x1f0; // Command block, ide bus 0
|
||||
unsigned int pio_base0_addr2 = 0x3f0; // Control block, ide bus 0
|
||||
unsigned int pio_base1_addr1 = 0x170; // Command block, ide bus 1
|
||||
unsigned int pio_base1_addr2 = 0x370; // Control block, ide bus 1
|
||||
|
||||
unsigned int pio_memory_seg = 0;
|
||||
unsigned int pio_reg_addrs[10];
|
||||
unsigned char pio_last_read[10];
|
||||
unsigned char pio_last_write[10];
|
||||
|
||||
|
||||
static uint8 pio_inbyte(uint16 port)
|
||||
{
|
||||
return in8(pio_reg_addrs[port]);
|
||||
}
|
||||
|
||||
static uint16 pio_inword(uint16 port)
|
||||
{
|
||||
return in16(pio_reg_addrs[port]);
|
||||
}
|
||||
|
||||
static void pio_outbyte(uint16 port, uint8 data)
|
||||
{
|
||||
out8(data, pio_reg_addrs[port]);
|
||||
}
|
||||
|
||||
static void pio_rep_inword(uint16 port, uint16 *addr, unsigned long count)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"rep ; insw" : "=D" (addr), "=c" (count) : "d" (pio_reg_addrs[port]),
|
||||
"0" (addr), "1" (count)
|
||||
);
|
||||
}
|
||||
|
||||
static void pio_rep_outword(uint16 port, uint16 *addr, unsigned long count)
|
||||
{
|
||||
__asm__ __volatile__
|
||||
(
|
||||
"rep ; outsw" : "=S" (addr), "=c" (count) : "d" (pio_reg_addrs[port]),
|
||||
"0" (addr), "1" (count)
|
||||
);
|
||||
}
|
||||
|
||||
static void ide_reg_poll()
|
||||
{
|
||||
while(1)
|
||||
{
|
||||
if ((pio_inbyte(CB_ASTAT) & CB_STAT_BSY) == 0) // If not busy
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ide_wait_busy()
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i=0; i<10000; i++)
|
||||
{
|
||||
if ((pio_inbyte(CB_ASTAT) & CB_STAT_BSY) == 0)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int ide_select_device(int bus, int device)
|
||||
{
|
||||
uint8 status;
|
||||
int i;
|
||||
ide_device ide = devices[(bus*2) + device];
|
||||
|
||||
// Test for a known, valid device
|
||||
if(ide.device_type == (NO_DEVICE | UNKNOWN_DEVICE))
|
||||
return NO_ERR;
|
||||
// See if we can get its attention
|
||||
if(ide_wait_busy() == false)
|
||||
return ERR_TIMEOUT;
|
||||
// Select required device
|
||||
pio_outbyte(CB_DH, device ? CB_DH_DEV1 : CB_DH_DEV0);
|
||||
DELAY400NS;
|
||||
for(i=0; i<10000; i++)
|
||||
{
|
||||
// Read the device status
|
||||
status = pio_inbyte(CB_STAT);
|
||||
if (ide.device_type == ATA_DEVICE)
|
||||
{
|
||||
if ((status & (CB_STAT_BSY | CB_STAT_RDY | CB_STAT_SKC))
|
||||
== (CB_STAT_RDY | CB_STAT_SKC))
|
||||
return NO_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((status & CB_STAT_BSY) == 0)
|
||||
return NO_ERR;
|
||||
}
|
||||
}
|
||||
return ERR_TIMEOUT;
|
||||
}
|
||||
|
||||
static void ide_delay(int bus, int device)
|
||||
{
|
||||
ide_device ide = devices[(bus*2) + device];
|
||||
|
||||
if(ide.device_type == ATAPI_DEVICE)
|
||||
thread_snooze(1000000);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
static int reg_pio_data_in(int bus, int dev, int cmd, int fr, int sc,
|
||||
unsigned int cyl, int head, int sect, uint8 *output,
|
||||
unsigned int numSect, unsigned int multiCnt)
|
||||
{
|
||||
unsigned char devHead;
|
||||
unsigned char devCtrl;
|
||||
unsigned char cylLow;
|
||||
unsigned char cylHigh;
|
||||
unsigned char status;
|
||||
uint16 *buffer = (uint16*)output;
|
||||
|
||||
// dprintf("reg_pio_data_in: bus %d dev %d cmd %d fr %d sc %d cyl %d head %d sect %d numSect %d multiCnt %d\n",
|
||||
// bus, dev, cmd, fr, sc, cyl, head, sect, numSect, multiCnt);
|
||||
|
||||
devCtrl = CB_DC_HD15 | CB_DC_NIEN;
|
||||
devHead = dev ? CB_DH_DEV1 : CB_DH_DEV0;
|
||||
devHead = devHead | (head & 0x4f);
|
||||
cylLow = cyl & 0x00ff;
|
||||
cylHigh = (cyl & 0xff00) >> 8;
|
||||
// these commands transfer only 1 sector
|
||||
if(cmd == (CMD_IDENTIFY_DEVICE | CMD_IDENTIFY_DEVICE_PACKET | CMD_READ_BUFFER))
|
||||
numSect = 1;
|
||||
// multiCnt = 1 unless CMD_READ_MULTIPLE true
|
||||
if(cmd != CMD_READ_MULTIPLE || !multiCnt)
|
||||
multiCnt = 1;
|
||||
// select the drive
|
||||
if(ide_select_device(bus, dev) == ERR_TIMEOUT)
|
||||
return ERR_TIMEOUT;
|
||||
// set up the registers
|
||||
pio_outbyte(CB_DC, devCtrl);
|
||||
pio_outbyte(CB_FR, fr);
|
||||
pio_outbyte(CB_SC, sc);
|
||||
pio_outbyte(CB_SN, sect);
|
||||
pio_outbyte(CB_CL, cylLow);
|
||||
pio_outbyte(CB_CH, cylHigh);
|
||||
pio_outbyte(CB_DH, devHead);
|
||||
// Start the command. The drive should immediately set BUSY status.
|
||||
pio_outbyte(CB_CMD, cmd);
|
||||
DELAY400NS;
|
||||
while(1)
|
||||
{
|
||||
ide_delay(bus, dev);
|
||||
// ensure drive isn't still busy
|
||||
ide_reg_poll();
|
||||
// check status once per read
|
||||
status = pio_inbyte(CB_STAT);
|
||||
if((numSect < 1) && (status & CB_STAT_DRQ))
|
||||
return ERR_BUFFER_NOT_EMPTY;
|
||||
if (numSect < 1)
|
||||
break;
|
||||
if((status & (CB_STAT_BSY | CB_STAT_DRQ)) == CB_STAT_DRQ)
|
||||
{
|
||||
unsigned int wordCnt = multiCnt > numSect ? numSect : multiCnt;
|
||||
wordCnt = wordCnt * 256;
|
||||
pio_rep_inword(CB_DATA, buffer, wordCnt);
|
||||
DELAY400NS;
|
||||
numSect = numSect - multiCnt;
|
||||
buffer += wordCnt;
|
||||
}
|
||||
// catch all possible fault conditions
|
||||
if(status & CB_STAT_BSY)
|
||||
return ERR_DISK_BUSY;
|
||||
if(status & CB_STAT_DF)
|
||||
return ERR_DEVICE_FAULT;
|
||||
if(status & CB_STAT_ERR)
|
||||
return ERR_HARDWARE_ERROR;
|
||||
if((status & CB_STAT_DRQ) == 0)
|
||||
return ERR_DRQ_NOT_SET;
|
||||
}
|
||||
return NO_ERR;
|
||||
}
|
||||
|
||||
static int reg_pio_data_out( int bus, int dev, int cmd, int fr, int sc,
|
||||
unsigned int cyl, int head, int sect, const uint8 *output,
|
||||
unsigned int numSect, unsigned int multiCnt )
|
||||
{
|
||||
unsigned char devHead;
|
||||
unsigned char devCtrl;
|
||||
unsigned char cylLow;
|
||||
unsigned char cylHigh;
|
||||
unsigned char status;
|
||||
uint16 *buffer = (uint16*)output;
|
||||
|
||||
devCtrl = CB_DC_HD15 | CB_DC_NIEN;
|
||||
devHead = dev ? CB_DH_DEV1 : CB_DH_DEV0;
|
||||
devHead = devHead | (head & 0x4f);
|
||||
cylLow = cyl & 0x00ff;
|
||||
cylHigh = (cyl & 0xff00) >> 8;
|
||||
if (cmd == CMD_WRITE_BUFFER)
|
||||
numSect = 1;
|
||||
// only Write Multiple and CFA Write Multiple W/O Erase uses multCnt
|
||||
if ((cmd != CMD_WRITE_MULTIPLE) && (cmd != CMD_CFA_WRITE_MULTIPLE_WO_ERASE))
|
||||
multiCnt = 1;
|
||||
// select the drive
|
||||
if (ide_select_device(bus, dev) != NO_ERR)
|
||||
return ERR_TIMEOUT;
|
||||
// set up the registers
|
||||
pio_outbyte(CB_DC, devCtrl);
|
||||
pio_outbyte(CB_FR, fr);
|
||||
pio_outbyte(CB_SC, sc);
|
||||
pio_outbyte(CB_SN, sect);
|
||||
pio_outbyte(CB_CL, cylLow);
|
||||
pio_outbyte(CB_CH, cylHigh);
|
||||
pio_outbyte(CB_DH, devHead);
|
||||
// Start the command. The drive should immediately set BUSY status.
|
||||
pio_outbyte(CB_CMD, cmd);
|
||||
DELAY400NS;
|
||||
if (ide_wait_busy() == false)
|
||||
return ERR_TIMEOUT;
|
||||
status = pio_inbyte(CB_STAT);
|
||||
while (1)
|
||||
{
|
||||
if ((status & (CB_STAT_BSY | CB_STAT_DRQ)) == CB_STAT_DRQ)
|
||||
{
|
||||
unsigned int wordCnt = multiCnt > numSect ? numSect : multiCnt;
|
||||
wordCnt = wordCnt * 256;
|
||||
pio_rep_outword(CB_DATA, buffer, wordCnt);
|
||||
DELAY400NS;
|
||||
numSect = numSect - multiCnt;
|
||||
buffer += wordCnt;
|
||||
}
|
||||
// check all possible fault conditions
|
||||
if(status & CB_STAT_BSY)
|
||||
return ERR_DISK_BUSY;
|
||||
if(status & CB_STAT_DF)
|
||||
return ERR_DEVICE_FAULT;
|
||||
if(status & CB_STAT_ERR)
|
||||
return ERR_HARDWARE_ERROR;
|
||||
if ((status & CB_STAT_DRQ) == 0)
|
||||
return ERR_DRQ_NOT_SET;
|
||||
ide_delay(bus, dev);
|
||||
// ensure drive isn't still busy
|
||||
ide_reg_poll();
|
||||
if(numSect < 1 && status & (CB_STAT_BSY | CB_STAT_DF | CB_STAT_ERR))
|
||||
{
|
||||
dprintf("status = 0x%x\n", status);
|
||||
return ERR_BUFFER_NOT_EMPTY;
|
||||
}
|
||||
}
|
||||
return NO_ERR;
|
||||
}
|
||||
|
||||
static void ide_btochs(uint32 block, ide_device *dev, int *cylinder, int *head, int *sect)
|
||||
{
|
||||
*sect = (block % dev->hardware_device.sectors) + 1;
|
||||
block /= dev->hardware_device.sectors;
|
||||
*head = (block % dev->hardware_device.heads) | (dev->device ? 1 : 0);
|
||||
block /= dev->hardware_device.heads;
|
||||
*cylinder = block & 0xFFFF;
|
||||
// dprintf("ide_btochs: block %d -> cyl %d head %d sect %d\n", block, *cylinder, *head, *sect);
|
||||
}
|
||||
|
||||
static void ide_btolba(uint32 block, ide_device *dev, int *cylinder, int *head, int *sect)
|
||||
{
|
||||
*sect = block & 0xFF;
|
||||
*cylinder = (block >> 8) & 0xFFFF;
|
||||
*head = ((block >> 24) & 0xF) | (dev->device ? 1: 0) | CB_DH_LBA;
|
||||
// dprintf("ide_btolba: block %d -> cyl %d head %d sect %d\n", block, *cylinder, *head, *sect);
|
||||
}
|
||||
|
||||
int ide_read_block(ide_device *device, char *data, uint32 block, uint8 numSectors)
|
||||
{
|
||||
int cyl, head, sect;
|
||||
|
||||
if(device->lba_supported)
|
||||
ide_btolba(block, device, &cyl, &head, §);
|
||||
else
|
||||
ide_btochs(block, device, &cyl, &head, §);
|
||||
|
||||
return reg_pio_data_in(device->bus, device->device, CMD_READ_SECTORS,
|
||||
0, numSectors, cyl, head, sect, data, numSectors, 2);
|
||||
}
|
||||
|
||||
int ide_write_block(ide_device *device, const char *data, uint32 block, uint8 numSectors)
|
||||
{
|
||||
int cyl, head, sect;
|
||||
|
||||
if(device->lba_supported)
|
||||
ide_btolba(block, device, &cyl, &head, §);
|
||||
else
|
||||
ide_btochs(block, device, &cyl, &head, §);
|
||||
|
||||
return reg_pio_data_out(device->bus, device->device, CMD_WRITE_SECTORS,
|
||||
0, numSectors, cyl, head, sect, data, numSectors, 2);
|
||||
}
|
||||
|
||||
void ide_string_conv (char *str, int len)
|
||||
{
|
||||
unsigned int i;
|
||||
int j;
|
||||
|
||||
for (i=0; i<len/sizeof(unsigned short); i++)
|
||||
{
|
||||
char c = str[i*2+1];
|
||||
str[i*2+1] = str[i*2];
|
||||
str[i*2] = c;
|
||||
}
|
||||
|
||||
str[len - 1] = 0;
|
||||
for (j=len-1; j>=0 && str[j]==' '; j--)
|
||||
str[j] = 0;
|
||||
}
|
||||
|
||||
// ide_reset() - execute a software reset
|
||||
bool ide_reset (int bus, int device)
|
||||
{
|
||||
unsigned char devCtrl = CB_DC_HD15 | CB_DC_NIEN;
|
||||
|
||||
// Set and then reset the soft reset bit in the Device
|
||||
// Control register. This causes device 0 be selected
|
||||
pio_outbyte(CB_DC, devCtrl | CB_DC_SRST);
|
||||
DELAY400NS;
|
||||
pio_outbyte(CB_DC, devCtrl);
|
||||
DELAY400NS;
|
||||
|
||||
return (ide_wait_busy() ? true : false);
|
||||
}
|
||||
|
||||
bool ide_identify_device(int bus, int device)
|
||||
{
|
||||
ide_device* ide = &devices[(bus*2) + device];
|
||||
uint8* buffer;
|
||||
int rc;
|
||||
|
||||
// Store specs for device
|
||||
ide->bus = bus;
|
||||
ide->device = device;
|
||||
|
||||
// Do an IDENTIFY DEVICE command
|
||||
buffer = (uint8*)&ide->hardware_device;
|
||||
rc = reg_pio_data_in(bus, device, CMD_IDENTIFY_DEVICE,
|
||||
1, 0, 0, 0, 0, buffer, 1, 0);
|
||||
|
||||
if (rc == NO_ERR) {
|
||||
// If command was ok, lets assume ATA device
|
||||
ide->device_type = ATA_DEVICE;
|
||||
|
||||
// Convert the model string to ASCIIZ
|
||||
ide_string_conv(ide->hardware_device.model, 40);
|
||||
|
||||
// Get copy over interesting data
|
||||
ide->sector_count = ide->hardware_device.cyls * ide->hardware_device.heads
|
||||
* ide->hardware_device.sectors;
|
||||
ide->bytes_per_sector = 512;
|
||||
ide->lba_supported = ide->hardware_device.capabilities & DRIVE_SUPPORT_LBA;
|
||||
ide->start_block = 0;
|
||||
ide->end_block = ide->sector_count + ide->start_block;
|
||||
|
||||
// Give some debugging output to show what was found
|
||||
dprintf ("ide: disk at bus %d, device %d %s\n", bus, device, ide->hardware_device.model);
|
||||
dprintf ("ide/%d/%d: %dMB; %d cyl, %d head, %d sec, %d bytes/sec (LBA=%d)\n",
|
||||
bus, device, ide->sector_count * ide->bytes_per_sector / (1024*1024),
|
||||
ide->hardware_device.cyls, ide->hardware_device.heads,
|
||||
ide->hardware_device.sectors, ide->bytes_per_sector, ide->lba_supported );
|
||||
} else {
|
||||
// Something went wrong, let's forget about this device
|
||||
ide->device_type = NO_DEVICE;
|
||||
}
|
||||
|
||||
return (rc == NO_ERROR) ? true : false;
|
||||
}
|
||||
|
||||
// Set the pio base addresses
|
||||
void ide_raw_init(int base1, int base2)
|
||||
{
|
||||
unsigned int pio_base_addr1 = base1;
|
||||
unsigned int pio_base_addr2 = base2;
|
||||
|
||||
pio_reg_addrs[CB_DATA] = pio_base_addr1 + 0; // 0
|
||||
pio_reg_addrs[CB_FR ] = pio_base_addr1 + 1; // 1
|
||||
pio_reg_addrs[CB_SC ] = pio_base_addr1 + 2; // 2
|
||||
pio_reg_addrs[CB_SN ] = pio_base_addr1 + 3; // 3
|
||||
pio_reg_addrs[CB_CL ] = pio_base_addr1 + 4; // 4
|
||||
pio_reg_addrs[CB_CH ] = pio_base_addr1 + 5; // 5
|
||||
pio_reg_addrs[CB_DH ] = pio_base_addr1 + 6; // 6
|
||||
pio_reg_addrs[CB_CMD ] = pio_base_addr1 + 7; // 7
|
||||
pio_reg_addrs[CB_DC ] = pio_base_addr2 + 6; // 8
|
||||
pio_reg_addrs[CB_DA ] = pio_base_addr2 + 7; // 9
|
||||
}
|
||||
|
||||
static char getHexChar(uint8 value)
|
||||
{
|
||||
if(value < 10)
|
||||
return value + '0';
|
||||
return 'A' + (value - 10);
|
||||
}
|
||||
|
||||
static void dumpHexLine(uint8 *buffer, int numberPerLine)
|
||||
{
|
||||
uint8 *copy = buffer;
|
||||
int i;
|
||||
|
||||
for(i=0; i<numberPerLine; i++)
|
||||
{
|
||||
uint8 value1 = getHexChar(((*copy) >> 4));
|
||||
uint8 value2 = getHexChar(((*copy) & 0xF));
|
||||
dprintf("%c%c ", value1, value2);
|
||||
copy++;
|
||||
}
|
||||
copy = buffer;
|
||||
for(i=0; i<numberPerLine; i++)
|
||||
{
|
||||
if(*copy >= ' ' && *copy <= 'Z')
|
||||
dprintf("%c", *copy);
|
||||
else
|
||||
dprintf(".");
|
||||
copy++;
|
||||
}
|
||||
dprintf("\n");
|
||||
}
|
||||
|
||||
static void dumpHexBuffer(uint8 *buffer, int size)
|
||||
{
|
||||
int numberPerLine = 8;
|
||||
int numberOfLines = size / numberPerLine;
|
||||
int i;
|
||||
|
||||
for(i=0; i<numberOfLines; i++)
|
||||
{
|
||||
dprintf("%d ", i*numberPerLine);
|
||||
dumpHexLine(buffer, numberPerLine);
|
||||
buffer += numberPerLine;
|
||||
}
|
||||
}
|
||||
|
||||
static bool ide_get_partition_info(ide_device *device, tPartition *partition, uint32 position)
|
||||
{
|
||||
char buffer[512];
|
||||
uint8* partitionBuffer = buffer;
|
||||
|
||||
// Try to read partition table
|
||||
if (ide_read_block(device, buffer, position, 1) != 0) {
|
||||
dprintf("unable to read partition table\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check partition table signature
|
||||
if (partitionBuffer[PART_MAGIC_OFFSET] != PARTITION_MAGIC1 ||
|
||||
partitionBuffer[PART_MAGIC_OFFSET+1] != PARTITION_MAGIC2) {
|
||||
dprintf("partition table magic is incorrect\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(partition, partitionBuffer + PARTITION_OFFSET, sizeof(tPartition) * NUM_PARTITIONS);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ide_get_partitions(ide_device *device)
|
||||
{
|
||||
int i;
|
||||
|
||||
memset(&device->partitions, 0, sizeof(tPartition) * 2 * NUM_PARTITIONS);
|
||||
if(ide_get_partition_info(device, device->partitions, 0) == false)
|
||||
return false;
|
||||
|
||||
dprintf("Primary Partition Table\n");
|
||||
for (i = 0; i < NUM_PARTITIONS; i++)
|
||||
{
|
||||
dprintf(" %d: flags:%x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
|
||||
i,
|
||||
device->partitions[i].boot_flags,
|
||||
device->partitions[i].partition_type,
|
||||
device->partitions[i].starting_head,
|
||||
device->partitions[i].starting_sector,
|
||||
device->partitions[i].starting_cylinder,
|
||||
device->partitions[i].ending_head,
|
||||
device->partitions[i].ending_sector,
|
||||
device->partitions[i].ending_cylinder,
|
||||
device->partitions[i].starting_block,
|
||||
device->partitions[i].sector_count);
|
||||
}
|
||||
if(device->partitions[1].partition_type == PTDosExtended)
|
||||
{
|
||||
int extOffset = device->partitions[1].starting_block;
|
||||
if(ide_get_partition_info(device, &device->partitions[4], extOffset) == false)
|
||||
return false;
|
||||
dprintf("Extended Partition Table\n");
|
||||
for (i=4; i<4+NUM_PARTITIONS; i++)
|
||||
{
|
||||
device->partitions[i].starting_block += extOffset;
|
||||
dprintf(" %d: flags:%x type:%x start:%d:%d:%d end:%d:%d:%d stblk:%d count:%d\n",
|
||||
i,
|
||||
device->partitions[i].boot_flags,
|
||||
device->partitions[i].partition_type,
|
||||
device->partitions[i].starting_head,
|
||||
device->partitions[i].starting_sector,
|
||||
device->partitions[i].starting_cylinder,
|
||||
device->partitions[i].ending_head,
|
||||
device->partitions[i].ending_sector,
|
||||
device->partitions[i].ending_cylinder,
|
||||
device->partitions[i].starting_block,
|
||||
device->partitions[i].sector_count);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// These two functions are called from ide_ioctl in ide.c. They are far from
|
||||
// tested, and mostly just a C conversion of a DEBUG script presented on
|
||||
// http://www.satwerk.de/ufd552.htm
|
||||
// This should be tweaked some more before actual release!
|
||||
|
||||
int ide_get_accoustic(ide_device *device, int8* level_ptr)
|
||||
{
|
||||
return ERR_UNIMPLEMENTED;
|
||||
}
|
||||
|
||||
int ide_set_accoustic(ide_device *device, int8 level)
|
||||
{
|
||||
pio_outbyte(CB_DH, (device->device == 1) ? CB_DH_DEV1 : CB_DH_DEV0);
|
||||
pio_outbyte(CB_CMD, CMD_SET_ACCOUSTIC_LEVEL);
|
||||
pio_outbyte(CB_SC, level);
|
||||
pio_outbyte(CB_STAT, 0xEF);
|
||||
|
||||
return NO_ERROR;
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
SubDir OBOS_TOP src kernel drivers fb_console ;
|
||||
|
||||
KernelStaticLibrary fb_console :
|
||||
fb_console.c
|
||||
: -fno-pic ;
|
@ -1,581 +0,0 @@
|
||||
/*
|
||||
** Copyright 2004, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
** Distributed under the terms of the Haiku License.
|
||||
**
|
||||
** Copyright 2001-2002, Travis Geiselbrecht. All rights reserved.
|
||||
** Distributed under the terms of the NewOS License.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <lock.h>
|
||||
#include <devfs.h>
|
||||
|
||||
#include <boot/kernel_args.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "font.h"
|
||||
|
||||
//#define TRACE_FB_CONSOLE
|
||||
#ifdef TRACE_FB_CONSOLE
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
status_t fb_console_dev_init(kernel_args *args);
|
||||
|
||||
#define WRAP(x, limit) ((x) % (limit))
|
||||
// This version makes the sh4 compiler throw up
|
||||
// This would work: (((x) >= (limit)) ? ((x) - (limit)) : (x))
|
||||
#define INC_WITH_WRAP(x, limit) WRAP((x) + 1, (limit))
|
||||
|
||||
enum {
|
||||
CONSOLE_OP_WRITEXY = 2376
|
||||
};
|
||||
|
||||
#define TAB_SIZE 8
|
||||
#define TAB_MASK 7
|
||||
|
||||
struct console_desc {
|
||||
// describe the framebuffer
|
||||
addr_t fb;
|
||||
addr_t fb_size;
|
||||
int fb_x;
|
||||
int fb_y;
|
||||
int fb_pixel_bytes;
|
||||
|
||||
// describe the setup we have
|
||||
int rows;
|
||||
int columns;
|
||||
|
||||
// describe the current state
|
||||
int x;
|
||||
int y;
|
||||
int color;
|
||||
int bcolor;
|
||||
int saved_x;
|
||||
int saved_y;
|
||||
|
||||
// text buffers
|
||||
char *buf;
|
||||
int first_line;
|
||||
int num_lines;
|
||||
char **lines;
|
||||
uint8 *dirty_lines;
|
||||
void *render_buf;
|
||||
|
||||
// renderer function
|
||||
void (*render_line)(char *line, int line_num);
|
||||
|
||||
mutex lock;
|
||||
int keyboard_fd;
|
||||
};
|
||||
|
||||
static struct console_desc console;
|
||||
|
||||
|
||||
static void
|
||||
render_line8(char *line, int line_num)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
uint8 *fb_spot = (uint8 *)(console.fb + line_num * CHAR_HEIGHT * console.fb_x);
|
||||
|
||||
for (y = 0; y < CHAR_HEIGHT; y++) {
|
||||
uint8 *render_spot = console.render_buf;
|
||||
for (x = 0; x < console.columns; x++) {
|
||||
if (line[x]) {
|
||||
uint8 bits = FONT[CHAR_HEIGHT * line[x] + y];
|
||||
for (i = 0; i < CHAR_WIDTH; i++) {
|
||||
if(bits & 1) *render_spot = console.color;
|
||||
else *render_spot = console.bcolor;
|
||||
bits >>= 1;
|
||||
render_spot++;
|
||||
}
|
||||
} else {
|
||||
// null character, ignore the rest of the line
|
||||
memset(render_spot, console.bcolor, (console.columns - x) * CHAR_WIDTH);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(fb_spot, console.render_buf, console.fb_x);
|
||||
fb_spot += console.fb_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
render_line16(char *line, int line_num)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
uint16 *fb_spot = (uint16 *)(console.fb + line_num * CHAR_HEIGHT * console.fb_x * 2);
|
||||
|
||||
for (y = 0; y < CHAR_HEIGHT; y++) {
|
||||
uint16 *render_spot = console.render_buf;
|
||||
for (x = 0; x < console.columns; x++) {
|
||||
if (line[x]) {
|
||||
uint8 bits = FONT[CHAR_HEIGHT * line[x] + y];
|
||||
for (i = 0; i < CHAR_WIDTH; i++) {
|
||||
if(bits & 1) *render_spot = console.color;
|
||||
else *render_spot = console.bcolor;
|
||||
bits >>= 1;
|
||||
render_spot++;
|
||||
}
|
||||
} else {
|
||||
// null character, ignore the rest of the line
|
||||
memset(render_spot, console.bcolor, (console.columns - x) * CHAR_WIDTH * 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(fb_spot, console.render_buf, console.fb_x * 2);
|
||||
fb_spot += console.fb_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
render_line32(char *line, int line_num)
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int i;
|
||||
uint32 *fb_spot = (uint32 *)(console.fb + line_num * CHAR_HEIGHT * console.fb_x * 4);
|
||||
|
||||
for (y = 0; y < CHAR_HEIGHT; y++) {
|
||||
uint32 *render_spot = console.render_buf;
|
||||
for (x = 0; x < console.columns; x++) {
|
||||
if (line[x]) {
|
||||
uint8 bits = FONT[CHAR_HEIGHT * line[x] + y];
|
||||
for (i = 0; i < CHAR_WIDTH; i++) {
|
||||
if(bits & 1) *render_spot = console.color;
|
||||
else *render_spot = console.bcolor;
|
||||
bits >>= 1;
|
||||
render_spot++;
|
||||
}
|
||||
} else {
|
||||
// null character, ignore the rest of the line
|
||||
memset(render_spot, console.bcolor, (console.columns - x) * CHAR_WIDTH * 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
memcpy(fb_spot, console.render_buf, console.fb_x * 4);
|
||||
fb_spot += console.fb_x;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** scans through the lines, seeing if any needs to be repainted */
|
||||
|
||||
static void
|
||||
repaint(void)
|
||||
{
|
||||
int i;
|
||||
int line_num;
|
||||
|
||||
line_num = console.first_line;
|
||||
for (i = 0; i < console.rows; i++) {
|
||||
//TRACE(("line_num = %d\n", line_num));
|
||||
if (console.dirty_lines[line_num]) {
|
||||
//TRACE(("repaint(): rendering line %d %d, func = %p\n", line_num, i, console.render_line));
|
||||
console.render_line(console.lines[line_num], i);
|
||||
console.dirty_lines[line_num] = 0;
|
||||
}
|
||||
line_num = INC_WITH_WRAP(line_num, console.num_lines);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scrup(void)
|
||||
{
|
||||
int i;
|
||||
int line_num;
|
||||
int last_line;
|
||||
|
||||
// move the pointer to the top line down one
|
||||
console.first_line = INC_WITH_WRAP(console.first_line, console.num_lines);
|
||||
|
||||
TRACE(("scrup: first_line now %d\n", console.first_line));
|
||||
|
||||
line_num = console.first_line;
|
||||
for (i = 0; i < console.rows; i++) {
|
||||
console.dirty_lines[line_num] = 1;
|
||||
line_num = INC_WITH_WRAP(line_num, console.num_lines);
|
||||
}
|
||||
|
||||
// clear out the last line
|
||||
last_line = WRAP(console.first_line + console.rows, console.num_lines);
|
||||
console.lines[last_line][0] = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
lf(void)
|
||||
{
|
||||
if (console.y + 1 < console.rows) {
|
||||
console.y++;
|
||||
return;
|
||||
}
|
||||
scrup();
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
cr(void)
|
||||
{
|
||||
console.x = 0;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
del(void)
|
||||
{
|
||||
int target_line = WRAP(console.first_line + console.y, console.num_lines);
|
||||
|
||||
if (console.x > 0) {
|
||||
console.x--;
|
||||
console.lines[target_line][console.x] = ' ';
|
||||
console.dirty_lines[target_line] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
static void
|
||||
save_cur(void)
|
||||
{
|
||||
console.saved_x = console.x;
|
||||
console.saved_y = console.y;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
restore_cur(void)
|
||||
{
|
||||
console.x = console.saved_x;
|
||||
console.y = console.saved_y;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static char
|
||||
console_put_character(const char c)
|
||||
{
|
||||
int target_line;
|
||||
|
||||
if (console.x + 1 >= console.columns) {
|
||||
cr();
|
||||
lf();
|
||||
}
|
||||
|
||||
target_line = WRAP(console.first_line + console.y, console.num_lines);
|
||||
console.lines[target_line][console.x++] = c;
|
||||
console.lines[target_line][console.x] = 0;
|
||||
console.dirty_lines[target_line] = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
tab(void)
|
||||
{
|
||||
int i = console.x;
|
||||
int target_line;
|
||||
|
||||
console.x = (console.x + TAB_SIZE) & ~TAB_MASK;
|
||||
if (console.x >= console.columns) {
|
||||
console.x -= console.columns;
|
||||
i = 0;
|
||||
lf();
|
||||
}
|
||||
|
||||
// We need to insert spaces, or else the whole line is going to be ignored.
|
||||
target_line = WRAP(console.first_line + console.y, console.num_lines);
|
||||
for (; i < console.x; i++) {
|
||||
console.lines[target_line][i] = ' ';
|
||||
}
|
||||
|
||||
console.lines[target_line][console.x] = '\0';
|
||||
|
||||
// There is no need to mark the line dirty
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_open(const char *name, uint32 flags, void **cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_freecookie(void * cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_close(void * cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_read(void * cookie, off_t pos, void *buffer, size_t *_length)
|
||||
{
|
||||
ssize_t bytesRead = read_pos(console.keyboard_fd, 0, buffer, *_length);
|
||||
if (bytesRead >= 0) {
|
||||
*_length = bytesRead;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
_console_write(const void *buffer, size_t *_length)
|
||||
{
|
||||
size_t length = *_length;
|
||||
size_t i;
|
||||
const char *c;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
c = &((const char *)buffer)[i];
|
||||
switch (*c) {
|
||||
case '\n':
|
||||
cr();
|
||||
lf();
|
||||
break;
|
||||
case '\r':
|
||||
cr();
|
||||
break;
|
||||
case 0x8: // backspace
|
||||
del();
|
||||
break;
|
||||
case '\t': // tab
|
||||
tab();
|
||||
break;
|
||||
case '\0':
|
||||
break;
|
||||
default:
|
||||
console_put_character(*c);
|
||||
}
|
||||
}
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_write(void * cookie, off_t pos, const void *buffer, size_t *_length)
|
||||
{
|
||||
status_t err;
|
||||
|
||||
TRACE(("console_write: text = \"%s\", len = %lu\n", (char *)buffer, *_length));
|
||||
|
||||
mutex_lock(&console.lock);
|
||||
|
||||
err = _console_write(buffer, _length);
|
||||
// update_cursor(x, y);
|
||||
repaint();
|
||||
|
||||
mutex_unlock(&console.lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
console_ioctl(void *cookie, uint32 op, void *buffer, size_t len)
|
||||
{
|
||||
int err;
|
||||
|
||||
switch (op) {
|
||||
/* case CONSOLE_OP_WRITEXY:
|
||||
{
|
||||
size_t wlen;
|
||||
int x,y;
|
||||
mutex_lock(&console.lock);
|
||||
|
||||
x = ((int *)buffer)[0];
|
||||
y = ((int *)buffer)[1];
|
||||
|
||||
save_cur();
|
||||
// gotoxy(x, y);
|
||||
wlen = len - 2 * sizeof(int);
|
||||
if (_console_write(((char *)buffer) + 2 * sizeof(int), &wlen) == B_OK)
|
||||
err = 0; // we're okay
|
||||
else
|
||||
err = EIO;
|
||||
restore_cur();
|
||||
mutex_unlock(&console.lock);
|
||||
break;
|
||||
}
|
||||
*/ default:
|
||||
err = EINVAL;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
static device_hooks sFrameBufferConsoleHooks = {
|
||||
&console_open,
|
||||
&console_close,
|
||||
&console_freecookie,
|
||||
&console_ioctl,
|
||||
&console_read,
|
||||
&console_write,
|
||||
NULL,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
||||
status_t
|
||||
fb_console_dev_init(kernel_args *args)
|
||||
{
|
||||
status_t status;
|
||||
int i;
|
||||
|
||||
if (!args->frame_buffer.enabled)
|
||||
return B_OK;
|
||||
|
||||
TRACE(("fb_console_dev_init: framebuffer found at 0x%lx, x %ld, y %ld, bit depth %ld\n",
|
||||
args->frame_buffer.physical_buffer.start, args->frame_buffer.width,
|
||||
args->frame_buffer.height, args->frame_buffer.depth));
|
||||
|
||||
memset(&console, 0, sizeof(console));
|
||||
|
||||
status = map_physical_memory("vesa_fb", (void *)args->frame_buffer.physical_buffer.start,
|
||||
args->frame_buffer.physical_buffer.size, B_ANY_KERNEL_ADDRESS,
|
||||
B_READ_AREA | B_WRITE_AREA, (void **)&console.fb);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
|
||||
console.fb_x = args->frame_buffer.width;
|
||||
console.fb_y = args->frame_buffer.height;
|
||||
console.fb_pixel_bytes = args->frame_buffer.depth / 8;
|
||||
console.fb_size = args->frame_buffer.physical_buffer.size;
|
||||
|
||||
switch (console.fb_pixel_bytes) {
|
||||
case 1:
|
||||
console.render_line = &render_line8;
|
||||
console.color = 0; // black
|
||||
console.bcolor = 63; // white
|
||||
break;
|
||||
case 2:
|
||||
console.render_line = &render_line16;
|
||||
console.color = 0xffff;
|
||||
console.bcolor = 0;
|
||||
break;
|
||||
case 4:
|
||||
console.render_line = &render_line32;
|
||||
console.color = 0x00ffffff;
|
||||
console.bcolor = 0;
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
TRACE(("framebuffer mapped at 0x%lx\n", console.fb));
|
||||
|
||||
// figure out the number of rows/columns we have
|
||||
console.rows = console.fb_y / CHAR_HEIGHT;
|
||||
console.columns = console.fb_x / CHAR_WIDTH;
|
||||
TRACE(("%d rows %d columns\n", console.rows, console.columns));
|
||||
|
||||
console.x = 0;
|
||||
console.y = 0;
|
||||
console.saved_x = 0;
|
||||
console.saved_y = 0;
|
||||
|
||||
// allocate some memory for this
|
||||
console.render_buf = malloc(console.fb_x * console.fb_pixel_bytes);
|
||||
memset((void *)console.render_buf, console.bcolor, console.fb_x * console.fb_pixel_bytes);
|
||||
console.buf = malloc(console.rows * (console.columns+1));
|
||||
memset(console.buf, 0, console.rows * (console.columns+1));
|
||||
console.lines = malloc(console.rows * sizeof(char *));
|
||||
console.dirty_lines = malloc(console.rows);
|
||||
// set up the line pointers
|
||||
for (i = 0; i < console.rows; i++) {
|
||||
console.lines[i] = (char *)((addr_t)console.buf + i*(console.columns+1));
|
||||
console.dirty_lines[i] = 1;
|
||||
}
|
||||
console.num_lines = console.rows;
|
||||
console.first_line = 0;
|
||||
|
||||
repaint();
|
||||
|
||||
mutex_init(&console.lock, "console_lock");
|
||||
console.keyboard_fd = open("/dev/keyboard", O_RDONLY);
|
||||
if (console.keyboard_fd < 0)
|
||||
panic("fb_console_dev_init: error opening /dev/keyboard\n");
|
||||
|
||||
// create device node
|
||||
if (devfs_publish_device("console", NULL, &sFrameBufferConsoleHooks) != B_OK)
|
||||
panic("fb_console: could not publish device!\n");
|
||||
|
||||
#if 0
|
||||
{
|
||||
// displays the palette in 8 bit mode
|
||||
#define BAR_WIDTH 8
|
||||
int x, y, i;
|
||||
int width = (console.fb_x - BAR_WIDTH - 1) / BAR_WIDTH;
|
||||
for (y = 0; y < console.fb_y; y++) {
|
||||
for (i = 0; i < width; i++) {
|
||||
uint8 field[BAR_WIDTH];
|
||||
for (x = 0; x < BAR_WIDTH; x++) {
|
||||
field[x] = i;
|
||||
}
|
||||
memcpy(console.fb + i*BAR_WIDTH + y*console.fb_x, field, BAR_WIDTH);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
int x, y;
|
||||
|
||||
for(y=0; y<console.fb_y; y++) {
|
||||
uint16 row[console.fb_x];
|
||||
for(x = 0; x<console.fb_x; x++) {
|
||||
row[x] = x;
|
||||
}
|
||||
dprintf("%d\n", y);
|
||||
memcpy(console.fb + y*console.fb_x*2, row, sizeof(row));
|
||||
}
|
||||
panic("foo\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i,j,k;
|
||||
|
||||
for(k=0;; k++) {
|
||||
for(i=0; i<ka->fb.y_size; i++) {
|
||||
uint16 row[ka->fb.x_size];
|
||||
for(j=0; j<ka->fb.x_size; j++) {
|
||||
uint8 byte = j+i+k;
|
||||
row[j] = byte;
|
||||
}
|
||||
memcpy(console.fb + i*ka->fb.x_size*2, row, sizeof(row));
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user