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:
Axel Dörfler 2005-03-18 02:53:52 +00:00
parent e17c805d8f
commit 1000949230
12 changed files with 0 additions and 2083 deletions

View File

@ -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 ;

View File

@ -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 ;

View File

@ -1,3 +0,0 @@
SubDir OBOS_TOP src kernel drivers arch ;
SubInclude OBOS_TOP src kernel drivers arch $(OBOS_ARCH) ;

View File

@ -1,3 +0,0 @@
SubDir OBOS_TOP src kernel drivers arch ppc ;
# nothing to do here

View File

@ -1,3 +0,0 @@
SubDir OBOS_TOP src kernel drivers arch x86 ;
SubInclude OBOS_TOP src kernel drivers arch x86 console ;

View File

@ -1,3 +0,0 @@
SubDir OBOS_TOP src kernel drivers arch x86 console ;
#KernelObjects console.c : -fnopic ;

View File

@ -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;
}

View File

@ -1,3 +0,0 @@
SubDir OBOS_TOP src kernel drivers arch x86 ide ;
KernelStaticLibrary libide : ide.c ide_raw.c ;

View File

@ -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;
}

View File

@ -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, &sect);
else
ide_btochs(block, device, &cyl, &head, &sect);
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, &sect);
else
ide_btochs(block, device, &cyl, &head, &sect);
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;
}

View File

@ -1,5 +0,0 @@
SubDir OBOS_TOP src kernel drivers fb_console ;
KernelStaticLibrary fb_console :
fb_console.c
: -fno-pic ;

View File

@ -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;
}