blob: 41f168702ac7ab76925a1bac5be69878c161c1c7 [file] [log] [blame]
Jianyun Lif0c568a2011-05-11 23:22:44 +08001/*
2 * Marvell UMI head file
3 *
4 * Copyright 2011 Marvell. <jyli@marvell.com>
5 *
6 * This file is licensed under GPLv2.
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; version 2 of the
11 * License.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21 * USA
22 */
23
24#ifndef MVUMI_H
25#define MVUMI_H
26
27#define MAX_BASE_ADDRESS 6
28
29#define VER_MAJOR 1
30#define VER_MINOR 1
31#define VER_OEM 0
32#define VER_BUILD 1500
33
34#define MV_DRIVER_NAME "mvumi"
Jianyun Lif0c568a2011-05-11 23:22:44 +080035#define PCI_DEVICE_ID_MARVELL_MV9143 0x9143
Shun Fubd756dd2012-09-23 22:16:14 +080036#define PCI_DEVICE_ID_MARVELL_MV9580 0x9580
Jianyun Lif0c568a2011-05-11 23:22:44 +080037
38#define MVUMI_INTERNAL_CMD_WAIT_TIME 45
Shun Fubd756dd2012-09-23 22:16:14 +080039#define MVUMI_INQUIRY_LENGTH 44
40#define MVUMI_INQUIRY_UUID_OFF 36
41#define MVUMI_INQUIRY_UUID_LEN 8
Jianyun Lif0c568a2011-05-11 23:22:44 +080042
43#define IS_DMA64 (sizeof(dma_addr_t) == 8)
44
45enum mvumi_qc_result {
Shun Fubd756dd2012-09-23 22:16:14 +080046 MV_QUEUE_COMMAND_RESULT_SENT = 0,
Jianyun Lif0c568a2011-05-11 23:22:44 +080047 MV_QUEUE_COMMAND_RESULT_NO_RESOURCE,
48};
49
Shun Fubd756dd2012-09-23 22:16:14 +080050struct mvumi_hw_regs {
51 /* For CPU */
52 void *main_int_cause_reg;
53 void *enpointa_mask_reg;
54 void *enpointb_mask_reg;
55 void *rstoutn_en_reg;
56 void *ctrl_sts_reg;
57 void *rstoutn_mask_reg;
58 void *sys_soft_rst_reg;
59
60 /* For Doorbell */
61 void *pciea_to_arm_drbl_reg;
62 void *arm_to_pciea_drbl_reg;
63 void *arm_to_pciea_mask_reg;
64 void *pciea_to_arm_msg0;
65 void *pciea_to_arm_msg1;
66 void *arm_to_pciea_msg0;
67 void *arm_to_pciea_msg1;
68
69 /* reset register */
70 void *reset_request;
71 void *reset_enable;
72
73 /* For Message Unit */
74 void *inb_list_basel;
75 void *inb_list_baseh;
76 void *inb_aval_count_basel;
77 void *inb_aval_count_baseh;
78 void *inb_write_pointer;
79 void *inb_read_pointer;
80 void *outb_list_basel;
81 void *outb_list_baseh;
82 void *outb_copy_basel;
83 void *outb_copy_baseh;
84 void *outb_copy_pointer;
85 void *outb_read_pointer;
86 void *inb_isr_cause;
87 void *outb_isr_cause;
88 void *outb_coal_cfg;
89 void *outb_coal_timeout;
90
91 /* Bit setting for HW */
92 u32 int_comaout;
93 u32 int_comaerr;
94 u32 int_dl_cpu2pciea;
95 u32 int_mu;
96 u32 int_drbl_int_mask;
97 u32 int_main_int_mask;
98 u32 cl_pointer_toggle;
99 u32 cl_slot_num_mask;
100 u32 clic_irq;
101 u32 clic_in_err;
102 u32 clic_out_err;
103};
104
105struct mvumi_dyn_list_entry {
106 u32 src_low_addr;
107 u32 src_high_addr;
108 u32 if_length;
109 u32 reserve;
110};
111
112#define SCSI_CMD_MARVELL_SPECIFIC 0xE1
113#define CDB_CORE_MODULE 0x1
114#define CDB_CORE_SHUTDOWN 0xB
115
Jianyun Lif0c568a2011-05-11 23:22:44 +0800116enum {
Jianyun Lif0c568a2011-05-11 23:22:44 +0800117 DRBL_HANDSHAKE = 1 << 0,
118 DRBL_SOFT_RESET = 1 << 1,
119 DRBL_BUS_CHANGE = 1 << 2,
120 DRBL_EVENT_NOTIFY = 1 << 3,
121 DRBL_MU_RESET = 1 << 4,
122 DRBL_HANDSHAKE_ISR = DRBL_HANDSHAKE,
123
Jianyun Lif0c568a2011-05-11 23:22:44 +0800124 /*
125 * Command flag is the flag for the CDB command itself
126 */
127 /* 1-non data; 0-data command */
128 CMD_FLAG_NON_DATA = 1 << 0,
129 CMD_FLAG_DMA = 1 << 1,
130 CMD_FLAG_PIO = 1 << 2,
131 /* 1-host read data */
132 CMD_FLAG_DATA_IN = 1 << 3,
133 /* 1-host write data */
134 CMD_FLAG_DATA_OUT = 1 << 4,
Shun Fubd756dd2012-09-23 22:16:14 +0800135 CMD_FLAG_PRDT_IN_HOST = 1 << 5,
Jianyun Lif0c568a2011-05-11 23:22:44 +0800136};
137
138#define APICDB0_EVENT 0xF4
139#define APICDB1_EVENT_GETEVENT 0
Shun Fubd756dd2012-09-23 22:16:14 +0800140#define APICDB1_HOST_GETEVENT 1
Jianyun Lif0c568a2011-05-11 23:22:44 +0800141#define MAX_EVENTS_RETURNED 6
142
Shun Fubd756dd2012-09-23 22:16:14 +0800143#define DEVICE_OFFLINE 0
144#define DEVICE_ONLINE 1
145
146struct mvumi_hotplug_event {
147 u16 size;
148 u8 dummy[2];
149 u8 bitmap[0];
150};
151
Jianyun Lif0c568a2011-05-11 23:22:44 +0800152struct mvumi_driver_event {
153 u32 time_stamp;
154 u32 sequence_no;
155 u32 event_id;
156 u8 severity;
157 u8 param_count;
158 u16 device_id;
159 u32 params[4];
160 u8 sense_data_length;
161 u8 Reserved1;
162 u8 sense_data[30];
163};
164
165struct mvumi_event_req {
166 unsigned char count;
167 unsigned char reserved[3];
168 struct mvumi_driver_event events[MAX_EVENTS_RETURNED];
169};
170
171struct mvumi_events_wq {
172 struct work_struct work_q;
173 struct mvumi_hba *mhba;
174 unsigned int event;
175 void *param;
176};
177
Shun Fubd756dd2012-09-23 22:16:14 +0800178#define HS_CAPABILITY_SUPPORT_COMPACT_SG (1U << 4)
179#define HS_CAPABILITY_SUPPORT_PRD_HOST (1U << 5)
180#define HS_CAPABILITY_SUPPORT_DYN_SRC (1U << 6)
181#define HS_CAPABILITY_NEW_PAGE_IO_DEPTH_DEF (1U << 14)
182
Jianyun Lif0c568a2011-05-11 23:22:44 +0800183#define MVUMI_MAX_SG_ENTRY 32
184#define SGD_EOT (1L << 27)
Shun Fubd756dd2012-09-23 22:16:14 +0800185#define SGD_EOT_CP (1L << 22)
Jianyun Lif0c568a2011-05-11 23:22:44 +0800186
187struct mvumi_sgl {
188 u32 baseaddr_l;
189 u32 baseaddr_h;
190 u32 flags;
191 u32 size;
192};
Shun Fubd756dd2012-09-23 22:16:14 +0800193struct mvumi_compact_sgl {
194 u32 baseaddr_l;
195 u32 baseaddr_h;
196 u32 flags;
197};
198
199#define GET_COMPACT_SGD_SIZE(sgd) \
200 ((((struct mvumi_compact_sgl *)(sgd))->flags) & 0x3FFFFFL)
201
202#define SET_COMPACT_SGD_SIZE(sgd, sz) do { \
203 (((struct mvumi_compact_sgl *)(sgd))->flags) &= ~0x3FFFFFL; \
204 (((struct mvumi_compact_sgl *)(sgd))->flags) |= (sz); \
205} while (0)
206#define sgd_getsz(_mhba, sgd, sz) do { \
207 if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
208 (sz) = GET_COMPACT_SGD_SIZE(sgd); \
209 else \
210 (sz) = (sgd)->size; \
211} while (0)
212
213#define sgd_setsz(_mhba, sgd, sz) do { \
214 if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
215 SET_COMPACT_SGD_SIZE(sgd, sz); \
216 else \
217 (sgd)->size = (sz); \
218} while (0)
219
220#define sgd_inc(_mhba, sgd) do { \
221 if (_mhba->hba_capability & HS_CAPABILITY_SUPPORT_COMPACT_SG) \
222 sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 12); \
223 else \
224 sgd = (struct mvumi_sgl *)(((unsigned char *) (sgd)) + 16); \
225} while (0)
Jianyun Lif0c568a2011-05-11 23:22:44 +0800226
227struct mvumi_res {
228 struct list_head entry;
229 dma_addr_t bus_addr;
230 void *virt_addr;
231 unsigned int size;
232 unsigned short type; /* enum Resource_Type */
233};
234
235/* Resource type */
236enum resource_type {
237 RESOURCE_CACHED_MEMORY = 0,
238 RESOURCE_UNCACHED_MEMORY
239};
240
241struct mvumi_sense_data {
Shun Fubd756dd2012-09-23 22:16:14 +0800242 u8 error_code:7;
Jianyun Lif0c568a2011-05-11 23:22:44 +0800243 u8 valid:1;
244 u8 segment_number;
245 u8 sense_key:4;
246 u8 reserved:1;
247 u8 incorrect_length:1;
248 u8 end_of_media:1;
249 u8 file_mark:1;
250 u8 information[4];
251 u8 additional_sense_length;
252 u8 command_specific_information[4];
253 u8 additional_sense_code;
254 u8 additional_sense_code_qualifier;
255 u8 field_replaceable_unit_code;
256 u8 sense_key_specific[3];
257};
258
259/* Request initiator must set the status to REQ_STATUS_PENDING. */
260#define REQ_STATUS_PENDING 0x80
261
262struct mvumi_cmd {
263 struct list_head queue_pointer;
264 struct mvumi_msg_frame *frame;
Shun Fubd756dd2012-09-23 22:16:14 +0800265 dma_addr_t frame_phys;
Jianyun Lif0c568a2011-05-11 23:22:44 +0800266 struct scsi_cmnd *scmd;
267 atomic_t sync_cmd;
268 void *data_buf;
269 unsigned short request_id;
270 unsigned char cmd_status;
271};
272
273/*
274 * the function type of the in bound frame
275 */
276#define CL_FUN_SCSI_CMD 0x1
277
278struct mvumi_msg_frame {
279 u16 device_id;
280 u16 tag;
281 u8 cmd_flag;
282 u8 req_function;
283 u8 cdb_length;
284 u8 sg_counts;
285 u32 data_transfer_length;
286 u16 request_id;
287 u16 reserved1;
288 u8 cdb[MAX_COMMAND_SIZE];
289 u32 payload[1];
290};
291
292/*
293 * the respond flag for data_payload of the out bound frame
294 */
295#define CL_RSP_FLAG_NODATA 0x0
296#define CL_RSP_FLAG_SENSEDATA 0x1
297
298struct mvumi_rsp_frame {
299 u16 device_id;
300 u16 tag;
301 u8 req_status;
302 u8 rsp_flag; /* Indicates the type of Data_Payload.*/
303 u16 request_id;
304 u32 payload[1];
305};
306
307struct mvumi_ob_data {
308 struct list_head list;
309 unsigned char data[0];
310};
311
312struct version_info {
313 u32 ver_major;
314 u32 ver_minor;
315 u32 ver_oem;
316 u32 ver_build;
317};
318
319#define FW_MAX_DELAY 30
320#define MVUMI_FW_BUSY (1U << 0)
321#define MVUMI_FW_ATTACH (1U << 1)
322#define MVUMI_FW_ALLOC (1U << 2)
323
324/*
325 * State is the state of the MU
326 */
327#define FW_STATE_IDLE 0
328#define FW_STATE_STARTING 1
329#define FW_STATE_HANDSHAKING 2
330#define FW_STATE_STARTED 3
331#define FW_STATE_ABORT 4
332
333#define HANDSHAKE_SIGNATURE 0x5A5A5A5AL
334#define HANDSHAKE_READYSTATE 0x55AA5AA5L
335#define HANDSHAKE_DONESTATE 0x55AAA55AL
336
337/* HandShake Status definition */
338#define HS_STATUS_OK 1
339#define HS_STATUS_ERR 2
340#define HS_STATUS_INVALID 3
341
342/* HandShake State/Cmd definition */
343#define HS_S_START 1
344#define HS_S_RESET 2
345#define HS_S_PAGE_ADDR 3
346#define HS_S_QUERY_PAGE 4
347#define HS_S_SEND_PAGE 5
348#define HS_S_END 6
349#define HS_S_ABORT 7
350#define HS_PAGE_VERIFY_SIZE 128
351
352#define HS_GET_STATE(a) (a & 0xFFFF)
353#define HS_GET_STATUS(a) ((a & 0xFFFF0000) >> 16)
354#define HS_SET_STATE(a, b) (a |= (b & 0xFFFF))
355#define HS_SET_STATUS(a, b) (a |= ((b & 0xFFFF) << 16))
356
357/* handshake frame */
358struct mvumi_hs_frame {
359 u16 size;
360 /* host information */
361 u8 host_type;
362 u8 reserved_1[1];
363 struct version_info host_ver; /* bios or driver version */
364
365 /* controller information */
366 u32 system_io_bus;
367 u32 slot_number;
368 u32 intr_level;
369 u32 intr_vector;
370
371 /* communication list configuration */
372 u32 ib_baseaddr_l;
373 u32 ib_baseaddr_h;
374 u32 ob_baseaddr_l;
375 u32 ob_baseaddr_h;
376
377 u8 ib_entry_size;
378 u8 ob_entry_size;
379 u8 ob_depth;
380 u8 ib_depth;
381
382 /* system time */
383 u64 seconds_since1970;
384};
385
386struct mvumi_hs_header {
387 u8 page_code;
388 u8 checksum;
389 u16 frame_length;
390 u32 frame_content[1];
391};
392
393/*
394 * the page code type of the handshake header
395 */
396#define HS_PAGE_FIRM_CAP 0x1
397#define HS_PAGE_HOST_INFO 0x2
398#define HS_PAGE_FIRM_CTL 0x3
399#define HS_PAGE_CL_INFO 0x4
400#define HS_PAGE_TOTAL 0x5
401
402#define HSP_SIZE(i) sizeof(struct mvumi_hs_page##i)
403
404#define HSP_MAX_SIZE ({ \
405 int size, m1, m2; \
406 m1 = max(HSP_SIZE(1), HSP_SIZE(3)); \
407 m2 = max(HSP_SIZE(2), HSP_SIZE(4)); \
408 size = max(m1, m2); \
409 size; \
410})
411
412/* The format of the page code for Firmware capability */
413struct mvumi_hs_page1 {
414 u8 pagecode;
415 u8 checksum;
416 u16 frame_length;
417
418 u16 number_of_ports;
419 u16 max_devices_support;
420 u16 max_io_support;
421 u16 umi_ver;
422 u32 max_transfer_size;
423 struct version_info fw_ver;
424 u8 cl_in_max_entry_size;
425 u8 cl_out_max_entry_size;
426 u8 cl_inout_list_depth;
427 u8 total_pages;
428 u16 capability;
429 u16 reserved1;
430};
431
432/* The format of the page code for Host information */
433struct mvumi_hs_page2 {
434 u8 pagecode;
435 u8 checksum;
436 u16 frame_length;
437
438 u8 host_type;
Shun Fubd756dd2012-09-23 22:16:14 +0800439 u8 host_cap;
440 u8 reserved[2];
Jianyun Lif0c568a2011-05-11 23:22:44 +0800441 struct version_info host_ver;
442 u32 system_io_bus;
443 u32 slot_number;
444 u32 intr_level;
445 u32 intr_vector;
446 u64 seconds_since1970;
447};
448
449/* The format of the page code for firmware control */
450struct mvumi_hs_page3 {
451 u8 pagecode;
452 u8 checksum;
453 u16 frame_length;
454 u16 control;
455 u8 reserved[2];
456 u32 host_bufferaddr_l;
457 u32 host_bufferaddr_h;
458 u32 host_eventaddr_l;
459 u32 host_eventaddr_h;
460};
461
462struct mvumi_hs_page4 {
463 u8 pagecode;
464 u8 checksum;
465 u16 frame_length;
466 u32 ib_baseaddr_l;
467 u32 ib_baseaddr_h;
468 u32 ob_baseaddr_l;
469 u32 ob_baseaddr_h;
470 u8 ib_entry_size;
471 u8 ob_entry_size;
472 u8 ob_depth;
473 u8 ib_depth;
474};
475
476struct mvumi_tag {
477 unsigned short *stack;
478 unsigned short top;
479 unsigned short size;
480};
481
Shun Fubd756dd2012-09-23 22:16:14 +0800482struct mvumi_device {
483 struct list_head list;
484 struct scsi_device *sdev;
485 u64 wwid;
486 u8 dev_type;
487 int id;
488};
489
Jianyun Lif0c568a2011-05-11 23:22:44 +0800490struct mvumi_hba {
491 void *base_addr[MAX_BASE_ADDRESS];
Shun Fubd756dd2012-09-23 22:16:14 +0800492 u32 pci_base[MAX_BASE_ADDRESS];
Jianyun Lif0c568a2011-05-11 23:22:44 +0800493 void *mmio;
494 struct list_head cmd_pool;
495 struct Scsi_Host *shost;
496 wait_queue_head_t int_cmd_wait_q;
497 struct pci_dev *pdev;
498 unsigned int unique_id;
499 atomic_t fw_outstanding;
500 struct mvumi_instance_template *instancet;
501
502 void *ib_list;
503 dma_addr_t ib_list_phys;
504
Shun Fubd756dd2012-09-23 22:16:14 +0800505 void *ib_frame;
506 dma_addr_t ib_frame_phys;
507
Jianyun Lif0c568a2011-05-11 23:22:44 +0800508 void *ob_list;
509 dma_addr_t ob_list_phys;
510
511 void *ib_shadow;
512 dma_addr_t ib_shadow_phys;
513
514 void *ob_shadow;
515 dma_addr_t ob_shadow_phys;
516
517 void *handshake_page;
518 dma_addr_t handshake_page_phys;
519
520 unsigned int global_isr;
521 unsigned int isr_status;
522
523 unsigned short max_sge;
524 unsigned short max_target_id;
525 unsigned char *target_map;
526 unsigned int max_io;
527 unsigned int list_num_io;
528 unsigned int ib_max_size;
529 unsigned int ob_max_size;
530 unsigned int ib_max_size_setting;
531 unsigned int ob_max_size_setting;
532 unsigned int max_transfer_size;
533 unsigned char hba_total_pages;
534 unsigned char fw_flag;
535 unsigned char request_id_enabled;
Shun Fubd756dd2012-09-23 22:16:14 +0800536 unsigned char eot_flag;
Jianyun Lif0c568a2011-05-11 23:22:44 +0800537 unsigned short hba_capability;
538 unsigned short io_seq;
539
540 unsigned int ib_cur_slot;
541 unsigned int ob_cur_slot;
542 unsigned int fw_state;
Shun Fubd756dd2012-09-23 22:16:14 +0800543 struct mutex sas_discovery_mutex;
Jianyun Lif0c568a2011-05-11 23:22:44 +0800544
545 struct list_head ob_data_list;
546 struct list_head free_ob_list;
547 struct list_head res_list;
548 struct list_head waiting_req_list;
549
550 struct mvumi_tag tag_pool;
551 struct mvumi_cmd **tag_cmd;
Shun Fubd756dd2012-09-23 22:16:14 +0800552 struct mvumi_hw_regs *regs;
553 struct mutex device_lock;
554 struct list_head mhba_dev_list;
555 struct list_head shost_dev_list;
556 struct task_struct *dm_thread;
557 atomic_t pnp_count;
Jianyun Lif0c568a2011-05-11 23:22:44 +0800558};
559
560struct mvumi_instance_template {
Shun Fubd756dd2012-09-23 22:16:14 +0800561 void (*fire_cmd) (struct mvumi_hba *, struct mvumi_cmd *);
562 void (*enable_intr) (struct mvumi_hba *);
563 void (*disable_intr) (struct mvumi_hba *);
564 int (*clear_intr) (void *);
565 unsigned int (*read_fw_status_reg) (struct mvumi_hba *);
566 unsigned int (*check_ib_list) (struct mvumi_hba *);
567 int (*check_ob_list) (struct mvumi_hba *, unsigned int *,
568 unsigned int *);
569 int (*reset_host) (struct mvumi_hba *);
Jianyun Lif0c568a2011-05-11 23:22:44 +0800570};
571
572extern struct timezone sys_tz;
573#endif