1230557Sjimharris/*-
2230557Sjimharris * BSD LICENSE
3230557Sjimharris *
4230557Sjimharris * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
5230557Sjimharris * All rights reserved.
6230557Sjimharris *
7230557Sjimharris * Redistribution and use in source and binary forms, with or without
8230557Sjimharris * modification, are permitted provided that the following conditions
9230557Sjimharris * are met:
10230557Sjimharris *
11230557Sjimharris *   * Redistributions of source code must retain the above copyright
12230557Sjimharris *     notice, this list of conditions and the following disclaimer.
13230557Sjimharris *   * Redistributions in binary form must reproduce the above copyright
14230557Sjimharris *     notice, this list of conditions and the following disclaimer in
15230557Sjimharris *     the documentation and/or other materials provided with the
16230557Sjimharris *     distribution.
17230557Sjimharris *
18230557Sjimharris * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19230557Sjimharris * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20230557Sjimharris * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21230557Sjimharris * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22230557Sjimharris * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23230557Sjimharris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24230557Sjimharris * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25230557Sjimharris * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26230557Sjimharris * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27230557Sjimharris * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28230557Sjimharris * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29230557Sjimharris *
30230557Sjimharris * $FreeBSD$
31230557Sjimharris */
32230557Sjimharris
33235751Sjimharris#ifndef _ISCI_H
34235751Sjimharris#define _ISCI_H
35235751Sjimharris
36230557Sjimharris#include <sys/param.h>
37230557Sjimharris#include <sys/systm.h>
38230557Sjimharris#include <sys/kernel.h>
39230557Sjimharris#include <sys/bus.h>
40230557Sjimharris#include <sys/lock.h>
41230557Sjimharris#include <sys/mutex.h>
42230557Sjimharris#include <sys/types.h>
43230557Sjimharris#include <sys/malloc.h>
44230557Sjimharris#include <sys/rman.h>
45230557Sjimharris
46230557Sjimharris#include <machine/bus.h>
47230557Sjimharris#include <machine/resource.h>
48230557Sjimharris
49230557Sjimharris#include <cam/cam.h>
50230557Sjimharris#include <cam/cam_ccb.h>
51230557Sjimharris#include <cam/cam_sim.h>
52230557Sjimharris#include <cam/cam_xpt_sim.h>
53230557Sjimharris
54230557Sjimharris#include <dev/isci/environment.h>
55230557Sjimharris#include <dev/isci/scil/intel_pci.h>
56230557Sjimharris
57230557Sjimharris#include <dev/isci/scil/sci_types.h>
58230557Sjimharris#include <dev/isci/scil/sci_object.h>
59230557Sjimharris#include <dev/isci/scil/sci_status.h>
60230557Sjimharris#include <dev/isci/scil/sci_pool.h>
61230557Sjimharris#include <dev/isci/scil/sci_fast_list.h>
62230557Sjimharris
63230557Sjimharris#include <dev/isci/scil/sci_controller_constants.h>
64230557Sjimharris
65230557Sjimharris#include <dev/isci/scil/scic_controller.h>
66230557Sjimharris#include <dev/isci/scil/scic_config_parameters.h>
67230557Sjimharris
68230557Sjimharris#define DEVICE2SOFTC(dev) ((struct isci_softc *) device_get_softc(dev))
69230557Sjimharris
70230557Sjimharris#define DEVICE_TIMEOUT 1000
71230557Sjimharris#define SCI_MAX_TIMERS  32
72230557Sjimharris
73230557Sjimharris#define ISCI_NUM_PCI_BARS  2
74230557Sjimharris#define ISCI_MAX_LUN		 8
75230557Sjimharris
76230557SjimharrisMALLOC_DECLARE(M_ISCI);
77230557Sjimharris
78230557Sjimharrisstruct ISCI_TIMER {
79230557Sjimharris	struct callout		callout;
80230557Sjimharris	SCI_TIMER_CALLBACK_T	callback;
81230557Sjimharris	void			*cookie;
82230557Sjimharris	BOOL			is_started;
83230557Sjimharris};
84230557Sjimharris
85230557Sjimharrisstruct ISCI_REMOTE_DEVICE {
86230557Sjimharris	uint32_t			index;
87230557Sjimharris	struct ISCI_DOMAIN 		*domain;
88230557Sjimharris	SCI_REMOTE_DEVICE_HANDLE_T	sci_object;
89230557Sjimharris	BOOL				is_resetting;
90230557Sjimharris	uint32_t			frozen_lun_mask;
91230557Sjimharris	SCI_FAST_LIST_ELEMENT_T		pending_device_reset_element;
92235751Sjimharris
93235751Sjimharris	/*
94235751Sjimharris	 * This queue maintains CCBs that have been returned with
95235751Sjimharris	 *  SCI_IO_FAILURE_INVALID_STATE from the SCI layer.  These CCBs
96235751Sjimharris	 *  need to be retried, but we cannot return CAM_REQUEUE_REQ because
97235751Sjimharris	 *  this status gets passed all the way back up to users of the pass(4)
98235751Sjimharris	 *  interface and breaks things like smartctl.  So instead, we queue
99235751Sjimharris	 *  these CCBs internally.
100235751Sjimharris	 */
101234106Sjimharris	TAILQ_HEAD(,ccb_hdr)		queued_ccbs;
102235751Sjimharris
103235751Sjimharris	/*
104235751Sjimharris	 * Marker denoting this remote device needs its first queued ccb to
105235751Sjimharris	 *  be retried.
106235751Sjimharris	 */
107235751Sjimharris	BOOL				release_queued_ccb;
108235751Sjimharris
109235751Sjimharris	/*
110235751Sjimharris	 * Points to a CCB in the queue that is currently being processed by
111235751Sjimharris	 *  SCIL.  This allows us to keep in flight CCBs in the queue so as to
112235751Sjimharris	 *  maintain ordering (i.e. in case we retry an I/O and then find out
113235751Sjimharris	 *  it needs to be retried again - it just keeps its same place in the
114235751Sjimharris	 *  queue.
115235751Sjimharris	 */
116235751Sjimharris	union ccb *			queued_ccb_in_progress;
117230557Sjimharris};
118230557Sjimharris
119230557Sjimharrisstruct ISCI_DOMAIN {
120233622Sjimharris	struct ISCI_CONTROLLER		*controller;
121233622Sjimharris	SCI_DOMAIN_HANDLE_T		sci_object;
122233622Sjimharris	uint8_t				index;
123233622Sjimharris	struct ISCI_REMOTE_DEVICE	*da_remote_device;
124230557Sjimharris};
125230557Sjimharris
126230557Sjimharrisstruct ISCI_MEMORY
127230557Sjimharris{
128230557Sjimharris	bus_addr_t	physical_address;
129230557Sjimharris	bus_dma_tag_t	dma_tag;
130230557Sjimharris	bus_dmamap_t	dma_map;
131230557Sjimharris	POINTER_UINT	virtual_address;
132230557Sjimharris	uint32_t	size;
133230557Sjimharris	int		error;
134230557Sjimharris};
135230557Sjimharris
136230557Sjimharrisstruct ISCI_INTERRUPT_INFO
137230557Sjimharris{
138230557Sjimharris	SCIC_CONTROLLER_HANDLER_METHODS_T 	*handlers;
139230557Sjimharris	void					*interrupt_target_handle;
140230557Sjimharris	struct resource				*res;
141230557Sjimharris	int					rid;
142230557Sjimharris	void					*tag;
143230557Sjimharris
144230557Sjimharris};
145230557Sjimharris
146241403Sjimharrisstruct ISCI_PHY
147240965Sjimharris{
148241403Sjimharris	struct cdev		*cdev_fault;
149241403Sjimharris	struct cdev		*cdev_locate;
150240965Sjimharris	SCI_CONTROLLER_HANDLE_T	handle;
151240965Sjimharris	int			index;
152241403Sjimharris	int			led_fault;
153241403Sjimharris	int			led_locate;
154240965Sjimharris};
155240965Sjimharris
156230557Sjimharrisstruct ISCI_CONTROLLER
157230557Sjimharris{
158230557Sjimharris	struct isci_softc 	*isci;
159230557Sjimharris	uint8_t			index;
160230557Sjimharris	SCI_CONTROLLER_HANDLE_T	scif_controller_handle;
161230557Sjimharris	struct ISCI_DOMAIN	domain[SCI_MAX_DOMAINS];
162230557Sjimharris	BOOL			is_started;
163233371Sjimharris	BOOL			has_been_scanned;
164230557Sjimharris	uint32_t		initial_discovery_mask;
165230557Sjimharris	BOOL			is_frozen;
166235751Sjimharris	BOOL			release_queued_ccbs;
167230557Sjimharris	uint8_t			*remote_device_memory;
168230557Sjimharris	struct ISCI_MEMORY	cached_controller_memory;
169230557Sjimharris	struct ISCI_MEMORY	uncached_controller_memory;
170230557Sjimharris	struct ISCI_MEMORY	request_memory;
171230557Sjimharris	bus_dma_tag_t		buffer_dma_tag;
172230557Sjimharris	struct mtx		lock;
173230557Sjimharris	struct cam_sim		*sim;
174230557Sjimharris	struct cam_path		*path;
175230557Sjimharris	struct ISCI_REMOTE_DEVICE *remote_device[SCI_MAX_REMOTE_DEVICES];
176230557Sjimharris	void 			*timer_memory;
177230557Sjimharris	SCIC_OEM_PARAMETERS_T	oem_parameters;
178230557Sjimharris	uint32_t		oem_parameters_version;
179230557Sjimharris	uint32_t		queue_depth;
180230557Sjimharris	uint32_t		sim_queue_depth;
181230557Sjimharris	SCI_FAST_LIST_T		pending_device_reset_list;
182241403Sjimharris	struct ISCI_PHY		phys[SCI_MAX_PHYS];
183230557Sjimharris
184230557Sjimharris	SCI_MEMORY_DESCRIPTOR_LIST_HANDLE_T mdl;
185230557Sjimharris
186230557Sjimharris	SCI_POOL_CREATE(remote_device_pool, struct ISCI_REMOTE_DEVICE *, SCI_MAX_REMOTE_DEVICES);
187230557Sjimharris	SCI_POOL_CREATE(request_pool, struct ISCI_REQUEST *, SCI_MAX_IO_REQUESTS);
188230557Sjimharris	SCI_POOL_CREATE(timer_pool, struct ISCI_TIMER *, SCI_MAX_TIMERS);
189239545Sjimharris	SCI_POOL_CREATE(unmap_buffer_pool, void *, SCI_MAX_REMOTE_DEVICES);
190230557Sjimharris};
191230557Sjimharris
192230557Sjimharrisstruct ISCI_REQUEST
193230557Sjimharris{
194230557Sjimharris	SCI_CONTROLLER_HANDLE_T		controller_handle;
195230557Sjimharris	SCI_REMOTE_DEVICE_HANDLE_T	remote_device_handle;
196230557Sjimharris	bus_dma_tag_t			dma_tag;
197230557Sjimharris	bus_dmamap_t			dma_map;
198230557Sjimharris	SCI_PHYSICAL_ADDRESS		physical_address;
199230557Sjimharris	struct callout			timer;
200230557Sjimharris};
201230557Sjimharris
202230557Sjimharrisstruct ISCI_IO_REQUEST
203230557Sjimharris{
204230557Sjimharris	struct ISCI_REQUEST	parent;
205230557Sjimharris	SCI_IO_REQUEST_HANDLE_T	sci_object;
206230557Sjimharris	union ccb		*ccb;
207230557Sjimharris	uint32_t		num_segments;
208230557Sjimharris	uint32_t		current_sge_index;
209230557Sjimharris	bus_dma_segment_t	*sge;
210230557Sjimharris};
211230557Sjimharris
212230557Sjimharrisstruct ISCI_TASK_REQUEST
213230557Sjimharris{
214230557Sjimharris	struct ISCI_REQUEST		parent;
215230557Sjimharris	struct scsi_sense_data		sense_data;
216230557Sjimharris	SCI_TASK_REQUEST_HANDLE_T	sci_object;
217230557Sjimharris	union ccb			*ccb;
218230557Sjimharris
219230557Sjimharris};
220230557Sjimharris
221230557Sjimharrisstruct ISCI_PCI_BAR {
222230557Sjimharris
223230557Sjimharris	bus_space_tag_t		bus_tag;
224230557Sjimharris	bus_space_handle_t	bus_handle;
225230557Sjimharris	int			resource_id;
226230557Sjimharris	struct resource		*resource;
227230557Sjimharris
228230557Sjimharris};
229230557Sjimharris
230230557Sjimharris/*
231230557Sjimharris * One of these per allocated PCI device.
232230557Sjimharris */
233230557Sjimharrisstruct isci_softc {
234230557Sjimharris
235230557Sjimharris	struct ISCI_PCI_BAR			pci_bar[ISCI_NUM_PCI_BARS];
236230557Sjimharris	struct ISCI_CONTROLLER			controllers[SCI_MAX_CONTROLLERS];
237230557Sjimharris	SCI_LIBRARY_HANDLE_T			sci_library_handle;
238230557Sjimharris	void *					sci_library_memory;
239230557Sjimharris	SCIC_CONTROLLER_HANDLER_METHODS_T	handlers[4];
240230557Sjimharris	struct ISCI_INTERRUPT_INFO		interrupt_info[4];
241230557Sjimharris	uint32_t				controller_count;
242230557Sjimharris	uint32_t				num_interrupts;
243230557Sjimharris	uint32_t				coalesce_number;
244230557Sjimharris	uint32_t				coalesce_timeout;
245230557Sjimharris	device_t				device;
246230557Sjimharris	SCI_PCI_COMMON_HEADER_T			pci_common_header;
247230557Sjimharris	BOOL					oem_parameters_found;
248230557Sjimharris	struct intr_config_hook			config_hook;
249230557Sjimharris};
250230557Sjimharris
251230557Sjimharrisint isci_allocate_resources(device_t device);
252230557Sjimharris
253230557Sjimharrisint isci_allocate_dma_buffer(device_t device, struct ISCI_MEMORY *memory);
254230557Sjimharris
255230557Sjimharrisvoid isci_remote_device_reset(struct ISCI_REMOTE_DEVICE *remote_device,
256230557Sjimharris    union ccb *ccb);
257230557Sjimharris
258230557Sjimharris/**
259230557Sjimharris *  Returns the negotiated link rate (in KB/s) for the associated
260230557Sjimharris *	remote device.  Used to fill out bitrate field for GET_TRANS_SETTINGS.
261230557Sjimharris *	Will match the negotiated link rate for the lowest numbered local phy
262230557Sjimharris *	in the port/domain containing this remote device.
263230557Sjimharris */
264230557Sjimharrisuint32_t isci_remote_device_get_bitrate(
265230557Sjimharris    struct ISCI_REMOTE_DEVICE *remote_device);
266230557Sjimharris
267230557Sjimharrisvoid isci_remote_device_freeze_lun_queue(
268230557Sjimharris    struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
269230557Sjimharris
270230557Sjimharrisvoid isci_remote_device_release_lun_queue(
271230557Sjimharris    struct ISCI_REMOTE_DEVICE *remote_device, lun_id_t lun);
272230557Sjimharris
273230557Sjimharrisvoid isci_remote_device_release_device_queue(
274230557Sjimharris    struct ISCI_REMOTE_DEVICE * remote_device);
275230557Sjimharris
276230557Sjimharrisvoid isci_request_construct(struct ISCI_REQUEST *request,
277230557Sjimharris    SCI_CONTROLLER_HANDLE_T scif_controller_handle,
278230557Sjimharris    bus_dma_tag_t io_buffer_dma_tag, bus_addr_t physical_address);
279230557Sjimharris
280230557Sjimharris#define isci_io_request_get_max_io_size() \
281230557Sjimharris	((SCI_MAX_SCATTER_GATHER_ELEMENTS - 1) * PAGE_SIZE)
282230557Sjimharris
283230557Sjimharris#define isci_task_request_get_object_size() \
284230557Sjimharris	(sizeof(struct ISCI_TASK_REQUEST) + scif_task_request_get_object_size())
285230557Sjimharris
286230557Sjimharris#define isci_io_request_get_object_size() \
287230557Sjimharris	(sizeof(struct ISCI_IO_REQUEST) + scif_io_request_get_object_size())
288230557Sjimharris
289230557Sjimharris#define isci_request_get_object_size() \
290230557Sjimharris	max( \
291230557Sjimharris	    isci_task_request_get_object_size(), \
292230557Sjimharris	    isci_io_request_get_object_size() \
293230557Sjimharris	)
294230557Sjimharris
295230557Sjimharris
296230557Sjimharrisvoid isci_io_request_execute_scsi_io(union ccb *ccb,
297230557Sjimharris    struct ISCI_CONTROLLER *controller);
298230557Sjimharris
299230557Sjimharris#if __FreeBSD_version >= 900026
300230557Sjimharrisvoid isci_io_request_execute_smp_io(
301230557Sjimharris    union ccb *ccb, struct ISCI_CONTROLLER *controller);
302230557Sjimharris#endif
303230557Sjimharris
304230557Sjimharrisvoid isci_io_request_timeout(void *);
305230557Sjimharris
306230557Sjimharrisvoid isci_get_oem_parameters(struct isci_softc *isci);
307230557Sjimharris
308230557Sjimharrisvoid isci_io_request_complete(
309230557Sjimharris    SCI_CONTROLLER_HANDLE_T scif_controller,
310230557Sjimharris    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
311230557Sjimharris    struct ISCI_IO_REQUEST * isci_request, SCI_IO_STATUS completion_status);
312230557Sjimharris
313230557Sjimharrisvoid isci_task_request_complete(
314230557Sjimharris    SCI_CONTROLLER_HANDLE_T scif_controller,
315230557Sjimharris    SCI_REMOTE_DEVICE_HANDLE_T remote_device,
316230557Sjimharris    SCI_TASK_REQUEST_HANDLE_T io_request, SCI_TASK_STATUS completion_status);
317230557Sjimharris
318230557Sjimharrisvoid isci_sysctl_initialize(struct isci_softc *isci);
319230557Sjimharris
320230557Sjimharrisvoid isci_controller_construct(struct ISCI_CONTROLLER *controller,
321230557Sjimharris    struct isci_softc *isci);
322230557Sjimharris
323230557SjimharrisSCI_STATUS isci_controller_initialize(struct ISCI_CONTROLLER *controller);
324230557Sjimharris
325230557Sjimharrisint isci_controller_allocate_memory(struct ISCI_CONTROLLER *controller);
326230557Sjimharris
327230557Sjimharrisvoid isci_controller_domain_discovery_complete(
328230557Sjimharris    struct ISCI_CONTROLLER *isci_controller, struct ISCI_DOMAIN *isci_domain);
329230557Sjimharris
330230557Sjimharrisint isci_controller_attach_to_cam(struct ISCI_CONTROLLER *controller);
331230557Sjimharris
332230557Sjimharrisvoid isci_controller_start(void *controller);
333230557Sjimharris
334235751Sjimharrisvoid isci_controller_release_queued_ccbs(struct ISCI_CONTROLLER *controller);
335235751Sjimharris
336230557Sjimharrisvoid isci_domain_construct(struct ISCI_DOMAIN *domain, uint32_t domain_index,
337230557Sjimharris    struct ISCI_CONTROLLER *controller);
338230557Sjimharris
339230557Sjimharrisvoid isci_interrupt_setup(struct isci_softc *isci);
340230557Sjimharrisvoid isci_interrupt_poll_handler(struct ISCI_CONTROLLER *controller);
341230557Sjimharris
342230557Sjimharrisvoid isci_log_message(uint32_t	verbosity, char *log_message_prefix,
343230557Sjimharris    char *log_message, ...);
344230557Sjimharris
345230557Sjimharrisextern uint32_t g_isci_debug_level;
346235751Sjimharris
347235751Sjimharris#endif /* #ifndef _ISCI_H */
348