Author: colin Date: 2010-01-19 10:08:52 +0100 (Tue, 19 Jan 2010) New Revision: 35156 Changeset: http://dev.haiku-os.org/changeset/35156/haiku Modified: haiku/trunk/src/libs/compat/freebsd_network/compat/sys/cdefs.h haiku/trunk/src/libs/compat/freebsd_network/compat/sys/firmware.h haiku/trunk/src/libs/compat/freebsd_network/compat/sys/libkern.h haiku/trunk/src/libs/compat/freebsd_network/firmware.c Log: * Changing the naming scheme for firmwares. Instead of directly renaming the respective firmware files renaming is now done within the firmware loader. The mapping of original firmware names to FreeBSD internal firmware names is now done within driver specific settings files. Those are committed in a next step. This approach allows a clean separation of FreeBSD compat layer requirements and native driver requirements. For example: we have two Intel PRO/Wireless 2100 drivers. Do we prefer the naming scheme of the native driver or do we force the native driver to use the one of the FreeBSD driver? With this commit we prefer native over FreeBSD. * Changed the firmware loader to make use of Haiku's file mapping facility. * Implementing firmware unloading. * Some minor cleanups in two compat layer header files, which are using Haiku defined identifiers, where apropriate. Modified: haiku/trunk/src/libs/compat/freebsd_network/compat/sys/cdefs.h =================================================================== --- haiku/trunk/src/libs/compat/freebsd_network/compat/sys/cdefs.h 2010-01-19 08:34:14 UTC (rev 35155) +++ haiku/trunk/src/libs/compat/freebsd_network/compat/sys/cdefs.h 2010-01-19 09:08:52 UTC (rev 35156) @@ -35,6 +35,10 @@ #ifndef _FBSD_COMPAT_SYS_CDEFS_H_ #define _FBSD_COMPAT_SYS_CDEFS_H_ + +#include <posix/sys/cdefs.h> + + #define __FBSDID(str) static const char __fbsdid[] = str /* @@ -174,7 +178,6 @@ * a feature that we cannot live without. */ #ifdef lint -#define __dead2 #define __pure2 #define __unused #define __packed @@ -182,18 +185,15 @@ #define __section(x) #else #if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER) -#define __dead2 #define __pure2 #define __unused #endif #if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER) -#define __dead2 __attribute__((__noreturn__)) #define __pure2 __attribute__((__const__)) #define __unused /* XXX Find out what to do for __packed, __aligned and __section */ #endif #if __GNUC_PREREQ__(2, 7) -#define __dead2 __attribute__((__noreturn__)) #define __pure2 __attribute__((__const__)) #define __unused __attribute__((__unused__)) #define __packed __attribute__((__packed__)) @@ -210,7 +210,6 @@ #endif #if defined(__INTEL_COMPILER) -#define __dead2 __attribute__((__noreturn__)) #define __pure2 __attribute__((__const__)) #define __unused __attribute__((__unused__)) #define __used __attribute__((__used__)) @@ -263,10 +262,6 @@ * first. It is only available with ANSI C. */ #if defined(__STDC__) || defined(__cplusplus) -#define __P(protos) protos /* full-blown ANSI C */ -#define __CONCAT1(x,y) x ## y -#define __CONCAT(x,y) __CONCAT1(x,y) -#define __STRING(x) #x /* stringify without expanding x */ #define __XSTRING(x) __STRING(x) /* expand x, then stringify */ #define __const const /* define reserved names to standard */ @@ -281,9 +276,6 @@ #endif /* !__cplusplus */ #else /* !(__STDC__ || __cplusplus) */ -#define __P(protos) () /* traditional C preprocessor */ -#define __CONCAT(x,y) x/**/y -#define __STRING(x) "x" #if !defined(__CC_SUPPORTS___INLINE) #define __const /* delete pseudo-ANSI C keywords */ Modified: haiku/trunk/src/libs/compat/freebsd_network/compat/sys/firmware.h =================================================================== --- haiku/trunk/src/libs/compat/freebsd_network/compat/sys/firmware.h 2010-01-19 08:34:14 UTC (rev 35155) +++ haiku/trunk/src/libs/compat/freebsd_network/compat/sys/firmware.h 2010-01-19 09:08:52 UTC (rev 35156) @@ -6,16 +6,18 @@ #define _FBSD_COMPAT_SYS_FIRMWARE_H_ +#define FIRMWARE_UNLOAD 0x0001 + + struct firmware { - const char* name; /* system-wide name */ - const void* data; /* location of image */ - size_t datasize; /* size of image in bytes */ - unsigned int version; /* version of the image */ + const char* name; // system-wide name + const void* data; // location of image + size_t datasize; // size of image in bytes + unsigned int version; // version of the image }; -const struct firmware* firmware_get(const char*); -#define FIRMWARE_UNLOAD 0x0001 /* unload if unreferenced */ +const struct firmware* firmware_get(const char*); void firmware_put(const struct firmware*, int); #endif /* _FBSD_COMPAT_SYS_FIRMWARE_H_ */ Modified: haiku/trunk/src/libs/compat/freebsd_network/compat/sys/libkern.h =================================================================== --- haiku/trunk/src/libs/compat/freebsd_network/compat/sys/libkern.h 2010-01-19 08:34:14 UTC (rev 35155) +++ haiku/trunk/src/libs/compat/freebsd_network/compat/sys/libkern.h 2010-01-19 09:08:52 UTC (rev 35156) @@ -16,6 +16,6 @@ static __inline int imax(int a, int b) { return (a > b ? a : b); } -static __inline int abs(int a) { return (a < 0 ? -a : a); } +extern int abs(int a); #endif /* _FBSD_COMPAT_SYS_LIBKERN_H_ */ Modified: haiku/trunk/src/libs/compat/freebsd_network/firmware.c =================================================================== --- haiku/trunk/src/libs/compat/freebsd_network/firmware.c 2010-01-19 08:34:14 UTC (rev 35155) +++ haiku/trunk/src/libs/compat/freebsd_network/firmware.c 2010-01-19 09:08:52 UTC (rev 35156) @@ -1,10 +1,12 @@ /* - * Copyright 2009, Colin Günther, coling@xxxxxxx + * Copyright 2009-2010, Colin Günther, coling@xxxxxxx * All Rights Reserved. Distributed under the terms of the MIT License. * */ +#include <posix/sys/mman.h> + #include <compat/sys/param.h> #include <compat/sys/firmware.h> #include <compat/sys/haiku-module.h> @@ -16,78 +18,115 @@ #include <StorageDefs.h> #include <SupportDefs.h> +#include <driver_settings.h> +#include <kernel/vm/vm.h> +#include <syscalls.h> +#include <vm_defs.h> +#include <device.h> + + + +#define MAX_FBSD_FIRMWARE_NAME_CHARS 64 + // For strndup, beeing cautious in kernel code is a good thing. + // NB: This constant doesn't exist in FreeBSD. + + const struct firmware* -firmware_get(const char* imageName) +firmware_get(const char* fbsdFirmwareName) { - int fileDescriptor; + area_id area; + void* driverSettings = NULL; + char* fbsdFirmwareNameCopy = NULL; + int fileDescriptor = 0; struct firmware* firmware = NULL; int32 firmwareFileSize; - char* firmwareName; - char* firmwarePath; - ssize_t readCount; + char* firmwarePath = NULL; + const char* haikuFirmwareName = NULL; + driverSettings = load_driver_settings(gDriverName); + if (driverSettings == NULL) { + driver_printf("%s: settings file %s is missing.\n", __func__, + gDriverName); + return NULL; + } + + haikuFirmwareName = get_driver_parameter(driverSettings, fbsdFirmwareName, + NULL, NULL); + if (haikuFirmwareName == NULL) { + driver_printf("%s: settings file %s file contains no mapping for %s.\n", + __func__, gDriverName, fbsdFirmwareName); + goto cleanup; + } + firmwarePath = (char*)malloc(B_PATH_NAME_LENGTH); if (firmwarePath == NULL) - goto cleanup0; + goto cleanup; if (find_directory(B_SYSTEM_DATA_DIRECTORY, -1, false, firmwarePath, B_PATH_NAME_LENGTH) != B_OK) - goto cleanup1; + goto cleanup; strlcat(firmwarePath, "/firmware/", B_PATH_NAME_LENGTH); strlcat(firmwarePath, gDriverName, B_PATH_NAME_LENGTH); strlcat(firmwarePath, "/", B_PATH_NAME_LENGTH); - strlcat(firmwarePath, imageName, B_PATH_NAME_LENGTH); + strlcat(firmwarePath, haikuFirmwareName, B_PATH_NAME_LENGTH); fileDescriptor = open(firmwarePath, B_READ_ONLY); if (fileDescriptor == -1) - goto cleanup1; + goto cleanup; firmwareFileSize = lseek(fileDescriptor, 0, SEEK_END); lseek(fileDescriptor, 0, SEEK_SET); - firmwareName = (char*)malloc(strlen(imageName) + 1); - if (firmwareName == NULL) - goto cleanup2; + fbsdFirmwareNameCopy = strndup(fbsdFirmwareName, + MAX_FBSD_FIRMWARE_NAME_CHARS); + if (fbsdFirmwareNameCopy == NULL) + goto cleanup; - strncpy(firmwareName, imageName, strlen(imageName) + 1); - firmware = (struct firmware*)malloc(sizeof(struct firmware)); if (firmware == NULL) - goto cleanup3; + goto cleanup; - firmware->data = malloc(firmwareFileSize); - if (firmware->data == NULL) - goto cleanup4; + firmware->data = NULL; + area = _user_map_file("mmap area", (void*)&firmware->data, B_ANY_ADDRESS, + firmwareFileSize, B_READ_AREA, REGION_PRIVATE_MAP, true, fileDescriptor, + 0); + if (area < 0) + goto cleanup; - readCount = read(fileDescriptor, (void*)firmware->data, firmwareFileSize); - if (readCount == -1) - goto cleanup5; - firmware->datasize = firmwareFileSize; - firmware->name = firmwareName; + firmware->name = fbsdFirmwareNameCopy; firmware->version = __haiku_firmware_version; - goto cleanup2; -cleanup5: - free(&firmware->data); -cleanup4: - free(firmware); - firmware = NULL; -cleanup3: - free(firmwareName); -cleanup2: close(fileDescriptor); -cleanup1: free(firmwarePath); -cleanup0: + unload_driver_settings(driverSettings); return firmware; + +cleanup: + if (firmware) + free(firmware); + if (fbsdFirmwareNameCopy) + free(fbsdFirmwareNameCopy); + if (firmwarePath) + free(firmwarePath); + if (fileDescriptor) + close(fileDescriptor); + if (driverSettings) + unload_driver_settings(driverSettings); + return NULL; } void -firmware_put(const struct firmware* pointer, int flags) +firmware_put(const struct firmware* firmware, int flags) { + if (firmware == NULL) + return; + _user_unmap_memory((void*)firmware->data, firmware->datasize); + if (firmware->name) + free((void*)firmware->name); + free((void*)firmware); }