ARM: Initial work on a NOR flash driver

Currently hardcoded to Verdex target. Code prepared to pick up configuration
details from FDT when implemented. Only enabled in FloppyImage for ARM.

This actually enables the kernel to read the content of the image file
passed using the "-pflash" parameter to QEMU....
This commit is contained in:
Ithamar R. Adema 2012-11-13 00:42:45 +01:00
parent b20073726a
commit 5f78788af9
4 changed files with 313 additions and 1 deletions

View File

@ -3,12 +3,15 @@
local X86_ONLY = ;
local PPC_ONLY = ;
local ARM_ONLY = ;
if $(TARGET_ARCH) = x86 {
X86_ONLY = "" ;
} else if $(TARGET_ARCH) = ppc {
X86_ONLY = ;
} else if $(TARGET_ARCH) = m68k {
X86_ONLY = ;
} else if $(TARGET_ARCH) = arm {
ARM_ONLY = "" ;
}
local GPL_ONLY = ;
@ -80,6 +83,7 @@ if $(TARGET_ARCH) = x86 {
# drivers
AddNewDriversToFloppyBootArchive disk scsi : scsi_cd scsi_disk ;
AddNewDriversToFloppyBootArchive disk : $(ARM_ONLY)norflash ;
if $(USB_BOOT) = 1 {
AddDriversToFloppyBootArchive disk usb : usb_disk ;
}
@ -122,7 +126,7 @@ AddBootModuleSymlinksToFloppyBootArchive
ahci generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata
it8211
$(USB_ONLY)<usb>uhci $(USB_ONLY)<usb>ohci $(USB_ONLY)<usb>ehci
scsi_cd scsi_disk $(USB_ONLY)usb_disk
scsi_cd scsi_disk $(USB_ONLY)usb_disk $(ARM_ONLY)norflash
intel session
$(SYSTEM_ADD_ONS_FILE_SYSTEMS)
$(BOOT_ADD_ONS_NET)

View File

@ -1,6 +1,7 @@
SubDir HAIKU_TOP src add-ons kernel drivers disk ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk floppy ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk norflash ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk scsi ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk usb ;
SubInclude HAIKU_TOP src add-ons kernel drivers disk virtual ;

View File

@ -0,0 +1,10 @@
SubDir HAIKU_TOP src add-ons kernel drivers disk norflash ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders drivers kernel ;
KernelAddon norflash :
norflash.cpp
;

View File

@ -0,0 +1,297 @@
/*
* Copyright 2012, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Ithamar R. Adema <ithamar@upgrade-android.com>
*/
#include <drivers/device_manager.h>
#include <drivers/KernelExport.h>
#include <drivers/Drivers.h>
#include <kernel/OS.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
//#define TRACE_NORFLASH
#ifdef TRACE_NORFLASH
#define TRACE(x...) dprintf("nor: " x)
#else
#define TRACE(x...)
#endif
#define NORFLASH_DEVICE_MODULE_NAME "drivers/disk/norflash/device_v1"
#define NORFLASH_DRIVER_MODULE_NAME "drivers/disk/norflash/driver_v1"
#define NORFLASH_ADDR 0x00000000
struct nor_driver_info {
device_node *node;
size_t blocksize;
size_t totalsize;
area_id id;
void *mapped;
};
static device_manager_info* sDeviceManager;
static const char *sTabTab = "\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t";
#define DS "%.*s"
#define DA depth - 1, sTabTab
static void
dump_hex(const char *data, int32 len, int depth = 1)
{
char str[128];
char astr[32];
char *p;
int l;
int i;
for (i = 0; i < len; ) {
p = str;
l = sizeof(str);
for (; i < len && (p == str || (i % 16 != 0)); i++) {
snprintf(p, l - 1, "%02x ", data[i]);
l -= strlen(p);
p += strlen(p);
astr[i % 16] = isprint(data[i]) ? data[i] : '.';
astr[i % 16] = isprint(data[i]) ? data[i] : '.';
astr[(i % 16) + 1] = '\0';
}
dprintf(DS" %-48.48s %s\n", DA, str, astr);
}
}
static status_t
nor_init_device(void* _info, void** _cookie)
{
TRACE("init_device\n");
nor_driver_info* info = (nor_driver_info*)_info;
info->mapped = NULL;
info->blocksize = 128 * 1024;
info->totalsize = info->blocksize * 256;
info->id = map_physical_memory("NORFlash", NORFLASH_ADDR, info->totalsize, B_ANY_KERNEL_ADDRESS, B_READ_AREA, &info->mapped);
if (info->id < 0)
return info->id;
*_cookie = info;
return B_OK;
}
static void
nor_uninit_device(void* _cookie)
{
TRACE("uninit_device\n");
nor_driver_info* info = (nor_driver_info*)_cookie;
if (info)
delete_area(info->id);
}
static status_t
nor_open(void *deviceCookie, const char *path, int openMode,
void **_cookie)
{
TRACE("open(%s)\n", path);
*_cookie = deviceCookie;
return B_OK;
}
static status_t
nor_close(void *_cookie)
{
TRACE("close()\n");
return B_OK;
}
static status_t
nor_free(void *_cookie)
{
TRACE("free()\n");
return B_OK;
}
static status_t
nor_ioctl(void *cookie, uint32 op, void *buffer, size_t length)
{
nor_driver_info* info = (nor_driver_info*)cookie;
TRACE("ioctl(%ld,%lu)\n", op, length);
switch(op) {
case B_GET_GEOMETRY:
{
device_geometry *deviceGeometry = (device_geometry*)buffer;
deviceGeometry->removable = false;
deviceGeometry->bytes_per_sector = info->blocksize;
deviceGeometry->sectors_per_track = info->totalsize / info->blocksize;
deviceGeometry->cylinder_count = 1;
deviceGeometry->head_count = 1;
deviceGeometry->device_type = B_DISK;
deviceGeometry->removable = false;
deviceGeometry->read_only = true;
deviceGeometry->write_once = false;
return B_OK;
}
break;
case B_GET_DEVICE_NAME:
strlcpy((char*)buffer, "NORFlash", length);
break;
}
return B_ERROR;
}
static status_t
nor_read(void *_cookie, off_t position, void *data, size_t *numbytes)
{
nor_driver_info* info = (nor_driver_info*)_cookie;
TRACE("read(%Ld,%lu)\n", position, *numbytes);
if (position + *numbytes > info->totalsize)
*numbytes = info->totalsize - (position + *numbytes);
memcpy(data, info->mapped + position, *numbytes);
#ifdef TRACE_NORFLASH
dump_hex((const char*)(info->mapped + position), *numbytes, 1);
#endif
return B_OK;
}
static status_t
nor_write(void *_cookie, off_t position, const void *data, size_t *numbytes)
{
TRACE("write(%Ld,%lu)\n", position, *numbytes);
*numbytes = 0;
return B_ERROR;
}
static float
nor_supports_device(device_node *parent)
{
TRACE("supports_device\n");
return 0.6;
}
static status_t
nor_register_device(device_node *node)
{
TRACE("register_device\n");
// ready to register
device_attr attrs[] = {
{ NULL }
};
return sDeviceManager->register_node(node, NORFLASH_DRIVER_MODULE_NAME,
attrs, NULL, NULL);
}
static status_t
nor_init_driver(device_node *node, void **cookie)
{
TRACE("init_driver\n");
nor_driver_info* info = (nor_driver_info*)malloc(sizeof(nor_driver_info));
if (info == NULL)
return B_NO_MEMORY;
memset(info, 0, sizeof(*info));
info->node = node;
*cookie = info;
return B_OK;
}
static void
nor_uninit_driver(void *_cookie)
{
TRACE("uninit_driver\n");
nor_driver_info* info = (nor_driver_info*)_cookie;
free(info);
}
static status_t
nor_register_child_devices(void* _cookie)
{
TRACE("register_child_devices\n");
nor_driver_info* info = (nor_driver_info*)_cookie;
status_t status;
status = sDeviceManager->publish_device(info->node, "disk/nor/0/raw",
NORFLASH_DEVICE_MODULE_NAME);
return status;
}
struct device_module_info sNORFlashDiskDevice = {
{
NORFLASH_DEVICE_MODULE_NAME,
0,
NULL
},
nor_init_device,
nor_uninit_device,
NULL, //nor_remove,
nor_open,
nor_close,
nor_free,
nor_read,
nor_write,
NULL, // nor_io,
nor_ioctl,
NULL, // select
NULL, // deselect
};
struct driver_module_info sNORFlashDiskDriver = {
{
NORFLASH_DRIVER_MODULE_NAME,
0,
NULL
},
nor_supports_device,
nor_register_device,
nor_init_driver,
nor_uninit_driver,
nor_register_child_devices,
NULL, // rescan
NULL, // removed
};
module_dependency module_dependencies[] = {
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info**)&sDeviceManager },
{ }
};
module_info* modules[] = {
(module_info*)&sNORFlashDiskDriver,
(module_info*)&sNORFlashDiskDevice,
NULL
};