17f33d2c1SStephan Aßmus/*
293c0a5d7SAxel Dörfler * Copyright 2005-2015, Axel D��rfler, axeld@pinc-software.de. All rights reserved.
37f33d2c1SStephan Aßmus * Copyright 2002-04, Thomas Kurschel. All rights reserved.
47f33d2c1SStephan Aßmus *
57f33d2c1SStephan Aßmus * Distributed under the terms of the MIT License.
67f33d2c1SStephan Aßmus */
77f33d2c1SStephan Aßmus#ifndef _ATA_PCI_H
87f33d2c1SStephan Aßmus#define _ATA_PCI_H
97f33d2c1SStephan Aßmus
1093c0a5d7SAxel Dörfler
1193c0a5d7SAxel Dörfler/*!	ATA adapter library
127f33d2c1SStephan Aßmus
137f33d2c1SStephan Aßmus	Module to simplify writing an ATA adapter driver.
147f33d2c1SStephan Aßmus
157f33d2c1SStephan Aßmus	The interface is not very abstract, i.e. the actual driver is
167f33d2c1SStephan Aßmus	free to access any controller or channel data of this library.
177f33d2c1SStephan Aßmus*/
187f33d2c1SStephan Aßmus
197f33d2c1SStephan Aßmus
207f33d2c1SStephan Aßmus#include <bus/ATA.h>
217f33d2c1SStephan Aßmus#include <bus/PCI.h>
227f33d2c1SStephan Aßmus#include <ata_types.h>
237f33d2c1SStephan Aßmus
247f33d2c1SStephan Aßmus
257f33d2c1SStephan Aßmus// one Physical Region Descriptor (PRD)
267f33d2c1SStephan Aßmus// (one region must not cross 64K boundary;
277f33d2c1SStephan Aßmus//  the PRD table must not cross a 64K boundary)
287f33d2c1SStephan Aßmustypedef struct prd_entry {
297f33d2c1SStephan Aßmus	uint32 address;				// physical address of block (must be even)
307f33d2c1SStephan Aßmus	uint16 count;				// size of block, 0 stands for 65536 (must be even)
317f33d2c1SStephan Aßmus	uint8 res6;
3293c0a5d7SAxel Dörfler	B_LBITFIELD8_2(
337f33d2c1SStephan Aßmus		res7_0 : 7,
347f33d2c1SStephan Aßmus		EOT : 1					// 1 for last entry
357f33d2c1SStephan Aßmus	);
367f33d2c1SStephan Aßmus} prd_entry;
377f33d2c1SStephan Aßmus
387f33d2c1SStephan Aßmus// IDE bus master command register
397f33d2c1SStephan Aßmus#define ATA_BM_COMMAND_START_STOP		0x01
407f33d2c1SStephan Aßmus#define ATA_BM_COMMAND_READ_FROM_DEVICE	0x08
417f33d2c1SStephan Aßmus
427f33d2c1SStephan Aßmus// IDE bus master status register
437f33d2c1SStephan Aßmus#define ATA_BM_STATUS_ACTIVE		0x01
447f33d2c1SStephan Aßmus#define ATA_BM_STATUS_ERROR			0x02
457f33d2c1SStephan Aßmus#define ATA_BM_STATUS_INTERRUPT		0x04
467f33d2c1SStephan Aßmus#define ATA_BM_STATUS_MASTER_DMA	0x20
477f33d2c1SStephan Aßmus#define ATA_BM_STATUS_SLAVE_DMA		0x40
487f33d2c1SStephan Aßmus#define ATA_BM_STATUS_SIMPLEX_DMA	0x80
497f33d2c1SStephan Aßmus
507f33d2c1SStephan Aßmus// offset of bus master registers
517f33d2c1SStephan Aßmusenum {
527f33d2c1SStephan Aßmus	ATA_BM_COMMAND_REG	= 0,
537f33d2c1SStephan Aßmus	ATA_BM_STATUS_REG	= 2,
547f33d2c1SStephan Aßmus	ATA_BM_PRDT_ADDRESS	= 4
557f33d2c1SStephan Aßmus		// offset of PRDT register; content must be dword-aligned
567f33d2c1SStephan Aßmus};
577f33d2c1SStephan Aßmus
587f33d2c1SStephan Aßmus
597f33d2c1SStephan Aßmus// (maximum) size of S/G table
607f33d2c1SStephan Aßmus// there are so many restrictions that we want to keep it inside one page
617f33d2c1SStephan Aßmus// to be sure that we fulfill them all
627f33d2c1SStephan Aßmus#define ATA_ADAPTER_MAX_SG_COUNT (B_PAGE_SIZE / sizeof( prd_entry ))
637f33d2c1SStephan Aßmus
647f33d2c1SStephan Aßmus
657f33d2c1SStephan Aßmus// channel node items
667f33d2c1SStephan Aßmus// io address of command block (uint16)
677f33d2c1SStephan Aßmus#define ATA_ADAPTER_COMMAND_BLOCK_BASE "ata_adapter/command_block_base"
687f33d2c1SStephan Aßmus// io address of control block (uint16)
697f33d2c1SStephan Aßmus#define ATA_ADAPTER_CONTROL_BLOCK_BASE "ata_adapter/control_block_base"
707f33d2c1SStephan Aßmus// interrupt number (uint8)
717f33d2c1SStephan Aßmus// can also be defined in controller node if both channels use same IRQ!
727f33d2c1SStephan Aßmus#define ATA_ADAPTER_INTNUM "ata_adapter/irq"
737f33d2c1SStephan Aßmus// 0 if primary channel, 1 if secondary channel, 2 if tertiary, ... (uint8)
747f33d2c1SStephan Aßmus#define ATA_ADAPTER_CHANNEL_INDEX "ata_adapter/channel_index"
757f33d2c1SStephan Aßmus
767f33d2c1SStephan Aßmus// controller node items
777f33d2c1SStephan Aßmus// io address of bus master registers (uint16)
787f33d2c1SStephan Aßmus#define ATA_ADAPTER_BUS_MASTER_BASE "ata_adapter/bus_master_base"
797f33d2c1SStephan Aßmus
807f33d2c1SStephan Aßmus
817f33d2c1SStephan Aßmus// info about one channel
827f33d2c1SStephan Aßmustypedef struct ata_adapter_channel_info {
837f33d2c1SStephan Aßmus	pci_device_module_info *pci;
847f33d2c1SStephan Aßmus	pci_device *device;
857f33d2c1SStephan Aßmus
867f33d2c1SStephan Aßmus	uint16 command_block_base;	// io address command block
877f33d2c1SStephan Aßmus	uint16 control_block_base; // io address control block
887f33d2c1SStephan Aßmus	uint16 bus_master_base;
897f33d2c1SStephan Aßmus	int intnum;				// interrupt number
907f33d2c1SStephan Aßmus
917f33d2c1SStephan Aßmus	uint32 lost;			// != 0 if device got removed, i.e. if it must not
927f33d2c1SStephan Aßmus							// be accessed anymore
937f33d2c1SStephan Aßmus
947f33d2c1SStephan Aßmus	ata_channel ataChannel;
957f33d2c1SStephan Aßmus	device_node *node;
967f33d2c1SStephan Aßmus
977f33d2c1SStephan Aßmus	int32 (*inthand)( void *arg );
987f33d2c1SStephan Aßmus
997f33d2c1SStephan Aßmus	area_id prd_area;
1007f33d2c1SStephan Aßmus	prd_entry *prdt;
1017f33d2c1SStephan Aßmus	uint32 prdt_phys;
1027f33d2c1SStephan Aßmus	uint32 dmaing;
1037f33d2c1SStephan Aßmus} ata_adapter_channel_info;
1047f33d2c1SStephan Aßmus
1057f33d2c1SStephan Aßmus
1067f33d2c1SStephan Aßmus// info about controller
1077f33d2c1SStephan Aßmustypedef struct ata_adapter_controller_info {
1087f33d2c1SStephan Aßmus	pci_device_module_info *pci;
1097f33d2c1SStephan Aßmus	pci_device *device;
1107f33d2c1SStephan Aßmus
1117f33d2c1SStephan Aßmus	uint16 bus_master_base;
1127f33d2c1SStephan Aßmus
1137f33d2c1SStephan Aßmus	uint32 lost;			// != 0 if device got removed, i.e. if it must not
1147f33d2c1SStephan Aßmus							// be accessed anymore
1157f33d2c1SStephan Aßmus
1167f33d2c1SStephan Aßmus	device_node *node;
1177f33d2c1SStephan Aßmus} ata_adapter_controller_info;
1187f33d2c1SStephan Aßmus
1197f33d2c1SStephan Aßmus
1207f33d2c1SStephan Aßmus// interface of IDE adapter library
1217f33d2c1SStephan Aßmustypedef struct {
1227f33d2c1SStephan Aßmus	module_info info;
1237f33d2c1SStephan Aßmus
1247f33d2c1SStephan Aßmus	void (*set_channel)(ata_adapter_channel_info *channel,
1257f33d2c1SStephan Aßmus					ata_channel ataChannel);
1267f33d2c1SStephan Aßmus
1277f33d2c1SStephan Aßmus	// function calls that can be forwarded from actual driver
1287f33d2c1SStephan Aßmus	status_t (*write_command_block_regs)(ata_adapter_channel_info *channel,
1297f33d2c1SStephan Aßmus					ata_task_file *tf, ata_reg_mask mask);
1307f33d2c1SStephan Aßmus	status_t (*read_command_block_regs)(ata_adapter_channel_info *channel,
1317f33d2c1SStephan Aßmus					ata_task_file *tf, ata_reg_mask mask);
1327f33d2c1SStephan Aßmus
1337f33d2c1SStephan Aßmus	uint8 (*get_altstatus) (ata_adapter_channel_info *channel);
1347f33d2c1SStephan Aßmus	status_t (*write_device_control) (ata_adapter_channel_info *channel, uint8 val);
1357f33d2c1SStephan Aßmus
1367f33d2c1SStephan Aßmus	status_t (*write_pio)(ata_adapter_channel_info *channel, uint16 *data, int count, bool force_16bit);
1377f33d2c1SStephan Aßmus	status_t (*read_pio)(ata_adapter_channel_info *channel, uint16 *data, int count, bool force_16bit);
1387f33d2c1SStephan Aßmus
1397f33d2c1SStephan Aßmus	status_t (*prepare_dma)(ata_adapter_channel_info *channel, const physical_entry *sg_list,
1407f33d2c1SStephan Aßmus					size_t sg_list_count, bool to_device);
1417f33d2c1SStephan Aßmus	status_t (*start_dma)(ata_adapter_channel_info *channel);
1427f33d2c1SStephan Aßmus	status_t (*finish_dma)(ata_adapter_channel_info *channel);
1437f33d2c1SStephan Aßmus
1447f33d2c1SStephan Aßmus	// default functions that should be replaced by a more specific version
1457f33d2c1SStephan Aßmus	// (copy them from source code of this library and modify them at will)
1467f33d2c1SStephan Aßmus	int32 (*inthand)(void *arg);
1477f33d2c1SStephan Aßmus
1487f33d2c1SStephan Aßmus	// functions that must be called by init/uninit etc. of channel driver
1497f33d2c1SStephan Aßmus	status_t (*init_channel)(device_node *node,
1507f33d2c1SStephan Aßmus					ata_adapter_channel_info **cookie, size_t total_data_size,
1517f33d2c1SStephan Aßmus					int32 (*inthand)(void *arg));
1527f33d2c1SStephan Aßmus	void (*uninit_channel)(ata_adapter_channel_info *channel);
1537f33d2c1SStephan Aßmus	void (*channel_removed)(ata_adapter_channel_info *channel);
1547f33d2c1SStephan Aßmus
1557f33d2c1SStephan Aßmus	// publish channel node
1567f33d2c1SStephan Aßmus	status_t (*publish_channel)(device_node *controller_node,
1577f33d2c1SStephan Aßmus					const char *channel_module_name, uint16 command_block_base,
1587f33d2c1SStephan Aßmus					uint16 control_block_base, uint8 intnum, bool can_dma,
1597f33d2c1SStephan Aßmus					uint8 channel_index, const char *name,
1607f33d2c1SStephan Aßmus					const io_resource *resources, device_node **node);
1617f33d2c1SStephan Aßmus	// verify channel configuration and publish node on success
1627f33d2c1SStephan Aßmus	status_t (*detect_channel)(pci_device_module_info *pci, pci_device *pciDevice,
1637f33d2c1SStephan Aßmus					device_node *controller_node, const char *channel_module_name,
1647f33d2c1SStephan Aßmus					bool controller_can_dma, uint16 command_block_base,
1657f33d2c1SStephan Aßmus					uint16 control_block_base, uint16 bus_master_base,
1667f33d2c1SStephan Aßmus					uint8 intnum, uint8 channel_index, const char *name,
1677f33d2c1SStephan Aßmus					device_node **node, bool supports_compatibility_mode);
1687f33d2c1SStephan Aßmus
1697f33d2c1SStephan Aßmus	// functions that must be called by init/uninit etc. of controller driver
1707f33d2c1SStephan Aßmus	status_t (*init_controller)(device_node *node,
1717f33d2c1SStephan Aßmus					ata_adapter_controller_info **cookie, size_t total_data_size);
1727f33d2c1SStephan Aßmus	void (*uninit_controller)(ata_adapter_controller_info *controller);
1737f33d2c1SStephan Aßmus	void (*controller_removed)(ata_adapter_controller_info *controller);
1747f33d2c1SStephan Aßmus
1757f33d2c1SStephan Aßmus	// publish controller node
1767f33d2c1SStephan Aßmus	status_t (*publish_controller)(device_node *parent, uint16 bus_master_base,
1777f33d2c1SStephan Aßmus					io_resource *resources, const char *controller_driver,
1787f33d2c1SStephan Aßmus					const char *controller_driver_type, const char *controller_name,
1797f33d2c1SStephan Aßmus					bool can_dma, bool can_cq, uint32 dma_alignment, uint32 dma_boundary,
1807f33d2c1SStephan Aßmus					uint32 max_sg_block_size, device_node **node);
1817f33d2c1SStephan Aßmus	// verify controller configuration and publish node on success
1827f33d2c1SStephan Aßmus	status_t (*detect_controller)(pci_device_module_info *pci, pci_device *pciDevice,
1837f33d2c1SStephan Aßmus					device_node *parent, uint16 bus_master_base,
1847f33d2c1SStephan Aßmus					const char *controller_driver, const char *controller_driver_type,
1857f33d2c1SStephan Aßmus					const char *controller_name, bool can_dma, bool can_cq,
1867f33d2c1SStephan Aßmus					uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
1877f33d2c1SStephan Aßmus					device_node **node);
1887f33d2c1SStephan Aßmus	// standard master probe for controller that registers controller and channel nodes
1897f33d2c1SStephan Aßmus	status_t (*probe_controller)(device_node *parent, const char *controller_driver,
1907f33d2c1SStephan Aßmus					const char *controller_driver_type, const char *controller_name,
1917f33d2c1SStephan Aßmus					const char *channel_module_name, bool can_dma, bool can_cq,
1927f33d2c1SStephan Aßmus					uint32 dma_alignment, uint32 dma_boundary, uint32 max_sg_block_size,
1937f33d2c1SStephan Aßmus					bool supports_compatibility_mode);
1947f33d2c1SStephan Aßmus} ata_adapter_interface;
1957f33d2c1SStephan Aßmus
1967f33d2c1SStephan Aßmus
1977f33d2c1SStephan Aßmus#define ATA_ADAPTER_MODULE_NAME "generic/ata_adapter/v1"
1987f33d2c1SStephan Aßmus
1997f33d2c1SStephan Aßmus#endif	/* _ATA_PCI_H */