* Integration of the new driver architecture.
* Moved devfs from fs/ to device_manager/, and separated the legacy driver
support from it.
* Removed fast_log module.
* There are a couple of (temporary) regressions, though:
- legacy SATA and ISA IDE support is disabled, the drivers haven't been
ported yet.
- The not yet used ATA bus manager hasn't been ported yet, either.
- AHCI changes have not been tested.
- the listdev command has been removed from the build (as it currently
doesn't work anymore).
- device manager generated IDs currently are not freed anymore when a device
node is removed.
- generic drivers can't yet use the new driver architecture.
- simple busses that do not support device types won't work yet.
- legacy driver publishing/unpublishing (ie. what USB needs) has not been
tested, and may be broken.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25662 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -33,7 +33,7 @@ BEOS_BIN = "[" addattr alert arp base64 basename bc beep bootman bzip2 cal cat
|
||||
funzip #fwcontrol
|
||||
gawk $(X86_ONLY)gdb grep groups gzip gzexe hd head hey hostname id ident
|
||||
ideinfo idestatus ifconfig <bin>install installsound iroster isvolume join
|
||||
keymap kill less lessecho lesskey link listarea listattr listdev listimage
|
||||
keymap kill less lessecho lesskey link listarea listattr listimage #listdev
|
||||
listport listres listsem ln locate logger login logname ls lsindex m4 make
|
||||
makebootable md5sum merge mimeset mkdos mkdir mkfifo mkfs mkindex modifiers mount
|
||||
mount_nfs mountvolume mv nc netstat nl nohup od open passwd paste patch
|
||||
@@ -145,7 +145,7 @@ AddFilesToHaikuImage beos system add-ons kernel bus_managers
|
||||
AddFilesToHaikuImage beos system add-ons kernel busses agp_gart
|
||||
: $(X86_ONLY)<agp_gart>intel ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel busses ide
|
||||
: generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata ;
|
||||
: generic_ide_pci ; #$(X86_ONLY)ide_isa silicon_image_3112 legacy_sata ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel busses scsi
|
||||
: ahci ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel busses usb
|
||||
@@ -156,7 +156,7 @@ AddFilesToHaikuImage beos system add-ons kernel debugger
|
||||
AddFilesToHaikuImage beos system add-ons kernel file_systems
|
||||
: $(BEOS_ADD_ONS_FILE_SYSTEMS) ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel generic
|
||||
: block_io dpc fast_log ide_adapter locked_pool mpu401 scsi_periph ;
|
||||
: block_io dpc ide_adapter locked_pool mpu401 scsi_periph ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel partitioning_systems
|
||||
: intel session ;
|
||||
AddFilesToHaikuImage beos system add-ons kernel interrupt_controllers
|
||||
@@ -172,7 +172,7 @@ AddDriversToHaikuImage : console dprintf $(X86_ONLY)keyboard null
|
||||
AddDriversToHaikuImage audio hmulti : $(BEOS_ADD_ONS_DRIVERS_AUDIO) ;
|
||||
AddDriversToHaikuImage midi : $(BEOS_ADD_ONS_DRIVERS_MIDI) ;
|
||||
AddDriversToHaikuImage bus : usb_raw ; # fw_raw
|
||||
AddDriversToHaikuImage disk scsi : scsi_cd scsi_dsk ;
|
||||
AddDriversToHaikuImage disk scsi : scsi_dsk ; #scsi_cd;
|
||||
AddDriversToHaikuImage disk usb : usb_disk ;
|
||||
AddDriversToHaikuImage disk virtual : nbd ;
|
||||
AddDriversToHaikuImage dvb : cx23882 ;
|
||||
@@ -358,9 +358,9 @@ AddFilesToHaikuImage beos system : zbeos ;
|
||||
AddBootModuleSymlinksToHaikuImage
|
||||
pci $(X86_ONLY)isa config_manager ide scsi
|
||||
$(PPC_ONLY)openpic
|
||||
block_io fast_log ide_adapter locked_pool scsi_periph
|
||||
ahci generic_ide_pci $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata
|
||||
scsi_cd scsi_dsk
|
||||
block_io ide_adapter locked_pool scsi_periph
|
||||
generic_ide_pci ahci # $(X86_ONLY)ide_isa silicon_image_3112 legacy_sata
|
||||
scsi_dsk #scsi_cd
|
||||
intel
|
||||
bfs
|
||||
;
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
#ifndef __BLOCK_IO_H__
|
||||
#define __BLOCK_IO_H__
|
||||
|
||||
/*
|
||||
Part of Open block device manager
|
||||
|
||||
/*!
|
||||
Block devices can be easily written by providing the interface
|
||||
specified hereinafter. The block device manager takes care of
|
||||
DMA and other restrictions imposed by underlying controller or
|
||||
@@ -24,7 +22,6 @@ typedef struct block_io_device_info *block_io_device;
|
||||
typedef struct block_io_handle_info *block_io_handle;
|
||||
|
||||
// cookies issued by device driver
|
||||
typedef struct block_device_device_cookie *block_device_device_cookie;
|
||||
typedef struct block_device_handle_cookie *block_device_handle_cookie;
|
||||
|
||||
|
||||
@@ -59,15 +56,20 @@ typedef struct phys_vecs {
|
||||
// maximum number of scatter/gather blocks (uint32, optional, default: unlimited)
|
||||
#define B_BLOCK_DEVICE_MAX_SG_BLOCKS "block_device/max_sg_blocks"
|
||||
|
||||
typedef struct block_device_cookie {
|
||||
struct device_node *node;
|
||||
} block_device_cookie;
|
||||
|
||||
// interface to be provided by device driver
|
||||
typedef struct block_device_interface {
|
||||
driver_module_info info;
|
||||
|
||||
void (*set_device)(block_device_cookie *cookie, block_io_device device);
|
||||
|
||||
// iovecs are physical address here
|
||||
// pos and num_blocks are in blocks; bytes_transferred in bytes
|
||||
// vecs are guaranteed to describe enough data for given block count
|
||||
status_t (*open)(block_device_device_cookie device, block_device_handle_cookie *handle);
|
||||
status_t (*open)(block_device_cookie *cookie, block_device_handle_cookie *handle);
|
||||
status_t (*close)(block_device_handle_cookie handle);
|
||||
status_t (*free)(block_device_handle_cookie handle);
|
||||
|
||||
@@ -79,12 +81,12 @@ typedef struct block_device_interface {
|
||||
status_t (*ioctl)(block_device_handle_cookie handle, int op, void *buf, size_t len);
|
||||
} block_device_interface;
|
||||
|
||||
#define B_BLOCK_IO_MODULE_NAME "generic/block_io/v1"
|
||||
#define B_BLOCK_IO_DEVICE_MODULE_NAME "generic/block_io/device_v1"
|
||||
|
||||
|
||||
// Interface for Drivers
|
||||
|
||||
// blkman interface used for callbacks done by driver
|
||||
// interface used for callbacks done by driver
|
||||
typedef struct block_io_for_driver_interface {
|
||||
module_info info;
|
||||
|
||||
|
||||
@@ -1,18 +1,11 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open IDE bus manager
|
||||
|
||||
IDE bus manager interface
|
||||
*/
|
||||
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef __IDE_H__
|
||||
#define __IDE_H__
|
||||
|
||||
#include <bus_manager.h>
|
||||
|
||||
#include <device_manager.h>
|
||||
#include <KernelExport.h>
|
||||
|
||||
@@ -37,10 +30,15 @@
|
||||
union ide_task_file;
|
||||
typedef unsigned int ide_reg_mask;
|
||||
|
||||
// channel cookie, issued by ide bus manager
|
||||
typedef struct ide_bus_info *ide_channel;
|
||||
|
||||
// interface of controller driver
|
||||
typedef struct {
|
||||
driver_module_info info;
|
||||
|
||||
void (*set_channel)(void *cookie, ide_channel channel);
|
||||
|
||||
status_t (*write_command_block_regs)
|
||||
(void *channel_cookie, union ide_task_file *tf, ide_reg_mask mask);
|
||||
status_t (*read_command_block_regs)
|
||||
@@ -60,10 +58,6 @@ typedef struct {
|
||||
} ide_controller_interface;
|
||||
|
||||
|
||||
// channel cookie, issued by ide bus manager
|
||||
typedef struct ide_bus_info *ide_channel;
|
||||
|
||||
|
||||
// Interface for Controller Driver
|
||||
|
||||
// interface of bus manager as seen from controller driver
|
||||
@@ -77,7 +71,7 @@ typedef struct {
|
||||
} ide_for_controller_interface;
|
||||
|
||||
|
||||
#define IDE_FOR_CONTROLLER_MODULE_NAME "bus_managers/ide/controller/v1"
|
||||
#define IDE_FOR_CONTROLLER_MODULE_NAME "bus_managers/ide/controller/driver_v1"
|
||||
|
||||
|
||||
#endif /* __IDE_H__ */
|
||||
|
||||
@@ -35,17 +35,17 @@
|
||||
#define B_MAX_ISA_DMA_COUNT 0x10000
|
||||
|
||||
typedef struct isa2_module_info {
|
||||
bus_module_info info;
|
||||
driver_module_info info;
|
||||
|
||||
uint8 (*read_io_8)( int mapped_io_addr );
|
||||
void (*write_io_8)( int mapped_io_addr, uint8 value );
|
||||
uint16 (*read_io_16)( int mapped_io_addr );
|
||||
void (*write_io_16)( int mapped_io_addr, uint16 value );
|
||||
uint32 (*read_io_32)( int mapped_io_addr );
|
||||
void (*write_io_32)( int mapped_io_addr, uint32 value );
|
||||
uint8 (*read_io_8)(int mapped_io_addr);
|
||||
void (*write_io_8)(int mapped_io_addr, uint8 value);
|
||||
uint16 (*read_io_16)(int mapped_io_addr);
|
||||
void (*write_io_16)(int mapped_io_addr, uint16 value);
|
||||
uint32 (*read_io_32)(int mapped_io_addr);
|
||||
void (*write_io_32)(int mapped_io_addr, uint32 value);
|
||||
|
||||
// don't know what it's for, remains for compatibility
|
||||
void *(*ram_address)( const void *physical_address_in_system_memory );
|
||||
void *(*ram_address)(const void *physical_address_in_system_memory);
|
||||
|
||||
// start dma transfer (scattered DMA is not supported as it's EISA specific)
|
||||
status_t (*start_isa_dma)(
|
||||
@@ -64,4 +64,4 @@ typedef struct isa2_module_info {
|
||||
#define ISA_DRIVERS_DIR "isa"
|
||||
|
||||
|
||||
#endif
|
||||
#endif /* _ISA2_H */
|
||||
|
||||
+26
-144
@@ -1,164 +1,46 @@
|
||||
/*
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
* Copyright 2008, Haiku Inc. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
PCI bus manager
|
||||
*/
|
||||
|
||||
#ifndef _PCI2_H
|
||||
#define _PCI2_H
|
||||
|
||||
|
||||
#include <device_manager.h>
|
||||
#include <PCI.h>
|
||||
|
||||
// currently, this structure is disabled to avoid collision with R5 header
|
||||
#if 0
|
||||
|
||||
typedef struct pci_info {
|
||||
ushort vendor_id; /* vendor id */
|
||||
ushort device_id; /* device id */
|
||||
uchar bus; /* bus number */
|
||||
uchar device; /* device number on bus */
|
||||
uchar function; /* function number in device */
|
||||
uchar revision; /* revision id */
|
||||
uchar class_api; /* specific register interface type */
|
||||
uchar class_sub; /* specific device function */
|
||||
uchar class_base; /* device type (display vs network, etc) */
|
||||
uchar line_size; /* cache line size in 32 bit words */
|
||||
uchar latency; /* latency timer */
|
||||
uchar header_type; /* header type */
|
||||
uchar bist; /* built-in self-test */
|
||||
uchar reserved; /* filler, for alignment */
|
||||
union {
|
||||
struct {
|
||||
ulong cardbus_cis; /* CardBus CIS pointer */
|
||||
ushort subsystem_id; /* subsystem (add-in card) id */
|
||||
ushort subsystem_vendor_id; /* subsystem (add-in card) vendor id */
|
||||
ulong rom_base; /* rom base address, viewed from host */
|
||||
ulong rom_base_pci; /* rom base addr, viewed from pci */
|
||||
ulong rom_size; /* rom size */
|
||||
ulong base_registers[6]; /* base registers, viewed from host */
|
||||
ulong base_registers_pci[6]; /* base registers, viewed from pci */
|
||||
ulong base_register_sizes[6]; /* size of what base regs point to */
|
||||
uchar base_register_flags[6]; /* flags from base address fields */
|
||||
uchar interrupt_line; /* interrupt line */
|
||||
uchar interrupt_pin; /* interrupt pin */
|
||||
uchar min_grant; /* burst period @ 33 Mhz */
|
||||
uchar max_latency; /* how often PCI access needed */
|
||||
} h0;
|
||||
struct {
|
||||
ulong base_registers[2]; /* base registers, viewed from host */
|
||||
ulong base_registers_pci[2]; /* base registers, viewed from pci */
|
||||
ulong base_register_sizes[2]; /* size of what base regs point to */
|
||||
uchar base_register_flags[2]; /* flags from base address fields */
|
||||
uchar primary_bus;
|
||||
uchar secondary_bus;
|
||||
uchar subordinate_bus;
|
||||
uchar secondary_latency;
|
||||
uchar io_base;
|
||||
uchar io_limit;
|
||||
ushort secondary_status;
|
||||
ushort memory_base;
|
||||
ushort memory_limit;
|
||||
ushort prefetchable_memory_base;
|
||||
ushort prefetchable_memory_limit;
|
||||
ulong prefetchable_memory_base_upper32;
|
||||
ulong prefetchable_memory_limit_upper32;
|
||||
ushort io_base_upper16;
|
||||
ushort io_limit_upper16;
|
||||
ulong rom_base; /* rom base address, viewed from host */
|
||||
ulong rom_base_pci; /* rom base addr, viewed from pci */
|
||||
uchar interrupt_line; /* interrupt line */
|
||||
uchar interrupt_pin; /* interrupt pin */
|
||||
ushort bridge_control;
|
||||
} h1;
|
||||
} u;
|
||||
} pci_info;
|
||||
typedef struct pci_device pci_device;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct pci_device_info *pci_device;
|
||||
|
||||
// Interface to one PCI device.
|
||||
// Actually, this is a _function_ of a device only, but
|
||||
// pci_function_module_info would be a bit non-intuitive
|
||||
typedef struct pci_device_module_info {
|
||||
driver_module_info info;
|
||||
|
||||
uint8 (*read_io_8)(pci_device device, int mapped_io_addr);
|
||||
void (*write_io_8)(pci_device device, int mapped_io_addr, uint8 value);
|
||||
uint16 (*read_io_16)(pci_device device, int mapped_io_addr);
|
||||
void (*write_io_16)(pci_device device, int mapped_io_addr, uint16 value);
|
||||
uint32 (*read_io_32)(pci_device device, int mapped_io_addr);
|
||||
void (*write_io_32)(pci_device device, int mapped_io_addr, uint32 value);
|
||||
uint8 (*read_io_8)(pci_device *device, addr_t mappedIOAddress);
|
||||
void (*write_io_8)(pci_device *device, addr_t mappedIOAddress,
|
||||
uint8 value);
|
||||
uint16 (*read_io_16)(pci_device *device, addr_t mappedIOAddress);
|
||||
void (*write_io_16)(pci_device *device, addr_t mappedIOAddress,
|
||||
uint16 value);
|
||||
uint32 (*read_io_32)(pci_device *device, addr_t mappedIOAddress);
|
||||
void (*write_io_32)(pci_device *device, addr_t mappedIOAddress,
|
||||
uint32 value);
|
||||
|
||||
uint32 (*read_pci_config)(pci_device device,
|
||||
uchar offset, /* offset in configuration space */
|
||||
uchar size); /* # bytes to read (1, 2 or 4) */
|
||||
void (*write_pci_config)(pci_device device,
|
||||
uchar offset, /* offset in configuration space */
|
||||
uchar size, /* # bytes to write (1, 2 or 4) */
|
||||
uint32 value); /* value to write */
|
||||
void *(*ram_address)(pci_device *device, const void *physicalAddress);
|
||||
|
||||
void *(*ram_address)(pci_device device, const void *physical_address_in_system_memory);
|
||||
|
||||
/* status_t (*allocate_iomem)( void *base, size_t len, const char *name );
|
||||
status_t (*release_iomem)( void *base, size_t len );
|
||||
|
||||
status_t (*allocate_ioports)( uint16 ioport_base, size_t len, const char *name );
|
||||
status_t (*release_ioports)( uint16 ioport_base, size_t len );*/
|
||||
|
||||
status_t (*get_pci_info)(pci_device device, struct pci_info *info);
|
||||
|
||||
status_t (*find_pci_capability)(pci_device device,
|
||||
uchar cap_id,
|
||||
uchar *offset);
|
||||
uint32 (*read_pci_config)(pci_device *device, uint8 offset,
|
||||
uint8 size);
|
||||
void (*write_pci_config)(pci_device *device, uint8 offset,
|
||||
uint8 size, uint32 value);
|
||||
status_t (*find_pci_capability)(pci_device *device, uint8 capID,
|
||||
uint8 *offset);
|
||||
void (*get_pci_info)(pci_device *device, struct pci_info *info);
|
||||
} pci_device_module_info;
|
||||
|
||||
|
||||
// directory of PCI drivers
|
||||
#define PCI_DRIVERS_DIR "pci"
|
||||
/* Attributes of PCI device nodes */
|
||||
#define B_PCI_DEVICE_DOMAIN "pci/domain" /* uint32 */
|
||||
#define B_PCI_DEVICE_BUS "pci/bus" /* uint8 */
|
||||
#define B_PCI_DEVICE_DEVICE "pci/device" /* uint8 */
|
||||
#define B_PCI_DEVICE_FUNCTION "pci/function" /* uint8 */
|
||||
|
||||
// attributes of PCI device nodes
|
||||
// bus idx (uint8)
|
||||
#define PCI_DEVICE_BUS_ITEM "pci/bus"
|
||||
// device idx (uint8)
|
||||
#define PCI_DEVICE_DEVICE_ITEM "pci/device"
|
||||
// function idx (uint8)
|
||||
#define PCI_DEVICE_FUNCTION_ITEM "pci/function"
|
||||
|
||||
// vendor id (uint16)
|
||||
#define PCI_DEVICE_VENDOR_ID_ITEM "pci/vendor_id"
|
||||
// device id (uint16)
|
||||
#define PCI_DEVICE_DEVICE_ID_ITEM "pci/device_id"
|
||||
// subsystem id (uint16)
|
||||
#define PCI_DEVICE_SUBSYSTEM_ID_ITEM "pci/subsystem_id"
|
||||
// subvendor id (uint16)
|
||||
#define PCI_DEVICE_SUBVENDOR_ID_ITEM "pci/subvendor_id"
|
||||
|
||||
// device base class (uint8)
|
||||
#define PCI_DEVICE_BASE_CLASS_ID_ITEM "pci/class/base_id"
|
||||
// device subclass (uint8)
|
||||
#define PCI_DEVICE_SUB_CLASS_ID_ITEM "pci/class/sub_id"
|
||||
// device api (uint8)
|
||||
#define PCI_DEVICE_API_ID_ITEM "pci/class/api_id"
|
||||
|
||||
|
||||
// dynamic consumer patterns for PCI devices
|
||||
#define PCI_DEVICE_DYNAMIC_CONSUMER_0 \
|
||||
PCI_DRIVERS_DIR "/" \
|
||||
"vendor %" PCI_DEVICE_VENDOR_ID_ITEM "%|" \
|
||||
", device %" PCI_DEVICE_DEVICE_ID_ITEM "%|" \
|
||||
", subsystem %" PCI_DEVICE_SUBSYSTEM_ID_ITEM "%|" \
|
||||
", subvendor %" PCI_DEVICE_SUBVENDOR_ID_ITEM "%"
|
||||
|
||||
#define PCI_DEVICE_DYNAMIC_CONSUMER_1 \
|
||||
PCI_DRIVERS_DIR "/" \
|
||||
"base_class %" PCI_DEVICE_BASE_CLASS_ID_ITEM "%|" \
|
||||
", sub_class %" PCI_DEVICE_SUB_CLASS_ID_ITEM "%|" \
|
||||
", api %" PCI_DEVICE_API_ID_ITEM "%"
|
||||
|
||||
#endif
|
||||
#endif /* _PCI2_H */
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2007, Haiku, Inc. All RightsReserved.
|
||||
* Copyright 2004-2008, Haiku, Inc. All RightsReserved.
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -320,7 +320,7 @@ typedef struct scsi_device_interface {
|
||||
status_t (*ioctl)(scsi_device device, uint32 op, void *buffer, size_t length);
|
||||
} scsi_device_interface;
|
||||
|
||||
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/driver/v1"
|
||||
#define SCSI_DEVICE_MODULE_NAME "bus_managers/scsi/device/driver_v1"
|
||||
|
||||
|
||||
// Bus node
|
||||
@@ -336,7 +336,7 @@ typedef struct scsi_device_interface {
|
||||
// This interface can be used by peripheral drivers to access the
|
||||
// bus directly.
|
||||
typedef struct scsi_bus_interface {
|
||||
bus_module_info info;
|
||||
driver_module_info info;
|
||||
|
||||
// get information about host controller
|
||||
uchar (*path_inquiry)(scsi_bus bus, scsi_path_inquiry *inquiry_data);
|
||||
@@ -345,7 +345,7 @@ typedef struct scsi_bus_interface {
|
||||
} scsi_bus_interface;
|
||||
|
||||
// name of SCSI bus node driver
|
||||
#define SCSI_BUS_MODULE_NAME "bus_managers/scsi/bus/v1"
|
||||
#define SCSI_BUS_MODULE_NAME "bus_managers/scsi/bus/driver_v1"
|
||||
|
||||
|
||||
// Interface for SIM
|
||||
@@ -404,7 +404,7 @@ typedef struct scsi_for_sim_interface {
|
||||
} scsi_for_sim_interface;
|
||||
|
||||
|
||||
#define SCSI_FOR_SIM_MODULE_NAME "bus_managers/scsi/sim/v1"
|
||||
#define SCSI_FOR_SIM_MODULE_NAME "bus_managers/scsi/sim/driver_v1"
|
||||
|
||||
|
||||
// SIM Node
|
||||
@@ -416,34 +416,35 @@ typedef struct scsi_for_sim_interface {
|
||||
// controller name (required, string)
|
||||
#define SCSI_DESCRIPTION_CONTROLLER_NAME "controller_name"
|
||||
|
||||
typedef void * scsi_sim_cookie;
|
||||
typedef void *scsi_sim_cookie;
|
||||
|
||||
// SIM interface
|
||||
// SCSI controller drivers must provide this interface
|
||||
typedef struct scsi_sim_interface {
|
||||
driver_module_info info;
|
||||
|
||||
void (*set_scsi_bus)(scsi_sim_cookie cookie, scsi_bus bus);
|
||||
|
||||
// execute request
|
||||
void (*scsi_io)( scsi_sim_cookie cookie, scsi_ccb *ccb );
|
||||
void (*scsi_io)(scsi_sim_cookie cookie, scsi_ccb *ccb);
|
||||
// abort request
|
||||
uchar (*abort)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort );
|
||||
uchar (*abort)(scsi_sim_cookie cookie, scsi_ccb *ccb_to_abort);
|
||||
// reset device
|
||||
uchar (*reset_device)( scsi_sim_cookie cookie, uchar target_id, uchar target_lun );
|
||||
uchar (*reset_device)(scsi_sim_cookie cookie, uchar target_id, uchar target_lun);
|
||||
// terminate request
|
||||
uchar (*term_io)( scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate );
|
||||
uchar (*term_io)(scsi_sim_cookie cookie, scsi_ccb *ccb_to_terminate);
|
||||
|
||||
// get information about bus
|
||||
uchar (*path_inquiry)( scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data );
|
||||
uchar (*path_inquiry)(scsi_sim_cookie cookie, scsi_path_inquiry *inquiry_data);
|
||||
// scan bus
|
||||
// this is called immediately before the SCSI bus manager scans the bus
|
||||
uchar (*scan_bus)( scsi_sim_cookie cookie );
|
||||
uchar (*scan_bus)(scsi_sim_cookie cookie);
|
||||
// reset bus
|
||||
uchar (*reset_bus)( scsi_sim_cookie cookie );
|
||||
uchar (*reset_bus)(scsi_sim_cookie cookie);
|
||||
|
||||
// get restrictions of one device
|
||||
// (used for non-SCSI transport protocols and bug fixes)
|
||||
void (*get_restrictions)(
|
||||
scsi_sim_cookie cookie,
|
||||
void (*get_restrictions)(scsi_sim_cookie cookie,
|
||||
uchar target_id, // target id
|
||||
bool *is_atapi, // set to true if this is an ATAPI device that
|
||||
// needs some commands emulated
|
||||
|
||||
+103
-122
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Haiku Inc. All Rights Reserved.
|
||||
* Copyright 2004-2008, Haiku Inc. All Rights Reserved.
|
||||
* Distributed under the terms of the MIT license.
|
||||
*/
|
||||
#ifndef _DEVICE_MANAGER_H
|
||||
@@ -11,189 +11,170 @@
|
||||
#include <module.h>
|
||||
|
||||
|
||||
// type of I/O resource
|
||||
/* type of I/O resource */
|
||||
enum {
|
||||
IO_MEM = 1,
|
||||
IO_PORT = 2,
|
||||
ISA_DMA_CHANNEL = 3
|
||||
B_IO_MEMORY = 1,
|
||||
B_IO_PORT = 2,
|
||||
B_ISA_DMA_CHANNEL = 3
|
||||
};
|
||||
|
||||
|
||||
// I/O resource description
|
||||
/* I/O resource description */
|
||||
typedef struct {
|
||||
uint32 type;
|
||||
// type of I/O resource
|
||||
/* type of I/O resource */
|
||||
|
||||
uint32 base;
|
||||
// I/O memory: first physical address (32 bit)
|
||||
// I/O port: first port address (16 bit)
|
||||
// ISA DMA channel: channel number (0-7)
|
||||
/* I/O memory: first physical address (32 bit)
|
||||
* I/O port: first port address (16 bit)
|
||||
* ISA DMA channel: channel number (0-7)
|
||||
*/
|
||||
|
||||
uint32 length;
|
||||
// I/O memory: size of address range (32 bit)
|
||||
// I/O port: size of port range (16 bit)
|
||||
// ISA DMA channel: must be 1
|
||||
/* I/O memory: size of address range (32 bit)
|
||||
* I/O port: size of port range (16 bit)
|
||||
* ISA DMA channel: must be 1
|
||||
*/
|
||||
} io_resource;
|
||||
|
||||
// attribute of a device node
|
||||
/* attribute of a device node */
|
||||
typedef struct {
|
||||
const char *name;
|
||||
type_code type; // for supported types, see value
|
||||
type_code type; /* for supported types, see value */
|
||||
union {
|
||||
uint8 ui8; // B_UINT8_TYPE
|
||||
uint16 ui16; // B_UINT16_TYPE
|
||||
uint32 ui32; // B_UINT32_TYPE
|
||||
uint64 ui64; // B_UINT64_TYPE
|
||||
const char *string; // B_STRING_TYPE
|
||||
struct { // B_RAW_TYPE
|
||||
void *data;
|
||||
uint8 ui8; /* B_UINT8_TYPE */
|
||||
uint16 ui16; /* B_UINT16_TYPE */
|
||||
uint32 ui32; /* B_UINT32_TYPE */
|
||||
uint64 ui64; /* B_UINT64_TYPE */
|
||||
const char *string; /* B_STRING_TYPE */
|
||||
struct { /* B_RAW_TYPE */
|
||||
const void *data;
|
||||
size_t length;
|
||||
} raw;
|
||||
} value;
|
||||
} device_attr;
|
||||
|
||||
|
||||
typedef struct device_node_info *device_node_handle;
|
||||
typedef struct io_resource_info *io_resource_handle;
|
||||
typedef struct device_attr_info *device_attr_handle;
|
||||
|
||||
typedef struct device_node device_node;
|
||||
typedef struct driver_module_info driver_module_info;
|
||||
|
||||
|
||||
// interface of the device manager
|
||||
/* interface of the device manager */
|
||||
|
||||
typedef struct device_manager_info {
|
||||
module_info info;
|
||||
|
||||
status_t (*init_driver)(device_node_handle node, void *userCookie,
|
||||
driver_module_info **interface, void **cookie);
|
||||
status_t (*uninit_driver)(device_node_handle node);
|
||||
status_t (*rescan_node)(device_node *node);
|
||||
|
||||
status_t (*rescan)(device_node_handle node);
|
||||
status_t (*register_node)(device_node *parent, const char *moduleName,
|
||||
const device_attr *attrs, const io_resource *ioResources,
|
||||
device_node **_node);
|
||||
status_t (*unregister_node)(device_node *node);
|
||||
|
||||
status_t (*register_device)(device_node_handle parent,
|
||||
const device_attr *attrs,
|
||||
const io_resource_handle *io_resources,
|
||||
device_node_handle *node);
|
||||
status_t (*unregister_device)(device_node_handle node);
|
||||
status_t (*get_driver)(device_node *node, driver_module_info **_module,
|
||||
void **_cookie);
|
||||
|
||||
device_node_handle (*get_root)();
|
||||
status_t (*get_next_child_device)(device_node_handle parent,
|
||||
device_node_handle *_node, const device_attr *attrs);
|
||||
device_node_handle (*get_parent)(device_node_handle node);
|
||||
void (*put_device_node)(device_node_handle node);
|
||||
device_node *(*get_root_node)();
|
||||
status_t (*get_next_child_node)(device_node *parent,
|
||||
const device_attr *attrs, device_node **node);
|
||||
device_node *(*get_parent_node)(device_node *node);
|
||||
void (*put_node)(device_node *node);
|
||||
|
||||
status_t (*acquire_io_resources)(io_resource *resources,
|
||||
io_resource_handle *handles);
|
||||
status_t (*release_io_resources)(const io_resource_handle *handles);
|
||||
status_t (*publish_device)(device_node *node, const char *path,
|
||||
const char *deviceModuleName);
|
||||
status_t (*unpublish_device)(device_node *node, const char *path);
|
||||
|
||||
int32 (*create_id)(const char *generator);
|
||||
status_t (*free_id)(const char *generator, uint32 id);
|
||||
|
||||
status_t (*get_attr_uint8)(device_node_handle node,
|
||||
const char *name, uint8 *value, bool recursive);
|
||||
status_t (*get_attr_uint16)(device_node_handle node,
|
||||
const char *name, uint16 *value, bool recursive);
|
||||
status_t (*get_attr_uint32)(device_node_handle node,
|
||||
const char *name, uint32 *value, bool recursive);
|
||||
status_t (*get_attr_uint64)(device_node_handle node,
|
||||
const char *name, uint64 *value, bool recursive);
|
||||
status_t (*get_attr_string)(device_node_handle node,
|
||||
const char *name, char **value, bool recursive);
|
||||
status_t (*get_attr_raw)(device_node_handle node,
|
||||
const char *name, void **data, size_t *_size,
|
||||
bool recursive);
|
||||
status_t (*get_attr_uint8)(const device_node *node, const char *name,
|
||||
uint8 *value, bool recursive);
|
||||
status_t (*get_attr_uint16)(const device_node *node, const char *name,
|
||||
uint16 *value, bool recursive);
|
||||
status_t (*get_attr_uint32)(const device_node *node, const char *name,
|
||||
uint32 *value, bool recursive);
|
||||
status_t (*get_attr_uint64)(const device_node *node, const char *name,
|
||||
uint64 *value, bool recursive);
|
||||
status_t (*get_attr_string)(const device_node *node, const char *name,
|
||||
const char **_value, bool recursive);
|
||||
status_t (*get_attr_raw)(const device_node *node, const char *name,
|
||||
const void **_data, size_t *_size, bool recursive);
|
||||
|
||||
status_t (*get_next_attr)(device_node_handle node,
|
||||
device_attr_handle *attrHandle);
|
||||
status_t (*release_attr)(device_node_handle node,
|
||||
device_attr_handle attr_handle);
|
||||
status_t (*retrieve_attr)(device_attr_handle attr_handle,
|
||||
const device_attr **attr);
|
||||
status_t (*write_attr)(device_node_handle node,
|
||||
const device_attr *attr);
|
||||
status_t (*remove_attr)(device_node_handle node, const char *name);
|
||||
status_t (*get_next_attr)(device_node *node, device_attr **_attr);
|
||||
} device_manager_info;
|
||||
|
||||
|
||||
#define B_DEVICE_MANAGER_MODULE_NAME "system/device_manager/v1"
|
||||
|
||||
|
||||
// interface of device driver
|
||||
/* interface of device driver */
|
||||
|
||||
struct driver_module_info {
|
||||
module_info info;
|
||||
|
||||
float (*supports_device)(device_node_handle parent, bool *_noConnection);
|
||||
status_t (*register_device)(device_node_handle parent);
|
||||
float (*supports_device)(device_node *parent);
|
||||
status_t (*register_device)(device_node *parent);
|
||||
|
||||
status_t (*init_driver)(device_node_handle node, void *user_cookie, void **_cookie);
|
||||
status_t (*uninit_driver)(void *cookie);
|
||||
status_t (*init_driver)(device_node *node, void **_driverCookie);
|
||||
void (*uninit_driver)(void *driverCookie);
|
||||
status_t (*register_child_devices)(void *driverCookie);
|
||||
status_t (*rescan_child_devices)(void *driverCookie);
|
||||
|
||||
void (*device_removed)(device_node_handle node, void *cookie);
|
||||
void (*device_cleanup)(device_node_handle node);
|
||||
|
||||
void (*get_supported_paths)(const char ***_busses, const char ***_devices);
|
||||
void (*device_removed)(void *driverCookie);
|
||||
status_t (*suspend)(void *driverCookie, int32 state);
|
||||
status_t (*resume)(void *driverCookie);
|
||||
};
|
||||
|
||||
|
||||
// standard device node attributes
|
||||
/* standard device node attributes */
|
||||
|
||||
#define PNP_MANAGER_ID_GENERATOR "id_generator"
|
||||
// if you are using an id generator (see create_id), you can let the
|
||||
// manager automatically free the id when the node is deleted by setting
|
||||
// the following attributes:
|
||||
// name of generator (string)
|
||||
#define PNP_MANAGER_AUTO_ID "auto_id"
|
||||
// generated id (uint32)
|
||||
#define B_DEVICE_PRETTY_NAME "device/pretty name" /* string */
|
||||
#define B_DEVICE_MAPPING "device/mapping" /* string */
|
||||
#define B_DEVICE_BUS "device/bus" /* string */
|
||||
#define B_DEVICE_FIXED_CHILD "device/fixed child" /* string */
|
||||
#define B_DEVICE_FLAGS "device/flags" /* uint32 */
|
||||
|
||||
#define B_DRIVER_MODULE "driver/module"
|
||||
#define B_DRIVER_PRETTY_NAME "driver/pretty name"
|
||||
#define B_DRIVER_FIXED_CHILD "driver/fixed child"
|
||||
#define B_DRIVER_MAPPING "driver/mapping"
|
||||
#define B_DRIVER_BUS "driver/bus"
|
||||
#define B_DRIVER_FIND_DEVICES_ON_DEMAND "driver/on demand"
|
||||
#define B_DRIVER_EXPLORE_LAST "driver/explore last"
|
||||
#define B_DEVICE_VENDOR_ID "device/vendor" /* uint16 */
|
||||
#define B_DEVICE_ID "device/id" /* uint16 */
|
||||
#define B_DEVICE_TYPE "device/type"
|
||||
/* uint16, PCI base class */
|
||||
#define B_DEVICE_SUB_TYPE "device/subtype"
|
||||
/* uint16, PCI sub type */
|
||||
#define B_DEVICE_INTERFACE "device/interface"
|
||||
/* uint16, PCI class API */
|
||||
|
||||
#define B_DRIVER_UNIQUE_DEVICE_ID "unique id"
|
||||
#define B_DRIVER_DEVICE_TYPE "device type"
|
||||
#define B_DEVICE_UNIQUE_ID "device/unique id" /* string */
|
||||
|
||||
#define B_AUDIO_DRIVER_TYPE "audio"
|
||||
#define B_BUS_DRIVER_TYPE "bus"
|
||||
#define B_DISK_DRIVER_TYPE "disk"
|
||||
#define B_GRAPHICS_DRIVER_TYPE "graphics"
|
||||
#define B_INPUT_DRIVER_TYPE "input"
|
||||
#define B_MISC_DRIVER_TYPE "misc"
|
||||
#define B_NETWORK_DRIVER_TYPE "net"
|
||||
#define B_VIDEO_DRIVER_TYPE "video"
|
||||
#define B_INTERRUPT_CONTROLLER_DRIVER_TYPE "interrupt controller"
|
||||
|
||||
#define PNP_DRIVER_CONNECTION "connection"
|
||||
// connection of parent the device is attached to (optional, string)
|
||||
// there can be only one device per connection
|
||||
/* device flags */
|
||||
#define B_FIND_CHILD_ON_DEMAND 0x01
|
||||
#define B_FIND_MULTIPLE_CHILDREN 0x02
|
||||
#define B_KEEP_DRIVER_LOADED 0x04
|
||||
|
||||
|
||||
// interface of a bus device driver
|
||||
/* interface of device */
|
||||
|
||||
typedef struct bus_module_info {
|
||||
driver_module_info info;
|
||||
typedef struct io_request io_request;
|
||||
|
||||
// scan the bus and register all devices.
|
||||
status_t (*register_child_devices)(void *cookie);
|
||||
struct device_module_info {
|
||||
module_info info;
|
||||
|
||||
// user initiated rescan of the bus - only propagate changes
|
||||
// you only need to implement this, if you cannot detect device changes yourself
|
||||
// driver is always loaded during this call, but other hooks may
|
||||
// be called concurrently
|
||||
status_t (*rescan_bus)(void *cookie);
|
||||
} bus_module_info;
|
||||
status_t (*init_device)(void *driverCookie, void **_deviceCookie);
|
||||
void (*uninit_device)(void *deviceCookie);
|
||||
void (*device_removed)(void *deviceCookie);
|
||||
|
||||
status_t (*open)(void *deviceCookie, const char *path, int openMode,
|
||||
void **_cookie);
|
||||
status_t (*close)(void *cookie);
|
||||
status_t (*free)(void *cookie);
|
||||
status_t (*read)(void *cookie, off_t pos, void *buffer, size_t *_length);
|
||||
status_t (*write)(void *cookie, off_t pos, const void *buffer,
|
||||
size_t *_length);
|
||||
status_t (*io)(void *cookie, io_request *request);
|
||||
status_t (*control)(void *cookie, uint32 op, void *buffer, size_t length);
|
||||
status_t (*select)(void *cookie, uint8 event, selectsync *sync);
|
||||
status_t (*deselect)(void *cookie, uint8 event, selectsync *sync);
|
||||
};
|
||||
|
||||
// standard attributes
|
||||
|
||||
// PnP bus identification (required, uint8)
|
||||
// define this to let the PnP manager know that this is a PnP bus
|
||||
// the actual content is ignored
|
||||
#define PNP_BUS_IS_BUS "bus/is_bus"
|
||||
extern struct device_manager_info *gDeviceManager;
|
||||
|
||||
#endif /* _DEVICE_MANAGER_H */
|
||||
|
||||
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fast logging facilities.
|
||||
|
||||
This logging is much faster then dprintf and is saver
|
||||
against buffer overflow conditions.
|
||||
|
||||
Clients have to define events by creating an array of
|
||||
fast_log_type entries, each consisting of a code and the
|
||||
associated human-readable description. During logging,
|
||||
only the code is stored to save space and time. Also,
|
||||
all arguments are stored binary (currently, they must
|
||||
be of type uint32). Conversion to human-readable text is
|
||||
post-poned until the logging data is read or a client
|
||||
connection is closed (as this invalidates the event-
|
||||
description binding).
|
||||
|
||||
The reader interface is /dev/FAST_LOG_DEVFS_NAME. This
|
||||
device can only be read from (no seeking or further
|
||||
functionality) and does not block if there is no data.
|
||||
This is because if you want to store the log into a
|
||||
file, the file access may lead to further logging data,
|
||||
so doing a sleep between reads saves logging entries.
|
||||
*/
|
||||
|
||||
#ifndef FAST_LOG_H
|
||||
#define FAST_LOG_H
|
||||
|
||||
#include <module.h>
|
||||
|
||||
// one event type as defined by client
|
||||
typedef struct fast_log_event_type {
|
||||
// code of event (zero means end-of-list)
|
||||
int16 event;
|
||||
// human-readable description
|
||||
const char *description;
|
||||
} fast_log_event_type;
|
||||
|
||||
|
||||
// handle of client connection
|
||||
typedef struct fast_log_connection *fast_log_handle;
|
||||
|
||||
|
||||
// client interface
|
||||
typedef struct fast_log_info {
|
||||
module_info minfo;
|
||||
|
||||
// open client connection
|
||||
// prefix - prefix to print in log before each event
|
||||
// types - array of event types; last entry must have event=0
|
||||
fast_log_handle (*start_log)(const char *prefix, fast_log_event_type types[]);
|
||||
// close client connection
|
||||
void (*stop_log)(fast_log_handle handle);
|
||||
|
||||
// log an entry without arguments
|
||||
void (*log_0)(fast_log_handle handle, int event);
|
||||
// log an entry with one argument
|
||||
void (*log_1)(fast_log_handle handle, int event, uint32 param1);
|
||||
// log an entry with two arguments
|
||||
void (*log_2)(fast_log_handle handle, int event, uint32 param1, uint32 param2);
|
||||
// log an entry with three arguments
|
||||
void (*log_3)(fast_log_handle handle, int event, uint32 param1, uint32 param2, uint32 param3);
|
||||
// log an entry with four arguments
|
||||
void (*log_4)(fast_log_handle handle, int event, uint32 param1, uint32 param2, uint32 param3, uint32 param4);
|
||||
|
||||
// log an entry with n arguments
|
||||
// don't cheat on num_params!
|
||||
void (*log_n)(fast_log_handle handle, int event, int num_params, ...);
|
||||
} fast_log_info;
|
||||
|
||||
// name of client interface module
|
||||
#define FAST_LOG_MODULE_NAME "generic/fast_log/v1"
|
||||
// name of device to read logging data from
|
||||
#define FAST_LOG_DEVFS_NAME "fast_log"
|
||||
|
||||
#endif
|
||||
@@ -91,7 +91,7 @@ enum {
|
||||
// info about one channel
|
||||
typedef struct ide_adapter_channel_info {
|
||||
pci_device_module_info *pci;
|
||||
pci_device device;
|
||||
pci_device *device;
|
||||
|
||||
uint16 command_block_base; // io address command block
|
||||
uint16 control_block_base; // io address control block
|
||||
@@ -102,7 +102,7 @@ typedef struct ide_adapter_channel_info {
|
||||
// be accessed anymore
|
||||
|
||||
ide_channel ide_channel;
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
|
||||
int32 (*inthand)( void *arg );
|
||||
|
||||
@@ -116,14 +116,14 @@ typedef struct ide_adapter_channel_info {
|
||||
// info about controller
|
||||
typedef struct ide_adapter_controller_info {
|
||||
pci_device_module_info *pci;
|
||||
pci_device device;
|
||||
pci_device *device;
|
||||
|
||||
uint16 bus_master_base;
|
||||
|
||||
uint32 lost; // != 0 if device got removed, i.e. if it must not
|
||||
// be accessed anymore
|
||||
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
} ide_adapter_controller_info;
|
||||
|
||||
|
||||
@@ -131,6 +131,9 @@ typedef struct ide_adapter_controller_info {
|
||||
typedef struct {
|
||||
module_info info;
|
||||
|
||||
void (*set_channel)(ide_adapter_channel_info *channel,
|
||||
ide_channel ideChannel);
|
||||
|
||||
// function calls that can be forwarded from actual driver
|
||||
status_t (*write_command_block_regs)(ide_adapter_channel_info *channel,
|
||||
ide_task_file *tf, ide_reg_mask mask);
|
||||
@@ -153,47 +156,47 @@ typedef struct {
|
||||
int32 (*inthand)(void *arg);
|
||||
|
||||
// functions that must be called by init/uninit etc. of channel driver
|
||||
status_t (*init_channel)(device_node_handle node, ide_channel ide_channel,
|
||||
status_t (*init_channel)(device_node *node,
|
||||
ide_adapter_channel_info **cookie, size_t total_data_size,
|
||||
int32 (*inthand)(void *arg));
|
||||
status_t (*uninit_channel)(ide_adapter_channel_info *channel);
|
||||
void (*channel_removed)(device_node_handle node, ide_adapter_channel_info *channel);
|
||||
void (*uninit_channel)(ide_adapter_channel_info *channel);
|
||||
void (*channel_removed)(ide_adapter_channel_info *channel);
|
||||
|
||||
// publish channel node
|
||||
status_t (*publish_channel)(device_node_handle controller_node,
|
||||
status_t (*publish_channel)(device_node *controller_node,
|
||||
const char *channel_module_name, uint16 command_block_base,
|
||||
uint16 control_block_base, uint8 intnum, bool can_dma,
|
||||
uint8 channel_index, const char *name,
|
||||
io_resource_handle *resources, device_node_handle *node);
|
||||
const io_resource *resources, device_node **node);
|
||||
// verify channel configuration and publish node on success
|
||||
status_t (*detect_channel)(pci_device_module_info *pci, pci_device pci_device,
|
||||
device_node_handle controller_node, const char *channel_module_name,
|
||||
status_t (*detect_channel)(pci_device_module_info *pci, pci_device *pciDevice,
|
||||
device_node *controller_node, const char *channel_module_name,
|
||||
bool controller_can_dma, uint16 command_block_base,
|
||||
uint16 control_block_base, uint16 bus_master_base,
|
||||
uint8 intnum, uint8 channel_index, const char *name,
|
||||
device_node_handle *node, bool supports_compatibility_mode);
|
||||
device_node **node, bool supports_compatibility_mode);
|
||||
|
||||
// functions that must be called by init/uninit etc. of controller driver
|
||||
status_t (*init_controller)(device_node_handle node, void *user_cookie,
|
||||
status_t (*init_controller)(device_node *node,
|
||||
ide_adapter_controller_info **cookie, size_t total_data_size);
|
||||
status_t (*uninit_controller)(ide_adapter_controller_info *controller);
|
||||
void (*controller_removed)(device_node_handle node, ide_adapter_controller_info *controller);
|
||||
void (*uninit_controller)(ide_adapter_controller_info *controller);
|
||||
void (*controller_removed)(ide_adapter_controller_info *controller);
|
||||
|
||||
// publish controller node
|
||||
status_t (*publish_controller)(device_node_handle parent, uint16 bus_master_base,
|
||||
io_resource_handle *resources, const char *controller_driver,
|
||||
status_t (*publish_controller)(device_node *parent, uint16 bus_master_base,
|
||||
io_resource *resources, const char *controller_driver,
|
||||
const char *controller_driver_type, const char *controller_name,
|
||||
bool can_dma, bool can_cq, uint32 dma_alignment, uint32 dma_boundary,
|
||||
uint32 max_sg_block_size, device_node_handle *node);
|
||||
uint32 max_sg_block_size, device_node **node);
|
||||
// verify controller configuration and publish node on success
|
||||
status_t (*detect_controller)(pci_device_module_info *pci, pci_device pci_device,
|
||||
device_node_handle parent, uint16 bus_master_base,
|
||||
status_t (*detect_controller)(pci_device_module_info *pci, pci_device *pciDevice,
|
||||
device_node *parent, uint16 bus_master_base,
|
||||
const char *controller_driver, const char *controller_driver_type,
|
||||
const char *controller_name, bool can_dma, bool can_cq,
|
||||
uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
|
||||
device_node_handle *node);
|
||||
device_node **node);
|
||||
// standard master probe for controller that registers controller and channel nodes
|
||||
status_t (*probe_controller)(device_node_handle parent, const char *controller_driver,
|
||||
status_t (*probe_controller)(device_node *parent, const char *controller_driver,
|
||||
const char *controller_driver_type, const char *controller_name,
|
||||
const char *channel_module_name, bool can_dma, bool can_cq,
|
||||
uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
|
||||
|
||||
@@ -92,7 +92,7 @@ typedef struct scsi_periph_interface {
|
||||
scsi_periph_callbacks *callbacks,
|
||||
scsi_device scsi_device,
|
||||
scsi_device_interface *scsi,
|
||||
device_node_handle node,
|
||||
device_node *node,
|
||||
bool removable,
|
||||
scsi_periph_device *driver );
|
||||
status_t (*unregister_device)( scsi_periph_device driver );
|
||||
@@ -150,7 +150,7 @@ typedef struct scsi_periph_interface {
|
||||
|
||||
// compose device name consisting of prefix and path/target/LUN
|
||||
// (result must be freed by caller)
|
||||
char *(*compose_device_name)(device_node_handle device_node, const char *prefix);
|
||||
char *(*compose_device_name)(device_node *device_node, const char *prefix);
|
||||
|
||||
// fill data with icon (for B_GET_ICON ioctl)
|
||||
status_t (*get_icon)( icon_type type, device_icon *data );
|
||||
|
||||
@@ -11,20 +11,11 @@
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
struct kernel_args;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void devfs_add_preloaded_drivers(struct kernel_args* args);
|
||||
|
||||
status_t devfs_add_driver(const char *path);
|
||||
|
||||
void devfs_driver_added(const char *path);
|
||||
void devfs_driver_removed(const char *path);
|
||||
|
||||
status_t devfs_unpublish_file_device(const char *path);
|
||||
status_t devfs_publish_file_device(const char *path, const char *filePath);
|
||||
|
||||
|
||||
@@ -1,85 +1,28 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2004-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_DEVICE_MANAGER_H
|
||||
#define _KERNEL_DEVICE_MANAGER_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <device_manager.h>
|
||||
|
||||
#include <util/list.h>
|
||||
|
||||
|
||||
typedef struct device_node_info device_node_info;
|
||||
|
||||
// info about a device node
|
||||
struct device_node_info {
|
||||
struct list_link siblings;
|
||||
device_node_info *parent;
|
||||
struct list children;
|
||||
int32 ref_count;
|
||||
|
||||
driver_module_info *driver;
|
||||
void *cookie;
|
||||
|
||||
bool registered; // true, if device is officially existent
|
||||
bool blocked_by_rescan; // true, if device is blocked because of rescan
|
||||
int32 num_waiting_hooks; // number of waiting hook calls
|
||||
sem_id hook_sem; // sem for waiting hook calls
|
||||
int32 load_block_count; // load-block nest count
|
||||
int32 num_blocked_loads; // number of waiting load calls
|
||||
sem_id load_block_sem; // sem for waiting load calls
|
||||
int32 load_count; // # of finished load_driver() calls
|
||||
int32 loading; // # of active (un)load_driver() calls
|
||||
uint32 rescan_depth; // > 0 if scanning is active
|
||||
struct device_attr_info *attributes; // list of attributes
|
||||
uint32 num_io_resources; // number of I/O resources
|
||||
io_resource_handle *io_resources; // array of I/O resource (NULL-terminated)
|
||||
bool automatically_loaded; // loaded automatically because PNP_DRIVER_ALWAYS_LOADED
|
||||
uint32 internal_id; // internal identifier
|
||||
};
|
||||
|
||||
|
||||
struct kernel_args;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern status_t probe_for_device_type(const char *type);
|
||||
extern status_t device_manager_init(struct kernel_args *args);
|
||||
extern status_t device_manager_init_post_modules(struct kernel_args *args);
|
||||
void legacy_driver_add_preloaded(struct kernel_args *args);
|
||||
|
||||
// temporary/optional device manager syscall API
|
||||
#define DEVICE_MANAGER_SYSCALLS "device_manager"
|
||||
|
||||
#define DM_GET_ROOT 1
|
||||
#define DM_GET_CHILD 2
|
||||
#define DM_GET_NEXT_CHILD 3
|
||||
#define DM_GET_NEXT_ATTRIBUTE 4
|
||||
|
||||
struct dev_attr {
|
||||
uint32 node_cookie;
|
||||
uint32 cookie;
|
||||
char name[255];
|
||||
type_code type;
|
||||
union {
|
||||
uint8 ui8;
|
||||
uint16 ui16;
|
||||
uint32 ui32;
|
||||
uint64 ui64;
|
||||
char string[255];
|
||||
struct {
|
||||
void *data;
|
||||
size_t length;
|
||||
} raw;
|
||||
} value;
|
||||
};
|
||||
status_t device_manager_probe(const char *path, uint32 updateCycle);
|
||||
status_t device_manager_init(struct kernel_args *args);
|
||||
status_t device_manager_init_post_modules(struct kernel_args *args);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _KRENEL_DEVICE_MANAGER_H */
|
||||
#endif /* _KERNEL_DEVICE_MANAGER_H */
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _SYSTEM_DEVICE_MANAGER_DEFS_H
|
||||
#define _SYSTEM_DEVICE_MANAGER_DEFS_H
|
||||
|
||||
|
||||
#include <device_manager.h>
|
||||
|
||||
|
||||
// temporary/optional device manager syscall API
|
||||
#define DEVICE_MANAGER_SYSCALLS "device_manager"
|
||||
|
||||
#define DM_GET_ROOT 1
|
||||
#define DM_GET_CHILD 2
|
||||
#define DM_GET_NEXT_CHILD 3
|
||||
#define DM_GET_NEXT_ATTRIBUTE 4
|
||||
|
||||
struct device_attr_info {
|
||||
uint32 node_cookie;
|
||||
uint32 cookie;
|
||||
char name[255];
|
||||
type_code type;
|
||||
union {
|
||||
uint8 ui8;
|
||||
uint16 ui16;
|
||||
uint32 ui32;
|
||||
uint64 ui64;
|
||||
char string[255];
|
||||
struct {
|
||||
void *data;
|
||||
size_t length;
|
||||
} raw;
|
||||
} value;
|
||||
};
|
||||
|
||||
#endif /* _SYSTEM_DEVICE_MANAGER_DEFS_H */
|
||||
@@ -66,8 +66,6 @@ reset_bus(ide_device_info *device, ide_qrequest *ignore)
|
||||
|
||||
dprintf("ide: reset_bus() device %p, bus %p\n", device, bus);
|
||||
|
||||
FAST_LOG0(bus->log, ev_ide_reset_bus);
|
||||
|
||||
if (device->reconnect_timer_installed) {
|
||||
cancel_timer(&device->reconnect_timer.te);
|
||||
device->reconnect_timer_installed = false;
|
||||
@@ -142,7 +140,6 @@ reset_device(ide_device_info *device, ide_qrequest *ignore)
|
||||
|
||||
dprintf("ide: reset_device() device %p\n", device);
|
||||
|
||||
FAST_LOG1(bus->log, ev_ide_reset_device, device->is_device1);
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (!device->is_atapi)
|
||||
@@ -202,13 +199,6 @@ send_command(ide_device_info *device, ide_qrequest *qrequest,
|
||||
uint8 num_retries = 0;
|
||||
bool irq_guard;
|
||||
|
||||
FAST_LOGN(bus->log, ev_ide_send_command, 15, device->is_device1, (uint32)qrequest,
|
||||
device->tf.raw.r[0], device->tf.raw.r[1], device->tf.raw.r[2],
|
||||
device->tf.raw.r[3], device->tf.raw.r[4], device->tf.raw.r[5],
|
||||
device->tf.raw.r[6],
|
||||
device->tf.raw.r[7], device->tf.raw.r[8], device->tf.raw.r[9],
|
||||
device->tf.raw.r[10], device->tf.raw.r[11]);
|
||||
|
||||
retry:
|
||||
irq_guard = bus->num_running_reqs > 1;
|
||||
|
||||
@@ -391,8 +381,6 @@ device_start_service(ide_device_info *device, int *tag)
|
||||
{
|
||||
ide_bus_info *bus = device->bus;
|
||||
|
||||
FAST_LOG1(bus->log, ev_ide_device_start_service, device->is_device1);
|
||||
|
||||
device->tf.write.command = IDE_CMD_SERVICE;
|
||||
device->tf.queued.mode = ide_mode_lba;
|
||||
|
||||
@@ -433,7 +421,6 @@ device_start_service(ide_device_info *device, int *tag)
|
||||
|
||||
*tag = device->tf.queued.tag;
|
||||
|
||||
FAST_LOG2(bus->log, ev_ide_device_start_service2, device->is_device1, *tag);
|
||||
return true;
|
||||
|
||||
err:
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
/** called when an IDE channel was registered by a controller driver */
|
||||
|
||||
static status_t
|
||||
ide_channel_added(device_node_handle parent)
|
||||
ide_channel_added(device_node *parent)
|
||||
{
|
||||
char *controller_name = NULL;
|
||||
const char *controller_name = NULL;
|
||||
uint32 channel_id;
|
||||
|
||||
SHOW_FLOW0(2, "");
|
||||
@@ -47,8 +47,7 @@ ide_channel_added(device_node_handle parent)
|
||||
{
|
||||
device_attr attrs[] =
|
||||
{
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: IDE_SIM_MODULE_NAME }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: SCSI_FOR_SIM_MODULE_NAME }},
|
||||
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { string: SCSI_FOR_SIM_MODULE_NAME }},
|
||||
|
||||
{ SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
|
||||
{ string: controller_name }},
|
||||
@@ -65,25 +64,17 @@ ide_channel_added(device_node_handle parent)
|
||||
// in ide_sim.c!
|
||||
{ B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: 255 }},
|
||||
{ IDE_CHANNEL_ID_ITEM, B_UINT32_TYPE, { ui32: channel_id }},
|
||||
{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { string: IDE_CHANNEL_ID_GENERATOR }},
|
||||
{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: channel_id }},
|
||||
// { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { string: IDE_CHANNEL_ID_GENERATOR }},
|
||||
// { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: channel_id }},
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
device_node_handle node;
|
||||
status_t res;
|
||||
|
||||
res = pnp->register_device(parent, attrs, NULL, &node);
|
||||
|
||||
free(controller_name);
|
||||
|
||||
return res;
|
||||
return pnp->register_node(parent, IDE_SIM_MODULE_NAME, attrs, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
err:
|
||||
free(controller_name);
|
||||
|
||||
return B_NO_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,19 +5,12 @@
|
||||
#ifndef __IDE_INTERNAL_H__
|
||||
#define __IDE_INTERNAL_H__
|
||||
|
||||
/*
|
||||
Part of Open IDE bus manager
|
||||
|
||||
Internal structures
|
||||
*/
|
||||
|
||||
|
||||
#include <bus/IDE.h>
|
||||
#include <bus/SCSI.h>
|
||||
#include "ide_device_infoblock.h"
|
||||
#include <ide_types.h>
|
||||
#include <device_manager.h>
|
||||
#include <fast_log.h>
|
||||
|
||||
#define debug_level_error 2
|
||||
#define debug_level_info 1
|
||||
@@ -28,24 +21,6 @@
|
||||
#include "wrapper.h"
|
||||
|
||||
|
||||
//#define USE_FAST_LOG
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
#define FAST_LOG0( handle, event ) fast_log->log_0( handle, event )
|
||||
#define FAST_LOG1( handle, event, param ) fast_log->log_1( handle, event, param )
|
||||
#define FAST_LOG2( handle, event, param1, param2 ) fast_log->log_2( handle, event, param1, param2 )
|
||||
#define FAST_LOG3( handle, event, param1, param2, param3 ) fast_log->log_3( handle, event, param1, param2, param3 )
|
||||
#define FAST_LOGN( handle, event, num_params... ) fast_log->log_n( handle, event, num_params )
|
||||
#else
|
||||
#define FAST_LOG0( handle, event )
|
||||
#define FAST_LOG1( handle, event, param )
|
||||
#define FAST_LOG2( handle, event, param1, param2 )
|
||||
#define FAST_LOG3( handle, event, param1, param2, param3 )
|
||||
#define FAST_LOGN( handle, event, num_params... )
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define IDE_STD_TIMEOUT 10
|
||||
#define IDE_RELEASE_TIMEOUT 10000000
|
||||
|
||||
@@ -58,7 +33,6 @@
|
||||
#define IDE_CHANNEL_ID_ITEM "ide/channel_id"
|
||||
|
||||
extern device_manager_info *pnp;
|
||||
extern fast_log_info *fast_log;
|
||||
|
||||
|
||||
typedef struct ide_bus_info ide_bus_info;
|
||||
@@ -228,14 +202,13 @@ struct ide_bus_info {
|
||||
|
||||
uchar path_id;
|
||||
|
||||
device_node_handle node; // our pnp node
|
||||
device_node *node; // our pnp node
|
||||
|
||||
// restrictions, read from controller node
|
||||
uint8 max_devices;
|
||||
uint8 can_DMA;
|
||||
uint8 can_CQ;
|
||||
|
||||
fast_log_handle log;
|
||||
char name[32];
|
||||
};
|
||||
|
||||
@@ -290,8 +263,8 @@ enum {
|
||||
|
||||
|
||||
// get selected device
|
||||
static inline
|
||||
ide_device_info *get_current_device(ide_bus_info *bus)
|
||||
static inline ide_device_info *
|
||||
get_current_device(ide_bus_info *bus)
|
||||
{
|
||||
ide_task_file tf;
|
||||
|
||||
|
||||
@@ -33,41 +33,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
scsi_for_sim_interface *scsi;
|
||||
fast_log_info *fast_log;
|
||||
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
static fast_log_event_type ide_events[] =
|
||||
{
|
||||
{ ev_ide_send_command, "ev_ide_send_command " },
|
||||
{ ev_ide_device_start_service, "ev_ide_device_start_service" },
|
||||
{ ev_ide_device_start_service2, "ev_ide_device_start_service2" },
|
||||
{ ev_ide_dpc_service, "ev_ide_dpc_service" },
|
||||
{ ev_ide_dpc_continue, "ev_ide_dpc_continue" },
|
||||
{ ev_ide_irq_handle, "ev_ide_irq_handle" },
|
||||
{ ev_ide_cancel_irq_timeout, "ev_ide_cancel_irq_timeout" },
|
||||
{ ev_ide_start_waiting, "ev_ide_start_waiting" },
|
||||
{ ev_ide_timeout_dpc, "ev_ide_timeout_dpc" },
|
||||
{ ev_ide_timeout, "ev_ide_timeout" },
|
||||
{ ev_ide_reset_bus, "ev_ide_reset_bus" },
|
||||
{ ev_ide_reset_device, "ev_ide_reset_device" },
|
||||
|
||||
{ ev_ide_scsi_io, "ev_ide_scsi_io" },
|
||||
{ ev_ide_scsi_io_exec, "ev_ide_scsi_io_exec" },
|
||||
{ ev_ide_scsi_io_invalid_device, "ev_ide_scsi_io_invalid_device" },
|
||||
{ ev_ide_scsi_io_bus_busy, "ev_ide_scsi_io_bus_busy" },
|
||||
{ ev_ide_scsi_io_device_busy, "ev_ide_scsi_io_device_busy" },
|
||||
{ ev_ide_scsi_io_disconnected, "ev_ide_scsi_io_disconnected" },
|
||||
{ ev_ide_finish_request, "ev_ide_finish_request" },
|
||||
{ ev_ide_finish_norelease, "ev_ide_finish_norelease" },
|
||||
|
||||
{ ev_ide_scan_device_int, "ev_ide_scan_device_int" },
|
||||
{ ev_ide_scan_device_int_cant_send, "ev_ide_scan_device_int_cant_send" },
|
||||
{ ev_ide_scan_device_int_keeps_busy, "ev_ide_scan_device_int_keeps_busy" },
|
||||
{ ev_ide_scan_device_int_found, "ev_ide_scan_device_int_found" },
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
static void disconnect_worker(ide_bus_info *bus, void *arg);
|
||||
@@ -96,15 +61,56 @@ is_queuable(ide_device_info *device, scsi_ccb *request)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scan_device(ide_bus_info *bus, int device)
|
||||
{
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
// currently, the SCSI bus manager doesn't block the
|
||||
// bus when a bus or device scan is issued, so we
|
||||
// have to use a SPC for that to be sure no one else
|
||||
// is accessing the device or bus concurrently
|
||||
schedule_synced_pc(bus, &bus->scan_bus_syncinfo, (void *)device);
|
||||
|
||||
acquire_sem(bus->scan_device_sem);
|
||||
}
|
||||
|
||||
|
||||
static uchar
|
||||
sim_scan_bus(ide_bus_info *bus)
|
||||
{
|
||||
int i;
|
||||
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
if (bus->disconnected)
|
||||
return SCSI_NO_HBA;
|
||||
|
||||
for (i = 0; i < bus->max_devices; ++i) {
|
||||
scan_device(bus, i);
|
||||
}
|
||||
|
||||
return SCSI_REQ_CMP;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sim_set_scsi_bus(ide_bus_info *bus, scsi_bus scsi)
|
||||
{
|
||||
bus->scsi_cookie = scsi;
|
||||
|
||||
// detect devices
|
||||
sim_scan_bus(bus);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
||||
{
|
||||
ide_device_info *device;
|
||||
bool queuable;
|
||||
ide_qrequest *qrequest;
|
||||
//ide_request_priv *priv;
|
||||
|
||||
// FAST_LOG3( bus->log, ev_ide_scsi_io, (uint32)request, request->target_id, request->target_lun );
|
||||
SHOW_FLOW(3, "%d:%d", request->target_id, request->target_lun);
|
||||
|
||||
if (bus->disconnected)
|
||||
@@ -156,9 +162,6 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
||||
++bus->num_running_reqs;
|
||||
bus->active_qrequest = qrequest;
|
||||
|
||||
FAST_LOGN(bus->log, ev_ide_scsi_io_exec, 4, (uint32)qrequest,
|
||||
(uint32)request, bus->num_running_reqs, device->num_running_reqs);
|
||||
|
||||
device->exec_io(device, qrequest);
|
||||
|
||||
return;
|
||||
@@ -166,7 +169,6 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
||||
err_inv_device:
|
||||
SHOW_ERROR(3, "Invalid device %d:%d",
|
||||
request->target_id, request->target_lun);
|
||||
FAST_LOG1(bus->log, ev_ide_scsi_io_invalid_device, (uint32)request);
|
||||
|
||||
request->subsys_status = SCSI_SEL_TIMEOUT;
|
||||
scsi->finished(request, 1);
|
||||
@@ -174,7 +176,6 @@ err_inv_device:
|
||||
|
||||
err_bus_busy:
|
||||
SHOW_FLOW0(3, "Bus busy");
|
||||
FAST_LOG1(bus->log, ev_ide_scsi_io_bus_busy, (uint32)request);
|
||||
|
||||
IDE_UNLOCK(bus);
|
||||
scsi->requeue(request, true);
|
||||
@@ -183,7 +184,6 @@ err_bus_busy:
|
||||
|
||||
err_device_busy:
|
||||
SHOW_FLOW0(3, "Device busy");
|
||||
FAST_LOG1(bus->log, ev_ide_scsi_io_device_busy, (uint32)request);
|
||||
|
||||
IDE_UNLOCK(bus);
|
||||
scsi->requeue(request, false);
|
||||
@@ -192,7 +192,6 @@ err_device_busy:
|
||||
|
||||
err_disconnected:
|
||||
SHOW_ERROR0(3, "No controller anymore");
|
||||
FAST_LOG1(bus->log, ev_ide_scsi_io_disconnected, (uint32)request);
|
||||
request->subsys_status = SCSI_NO_HBA;
|
||||
scsi->finished(request, 1);
|
||||
return;
|
||||
@@ -202,7 +201,7 @@ err_disconnected:
|
||||
static uchar
|
||||
sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
|
||||
{
|
||||
char *controller_name;
|
||||
const char *controller_name;
|
||||
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
@@ -228,7 +227,6 @@ sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
|
||||
if (pnp->get_attr_string(bus->node, SCSI_DESCRIPTION_CONTROLLER_NAME,
|
||||
&controller_name, true) == B_OK) {
|
||||
strlcpy(info->hba_vid, controller_name, SCSI_HBA_ID);
|
||||
free(controller_name);
|
||||
} else
|
||||
strlcpy(info->hba_vid, "", SCSI_HBA_ID);
|
||||
|
||||
@@ -241,39 +239,6 @@ sim_path_inquiry(ide_bus_info *bus, scsi_path_inquiry *info)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scan_device(ide_bus_info *bus, int device)
|
||||
{
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
// currently, the SCSI bus manager doesn't block the
|
||||
// bus when a bus or device scan is issued, so we
|
||||
// have to use a SPC for that to be sure no one else
|
||||
// is accessing the device or bus concurrently
|
||||
schedule_synced_pc(bus, &bus->scan_bus_syncinfo, (void *)device);
|
||||
|
||||
acquire_sem(bus->scan_device_sem);
|
||||
}
|
||||
|
||||
|
||||
static uchar
|
||||
sim_scan_bus(ide_bus_info *bus)
|
||||
{
|
||||
int i;
|
||||
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
if (bus->disconnected)
|
||||
return SCSI_NO_HBA;
|
||||
|
||||
for (i = 0; i < bus->max_devices; ++i) {
|
||||
scan_device(bus, i);
|
||||
}
|
||||
|
||||
return SCSI_REQ_CMP;
|
||||
}
|
||||
|
||||
|
||||
static uchar
|
||||
sim_abort(ide_bus_info *bus, scsi_ccb *ccb_to_abort)
|
||||
{
|
||||
@@ -371,7 +336,6 @@ finish_request(ide_qrequest *qrequest, bool resubmit)
|
||||
scsi_ccb *request;
|
||||
uint num_running;
|
||||
|
||||
FAST_LOG2(bus->log, ev_ide_finish_request, (uint32)qrequest, resubmit);
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
// save request first, as qrequest can be reused as soon as
|
||||
@@ -488,8 +452,6 @@ finish_norelease(ide_qrequest *qrequest, bool resubmit)
|
||||
ide_bus_info *bus = device->bus;
|
||||
uint num_requests;
|
||||
|
||||
FAST_LOG2(bus->log, ev_ide_finish_norelease, (uint32)qrequest, resubmit);
|
||||
|
||||
qrequest->running = false;
|
||||
qrequest->next = device->free_qrequests;
|
||||
device->free_qrequests = qrequest;
|
||||
@@ -544,9 +506,8 @@ finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
|
||||
|
||||
|
||||
static status_t
|
||||
ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
||||
ide_sim_init_bus(device_node *node, void **cookie)
|
||||
{
|
||||
device_node_handle parent;
|
||||
ide_bus_info *bus;
|
||||
bool dmaDisabled = false;
|
||||
status_t status;
|
||||
@@ -573,18 +534,9 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
||||
sprintf(bus->name, "ide_bus %d", (int)channel_id);
|
||||
}
|
||||
|
||||
#if 0
|
||||
bus->log = fast_log->start_log(bus->name, ide_events);
|
||||
if (bus->log == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
init_synced_pc(&bus->scan_bus_syncinfo, scan_device_worker);
|
||||
init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
|
||||
|
||||
bus->scsi_cookie = user_cookie;
|
||||
bus->state = ide_state_idle;
|
||||
bus->timer.bus = bus;
|
||||
bus->synced_pc_list = NULL;
|
||||
@@ -657,23 +609,18 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
||||
bus->can_CQ = false;
|
||||
}
|
||||
|
||||
parent = pnp->get_parent(node);
|
||||
|
||||
status = pnp->init_driver(parent, bus, (driver_module_info **)&bus->controller,
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, (driver_module_info **)&bus->controller,
|
||||
(void **)&bus->channel_cookie);
|
||||
|
||||
pnp->put_device_node(parent);
|
||||
if (status != B_OK)
|
||||
goto err5;
|
||||
bus->controller->set_channel(bus->channel_cookie, bus);
|
||||
pnp->put_node(parent);
|
||||
}
|
||||
|
||||
*cookie = bus;
|
||||
|
||||
// detect devices
|
||||
sim_scan_bus(bus);
|
||||
return B_OK;
|
||||
|
||||
err5:
|
||||
DELETE_BEN(&bus->status_report_ben);
|
||||
err4:
|
||||
delete_sem(bus->scan_device_sem);
|
||||
err3:
|
||||
@@ -683,10 +630,6 @@ err2:
|
||||
err1:
|
||||
uninit_synced_pc(&bus->scan_bus_syncinfo);
|
||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
||||
#ifdef USE_FAST_LOG
|
||||
fast_log->stop_log(bus->log);
|
||||
err:
|
||||
#endif
|
||||
free(bus);
|
||||
|
||||
return status;
|
||||
@@ -696,18 +639,12 @@ err:
|
||||
static status_t
|
||||
ide_sim_uninit_bus(ide_bus_info *bus)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(bus->node);
|
||||
|
||||
pnp->uninit_driver(parent);
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
DELETE_BEN(&bus->status_report_ben);
|
||||
delete_sem(bus->scan_device_sem);
|
||||
delete_sem(bus->sync_wait_sem);
|
||||
scsi->free_dpc(bus->irq_dpc);
|
||||
uninit_synced_pc(&bus->scan_bus_syncinfo);
|
||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
||||
// fast_log->stop_log(bus->log);
|
||||
|
||||
free(bus);
|
||||
|
||||
@@ -732,12 +669,8 @@ disconnect_worker(ide_bus_info *bus, void *arg)
|
||||
|
||||
|
||||
static void
|
||||
ide_sim_bus_removed(device_node_handle node, ide_bus_info *bus)
|
||||
ide_sim_bus_removed(ide_bus_info *bus)
|
||||
{
|
||||
if (bus == NULL)
|
||||
// driver not loaded - no manual intervention needed
|
||||
return;
|
||||
|
||||
// XPT must not issue further commands
|
||||
scsi->block_bus(bus->scsi_cookie);
|
||||
// make sure, we refuse all new commands
|
||||
@@ -852,11 +785,16 @@ scsi_sim_interface ide_sim_module = {
|
||||
|
||||
NULL, // supported devices
|
||||
NULL, // register node
|
||||
(status_t (*)(device_node_handle, void *, void **))ide_sim_init_bus,
|
||||
(status_t (*)(void *) ) ide_sim_uninit_bus,
|
||||
(void (*)(device_node_handle, void *)) ide_sim_bus_removed
|
||||
(status_t (*)(device_node *, void **)) ide_sim_init_bus,
|
||||
(void (*)(void *)) ide_sim_uninit_bus,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
(void (*)(void *)) ide_sim_bus_removed,
|
||||
NULL, // suspend
|
||||
NULL // resume
|
||||
},
|
||||
|
||||
(void (*)(scsi_sim_cookie, scsi_bus)) sim_set_scsi_bus,
|
||||
(void (*)(scsi_sim_cookie, scsi_ccb *)) sim_scsi_io,
|
||||
(uchar (*)(scsi_sim_cookie, scsi_ccb *)) sim_abort,
|
||||
(uchar (*)(scsi_sim_cookie, uchar, uchar)) sim_reset_device,
|
||||
|
||||
@@ -42,7 +42,6 @@ ide_dpc(void *arg)
|
||||
// in idle state, so we just check whether there is an active request,
|
||||
// which means that we were async_waiting
|
||||
if (bus->active_qrequest != NULL) {
|
||||
FAST_LOG1(bus->log, ev_ide_dpc_continue, (uint32)bus->active_qrequest);
|
||||
TRACE(("continue command\n"));
|
||||
|
||||
// cancel timeout
|
||||
@@ -66,8 +65,6 @@ ide_dpc(void *arg)
|
||||
// for service requests
|
||||
TRACE(("irq in idle mode - possible service request\n"));
|
||||
|
||||
FAST_LOG0(bus->log, ev_ide_dpc_service);
|
||||
|
||||
device = get_current_device(bus);
|
||||
if (device == NULL) {
|
||||
// got an interrupt from a non-existing device
|
||||
@@ -191,8 +188,6 @@ ide_irq_handler(ide_bus_info *bus, uint8 status)
|
||||
void
|
||||
cancel_irq_timeout(ide_bus_info *bus)
|
||||
{
|
||||
FAST_LOG0(bus->log, ev_ide_cancel_irq_timeout);
|
||||
|
||||
IDE_LOCK(bus);
|
||||
bus->state = ide_state_accessing;
|
||||
IDE_UNLOCK(bus);
|
||||
@@ -210,8 +205,6 @@ start_waiting(ide_bus_info *bus, uint32 timeout, int new_state)
|
||||
{
|
||||
int res;
|
||||
|
||||
FAST_LOG1(bus->log, ev_ide_start_waiting, new_state);
|
||||
|
||||
TRACE(("timeout = %u\n", (uint)timeout));
|
||||
|
||||
bus->state = new_state;
|
||||
@@ -260,8 +253,6 @@ ide_timeout_dpc(void *arg)
|
||||
|
||||
dprintf("ide: ide_timeout_dpc() bus %p, device %p\n", bus, device);
|
||||
|
||||
FAST_LOG1(bus->log, ev_ide_timeout_dpc, (uint32)qrequest);
|
||||
|
||||
// this also resets overlapped commands
|
||||
reset_device(device, qrequest);
|
||||
|
||||
@@ -287,8 +278,6 @@ ide_timeout(timer *arg)
|
||||
{
|
||||
ide_bus_info *bus = ((ide_bus_timer_info *)arg)->bus;
|
||||
|
||||
FAST_LOG0(bus->log, ev_ide_timeout);
|
||||
|
||||
TRACE(("ide_timeout(): %p\n", bus));
|
||||
|
||||
dprintf("ide: ide_timeout() bus %p\n", bus);
|
||||
|
||||
@@ -137,6 +137,7 @@ unlock_isa_dma_channel(long channel)
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
static status_t
|
||||
isa_init_driver(device_node_handle node, void *user_cookie, void **cookie)
|
||||
{
|
||||
@@ -202,6 +203,7 @@ isa_get_paths(const char ***_bus, const char ***_device)
|
||||
*_bus = kBus;
|
||||
*_device = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
static status_t
|
||||
@@ -246,6 +248,7 @@ static isa_module_info isa_module = {
|
||||
&unlock_isa_dma_channel
|
||||
};
|
||||
|
||||
#if 0
|
||||
static isa2_module_info isa2_module = {
|
||||
{
|
||||
{
|
||||
@@ -278,9 +281,10 @@ static isa2_module_info isa2_module = {
|
||||
|
||||
start_isa_dma,
|
||||
};
|
||||
#endif
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&isa_module,
|
||||
(module_info *)&isa2_module,
|
||||
// (module_info *)&isa2_module,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -8,15 +8,11 @@ KernelAddon pci :
|
||||
pci_fixup.cpp
|
||||
pci_info.cpp
|
||||
pci_module.c
|
||||
pci_device.c
|
||||
kernel_cpp.cpp
|
||||
pci_root.cpp
|
||||
pci_device.cpp
|
||||
: pci_arch_bus_manager.a
|
||||
;
|
||||
|
||||
SEARCH on [ FGristFiles
|
||||
kernel_cpp.cpp
|
||||
] = [ FDirName $(HAIKU_TOP) src system kernel util ] ;
|
||||
|
||||
# pci_info.cpp currently needs pcihdr.h so we make its path available and adds dependency
|
||||
ObjectHdrs [ FGristFiles pci_info$(SUFOBJ) ]
|
||||
: [ FDirName $(TARGET_COMMON_DEBUG_OBJECT_DIR) preferences devices ] ;
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
/*
|
||||
* Copyright 2007, François Revol <[email protected]>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_controller.h"
|
||||
|
||||
#include <arch_platform.h>
|
||||
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
|
||||
/*
|
||||
* As we don't have any real PCI bus in any of the supported m68k platforms,
|
||||
* we fake one, with hardcoded devices.
|
||||
* TODO: this doesn't make any sense, as we can't share any drivers, anyway.
|
||||
* We should better export dedicated bus managers for Zorro etc. busses on
|
||||
* these systems.
|
||||
* TODO: actually, there are several PCI boards for the Amiga.
|
||||
*/
|
||||
|
||||
#include "amiga/pci_amiga.h"
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
/*
|
||||
* Copyright 2007, François Revol <[email protected]>.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_io.h"
|
||||
#include "pci_priv.h"
|
||||
|
||||
|
||||
status_t
|
||||
pci_io_init()
|
||||
{
|
||||
|
||||
@@ -1,8 +1,14 @@
|
||||
/*
|
||||
* Copyright 2006, Ingo Weinhold. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_controller.h"
|
||||
|
||||
#include <arch_platform.h>
|
||||
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
|
||||
#include "openfirmware/pci_openfirmware.h"
|
||||
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
/*
|
||||
* Copyright 2006, Ingo Weinhold. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_io.h"
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
|
||||
|
||||
status_t
|
||||
pci_io_init()
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include "pci_priv.h"
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_private.h"
|
||||
#include "pci_bios.h"
|
||||
|
||||
|
||||
status_t
|
||||
pci_bios_init(void)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include "pci_irq.h"
|
||||
#include "pci_bios.h"
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
#include "pci_controller.h"
|
||||
#include "arch_cpu.h"
|
||||
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#include "pci_priv.h"
|
||||
/*
|
||||
* Copyright 2006, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "pci_private.h"
|
||||
#include "arch_cpu.h"
|
||||
|
||||
|
||||
status_t
|
||||
pci_io_init()
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#include "util/kernel_cpp.h"
|
||||
#include "pci_fixup.h"
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
#include "pci.h"
|
||||
|
||||
#define TRACE_CAP(x...) dprintf(x)
|
||||
|
||||
@@ -1,239 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
PCI bus manager
|
||||
|
||||
PCI device layer. There is one node per PCI device.
|
||||
The common root is the PCI root node.
|
||||
*/
|
||||
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "pci_priv.h"
|
||||
|
||||
|
||||
// information about one PCI device
|
||||
typedef struct pci_device_info {
|
||||
uint8 bus; // bus number
|
||||
uint8 device; // device number
|
||||
uint8 function; // function number
|
||||
device_node_handle node;
|
||||
pci_root_info *root; // parent, i.e. PCI root
|
||||
char name[32]; // name (for fast log)
|
||||
} pci_device_info;
|
||||
|
||||
|
||||
static uint8
|
||||
pci_device_read_io_8(pci_device_info *device, int mapped_io_addr)
|
||||
{
|
||||
return pci_read_io_8(mapped_io_addr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_io_8(pci_device_info *device, int mapped_io_addr, uint8 value)
|
||||
{
|
||||
pci_write_io_8(mapped_io_addr, value);
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
pci_device_read_io_16(pci_device_info *device, int mapped_io_addr)
|
||||
{
|
||||
return pci_read_io_16(mapped_io_addr);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_io_16(pci_device_info *device, int mapped_io_addr, uint16 value)
|
||||
{
|
||||
pci_write_io_16(mapped_io_addr, value);
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
pci_device_read_io_32(pci_device_info *device, int mapped_io_addr)
|
||||
{
|
||||
return pci_read_io_32(mapped_io_addr);
|
||||
}
|
||||
|
||||
static void
|
||||
pci_device_write_io_32(pci_device_info *device, int mapped_io_addr, uint32 value)
|
||||
{
|
||||
pci_write_io_32(mapped_io_addr, value);
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
pci_device_read_pci_config(pci_device_info *device, uint8 offset, uint8 size)
|
||||
{
|
||||
return device->root->read_pci_config(device->bus, device->device,
|
||||
device->function, offset, size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_pci_config(pci_device device, uint8 offset, uint8 size, uint32 value)
|
||||
{
|
||||
return device->root->write_pci_config(device->bus, device->device,
|
||||
device->function, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
static void *
|
||||
pci_device_ram_address(pci_device_info *device,
|
||||
const void *physical_address_in_system_memory)
|
||||
{
|
||||
return pci_ram_address(physical_address_in_system_memory);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_get_pci_info(pci_device device, struct pci_info *info)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (device == NULL || info == NULL)
|
||||
return B_BAD_VALUE;
|
||||
|
||||
// TODO: Implement more efficiently!
|
||||
for (i = 0; pci_get_nth_pci_info(i, info) == B_OK; i++) {
|
||||
if (device->bus == info->bus && device->device == info->device
|
||||
&& device->function == info->function) {
|
||||
return B_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return B_ENTRY_NOT_FOUND;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_find_capability(pci_device device, uchar cap_id, uchar *offset)
|
||||
{
|
||||
return pci_find_capability(device->bus, device->device,
|
||||
device->function, cap_id, offset);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_init_driver(device_node_handle node, void *user_cookie, void **cookie)
|
||||
{
|
||||
uint8 bus, deviceNumber, function;
|
||||
device_node_handle parent;
|
||||
pci_device_info *device;
|
||||
pci_root_info *root;
|
||||
status_t status;
|
||||
void *dummy;
|
||||
|
||||
if (gDeviceManager->get_attr_uint8(node, PCI_DEVICE_BUS_ITEM, &bus, false) != B_OK
|
||||
|| gDeviceManager->get_attr_uint8(node, PCI_DEVICE_DEVICE_ITEM, &deviceNumber, false) != B_OK
|
||||
|| gDeviceManager->get_attr_uint8(node, PCI_DEVICE_FUNCTION_ITEM, &function, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
parent = gDeviceManager->get_parent(node);
|
||||
|
||||
status = gDeviceManager->init_driver(parent, NULL, (driver_module_info **)&root, &dummy);
|
||||
if (status != B_OK)
|
||||
goto err;
|
||||
|
||||
device = malloc(sizeof(*device));
|
||||
if (device == NULL) {
|
||||
status = B_NO_MEMORY;
|
||||
goto err;
|
||||
}
|
||||
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
memset(device, 0, sizeof(*device));
|
||||
|
||||
device->bus = bus;
|
||||
device->device = deviceNumber;
|
||||
device->function = function;
|
||||
device->node = node;
|
||||
device->root = root;
|
||||
|
||||
snprintf(device->name, sizeof(device->name), "pci_device %u:%u:%u",
|
||||
bus, deviceNumber, function);
|
||||
|
||||
*cookie = device;
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
gDeviceManager->uninit_driver(parent);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_uninit_driver(void *cookie)
|
||||
{
|
||||
pci_device_info *device = cookie;
|
||||
device_node_handle parent;
|
||||
|
||||
parent = gDeviceManager->get_parent(device->node);
|
||||
gDeviceManager->uninit_driver(parent);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
free(device);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
pci_device_module_info gPCIDeviceModule = {
|
||||
{
|
||||
{
|
||||
PCI_DEVICE_MODULE_NAME,
|
||||
0,
|
||||
pci_device_std_ops
|
||||
},
|
||||
|
||||
NULL, // supports device
|
||||
NULL, // register device (our parent registered us)
|
||||
pci_device_init_driver,
|
||||
pci_device_uninit_driver,
|
||||
NULL, // removed
|
||||
NULL, // cleanup
|
||||
NULL, // get supported paths
|
||||
},
|
||||
|
||||
pci_device_read_io_8,
|
||||
pci_device_write_io_8,
|
||||
pci_device_read_io_16,
|
||||
pci_device_write_io_16,
|
||||
pci_device_read_io_32,
|
||||
pci_device_write_io_32,
|
||||
|
||||
pci_device_read_pci_config,
|
||||
pci_device_write_pci_config,
|
||||
|
||||
pci_device_ram_address,
|
||||
|
||||
pci_device_get_pci_info,
|
||||
|
||||
pci_device_find_capability
|
||||
};
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2002-2003, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "pci.h"
|
||||
#include "pci_private.h"
|
||||
|
||||
|
||||
// information about one PCI device
|
||||
struct pci_device {
|
||||
PCIDev* device;
|
||||
device_node* node;
|
||||
};
|
||||
|
||||
|
||||
static uint8
|
||||
pci_device_read_io_8(pci_device* device, addr_t mappedIOAddress)
|
||||
{
|
||||
return pci_read_io_8(mappedIOAddress);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_io_8(pci_device* device, addr_t mappedIOAddress,
|
||||
uint8 value)
|
||||
{
|
||||
pci_write_io_8(mappedIOAddress, value);
|
||||
}
|
||||
|
||||
|
||||
static uint16
|
||||
pci_device_read_io_16(pci_device* device, addr_t mappedIOAddress)
|
||||
{
|
||||
return pci_read_io_16(mappedIOAddress);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_io_16(pci_device* device, addr_t mappedIOAddress,
|
||||
uint16 value)
|
||||
{
|
||||
pci_write_io_16(mappedIOAddress, value);
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
pci_device_read_io_32(pci_device* device, addr_t mappedIOAddress)
|
||||
{
|
||||
return pci_read_io_32(mappedIOAddress);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_io_32(pci_device* device, addr_t mappedIOAddress, uint32 value)
|
||||
{
|
||||
pci_write_io_32(mappedIOAddress, value);
|
||||
}
|
||||
|
||||
|
||||
static uint32
|
||||
pci_device_read_pci_config(pci_device* device, uint8 offset, uint8 size)
|
||||
{
|
||||
return gPCI->ReadConfig(device->device, offset, size);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_write_pci_config(pci_device* device, uint8 offset, uint8 size,
|
||||
uint32 value)
|
||||
{
|
||||
gPCI->WriteConfig(device->device, offset, size, value);
|
||||
}
|
||||
|
||||
|
||||
static void*
|
||||
pci_device_ram_address(pci_device* device, const void* physicalAddress)
|
||||
{
|
||||
return pci_ram_address(physicalAddress);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_find_capability(pci_device* device, uint8 capID, uint8* offset)
|
||||
{
|
||||
return gPCI->FindCapability(device->device, capID, offset);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_get_pci_info(pci_device* device, struct pci_info* info)
|
||||
{
|
||||
if (info == NULL)
|
||||
return;
|
||||
|
||||
*info = device->device->info;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_init_driver(device_node* node, void** _cookie)
|
||||
{
|
||||
uint32 domain;
|
||||
uint8 bus, deviceNumber, function;
|
||||
if (gDeviceManager->get_attr_uint32(node, B_PCI_DEVICE_DOMAIN, &domain,
|
||||
false) != B_OK
|
||||
|| gDeviceManager->get_attr_uint8(node, B_PCI_DEVICE_BUS, &bus,
|
||||
false) != B_OK
|
||||
|| gDeviceManager->get_attr_uint8(node, B_PCI_DEVICE_DEVICE,
|
||||
&deviceNumber, false) != B_OK
|
||||
|| gDeviceManager->get_attr_uint8(node, B_PCI_DEVICE_FUNCTION,
|
||||
&function, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
pci_device* device = (pci_device*)malloc(sizeof(*device));
|
||||
if (device == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
device->device = gPCI->FindDevice(domain, bus, deviceNumber, function);
|
||||
device->node = node;
|
||||
|
||||
*_cookie = device;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_device_uninit_driver(void* cookie)
|
||||
{
|
||||
pci_device* device = (pci_device*)cookie;
|
||||
free(device);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_device_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
pci_device_module_info gPCIDeviceModule = {
|
||||
{
|
||||
{
|
||||
PCI_DEVICE_MODULE_NAME,
|
||||
0,
|
||||
pci_device_std_ops
|
||||
},
|
||||
|
||||
NULL, // supports device
|
||||
NULL, // register device (our parent registered us)
|
||||
pci_device_init_driver,
|
||||
pci_device_uninit_driver,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan devices
|
||||
NULL, // device removed
|
||||
},
|
||||
|
||||
pci_device_read_io_8,
|
||||
pci_device_write_io_8,
|
||||
pci_device_read_io_16,
|
||||
pci_device_write_io_16,
|
||||
pci_device_read_io_32,
|
||||
pci_device_write_io_32,
|
||||
|
||||
pci_device_ram_address,
|
||||
|
||||
pci_device_read_pci_config,
|
||||
pci_device_write_pci_config,
|
||||
pci_device_find_capability,
|
||||
pci_device_get_pci_info
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
** Copyright 2003-2006, Marcus Overhagen. All rights reserved.
|
||||
** Distributed under the terms of the MIT License.
|
||||
*/
|
||||
* Copyright 2003-2006, Marcus Overhagen. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <PCI.h>
|
||||
#include <string.h>
|
||||
#include "pci_info.h"
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
#include "pci.h"
|
||||
|
||||
#define PCI_VERBOSE 1
|
||||
|
||||
@@ -1,20 +1,14 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <device_manager.h>
|
||||
#include <bus_manager.h>
|
||||
#include <PCI.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "pci_priv.h"
|
||||
#include "pci_private.h"
|
||||
#include "pci_info.h"
|
||||
#include "pci.h"
|
||||
|
||||
@@ -22,139 +16,6 @@
|
||||
device_manager_info *gDeviceManager;
|
||||
|
||||
|
||||
// name of PCI root module
|
||||
#define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/device_v1"
|
||||
|
||||
|
||||
static float
|
||||
pci_module_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
{
|
||||
char *bus;
|
||||
|
||||
// make sure parent is really device root
|
||||
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false))
|
||||
return B_ERROR;
|
||||
|
||||
if (strcmp(bus, "root")) {
|
||||
free(bus);
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
free(bus);
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_module_register_device(device_node_handle parent)
|
||||
{
|
||||
|
||||
// XXX how do we handle this for PPC?
|
||||
// I/O port for PCI config space address
|
||||
#define PCI_CONFIG_ADDRESS 0xcf8
|
||||
|
||||
io_resource resources[2] = {
|
||||
{ IO_PORT, PCI_CONFIG_ADDRESS, 8 },
|
||||
{}
|
||||
};
|
||||
device_attr attrs[] = {
|
||||
// info about ourself
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: PCI_ROOT_MODULE_NAME }},
|
||||
// unique connection name
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "PCI" }},
|
||||
|
||||
// mark as being a bus
|
||||
{ PNP_BUS_IS_BUS, B_UINT8_TYPE, { ui8: 1 }},
|
||||
// search for device drivers once all devices are detected
|
||||
//{ PNP_BUS_DEFER_PROBE, B_UINT8_TYPE, { ui8: 1 }},
|
||||
// don't scan if loaded as we own I/O resources
|
||||
//{ PNP_DRIVER_NO_LIVE_RESCAN, B_UINT8_TYPE, { ui8: 1 }},
|
||||
{}
|
||||
};
|
||||
|
||||
io_resource_handle resourceHandles[2];
|
||||
device_node_handle node;
|
||||
// char *parent_type;
|
||||
status_t res;
|
||||
|
||||
res = gDeviceManager->acquire_io_resources(resources, resourceHandles);
|
||||
if (res < B_OK)
|
||||
return res;
|
||||
|
||||
return gDeviceManager->register_device(parent, attrs, resourceHandles, &node);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_module_register_child_devices(void *cookie)
|
||||
{
|
||||
device_node_handle node = cookie;
|
||||
pci_info device;
|
||||
int32 i = 0;
|
||||
|
||||
while (pci_get_nth_pci_info(i, &device) == B_OK) {
|
||||
device_attr attrs[] = {
|
||||
// info about device
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: PCI_DEVICE_MODULE_NAME }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string:
|
||||
"bus: %"PCI_DEVICE_BUS_ITEM
|
||||
"%, device: %"PCI_DEVICE_DEVICE_ITEM
|
||||
"%, function: %"PCI_DEVICE_FUNCTION_ITEM"%" }},
|
||||
|
||||
// location on PCI bus
|
||||
{ PCI_DEVICE_BUS_ITEM, B_UINT8_TYPE, { ui8: device.bus }},
|
||||
{ PCI_DEVICE_DEVICE_ITEM, B_UINT8_TYPE, { ui8: device.device }},
|
||||
{ PCI_DEVICE_FUNCTION_ITEM, B_UINT8_TYPE, { ui8: device.function }},
|
||||
|
||||
// info about the device
|
||||
{ PCI_DEVICE_VENDOR_ID_ITEM, B_UINT16_TYPE, { ui16: device.vendor_id }},
|
||||
{ PCI_DEVICE_DEVICE_ID_ITEM, B_UINT16_TYPE, { ui16: device.device_id }},
|
||||
{ PCI_DEVICE_SUBSYSTEM_ID_ITEM, B_UINT16_TYPE, { ui16: device.u.h0.subsystem_id }},
|
||||
{ PCI_DEVICE_SUBVENDOR_ID_ITEM, B_UINT16_TYPE, { ui16: device.u.h0.subsystem_vendor_id }},
|
||||
|
||||
{ PCI_DEVICE_BASE_CLASS_ID_ITEM, B_UINT8_TYPE, { ui8: device.class_base }},
|
||||
{ PCI_DEVICE_SUB_CLASS_ID_ITEM, B_UINT8_TYPE, { ui8: device.class_sub }},
|
||||
{ PCI_DEVICE_API_ID_ITEM, B_UINT8_TYPE, { ui8: device.class_api }},
|
||||
|
||||
// consumer specification
|
||||
{ B_DRIVER_BUS, B_STRING_TYPE, { string: "pci" }},
|
||||
{ B_DRIVER_MAPPING, B_STRING_TYPE, { string: "%"PCI_DEVICE_VENDOR_ID_ITEM "%|_%" PCI_DEVICE_DEVICE_ID_ITEM "%" }},
|
||||
|
||||
// ToDo: this is a hack
|
||||
{ B_DRIVER_DEVICE_TYPE, B_STRING_TYPE, { string: device.class_base == PCI_mass_storage ? "drivers/dev/disk" : "drivers/dev" }},
|
||||
{ NULL }
|
||||
};
|
||||
device_node_handle deviceNode;
|
||||
|
||||
gDeviceManager->register_device(node, attrs, NULL, &deviceNode);
|
||||
// currently, we don't care about loosing devices as we cannot do
|
||||
// anything about that but want to register remaining devices (if possible)
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
pci_module_get_paths(const char ***_bus, const char ***_device)
|
||||
{
|
||||
static const char *kBus[] = {"root", NULL};
|
||||
|
||||
*_bus = kBus;
|
||||
*_device = NULL;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_module_init(device_node_handle node, void *user_cookie, void **_cookie)
|
||||
{
|
||||
*_cookie = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
pci_old_module_std_ops(int32 op, ...)
|
||||
{
|
||||
@@ -184,25 +45,6 @@ pci_old_module_std_ops(int32 op, ...)
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
pci_module_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
{
|
||||
module_info *module;
|
||||
return get_module(B_PCI_MODULE_NAME, &module);
|
||||
// this serializes our module initialization
|
||||
}
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
return put_module(B_PCI_MODULE_NAME);
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
static struct pci_module_info sOldPCIModule = {
|
||||
{
|
||||
{
|
||||
@@ -225,32 +67,6 @@ static struct pci_module_info sOldPCIModule = {
|
||||
&pci_find_capability
|
||||
};
|
||||
|
||||
static struct pci_root_info sPCIModule = {
|
||||
{
|
||||
{
|
||||
{
|
||||
PCI_ROOT_MODULE_NAME,
|
||||
0,
|
||||
pci_module_std_ops
|
||||
},
|
||||
|
||||
pci_module_supports_device,
|
||||
pci_module_register_device,
|
||||
pci_module_init,
|
||||
NULL, // uninit
|
||||
NULL, // removed
|
||||
NULL, // cleanup
|
||||
pci_module_get_paths,
|
||||
},
|
||||
|
||||
pci_module_register_child_devices,
|
||||
NULL, // rescan bus
|
||||
},
|
||||
|
||||
&pci_read_config,
|
||||
&pci_write_config
|
||||
};
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager},
|
||||
{}
|
||||
@@ -258,7 +74,7 @@ module_dependency module_dependencies[] = {
|
||||
|
||||
module_info *modules[] = {
|
||||
(module_info *)&sOldPCIModule,
|
||||
(module_info *)&sPCIModule,
|
||||
(module_info *)&gPCIRootModule,
|
||||
(module_info *)&gPCIDeviceModule,
|
||||
NULL
|
||||
};
|
||||
|
||||
+6
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2005-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2003-2006, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
// name of PCI device modules
|
||||
#define PCI_DEVICE_MODULE_NAME "bus_managers/pci/device_v1"
|
||||
#define PCI_DEVICE_MODULE_NAME "bus_managers/pci/driver_v1"
|
||||
|
||||
extern device_manager_info *gDeviceManager;
|
||||
|
||||
@@ -22,8 +22,8 @@ extern device_manager_info *gDeviceManager;
|
||||
// PCI root.
|
||||
// apart from being the common parent of all PCI devices, it
|
||||
// manages access to PCI config space
|
||||
typedef struct pci_root_info {
|
||||
bus_module_info info;
|
||||
typedef struct pci_root_module_info {
|
||||
driver_module_info info;
|
||||
|
||||
// read PCI config space
|
||||
uint32 (*read_pci_config)(uint8 bus, uint8 device, uint8 function,
|
||||
@@ -32,8 +32,9 @@ typedef struct pci_root_info {
|
||||
// write PCI config space
|
||||
void (*write_pci_config)(uint8 bus, uint8 device, uint8 function,
|
||||
uint8 offset, uint8 size, uint32 value);
|
||||
} pci_root_info;
|
||||
} pci_root_module_info;
|
||||
|
||||
extern pci_root_module_info gPCIRootModule;
|
||||
extern pci_device_module_info gPCIDeviceModule;
|
||||
|
||||
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2005-2008, Axel Dörfler, [email protected]. All rights reserved.
|
||||
* Copyright 2003, Marcus Overhagen. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include <device_manager.h>
|
||||
#include <PCI.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "pci_private.h"
|
||||
#include "pci.h"
|
||||
|
||||
|
||||
// name of PCI root module
|
||||
#define PCI_ROOT_MODULE_NAME "bus_managers/pci/root/driver_v1"
|
||||
|
||||
|
||||
static float
|
||||
pci_root_supports_device(device_node* parent)
|
||||
{
|
||||
// make sure parent is really device root
|
||||
const char* bus;
|
||||
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
|
||||
return B_ERROR;
|
||||
|
||||
if (strcmp(bus, "root"))
|
||||
return 0.0;
|
||||
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_root_register_device(device_node* parent)
|
||||
{
|
||||
// XXX how do we handle this for PPC?
|
||||
// I/O port for PCI config space address
|
||||
#define PCI_CONFIG_ADDRESS 0xcf8
|
||||
|
||||
io_resource resources[2] = {
|
||||
{B_IO_PORT, PCI_CONFIG_ADDRESS, 8},
|
||||
{}
|
||||
};
|
||||
device_attr attrs[] = {
|
||||
{B_DEVICE_PRETTY_NAME, B_STRING_TYPE, {string: "PCI"}},
|
||||
{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_KEEP_DRIVER_LOADED}},
|
||||
{}
|
||||
};
|
||||
|
||||
return gDeviceManager->register_node(parent, PCI_ROOT_MODULE_NAME, attrs,
|
||||
resources, NULL);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_root_register_child_devices(void* cookie)
|
||||
{
|
||||
device_node* node = (device_node*)cookie;
|
||||
|
||||
pci_info info;
|
||||
for (int32 i = 0; pci_get_nth_pci_info(i, &info) == B_OK; i++) {
|
||||
int domain;
|
||||
uint8 bus;
|
||||
if (gPCI->ResolveVirtualBus(info.bus, &domain, &bus) != B_OK) {
|
||||
dprintf("FAILED!!!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
device_attr attrs[] = {
|
||||
// info about device
|
||||
{B_DEVICE_BUS, B_STRING_TYPE, {string: "pci"}},
|
||||
|
||||
// location on PCI bus
|
||||
{B_PCI_DEVICE_DOMAIN, B_UINT32_TYPE, {ui8: domain}},
|
||||
{B_PCI_DEVICE_BUS, B_UINT8_TYPE, {ui8: bus}},
|
||||
{B_PCI_DEVICE_DEVICE, B_UINT8_TYPE, {ui8: info.device}},
|
||||
{B_PCI_DEVICE_FUNCTION, B_UINT8_TYPE, {ui8: info.function}},
|
||||
|
||||
// info about the device
|
||||
{B_DEVICE_VENDOR_ID, B_UINT16_TYPE, { ui16: info.vendor_id }},
|
||||
{B_DEVICE_ID, B_UINT16_TYPE, { ui16: info.device_id }},
|
||||
|
||||
{B_DEVICE_TYPE, B_UINT16_TYPE, { ui16: info.class_base }},
|
||||
{B_DEVICE_SUB_TYPE, B_UINT16_TYPE, { ui16: info.class_sub }},
|
||||
{B_DEVICE_INTERFACE, B_UINT16_TYPE, { ui16: info.class_api }},
|
||||
|
||||
{B_DEVICE_FLAGS, B_UINT32_TYPE, {ui32: B_FIND_CHILD_ON_DEMAND}},
|
||||
{}
|
||||
};
|
||||
|
||||
gDeviceManager->register_node(node, PCI_DEVICE_MODULE_NAME, attrs,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
pci_root_init(device_node* node, void** _cookie)
|
||||
{
|
||||
*_cookie = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static int32
|
||||
pci_root_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
{
|
||||
module_info *module;
|
||||
return get_module(B_PCI_MODULE_NAME, &module);
|
||||
// this serializes our module initialization
|
||||
}
|
||||
|
||||
case B_MODULE_UNINIT:
|
||||
return put_module(B_PCI_MODULE_NAME);
|
||||
}
|
||||
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
|
||||
struct pci_root_module_info gPCIRootModule = {
|
||||
{
|
||||
{
|
||||
PCI_ROOT_MODULE_NAME,
|
||||
0,
|
||||
pci_root_std_ops
|
||||
},
|
||||
|
||||
pci_root_supports_device,
|
||||
pci_root_register_device,
|
||||
pci_root_init,
|
||||
NULL, // uninit
|
||||
pci_root_register_child_devices,
|
||||
NULL, // rescan devices
|
||||
NULL, // device removed
|
||||
},
|
||||
|
||||
&pci_read_config,
|
||||
&pci_write_config
|
||||
};
|
||||
@@ -3,54 +3,41 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open SCSI bus manager
|
||||
|
||||
Devfs entry for raw bus access.
|
||||
|
||||
This interface will go away. It's used by scsi_probe as
|
||||
long as we have no proper pnpfs where all the info can
|
||||
be retrieved from.
|
||||
*/
|
||||
//! Devfs entry for raw bus access.
|
||||
|
||||
#include "scsi_internal.h"
|
||||
#include <device/scsi_bus_raw_driver.h>
|
||||
#include <pnp_devfs.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <device/scsi_bus_raw_driver.h>
|
||||
|
||||
|
||||
// info about bus
|
||||
// (used both as bus cookie and file handle cookie)
|
||||
typedef struct bus_raw_info {
|
||||
scsi_bus_interface *interface;
|
||||
scsi_bus cookie;
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
} bus_raw_info;
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_bus_raw_init_device(device_node_handle node,
|
||||
void *userCookie, void **cookie)
|
||||
scsi_bus_raw_init(device_node *node, void **cookie)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(node);
|
||||
device_node *parent;
|
||||
bus_raw_info *bus;
|
||||
scsi_bus_interface *interface;
|
||||
scsi_bus bus_cookie;
|
||||
|
||||
status_t res = pnp->init_driver(parent, NULL,
|
||||
(driver_module_info **)&interface, (void **)&bus_cookie);
|
||||
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
bus = malloc(sizeof(*bus));
|
||||
bus->interface = interface;
|
||||
bus->cookie = bus_cookie;
|
||||
if (bus == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent,
|
||||
(driver_module_info **)&bus->interface, (void **)&bus->cookie);
|
||||
pnp->put_node(parent);
|
||||
|
||||
bus->node = node;
|
||||
|
||||
*cookie = bus;
|
||||
@@ -58,64 +45,19 @@ scsi_bus_raw_init_device(device_node_handle node,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_bus_raw_uninit_device(bus_raw_info *bus)
|
||||
static void
|
||||
scsi_bus_raw_uninit(void *bus)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(bus->node);
|
||||
status_t status = pnp->uninit_driver(parent);
|
||||
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
free(bus);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_bus_raw_probe(device_node_handle parent)
|
||||
{
|
||||
uint8 path_id;
|
||||
char *name;
|
||||
|
||||
if (pnp->get_attr_uint8(parent, SCSI_BUS_PATH_ID_ITEM, &path_id, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
// put that on heap to not overflow the limited kernel stack
|
||||
name = malloc(PATH_MAX + 1);
|
||||
if (name == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "bus/scsi/%d/bus_raw", path_id);
|
||||
|
||||
{
|
||||
device_attr attributes[] = {
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: SCSI_BUS_RAW_MODULE_NAME }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: PNP_DEVFS_MODULE_NAME }},
|
||||
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "bus_raw" }},
|
||||
|
||||
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
||||
{}
|
||||
};
|
||||
|
||||
device_node_handle node;
|
||||
status_t res = pnp->register_device(parent, attributes, NULL, &node);
|
||||
free(name);
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_bus_raw_open(bus_raw_info *bus, uint32 flags,
|
||||
bus_raw_info **handle_cookie)
|
||||
scsi_bus_raw_open(void *bus, const char *path, uint32 flags,
|
||||
void **handle_cookie)
|
||||
{
|
||||
*handle_cookie = bus;
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -129,14 +71,15 @@ scsi_bus_raw_close(void *cookie)
|
||||
static status_t
|
||||
scsi_bus_raw_free(void *cookie)
|
||||
{
|
||||
return B_ERROR;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_bus_raw_control(bus_raw_info *bus, uint32 op, void *data,
|
||||
size_t len)
|
||||
scsi_bus_raw_control(void *_cookie, int32 op, void *data, size_t length)
|
||||
{
|
||||
bus_raw_info *bus = _cookie;
|
||||
|
||||
switch (op) {
|
||||
case B_SCSI_BUS_RAW_RESET:
|
||||
return bus->interface->reset_bus(bus->cookie);
|
||||
@@ -167,40 +110,24 @@ scsi_bus_raw_write(void *cookie, off_t position,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pnp_devfs_driver_info scsi_bus_raw_module = {
|
||||
{
|
||||
struct device_module_info gSCSIBusRawModule = {
|
||||
{
|
||||
SCSI_BUS_RAW_MODULE_NAME,
|
||||
0,
|
||||
std_ops
|
||||
},
|
||||
|
||||
NULL,
|
||||
scsi_bus_raw_probe,
|
||||
scsi_bus_raw_init_device,
|
||||
(status_t (*) (void *))scsi_bus_raw_uninit_device,
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
|
||||
(status_t (*) (void *, uint32, void **))scsi_bus_raw_open,
|
||||
scsi_bus_raw_init,
|
||||
scsi_bus_raw_uninit,
|
||||
NULL, // removed
|
||||
|
||||
scsi_bus_raw_open,
|
||||
scsi_bus_raw_close,
|
||||
scsi_bus_raw_free,
|
||||
(status_t (*) (void *, uint32, void *, size_t))scsi_bus_raw_control,
|
||||
scsi_bus_raw_read,
|
||||
scsi_bus_raw_write
|
||||
scsi_bus_raw_write,
|
||||
NULL, // io
|
||||
scsi_bus_raw_control,
|
||||
NULL, // select
|
||||
NULL // deselect
|
||||
};
|
||||
|
||||
@@ -85,7 +85,7 @@ scsi_service_threadproc(void *arg)
|
||||
|
||||
|
||||
static scsi_bus_info *
|
||||
scsi_create_bus(device_node_handle node, uint8 path_id)
|
||||
scsi_create_bus(device_node *node, uint8 path_id)
|
||||
{
|
||||
scsi_bus_info *bus;
|
||||
int res;
|
||||
@@ -153,8 +153,6 @@ err2:
|
||||
err3:
|
||||
delete_sem(bus->start_service);
|
||||
err4:
|
||||
//scsi_destroy_device(bus->global_device);
|
||||
//err5:
|
||||
delete_sem(bus->scan_lun_lock);
|
||||
err6:
|
||||
free(bus);
|
||||
@@ -184,9 +182,8 @@ scsi_destroy_bus(scsi_bus_info *bus)
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
||||
scsi_init_bus(device_node *node, void **cookie)
|
||||
{
|
||||
device_node_handle parent;
|
||||
uint8 path_id;
|
||||
scsi_bus_info *bus;
|
||||
status_t res;
|
||||
@@ -244,15 +241,14 @@ scsi_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
||||
goto err;
|
||||
}
|
||||
|
||||
parent = pnp->get_parent(node);
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, (driver_module_info **)&bus->interface,
|
||||
(void **)&bus->sim_cookie);
|
||||
pnp->put_node(parent);
|
||||
|
||||
res = pnp->init_driver(parent, bus,
|
||||
(driver_module_info **)&bus->interface, (void **)&bus->sim_cookie);
|
||||
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
if (res != B_OK)
|
||||
goto err;
|
||||
bus->interface->set_scsi_bus(bus->sim_cookie, bus);
|
||||
}
|
||||
|
||||
// cache inquiry data
|
||||
scsi_inquiry_path(bus, &bus->inquiry_data);
|
||||
@@ -271,16 +267,10 @@ err:
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
scsi_uninit_bus(scsi_bus_info *bus)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(bus->node);
|
||||
pnp->uninit_driver(parent);
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
scsi_destroy_bus(bus);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -288,7 +278,6 @@ uchar
|
||||
scsi_inquiry_path(scsi_bus bus, scsi_path_inquiry *inquiry_data)
|
||||
{
|
||||
SHOW_FLOW(4, "path_id=%d", bus->path_id);
|
||||
|
||||
return bus->interface->path_inquiry(bus->sim_cookie, inquiry_data);
|
||||
}
|
||||
|
||||
@@ -304,7 +293,6 @@ static status_t
|
||||
scsi_bus_module_init(void)
|
||||
{
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
return init_temp_sg();
|
||||
}
|
||||
|
||||
@@ -315,7 +303,6 @@ scsi_bus_module_uninit(void)
|
||||
SHOW_INFO0(4, "");
|
||||
|
||||
uninit_temp_sg();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -336,7 +323,6 @@ std_ops(int32 op, ...)
|
||||
|
||||
|
||||
scsi_bus_interface scsi_bus_module = {
|
||||
{
|
||||
{
|
||||
{
|
||||
SCSI_BUS_MODULE_NAME,
|
||||
@@ -347,10 +333,8 @@ scsi_bus_interface scsi_bus_module = {
|
||||
NULL, // supported devices
|
||||
NULL, // register node
|
||||
scsi_init_bus,
|
||||
(status_t (*)(void *))scsi_uninit_bus,
|
||||
NULL
|
||||
},
|
||||
|
||||
(void (*)(void *))scsi_uninit_bus,
|
||||
(status_t (*)(void *))scsi_scan_bus,
|
||||
(status_t (*)(void *))scsi_scan_bus,
|
||||
NULL
|
||||
},
|
||||
|
||||
@@ -22,22 +22,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
static fast_log_event_type scsi_device_events[] = {
|
||||
{ ev_scsi_requeue_request, "ev_scsi_requeue_request" },
|
||||
{ ev_scsi_resubmit_request, "ev_scsi_resubmit_request" },
|
||||
{ ev_scsi_submit_autosense, "ev_scsi_submit_autosense" },
|
||||
{ ev_scsi_finish_autosense, "ev_scsi_finish_autosense" },
|
||||
{ ev_scsi_device_queue_overflow, "ev_scsi_device_queue_overflow" },
|
||||
{ ev_scsi_request_finished, "ev_scsi_request_finished" },
|
||||
{ ev_scsi_async_io, "ev_scsi_async_io" },
|
||||
{ ev_scsi_do_resend_request, "ev_scsi_do_resend_request" },
|
||||
{ ev_copy_sg_data, "ev_copy_sg_data" },
|
||||
{}
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
/** free autosense request of device */
|
||||
|
||||
static void
|
||||
@@ -74,11 +58,6 @@ scsi_free_device(scsi_device_info *device)
|
||||
DELETE_BEN(&device->dma_buffer_lock);
|
||||
delete_sem(device->dma_buffer_owner);
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
if (device->log != NULL)
|
||||
fast_log->stop_log(device->log);
|
||||
#endif
|
||||
|
||||
free(device);
|
||||
}
|
||||
|
||||
@@ -133,15 +112,9 @@ scsi_register_device(scsi_bus_info *bus, uchar target_id,
|
||||
char product_ident[sizeof( inquiry_data->product_ident ) + 1];
|
||||
char product_rev[sizeof( inquiry_data->product_rev ) + 1];
|
||||
device_attr attrs[] = {
|
||||
// info about driver
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: SCSI_DEVICE_MODULE_NAME }},
|
||||
|
||||
// connection
|
||||
{ SCSI_DEVICE_TARGET_ID_ITEM, B_UINT8_TYPE, { ui8: target_id }},
|
||||
{ SCSI_DEVICE_TARGET_LUN_ITEM, B_UINT8_TYPE, { ui8: target_lun }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string:
|
||||
"target: %"SCSI_DEVICE_TARGET_ID_ITEM
|
||||
"%, lun: %"SCSI_DEVICE_TARGET_LUN_ITEM"%" }},
|
||||
|
||||
// inquiry data (used for both identification and information)
|
||||
{ SCSI_DEVICE_INQUIRY_ITEM, B_RAW_TYPE,
|
||||
@@ -154,8 +127,7 @@ scsi_register_device(scsi_bus_info *bus, uchar target_id,
|
||||
{ SCSI_DEVICE_REVISION_ITEM, B_STRING_TYPE, { string: product_rev }},
|
||||
|
||||
// description of peripheral drivers
|
||||
{ B_DRIVER_BUS, B_STRING_TYPE, { string: "scsi" }},
|
||||
// ToDo: mapping is missing
|
||||
{ B_DEVICE_BUS, B_STRING_TYPE, { string: "scsi" }},
|
||||
|
||||
// extra restriction of maximum number of blocks per transfer
|
||||
{ B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: max_blocks }},
|
||||
@@ -166,16 +138,13 @@ scsi_register_device(scsi_bus_info *bus, uchar target_id,
|
||||
{ SCSI_DEVICE_MANUAL_AUTOSENSE_ITEM, B_UINT8_TYPE, { ui8: manual_autosense }},
|
||||
{ NULL }
|
||||
};
|
||||
device_node_handle node;
|
||||
status_t res;
|
||||
|
||||
beautify_string(vendor_ident, inquiry_data->vendor_ident, sizeof(vendor_ident));
|
||||
beautify_string(product_ident, inquiry_data->product_ident, sizeof(product_ident));
|
||||
beautify_string(product_rev, inquiry_data->product_rev, sizeof(product_rev));
|
||||
|
||||
res = pnp->register_device(bus->node, attrs, NULL, &node);
|
||||
if (res < 0)
|
||||
return res;
|
||||
return pnp->register_node(bus->node, SCSI_DEVICE_MODULE_NAME, attrs,
|
||||
NULL, NULL);
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
@@ -184,7 +153,7 @@ scsi_register_device(scsi_bus_info *bus, uchar target_id,
|
||||
|
||||
// create data structure for a device
|
||||
static scsi_device_info *
|
||||
scsi_create_device(device_node_handle node, scsi_bus_info *bus,
|
||||
scsi_create_device(device_node *node, scsi_bus_info *bus,
|
||||
int target_id, int target_lun)
|
||||
{
|
||||
scsi_device_info *device;
|
||||
@@ -289,15 +258,13 @@ err:
|
||||
#define SET_BIT(field, bit) field[(bit) >> 3] |= 1 << ((bit) & 7)
|
||||
|
||||
static status_t
|
||||
scsi_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
scsi_init_device(device_node *node, void **cookie)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(node);
|
||||
scsi_res_inquiry *inquiry_data = NULL;
|
||||
const scsi_res_inquiry *inquiry_data = NULL;
|
||||
uint8 target_id, target_lun, path_id;
|
||||
scsi_bus_info *bus;
|
||||
scsi_device_info *device;
|
||||
status_t res;
|
||||
driver_module_info *bus_interface;
|
||||
size_t inquiry_data_len;
|
||||
uint8 is_atapi, manual_autosense;
|
||||
|
||||
@@ -308,38 +275,26 @@ scsi_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
|| pnp->get_attr_uint8( node, SCSI_DEVICE_IS_ATAPI_ITEM, &is_atapi, false) != B_OK
|
||||
|| pnp->get_attr_uint8( node, SCSI_DEVICE_MANUAL_AUTOSENSE_ITEM, &manual_autosense, false) != B_OK
|
||||
|| pnp->get_attr_raw( node, SCSI_DEVICE_INQUIRY_ITEM,
|
||||
(void **)&inquiry_data, &inquiry_data_len, false) != B_OK
|
||||
(const void **)&inquiry_data, &inquiry_data_len, false) != B_OK
|
||||
|| inquiry_data_len != sizeof(*inquiry_data)) {
|
||||
res = B_ERROR;
|
||||
goto err1;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
res = pnp->init_driver(parent, NULL, &bus_interface,
|
||||
(void **)&bus);
|
||||
if (res != B_OK)
|
||||
goto err1;
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, NULL, (void **)&bus);
|
||||
pnp->put_node(parent);
|
||||
}
|
||||
|
||||
device = scsi_create_device(node, bus, target_id, target_lun);
|
||||
if (device == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err2;
|
||||
}
|
||||
if (device == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// never mind if there is no path - it might be an emulated controller
|
||||
path_id = -1;
|
||||
|
||||
pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &path_id, true);
|
||||
|
||||
sprintf(device->name, "scsi_device %u:%u:%u", path_id, target_id, target_lun);
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
device->log = fast_log->start_log(device->name, scsi_device_events);
|
||||
if (device->log == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err3;
|
||||
}
|
||||
#endif
|
||||
|
||||
device->inquiry_data = *inquiry_data;
|
||||
|
||||
// save restrictions
|
||||
@@ -365,14 +320,14 @@ scsi_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
if (device->manual_autosense) {
|
||||
if (scsi_create_autosense_request(device) != B_OK) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err3;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
// if this is an ATAPI device, we need an emulation buffer
|
||||
if (scsi_init_emulation_buffer(device, SCSI_ATAPI_BUFFER_SIZE) != B_OK) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err3;
|
||||
goto err;
|
||||
}
|
||||
|
||||
memset(device->emulation_map, 0, sizeof(device->emulation_map));
|
||||
@@ -385,41 +340,26 @@ scsi_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
SET_BIT(device->emulation_map, SCSI_OP_INQUIRY);
|
||||
}
|
||||
|
||||
free(inquiry_data);
|
||||
|
||||
*cookie = device;
|
||||
return B_OK;
|
||||
|
||||
err3:
|
||||
err:
|
||||
scsi_free_device(device);
|
||||
err2:
|
||||
pnp->uninit_driver(parent);
|
||||
err1:
|
||||
pnp->put_device_node(parent);
|
||||
free(inquiry_data);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
scsi_uninit_device(scsi_device_info *device)
|
||||
{
|
||||
device_node_handle parent = pnp->get_parent(device->node);
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
scsi_free_device(device);
|
||||
|
||||
// must unload parent at last as scsi_free_device access it
|
||||
pnp->uninit_driver(parent);
|
||||
pnp->put_device_node(parent);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
scsi_device_removed(device_node_handle node, scsi_device_info *device)
|
||||
scsi_device_removed(scsi_device_info *device)
|
||||
{
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
@@ -445,7 +385,7 @@ scsi_force_get_device(scsi_bus_info *bus, uchar target_id,
|
||||
{ SCSI_DEVICE_TARGET_LUN_ITEM, B_UINT8_TYPE, { ui8: target_lun }},
|
||||
{ NULL }
|
||||
};
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
status_t res;
|
||||
driver_module_info *driver_interface;
|
||||
scsi_device device;
|
||||
@@ -457,15 +397,16 @@ scsi_force_get_device(scsi_bus_info *bus, uchar target_id,
|
||||
|
||||
// check whether device registered already
|
||||
node = NULL;
|
||||
pnp->get_next_child_device(bus->node, &node, attrs);
|
||||
pnp->get_next_child_node(bus->node, attrs, &node);
|
||||
|
||||
SHOW_FLOW(3, "%p", node);
|
||||
|
||||
if (node != NULL) {
|
||||
// TODO: have a second look a this one!
|
||||
// there is one - get it
|
||||
res = pnp->init_driver(node, NULL, &driver_interface,
|
||||
(void **)&device);
|
||||
pnp->put_device_node(node);
|
||||
res = pnp->get_driver(node, &driver_interface, (void **)&device);
|
||||
if (res != B_OK)
|
||||
pnp->put_node(node);
|
||||
} else {
|
||||
// device doesn't exist yet - create a temporary one
|
||||
device = scsi_create_device(NULL, bus, target_id, target_lun);
|
||||
@@ -495,12 +436,13 @@ scsi_put_forced_device(scsi_device_info *device)
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (device->node != NULL)
|
||||
if (device->node != NULL) {
|
||||
// device is registered
|
||||
pnp->uninit_driver(device->node);
|
||||
else
|
||||
pnp->put_node(device->node);
|
||||
} else {
|
||||
// device is temporary
|
||||
scsi_free_device(device);
|
||||
}
|
||||
|
||||
release_sem(bus->scan_lun_lock);
|
||||
}
|
||||
@@ -563,8 +505,10 @@ scsi_device_interface scsi_device_module = {
|
||||
NULL, // supported devices
|
||||
NULL, // register node
|
||||
scsi_init_device,
|
||||
(status_t (*)(void *)) scsi_uninit_device,
|
||||
(void (*)(device_node_handle, void *)) scsi_device_removed
|
||||
(void (*)(void *)) scsi_uninit_device,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
(void (*)(void *)) scsi_device_removed
|
||||
},
|
||||
|
||||
scsi_alloc_ccb,
|
||||
|
||||
@@ -475,23 +475,6 @@ copy_sg_data(scsi_ccb *request, uint offset, uint allocation_length,
|
||||
else
|
||||
memcpy((void *)(virtualAddress + offset), buffer, bytes);
|
||||
|
||||
#if 0
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
char byte;
|
||||
|
||||
if (to_buffer)
|
||||
byte = ((char *)virtualAddress)[offset + i];
|
||||
else
|
||||
byte = ((char *)buffer)[i];
|
||||
|
||||
FAST_LOG1( request->device->log, ev_copy_sg_data, byte );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
vm_put_physical_page(virtualAddress);
|
||||
|
||||
buffer = (char *)buffer + bytes;
|
||||
|
||||
@@ -3,12 +3,6 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open SCSI bus manager
|
||||
|
||||
Main file
|
||||
*/
|
||||
|
||||
#include "scsi_internal.h"
|
||||
#include <pnp_devfs.h>
|
||||
|
||||
@@ -25,6 +19,6 @@ module_info *modules[] = {
|
||||
(module_info *)&scsi_for_sim_module,
|
||||
(module_info *)&scsi_bus_module,
|
||||
(module_info *)&scsi_device_module,
|
||||
(module_info *)&scsi_bus_raw_module,
|
||||
(module_info *)&gSCSIBusRawModule,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -12,33 +12,14 @@
|
||||
#include <scsi_cmds.h>
|
||||
#include <locked_pool.h>
|
||||
#include <device_manager.h>
|
||||
#include <fast_log.h>
|
||||
|
||||
#define debug_level_error 2
|
||||
#define debug_level_info 1
|
||||
#define debug_level_flow 0
|
||||
#define debug_level_error 4
|
||||
#define debug_level_info 4
|
||||
#define debug_level_flow 4
|
||||
|
||||
#define DEBUG_MSG_PREFIX "SCSI -- "
|
||||
|
||||
#include "wrapper.h"
|
||||
|
||||
//#define USE_FAST_LOG
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
#define FAST_LOG0( handle, event ) fast_log->log_0( handle, event )
|
||||
#define FAST_LOG1( handle, event, param ) fast_log->log_1( handle, event, param )
|
||||
#define FAST_LOG2( handle, event, param1, param2 ) fast_log->log_2( handle, event, param1, param2 )
|
||||
#define FAST_LOG3( handle, event, param1, param2, param3 ) fast_log->log_3( handle, event, param1, param2, param3 )
|
||||
#define FAST_LOGN( handle, event, num_params... ) fast_log->log_n( handle, event, num_params )
|
||||
#else
|
||||
#define FAST_LOG0( handle, event )
|
||||
#define FAST_LOG1( handle, event, param )
|
||||
#define FAST_LOG2( handle, event, param1, param2 )
|
||||
#define FAST_LOG3( handle, event, param1, param2, param3 )
|
||||
#define FAST_LOGN( handle, event, num_params... )
|
||||
#endif
|
||||
|
||||
|
||||
#include "scsi_lock.h"
|
||||
|
||||
|
||||
@@ -77,7 +58,7 @@
|
||||
#define SCSI_DEVICE_MANUAL_AUTOSENSE_ITEM "scsi/manual_autosense"
|
||||
|
||||
// name of internal scsi_bus_raw device driver
|
||||
#define SCSI_BUS_RAW_MODULE_NAME "bus_managers/scsi/bus/raw"
|
||||
#define SCSI_BUS_RAW_MODULE_NAME "bus_managers/scsi/bus/raw/device_v1"
|
||||
|
||||
// info about DPC
|
||||
typedef struct scsi_dpc_info {
|
||||
@@ -127,7 +108,7 @@ typedef struct scsi_bus_info {
|
||||
|
||||
locked_pool_cookie ccb_pool; // ccb pool (one per bus)
|
||||
|
||||
device_node_handle node; // pnp node of bus
|
||||
device_node *node; // pnp node of bus
|
||||
|
||||
dma_params dma_params; // dma restrictions of controller
|
||||
|
||||
@@ -191,17 +172,12 @@ typedef struct scsi_device_info {
|
||||
// and thus must be emulated
|
||||
|
||||
scsi_res_inquiry inquiry_data;
|
||||
device_node_handle node; // device node
|
||||
device_node *node; // device node
|
||||
|
||||
benaphore dma_buffer_lock; // lock between DMA buffer user and clean-up daemon
|
||||
sem_id dma_buffer_owner; // to be acquired before using DMA buffer
|
||||
dma_buffer dma_buffer; // DMA buffer
|
||||
|
||||
#ifdef USE_FAST_LOG
|
||||
fast_log_handle log; // fast log connection
|
||||
#endif
|
||||
char name[30]; // name for fast log entries
|
||||
|
||||
// buffer used for emulating SCSI commands
|
||||
char *buffer;
|
||||
physical_entry *buffer_sg_list;
|
||||
@@ -240,12 +216,11 @@ enum {
|
||||
|
||||
extern locked_pool_interface *locked_pool;
|
||||
extern device_manager_info *pnp;
|
||||
extern fast_log_info *fast_log;
|
||||
|
||||
extern scsi_for_sim_interface scsi_for_sim_module;
|
||||
extern scsi_bus_interface scsi_bus_module;
|
||||
extern scsi_device_interface scsi_device_module;
|
||||
extern struct pnp_devfs_driver_info scsi_bus_raw_module;
|
||||
extern struct device_module_info gSCSIBusRawModule;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -23,7 +23,6 @@ scsi_requeue_request(scsi_ccb *request, bool bus_overflow)
|
||||
scsi_device_info *device = request->device;
|
||||
bool was_servicable, start_retry;
|
||||
|
||||
FAST_LOG1(device->log, ev_scsi_requeue_request, (uint32)request);
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (request->state != SCSI_STATE_SENT) {
|
||||
@@ -86,7 +85,6 @@ scsi_resubmit_request(scsi_ccb *request)
|
||||
scsi_device_info *device = request->device;
|
||||
bool was_servicable, start_retry;
|
||||
|
||||
FAST_LOG1(device->log, ev_scsi_resubmit_request, (uint32)request);
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (request->state != SCSI_STATE_SENT) {
|
||||
@@ -141,7 +139,6 @@ submit_autosense(scsi_ccb *request)
|
||||
{
|
||||
scsi_device_info *device = request->device;
|
||||
|
||||
FAST_LOG1(device->log, ev_scsi_submit_autosense, (uint32)request);
|
||||
//snooze(1000000);
|
||||
|
||||
SHOW_FLOW0(3, "sending autosense");
|
||||
@@ -174,7 +171,6 @@ finish_autosense(scsi_device_info *device)
|
||||
scsi_ccb *orig_request = device->auto_sense_originator;
|
||||
scsi_ccb *request = device->auto_sense_request;
|
||||
|
||||
FAST_LOG2(device->log, ev_scsi_finish_autosense, (uint32)request, (uint32)orig_request);
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (request->subsys_status == SCSI_REQ_CMP) {
|
||||
@@ -209,8 +205,6 @@ scsi_device_queue_overflow(scsi_ccb *request, uint num_requests)
|
||||
scsi_device_info *device = request->device;
|
||||
int diff_max_slots;
|
||||
|
||||
FAST_LOG2(device->log, ev_scsi_device_queue_overflow, (uint32)request, num_requests);
|
||||
|
||||
// set maximum number of concurrent requests to number of
|
||||
// requests running when QUEUE FULL condition occurred - 1
|
||||
// (the "1" is the refused request)
|
||||
@@ -245,7 +239,6 @@ scsi_request_finished(scsi_ccb *request, uint num_requests)
|
||||
scsi_bus_info *bus = request->bus;
|
||||
bool was_servicable, start_service, do_autosense;
|
||||
|
||||
FAST_LOG2(device->log, ev_scsi_request_finished, (uint32)request, num_requests);
|
||||
SHOW_FLOW(3, "%p", request);
|
||||
|
||||
if (request->state != SCSI_STATE_SENT) {
|
||||
@@ -413,14 +406,6 @@ scsi_async_io(scsi_ccb *request)
|
||||
goto err;
|
||||
}
|
||||
|
||||
FAST_LOGN(request->device->log, ev_scsi_async_io,
|
||||
func_group_len[request->cdb[0] >> 5] + 2,
|
||||
(uint32)request, request->data_length,
|
||||
request->cdb[0], request->cdb[1], request->cdb[2], request->cdb[3],
|
||||
request->cdb[4], request->cdb[5], request->cdb[6], request->cdb[7],
|
||||
request->cdb[8], request->cdb[9], request->cdb[10], request->cdb[11],
|
||||
request->cdb[12], request->cdb[13], request->cdb[14], request->cdb[15]);
|
||||
|
||||
if (!request->device->valid) {
|
||||
SHOW_ERROR0( 3, "device got removed" );
|
||||
|
||||
@@ -636,8 +621,6 @@ scsi_check_exec_service(scsi_bus_info *bus)
|
||||
|
||||
RELEASE_BEN(&bus->mutex);
|
||||
|
||||
FAST_LOG1(request->device->log, ev_scsi_do_resend_request, (uint32)request);
|
||||
|
||||
request->state = SCSI_STATE_SENT;
|
||||
bus->interface->scsi_io(bus->sim_cookie, request);
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2006, Haiku, Inc. All RightsReserved.
|
||||
* Copyright 2004-2008, Haiku, Inc. All RightsReserved.
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "scsi_internal.h"
|
||||
#include "queuing.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -23,10 +24,10 @@
|
||||
*/
|
||||
|
||||
static status_t
|
||||
scsi_controller_added(device_node_handle parent)
|
||||
scsi_controller_added(device_node *parent)
|
||||
{
|
||||
char *controller_name;
|
||||
int path_id;
|
||||
const char *controller_name;
|
||||
int pathID;
|
||||
|
||||
SHOW_FLOW0(4, "");
|
||||
|
||||
@@ -36,52 +37,67 @@ scsi_controller_added(device_node_handle parent)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
path_id = pnp->create_id(SCSI_PATHID_GENERATOR);
|
||||
if (path_id < 0) {
|
||||
pathID = pnp->create_id(SCSI_PATHID_GENERATOR);
|
||||
if (pathID < 0) {
|
||||
dprintf("scsi: Cannot register SCSI controller %s - out of path IDs\n",
|
||||
controller_name);
|
||||
free(controller_name);
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
free(controller_name);
|
||||
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
// general information
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: SCSI_BUS_MODULE_NAME }},
|
||||
|
||||
// we are a bus
|
||||
{ PNP_BUS_IS_BUS, B_UINT8_TYPE, { ui8: 1 }},
|
||||
|
||||
// remember who we are
|
||||
// (could use the controller name, but probably some software would choke)
|
||||
{ SCSI_BUS_PATH_ID_ITEM, B_UINT8_TYPE, { ui8: path_id }},
|
||||
{ SCSI_BUS_PATH_ID_ITEM, B_UINT8_TYPE, { ui8: pathID }},
|
||||
|
||||
// tell PnP manager to clean up ID
|
||||
{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { string: SCSI_PATHID_GENERATOR }},
|
||||
{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: path_id }},
|
||||
|
||||
// tell internal bus raw driver to register bus' device in devfs
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: SCSI_BUS_RAW_MODULE_NAME }},
|
||||
{ NULL, 0 }
|
||||
// { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE, { string: SCSI_PATHID_GENERATOR }},
|
||||
// { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: path_id }},
|
||||
{}
|
||||
};
|
||||
|
||||
device_node_handle node;
|
||||
return pnp->register_node(parent, SCSI_BUS_MODULE_NAME, attrs, NULL,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_controller_init(device_node *node, void **_cookie)
|
||||
{
|
||||
*_cookie = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
scsi_controller_register_raw_device(void *_cookie)
|
||||
{
|
||||
device_node *node = (device_node *)_cookie;
|
||||
uint32 channel;
|
||||
uint8 pathID;
|
||||
char *name;
|
||||
|
||||
#if 1
|
||||
// TODO: this seems to cause a crash in some configurations, and needs to be investigated!
|
||||
// see bug #389 and #393.
|
||||
#if 0
|
||||
uint32 channel;
|
||||
|
||||
if (pnp->get_attr_uint32(parent, "ide/channel_id", &channel, true) == B_OK) {
|
||||
// TODO: check if the above is still true
|
||||
if (pnp->get_attr_uint32(node, "ide/channel_id", &channel, true) == B_OK) {
|
||||
// this is actually an IDE device, we don't need to publish
|
||||
// a bus device for those
|
||||
attrs[5].name = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
#endif
|
||||
pnp->get_attr_uint8(node, SCSI_BUS_PATH_ID_ITEM, &pathID, false);
|
||||
|
||||
return pnp->register_device(parent, attrs, NULL, &node);
|
||||
}
|
||||
// put that on heap to not overflow the limited kernel stack
|
||||
name = malloc(PATH_MAX + 1);
|
||||
if (name == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
snprintf(name, PATH_MAX + 1, "bus/scsi/%d/bus_raw", pathID);
|
||||
|
||||
return pnp->publish_device(node, name, SCSI_BUS_RAW_MODULE_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -110,9 +126,11 @@ scsi_for_sim_interface scsi_for_sim_module =
|
||||
|
||||
NULL, // supported devices
|
||||
scsi_controller_added,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
scsi_controller_init,
|
||||
NULL, // uninit
|
||||
scsi_controller_register_raw_device,
|
||||
NULL, // rescan
|
||||
NULL, // removed
|
||||
},
|
||||
|
||||
scsi_requeue_request,
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_flow
|
||||
# define debug_level_flow 3
|
||||
# define debug_level_flow 4
|
||||
#endif
|
||||
|
||||
#ifndef debug_level_info
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
#include "wrapper.h"
|
||||
|
||||
#define GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ide/generic_ide_pci/device_v1"
|
||||
#define GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME "busses/ide/generic_ide_pci/driver_v1"
|
||||
#define GENERIC_IDE_PCI_CHANNEL_MODULE_NAME "busses/ide/generic_ide_pci/channel/v1"
|
||||
|
||||
#define IDE_PCI_CONTROLLER_TYPE_NAME "ide pci controller"
|
||||
@@ -33,6 +33,13 @@ static ide_adapter_interface *ide_adapter;
|
||||
device_manager_info *pnp;
|
||||
|
||||
|
||||
static void
|
||||
set_channel(void *cookie, ide_channel channel)
|
||||
{
|
||||
ide_adapter->set_channel((ide_adapter_channel_info *)cookie, channel);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
write_command_block_regs(void *channel_cookie, ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
@@ -99,54 +106,52 @@ finish_dma(void *channel_cookie)
|
||||
|
||||
|
||||
static status_t
|
||||
init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
void **channel_cookie)
|
||||
init_channel(device_node *node, void **channel_cookie)
|
||||
{
|
||||
return ide_adapter->init_channel(node, ide_channel,
|
||||
return ide_adapter->init_channel(node,
|
||||
(ide_adapter_channel_info **)channel_cookie,
|
||||
sizeof(ide_adapter_channel_info), ide_adapter->inthand);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
uninit_channel(void *channel_cookie)
|
||||
{
|
||||
return ide_adapter->uninit_channel((ide_adapter_channel_info *)channel_cookie);
|
||||
ide_adapter->uninit_channel((ide_adapter_channel_info *)channel_cookie);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
channel_removed(device_node_handle node, void *channel_cookie)
|
||||
channel_removed(void *channel_cookie)
|
||||
{
|
||||
return ide_adapter->channel_removed(node, (ide_adapter_channel_info *)channel_cookie);
|
||||
ide_adapter->channel_removed((ide_adapter_channel_info *)channel_cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
init_controller(device_node_handle node, void *user_cookie,
|
||||
ide_adapter_controller_info **cookie)
|
||||
init_controller(device_node *node, ide_adapter_controller_info **cookie)
|
||||
{
|
||||
return ide_adapter->init_controller(node, user_cookie, cookie,
|
||||
return ide_adapter->init_controller(node, cookie,
|
||||
sizeof( ide_adapter_controller_info));
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
uninit_controller(ide_adapter_controller_info *controller)
|
||||
{
|
||||
return ide_adapter->uninit_controller(controller);
|
||||
ide_adapter->uninit_controller(controller);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
controller_removed(device_node_handle node, ide_adapter_controller_info *controller)
|
||||
controller_removed(ide_adapter_controller_info *controller)
|
||||
{
|
||||
return ide_adapter->controller_removed(node, controller);
|
||||
return ide_adapter->controller_removed(controller);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
probe_controller(device_node_handle parent)
|
||||
probe_controller(device_node *parent)
|
||||
{
|
||||
return ide_adapter->probe_controller(parent,
|
||||
GENERIC_IDE_PCI_CONTROLLER_MODULE_NAME, "generic_ide_pci",
|
||||
@@ -162,35 +167,22 @@ probe_controller(device_node_handle parent)
|
||||
|
||||
|
||||
static float
|
||||
supports_device(device_node_handle parent, bool *_noConnection)
|
||||
supports_device(device_node *parent)
|
||||
{
|
||||
char *bus;
|
||||
uint8 baseClass, subClass;
|
||||
const char *bus;
|
||||
uint16 baseClass, subClass;
|
||||
|
||||
// make sure parent is an PCI IDE mass storage host adapter device node
|
||||
if (pnp->get_attr_string(parent, B_DRIVER_BUS, &bus, false) != B_OK
|
||||
|| pnp->get_attr_uint8(parent, PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) != B_OK
|
||||
|| pnp->get_attr_uint8(parent, PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) != B_OK)
|
||||
return B_ERROR;
|
||||
if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false) != B_OK
|
||||
|| pnp->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass, false) != B_OK
|
||||
|| pnp->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass, false) != B_OK)
|
||||
return -1;
|
||||
|
||||
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage || subClass != PCI_ide) {
|
||||
free(bus);
|
||||
return 0.0;
|
||||
}
|
||||
if (strcmp(bus, "pci") || baseClass != PCI_mass_storage
|
||||
|| subClass != PCI_ide)
|
||||
return 0.0f;
|
||||
|
||||
free(bus);
|
||||
return 0.3;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
get_paths(const char ***_bus, const char ***_device)
|
||||
{
|
||||
static const char *kBus[] = { "pci", NULL };
|
||||
static const char *kDevice[] = { "drivers/dev/disk/ide", NULL };
|
||||
|
||||
*_bus = kBus;
|
||||
*_device = kDevice;
|
||||
return 0.3f;
|
||||
}
|
||||
|
||||
|
||||
@@ -227,13 +219,15 @@ static ide_controller_interface channel_interface = {
|
||||
|
||||
NULL, // supports device
|
||||
NULL, // register device
|
||||
(status_t (*)(device_node_handle, void *, void **))init_channel,
|
||||
(status_t (*)(device_node *, void **))init_channel,
|
||||
uninit_channel,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
channel_removed,
|
||||
NULL, // cleanup
|
||||
NULL, // get_paths
|
||||
},
|
||||
|
||||
&set_channel,
|
||||
|
||||
&write_command_block_regs,
|
||||
&read_command_block_regs,
|
||||
|
||||
@@ -258,11 +252,11 @@ static driver_module_info controller_interface = {
|
||||
|
||||
supports_device,
|
||||
probe_controller,
|
||||
(status_t (*)(device_node_handle, void *, void **)) init_controller,
|
||||
(status_t (*)(void *)) uninit_controller,
|
||||
(void (*)(device_node_handle, void *)) controller_removed,
|
||||
NULL, // cleanup
|
||||
get_paths,
|
||||
(status_t (*)(device_node *, void **)) init_controller,
|
||||
(void (*)(void *)) uninit_controller,
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
(void (*)(void *)) controller_removed,
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
|
||||
@@ -131,7 +131,7 @@ get_device_info(uint16 vendorID, uint16 deviceID, const char **name,
|
||||
|
||||
|
||||
static status_t
|
||||
register_sim(device_node_handle parent)
|
||||
register_sim(device_node *parent)
|
||||
{
|
||||
int32 id = gDeviceManager->create_id(AHCI_ID_GENERATOR);
|
||||
if (id < 0)
|
||||
@@ -139,25 +139,22 @@ register_sim(device_node_handle parent)
|
||||
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE,
|
||||
{ string: AHCI_SIM_MODULE_NAME }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE,
|
||||
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE,
|
||||
{ string: SCSI_FOR_SIM_MODULE_NAME }},
|
||||
|
||||
{ SCSI_DESCRIPTION_CONTROLLER_NAME, B_STRING_TYPE,
|
||||
{ string: AHCI_DEVICE_MODULE_NAME }},
|
||||
{ B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: 255 }},
|
||||
{ AHCI_ID_ITEM, B_UINT32_TYPE, { ui32: id }},
|
||||
{ PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE,
|
||||
{ string: AHCI_ID_GENERATOR }},
|
||||
{ PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }},
|
||||
// { PNP_MANAGER_ID_GENERATOR, B_STRING_TYPE,
|
||||
// { string: AHCI_ID_GENERATOR }},
|
||||
// { PNP_MANAGER_AUTO_ID, B_UINT32_TYPE, { ui32: id }},
|
||||
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
device_node_handle node;
|
||||
status_t status = gDeviceManager->register_device(parent, attrs, NULL,
|
||||
&node);
|
||||
status_t status = gDeviceManager->register_node(parent,
|
||||
AHCI_SIM_MODULE_NAME, attrs, NULL, NULL);
|
||||
if (status < B_OK)
|
||||
gDeviceManager->free_id(AHCI_ID_GENERATOR, id);
|
||||
|
||||
@@ -170,33 +167,38 @@ register_sim(device_node_handle parent)
|
||||
|
||||
|
||||
static float
|
||||
ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
ahci_supports_device(device_node *parent)
|
||||
{
|
||||
uint8 baseClass, subClass, classAPI;
|
||||
uint16 baseClass, subClass, classAPI;
|
||||
uint16 vendorID;
|
||||
uint16 deviceID;
|
||||
bool isPCI;
|
||||
const char *name;
|
||||
char *bus;
|
||||
const char *bus;
|
||||
|
||||
TRACE("ahci_supports_device\n");
|
||||
|
||||
if (gDeviceManager->get_attr_string(parent, B_DRIVER_BUS, &bus, false) < B_OK)
|
||||
return 0.0f;
|
||||
isPCI = !strcmp(bus, "pci");
|
||||
free(bus);
|
||||
if (!isPCI)
|
||||
if (gDeviceManager->get_attr_string(parent, B_DEVICE_BUS, &bus, false)
|
||||
< B_OK)
|
||||
return 0.0f;
|
||||
|
||||
if (gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BASE_CLASS_ID_ITEM, &baseClass, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_SUB_CLASS_ID_ITEM, &subClass, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_API_ID_ITEM, &classAPI, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_VENDOR_ID_ITEM, &vendorID, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, PCI_DEVICE_DEVICE_ID_ITEM, &deviceID, false) < B_OK)
|
||||
if (strcmp(bus, "pci"))
|
||||
return 0.0f;
|
||||
|
||||
if (gDeviceManager->get_attr_uint16(parent, B_DEVICE_TYPE, &baseClass,
|
||||
false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_SUB_TYPE, &subClass,
|
||||
false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_INTERFACE,
|
||||
&classAPI, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_VENDOR_ID,
|
||||
&vendorID, false) < B_OK
|
||||
|| gDeviceManager->get_attr_uint16(parent, B_DEVICE_ID, &deviceID,
|
||||
false) < B_OK)
|
||||
return 0.0f;
|
||||
|
||||
if (get_device_info(vendorID, deviceID, &name, NULL) < B_OK) {
|
||||
if (baseClass != PCI_mass_storage || subClass != PCI_sata || classAPI != PCI_sata_ahci)
|
||||
if (baseClass != PCI_mass_storage || subClass != PCI_sata
|
||||
|| classAPI != PCI_sata_ahci)
|
||||
return 0.0f;
|
||||
TRACE("generic AHCI controller found! vendor 0x%04x, device 0x%04x\n", vendorID, deviceID);
|
||||
return 0.8f;
|
||||
@@ -205,23 +207,15 @@ ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
if (vendorID == PCI_VENDOR_JMICRON) {
|
||||
// JMicron uses the same device ID for SATA and PATA controllers,
|
||||
// check if BAR5 exists to determine if it's a AHCI controller
|
||||
uint8 bus, device, function;
|
||||
pci_device_module_info *pci;
|
||||
pci_device *device;
|
||||
pci_info info;
|
||||
pci_module_info *pci;
|
||||
size_t size = 0;
|
||||
int i;
|
||||
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_BUS_ITEM, &bus, false);
|
||||
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_DEVICE_ITEM, &device, false);
|
||||
gDeviceManager->get_attr_uint8(parent, PCI_DEVICE_FUNCTION_ITEM, &function, false);
|
||||
get_module(B_PCI_MODULE_NAME, (module_info **)&pci);
|
||||
for (i = 0; B_OK == pci->get_nth_pci_info(i, &info); i++) {
|
||||
if (info.bus == bus && info.device == device && info.function == function) {
|
||||
size = info.u.h0.base_register_sizes[5];
|
||||
break;
|
||||
}
|
||||
}
|
||||
put_module(B_PCI_MODULE_NAME);
|
||||
if (size == 0)
|
||||
|
||||
gDeviceManager->get_driver(parent, (driver_module_info **)&pci,
|
||||
(void **)&device);
|
||||
pci->get_pci_info(device, &info);
|
||||
|
||||
if (info.u.h0.base_register_sizes[5] == 0)
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
@@ -231,15 +225,9 @@ ahci_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_register_device(device_node_handle parent)
|
||||
ahci_register_device(device_node *parent)
|
||||
{
|
||||
device_node_handle node;
|
||||
status_t status;
|
||||
|
||||
device_attr attrs[] = {
|
||||
// info about ourself and our consumer
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: AHCI_DEVICE_MODULE_NAME }},
|
||||
|
||||
{ SCSI_DEVICE_MAX_TARGET_COUNT, B_UINT32_TYPE,
|
||||
{ ui32: 33 }},
|
||||
|
||||
@@ -261,86 +249,44 @@ ahci_register_device(device_node_handle parent)
|
||||
|
||||
TRACE("ahci_register_device\n");
|
||||
|
||||
status = gDeviceManager->register_device(parent, attrs,
|
||||
NULL, &node);
|
||||
if (status < B_OK)
|
||||
return status;
|
||||
return gDeviceManager->register_node(parent, AHCI_DEVICE_MODULE_NAME,
|
||||
attrs, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_init_driver(device_node *node, void **_cookie)
|
||||
{
|
||||
TRACE("ahci_init_driver\n");
|
||||
*_cookie = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ahci_uninit_driver(void *cookie)
|
||||
{
|
||||
TRACE("ahci_uninit_driver, cookie %p\n", cookie);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_register_child_devices(void *cookie)
|
||||
{
|
||||
device_node *node = (device_node *)cookie;
|
||||
|
||||
// TODO: register SIM for every controller we find!
|
||||
return register_sim(node);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_init_driver(device_node_handle node, void *userCookie, void **_cookie)
|
||||
{
|
||||
pci_device *_userCookie = userCookie;
|
||||
pci_device pciDevice;
|
||||
device_node_handle parent;
|
||||
status_t status;
|
||||
|
||||
TRACE("ahci_init_driver, userCookie %p\n", userCookie);
|
||||
|
||||
parent = gDeviceManager->get_parent(node);
|
||||
|
||||
// initialize parent (the bus) to get the PCI interface and device
|
||||
status = gDeviceManager->init_driver(parent, NULL,
|
||||
(driver_module_info **)&gPCI, (void **)&pciDevice);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
TRACE("ahci_init_driver: gPCI %p, pciDevice %p\n", gPCI, pciDevice);
|
||||
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
*_userCookie = pciDevice;
|
||||
*_cookie = node;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_uninit_driver(void *cookie)
|
||||
{
|
||||
device_node_handle node = cookie;
|
||||
device_node_handle parent;
|
||||
|
||||
TRACE("ahci_uninit_driver, cookie %p\n", cookie);
|
||||
|
||||
parent = gDeviceManager->get_parent(node);
|
||||
gDeviceManager->uninit_driver(parent);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ahci_device_removed(device_node_handle node, void *cookie)
|
||||
ahci_device_removed(void *cookie)
|
||||
{
|
||||
TRACE("ahci_device_removed, cookie %p\n", cookie);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ahci_device_cleanup(device_node_handle node)
|
||||
{
|
||||
TRACE("ahci_device_cleanup\n");
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ahci_get_supported_paths(const char ***_busses, const char ***_devices)
|
||||
{
|
||||
static const char *kBus[] = { "pci", NULL };
|
||||
static const char *kDevice[] = { "drivers/dev/disk/sata", NULL };
|
||||
|
||||
TRACE("ahci_get_supported_paths\n");
|
||||
|
||||
*_busses = kBus;
|
||||
*_devices = kDevice;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops(int32 op, ...)
|
||||
{
|
||||
@@ -365,15 +311,14 @@ driver_module_info sAHCIDevice = {
|
||||
ahci_register_device,
|
||||
ahci_init_driver,
|
||||
ahci_uninit_driver,
|
||||
ahci_device_removed,
|
||||
ahci_device_cleanup,
|
||||
ahci_get_supported_paths,
|
||||
ahci_register_child_devices,
|
||||
NULL, // rescan
|
||||
ahci_device_removed
|
||||
};
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&gDeviceManager },
|
||||
// { B_PCI_MODULE_NAME, (module_info **)&gPCI },
|
||||
{ SCSI_FOR_SIM_MODULE_NAME, (module_info **)&gSCSI },
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
#define FLOW(a...) dprintf("ahci: " a)
|
||||
|
||||
|
||||
AHCIController::AHCIController(device_node_handle node, pci_device_info *device)
|
||||
AHCIController::AHCIController(device_node *node, pci_device *device)
|
||||
: fNode(node)
|
||||
, fPCIDevice(device)
|
||||
, fPCIVendorID(0xffff)
|
||||
@@ -48,11 +48,7 @@ status_t
|
||||
AHCIController::Init()
|
||||
{
|
||||
pci_info pciInfo;
|
||||
|
||||
if (gPCI->get_pci_info(fPCIDevice, &pciInfo) < B_OK) {
|
||||
dprintf("AHCIController::Init ERROR: getting PCI info failed!\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
gPCI->get_pci_info(fPCIDevice, &pciInfo);
|
||||
|
||||
fPCIVendorID = pciInfo.vendor_id;
|
||||
fPCIDeviceID = pciInfo.device_id;
|
||||
@@ -231,7 +227,6 @@ AHCIController::Uninit()
|
||||
// well...
|
||||
remove_io_interrupt_handler(fIRQ, Interrupt, this);
|
||||
|
||||
|
||||
delete_area(fRegsArea);
|
||||
|
||||
// --- Instance check workaround begin
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
class AHCIController {
|
||||
public:
|
||||
AHCIController(device_node_handle node,
|
||||
pci_device_info *pciDevice);
|
||||
AHCIController(device_node *node, pci_device *pciDevice);
|
||||
~AHCIController();
|
||||
|
||||
status_t Init();
|
||||
@@ -25,20 +24,20 @@ public:
|
||||
uchar ResetDevice(uchar targetID, uchar targetLUN);
|
||||
void GetRestrictions(uchar targetID, bool *isATAPI, bool *noAutoSense, uint32 *maxBlocks);
|
||||
|
||||
device_node_handle DeviceNode() { return fNode; }
|
||||
device_node * DeviceNode() { return fNode; }
|
||||
|
||||
private:
|
||||
bool IsDevicePresent(uint device);
|
||||
status_t ResetController();
|
||||
void FlushPostedWrites();
|
||||
|
||||
static int32 Interrupt(void *data);
|
||||
static int32 Interrupt(void *data);
|
||||
|
||||
friend class AHCIPort;
|
||||
|
||||
private:
|
||||
device_node_handle fNode;
|
||||
pci_device_info* fPCIDevice;
|
||||
device_node * fNode;
|
||||
pci_device * fPCIDevice;
|
||||
uint16 fPCIVendorID;
|
||||
uint16 fPCIDeviceID;
|
||||
uint32 fFlags;
|
||||
|
||||
@@ -22,6 +22,12 @@ scsi_for_sim_interface *gSCSI;
|
||||
// #pragma mark - SIM module interface
|
||||
|
||||
|
||||
static void
|
||||
ahci_set_scsi_bus(scsi_sim_cookie cookie, scsi_bus bus)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
//! execute request
|
||||
static void
|
||||
ahci_scsi_io(scsi_sim_cookie cookie, scsi_ccb *request)
|
||||
@@ -122,30 +128,26 @@ ahci_ioctl(scsi_sim_cookie cookie, uint8 targetID, uint32 op, void *buffer,
|
||||
|
||||
|
||||
static status_t
|
||||
ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie)
|
||||
ahci_sim_init_bus(device_node *node, void **_cookie)
|
||||
{
|
||||
pci_device_info *pciDevice;
|
||||
device_node_handle parent;
|
||||
AHCIController *controller;
|
||||
status_t status;
|
||||
TRACE("ahci_sim_init_bus\n");
|
||||
|
||||
TRACE("ahci_sim_init_bus: userCookie %p\n", userCookie);
|
||||
// get the PCI device from our parent's parent
|
||||
device_node *parent = gDeviceManager->get_parent_node(node);
|
||||
device_node *pciParent = gDeviceManager->get_parent_node(parent);
|
||||
gDeviceManager->put_node(parent);
|
||||
|
||||
TRACE("ahci_sim_init_bus: gPCI %p\n", gPCI);
|
||||
|
||||
// initialize parent (the bus) to get the PCI device
|
||||
parent = gDeviceManager->get_parent(node);
|
||||
status = gDeviceManager->init_driver(parent, &pciDevice, NULL, NULL);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
pci_device *pciDevice;
|
||||
gDeviceManager->get_driver(pciParent, NULL, (void **)&pciDevice);
|
||||
gDeviceManager->put_node(pciParent);
|
||||
|
||||
TRACE("ahci_sim_init_bus: pciDevice %p\n", pciDevice);
|
||||
|
||||
controller = new(std::nothrow) AHCIController(node, pciDevice);
|
||||
AHCIController *controller = new(std::nothrow) AHCIController(node,
|
||||
pciDevice);
|
||||
if (!controller)
|
||||
return B_NO_MEMORY;
|
||||
status = controller->Init();
|
||||
status_t status = controller->Init();
|
||||
if (status < B_OK) {
|
||||
delete controller;
|
||||
return status;
|
||||
@@ -157,27 +159,19 @@ ahci_sim_init_bus(device_node_handle node, void *userCookie, void **_cookie)
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
ahci_sim_uninit_bus(void *cookie)
|
||||
{
|
||||
TRACE("ahci_sim_uninit_bus, cookie %p\n", cookie);
|
||||
AHCIController *controller = static_cast<AHCIController *>(cookie);
|
||||
|
||||
device_node_handle parent = gDeviceManager->get_parent(
|
||||
controller->DeviceNode());
|
||||
|
||||
controller->Uninit();
|
||||
delete controller;
|
||||
|
||||
gDeviceManager->uninit_driver(parent);
|
||||
gDeviceManager->put_device_node(parent);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ahci_sim_bus_removed(device_node_handle node, void *cookie)
|
||||
ahci_sim_bus_removed(void *cookie)
|
||||
{
|
||||
TRACE("ahci_sim_bus_removed, cookie %p\n", cookie);
|
||||
}
|
||||
@@ -208,10 +202,11 @@ scsi_sim_interface gAHCISimInterface = {
|
||||
NULL, // register node
|
||||
ahci_sim_init_bus,
|
||||
ahci_sim_uninit_bus,
|
||||
ahci_sim_bus_removed,
|
||||
NULL, // device cleanup
|
||||
NULL, // get supported paths
|
||||
NULL, // register child devices
|
||||
NULL, // rescan
|
||||
ahci_sim_bus_removed
|
||||
},
|
||||
ahci_set_scsi_bus,
|
||||
ahci_scsi_io,
|
||||
ahci_abort_io,
|
||||
ahci_reset_device,
|
||||
@@ -222,4 +217,3 @@ scsi_sim_interface gAHCISimInterface = {
|
||||
ahci_get_restrictions,
|
||||
ahci_ioctl
|
||||
};
|
||||
|
||||
|
||||
@@ -17,75 +17,57 @@
|
||||
|
||||
|
||||
status_t
|
||||
das_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
das_init_device(device_node *node, void **cookie)
|
||||
{
|
||||
das_device_info *device;
|
||||
status_t res;
|
||||
scsi_ccb *request;
|
||||
status_t status;
|
||||
uint8 removable;
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
status = pnp->get_attr_uint8(node, "removable",
|
||||
&removable, false);
|
||||
if (status != B_OK)
|
||||
return status;
|
||||
|
||||
device = (das_device_info *)malloc(sizeof(*device));
|
||||
if (device == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(device, 0, sizeof(*device));
|
||||
|
||||
device->block_io_device = user_cookie;
|
||||
device->node = node;
|
||||
device->removable = removable;
|
||||
|
||||
res = pnp->get_attr_uint8(node, "removable",
|
||||
&device->removable, false);
|
||||
if (res != B_OK)
|
||||
goto err1;
|
||||
|
||||
// register it everywhere
|
||||
res = pnp->init_driver(pnp->get_parent(node), NULL, (driver_module_info **)&device->scsi,
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, (driver_module_info **)&device->scsi,
|
||||
(void **)&device->scsi_device);
|
||||
if (res != B_OK)
|
||||
goto err2;
|
||||
|
||||
res = scsi_periph->register_device((periph_device_cookie)device, &callbacks,
|
||||
device->scsi_device, device->scsi, device->node, device->removable,
|
||||
&device->scsi_periph_device);
|
||||
if (res != B_OK)
|
||||
goto err3;
|
||||
|
||||
// and get (initial) capacity
|
||||
request = device->scsi->alloc_ccb(device->scsi_device);
|
||||
if (request == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err4;
|
||||
pnp->put_node(parent);
|
||||
}
|
||||
|
||||
scsi_periph->check_capacity(device->scsi_periph_device, request);
|
||||
|
||||
device->scsi->free_ccb(request);
|
||||
status = scsi_periph->register_device((periph_device_cookie)device,
|
||||
&callbacks, device->scsi_device, device->scsi, device->node,
|
||||
device->removable, &device->scsi_periph_device);
|
||||
if (status != B_OK) {
|
||||
free(device);
|
||||
return status;
|
||||
}
|
||||
|
||||
SHOW_FLOW0(3, "done");
|
||||
|
||||
*cookie = device;
|
||||
return B_OK;
|
||||
|
||||
err4:
|
||||
scsi_periph->unregister_device(device->scsi_periph_device);
|
||||
err3:
|
||||
pnp->uninit_driver(pnp->get_parent(node));
|
||||
err2:
|
||||
err1:
|
||||
free(device);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
das_uninit_device(das_device_info *device)
|
||||
void
|
||||
das_uninit_device(void *_cookie)
|
||||
{
|
||||
scsi_periph->unregister_device(device->scsi_periph_device);
|
||||
pnp->uninit_driver(pnp->get_parent(device->node));
|
||||
free(device);
|
||||
das_device_info *device = (das_device_info *)_cookie;
|
||||
|
||||
return B_OK;
|
||||
scsi_periph->unregister_device(device->scsi_periph_device);
|
||||
free(device);
|
||||
}
|
||||
|
||||
|
||||
@@ -95,27 +77,27 @@ das_uninit_device(das_device_info *device)
|
||||
*/
|
||||
|
||||
status_t
|
||||
das_device_added(device_node_handle node)
|
||||
das_device_added(device_node *node)
|
||||
{
|
||||
scsi_res_inquiry *device_inquiry = NULL;
|
||||
const scsi_res_inquiry *deviceInquiry = NULL;
|
||||
uint8 device_type;
|
||||
size_t inquiry_len;
|
||||
char *name;
|
||||
size_t inquiryLength;
|
||||
uint32 max_blocks;
|
||||
|
||||
// check whether it's really a Direct Access Device
|
||||
if (pnp->get_attr_uint8(node, SCSI_DEVICE_TYPE_ITEM, &device_type, true) != B_OK
|
||||
|| device_type != scsi_dev_direct_access)
|
||||
goto err;
|
||||
return B_ERROR;
|
||||
|
||||
// get inquiry data
|
||||
if (pnp->get_attr_raw(node, SCSI_DEVICE_INQUIRY_ITEM,
|
||||
(void **)&device_inquiry, &inquiry_len, true) != B_OK
|
||||
|| inquiry_len < sizeof(device_inquiry))
|
||||
goto err;
|
||||
(const void **)&deviceInquiry, &inquiryLength, true) != B_OK
|
||||
|| inquiryLength < sizeof(deviceInquiry))
|
||||
return B_ERROR;
|
||||
|
||||
// get block limit of underlying hardware to lower it (if necessary)
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, &max_blocks, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, &max_blocks,
|
||||
true) != B_OK)
|
||||
max_blocks = INT_MAX;
|
||||
|
||||
// using 10 byte commands, at most 0xffff blocks can be transmitted at once
|
||||
@@ -123,23 +105,11 @@ das_device_added(device_node_handle node)
|
||||
// are supported, but the block_io module can live with that)
|
||||
max_blocks = min(max_blocks, 0xffff);
|
||||
|
||||
name = scsi_periph->compose_device_name(node, "disk/scsi");
|
||||
if (name == NULL) {
|
||||
SHOW_ERROR0(2, "Cannot compose device name");
|
||||
goto err;
|
||||
}
|
||||
|
||||
SHOW_FLOW(3, "name = %s", name);
|
||||
|
||||
// ready to register
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: SCSI_DSK_MODULE_NAME }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
|
||||
// tell block_io whether the device is removable
|
||||
{ "removable", B_UINT8_TYPE, { ui8: device_inquiry->removable_medium }},
|
||||
// tell which name we want to have in devfs
|
||||
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: name }},
|
||||
{ "removable", B_UINT8_TYPE, { ui8: deviceInquiry->removable_medium }},
|
||||
// impose own max block restriction
|
||||
{ B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, B_UINT32_TYPE, { ui32: max_blocks }},
|
||||
// in general, any disk can be a BIOS drive (even ZIP-disks)
|
||||
@@ -147,16 +117,7 @@ das_device_added(device_node_handle node)
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
status_t res = pnp->register_device(node, attrs, NULL, &node);
|
||||
|
||||
free(name);
|
||||
free(device_inquiry);
|
||||
|
||||
return res;
|
||||
return pnp->register_node(node, SCSI_DSK_MODULE_NAME, attrs, NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
err:
|
||||
free(device_inquiry);
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
@@ -3,12 +3,7 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open SCSI Disk Driver
|
||||
|
||||
File handle management.
|
||||
*/
|
||||
|
||||
/*! File handle management. */
|
||||
|
||||
#include "scsi_dsk_int.h"
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de.
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open SCSI Disk Driver
|
||||
|
||||
Main file.
|
||||
|
||||
You'll find das_... all over the place. This stands for
|
||||
"Direct Access Storage" which is the official SCSI name for
|
||||
normal (floppy/hard/ZIP)-disk drives.
|
||||
@@ -28,6 +25,23 @@ device_manager_info *pnp;
|
||||
block_io_for_driver_interface *gBlockIO;
|
||||
|
||||
|
||||
static void
|
||||
das_set_device(das_device_info *info, block_io_device device)
|
||||
{
|
||||
scsi_ccb *request;
|
||||
|
||||
info->block_io_device = device;
|
||||
|
||||
// and get (initial) capacity
|
||||
request = info->scsi->alloc_ccb(info->scsi_device);
|
||||
if (request == NULL)
|
||||
return;
|
||||
|
||||
scsi_periph->check_capacity(info->scsi_periph_device, request);
|
||||
info->scsi->free_ccb(request);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
das_read(das_handle_info *handle, const phys_vecs *vecs, off_t pos,
|
||||
size_t num_blocks, uint32 block_size, size_t *bytes_transferred)
|
||||
@@ -247,39 +261,43 @@ das_ioctl(das_handle_info *handle, int op, void *buf, size_t len)
|
||||
|
||||
|
||||
static float
|
||||
das_supports_device(device_node_handle parent, bool *_noConnection)
|
||||
das_supports_device(device_node *parent)
|
||||
{
|
||||
char *bus;
|
||||
uint8 device_type;
|
||||
const char *bus;
|
||||
uint8 deviceType;
|
||||
|
||||
// make sure parent is really the SCSI bus manager
|
||||
if (pnp->get_attr_string(parent, B_DRIVER_BUS, &bus, false))
|
||||
return B_ERROR;
|
||||
if (pnp->get_attr_string(parent, B_DEVICE_BUS, &bus, false))
|
||||
return -1;
|
||||
|
||||
if (strcmp(bus, "scsi")) {
|
||||
free(bus);
|
||||
if (strcmp(bus, "scsi"))
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
// check whether it's really a Direct Access Device
|
||||
if (pnp->get_attr_uint8(parent, SCSI_DEVICE_TYPE_ITEM, &device_type, true) != B_OK
|
||||
|| device_type != scsi_dev_direct_access) {
|
||||
free(bus);
|
||||
if (pnp->get_attr_uint8(parent, SCSI_DEVICE_TYPE_ITEM, &deviceType, true)
|
||||
!= B_OK || deviceType != scsi_dev_direct_access)
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
free(bus);
|
||||
return 0.6;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
das_get_paths(const char ***_bus, const char ***_device)
|
||||
static status_t
|
||||
das_publish_device(void *_cookie)
|
||||
{
|
||||
static const char *kBus[] = { "scsi", NULL };
|
||||
das_device_info *device = (das_device_info *)_cookie;
|
||||
status_t status;
|
||||
char *name;
|
||||
|
||||
*_bus = kBus;
|
||||
*_device = NULL;
|
||||
name = scsi_periph->compose_device_name(device->node, "disk/scsi");
|
||||
if (name == NULL)
|
||||
return B_ERROR;
|
||||
|
||||
status = pnp->publish_device(device->node, name,
|
||||
B_BLOCK_IO_DEVICE_MODULE_NAME);
|
||||
|
||||
free(name);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -304,7 +322,7 @@ module_dependency module_dependencies[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
block_device_interface scsi_dsk_module = {
|
||||
block_device_interface sSCSIDiskModule = {
|
||||
{
|
||||
{
|
||||
SCSI_DSK_MODULE_NAME,
|
||||
@@ -315,13 +333,13 @@ block_device_interface scsi_dsk_module = {
|
||||
das_supports_device,
|
||||
das_device_added,
|
||||
das_init_device,
|
||||
(status_t (*) (void *))das_uninit_device,
|
||||
NULL, // remove device
|
||||
NULL, // cleanup device
|
||||
das_get_paths,
|
||||
das_uninit_device,
|
||||
das_publish_device,
|
||||
NULL, // rescan
|
||||
},
|
||||
|
||||
(status_t (*)(block_device_device_cookie, block_device_handle_cookie *))&das_open,
|
||||
(void (*)(block_device_cookie *, block_io_device)) &das_set_device,
|
||||
(status_t (*)(block_device_cookie *, block_device_handle_cookie *))&das_open,
|
||||
(status_t (*)(block_device_handle_cookie)) &das_close,
|
||||
(status_t (*)(block_device_handle_cookie)) &das_free,
|
||||
|
||||
@@ -333,10 +351,7 @@ block_device_interface scsi_dsk_module = {
|
||||
(status_t (*)(block_device_handle_cookie, int, void *, size_t))&das_ioctl,
|
||||
};
|
||||
|
||||
#if !_BUILDING_kernel && !BOOT
|
||||
_EXPORT
|
||||
module_info *modules[] = {
|
||||
(module_info *)&scsi_dsk_module,
|
||||
(module_info *)&sSCSIDiskModule,
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -4,8 +4,6 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open SCSI Disk Driver
|
||||
|
||||
Peripheral driver to handle any kind of SCSI disks,
|
||||
i.e. hard disk and floopy disks (ZIP etc.)
|
||||
|
||||
@@ -17,6 +15,6 @@
|
||||
|
||||
#include <device_manager.h>
|
||||
|
||||
#define SCSI_DSK_MODULE_NAME "drivers/disk/scsi/scsi_dsk/device_v1"
|
||||
#define SCSI_DSK_MODULE_NAME "drivers/disk/scsi/scsi_dsk/driver_v1"
|
||||
|
||||
#endif /* _SCSI_DSK_H */
|
||||
|
||||
@@ -23,8 +23,9 @@
|
||||
#include "wrapper.h"
|
||||
|
||||
|
||||
// must start as block_device_cookie
|
||||
typedef struct das_device_info {
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
scsi_periph_device scsi_periph_device;
|
||||
scsi_device scsi_device;
|
||||
scsi_device_interface *scsi;
|
||||
@@ -47,21 +48,18 @@ extern scsi_periph_callbacks callbacks;
|
||||
extern block_io_for_driver_interface *gBlockIO;
|
||||
|
||||
|
||||
// device_mgr.c
|
||||
// device.c
|
||||
|
||||
status_t das_init_device(device_node_handle node, void *user_cookie, void **cookie);
|
||||
status_t das_uninit_device(das_device_info *device);
|
||||
status_t das_device_added(device_node_handle node);
|
||||
status_t das_device_added(device_node *node);
|
||||
status_t das_init_device(device_node *node, void **cookie);
|
||||
void das_uninit_device(void *cookie);
|
||||
|
||||
|
||||
// handle_mgr.c
|
||||
// scsi_dsk.c
|
||||
|
||||
status_t das_open(das_device_info *device, das_handle_info **handle_out);
|
||||
status_t das_close(das_handle_info *handle);
|
||||
status_t das_free(das_handle_info *handle);
|
||||
|
||||
|
||||
// scsi_dsk.c
|
||||
|
||||
void das_set_capacity(das_device_info *device, uint64 capacity,
|
||||
uint32 block_size);
|
||||
|
||||
@@ -3,7 +3,6 @@ SubDir HAIKU_TOP src add-ons kernel generic ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic atomizer ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic block_io ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic dpc ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic fast_log ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic ide_adapter ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic locked_pool ;
|
||||
SubInclude HAIKU_TOP src add-ons kernel generic mpu401 ;
|
||||
|
||||
@@ -3,16 +3,9 @@
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Open block device manager
|
||||
|
||||
Actual I/O.
|
||||
|
||||
Main file.
|
||||
*/
|
||||
|
||||
|
||||
#include "block_io_private.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
@@ -37,7 +30,7 @@ device_manager_info *pnp;
|
||||
|
||||
|
||||
static status_t
|
||||
block_io_open(block_io_device_info *device, uint32 flags,
|
||||
block_io_open(block_io_device_info *device, const char *path, int openMode,
|
||||
block_io_handle_info **res_handle)
|
||||
{
|
||||
block_io_handle_info *handle;
|
||||
@@ -327,31 +320,10 @@ block_io_ioctl(block_io_handle_info *handle, uint32 op, void *buffer, size_t len
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
block_io_register_device(device_node_handle parent)
|
||||
{
|
||||
TRACE(("block_io_register_device()\n"));
|
||||
|
||||
// ready to register at devfs
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: B_BLOCK_IO_MODULE_NAME }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "block_io" }},
|
||||
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: PNP_DEVFS_MODULE_NAME }},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
device_node_handle node;
|
||||
|
||||
return pnp->register_device(parent, attrs, NULL, &node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
block_io_remove(device_node_handle node, void *cookie)
|
||||
block_io_remove(void *cookie)
|
||||
{
|
||||
#if 0
|
||||
uint8 bios_id;
|
||||
//bios_drive *drive;
|
||||
|
||||
@@ -361,7 +333,6 @@ block_io_remove(device_node_handle node, void *cookie)
|
||||
return;
|
||||
|
||||
// ToDo: this assumes private R5 kernel functions to be present
|
||||
#if 0
|
||||
for (drive = bios_drive_info; drive->bios_id != 0; ++drive) {
|
||||
if (drive->bios_id == bios_id)
|
||||
break;
|
||||
@@ -376,26 +347,28 @@ block_io_remove(device_node_handle node, void *cookie)
|
||||
|
||||
|
||||
static status_t
|
||||
block_io_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
block_io_init_device(void *_data, void **cookie)
|
||||
{
|
||||
block_device_cookie *data = (block_device_cookie *)_data;
|
||||
block_io_device_info *device;
|
||||
block_device_params params;
|
||||
char *name, *tmp_name;
|
||||
// const char *name;
|
||||
// char *tmp_name;
|
||||
uint8 is_bios_drive;
|
||||
status_t res;
|
||||
|
||||
TRACE(("block_io_init_device()\n"));
|
||||
|
||||
// extract controller/protocoll restrictions from node
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_DMA_ALIGNMENT, ¶ms.alignment, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(data->node, B_BLOCK_DEVICE_DMA_ALIGNMENT, ¶ms.alignment, true) != B_OK)
|
||||
params.alignment = 0;
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, ¶ms.max_blocks, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(data->node, B_BLOCK_DEVICE_MAX_BLOCKS_ITEM, ¶ms.max_blocks, true) != B_OK)
|
||||
params.max_blocks = 0xffffffff;
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_DMA_BOUNDARY, ¶ms.dma_boundary, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(data->node, B_BLOCK_DEVICE_DMA_BOUNDARY, ¶ms.dma_boundary, true) != B_OK)
|
||||
params.dma_boundary = ~0;
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, ¶ms.max_sg_block_size, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(data->node, B_BLOCK_DEVICE_MAX_SG_BLOCK_SIZE, ¶ms.max_sg_block_size, true) != B_OK)
|
||||
params.max_sg_block_size = 0xffffffff;
|
||||
if (pnp->get_attr_uint32(node, B_BLOCK_DEVICE_MAX_SG_BLOCKS, ¶ms.max_sg_blocks, true) != B_OK)
|
||||
if (pnp->get_attr_uint32(data->node, B_BLOCK_DEVICE_MAX_SG_BLOCKS, ¶ms.max_sg_blocks, true) != B_OK)
|
||||
params.max_sg_blocks = ~0;
|
||||
|
||||
// do some sanity check:
|
||||
@@ -427,16 +400,9 @@ block_io_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
// (they consume 4KB and can describe up to 2MB virtual cont. memory!)
|
||||
params.max_sg_blocks = min(params.max_sg_blocks, 512);
|
||||
|
||||
if (pnp->get_attr_uint8(node, B_BLOCK_DEVICE_IS_BIOS_DRIVE, &is_bios_drive, true) != B_OK)
|
||||
if (pnp->get_attr_uint8(data->node, B_BLOCK_DEVICE_IS_BIOS_DRIVE, &is_bios_drive, true) != B_OK)
|
||||
is_bios_drive = false;
|
||||
|
||||
// we don't really care about /dev name, but if it is
|
||||
// missing, we will get a problem
|
||||
if (pnp->get_attr_string(node, PNP_DEVFS_FILENAME, &name, true) != B_OK) {
|
||||
dprintf("devfs filename is missing.\n");
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
device = (block_io_device_info *)malloc(sizeof(*device));
|
||||
if (device == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
@@ -445,14 +411,15 @@ block_io_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
|
||||
memset(device, 0, sizeof(*device));
|
||||
|
||||
device->node = node;
|
||||
device->node = data->node;
|
||||
|
||||
res = benaphore_init(&device->lock, "block_device_mutex");
|
||||
if (res < 0)
|
||||
goto err2;
|
||||
|
||||
#if 0
|
||||
// construct a identifiable name for S/G pool
|
||||
tmp_name = malloc(strlen(name) + strlen(" sg_lists") + 1);
|
||||
tmp_name = malloc(name + strlen(" sg_lists") + 1);
|
||||
if (tmp_name == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
goto err3;
|
||||
@@ -460,16 +427,17 @@ block_io_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
|
||||
strcpy(tmp_name, name);
|
||||
strcat(tmp_name, " sg_lists");
|
||||
#endif
|
||||
|
||||
// create S/G pool with initial size 1
|
||||
// (else, we may be on the paging path and have no S/G entries at hand)
|
||||
device->phys_vecs_pool = locked_pool->create(
|
||||
params.max_sg_blocks * sizeof(physical_entry),
|
||||
sizeof( physical_entry ) - 1,
|
||||
0, 16*1024, 32, 1, tmp_name, B_FULL_LOCK | B_CONTIGUOUS,
|
||||
0, 16*1024, 32, 1, "block io sg lists", B_FULL_LOCK | B_CONTIGUOUS,
|
||||
NULL, NULL, NULL);
|
||||
|
||||
free(tmp_name);
|
||||
// free(tmp_name);
|
||||
|
||||
if (device->phys_vecs_pool == NULL) {
|
||||
res = B_NO_MEMORY;
|
||||
@@ -479,41 +447,33 @@ block_io_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
device->params = params;
|
||||
device->is_bios_drive = is_bios_drive != 0;
|
||||
|
||||
res = pnp->init_driver(pnp->get_parent(node), device,
|
||||
(driver_module_info **)&device->interface, (void **)&device->cookie);
|
||||
if (res != B_OK)
|
||||
goto err4;
|
||||
pnp->get_driver(device->node, (driver_module_info **)&device->interface,
|
||||
(void **)&device->cookie);
|
||||
|
||||
free(name);
|
||||
device->interface->set_device(device->cookie, device);
|
||||
|
||||
TRACE(("done\n"));
|
||||
|
||||
*cookie = device;
|
||||
return B_OK;
|
||||
|
||||
err4:
|
||||
locked_pool->destroy(device->phys_vecs_pool);
|
||||
err3:
|
||||
benaphore_destroy(&device->lock);
|
||||
err2:
|
||||
free(device);
|
||||
err1:
|
||||
free(name);
|
||||
pnp->uninit_driver(pnp->get_parent(node));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
block_io_uninit_device(block_io_device_info *device)
|
||||
static void
|
||||
block_io_uninit_device(void *_cookie)
|
||||
{
|
||||
pnp->uninit_driver(pnp->get_parent(device->node));
|
||||
block_io_device_info *device = _cookie;
|
||||
|
||||
locked_pool->destroy(device->phys_vecs_pool);
|
||||
benaphore_destroy(&device->lock);
|
||||
free(device);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -594,70 +554,47 @@ module_dependency module_dependencies[] = {
|
||||
};
|
||||
|
||||
|
||||
pnp_devfs_driver_info block_io_module = {
|
||||
struct device_module_info sBlockIOModule = {
|
||||
{
|
||||
{
|
||||
B_BLOCK_IO_MODULE_NAME,
|
||||
B_BLOCK_IO_DEVICE_MODULE_NAME,
|
||||
0,
|
||||
|
||||
std_ops
|
||||
},
|
||||
|
||||
NULL, // supports device
|
||||
block_io_register_device,
|
||||
block_io_init_device,
|
||||
(status_t (*)( void * )) block_io_uninit_device,
|
||||
block_io_uninit_device,
|
||||
block_io_remove,
|
||||
NULL, // cleanup
|
||||
NULL, // get paths
|
||||
},
|
||||
|
||||
(status_t (*)(void *, uint32, void **))block_io_open,
|
||||
(status_t (*)(void *, const char *, int, void **))block_io_open,
|
||||
(status_t (*)(void *))block_io_close,
|
||||
(status_t (*)(void *))block_io_freecookie,
|
||||
|
||||
(status_t (*)(void *, uint32, void *, size_t))block_io_ioctl,
|
||||
|
||||
(status_t (*)(void *, off_t, void *, size_t *))block_io_read,
|
||||
(status_t (*)(void *, off_t, const void *, size_t *))block_io_write,
|
||||
NULL, // io
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
(status_t (*)(void *, int32, void *, size_t))block_io_ioctl,
|
||||
|
||||
(status_t (*)(void *, off_t, const iovec *, size_t, size_t *))block_io_readv,
|
||||
(status_t (*)(void *, off_t, const iovec *, size_t, size_t *))block_io_writev
|
||||
NULL, // select
|
||||
NULL, // deselect
|
||||
// (status_t (*)(void *, off_t, const iovec *, size_t, size_t *))block_io_readv,
|
||||
// (status_t (*)(void *, off_t, const iovec *, size_t, size_t *))block_io_writev
|
||||
};
|
||||
|
||||
|
||||
static status_t
|
||||
std_ops_for_driver(int32 op, ...)
|
||||
{
|
||||
// there is nothing to setup as this is a interface for
|
||||
// drivers which are loaded by _us_
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
block_io_for_driver_interface block_io_for_driver_module = {
|
||||
block_io_for_driver_interface sBlockIOForDriverModule = {
|
||||
{
|
||||
B_BLOCK_IO_FOR_DRIVER_MODULE_NAME,
|
||||
0,
|
||||
|
||||
std_ops_for_driver
|
||||
NULL
|
||||
},
|
||||
|
||||
block_io_set_media_params,
|
||||
};
|
||||
|
||||
module_info *modules[] = {
|
||||
&block_io_module.info.info,
|
||||
&block_io_for_driver_module.info,
|
||||
&sBlockIOModule.info,
|
||||
&sBlockIOForDriverModule.info,
|
||||
NULL
|
||||
};
|
||||
|
||||
@@ -34,9 +34,9 @@ typedef struct block_device_params {
|
||||
|
||||
// device info
|
||||
typedef struct block_io_device_info {
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
block_device_interface *interface;
|
||||
block_device_device_cookie cookie;
|
||||
block_device_cookie *cookie;
|
||||
|
||||
benaphore lock; // used for access to following variables
|
||||
uint32 block_size;
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
SubDir HAIKU_TOP src add-ons kernel generic fast_log ;
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
|
||||
KernelAddon fast_log :
|
||||
clients.c
|
||||
device.c
|
||||
long_buffers.c
|
||||
;
|
||||
|
||||
@@ -1,585 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fast logging facilities.
|
||||
|
||||
Client interface.
|
||||
|
||||
Every client opens a connection, passing a list of event
|
||||
ids together with their description. All logging calls
|
||||
write the encoded event into a buffer, using the event id
|
||||
to save space. Once the logging data is to be read, the
|
||||
buffer is decoded and written to the long buffers. The
|
||||
same happens when a client closes a connection, as the
|
||||
association between event ids and descriptions would be
|
||||
lost.
|
||||
|
||||
The buffer is split into a lower and an upper half, each
|
||||
of size fast_log_buffer_size. The currently active half
|
||||
is determined by bit 31 of fast_log_buffer_offset_alloc:
|
||||
zero means lower, one means upper half.
|
||||
|
||||
During write, fast_log_buffer_offset_alloc is first
|
||||
incremented by the requested number of bytes atomically.
|
||||
If there is enough space, the even data is copied into
|
||||
the buffer and fast_log_buffer_offset_filled is
|
||||
atomically incremented as well. This allows concurrent
|
||||
filling by different threads without using any locking.
|
||||
If the buffer is too short, logging data is discarded.
|
||||
|
||||
For read out, fast_log_buffer_offset_alloc
|
||||
is atomically set to the beginning of the opposite buffer,
|
||||
making sure that no further events are appended to the
|
||||
previously active buffer. Then, we wait for
|
||||
fast_log_buffer_offset having reached the value of
|
||||
fast_log_buffer_alloc when it was reset, i.e. until
|
||||
all active writes are completed. Now, the buffer can
|
||||
be read out savely.
|
||||
|
||||
To detect buffer overflow, buffer halves are set to
|
||||
zero before they are activated. If a write fails because
|
||||
lack of space, nothing is writting to the buffer, though
|
||||
fast_log_buffer_offset and fast_log_buffer_alloc are
|
||||
incremented. This leads to an unwritten entry in the log,
|
||||
which content remains zero. The easier way is to detect
|
||||
whether fast_log_alloc is byond buffer size (which is
|
||||
done as well), but because entries have different sizes,
|
||||
we don't know which was the lastly written entry.
|
||||
*/
|
||||
|
||||
|
||||
#include "fast_log_int.h"
|
||||
#include "dl_list.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
#include <SupportDefs.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// one client connection
|
||||
typedef struct fast_log_connection {
|
||||
struct fast_log_connection *prev, *next;
|
||||
// prefix in log
|
||||
const char *prefix;
|
||||
// list of event types
|
||||
fast_log_event_type *types;
|
||||
} fast_log_connection;
|
||||
|
||||
// one entry in logging buffer
|
||||
typedef struct fast_log_entry {
|
||||
// client handle.
|
||||
// this must be first as it is checked against NULL
|
||||
// by reader to detect overflown entries; moving it
|
||||
// to a later offset would make reading of it dangerous
|
||||
// as it could be located byond end of buffer
|
||||
// (perhaps this could be handled as well, but it
|
||||
// would make things more complicated)
|
||||
fast_log_connection *handle;
|
||||
// event type
|
||||
int16 event;
|
||||
// number of entries in "params"
|
||||
int16 num_params;
|
||||
// timestamp
|
||||
bigtime_t time;
|
||||
// parameters
|
||||
uint32 params[1];
|
||||
} fast_log_entry;
|
||||
|
||||
// list of clients
|
||||
static fast_log_connection *fast_log_handles = NULL;
|
||||
// to lock during access of fast_log_handles
|
||||
sem_id fast_log_clients_sem;
|
||||
// to lock during conversion of encoded buffer to long buffer
|
||||
sem_id fast_log_convert_sem;
|
||||
// logging buffer.
|
||||
// it consists of 2*fast_log_buffer_size, see header
|
||||
char *fast_log_buffer;
|
||||
// offset in logging buffer for next write.
|
||||
// bit 31 is set for upper buffer half and is rest for lower buffer half
|
||||
uint32 fast_log_buffer_offset_alloc;
|
||||
// offset of end of last write
|
||||
uint32 fast_log_buffer_offset_filled;
|
||||
// size of one half of log buffer
|
||||
int fast_log_buffer_size = /*512*/ 16*1024;
|
||||
// ToDo: cut down because of current allocator...
|
||||
|
||||
|
||||
device_manager_info *pnp;
|
||||
|
||||
|
||||
/** convert event code to text
|
||||
* text_buffer - buffer used if text must is composed manually
|
||||
* (must be at least 24 characters long)
|
||||
*/
|
||||
|
||||
static const char *
|
||||
fast_log_event2text(fast_log_connection *handle, int16 event, char *text_buffer)
|
||||
{
|
||||
fast_log_event_type *type;
|
||||
|
||||
for (type = handle->types; type->event != 0; ++type) {
|
||||
if (type->event == event)
|
||||
return type->description;
|
||||
}
|
||||
|
||||
// longest message is 11 characters + 11 integer characters + zero byte
|
||||
sprintf(text_buffer, "unknown (%d)", event);
|
||||
return text_buffer;
|
||||
}
|
||||
|
||||
|
||||
/** decode one entry and write it to long buffer */
|
||||
|
||||
static void
|
||||
fast_log_decode_entry(fast_log_entry *entry)
|
||||
{
|
||||
fast_log_connection *handle = entry->handle;
|
||||
char buffer[100];
|
||||
uint64 time;
|
||||
uint32 min, sec, mill, mic;
|
||||
char text_buffer[30];
|
||||
int i;
|
||||
|
||||
time = entry->time; //entry->tsc / (sysinfo.cpu_clock_speed / 1000000);
|
||||
mic = time % 1000;
|
||||
time /= 1000;
|
||||
mill = time % 1000;
|
||||
time /= 1000;
|
||||
sec = time % 60;
|
||||
time /= 60;
|
||||
min = time;
|
||||
|
||||
sprintf(buffer, "%03ld:%02ld:%03ld.%03ld ", min, sec, mill, mic);
|
||||
fast_log_write_long_log(buffer);
|
||||
|
||||
fast_log_write_long_log(handle->prefix);
|
||||
fast_log_write_long_log(": ");
|
||||
fast_log_write_long_log(fast_log_event2text(handle, entry->event, text_buffer));
|
||||
fast_log_write_long_log(" ");
|
||||
|
||||
for (i = 0; i < entry->num_params; ++i) {
|
||||
if (i > 0)
|
||||
fast_log_write_long_log(", ");
|
||||
|
||||
sprintf(buffer, "%08x", (uint)entry->params[i]);
|
||||
fast_log_write_long_log(buffer);
|
||||
}
|
||||
|
||||
fast_log_write_long_log("\n");
|
||||
}
|
||||
|
||||
|
||||
/** flush all compressed logging entries to long log */
|
||||
|
||||
void
|
||||
fast_log_flush_buffer(void)
|
||||
{
|
||||
uint32 offset;
|
||||
uint32 start, new_start, new_offset_alloc, size;
|
||||
int i;
|
||||
|
||||
acquire_sem(fast_log_convert_sem);
|
||||
|
||||
// flip between lower and upper half of buffer
|
||||
if ((fast_log_buffer_offset_alloc & (1L << 31)) == 0) {
|
||||
start = 0;
|
||||
new_start = fast_log_buffer_size;
|
||||
new_offset_alloc = 1L << 31;
|
||||
} else {
|
||||
start = fast_log_buffer_size;
|
||||
new_start = 0;
|
||||
new_offset_alloc = 0;
|
||||
}
|
||||
|
||||
// reset new buffer to zero to detect uninitialized, overflown entries
|
||||
memset(fast_log_buffer + new_start, 0, fast_log_buffer_size);
|
||||
|
||||
// swap buffers
|
||||
size = atomic_set((vint32*)&fast_log_buffer_offset_alloc, new_offset_alloc);
|
||||
|
||||
// get rid of bit 31 flag
|
||||
size &= ~(1 << 31);
|
||||
|
||||
// decrement offset of filled data by number of bytes allocated when
|
||||
// the buffer was swapped; if all writers are done, the offset is
|
||||
// >= 0 now, if some writers aren't finished, it is < 0
|
||||
atomic_add(&fast_log_buffer_offset_filled, -size);
|
||||
|
||||
// wait until all writers are finished
|
||||
for (i = 1000000; i >= 0; --i) {
|
||||
if ((int32)fast_log_buffer_offset_filled >= 0)
|
||||
break;
|
||||
|
||||
spin(1);
|
||||
// ToDo: spin?? If that should be a "yield", it should be snooze(1).
|
||||
}
|
||||
|
||||
// perhaps we are in a spinlock or something nasty like that,
|
||||
// so the writer is blocked by us
|
||||
if (i < 0) {
|
||||
fast_log_write_long_log("<TIME-OUT> during waiting for log writers; some "
|
||||
"events got lost; perhaps a client disconnected with a spinlock hold\n");
|
||||
}
|
||||
|
||||
// dprintf( "start=%d, size=%d\n", (int)start, (int)size );
|
||||
|
||||
// uncompress log
|
||||
for (offset = 0; offset < size; ) {
|
||||
fast_log_entry *entry;
|
||||
|
||||
// check whether there was an overflow when the buffer
|
||||
// had zero bytes left
|
||||
if (offset > (uint32)fast_log_buffer_size) {
|
||||
fast_log_write_long_log("<TRUNCATED1>\n");
|
||||
break;
|
||||
}
|
||||
|
||||
entry = (fast_log_entry *)&fast_log_buffer[start + offset];
|
||||
|
||||
// check for overflow when the buffer had some bytes left;
|
||||
// in this case, the entry is uninitialized and thus contains
|
||||
// all zeros
|
||||
if (entry->handle == NULL) {
|
||||
fast_log_write_long_log( "<TRUNCATED2>\n" );
|
||||
// the entry may be partially byond end of buffer, so
|
||||
// we must not access any other element of the entry
|
||||
break;
|
||||
} else {
|
||||
// normal entry, so it's time to decode it
|
||||
fast_log_decode_entry(entry);
|
||||
}
|
||||
|
||||
offset += sizeof(fast_log_entry)
|
||||
+ (entry->num_params - 1) * sizeof(entry->params[0]);
|
||||
}
|
||||
|
||||
release_sem(fast_log_convert_sem);
|
||||
}
|
||||
|
||||
|
||||
/** start logging of one client */
|
||||
|
||||
static fast_log_handle
|
||||
fast_log_start_log(const char *prefix, fast_log_event_type types[])
|
||||
{
|
||||
fast_log_connection *handle;
|
||||
|
||||
handle = malloc(sizeof(*handle));
|
||||
if (handle == NULL)
|
||||
return NULL;
|
||||
|
||||
handle->prefix = prefix;
|
||||
handle->types = types;
|
||||
|
||||
acquire_sem(fast_log_clients_sem);
|
||||
ADD_DL_LIST_HEAD(handle, fast_log_handles, );
|
||||
release_sem(fast_log_clients_sem);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
|
||||
/** close connection of one client */
|
||||
|
||||
static void
|
||||
fast_log_stop_log(fast_log_handle handle)
|
||||
{
|
||||
if (handle == NULL)
|
||||
return;
|
||||
|
||||
fast_log_flush_buffer();
|
||||
|
||||
acquire_sem(fast_log_clients_sem);
|
||||
REMOVE_DL_LIST(handle, fast_log_handles, );
|
||||
release_sem(fast_log_clients_sem);
|
||||
|
||||
free(handle);
|
||||
}
|
||||
|
||||
#define ENTRY_SIZE(num_params) (sizeof(fast_log_entry) + sizeof(uint32) * ((num_params)-1))
|
||||
|
||||
/** allocate space in log */
|
||||
|
||||
static fast_log_entry *
|
||||
fast_log_alloc_entry(fast_log_handle handle, int num_params)
|
||||
{
|
||||
uint32 offset, real_offset, chunk_offset;
|
||||
fast_log_entry *entry;
|
||||
|
||||
if (handle == NULL)
|
||||
return NULL;
|
||||
|
||||
// alloc space in buffer
|
||||
offset = atomic_add( &fast_log_buffer_offset_alloc, ENTRY_SIZE( num_params ));
|
||||
|
||||
real_offset = offset & ~(1L << 31);
|
||||
chunk_offset = ((offset & (1L << 31)) == 0 ? 0 : fast_log_buffer_size);
|
||||
|
||||
// take care of bit 31 trick to get the address of the new entry
|
||||
entry = (fast_log_entry *)&fast_log_buffer[chunk_offset + real_offset];
|
||||
|
||||
if (real_offset + ENTRY_SIZE( num_params ) < (uint32)fast_log_buffer_size) {
|
||||
// there is enough space in buffer, so we can fill it
|
||||
entry->time = system_time();
|
||||
entry->handle = handle;
|
||||
entry->num_params = num_params;
|
||||
return entry;
|
||||
} else {
|
||||
// buffer overflow, return NULL to notify caller
|
||||
atomic_add( &fast_log_buffer_offset_filled, ENTRY_SIZE( num_params ));
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event without parameters */
|
||||
|
||||
static void
|
||||
fast_log_log_0(fast_log_handle handle, int event)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, 0);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->event = event;
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event with one parameter */
|
||||
|
||||
static void
|
||||
fast_log_log_1(fast_log_handle handle, int event, uint32 param1)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, 1);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->event = event;
|
||||
entry->params[0] = param1;
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(1));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event with two parameters */
|
||||
|
||||
static void
|
||||
fast_log_log_2(fast_log_handle handle, int event, uint32 param1, uint32 param2)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, 2);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->event = event;
|
||||
entry->params[0] = param1;
|
||||
entry->params[1] = param2;
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event with three parameters */
|
||||
|
||||
static void
|
||||
fast_log_log_3(fast_log_handle handle, int event,
|
||||
uint32 param1, uint32 param2, uint32 param3)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, 3);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->event = event;
|
||||
entry->params[0] = param1;
|
||||
entry->params[1] = param2;
|
||||
entry->params[2] = param3;
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(3));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event with four parameters */
|
||||
|
||||
static void
|
||||
fast_log_log_4(fast_log_handle handle, int event, uint32 param1,
|
||||
uint32 param2, uint32 param3, uint32 param4)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, 4);
|
||||
|
||||
if (entry != NULL) {
|
||||
entry->event = event;
|
||||
entry->params[0] = param1;
|
||||
entry->params[1] = param2;
|
||||
entry->params[2] = param3;
|
||||
entry->params[3] = param4;
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(4));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** log event with n parameters */
|
||||
|
||||
static void
|
||||
fast_log_log_n(fast_log_handle handle, int event, int num_params, ...)
|
||||
{
|
||||
fast_log_entry *entry;
|
||||
va_list vl;
|
||||
|
||||
entry = fast_log_alloc_entry(handle, num_params);
|
||||
|
||||
if (entry != NULL) {
|
||||
int i;
|
||||
va_start(vl, num_params);
|
||||
|
||||
entry->event = event;
|
||||
|
||||
for (i = 0; i < num_params; ++i) {
|
||||
entry->params[i] = va_arg(vl, int);
|
||||
}
|
||||
|
||||
va_end(vl);
|
||||
|
||||
atomic_add(&fast_log_buffer_offset_filled, ENTRY_SIZE(num_params));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** clean up client structures */
|
||||
|
||||
static void
|
||||
fast_log_uninit_clients()
|
||||
{
|
||||
free(fast_log_buffer);
|
||||
delete_sem(fast_log_clients_sem);
|
||||
delete_sem(fast_log_convert_sem);
|
||||
}
|
||||
|
||||
|
||||
/** init client structures.
|
||||
* you must call fast_log_uninit_clients on fail
|
||||
*/
|
||||
|
||||
static status_t
|
||||
fast_log_init_clients()
|
||||
{
|
||||
fast_log_buffer = NULL;
|
||||
fast_log_clients_sem = -1;
|
||||
fast_log_convert_sem = -1;
|
||||
|
||||
fast_log_clients_sem = create_sem(1, "fast_log_clients_sem");
|
||||
if (fast_log_clients_sem < B_OK)
|
||||
return fast_log_clients_sem;
|
||||
|
||||
fast_log_convert_sem = create_sem(1, "fast_log_convert_sem");
|
||||
if (fast_log_convert_sem < B_OK)
|
||||
return fast_log_convert_sem;
|
||||
|
||||
fast_log_buffer = malloc(2 * fast_log_buffer_size);
|
||||
if (fast_log_buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(fast_log_buffer, 0, 2 * fast_log_buffer_size);
|
||||
|
||||
fast_log_buffer_offset_filled = fast_log_buffer_offset_alloc = 0;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** uninitialize module */
|
||||
|
||||
static status_t
|
||||
fast_log_uninit(void)
|
||||
{
|
||||
fast_log_uninit_dev();
|
||||
fast_log_uninit_long_buffer();
|
||||
fast_log_uninit_clients();
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** initialize module */
|
||||
|
||||
static status_t
|
||||
fast_log_init(void)
|
||||
{
|
||||
status_t res;
|
||||
|
||||
if ((res = fast_log_init_long_buffer()) < B_OK)
|
||||
goto err3;
|
||||
|
||||
if ((res = fast_log_init_clients()) < B_OK)
|
||||
goto err2;
|
||||
|
||||
if ((res = fast_log_init_dev()) < B_OK)
|
||||
// yes: don't call uninit for device.c
|
||||
goto err2;
|
||||
|
||||
return B_OK;
|
||||
|
||||
err2:
|
||||
fast_log_uninit_clients();
|
||||
err3:
|
||||
fast_log_uninit_long_buffer();
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
return fast_log_init();
|
||||
case B_MODULE_UNINIT:
|
||||
return fast_log_uninit();
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module_dependency module_dependencies[] = {
|
||||
{ B_DEVICE_MANAGER_MODULE_NAME, (module_info **)&pnp },
|
||||
{}
|
||||
};
|
||||
|
||||
// client interface
|
||||
fast_log_info fast_log_module = {
|
||||
{
|
||||
FAST_LOG_MODULE_NAME,
|
||||
0,
|
||||
fast_log_std_ops
|
||||
},
|
||||
|
||||
fast_log_start_log,
|
||||
fast_log_stop_log,
|
||||
|
||||
fast_log_log_0,
|
||||
fast_log_log_1,
|
||||
fast_log_log_2,
|
||||
fast_log_log_3,
|
||||
fast_log_log_4,
|
||||
fast_log_log_n
|
||||
};
|
||||
|
||||
// embedded modules
|
||||
module_info *modules[] = {
|
||||
(module_info *)&fast_log_module,
|
||||
(module_info *)&fast_log_devfs_module,
|
||||
NULL
|
||||
};
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fast logging facilities.
|
||||
|
||||
Devfs interface.
|
||||
|
||||
Publishes a file where logging data can be read from
|
||||
directly via read. Once read, the logging data is freed.
|
||||
Obviously, you cannot seek in the file.
|
||||
|
||||
Concurrent reads are permitted, but you will have fun
|
||||
merging read data.
|
||||
*/
|
||||
|
||||
|
||||
#include "fast_log_int.h"
|
||||
#include <pnp_devfs.h>
|
||||
#include <device_manager.h>
|
||||
|
||||
|
||||
// Devfs node
|
||||
device_node_handle fast_log_devfs_node;
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_open(void *device_cookie, uint32 flags, void **handle_cookie)
|
||||
{
|
||||
handle_cookie = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_close(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_free(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_control(void *cookie, uint32 op, void *data, size_t len)
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_read(void *cookie, off_t position, void *data, size_t *num_bytes)
|
||||
{
|
||||
*num_bytes = fast_log_read_long(data, *num_bytes);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_write(void *cookie, off_t position, const void *data, size_t *num_bytes)
|
||||
{
|
||||
*num_bytes = 0;
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/** create devfs entry */
|
||||
|
||||
static status_t
|
||||
fast_log_create_devfs_entry(void)
|
||||
{
|
||||
status_t res;
|
||||
device_attr attrs[] = {
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: FAST_LOG_DEVFS_MODULE_NAME }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: PNP_DEVFS_MODULE_NAME }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: "fast_log" }},
|
||||
|
||||
{ PNP_DEVFS_FILENAME, B_STRING_TYPE, { string: FAST_LOG_DEVFS_NAME }},
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
res = pnp->register_device(NULL, attrs, NULL, &fast_log_devfs_node);
|
||||
if (res < 0)
|
||||
fast_log_devfs_node = NULL;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_init_device(device_node_handle node, void *user_cookie, void **cookie)
|
||||
{
|
||||
*cookie = NULL;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_uninit_device(void *cookie)
|
||||
{
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
fast_log_devfs_std_ops(int32 op, ...)
|
||||
{
|
||||
switch (op) {
|
||||
case B_MODULE_INIT:
|
||||
case B_MODULE_UNINIT:
|
||||
return B_OK;
|
||||
|
||||
default:
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// devfs interface
|
||||
pnp_devfs_driver_info fast_log_devfs_module = {
|
||||
{
|
||||
{
|
||||
FAST_LOG_DEVFS_MODULE_NAME,
|
||||
0,
|
||||
fast_log_devfs_std_ops
|
||||
},
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
|
||||
fast_log_devfs_init_device,
|
||||
fast_log_devfs_uninit_device,
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
},
|
||||
|
||||
fast_log_devfs_open,
|
||||
fast_log_devfs_close,
|
||||
fast_log_devfs_free,
|
||||
fast_log_devfs_control,
|
||||
fast_log_devfs_read,
|
||||
fast_log_devfs_write
|
||||
};
|
||||
|
||||
|
||||
/** cleanup devfs interface */
|
||||
|
||||
void
|
||||
fast_log_uninit_dev(void)
|
||||
{
|
||||
if (fast_log_devfs_node != NULL)
|
||||
pnp->unregister_device(fast_log_devfs_node);
|
||||
}
|
||||
|
||||
|
||||
/** init devfs interface */
|
||||
|
||||
status_t
|
||||
fast_log_init_dev(void)
|
||||
{
|
||||
status_t res;
|
||||
|
||||
fast_log_devfs_node = NULL;
|
||||
|
||||
if ((res = fast_log_create_devfs_entry()) < 0)
|
||||
return res;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Macros for double linked lists
|
||||
*/
|
||||
|
||||
#ifndef _DL_LIST_H
|
||||
#define _DL_LIST_H
|
||||
|
||||
#define REMOVE_DL_LIST( item, head, prefix ) \
|
||||
do { \
|
||||
if( item->prefix##prev ) \
|
||||
item->prefix##prev->prefix##next = item->prefix##next; \
|
||||
else \
|
||||
head = item->prefix##next; \
|
||||
\
|
||||
if( item->prefix##next ) \
|
||||
item->prefix##next->prefix##prev = item->prefix##prev; \
|
||||
} while( 0 )
|
||||
|
||||
#define ADD_DL_LIST_HEAD( item, head, prefix ) \
|
||||
do { \
|
||||
item->prefix##next = head; \
|
||||
item->prefix##prev = NULL; \
|
||||
\
|
||||
if( (head) ) \
|
||||
(head)->prefix##prev = item; \
|
||||
\
|
||||
(head) = item; \
|
||||
} while( 0 )
|
||||
|
||||
#define REMOVE_CDL_LIST( item, head, prefix ) \
|
||||
do { \
|
||||
item->prefix##next->prefix##prev = item->prefix##prev; \
|
||||
item->prefix##prev->prefix##next = item->prefix##next; \
|
||||
\
|
||||
if( item == (head) ) { \
|
||||
if( item->prefix##next != item ) \
|
||||
(head) = item->prefix##next; \
|
||||
else \
|
||||
(head) = NULL; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#define ADD_CDL_LIST_TAIL( item, type, head, prefix ) \
|
||||
do { \
|
||||
type *old_head = head; \
|
||||
\
|
||||
if( old_head ) { \
|
||||
type *first, *last; \
|
||||
\
|
||||
first = old_head; \
|
||||
last = first->prefix##prev; \
|
||||
\
|
||||
item->prefix##next = first; \
|
||||
item->prefix##prev = last; \
|
||||
first->prefix##prev = item; \
|
||||
last->prefix##next = item; \
|
||||
} else { \
|
||||
head = item; \
|
||||
item->prefix##next = item->prefix##prev = item; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#define ADD_CDL_LIST_HEAD( item, type, head, prefix ) \
|
||||
do { \
|
||||
type *old_head = head; \
|
||||
\
|
||||
head = item; \
|
||||
if( old_head ) { \
|
||||
type *first, *last; \
|
||||
\
|
||||
first = old_head; \
|
||||
last = first->prefix##prev; \
|
||||
\
|
||||
item->prefix##next = first; \
|
||||
item->prefix##prev = last; \
|
||||
first->prefix##prev = item; \
|
||||
last->prefix##next = item; \
|
||||
} else { \
|
||||
item->prefix##next = item->prefix##prev = item; \
|
||||
} \
|
||||
} while( 0 )
|
||||
|
||||
#endif
|
||||
@@ -1,45 +0,0 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fast logging facilities.
|
||||
|
||||
Internal header.
|
||||
*/
|
||||
|
||||
#include <drivers/fast_log.h>
|
||||
#include <malloc.h>
|
||||
#include <pnp_devfs.h>
|
||||
#include <device_manager.h>
|
||||
|
||||
// maximum number of long buffer
|
||||
#define FAST_LOG_MAX_LONG_BUFFERS 256;
|
||||
// size of one long buffer
|
||||
#define FAST_LOG_LONG_BUFFER_SIZE (16*1024)
|
||||
// name of dev interface module
|
||||
#define FAST_LOG_DEVFS_MODULE_NAME "generic/fast_log/devfs/v1"
|
||||
|
||||
|
||||
extern device_manager_info *pnp;
|
||||
|
||||
|
||||
// long_buffers.c
|
||||
|
||||
|
||||
void fast_log_write_long_log(const char *str);
|
||||
void fast_log_flush_buffer(void);
|
||||
size_t fast_log_read_long(char *buffer, size_t len);
|
||||
status_t fast_log_init_long_buffer(void);
|
||||
void fast_log_uninit_long_buffer(void);
|
||||
|
||||
|
||||
|
||||
// device.c
|
||||
|
||||
|
||||
status_t fast_log_init_dev(void);
|
||||
void fast_log_uninit_dev(void);
|
||||
|
||||
extern pnp_devfs_driver_info fast_log_devfs_module;
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
** Copyright 2002/03, Thomas Kurschel. All rights reserved.
|
||||
** Distributed under the terms of the OpenBeOS License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Fast logging facilities.
|
||||
|
||||
Long buffer.
|
||||
|
||||
The internal log buffer uses encoded events and
|
||||
cannot be decoded on demand as the event codes are
|
||||
passed by the client and can be changed each time
|
||||
the client connects. So, we store the decoded events
|
||||
in long buffers which can be read from directly.
|
||||
|
||||
The long buffer is split up into several smaller
|
||||
buffers that are allocated and freed on demand
|
||||
to save space.
|
||||
*/
|
||||
|
||||
|
||||
#include "fast_log_int.h"
|
||||
#include "dl_list.h"
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
|
||||
// one long buffer
|
||||
typedef struct tagfast_log_long_buffer {
|
||||
struct tagfast_log_long_buffer *next, *prev;
|
||||
// content
|
||||
char *data;
|
||||
// offset for writing
|
||||
size_t write_offset;
|
||||
// offset for reading
|
||||
size_t read_offset;
|
||||
// size of buffer
|
||||
size_t size;
|
||||
} fast_log_long_buffer;
|
||||
|
||||
static fast_log_long_buffer
|
||||
// list of long buffers
|
||||
*fast_log_long_buffers,
|
||||
// current buffer to write to
|
||||
// (NULL if all long buffers are full)
|
||||
*fast_log_cur_long_buffer;
|
||||
|
||||
static uint
|
||||
// current number of long buffers
|
||||
fast_log_num_long_buffers,
|
||||
// maximum number of long buffers
|
||||
fast_log_max_long_buffers;
|
||||
|
||||
// size of one long buffer
|
||||
static size_t fast_log_long_buffer_size;
|
||||
// true, if all long buffers are full
|
||||
// (used to insert a proper message in logging)
|
||||
static bool fast_log_long_overflow = false;
|
||||
// grab this when you want to access a long buffer.
|
||||
// you must make sure that no swapping occurs when holding this lock
|
||||
static benaphore fast_log_long_buffer_ben;
|
||||
// grab this when you read out long buffers.
|
||||
// you are allowed to swap when you hold this lock;
|
||||
// must be acquired before fast_log_long_buffer_ben
|
||||
static benaphore fast_log_long_read_ben;
|
||||
|
||||
|
||||
/** flush current long log buffer and allocate new one */
|
||||
|
||||
static status_t
|
||||
fast_log_inc_long_buffer(void)
|
||||
{
|
||||
fast_log_long_buffer *buffer;
|
||||
|
||||
fast_log_cur_long_buffer = NULL;
|
||||
|
||||
// allocate new buffer if allowed and possible
|
||||
if (fast_log_num_long_buffers >= fast_log_max_long_buffers)
|
||||
return B_ERROR;
|
||||
|
||||
buffer = malloc(sizeof(*buffer) + fast_log_long_buffer_size);
|
||||
if (buffer == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
memset(buffer, 0, sizeof(*buffer));
|
||||
buffer->write_offset = 0;
|
||||
buffer->read_offset = 0;
|
||||
buffer->size = fast_log_long_buffer_size;
|
||||
buffer->data = (char *)(buffer + 1);
|
||||
|
||||
ADD_CDL_LIST_TAIL(buffer, fast_log_long_buffer, fast_log_long_buffers, );
|
||||
|
||||
fast_log_cur_long_buffer = buffer;
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** store string in long log, internal */
|
||||
|
||||
static status_t
|
||||
fast_log_write_long_log_intern(const char *str)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
len = strlen(str);
|
||||
|
||||
while (len > 0) {
|
||||
fast_log_long_buffer *buffer;
|
||||
size_t cur_len;
|
||||
|
||||
// get buffer, alloc a new one if there isn't one
|
||||
if (fast_log_cur_long_buffer == NULL) {
|
||||
if (fast_log_inc_long_buffer() != B_OK)
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
buffer = fast_log_cur_long_buffer;
|
||||
|
||||
cur_len = min(len, buffer->size - buffer->write_offset);
|
||||
memcpy(buffer->data + buffer->write_offset, str, cur_len);
|
||||
|
||||
buffer->write_offset += cur_len;
|
||||
len -= cur_len;
|
||||
str += cur_len;
|
||||
|
||||
if (buffer->write_offset == buffer->size) {
|
||||
// next iteration will get a new one
|
||||
fast_log_cur_long_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** store string in long log */
|
||||
|
||||
void
|
||||
fast_log_write_long_log(const char *str)
|
||||
{
|
||||
benaphore_lock(&fast_log_long_buffer_ben);
|
||||
|
||||
// write pending "overflow" message
|
||||
if (fast_log_long_overflow) {
|
||||
if (fast_log_write_long_log_intern("<BUFFER OVERFLOW, increase max_long_buffers>\n") != B_OK)
|
||||
goto err;
|
||||
|
||||
fast_log_long_overflow = false;
|
||||
}
|
||||
|
||||
if (fast_log_write_long_log_intern(str) != B_OK)
|
||||
fast_log_long_overflow = true;
|
||||
|
||||
err:
|
||||
benaphore_unlock(&fast_log_long_buffer_ben);
|
||||
}
|
||||
|
||||
|
||||
/** free (first) long buffer */
|
||||
|
||||
static void
|
||||
fast_log_free_long_buffer(void)
|
||||
{
|
||||
fast_log_long_buffer *buffer = fast_log_long_buffers;
|
||||
|
||||
REMOVE_CDL_LIST(buffer, fast_log_long_buffers, );
|
||||
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
|
||||
/** read data from long buffers */
|
||||
|
||||
size_t
|
||||
fast_log_read_long(char *data, size_t len)
|
||||
{
|
||||
size_t left_bytes = len;
|
||||
|
||||
// fill long buffer
|
||||
fast_log_flush_buffer();
|
||||
|
||||
// make sure noone reads log concurrently
|
||||
benaphore_lock(&fast_log_long_read_ben);
|
||||
benaphore_lock(&fast_log_long_buffer_ben);
|
||||
|
||||
while (left_bytes > 0 && fast_log_long_buffers != NULL) {
|
||||
size_t cur_len;
|
||||
fast_log_long_buffer *buffer;
|
||||
|
||||
buffer = fast_log_long_buffers;
|
||||
|
||||
cur_len = min(left_bytes, buffer->write_offset - buffer->read_offset);
|
||||
if (cur_len == 0)
|
||||
break;
|
||||
|
||||
// "data" may be pagable, so release lock during memcpy
|
||||
benaphore_unlock(&fast_log_long_buffer_ben);
|
||||
|
||||
memcpy(data, buffer->data + buffer->read_offset, cur_len);
|
||||
|
||||
benaphore_lock(&fast_log_long_buffer_ben);
|
||||
|
||||
buffer->read_offset += cur_len;
|
||||
data += cur_len;
|
||||
left_bytes -= cur_len;
|
||||
|
||||
// once a buffer is completely read, free it
|
||||
if (buffer->read_offset == buffer->size) {
|
||||
fast_log_free_long_buffer();
|
||||
buffer = fast_log_long_buffers;
|
||||
}
|
||||
}
|
||||
|
||||
benaphore_unlock(&fast_log_long_buffer_ben);
|
||||
benaphore_unlock(&fast_log_long_read_ben);
|
||||
|
||||
return len - left_bytes;
|
||||
}
|
||||
|
||||
|
||||
/** cleanup long buffers */
|
||||
|
||||
void
|
||||
fast_log_uninit_long_buffer(void)
|
||||
{
|
||||
while (fast_log_long_buffers != NULL)
|
||||
fast_log_free_long_buffer();
|
||||
|
||||
benaphore_destroy(&fast_log_long_buffer_ben);
|
||||
benaphore_destroy(&fast_log_long_read_ben);
|
||||
}
|
||||
|
||||
|
||||
/** initialize long buffers.
|
||||
* you must call "fast_log_uninit_long_buffer" on fail
|
||||
*/
|
||||
|
||||
status_t
|
||||
fast_log_init_long_buffer(void)
|
||||
{
|
||||
status_t res;
|
||||
|
||||
fast_log_long_buffer_ben.sem = -1;
|
||||
fast_log_long_read_ben.sem = -1;
|
||||
|
||||
fast_log_long_buffers = fast_log_cur_long_buffer = NULL;
|
||||
fast_log_num_long_buffers = 0;
|
||||
|
||||
fast_log_max_long_buffers = 256;
|
||||
fast_log_long_buffer_size = 16*1024;
|
||||
|
||||
fast_log_long_overflow = false;
|
||||
|
||||
if ((res = benaphore_init(&fast_log_long_buffer_ben, "fast_log_long_buffer_ben")) < 0)
|
||||
return res;
|
||||
|
||||
if ((res = benaphore_init( &fast_log_long_read_ben, "fast_log_long_read_ben")) < 0)
|
||||
return res;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -37,12 +37,19 @@ static ide_for_controller_interface *ide;
|
||||
static device_manager_info *pnp;
|
||||
|
||||
|
||||
static void
|
||||
set_channel(ide_adapter_channel_info *channel, ide_channel ideChannel)
|
||||
{
|
||||
channel->ide_channel = ideChannel;
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ide_adapter_write_command_block_regs(ide_adapter_channel_info *channel,
|
||||
ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
int i;
|
||||
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
@@ -71,7 +78,7 @@ ide_adapter_read_command_block_regs(ide_adapter_channel_info *channel,
|
||||
ide_task_file *tf, ide_reg_mask mask)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
int i;
|
||||
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
@@ -94,7 +101,7 @@ static uint8
|
||||
ide_adapter_get_altstatus(ide_adapter_channel_info *channel)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint16 altstatusaddr = channel->control_block_base;
|
||||
|
||||
if (channel->lost)
|
||||
@@ -108,7 +115,7 @@ static status_t
|
||||
ide_adapter_write_device_control(ide_adapter_channel_info *channel, uint8 val)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint16 device_control_addr = channel->control_block_base;
|
||||
|
||||
SHOW_FLOW(3, "%x", (int)val);
|
||||
@@ -127,7 +134,7 @@ ide_adapter_write_pio(ide_adapter_channel_info *channel, uint16 *data,
|
||||
int count, bool force_16bit)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
@@ -153,7 +160,7 @@ ide_adapter_read_pio(ide_adapter_channel_info *channel, uint16 *data,
|
||||
int count, bool force_16bit)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
|
||||
uint16 ioaddr = channel->command_block_base;
|
||||
|
||||
@@ -181,7 +188,7 @@ ide_adapter_inthand(void *arg)
|
||||
{
|
||||
ide_adapter_channel_info *channel = (ide_adapter_channel_info *)arg;
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint8 status;
|
||||
|
||||
SHOW_FLOW0(3, "");
|
||||
@@ -211,7 +218,7 @@ ide_adapter_prepare_dma(ide_adapter_channel_info *channel,
|
||||
const physical_entry *sgList, size_t sgListCount, bool writeToDevice)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint8 command;
|
||||
uint8 status;
|
||||
prd_entry *prd = channel->prdt;
|
||||
@@ -255,7 +262,7 @@ static status_t
|
||||
ide_adapter_start_dma(ide_adapter_channel_info *channel)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint8 command;
|
||||
|
||||
command = pci->read_io_8(device, channel->bus_master_base
|
||||
@@ -275,7 +282,7 @@ static status_t
|
||||
ide_adapter_finish_dma(ide_adapter_channel_info *channel)
|
||||
{
|
||||
pci_device_module_info *pci = channel->pci;
|
||||
pci_device device = channel->device;
|
||||
pci_device *device = channel->device;
|
||||
uint8 command;
|
||||
uint8 status, newStatus;
|
||||
|
||||
@@ -319,7 +326,7 @@ ide_adapter_finish_dma(ide_adapter_channel_info *channel)
|
||||
|
||||
|
||||
static status_t
|
||||
ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
ide_adapter_init_channel(device_node *node,
|
||||
ide_adapter_channel_info **cookie, size_t total_data_size,
|
||||
int32 (*inthand)(void *arg))
|
||||
{
|
||||
@@ -334,6 +341,7 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
|
||||
TRACE("PCI-IDE: init channel...\n");
|
||||
|
||||
#if 0
|
||||
if (1 /* debug */){
|
||||
uint8 bus, device, function;
|
||||
uint16 vendorID, deviceID;
|
||||
@@ -345,6 +353,7 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
TRACE("PCI-IDE: bus %3d, device %2d, function %2d: vendor %04x, device %04x\n",
|
||||
bus, device, function, vendorID, deviceID);
|
||||
}
|
||||
#endif
|
||||
|
||||
// get device data
|
||||
if (pnp->get_attr_uint16(node, IDE_ADAPTER_COMMAND_BLOCK_BASE, &command_block_base, false) != B_OK
|
||||
@@ -353,8 +362,11 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
|| pnp->get_attr_uint8(node, IDE_ADAPTER_CHANNEL_INDEX, &channel_index, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if (pnp->init_driver(pnp->get_parent(node), NULL, NULL, (void **)&controller) != B_OK)
|
||||
return B_ERROR;
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, NULL, (void **)&controller);
|
||||
pnp->put_node(parent);
|
||||
}
|
||||
|
||||
channel = (ide_adapter_channel_info *)malloc(total_data_size);
|
||||
if (channel == NULL) {
|
||||
@@ -372,7 +384,6 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
channel->control_block_base = control_block_base;
|
||||
channel->bus_master_base = controller->bus_master_base + (channel_index * 8);
|
||||
channel->intnum = intnum;
|
||||
channel->ide_channel = ide_channel;
|
||||
channel->dmaing = false;
|
||||
channel->inthand = inthand;
|
||||
|
||||
@@ -411,7 +422,6 @@ ide_adapter_init_channel(device_node_handle node, ide_channel ide_channel,
|
||||
err3:
|
||||
delete_area(channel->prd_area);
|
||||
err2:
|
||||
pnp->uninit_driver(pnp->get_parent(node));
|
||||
err:
|
||||
free(channel);
|
||||
|
||||
@@ -419,7 +429,7 @@ err:
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
ide_adapter_uninit_channel(ide_adapter_channel_info *channel)
|
||||
{
|
||||
// disable IRQs
|
||||
@@ -432,17 +442,13 @@ ide_adapter_uninit_channel(ide_adapter_channel_info *channel)
|
||||
|
||||
remove_io_interrupt_handler(channel->intnum, channel->inthand, channel);
|
||||
|
||||
pnp->uninit_driver( pnp->get_parent(channel->node));
|
||||
|
||||
delete_area(channel->prd_area);
|
||||
free(channel);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ide_adapter_channel_removed(device_node_handle node, ide_adapter_channel_info *channel)
|
||||
ide_adapter_channel_removed(ide_adapter_channel_info *channel)
|
||||
{
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
@@ -455,18 +461,16 @@ ide_adapter_channel_removed(device_node_handle node, ide_adapter_channel_info *c
|
||||
/** publish node of ide channel */
|
||||
|
||||
static status_t
|
||||
ide_adapter_publish_channel(device_node_handle controller_node,
|
||||
ide_adapter_publish_channel(device_node *controller_node,
|
||||
const char *channel_module_name, uint16 command_block_base,
|
||||
uint16 control_block_base, uint8 intnum, bool can_dma,
|
||||
uint8 channel_index, const char *name, io_resource_handle *resources,
|
||||
device_node_handle *node)
|
||||
uint8 channel_index, const char *name, const io_resource *resources,
|
||||
device_node **node)
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
// info about ourself and our consumer
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: channel_module_name }},
|
||||
{ B_DRIVER_PRETTY_NAME, B_STRING_TYPE, { string: "IDE PCI" }},
|
||||
{ PNP_DRIVER_CONNECTION, B_STRING_TYPE, { string: name }},
|
||||
{ B_DRIVER_FIXED_CHILD, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
|
||||
{ B_DEVICE_PRETTY_NAME, B_STRING_TYPE, { string: "IDE PCI" }},
|
||||
{ B_DEVICE_FIXED_CHILD, B_STRING_TYPE, { string: IDE_FOR_CONTROLLER_MODULE_NAME }},
|
||||
|
||||
// private data to identify channel
|
||||
{ IDE_ADAPTER_COMMAND_BLOCK_BASE, B_UINT16_TYPE, { ui16: command_block_base }},
|
||||
@@ -479,21 +483,21 @@ ide_adapter_publish_channel(device_node_handle controller_node,
|
||||
|
||||
SHOW_FLOW0(2, "");
|
||||
|
||||
return pnp->register_device(controller_node, attrs, resources, node);
|
||||
return pnp->register_node(controller_node, channel_module_name, attrs,
|
||||
resources, node);
|
||||
}
|
||||
|
||||
|
||||
/** detect IDE channel */
|
||||
|
||||
static status_t
|
||||
ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
|
||||
device_node_handle controller_node, const char *channel_module_name,
|
||||
ide_adapter_detect_channel(pci_device_module_info *pci, pci_device *pci_device,
|
||||
device_node *controller_node, const char *channel_module_name,
|
||||
bool controller_can_dma, uint16 command_block_base, uint16 control_block_base,
|
||||
uint16 bus_master_base, uint8 intnum, uint8 channel_index, const char *name,
|
||||
device_node_handle *node, bool supports_compatibility_mode)
|
||||
device_node **node, bool supports_compatibility_mode)
|
||||
{
|
||||
uint8 api;
|
||||
io_resource_handle resource_handles[3];
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
@@ -549,42 +553,38 @@ ide_adapter_detect_channel(pci_device_module_info *pci, pci_device pci_device,
|
||||
}
|
||||
|
||||
{
|
||||
// allocate channel's I/O resources
|
||||
io_resource resources[3] = {
|
||||
{ IO_PORT, command_block_base, 8 },
|
||||
{ IO_PORT, control_block_base, 1 },
|
||||
{ B_IO_PORT, command_block_base, 8 },
|
||||
{ B_IO_PORT, control_block_base, 1 },
|
||||
{}
|
||||
};
|
||||
|
||||
if (pnp->acquire_io_resources(resources, resource_handles) != B_OK) {
|
||||
TRACE("PCI-IDE: Couldn't acquire channel resources %#x and %#x\n",
|
||||
command_block_base, control_block_base);
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ide_adapter_publish_channel(controller_node, channel_module_name,
|
||||
command_block_base, control_block_base, intnum, controller_can_dma,
|
||||
channel_index, name, resource_handles, node);
|
||||
channel_index, name, resources, node);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ide_adapter_init_controller(device_node_handle node, void *user_cookie,
|
||||
ide_adapter_init_controller(device_node *node,
|
||||
ide_adapter_controller_info **cookie, size_t total_data_size)
|
||||
{
|
||||
pci_device_module_info *pci;
|
||||
pci_device device;
|
||||
pci_device *device;
|
||||
ide_adapter_controller_info *controller;
|
||||
uint16 bus_master_base;
|
||||
uint16 pcicmd;
|
||||
// uint16 pcicmd;
|
||||
|
||||
// get device data
|
||||
if (pnp->get_attr_uint16(node, IDE_ADAPTER_BUS_MASTER_BASE, &bus_master_base, false) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
if (pnp->init_driver(pnp->get_parent(node), NULL, (driver_module_info **)&pci, (void **)&device) != B_OK)
|
||||
return B_ERROR;
|
||||
{
|
||||
device_node *parent = pnp->get_parent_node(node);
|
||||
pnp->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
|
||||
pnp->put_node(parent);
|
||||
}
|
||||
|
||||
controller = (ide_adapter_controller_info *)malloc(total_data_size);
|
||||
if (controller == NULL)
|
||||
@@ -617,42 +617,35 @@ ide_adapter_init_controller(device_node_handle node, void *user_cookie,
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
static void
|
||||
ide_adapter_uninit_controller(ide_adapter_controller_info *controller)
|
||||
{
|
||||
pnp->uninit_driver(pnp->get_parent(controller->node));
|
||||
|
||||
free(controller);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ide_adapter_controller_removed(device_node_handle node,
|
||||
ide_adapter_controller_info *controller)
|
||||
ide_adapter_controller_removed(ide_adapter_controller_info *controller)
|
||||
{
|
||||
SHOW_FLOW0(3, "");
|
||||
|
||||
if (controller != NULL)
|
||||
if (controller != NULL) {
|
||||
// disable access instantly; unit_device takes care of unregistering ioports
|
||||
atomic_or(&controller->lost, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** publish node of ide controller */
|
||||
|
||||
static status_t
|
||||
ide_adapter_publish_controller(device_node_handle parent, uint16 bus_master_base,
|
||||
io_resource_handle *resources, const char *controller_driver,
|
||||
ide_adapter_publish_controller(device_node *parent, uint16 bus_master_base,
|
||||
io_resource *resources, const char *controller_driver,
|
||||
const char *controller_driver_type, const char *controller_name, bool can_dma,
|
||||
bool can_cq, uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
|
||||
device_node_handle *node)
|
||||
device_node **node)
|
||||
{
|
||||
device_attr attrs[] = {
|
||||
// info about ourself and our consumer
|
||||
{ B_DRIVER_MODULE, B_STRING_TYPE, { string: controller_driver }},
|
||||
|
||||
// properties of this controller for ide bus manager
|
||||
// there are always max. 2 devices
|
||||
// (unless this is a Compact Flash Card with a built-in IDE controller,
|
||||
@@ -683,20 +676,23 @@ ide_adapter_publish_controller(device_node_handle parent, uint16 bus_master_base
|
||||
|
||||
SHOW_FLOW0( 2, "" );
|
||||
|
||||
return pnp->register_device(parent, attrs, resources, node);
|
||||
return pnp->register_node(parent, controller_driver, attrs, resources, node);
|
||||
}
|
||||
|
||||
|
||||
/** detect pure IDE controller, i.e. without channels */
|
||||
|
||||
static status_t
|
||||
ide_adapter_detect_controller(pci_device_module_info *pci, pci_device pci_device,
|
||||
device_node_handle parent, uint16 bus_master_base, const char *controller_driver,
|
||||
ide_adapter_detect_controller(pci_device_module_info *pci, pci_device *pci_device,
|
||||
device_node *parent, uint16 bus_master_base, const char *controller_driver,
|
||||
const char *controller_driver_type, const char *controller_name, bool can_dma,
|
||||
bool can_cq, uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
|
||||
device_node_handle *node)
|
||||
device_node **node)
|
||||
{
|
||||
io_resource_handle resource_handles[2];
|
||||
io_resource resources[2] = {
|
||||
{ B_IO_PORT, bus_master_base, 16 },
|
||||
{}
|
||||
};
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
@@ -705,43 +701,31 @@ ide_adapter_detect_controller(pci_device_module_info *pci, pci_device pci_device
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
{
|
||||
io_resource resources[2] = {
|
||||
{ IO_PORT, bus_master_base, 16 },
|
||||
{}
|
||||
};
|
||||
|
||||
if (pnp->acquire_io_resources(resources, resource_handles) != B_OK) {
|
||||
TRACE("PCI-IDE: Couldn't acquire controller resource %#x\n", bus_master_base);
|
||||
return B_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return ide_adapter_publish_controller(parent, bus_master_base, resource_handles,
|
||||
return ide_adapter_publish_controller(parent, bus_master_base, resources,
|
||||
controller_driver, controller_driver_type, controller_name, can_dma, can_cq,
|
||||
dma_alignment, dma_boundary, max_sg_block_size, node);
|
||||
}
|
||||
|
||||
|
||||
static status_t
|
||||
ide_adapter_probe_controller(device_node_handle parent, const char *controller_driver,
|
||||
ide_adapter_probe_controller(device_node *parent, const char *controller_driver,
|
||||
const char *controller_driver_type, const char *controller_name,
|
||||
const char *channel_module_name, bool can_dma, bool can_cq, uint32 dma_alignment,
|
||||
uint32 dma_boundary, uint32 max_sg_block_size, bool supports_compatibility_mode)
|
||||
{
|
||||
pci_device_module_info *pci;
|
||||
pci_device device;
|
||||
pci_device *device;
|
||||
uint16 command_block_base[2];
|
||||
uint16 control_block_base[2];
|
||||
uint16 bus_master_base;
|
||||
device_node_handle controller_node, channels[2];
|
||||
device_node *controller_node;
|
||||
device_node *channels[2];
|
||||
uint8 intnum;
|
||||
status_t res;
|
||||
|
||||
SHOW_FLOW0( 3, "" );
|
||||
|
||||
if (pnp->init_driver(parent, NULL, (driver_module_info **)&pci, (void **)&device) != B_OK)
|
||||
return B_ERROR;
|
||||
pnp->get_driver(parent, (driver_module_info **)&pci, (void **)&device);
|
||||
|
||||
command_block_base[0] = pci->read_pci_config(device, PCI_base_registers, 4 );
|
||||
control_block_base[0] = pci->read_pci_config(device, PCI_base_registers + 4, 4);
|
||||
@@ -762,7 +746,7 @@ ide_adapter_probe_controller(device_node_handle parent, const char *controller_d
|
||||
// don't register if controller is already registered!
|
||||
// (happens during rescan; registering new channels would kick out old channels)
|
||||
if (res != B_OK || controller_node == NULL)
|
||||
goto err;
|
||||
return res;
|
||||
|
||||
// ignore errors during registration of channels - could be a simple rescan collision
|
||||
ide_adapter_detect_channel(pci, device, controller_node, channel_module_name,
|
||||
@@ -773,13 +757,7 @@ ide_adapter_probe_controller(device_node_handle parent, const char *controller_d
|
||||
can_dma, command_block_base[1], control_block_base[1], bus_master_base,
|
||||
intnum, 1, "Secondary Channel", &channels[1], supports_compatibility_mode);
|
||||
|
||||
pnp->uninit_driver(parent);
|
||||
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
pnp->uninit_driver(parent);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -811,6 +789,8 @@ static ide_adapter_interface adapter_interface = {
|
||||
std_ops
|
||||
},
|
||||
|
||||
set_channel,
|
||||
|
||||
ide_adapter_write_command_block_regs,
|
||||
ide_adapter_read_command_block_regs,
|
||||
|
||||
|
||||
@@ -21,9 +21,9 @@
|
||||
|
||||
|
||||
char *
|
||||
periph_compose_device_name(device_node_handle node, const char *prefix)
|
||||
periph_compose_device_name(device_node *node, const char *prefix)
|
||||
{
|
||||
uint8 pathID, targetID, targetLUN, isPrimary, type;
|
||||
uint8 pathID, targetID, targetLUN, type;
|
||||
char name[128];
|
||||
uint32 channel;
|
||||
|
||||
@@ -55,7 +55,7 @@ periph_compose_device_name(device_node_handle node, const char *prefix)
|
||||
|
||||
status_t
|
||||
periph_register_device(periph_device_cookie periph_device, scsi_periph_callbacks *callbacks,
|
||||
scsi_device scsi_device, scsi_device_interface *scsi, device_node_handle node,
|
||||
scsi_device scsi_device, scsi_device_interface *scsi, device_node *node,
|
||||
bool removable, scsi_periph_device *driver)
|
||||
{
|
||||
scsi_periph_device_info *device;
|
||||
|
||||
@@ -184,16 +184,14 @@ abort:
|
||||
static status_t
|
||||
inquiry(scsi_periph_device_info *device, scsi_inquiry *inquiry)
|
||||
{
|
||||
scsi_res_inquiry *device_inquiry = NULL;
|
||||
const scsi_res_inquiry *device_inquiry = NULL;
|
||||
size_t inquiry_len;
|
||||
|
||||
if (pnp->get_attr_raw(device->node, SCSI_DEVICE_INQUIRY_ITEM,
|
||||
(void **)&device_inquiry, &inquiry_len, true) != B_OK)
|
||||
(const void **)&device_inquiry, &inquiry_len, true) != B_OK)
|
||||
return B_ERROR;
|
||||
|
||||
memcpy(inquiry, device_inquiry, min(inquiry_len, sizeof(scsi_inquiry)));
|
||||
free(device_inquiry);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ typedef struct scsi_periph_device_info {
|
||||
scsi_device scsi_device;
|
||||
scsi_device_interface *scsi;
|
||||
periph_device_cookie periph_device;
|
||||
device_node_handle node;
|
||||
device_node *node;
|
||||
|
||||
bool removal_requested;
|
||||
|
||||
@@ -80,9 +80,9 @@ status_t periph_check_capacity(scsi_periph_device_info *device, scsi_ccb *ccb);
|
||||
|
||||
status_t periph_register_device(periph_device_cookie periph_device,
|
||||
scsi_periph_callbacks *callbacks, scsi_device scsi_device, scsi_device_interface *scsi,
|
||||
device_node_handle node, bool removable, scsi_periph_device *driver);
|
||||
device_node *node, bool removable, scsi_periph_device *driver);
|
||||
status_t periph_unregister_device(scsi_periph_device_info *driver);
|
||||
char *periph_compose_device_name(device_node_handle device_node, const char *prefix);
|
||||
char *periph_compose_device_name(device_node *device_node, const char *prefix);
|
||||
|
||||
|
||||
// io.c
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "BaseDevice.h"
|
||||
|
||||
|
||||
BaseDevice::BaseDevice()
|
||||
:
|
||||
fNode(NULL),
|
||||
fDeviceModule(NULL),
|
||||
fDeviceData(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
BaseDevice::~BaseDevice()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
BaseDevice::InitDevice()
|
||||
{
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BaseDevice::UninitDevice()
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef BASE_DEVICE_H
|
||||
#define BASE_DEVICE_H
|
||||
|
||||
|
||||
#include <device_manager.h>
|
||||
|
||||
|
||||
class BaseDevice {
|
||||
public:
|
||||
BaseDevice();
|
||||
virtual ~BaseDevice();
|
||||
|
||||
device_node* Node() const { return fNode; }
|
||||
|
||||
virtual status_t InitDevice();
|
||||
virtual void UninitDevice();
|
||||
|
||||
device_module_info* Module() const { return fDeviceModule; }
|
||||
void* Data() const { return fDeviceData; }
|
||||
|
||||
bool HasSelect() const
|
||||
{ return Module()->select != NULL; }
|
||||
bool HasDeselect() const
|
||||
{ return Module()->deselect != NULL; }
|
||||
bool HasRead() const
|
||||
{ return Module()->read != NULL; }
|
||||
bool HasWrite() const
|
||||
{ return Module()->write != NULL; }
|
||||
bool HasIO() const
|
||||
{ return Module()->io != NULL; }
|
||||
|
||||
virtual status_t Open(const char* path, int openMode,
|
||||
void** _cookie);
|
||||
status_t Read(void* cookie, off_t pos, void* buffer,
|
||||
size_t* _length);
|
||||
status_t Write(void* cookie, off_t pos, const void* buffer,
|
||||
size_t* _length);
|
||||
status_t IO(void* cookie, io_request* request);
|
||||
status_t Control(void* cookie, int32 op, void* buffer,
|
||||
size_t length);
|
||||
virtual status_t Select(void* cookie, uint8 event, selectsync* sync);
|
||||
status_t Deselect(void* cookie, uint8 event,
|
||||
selectsync* sync);
|
||||
|
||||
status_t Close(void* cookie);
|
||||
status_t Free(void* cookie);
|
||||
|
||||
protected:
|
||||
device_node* fNode;
|
||||
int32 fInitialized;
|
||||
device_module_info* fDeviceModule;
|
||||
void* fDeviceData;
|
||||
};
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Open(const char* path, int openMode, void** _cookie)
|
||||
{
|
||||
return Module()->open(Data(), path, openMode, _cookie);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Read(void* cookie, off_t pos, void* buffer, size_t* _length)
|
||||
{
|
||||
return Module()->read(cookie, pos, buffer, _length);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Write(void* cookie, off_t pos, const void* buffer, size_t* _length)
|
||||
{
|
||||
return Module()->write(cookie, pos, buffer, _length);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::IO(void* cookie, io_request* request)
|
||||
{
|
||||
return Module()->io(cookie, request);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Control(void* cookie, int32 op, void* buffer, size_t length)
|
||||
{
|
||||
return Module()->control(cookie, op, buffer, length);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Select(void* cookie, uint8 event, selectsync* sync)
|
||||
{
|
||||
return Module()->select(cookie, event, sync);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Deselect(void* cookie, uint8 event, selectsync* sync)
|
||||
{
|
||||
return Module()->deselect(cookie, event, sync);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Close(void* cookie)
|
||||
{
|
||||
return Module()->close(cookie);
|
||||
}
|
||||
|
||||
|
||||
inline status_t
|
||||
BaseDevice::Free(void* cookie)
|
||||
{
|
||||
return Module()->free(cookie);
|
||||
}
|
||||
|
||||
#endif // BASE_DEVICE_H
|
||||
@@ -4,18 +4,13 @@ UsePrivateHeaders [ FDirName kernel boot platform $(TARGET_BOOT_PLATFORM) ] ;
|
||||
UsePrivateHeaders [ FDirName kernel util ] shared ;
|
||||
|
||||
KernelMergeObject kernel_device_manager.o :
|
||||
attributes.c
|
||||
device_manager.c
|
||||
driver_loader.c
|
||||
id_generator.c
|
||||
io_resources.c
|
||||
nodes.c
|
||||
notifications.c
|
||||
patterns.c
|
||||
probe.cpp
|
||||
registration.c
|
||||
root_node.c
|
||||
scan.c
|
||||
BaseDevice.cpp
|
||||
device_manager.cpp
|
||||
devfs.cpp
|
||||
id_generator.cpp
|
||||
io_resources.cpp
|
||||
legacy_drivers.cpp
|
||||
# probe.cpp
|
||||
settings.cpp
|
||||
:
|
||||
$(TARGET_KERNEL_PIC_CCFLAGS) -Wno-unused
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEVFS_PRIVATE_H
|
||||
#define DEVFS_PRIVATE_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
class BaseDevice;
|
||||
|
||||
status_t devfs_publish_device(const char* path, BaseDevice* device);
|
||||
status_t devfs_get_device(dev_t device, ino_t node, BaseDevice** _device);
|
||||
|
||||
#endif /* DEVFS_PRIVATE_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,223 +1,10 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Copyright 2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef DEVICE_MANAGER_PRIVATE
|
||||
#define DEVICE_MANAGER_PRIVATE
|
||||
|
||||
/*
|
||||
Part of Device Manager
|
||||
Internal header.
|
||||
*/
|
||||
|
||||
#include <kdevice_manager.h>
|
||||
#include <util/list.h>
|
||||
|
||||
#include <lock.h>
|
||||
|
||||
#define GENERATOR_MAX_ID 64
|
||||
#define UNIVERSAL_SUBDIR "/universal"
|
||||
#define GENERIC_SUBDIR "/generic"
|
||||
|
||||
// driver registration directories
|
||||
#define PNP_DIR
|
||||
#define SYSTEM_DRIVER_REGISTRATION "/boot/beos/system/add-ons/kernel/"PNP_DIR"registration/"
|
||||
#define COMMON_DRIVER_REGISTRATION "/boot/home/config/add-ons/kernel/"PNP_DIR"registration/"
|
||||
|
||||
// info about ID generator
|
||||
typedef struct id_generator {
|
||||
struct list_link link;
|
||||
struct id_generator *prev, *next;
|
||||
int32 ref_count;
|
||||
char *name;
|
||||
uint32 num_ids;
|
||||
uint8 alloc_map[(GENERATOR_MAX_ID + 7) / 8];
|
||||
} id_generator;
|
||||
#ifndef DEVICE_MANAGER_PRIVATE_H
|
||||
#define DEVICE_MANAGER_PRIVATE_H
|
||||
|
||||
|
||||
// info about a node attribute
|
||||
typedef struct device_attr_info {
|
||||
struct device_attr_info *prev, *next;
|
||||
int32 ref_count; // reference count
|
||||
device_attr attr;
|
||||
} device_attr_info;
|
||||
|
||||
|
||||
// I/O resource
|
||||
typedef struct io_resource_info {
|
||||
struct io_resource_info *prev, *next;
|
||||
device_node_info *owner; // associated node; NULL for temporary allocation
|
||||
io_resource resource; // info about actual resource
|
||||
} io_resource_info;
|
||||
|
||||
|
||||
// a structure to put nodes into lists
|
||||
struct node_entry {
|
||||
struct list_link link;
|
||||
device_node_info *node;
|
||||
};
|
||||
|
||||
|
||||
// global lock
|
||||
// whenever you do something in terms of nodes, grab it
|
||||
extern benaphore gNodeLock;
|
||||
// root node
|
||||
extern device_node_info *gRootNode;
|
||||
|
||||
// true, if user addons are disabled via safemode
|
||||
extern bool disable_useraddons;
|
||||
|
||||
|
||||
// # of allocate_io_resource() calls waiting for a retry
|
||||
extern int pnp_resource_wait_count;
|
||||
// semaphore for allocate_io_resource() call retry
|
||||
extern sem_id pnp_resource_wait_sem;
|
||||
|
||||
// list of driver registration directories
|
||||
extern const char *pnp_registration_dirs[];
|
||||
|
||||
|
||||
// list of I/O memory, I/O ports and ISA DMA channels
|
||||
extern io_resource_info *io_mem_list, *io_port_list, *isa_dma_list;
|
||||
|
||||
|
||||
// nesting of pnp_load_boot_links calls
|
||||
int pnp_fs_emulation_nesting;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// attributes.c
|
||||
|
||||
device_attr_info *pnp_find_attr_nolock(device_node_handle node, const char *name,
|
||||
bool recursive, type_code type);
|
||||
status_t pnp_get_attr_uint8(device_node_handle node, const char *name,
|
||||
uint8 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint8_nolock(device_node_handle node, const char *name,
|
||||
uint8 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint16(device_node_handle node, const char *name,
|
||||
uint16 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint16_nolock(device_node_handle node, const char *name,
|
||||
uint16 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint32(device_node_handle node, const char *name,
|
||||
uint32 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint32_nolock(device_node_handle node, const char *name,
|
||||
uint32 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint64(device_node_handle node, const char *name,
|
||||
uint64 *value, bool recursive);
|
||||
status_t pnp_get_attr_uint64_nolock(device_node_handle node, const char *name,
|
||||
uint64 *value, bool recursive);
|
||||
status_t pnp_get_attr_string(device_node_handle node, const char *name,
|
||||
char **value, bool recursive);
|
||||
status_t pnp_get_attr_string_nolock(device_node_handle node, const char *name,
|
||||
const char **value, bool recursive);
|
||||
status_t pnp_get_attr_raw(device_node_handle node, const char *name,
|
||||
void **data, size_t *len, bool recursive);
|
||||
status_t pnp_get_attr_raw_nolock(device_node_handle node, const char *name,
|
||||
const void **data, size_t *len, bool recursive);
|
||||
void pnp_free_node_attr(device_attr_info *attr);
|
||||
status_t pnp_get_next_node_with_attrs(device_node_info **_node, const device_attr *attrs);
|
||||
int pnp_compare_attrs(const device_attr *attrA, const device_attr *attrB);
|
||||
status_t pnp_duplicate_node_attr(const device_attr *src, device_attr_info **dest_out);
|
||||
status_t pnp_get_next_attr(device_node_handle node, device_attr_handle *attr);
|
||||
status_t pnp_release_attr(device_node_handle node, device_attr_handle attr);
|
||||
status_t pnp_retrieve_attr(device_attr_handle attr, const device_attr **attr_content);
|
||||
status_t pnp_write_attr(device_node_handle node, const device_attr *attr);
|
||||
void pnp_remove_attr_int(device_node_handle node, device_attr_info *attr);
|
||||
status_t pnp_remove_attr(device_node_handle node, const char *name);
|
||||
|
||||
|
||||
// driver_loader.c
|
||||
|
||||
status_t pnp_load_driver(device_node_handle node, void *user_cookie,
|
||||
driver_module_info **interface, void **cookie);
|
||||
status_t pnp_unload_driver(device_node_handle node);
|
||||
void pnp_unblock_load(device_node_info *node);
|
||||
|
||||
|
||||
// id_generator.c
|
||||
|
||||
int32 dm_create_id(const char *name);
|
||||
status_t dm_free_id(const char *name, uint32 id);
|
||||
extern status_t dm_init_id_generator(void);
|
||||
|
||||
|
||||
// io_resources.c
|
||||
|
||||
status_t dm_acquire_io_resources(io_resource *resources, io_resource_handle *handles);
|
||||
status_t dm_release_io_resources(const io_resource_handle *handles);
|
||||
void dm_assign_io_resources(device_node_info *node, const io_resource_handle *handles);
|
||||
void dm_release_node_resources(device_node_info *node);
|
||||
|
||||
|
||||
// nodes.c
|
||||
|
||||
status_t dm_allocate_node(const device_attr *attrs, const io_resource_handle *resources,
|
||||
device_node_info **new_node);
|
||||
void dm_add_child_node(device_node_info *node, device_node_info *parent);
|
||||
void dm_get_node_nolock(device_node_info *node);
|
||||
void dm_get_node(device_node_info *node);
|
||||
void dm_put_node_nolock(device_node_info *node);
|
||||
void dm_dump_node(device_node_info *node, int32 level);
|
||||
status_t dm_init_nodes(void);
|
||||
|
||||
void dm_put_node(device_node_info *node);
|
||||
status_t dm_get_next_child_node(device_node_info *parent,
|
||||
device_node_info **_node, const device_attr *attrs);
|
||||
device_node_info *dm_get_root(void);
|
||||
device_node_info *dm_get_parent(device_node_info *node);
|
||||
|
||||
status_t device_manager_control(const char *subsystem, uint32 function, void *buffer, size_t bufferSize);
|
||||
|
||||
|
||||
// notifications.c
|
||||
|
||||
status_t dm_notify_unregistration(device_node_info *node);
|
||||
void pnp_start_hook_call(device_node_info *node);
|
||||
void pnp_start_hook_call_nolock(device_node_info *node);
|
||||
void pnp_finish_hook_call(device_node_info *node);
|
||||
void pnp_finish_hook_call_nolock(device_node_info *node);
|
||||
|
||||
|
||||
// patterns.c
|
||||
|
||||
status_t pnp_expand_pattern(device_node_info *node, const char *pattern,
|
||||
char *dest, char *buffer, size_t *term_array, int *num_parts);
|
||||
status_t pnp_expand_pattern_attr(device_node_info *node, const char *attr_name,
|
||||
char **expanded);
|
||||
|
||||
|
||||
// probe.cpp
|
||||
status_t dm_register_child_device(device_node_info *node, const char *childName, bool checkSupport);
|
||||
status_t dm_register_fixed_child_devices(device_node_info *node);
|
||||
status_t dm_register_dynamic_child_devices(device_node_info *node);
|
||||
|
||||
|
||||
// registration.c
|
||||
|
||||
status_t dm_register_node(device_node_handle parent, const device_attr *attrs,
|
||||
const io_resource_handle *resources, device_node_handle *_newNode);
|
||||
status_t dm_unregister_node(device_node_handle node);
|
||||
|
||||
void pnp_unref_unregistered_nodes(device_node_info *node_list);
|
||||
|
||||
|
||||
// root_node.c
|
||||
|
||||
void dm_init_root_node(void);
|
||||
|
||||
|
||||
// scan.c
|
||||
|
||||
status_t dm_rescan(device_node_handle node);
|
||||
status_t dm_register_child_devices(device_node_info *node);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* DEVICE_MANAGER_PRIVATE_H */
|
||||
#endif // DEVICE_MANAGER_PRIVATE_H
|
||||
|
||||
+81
-82
@@ -1,16 +1,11 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of the Device Manager
|
||||
|
||||
ID generator.
|
||||
|
||||
Generators are created on demand and deleted if all their
|
||||
/*! Generators are created on demand and deleted if all their
|
||||
IDs are freed. They have a ref_count which is increased
|
||||
whenever someone messes with the generator.
|
||||
|
||||
@@ -26,13 +21,17 @@
|
||||
*/
|
||||
|
||||
|
||||
#include "device_manager_private.h"
|
||||
#include <KernelExport.h>
|
||||
#include <util/list.h>
|
||||
#include "id_generator.h"
|
||||
|
||||
#include <new>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <util/AutoLock.h>
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
//#define TRACE_ID_GENERATOR
|
||||
#ifdef TRACE_ID_GENERATOR
|
||||
@@ -41,52 +40,68 @@
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
#define GENERATOR_MAX_ID 64
|
||||
|
||||
struct list sGenerators;
|
||||
static benaphore sGeneratorLock;
|
||||
struct id_generator : DoublyLinkedListLinkImpl<id_generator> {
|
||||
id_generator(const char* name)
|
||||
:
|
||||
ref_count(1),
|
||||
name(strdup(name)),
|
||||
num_ids(0)
|
||||
{
|
||||
memset(&alloc_map, 0, sizeof(alloc_map));
|
||||
}
|
||||
|
||||
~id_generator()
|
||||
{
|
||||
free(name);
|
||||
}
|
||||
|
||||
int32 ref_count;
|
||||
char* name;
|
||||
uint32 num_ids;
|
||||
uint8 alloc_map[(GENERATOR_MAX_ID + 7) / 8];
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<id_generator> GeneratorList;
|
||||
|
||||
|
||||
/** Create new generator
|
||||
* sGeneratorLock must be held
|
||||
*/
|
||||
GeneratorList sGenerators;
|
||||
static mutex sLock;
|
||||
|
||||
static id_generator *
|
||||
create_generator(const char *name)
|
||||
|
||||
/*! Create new generator.
|
||||
sLock must be held.
|
||||
*/
|
||||
static id_generator*
|
||||
create_generator(const char* name)
|
||||
{
|
||||
id_generator *generator;
|
||||
|
||||
TRACE(("create_generator(name: %s)\n", name));
|
||||
|
||||
generator = malloc(sizeof(*generator));
|
||||
id_generator* generator = new(std::nothrow) id_generator(name);
|
||||
if (generator == NULL)
|
||||
return NULL;
|
||||
|
||||
memset(generator, 0, sizeof(*generator));
|
||||
|
||||
generator->name = strdup(name);
|
||||
if (generator->name == NULL) {
|
||||
free(generator);
|
||||
delete generator;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
generator->ref_count = 1;
|
||||
|
||||
list_add_link_to_head(&sGenerators, generator);
|
||||
sGenerators.Add(generator);
|
||||
return generator;
|
||||
}
|
||||
|
||||
|
||||
/** Allocate id */
|
||||
|
||||
/*! Allocate ID */
|
||||
static int32
|
||||
create_id_internal(id_generator *generator)
|
||||
create_id_internal(id_generator* generator)
|
||||
{
|
||||
uint32 id;
|
||||
|
||||
TRACE(("create_id_internal(name: %s)\n", generator->name));
|
||||
|
||||
// see above: we use global instead of local lock
|
||||
benaphore_lock(&sGeneratorLock);
|
||||
MutexLocker _(sLock);
|
||||
|
||||
// simple bit search
|
||||
for (id = 0; id < GENERATOR_MAX_ID; ++id) {
|
||||
@@ -94,104 +109,92 @@ create_id_internal(id_generator *generator)
|
||||
TRACE((" id: %lu\n", id));
|
||||
|
||||
generator->alloc_map[id / 8] |= 1 << (id & 7);
|
||||
++generator->num_ids;
|
||||
generator->num_ids++;
|
||||
|
||||
benaphore_unlock(&sGeneratorLock);
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
||||
benaphore_unlock(&sGeneratorLock);
|
||||
|
||||
return B_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/** Find generator by name
|
||||
* sGeneratorLock must be held
|
||||
*/
|
||||
|
||||
static id_generator *
|
||||
find_generator(const char *name)
|
||||
/*! Gets a generator by name, and acquires a reference to it.
|
||||
sLock must be held.
|
||||
*/
|
||||
static id_generator*
|
||||
get_generator(const char* name)
|
||||
{
|
||||
id_generator *generator = NULL;
|
||||
|
||||
TRACE(("find_generator(name: %s)\n", name));
|
||||
|
||||
while ((generator = list_get_next_item(&sGenerators, generator)) != NULL) {
|
||||
GeneratorList::Iterator iterator = sGenerators.GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
id_generator* generator = iterator.Next();
|
||||
|
||||
if (!strcmp(generator->name, name)) {
|
||||
// increase ref_count, so it won't go away
|
||||
++generator->ref_count;
|
||||
break;
|
||||
generator->ref_count++;
|
||||
return generator;
|
||||
}
|
||||
}
|
||||
|
||||
return generator;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/** Decrease ref_count, deleting generator if not used anymore */
|
||||
|
||||
/*! Decrease ref_count, deleting generator if not used anymore */
|
||||
static void
|
||||
release_generator(id_generator *generator)
|
||||
{
|
||||
TRACE(("release_generator(name: %s)\n", generator->name));
|
||||
|
||||
benaphore_lock(&sGeneratorLock);
|
||||
MutexLocker _(sLock);
|
||||
|
||||
if (--generator->ref_count == 0) {
|
||||
// no one messes with generator
|
||||
if (generator->num_ids == 0) {
|
||||
TRACE((" Destroy %s\n", generator->name));
|
||||
// no IDs is allocated - destroy generator
|
||||
list_remove_link(generator);
|
||||
free(generator->name);
|
||||
free(generator);
|
||||
sGenerators.Remove(generator);
|
||||
delete generator;
|
||||
}
|
||||
}
|
||||
|
||||
benaphore_unlock(&sGeneratorLock);
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Private kernel API
|
||||
// #pragma mark - Private kernel API
|
||||
|
||||
|
||||
status_t
|
||||
void
|
||||
dm_init_id_generator(void)
|
||||
{
|
||||
list_init(&sGenerators);
|
||||
return benaphore_init(&sGeneratorLock, "id generator");
|
||||
new(&sGenerators) GeneratorList;
|
||||
mutex_init(&sLock, "id generator");
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Public module API
|
||||
// #pragma mark - Public module API
|
||||
|
||||
|
||||
/** Create automatic ID */
|
||||
|
||||
/*! Create automatic ID */
|
||||
int32
|
||||
dm_create_id(const char *name)
|
||||
dm_create_id(const char* name)
|
||||
{
|
||||
id_generator *generator;
|
||||
int32 id;
|
||||
|
||||
// find generator, create new if not there
|
||||
benaphore_lock(&sGeneratorLock);
|
||||
mutex_lock(&sLock);
|
||||
|
||||
generator = find_generator(name);
|
||||
id_generator* generator = get_generator(name);
|
||||
if (generator == NULL)
|
||||
generator = create_generator(name);
|
||||
|
||||
benaphore_unlock(&sGeneratorLock);
|
||||
mutex_unlock(&sLock);
|
||||
|
||||
if (generator == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
// get ID
|
||||
id = create_id_internal(generator);
|
||||
int32 id = create_id_internal(generator);
|
||||
|
||||
release_generator(generator);
|
||||
|
||||
@@ -200,21 +203,18 @@ dm_create_id(const char *name)
|
||||
}
|
||||
|
||||
|
||||
/** Free automatically generated ID */
|
||||
|
||||
/*! Free automatically generated ID */
|
||||
status_t
|
||||
dm_free_id(const char *name, uint32 id)
|
||||
dm_free_id(const char* name, uint32 id)
|
||||
{
|
||||
id_generator *generator;
|
||||
|
||||
TRACE(("dm_free_id(name: %s, id: %ld)\n", name, id));
|
||||
|
||||
// find generator
|
||||
benaphore_lock(&sGeneratorLock);
|
||||
mutex_lock(&sLock);
|
||||
|
||||
generator = find_generator(name);
|
||||
id_generator* generator = get_generator(name);
|
||||
|
||||
benaphore_unlock(&sGeneratorLock);
|
||||
mutex_unlock(&sLock);
|
||||
|
||||
if (generator == NULL) {
|
||||
TRACE((" Generator %s doesn't exist\n", name));
|
||||
@@ -226,7 +226,8 @@ dm_free_id(const char *name, uint32 id)
|
||||
// make sure it's really allocated
|
||||
// (very important to keep <num_ids> in sync
|
||||
if ((generator->alloc_map[id / 8] & (1 << (id & 7))) == 0) {
|
||||
dprintf("id %ld of generator %s wasn't allocated\n", id, generator->name);
|
||||
dprintf("id %ld of generator %s wasn't allocated\n", id,
|
||||
generator->name);
|
||||
|
||||
release_generator(generator);
|
||||
return B_BAD_VALUE;
|
||||
@@ -236,7 +237,5 @@ dm_free_id(const char *name, uint32 id)
|
||||
generator->num_ids--;
|
||||
|
||||
release_generator(generator);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef ID_GENERATOR_H
|
||||
#define ID_GENERATOR_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int32 dm_create_id(const char *name);
|
||||
status_t dm_free_id(const char *name, uint32 id);
|
||||
|
||||
void dm_init_id_generator(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* ID_GENERATOR_H */
|
||||
@@ -1,588 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
/*
|
||||
Part of Device Manager
|
||||
|
||||
I/O resource manager.
|
||||
|
||||
I/O resources are allocated in two flavours:
|
||||
1. explicit allocation for hardware detection ("temporary allocation")
|
||||
2. implicit allocation for registered devices
|
||||
|
||||
If hardware detection fails, the resources are freed explicitely,
|
||||
if it succeeds, ownership is transfered to the device node.
|
||||
|
||||
Resources allocation collision is handled in the following way:
|
||||
- during ownership transfer to a device node, all other device nodes
|
||||
that collide in terms of resources are removed
|
||||
- if two temporary allocations collide, one must wait
|
||||
- if a temporary allocation collides with a device node whose driver is
|
||||
loaded, the temporary allocation fails (waiting for the driver may
|
||||
be hopeless as the driver may stay in memory forever)
|
||||
- if a temporary allocation collides with a device node whose driver is
|
||||
not loaded, loading of the driver is blocked
|
||||
|
||||
To avoid deadlocks between temporary allocations, they are done atomically:
|
||||
either the entire allocation succeeds or fails. If it fails because of a
|
||||
collision with another temporary allocation, a complete retry is done as
|
||||
soon as someone released some resource.
|
||||
*/
|
||||
|
||||
#include "device_manager_private.h"
|
||||
#include "dl_list.h"
|
||||
|
||||
#include <KernelExport.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define TRACE_IO_RESOURCES
|
||||
#ifdef TRACE_IO_RESOURCES
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
// forward declarations to avoid inlining
|
||||
static void unblock_temporary_allocation(void);
|
||||
static void release_range(io_resource_info **list, io_resource_info *resource,
|
||||
io_resource_info *up_to);
|
||||
static void unregister_colliding_node_range(io_resource_info *list,
|
||||
io_resource_info *resource);
|
||||
|
||||
|
||||
/** validate I/O resource data */
|
||||
|
||||
static status_t
|
||||
validate_io_resource(io_resource *src)
|
||||
{
|
||||
TRACE(("validate_io_resource()\n"));
|
||||
|
||||
switch (src->type) {
|
||||
case IO_MEM:
|
||||
if (src->base + src->length < src->base)
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
case IO_PORT:
|
||||
if ((uint16)src->base != src->base
|
||||
|| (uint16)src->length != src->length
|
||||
|| (uint16)(src->base + src->length) < src->base)
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
case ISA_DMA_CHANNEL:
|
||||
if (src->base > 8 || src->length != 1)
|
||||
return B_BAD_VALUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
return B_BAD_VALUE;
|
||||
}
|
||||
|
||||
TRACE((" success!\n"));
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** Allocate info structure for I/O resources */
|
||||
|
||||
static status_t
|
||||
alloc_io_resource_info(io_resource *src, io_resource_info **dest_out)
|
||||
{
|
||||
io_resource_info *dest;
|
||||
|
||||
TRACE(("alloc_io_resource_info()\n"));
|
||||
|
||||
dest = calloc(1, sizeof(*dest));
|
||||
if (dest == NULL)
|
||||
return B_NO_MEMORY;
|
||||
|
||||
dest->owner = NULL;
|
||||
|
||||
dest->resource.type = src->type;
|
||||
dest->resource.base = src->base;
|
||||
dest->resource.length = src->length;
|
||||
|
||||
*dest_out = dest;
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** Acquire I/O range; returns B_WOULD_BLOCK on collision with
|
||||
* temporary allocation.
|
||||
* gNodeLock must be held
|
||||
*/
|
||||
|
||||
static status_t
|
||||
acquire_range(io_resource_info **list, io_resource_info *resource)
|
||||
{
|
||||
io_resource_info *cur;
|
||||
uint32 base = resource->resource.base;
|
||||
uint32 length = resource->resource.length;
|
||||
status_t res = B_OK;
|
||||
|
||||
TRACE(("acquire_range(base %lx, length %lx)\n", base, length));
|
||||
|
||||
for (cur = *list; cur != NULL; cur = cur->next) {
|
||||
// we need the "base + length - 1" trick to avoid wrap around at 4 GB
|
||||
if (cur->resource.base >= base
|
||||
&& cur->resource.base + length - 1 <= base + length - 1) {
|
||||
device_node_info *owner = cur->owner;
|
||||
|
||||
TRACE((" collision\n"));
|
||||
|
||||
if (owner == NULL) {
|
||||
// collision with temporary allocation - block ourself
|
||||
TRACE((" collision with temporary allocation - retry later\n"));
|
||||
|
||||
res = B_WOULD_BLOCK;
|
||||
break;
|
||||
} else {
|
||||
// collision with device
|
||||
if (owner->loading + owner->load_count > 0) {
|
||||
// driver is already loaded - give up
|
||||
// (driver may get loaded forever)
|
||||
TRACE((" collision with loaded driver - giving up\n"));
|
||||
|
||||
res = B_BUSY;
|
||||
break;
|
||||
} else {
|
||||
// driver is not loaded - block loading
|
||||
TRACE((" collision with unloaded driver - block driver %p\n", owner));
|
||||
|
||||
++owner->load_block_count;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (cur != NULL) {
|
||||
// collided with someone
|
||||
TRACE((" Resource collision\n"));
|
||||
|
||||
release_range(list, resource, cur);
|
||||
return res;
|
||||
}
|
||||
|
||||
ADD_DL_LIST_HEAD(resource, *list, );
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
/** Free I/O resource info */
|
||||
|
||||
static void
|
||||
free_io_resource_info(io_resource_info *resource)
|
||||
{
|
||||
TRACE(("free_io_resource_info()\n"));
|
||||
|
||||
free(resource);
|
||||
}
|
||||
|
||||
|
||||
/** Acquire I/O resource.
|
||||
* An I/O resource info structure is allocated and added to
|
||||
* appropriate resource list (i.e. mem/port/channel) plus
|
||||
* all colliding resources (including ours) are marked blocked;
|
||||
* returns B_WOULD_BLOCK on collision with temporary allocation;
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
acquire_io_resource(io_resource *src, io_resource_handle *dest_out)
|
||||
{
|
||||
io_resource_info *dest;
|
||||
status_t res;
|
||||
|
||||
TRACE(("acquire_io_resource(type = %ld, base = %lx, length = %lx)\n",
|
||||
src->type, src->base, src->length));
|
||||
|
||||
res = validate_io_resource(src);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
res = alloc_io_resource_info(src, &dest);
|
||||
if (res != B_OK)
|
||||
return res;
|
||||
|
||||
switch (src->type) {
|
||||
case IO_MEM:
|
||||
res = acquire_range(&io_mem_list, dest);
|
||||
break;
|
||||
case IO_PORT:
|
||||
res = acquire_range(&io_port_list, dest);
|
||||
break;
|
||||
case ISA_DMA_CHANNEL:
|
||||
res = acquire_range(&isa_dma_list, dest);
|
||||
break;
|
||||
}
|
||||
|
||||
if (res != B_OK)
|
||||
// collided with someone
|
||||
goto err;
|
||||
|
||||
*dest_out = dest;
|
||||
|
||||
TRACE((" done\n"));
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
free_io_resource_info(dest);
|
||||
|
||||
TRACE((" failed: %s\n", strerror(res)));
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/** Release I/O resource.
|
||||
* gNodeLock must be held
|
||||
*/
|
||||
|
||||
static void
|
||||
release_io_resource(io_resource_info *resource)
|
||||
{
|
||||
TRACE(("release_io_resource()\n"));
|
||||
|
||||
switch (resource->resource.type) {
|
||||
case IO_MEM:
|
||||
release_range(&io_mem_list, resource, NULL);
|
||||
break;
|
||||
case IO_PORT:
|
||||
release_range(&io_port_list, resource, NULL);
|
||||
break;
|
||||
case ISA_DMA_CHANNEL:
|
||||
release_range(&isa_dma_list, resource, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
free_io_resource_info(resource);
|
||||
}
|
||||
|
||||
|
||||
/** Release I/O range, which can be I/O memory, ports and ISA DMA channels
|
||||
* up_to - up to but not including colliding range to be released
|
||||
* (NULL for normal release, not-NULL if used during failed allocation)
|
||||
* blocked users get notified;
|
||||
* gNodeLock must be held
|
||||
*/
|
||||
|
||||
static void
|
||||
release_range(io_resource_info **list, io_resource_info *resource, io_resource_info *up_to)
|
||||
{
|
||||
io_resource_info *cur;
|
||||
uint32 base = resource->resource.base;
|
||||
uint32 length = resource->resource.length;
|
||||
|
||||
TRACE(("release_range()\n"));
|
||||
|
||||
for (cur = *list; cur != NULL && cur != up_to; cur = cur->next) {
|
||||
if (cur == resource)
|
||||
// ignore ourselves
|
||||
continue;
|
||||
|
||||
// we need the "base + length - 1" trick to avoid wrap around at 4 GB
|
||||
if (cur->resource.base >= base && cur->resource.base + length - 1 <= base + length - 1) {
|
||||
device_node_info *owner = cur->owner;
|
||||
|
||||
TRACE((" unblock\n"));
|
||||
|
||||
if (owner != NULL) {
|
||||
// collision with driver - unblock it
|
||||
TRACE((" collision with driver - unblock driver %p\n", owner));
|
||||
|
||||
pnp_unblock_load(owner);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (up_to == NULL) {
|
||||
// normal release - remove from list and
|
||||
// notify blocked temporary allocations
|
||||
REMOVE_DL_LIST(resource, *list, );
|
||||
|
||||
unblock_temporary_allocation();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Wait until someone freed some resource or
|
||||
* allocated some resource permanently.
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
static void
|
||||
wait_for_resources(void)
|
||||
{
|
||||
TRACE(("wait_for_resources()\n"));
|
||||
|
||||
++pnp_resource_wait_count;
|
||||
|
||||
// we have to release while waiting
|
||||
benaphore_unlock(&gNodeLock);
|
||||
|
||||
acquire_sem(pnp_resource_wait_sem);
|
||||
|
||||
benaphore_lock(&gNodeLock);
|
||||
}
|
||||
|
||||
|
||||
/** Try to acquire list of resources.
|
||||
* returns B_WOULD_BLOCK on collision with temporary allocation.
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
try_acquire_io_resources(io_resource *resources, io_resource_handle *handles)
|
||||
{
|
||||
io_resource *resource;
|
||||
io_resource_handle *handle, *handle2;
|
||||
status_t res = B_OK;
|
||||
|
||||
for (resource = resources, handle = handles;
|
||||
resource->type != 0; ++resource, ++handle) {
|
||||
res = acquire_io_resource(resource, handle);
|
||||
if (res != B_OK)
|
||||
break;
|
||||
}
|
||||
|
||||
if (res != B_OK)
|
||||
goto err;
|
||||
|
||||
*handle++ = NULL;
|
||||
|
||||
return B_OK;
|
||||
|
||||
err:
|
||||
// collision detected: free all previously acquired resources
|
||||
for (handle2 = handle; handle2 != handle; ++handle2)
|
||||
release_io_resource(*handle2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/** Acquire I/O resources.
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
static status_t
|
||||
acquire_io_resources(io_resource *resources, io_resource_handle *handles)
|
||||
{
|
||||
// try allocation until we either got all resources or
|
||||
// detected a collision with a loaded device node
|
||||
while (true) {
|
||||
status_t res;
|
||||
|
||||
// allocate all resources
|
||||
res = try_acquire_io_resources( resources, handles );
|
||||
if (res == B_OK)
|
||||
return B_OK;
|
||||
|
||||
if (res == B_WOULD_BLOCK) {
|
||||
// collision with temporary allocation:
|
||||
// wait until some resource is freed or blocked forever
|
||||
// by a loaded driver
|
||||
wait_for_resources();
|
||||
} else {
|
||||
// collided with loaded node - no point waiting for the node
|
||||
TRACE(("acquire_io_resouces(): Collision with loaded device node\n"));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Unregister devices that collide with one of our I/O resources */
|
||||
|
||||
static void
|
||||
unregister_colliding_nodes(const io_resource_handle *resources)
|
||||
{
|
||||
const io_resource_handle *resource;
|
||||
|
||||
for (resource = resources; *resource != NULL; ++resource) {
|
||||
switch ((*resource)->resource.type) {
|
||||
case IO_MEM:
|
||||
unregister_colliding_node_range(io_mem_list, *resource);
|
||||
break;
|
||||
case IO_PORT:
|
||||
unregister_colliding_node_range(io_port_list, *resource);
|
||||
break;
|
||||
case ISA_DMA_CHANNEL:
|
||||
unregister_colliding_node_range(isa_dma_list, *resource);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Unregister device nodes that collide with I/O resource */
|
||||
|
||||
static void
|
||||
unregister_colliding_node_range(io_resource_info *list, io_resource_info *resource)
|
||||
{
|
||||
io_resource_info *cur;
|
||||
uint32 base = resource->resource.base;
|
||||
uint32 length = resource->resource.length;
|
||||
|
||||
do {
|
||||
for (cur = list; cur != NULL; cur = cur->next) {
|
||||
// ignore ourself
|
||||
if (cur == resource)
|
||||
continue;
|
||||
|
||||
// we need the "base + length - 1" trick to avoid wrap around at 4 GB
|
||||
if (cur->resource.base >= base
|
||||
&& cur->resource.base + length - 1 <= base + length - 1) {
|
||||
device_node_handle owner = cur->owner;
|
||||
|
||||
if (owner == NULL)
|
||||
panic("Transfer of I/O resources from temporary to device node collided with other temporary allocation");
|
||||
|
||||
TRACE(("Deleting colliding device node %p\n", owner));
|
||||
|
||||
// make sure node still exists after we'll have released lock
|
||||
++owner->ref_count;
|
||||
|
||||
// we have to release lock during unregistration
|
||||
benaphore_unlock(&gNodeLock);
|
||||
|
||||
// unregister device node - we own its resources now
|
||||
// (its resources are freed by the next remove_node_ref call)
|
||||
dm_unregister_node(owner);
|
||||
|
||||
benaphore_lock(&gNodeLock);
|
||||
|
||||
dm_put_node_nolock(owner);
|
||||
// restart loop as resource list may have changed meanwhile
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (cur != NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Unblock other temporary allocations so they can retry.
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
static void
|
||||
unblock_temporary_allocation(void)
|
||||
{
|
||||
if (pnp_resource_wait_count > 0) {
|
||||
TRACE(("unblock concurrent temporary allocation\n"));
|
||||
|
||||
release_sem_etc(pnp_resource_wait_sem, pnp_resource_wait_count, 0);
|
||||
pnp_resource_wait_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
/** Transfer temporary I/O resources to device node;
|
||||
* colliding devices are unregistered.
|
||||
*/
|
||||
|
||||
void
|
||||
dm_assign_io_resources(device_node_info *node, const io_resource_handle *resources)
|
||||
{
|
||||
io_resource_handle *resource;
|
||||
|
||||
if (resources == NULL)
|
||||
return;
|
||||
|
||||
unregister_colliding_nodes(resources);
|
||||
|
||||
memcpy(node->io_resources, resources,
|
||||
(node->num_io_resources + 1) * sizeof(io_resource_handle));
|
||||
|
||||
benaphore_lock(&gNodeLock);
|
||||
|
||||
for (resource = node->io_resources; *resource != NULL; ++resource) {
|
||||
(*resource)->owner = node;
|
||||
}
|
||||
|
||||
// as the resources were only temporary previously, other temporary
|
||||
// allocations may be waiting for us; time to wake them, so they can
|
||||
// give up
|
||||
unblock_temporary_allocation();
|
||||
|
||||
benaphore_unlock(&gNodeLock);
|
||||
}
|
||||
|
||||
|
||||
/** Release I/O resources of a device node and set list to NULL;
|
||||
* users previously blocked by our resource alloction are notified;
|
||||
* gNodeLock must be held.
|
||||
*/
|
||||
|
||||
void
|
||||
dm_release_node_resources(device_node_info *node)
|
||||
{
|
||||
io_resource_handle *resource;
|
||||
|
||||
if (*node->io_resources != NULL)
|
||||
TRACE(("freeing I/O resources of node %p\n", node));
|
||||
|
||||
for (resource = node->io_resources; *resource != NULL; ++resource) {
|
||||
// set owner to NULL as we don't want to resource anymore
|
||||
(*resource)->owner = NULL;
|
||||
release_io_resource(*resource);
|
||||
}
|
||||
|
||||
// make sure we won't release resources twice
|
||||
*node->io_resources = NULL;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
// Part of the module API
|
||||
|
||||
|
||||
/** acquire I/O resources */
|
||||
|
||||
status_t
|
||||
dm_acquire_io_resources(io_resource *resources, io_resource_handle *handles)
|
||||
{
|
||||
status_t status;
|
||||
|
||||
TRACE(("dm_acquire_io_resources()\n"));
|
||||
|
||||
benaphore_lock(&gNodeLock);
|
||||
status = acquire_io_resources(resources, handles);
|
||||
benaphore_unlock(&gNodeLock);
|
||||
|
||||
TRACE((" done (%s)\n", strerror(status)));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/** release I/O resources */
|
||||
|
||||
status_t
|
||||
dm_release_io_resources(const io_resource_handle *handles)
|
||||
{
|
||||
io_resource_info *const *resource;
|
||||
|
||||
if (handles == NULL)
|
||||
return B_OK;
|
||||
|
||||
benaphore_lock(&gNodeLock);
|
||||
|
||||
for (resource = handles; *resource != NULL; ++resource)
|
||||
release_io_resource(*resource);
|
||||
|
||||
benaphore_unlock(&gNodeLock);
|
||||
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-2004, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
|
||||
|
||||
#include "io_resources.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
//#define TRACE_IO_RESOURCES
|
||||
#ifdef TRACE_IO_RESOURCES
|
||||
# define TRACE(x) dprintf x
|
||||
#else
|
||||
# define TRACE(x) ;
|
||||
#endif
|
||||
|
||||
|
||||
typedef DoublyLinkedList<io_resource_private,
|
||||
DoublyLinkedListMemberGetLink<io_resource_private,
|
||||
&io_resource_private::fTypeLink> > ResourceTypeList;
|
||||
|
||||
|
||||
static ResourceTypeList sMemoryList;
|
||||
static ResourceTypeList sPortList;
|
||||
static ResourceTypeList sDMAChannelList;
|
||||
|
||||
|
||||
io_resource_private::io_resource_private()
|
||||
{
|
||||
_Init();
|
||||
}
|
||||
|
||||
|
||||
io_resource_private::~io_resource_private()
|
||||
{
|
||||
Release();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
io_resource_private::_Init()
|
||||
{
|
||||
type = 0;
|
||||
base = 0;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
|
||||
status_t
|
||||
io_resource_private::Acquire(const io_resource& resource)
|
||||
{
|
||||
if (!_IsValid(resource))
|
||||
return B_BAD_VALUE;
|
||||
|
||||
type = resource.type;
|
||||
base = resource.base;
|
||||
|
||||
if (type != B_ISA_DMA_CHANNEL)
|
||||
length = resource.length;
|
||||
else
|
||||
length = 1;
|
||||
|
||||
ResourceTypeList* list = NULL;
|
||||
|
||||
switch (type) {
|
||||
case B_IO_MEMORY:
|
||||
list = &sMemoryList;
|
||||
break;
|
||||
case B_IO_PORT:
|
||||
list = &sPortList;
|
||||
break;
|
||||
case B_ISA_DMA_CHANNEL:
|
||||
list = &sDMAChannelList;
|
||||
break;
|
||||
}
|
||||
|
||||
ResourceTypeList::Iterator iterator = list->GetIterator();
|
||||
while (iterator.HasNext()) {
|
||||
io_resource* resource = iterator.Next();
|
||||
|
||||
// we need the "base + length - 1" trick to avoid wrap around at 4 GB
|
||||
if (resource->base >= base
|
||||
&& resource->base + length - 1 <= base + length - 1) {
|
||||
// This range is already covered by someone else
|
||||
// TODO: we might want to ignore resources that belong to
|
||||
// a node that isn't used.
|
||||
return B_RESOURCE_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
list->Add(this);
|
||||
return B_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
io_resource_private::Release()
|
||||
{
|
||||
if (type == 0)
|
||||
return;
|
||||
|
||||
switch (type) {
|
||||
case B_IO_MEMORY:
|
||||
sMemoryList.Remove(this);
|
||||
break;
|
||||
case B_IO_PORT:
|
||||
sPortList.Remove(this);
|
||||
break;
|
||||
case B_ISA_DMA_CHANNEL:
|
||||
sDMAChannelList.Remove(this);
|
||||
break;
|
||||
}
|
||||
|
||||
_Init();
|
||||
}
|
||||
|
||||
|
||||
/*static*/ bool
|
||||
io_resource_private::_IsValid(const io_resource& resource)
|
||||
{
|
||||
switch (resource.type) {
|
||||
case B_IO_MEMORY:
|
||||
return resource.base + resource.length > resource.base;
|
||||
case B_IO_PORT:
|
||||
return (uint16)resource.base == resource.base
|
||||
&& (uint16)resource.length == resource.length
|
||||
&& resource.base + resource.length > resource.base;
|
||||
case B_ISA_DMA_CHANNEL:
|
||||
return resource.base <= 8;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
void
|
||||
dm_init_io_resources(void)
|
||||
{
|
||||
new(&sMemoryList) ResourceTypeList;
|
||||
new(&sPortList) ResourceTypeList;
|
||||
new(&sDMAChannelList) ResourceTypeList;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright 2004-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Copyright 2002-04, Thomas Kurschel. All rights reserved.
|
||||
*
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef IO_RESOURCES_H
|
||||
#define IO_RESOURCES_H
|
||||
|
||||
|
||||
#include <device_manager.h>
|
||||
|
||||
#include <util/DoublyLinkedList.h>
|
||||
|
||||
|
||||
struct io_resource_private : io_resource,
|
||||
DoublyLinkedListLinkImpl<io_resource_private> {
|
||||
io_resource_private();
|
||||
~io_resource_private();
|
||||
|
||||
status_t Acquire(const io_resource& resource);
|
||||
void Release();
|
||||
|
||||
private:
|
||||
void _Init();
|
||||
static bool _IsValid(const io_resource& resource);
|
||||
|
||||
public:
|
||||
DoublyLinkedListLink<io_resource_private> fTypeLink;
|
||||
};
|
||||
|
||||
typedef DoublyLinkedList<io_resource_private> ResourceList;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dm_init_io_resources(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* IO_RESOURCES_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef LEGACY_DRIVERS_H
|
||||
#define LEGACY_DRIVERS_H
|
||||
|
||||
|
||||
#include <Drivers.h>
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
status_t legacy_driver_add(const char* path);
|
||||
status_t legacy_driver_publish(const char* path, device_hooks* hooks);
|
||||
status_t legacy_driver_rescan(const char* driverName);
|
||||
status_t legacy_driver_probe(const char* path);
|
||||
status_t legacy_driver_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LEGACY_DRIVERS_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,6 @@ UsePrivateHeaders [ FDirName kernel util ] ;
|
||||
UsePrivateHeaders net shared storage ;
|
||||
|
||||
KernelMergeObject kernel_fs.o :
|
||||
devfs.cpp
|
||||
fd.cpp
|
||||
fifo.cpp
|
||||
IOScheduler.cpp
|
||||
|
||||
@@ -275,7 +275,7 @@ main2(void *unused)
|
||||
device_manager_init(&sKernelArgs);
|
||||
|
||||
TRACE("Add preloaded old-style drivers\n");
|
||||
devfs_add_preloaded_drivers(&sKernelArgs);
|
||||
legacy_driver_add_preloaded(&sKernelArgs);
|
||||
|
||||
int_init_post_device_manager(&sKernelArgs);
|
||||
|
||||
|
||||
@@ -45,7 +45,6 @@
|
||||
*/
|
||||
extern module_info gDeviceManagerModule;
|
||||
extern module_info gDeviceRootModule;
|
||||
extern module_info gDeviceForDriversModule;
|
||||
extern module_info gFrameBufferConsoleModule;
|
||||
|
||||
// file systems
|
||||
@@ -55,7 +54,6 @@ extern module_info gDeviceFileSystem;
|
||||
static module_info *sBuiltInModules[] = {
|
||||
&gDeviceManagerModule,
|
||||
&gDeviceRootModule,
|
||||
&gDeviceForDriversModule,
|
||||
&gFrameBufferConsoleModule,
|
||||
|
||||
&gRootFileSystem,
|
||||
|
||||
Reference in New Issue
Block a user