1: /*-
2: * Copyright (c) 2002 Adaptec Inc.
3: * All rights reserved.
4: *
5: * Written by: David Jeffery
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: *
28: * $FreeBSD: src/sys/dev/ips/ips.h,v 1.5 2003/11/27 08:37:36 mbr Exp $
29: * $DragonFly: src/sys/dev/raid/ips/ips.h,v 1.1 2004/01/15 15:41:23 drhodus Exp $
30: */
31:
32:
33: #include <sys/param.h>
34: #include <sys/systm.h>
35: #include <sys/kernel.h>
36: #include <sys/bus.h>
37: #include <sys/conf.h>
38: #include <sys/types.h>
39: #include <sys/queue.h>
40: #include <sys/buf.h>
41: #include <sys/malloc.h>
42: #include <sys/time.h>
43:
44: #include <machine/bus_memio.h>
45: #include <machine/bus.h>
46: #include <sys/rman.h>
47: #include <machine/resource.h>
48:
49: #include <bus/pci/pcireg.h>
50: #include <bus/pci/pcivar.h>
51:
52: /*
53: * IPS CONSTANTS
54: */
55: #define IPS_VENDOR_ID 0x1014
56: #define IPS_MORPHEUS_DEVICE_ID 0x01BD
57: #define IPS_COPPERHEAD_DEVICE_ID 0x002E
58: #define IPS_CSL 0xff
59: #define IPS_POCL 0x30
60:
61: /* amounts of memory to allocate for certain commands */
62: #define IPS_ADAPTER_INFO_LEN (sizeof(ips_adapter_info_t))
63: #define IPS_DRIVE_INFO_LEN (sizeof(ips_drive_info_t))
64: #define IPS_COMMAND_LEN 24
65: #define IPS_MAX_SG_LEN (sizeof(ips_sg_element_t) * IPS_MAX_SG_ELEMENTS)
66: #define IPS_NVRAM_PAGE_SIZE 128
67: /* various flags */
68: #define IPS_NOWAIT_FLAG 1
69:
70: /* states for the card to be in */
71: #define IPS_DEV_OPEN 0x01
72: #define IPS_TIMEOUT 0x02 /* command time out, need reset */
73: #define IPS_OFFLINE 0x04 /* can't reset card/card failure */
74:
75: /* max number of commands set to something low for now */
76: #define IPS_MAX_CMD_NUM 128
77: #define IPS_MAX_NUM_DRIVES 8
78: #define IPS_MAX_SG_ELEMENTS 32
79: #define IPS_MAX_IOBUF_SIZE (64 * 1024)
80: #define IPS_BLKSIZE 512
81:
82: /* logical drive states */
83:
84: #define IPS_LD_OFFLINE 0x02
85: #define IPS_LD_OKAY 0x03
86: #define IPS_LD_DEGRADED 0x04
87: #define IPS_LD_FREE 0x00
88: #define IPS_LD_SYS 0x06
89: #define IPS_LD_CRS 0x24
90:
91: /* register offsets */
92: #define MORPHEUS_REG_OMR0 0x0018 /* Outbound Msg. Reg. 0 */
93: #define MORPHEUS_REG_OMR1 0x001C /* Outbound Msg. Reg. 1 */
94: #define MORPHEUS_REG_IDR 0x0020 /* Inbound Doorbell Reg. */
95: #define MORPHEUS_REG_IISR 0x0024 /* Inbound IRQ Status Reg. */
96: #define MORPHEUS_REG_IIMR 0x0028 /* Inbound IRQ Mask Reg. */
97: #define MORPHEUS_REG_OISR 0x0030 /* Outbound IRQ Status Reg. */
98: #define MORPHEUS_REG_OIMR 0x0034 /* Outbound IRQ Status Reg. */
99: #define MORPHEUS_REG_IQPR 0x0040 /* Inbound Queue Port Reg. */
100: #define MORPHEUS_REG_OQPR 0x0044 /* Outbound Queue Port Reg. */
101:
102: #define COPPER_REG_SCPR 0x05 /* Subsystem Ctrl. Port Reg. */
103: #define COPPER_REG_ISPR 0x06 /* IRQ Status Port Reg. */
104: #define COPPER_REG_CBSP 0x07 /* ? Reg. */
105: #define COPPER_REG_HISR 0x08 /* Host IRQ Status Reg. */
106: #define COPPER_REG_CCSAR 0x10 /* Cmd. Channel Sys Addr Reg.*/
107: #define COPPER_REG_CCCR 0x14 /* Cmd. Channel Ctrl. Reg. */
108: #define COPPER_REG_SQHR 0x20 /* Status Queue Head Reg. */
109: #define COPPER_REG_SQTR 0x24 /* Status Queue Tail Reg. */
110: #define COPPER_REG_SQER 0x28 /* Status Queue End Reg. */
111: #define COPPER_REG_SQSR 0x2C /* Status Queue Start Reg. */
112:
113: /* bit definitions */
114: #define MORPHEUS_BIT_POST1 0x01
115: #define MORPHEUS_BIT_POST2 0x02
116: #define MORPHEUS_BIT_CMD_IRQ 0x08
117:
118: #define COPPER_CMD_START 0x101A
119: #define COPPER_SEM_BIT 0x08
120: #define COPPER_EI_BIT 0x80
121: #define COPPER_EBM_BIT 0x02
122: #define COPPER_RESET_BIT 0x80
123: #define COPPER_GHI_BIT 0x04
124: #define COPPER_SCE_BIT 0x01
125: #define COPPER_OP_BIT 0x01
126: #define COPPER_ILE_BIT 0x10
127:
128: /* status defines */
129: #define IPS_POST1_OK 0x8000
130: #define IPS_POST2_OK 0x000f
131:
132: /* command op codes */
133: #define IPS_READ_CMD 0x02
134: #define IPS_WRITE_CMD 0x03
135: #define IPS_ADAPTER_INFO_CMD 0x05
136: #define IPS_CACHE_FLUSH_CMD 0x0A
137: #define IPS_REBUILD_STATUS_CMD 0x0C
138: #define IPS_ERROR_TABLE_CMD 0x17
139: #define IPS_DRIVE_INFO_CMD 0x19
140: #define IPS_SUBSYS_PARAM_CMD 0x40
141: #define IPS_CONFIG_SYNC_CMD 0x58
142: #define IPS_SG_READ_CMD 0x82
143: #define IPS_SG_WRITE_CMD 0x83
144: #define IPS_RW_NVRAM_CMD 0xBC
145: #define IPS_FFDC_CMD 0xD7
146:
147: /* error information returned by the adapter */
148: #define IPS_MIN_ERROR 0x02
149: #define IPS_ERROR_STATUS 0x13000200 /* ahh, magic numbers */
150:
151: #define IPS_OS_FREEBSD 8
152: #define IPS_VERSION_MAJOR "0.90"
153: #define IPS_VERSION_MINOR ".10"
154:
155: /* Adapter Types */
156: #define IPS_ADAPTER_COPPERHEAD 0x01
157: #define IPS_ADAPTER_COPPERHEAD2 0x02
158: #define IPS_ADAPTER_COPPERHEADOB1 0x03
159: #define IPS_ADAPTER_COPPERHEADOB2 0x04
160: #define IPS_ADAPTER_CLARINET 0x05
161: #define IPS_ADAPTER_CLARINETLITE 0x06
162: #define IPS_ADAPTER_TROMBONE 0x07
163: #define IPS_ADAPTER_MORPHEUS 0x08
164: #define IPS_ADAPTER_MORPHEUSLITE 0x09
165: #define IPS_ADAPTER_NEO 0x0A
166: #define IPS_ADAPTER_NEOLITE 0x0B
167: #define IPS_ADAPTER_SARASOTA2 0x0C
168: #define IPS_ADAPTER_SARASOTA1 0x0D
169: #define IPS_ADAPTER_MARCO 0x0E
170: #define IPS_ADAPTER_SEBRING 0x0F
171: #define IPS_ADAPTER_MAX_T IPS_ADAPTER_SEBRING
172:
173: /* values for ffdc_settime (from gmtime) */
174: #define IPS_SECSPERMIN 60
175: #define IPS_MINSPERHOUR 60
176: #define IPS_HOURSPERDAY 24
177: #define IPS_DAYSPERWEEK 7
178: #define IPS_DAYSPERNYEAR 365
179: #define IPS_DAYSPERLYEAR 366
180: #define IPS_SECSPERHOUR (IPS_SECSPERMIN * IPS_MINSPERHOUR)
181: #define IPS_SECSPERDAY ((long) IPS_SECSPERHOUR * IPS_HOURSPERDAY)
182: #define IPS_MONSPERYEAR 12
183: #define IPS_EPOCH_YEAR 1970
184: #define IPS_LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
185: #define ips_isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))
186:
187:
188: /*
189: * for compatibility
190: */
191: /* struct buf to struct bio changes */
192: #define BIO_ERROR B_ERROR
193: #define BIO_READ B_READ
194: #define bio buf
195: #define bio_error b_error
196: #define bio_flags b_flags
197: #define bio_driver1 b_driver1
198: #define bio_pblkno b_pblkno
199: #define bio_data b_data
200: #define bio_bcount b_bcount
201: #define bio_dev b_dev
202: #define bio_resid b_resid
203:
204: /* geom */
205: #define bio_disk bio_dev
206: #define d_drv1 si_drv1
207: #define d_maxsize si_iosize_max
208:
209: struct mtx {
210: volatile int locked;
211: intrmask_t spl;
212: };
213:
214: #define IPS_LOCK_INIT(sc) (sc)->cmd_mtx.locked = 0
215: #define IPS_LOCK(sc) do { \
216: int s = splbio(); \
217: if ((sc)->cmd_mtx.locked++ == 0) \
218: (sc)->cmd_mtx.spl = s; \
219: else \
220: splx(s); \
221: } while (0)
222: #define IPS_UNLOCK(sc) do { \
223: if ((sc)->cmd_mtx.locked) { \
224: if (--((sc)->cmd_mtx.locked) == 0) \
225: splx((sc)->cmd_mtx.spl); \
226: } \
227: } while (0)
228: #define IPS_LOCK_FREE(sc)
229:
230: #define disk_open_t d_open_t
231: #define disk_close_t d_close_t
232: #define disk_strategy_t d_strategy_t
233:
234: #if defined(PCIR_MAPS) && !defined(PCIR_BARS)
235: # define PCIR_BAR(x) (PCIR_BARS + (x) * 4)
236: # define PCIR_BARS PCIR_MAPS
237: #endif
238:
239:
240: /*
241: * IPS MACROS
242: */
243:
244: #define ips_read_1(sc,offset) bus_space_read_1(sc->bustag, sc->bushandle, offset)
245: #define ips_read_2(sc,offset) bus_space_read_2(sc->bustag, sc->bushandle, offset)
246: #define ips_read_4(sc,offset) bus_space_read_4(sc->bustag, sc->bushandle, offset)
247:
248: #define ips_write_1(sc,offset,value) bus_space_write_1(sc->bustag, sc->bushandle, offset, value)
249: #define ips_write_2(sc,offset,value) bus_space_write_2(sc->bustag, sc->bushandle, offset, value)
250: #define ips_write_4(sc,offset,value) bus_space_write_4(sc->bustag, sc->bushandle, offset, value)
251:
252: #define ips_read_request(iobuf) ((iobuf)->b_flags & B_READ)
253:
254: /* this is ugly. It zeros the end elements in an ips_command_t struct starting with the status element */
255: #define clear_ips_command(command) bzero(&((command)->status), (unsigned long)(&(command)[1])-(unsigned long)&((command)->status))
256:
257: #define COMMAND_ERROR(status) (((status)->fields.basic_status & 0x0f) >= IPS_MIN_ERROR)
258:
259: #ifndef IPS_DEBUG
260: #define DEVICE_PRINTF(x...)
261: #define PRINTF(x...)
262: #else
263: #define DEVICE_PRINTF(level,x...) if(IPS_DEBUG >= level)device_printf(x)
264: #define PRINTF(level,x...) if(IPS_DEBUG >= level)printf(x)
265: #endif
266:
267: /*
268: * IPS STRUCTS
269: */
270: struct ips_softc;
271:
272: typedef struct {
273: u_int8_t command;
274: u_int8_t id;
275: u_int8_t drivenum;
276: u_int8_t reserve2;
277: u_int32_t lba;
278: u_int32_t buffaddr;
279: u_int32_t reserve3;
280: } __attribute__ ((packed)) ips_generic_cmd;
281:
282: typedef struct {
283: u_int8_t command;
284: u_int8_t id;
285: u_int8_t drivenum;
286: u_int8_t segnum;
287: u_int32_t lba;
288: u_int32_t buffaddr;
289: u_int16_t length;
290: u_int16_t reserve1;
291: } __attribute__ ((packed)) ips_io_cmd;
292:
293: typedef struct {
294: u_int8_t command;
295: u_int8_t id;
296: u_int8_t pagenum;
297: u_int8_t rw;
298: u_int32_t reserve1;
299: u_int32_t buffaddr;
300: u_int32_t reserve3;
301: } __attribute__ ((packed)) ips_rw_nvram_cmd;
302:
303: typedef struct {
304: u_int8_t command;
305: u_int8_t id;
306: u_int8_t drivenum;
307: u_int8_t reserve1;
308: u_int32_t reserve2;
309: u_int32_t buffaddr;
310: u_int32_t reserve3;
311: } __attribute__ ((packed)) ips_drive_cmd;
312:
313: typedef struct {
314: u_int8_t command;
315: u_int8_t id;
316: u_int8_t reserve1;
317: u_int8_t commandtype;
318: u_int32_t reserve2;
319: u_int32_t buffaddr;
320: u_int32_t reserve3;
321: } __attribute__((packed)) ips_adapter_info_cmd;
322:
323: typedef struct {
324: u_int8_t command;
325: u_int8_t id;
326: u_int8_t reset_count;
327: u_int8_t reset_type;
328: u_int8_t second;
329: u_int8_t minute;
330: u_int8_t hour;
331: u_int8_t day;
332: u_int8_t reserve1[4];
333: u_int8_t month;
334: u_int8_t yearH;
335: u_int8_t yearL;
336: u_int8_t reserve2;
337: } __attribute__((packed)) ips_adapter_ffdc_cmd;
338:
339: typedef union{
340: ips_generic_cmd generic_cmd;
341: ips_drive_cmd drive_cmd;
342: ips_adapter_info_cmd adapter_info_cmd;
343: } ips_cmd_buff_t;
344:
345: typedef struct {
346: u_int32_t signature;
347: u_int8_t reserved;
348: u_int8_t adapter_slot;
349: u_int16_t adapter_type;
350: u_int8_t bios_high[4];
351: u_int8_t bios_low[4];
352: u_int16_t reserve2;
353: u_int8_t reserve3;
354: u_int8_t operating_system;
355: u_int8_t driver_high[4];
356: u_int8_t driver_low[4];
357: u_int8_t reserve4[100];
358: } __attribute__((packed)) ips_nvram_page5;
359:
360: typedef struct {
361: u_int32_t addr;
362: u_int32_t len;
363: } ips_sg_element_t;
364:
365: typedef struct {
366: u_int8_t drivenum;
367: u_int8_t merge_id;
368: u_int8_t raid_lvl;
369: u_int8_t state;
370: u_int32_t sector_count;
371: } __attribute__((packed)) ips_drive_t;
372:
373: typedef struct {
374: u_int8_t drivecount;
375: u_int8_t reserve1;
376: u_int16_t reserve2;
377: ips_drive_t drives[IPS_MAX_NUM_DRIVES];
378: } __attribute__((packed)) ips_drive_info_t;
379:
380: typedef struct {
381: u_int8_t drivecount;
382: u_int8_t miscflags;
383: u_int8_t SLTflags;
384: u_int8_t BSTflags;
385: u_int8_t pwr_chg_count;
386: u_int8_t wrong_addr_count;
387: u_int8_t unident_count;
388: u_int8_t nvram_dev_chg_count;
389: u_int8_t codeblock_version[8];
390: u_int8_t bootblock_version[8];
391: u_int32_t drive_sector_count[IPS_MAX_NUM_DRIVES];
392: u_int8_t max_concurrent_cmds;
393: u_int8_t max_phys_devices;
394: u_int16_t flash_prog_count;
395: u_int8_t defunct_disks;
396: u_int8_t rebuildflags;
397: u_int8_t offline_drivecount;
398: u_int8_t critical_drivecount;
399: u_int16_t config_update_count;
400: u_int8_t blockedflags;
401: u_int8_t psdn_error;
402: u_int16_t addr_dead_disk[4*16]; /* ugly, max # channels * max # scsi devices per channel */
403: } __attribute__((packed)) ips_adapter_info_t;
404:
405: typedef struct {
406: u_int32_t status[IPS_MAX_CMD_NUM];
407: u_int32_t base_phys_addr;
408: int nextstatus;
409: bus_dma_tag_t dmatag;
410: bus_dmamap_t dmamap;
411: } ips_copper_queue_t;
412:
413: typedef union {
414: struct {
415: u_int8_t reserved;
416: u_int8_t command_id;
417: u_int8_t basic_status;
418: u_int8_t extended_status;
419: } fields;
420: volatile u_int32_t value;
421: } ips_cmd_status_t;
422:
423: /* used to keep track of current commands to the card */
424: typedef struct ips_command {
425: u_int8_t command_number;
426: u_int8_t id;
427: u_int8_t timeout;
428: struct ips_softc *sc;
429: bus_dmamap_t command_dmamap;
430: void *command_buffer;
431: u_int32_t command_phys_addr; /*WARNING! must be changed if 64bit addressing ever used*/
432: ips_cmd_status_t status;
433: SLIST_ENTRY(ips_command) next;
434: bus_dma_tag_t data_dmatag;
435: bus_dmamap_t data_dmamap;
436: void *data_buffer;
437: void *arg;
438: void (*callback)(struct ips_command *command);
439: } ips_command_t;
440:
441: typedef struct ips_wait_list {
442: STAILQ_ENTRY(ips_wait_list) next;
443: void *data;
444: int (* callback)(ips_command_t *command);
445: } ips_wait_list_t;
446:
447: typedef struct ips_softc {
448: struct resource *iores;
449: struct resource *irqres;
450: struct intr_config_hook ips_ich;
451: int configured;
452: int state;
453: int iotype;
454: int rid;
455: int irqrid;
456: void *irqcookie;
457: bus_space_tag_t bustag;
458: bus_space_handle_t bushandle;
459: bus_dma_tag_t adapter_dmatag;
460: bus_dma_tag_t command_dmatag;
461: bus_dma_tag_t sg_dmatag;
462: device_t dev;
463: dev_t device_file;
464: struct callout_handle timer;
465: u_int16_t adapter_type;
466: ips_adapter_info_t adapter_info;
467: device_t diskdev[IPS_MAX_NUM_DRIVES];
468: ips_drive_t drives[IPS_MAX_NUM_DRIVES];
469: u_int8_t drivecount;
470: u_int16_t ffdc_resetcount;
471: struct timeval ffdc_resettime;
472: u_int8_t next_drive;
473: u_int8_t max_cmds;
474: volatile u_int8_t used_commands;
475: ips_command_t commandarray[IPS_MAX_CMD_NUM];
476: SLIST_HEAD(command_list, ips_command) free_cmd_list;
477: STAILQ_HEAD(command_wait_list,ips_wait_list) cmd_wait_list;
478: int (*ips_adapter_reinit)(struct ips_softc *sc,
479: int force);
480: void (*ips_adapter_intr)(void *sc);
481: void (*ips_issue_cmd)(ips_command_t *command);
482: ips_copper_queue_t *copper_queue;
483: struct mtx cmd_mtx;
484: } ips_softc_t;
485:
486: /* function defines from ips_ioctl.c */
487: extern int ips_ioctl_request(ips_softc_t *sc, u_long ioctl_cmd, caddr_t addr,
488: int32_t flags);
489: /* function defines from ips_disk.c */
490: extern void ipsd_finish(struct bio *iobuf);
491:
492: /* function defines from ips_commands.c */
493: extern int ips_flush_cache(ips_softc_t *sc);
494: extern void ips_start_io_request(ips_softc_t *sc, struct bio *iobuf);
495: extern int ips_get_drive_info(ips_softc_t *sc);
496: extern int ips_get_adapter_info(ips_softc_t *sc);
497: extern int ips_ffdc_reset(ips_softc_t *sc);
498: extern int ips_update_nvram(ips_softc_t *sc);
499: extern int ips_clear_adapter(ips_softc_t *sc);
500:
501: /* function defines from ips.c */
502: extern int ips_get_free_cmd(ips_softc_t *sc, int (*callback)(ips_command_t *),
503: void *data, unsigned long flags);
504: extern void ips_insert_free_cmd(ips_softc_t *sc, ips_command_t *command);
505: extern int ips_adapter_init(ips_softc_t *sc);
506: extern int ips_morpheus_reinit(ips_softc_t *sc, int force);
507: extern int ips_adapter_free(ips_softc_t *sc);
508: extern void ips_morpheus_intr(void *sc);
509: extern void ips_issue_morpheus_cmd(ips_command_t *command);
510: extern int ips_copperhead_reinit(ips_softc_t *sc, int force);
511: extern void ips_copperhead_intr(void *sc);
512: extern void ips_issue_copperhead_cmd(ips_command_t *command);
513:
514: #define IPS_CDEV_MAJOR 175
515: #define IPSD_CDEV_MAJOR 176