summaryrefslogtreecommitdiffstats
path: root/sys/dev/dpt/dpt.h
blob: 6c0e341db475492e7685ce145d684bd6ac8ab25f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
/*-
 *       Copyright (c) 1997 by Simon Shapiro
 *       All Rights Reserved
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification, immediately at the beginning of the file.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. The name of the author may not be used to endorse or promote products
 *    derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * $FreeBSD$
 */

/*
 *
 *  dpt.h:	Definitions and constants used by the SCSI side of the DPT
 *
 *  credits:	Mike Neuffer;	DPT low level code and in other areas as well.
 *		Mark Salyzyn; 	Many vital bits of info and diagnostics.
 *		Justin Gibbs;	FreeBSD API, debugging and style
 *		Ron McDaniels;	SCSI Software Interrupts
 *		FreeBSD.ORG;	Great O/S to work on and for.
 */

#ifndef _DPT_H
#define _DPT_H

#include <sys/ioccom.h>


#undef DPT_USE_DLM_SWI

#define DPT_RELEASE				1
#define DPT_VERSION				4
#define DPT_PATCH				5
#define DPT_MONTH				8
#define DPT_DAY					3
#define DPT_YEAR				18	/* 1998 - 1980 */

#define DPT_CTL_RELEASE			1
#define DPT_CTL_VERSION			0
#define DPT_CTL_PATCH			6

#ifndef PAGESIZ
#define PAGESIZ					4096
#endif

#ifndef physaddr
typedef void *physaddr;
#endif

#undef	DPT_INQUIRE_DEVICES	  /* We have no buyers for this function */
#define DPT_SUPPORT_POLLING	  /* Use polled mode at boot (must be ON!) */
#define DPT_OPENNINGS		8 /* Commands-in-progress per device */

#define DPT_RETRIES		5 /* Times to retry failed commands */
#undef	DPT_DISABLE_SG
#define DPT_HAS_OPEN

/* Arguments to dpt_run_queue() can be: */

#define DPT_MAX_TARGET_MODE_BUFFER_SIZE		8192
#define DPT_FREE_LIST_INCREMENT			64
#define DPT_CMD_LEN	      	 		12

/*
 * How many segments do we want in a Scatter/Gather list?
 * Some HBA's can  do 16, Some 8192. Since we pre-allocate
 * them in fixed increments, we need to put a practical limit on
 * these. A passed parameter (from kernel boot or lkm) would help
 */
#define DPT_MAX_SEGS		      	 	32

/* Debug levels */

#undef	DPT_DEBUG_PCI
#undef	DPT_DEBUG_INIT
#undef	DPT_DEBUG_SETUP
#undef	DPT_DEBUG_STATES
#undef	DPT_DEBUG_CONFIG
#undef	DPT_DEBUG_QUEUES
#undef	DPT_DEBUG_SCSI_CMD
#undef	DPT_DEBUG_SOFTINTR
#undef	DPT_DEBUG_HARDINTR
#undef	DPT_DEBUG_HEX_DUMPS
#undef	DPT_DEBUG_POLLING
#undef	DPT_DEBUG_INQUIRE
#undef	DPT_DEBUG_COMPLETION
#undef	DPT_DEBUG_COMPLETION_ERRORS
#define	DPT_DEBUG_MINPHYS
#undef	DPT_DEBUG_SG
#undef	DPT_DEBUG_SG_SHOW_DATA
#undef	DPT_DEBUG_SCSI_CMD_NAME
#undef	DPT_DEBUG_CONTROL
#undef	DPT_DEBUG_TIMEOUTS
#undef	DPT_DEBUG_SHUTDOWN
#define	DPT_DEBUG_USER_CMD

/*
 * Misc. definitions
 */
#undef TRUE
#undef FALSE
#define TRUE	 		1
#define FALSE			0

#define MAX_CHANNELS	3
#define MAX_TARGETS		16
#define MAX_LUNS        8

/* Map minor numbers to device identity */
#define TARGET_MASK			0x000f
#define BUS_MASK			0x0030
#define HBA_MASK			0x01c0
#define LUN_MASK			0x0e00

#define minor2target(minor)		( minor & TARGET_MASK )
#define minor2bus(minor)		( (minor & BUS_MASK) >> 4 )
#define minor2hba(minor)		( (minor & HBA_MASK) >> 6 )
#define minor2lun(minor)		( (minor & LUN_MASK) >> 9 )

/*
 * Valid values for cache_type
 */
#define DPT_NO_CACHE		       	0
#define DPT_CACHE_WRITETHROUGH		1
#define DPT_CACHE_WRITEBACK		2

#define min(a,b) ((a<b)?(a):(b))

#define MAXISA			       	4
#define MAXEISA			      	16
#define MAXPCI		       		16
#define MAXIRQ	       			16
#define MAXTARGET		      	16

#define IS_ISA				'I'
#define IS_EISA				'E'
#define IS_PCI				'P'

#define BROKEN_INQUIRY	1

#define BUSMASTER			0xff
#define PIO			       	0xfe

#define EATA_SIGNATURE			0x41544145 /* little ENDIAN "EATA" */
#define	DPT_BLINK_INDICATOR		0x42445054

#define DPT_ID1				0x12
#define DPT_ID2				0x1
#define ATT_ID1				0x06
#define ATT_ID2				0x94
#define ATT_ID3				0x0

#define NEC_ID1				0x38
#define NEC_ID2				0xa3
#define NEC_ID3				0x82

#define MAX_PCI_DEVICES			32 /* Maximum # Of Devices Per Bus */
#define MAX_METHOD_2			16 /* Max Devices For Method 2 */
#define MAX_PCI_BUS			16 /* Maximum # Of Busses Allowed */

#define DPT_MAX_RETRIES			2

#define READ		       		0
#define WRITE	       			1
#define OTHER			       	2

#define HD(cmd)	((hostdata *)&(cmd->host->hostdata))
#define CD(cmd)	((struct eata_ccb *)(cmd->host_scribble))
#define SD(host) ((hostdata *)&(host->hostdata))

/*
 * EATA Command & Register definitions
 */
    
#define PCI_REG_DPTconfig		       	0x40
#define PCI_REG_PumpModeAddress			0x44
#define PCI_REG_PumpModeData			0x48
#define PCI_REG_ConfigParam1			0x50
#define PCI_REG_ConfigParam2			0x54

#define EATA_CMD_PIO_SETUPTEST			0xc6
#define EATA_CMD_PIO_READ_CONFIG		0xf0
#define EATA_CMD_PIO_SET_CONFIG			0xf1
#define EATA_CMD_PIO_SEND_CP			0xf2
#define EATA_CMD_PIO_RECEIVE_SP			0xf3
#define EATA_CMD_PIO_TRUNC		      	0xf4

#define EATA_CMD_RESET			       	0xf9
#define EATA_COLD_BOOT                          0x06 /* Last resort only! */

#define EATA_CMD_IMMEDIATE		       	0xfa

#define EATA_CMD_DMA_READ_CONFIG		0xfd
#define EATA_CMD_DMA_SET_CONFIG			0xfe
#define EATA_CMD_DMA_SEND_CP			0xff

#define ECS_EMULATE_SENSE		       	0xd4

/*
 * Immediate Commands
 * Beware of this enumeration.	Not all commands are in sequence!
 */

enum dpt_immediate_cmd {
    EATA_GENERIC_ABORT,
    EATA_SPECIFIC_RESET,
    EATA_BUS_RESET,
    EATA_SPECIFIC_ABORT,
    EATA_QUIET_INTR,
    EATA_SMART_ROM_DL_EN,
    EATA_COLD_BOOT_HBA,	/* Only as a last resort	*/
    EATA_FORCE_IO,
    EATA_SCSI_BUS_OFFLINE,
    EATA_RESET_MASKED_BUS,
    EATA_POWER_OFF_WARN
};

#define HA_CTRLREG		0x206 /* control register for HBA */
#define HA_CTRL_DISINT		0x02  /* CTRLREG: disable interrupts */
#define HA_CTRL_RESCPU		0x04  /* CTRLREG: reset processo */
#define HA_CTRL_8HEADS		0x08  /*
				       * CTRLREG: set for drives with
				       * >=8 heads
				       * (WD1003 rudimentary :-)
				       */

#define HA_WCOMMAND		0x07  /* command register offset	*/
#define HA_WIFC		       	0x06  /* immediate command offset	*/
#define HA_WCODE	       	0x05
#define HA_WCODE2	       	0x04
#define HA_WDMAADDR		0x02  /* DMA address LSB offset	*/
#define HA_RERROR	       	0x01  /* Error Register, offset 1 from base */
#define HA_RAUXSTAT		0x08  /* aux status register offset */
#define HA_RSTATUS		0x07  /* status register offset	*/
#define HA_RDATA	       	0x00  /* data register (16bit)	*/
#define HA_WDATA	       	0x00  /* data register (16bit)	*/

#define HA_ABUSY	       	0x01  /* aux busy bit		*/
#define HA_AIRQ			0x02  /* aux IRQ pending bit	*/
#define HA_SERROR	       	0x01  /* pr. command ended in error */
#define HA_SMORE	       	0x02  /* more data soon to come	*/
#define HA_SCORR	       	0x04  /* datio_addra corrected	*/
#define HA_SDRQ		       	0x08  /* data request active	*/
#define HA_SSC		       	0x10  /* seek complete		*/
#define HA_SFAULT	       	0x20  /* write fault		*/
#define HA_SREADY	       	0x40  /* drive ready		*/
#define HA_SBUSY	       	0x80  /* drive busy		*/
#define HA_SDRDY	       	(HA_SSC|HA_SREADY|HA_SDRQ)

/*
 * Message definitions	
 */

enum dpt_message {
	HA_NO_ERROR,		/* No Error				*/
	HA_ERR_SEL_TO,		/* Selection Timeout			*/
	HA_ERR_CMD_TO,		/* Command Timeout			*/
	HA_SCSIBUS_RESET,
	HA_HBA_POWER_UP,	/* Initial Controller Power-up		*/
	HA_UNX_BUSPHASE,	/* Unexpected Bus Phase			*/
	HA_UNX_BUS_FREE,	/* Unexpected Bus Free			*/
	HA_BUS_PARITY,		/* Bus Parity Error			*/
	HA_SCSI_HUNG,		/* SCSI Hung				*/
	HA_UNX_MSGRJCT,		/* Unexpected Message Rejected		*/
	HA_RESET_STUCK,		/* SCSI Bus Reset Stuck			*/
	HA_RSENSE_FAIL,		/* Auto Request-Sense Failed		*/
	HA_PARITY_ERR,		/* Controller Ram Parity Error		*/
	HA_CP_ABORT_NA,		/* Abort Message sent to non-active cmd */
	HA_CP_ABORTED,		/* Abort Message sent to active cmd	*/
	HA_CP_RESET_NA,		/* Reset Message sent to non-active cmd */
	HA_CP_RESET,		/* Reset Message sent to active cmd	*/
	HA_ECC_ERR,		/* Controller Ram ECC Error		*/
	HA_PCI_PARITY,		/* PCI Parity Error			*/
	HA_PCI_MABORT,		/* PCI Master Abort			*/
	HA_PCI_TABORT,		/* PCI Target Abort			*/
	HA_PCI_STABORT		/* PCI Signaled Target Abort		*/
};

#define HA_STATUS_MASK  	0x7F
#define HA_IDENTIFY_MSG 	0x80
#define HA_DISCO_RECO   	0x40            /* Disconnect/Reconnect         */

#define DPT_RW_BUFF_HEART	0X00
#define DPT_RW_BUFF_DLM		0x02
#define DPT_RW_BUFF_ACCESS	0x03

#define HA_INTR_OFF		1
#define HA_INTR_ON	       	0

/* This is really a one-time shot through some black magic */
#define DPT_EATA_REVA 0x1c
#define DPT_EATA_REVB 0x1e
#define DPT_EATA_REVC 0x22
#define DPT_EATA_REVZ 0x24


/* IOCTL List */

#define DPT_RW_CMD_LEN 			32
#define DPT_RW_CMD_DUMP_SOFTC		"dump softc"
#define DPT_RW_CMD_DUMP_SYSINFO		"dump sysinfo"
#define DPT_RW_CMD_DUMP_METRICS		"dump metrics"
#define DPT_RW_CMD_CLEAR_METRICS	"clear metrics"
#define DPT_RW_CMD_SHOW_LED		"show LED"

#define DPT_IOCTL_INTERNAL_METRICS	_IOR('D',  1, dpt_perf_t)
#define DPT_IOCTL_SOFTC		       	_IOR('D',  2, dpt_user_softc_t) 
#define DPT_IOCTL_SEND		       	_IOWR('D', 3, eata_pt_t)
#define SDI_SEND			0x40044444 /* Observed from dptmgr */

/*
 *	Other	definitions
 */

#define DPT_HCP_LENGTH(page)	(ntohs(*(int16_t *)(void *)(&page[2]))+4)
#define DPT_HCP_FIRST(page) 	(&page[4])
#define DPT_HCP_NEXT(param) 	(&param[3 + param[3] + 1])
#define DPT_HCP_CODE(param)	(ntohs(*(int16_t *)(void *)param))


/* Possible return values from dpt_register_buffer() */

#define SCSI_TM_READ_BUFFER	0x3c
#define SCSI_TM_WRITE_BUFFER	0x3b

#define SCSI_TM_MODE_MASK	0x07  /* Strip off reserved and LUN */
#define SCSI_TM_LUN_MASK	0xe0  /* Strip off reserved and LUN */

typedef enum {
	SUCCESSFULLY_REGISTERED,
	DRIVER_DOWN,
	ALREADY_REGISTERED,
	REGISTERED_TO_ANOTHER,
	NOT_REGISTERED,	
	INVALID_UNIT,
	INVALID_SENDER,
	INVALID_CALLBACK,
	NO_RESOURCES
} dpt_rb_t;

typedef enum {
	REGISTER_BUFFER,
	RELEASE_BUFFER
} dpt_rb_op_t;

/*
 * New way for completion routines to reliably copmplete processing.
 * Should take properly typed dpt_softc_t and dpt_ccb_t,
 * but interdependencies preclude that.
 */
typedef void (*ccb_callback)(void *dpt, int bus, void *ccb);

typedef void (*buff_wr_done)(int unit, u_int8_t channel, u_int8_t target,
			     u_int8_t lun, u_int16_t offset, u_int16_t length,
			     int result);

typedef void (*dpt_rec_buff)(int unit, u_int8_t channel, u_int8_t target,
			     u_int8_t lun, void *buffer, u_int16_t offset,
			     u_int16_t length);

/* HBA's Status port (register) bitmap */
typedef struct reg_bit {   /* reading this one will clear the interrupt */
	u_int8_t error :1, /* previous command ended in an error */
		 more  :1, /* More DATA coming soon Poll BSY & DRQ (PIO) */
		 corr  :1, /* data read was successfully corrected with ECC */
		 drq   :1, /* data request active */
		 sc    :1, /* seek complete */
		 fault :1, /* write fault */
		 ready :1, /* drive ready */
		 busy  :1; /* controller busy */
} dpt_status_reg_t;

/* HBA's Auxiliary status port (register) bitmap */
typedef struct reg_abit {  /* reading this won't clear the interrupt */
	u_int8_t abusy :1, /* auxiliary busy */
		 irq   :1, /* set when drive interrupt is asserted */
		       :6;
} dpt_aux_status_t;

/* The EATA Register Set as a structure */
typedef struct eata_register {
	u_int8_t data_reg[2];	/* R, couldn't figure this one out */
	u_int8_t cp_addr[4];	/* W, CP address register */
	union {
		u_int8_t command; /*
				   * W, command code:
				   * [read|set] conf, send CP
				   */
		struct	 reg_bit status; /* R, see register_bit1 */
		u_int8_t statusbyte;
	} ovr;
	struct reg_abit aux_stat; /* R, see register_bit2 */
} eata_reg_t;

/*
 * Holds the results of a READ_CONFIGURATION command
 * Beware of data items which are larger than 1 byte.
 * these come from the DPT in network order.
 * On an Intel ``CPU'' they will be upside down and backwards!
 * The dpt_get_conf function is normally responsible for flipping
 * Everything back.
 */
typedef struct get_conf {  /* Read Configuration Array */
	union {
		struct {
			u_int8_t foo_DevType;
			u_int8_t foo_PageCode;
			u_int8_t foo_Reserved0; 
			u_int8_t foo_len;
		} foo;
		u_int32_t foo_length;	/* Should return 0x22, 0x24, etc */
	} bar;
#define gcs_length	       	bar.foo_length
#define gcs_PageCode		bar.foo.foo_DevType
#define gcs_reserved0		bar.foo.foo_Reserved0
#define gcs_len		       	bar.foo.foo_len

	u_int32_t signature;	/* Signature MUST be "EATA".	ntohl()`ed */

	u_int8_t  version2 :4,
		  version  :4;	/* EATA Version level */

	u_int8_t  OCS_enabled :1, /* Overlap Command Support enabled */
		  TAR_support :1, /* SCSI Target Mode supported */
		  TRNXFR      :1, /* Truncate Transfer Cmd Used in PIO Mode */
		  MORE_support:1, /* MORE supported (PIO Mode Only) */
		  DMA_support :1, /* DMA supported */
		  DMA_valid   :1, /* DRQ value in Byte 30 is valid */
		  ATA	      :1, /* ATA device connected (not supported) */
		  HAA_valid   :1; /* Hostadapter Address is valid */

	u_int16_t cppadlen; /*
			     * Number of pad bytes send after CD data set
			     * to zero for DMA commands. Ntohl()`ed
			     */
	u_int8_t  scsi_idS; /* SCSI ID of controller 2-0 Byte 0 res. */
	u_int8_t  scsi_id2; /* If not, zero is returned */
	u_int8_t  scsi_id1;
	u_int8_t  scsi_id0;
	u_int32_t cplen;    /* CP length: number of valid cp bytes */

	u_int32_t splen;    /* Returned bytes for a received SP command */
	u_int16_t queuesiz; /* max number of queueable CPs */

	u_int16_t dummy;
	u_int16_t SGsiz;	/* max number of SG table entrie */

	u_int8_t  IRQ	     :4,/* IRQ used this HBA */
		  IRQ_TR     :1,/* IRQ Trigger: 0=edge, 1=level	 */
		  SECOND     :1,/* This is a secondary controller */
		  DMA_channel:2;/* DRQ index, DRQ is 2comp of DRQX */

	u_int8_t  sync;		/* 0-7 sync active bitmask (deprecated) */
	u_int8_t  DSBLE   :1,	/* ISA i/o addressing is disabled */
		  FORCADR :1,	/* i/o address has been forced */
		  SG_64K  :1,
		  SG_UAE  :1,
			  :4;

	u_int8_t  MAX_ID   :5,	/* Max number of SCSI target IDs */
		  MAX_CHAN :3;	/* Number of SCSI busses on HBA	 */

	u_int8_t  MAX_LUN;	/* Max number of LUNs */
	u_int8_t	  :3,
		  AUTOTRM :1,
		  M1_inst :1,
		  ID_qest :1,	/* Raidnum ID is questionable */
		  is_PCI  :1,	/* HBA is PCI */
		  is_EISA :1;	/* HBA is EISA */

	u_int8_t  RAIDNUM;	/* unique HBA identifier */
	u_int8_t  unused[4];	/* When doing PIO, you	GET 512 bytes */
    
	/* >>------>>	End of The DPT structure	<<------<< */

	u_int32_t length;	/* True length, after ntohl conversion	*/
} dpt_conf_t;

/* Scatter-Gather list entry */
typedef struct dpt_sg_segment {
	u_int32_t seg_addr;	/* All fields in network byte order */
	u_int32_t seg_len;
} dpt_sg_t;


/* Status Packet */
typedef struct eata_sp {
	u_int8_t  hba_stat :7,	/* HBA status */
		  EOC	  :1;	/* True if command finished */

	u_int8_t  scsi_stat;	/* Target SCSI status */

	u_int8_t  reserved[2];

	u_int32_t residue_len;	/* Number of bytes not transferred */

	u_int32_t ccb_busaddr;

	u_int8_t  sp_ID_Message;
	u_int8_t  sp_Que_Message;
	u_int8_t  sp_Tag_Message;
	u_int8_t  msg[9];
} dpt_sp_t;

/*
 * A strange collection of O/S-Hardware releated bits and pieces.
 * Used by the dpt_ioctl() entry point to return DPT_SYSINFO command.
 */
typedef struct dpt_drive_parameters {
	u_int16_t cylinders; /* Up to 1024 */
	u_int8_t  heads;     /* Up to 255  */
	u_int8_t  sectors;   /* Up to 63   */
} dpt_drive_t;

typedef struct driveParam_S driveParam_T;

#define SI_CMOS_Valid           0x0001
#define SI_NumDrivesValid       0x0002
#define SI_ProcessorValid       0x0004
#define SI_MemorySizeValid      0x0008
#define SI_DriveParamsValid     0x0010
#define SI_SmartROMverValid     0x0020
#define SI_OSversionValid       0x0040
#define SI_OSspecificValid      0x0080	
#define SI_BusTypeValid         0x0100

#define SI_ALL_VALID        	0x0FFF
#define SI_NO_SmartROM     	0x8000

#define SI_ISA_BUS	       	0x00
#define SI_MCA_BUS        	0x01
#define SI_EISA_BUS	       	0x02
#define SI_PCI_BUS	       	0x04

#define HBA_BUS_ISA		0x00
#define HBA_BUS_EISA		0x01
#define HBA_BUS_PCI		0x02

typedef struct dpt_sysinfo {
	u_int8_t    drive0CMOS;			/* CMOS Drive 0 Type */
	u_int8_t    drive1CMOS;			/* CMOS Drive 1 Type */
	u_int8_t    numDrives;			/* 0040:0075 contents */
	u_int8_t    processorFamily;		/* Same as DPTSIG definition */
	u_int8_t    processorType;		/* Same as DPTSIG definition */
	u_int8_t    smartROMMajorVersion;
	u_int8_t    smartROMMinorVersion;	/* SmartROM version */
	u_int8_t    smartROMRevision;
	u_int16_t   flags;			/* See bit definitions above */
	u_int16_t   conventionalMemSize;	/* in KB */
	u_int32_t   extendedMemSize;		/* in KB */
	u_int32_t   osType;			/* Same as DPTSIG definition */
	u_int8_t    osMajorVersion;
	u_int8_t    osMinorVersion;		/* The OS version */
	u_int8_t    osRevision;
	u_int8_t    osSubRevision;
	u_int8_t    busType;			/* See defininitions above */
	u_int8_t    pad[3];			/* For alignment */
	dpt_drive_t drives[16];			/* SmartROM Logical Drives */
} dpt_sysinfo_t;

/* SEND_COMMAND packet structure */
typedef struct eata_ccb {
	u_int8_t SCSI_Reset   :1, /* Cause a SCSI Bus reset on the cmd */
		 HBA_Init     :1, /* Cause Controller to reinitialize */
		 Auto_Req_Sen :1, /* Do Auto Request Sense on errors */
		 scatter      :1, /* Data Ptr points to a SG Packet */
		 Quick	      :1, /* Set this one for NO Status PAcket */
		 Interpret    :1, /* Interpret the SCSI cdb for own use */
		 DataOut      :1, /* Data Out phase with command */
		 DataIn	      :1; /* Data In phase with command */

	u_int8_t reqlen;	  /* Request Sense Length, if Auto_Req_Sen=1 */
	u_int8_t unused[3];
	u_int8_t FWNEST  :1,	  /* send cmd to phys RAID component */
		 unused2 :7;

	u_int8_t Phsunit	:1, /* physical unit on mirrored pair */
		 I_AT		:1, /* inhibit address translation  */
		 Disable_Cache	:1, /* HBA inhibit caching */
				:5;

	u_int8_t cp_id		:5, /* SCSI Device ID of target */
		 cp_channel	:3; /* SCSI Channel # of HBA */

	u_int8_t cp_LUN		:5,
		 cp_luntar	:1, /* CP is for target ROUTINE */
		 cp_dispri	:1, /* Grant disconnect privilege */
		 cp_identify	:1; /* Always TRUE */

	u_int8_t cp_msg[3];	/* Message bytes 0-3 */

	union {
		struct {
			u_int8_t x_scsi_cmd; /* Partial SCSI CDB def */

			u_int8_t x_extent  :1,
				 x_bytchk  :1,
				 x_reladr  :1,
				 x_cmplst  :1,
				 x_fmtdata :1,
				 x_lun	   :3;

			u_int8_t x_page;
			u_int8_t reserved4;
			u_int8_t x_len;
			u_int8_t x_link	   :1;
			u_int8_t x_flag	   :1;
			u_int8_t reserved5 :4;
			u_int8_t x_vendor  :2;
		} x;
		u_int8_t z[12];	/* Command Descriptor Block (= 12) */
	} cp_w;

#define cp_cdb		cp_w.z
#define cp_scsi_cmd	cp_w.x.x_scsi_cmd
#define cp_extent      	cp_w.x.x_extent
#define cp_lun 		cp_w.x.x_lun
#define cp_page	       	cp_w.x.x_page 
#define cp_len	       	cp_w.x.x_len

#define MULTIFUNCTION_CMD	0x0e	/* SCSI Multi Function Cmd */
#define BUS_QUIET		0x04	/* Quite Scsi Bus Code     */
#define BUS_UNQUIET		0x05	/* Un Quiet Scsi Bus Code  */

	u_int32_t cp_datalen;	/*
				 * Data Transfer Length. If scatter=1 len (IN
				 * BYTES!) of the S/G array
				 */

	u_int32_t cp_busaddr;	/* Unique identifier.  Busaddr works well */
	u_int32_t cp_dataDMA;	/*
				 * Data Address, if scatter=1 then it is the
				 * address of scatter packet
				 */
	u_int32_t cp_statDMA;	/* address for Status Packet */
	u_int32_t cp_reqDMA;	/*
				 * Request Sense Address, used if CP command
				 * ends with error
				 */
	u_int8_t  CP_OpCode;
	
} eata_ccb_t;

/* 
 * DPT Signature Structure.
 * Used by /dev/dpt to directly pass commands to the HBA
 * We have more information here than we care for...
 */

/* Current Signature Version - sigBYTE dsSigVersion; */
#define SIG_VERSION 1

/* 
 * Processor Family - sigBYTE dsProcessorFamily;	DISTINCT VALUE 
 *
 * What type of processor the file is meant to run on.
 * This will let us know whether to read sigWORDs as high/low or low/high.
 */
#define PROC_INTEL	0x00	/* Intel 80x86 */
#define PROC_MOTOROLA	0x01	/* Motorola 68K */
#define PROC_MIPS4000	0x02	/* MIPS RISC 4000 */
#define PROC_ALPHA	0x03	/* DEC Alpha */

/* 
 * Specific Minimim Processor - sigBYTE dsProcessor; FLAG BITS 
 *
 * Different bit definitions dependent on processor_family
 */

/* PROC_INTEL: */
#define PROC_8086	0x01   	/* Intel 8086 */
#define PROC_286	0x02   	/* Intel 80286 */
#define PROC_386	0x04	/* Intel 80386 */
#define PROC_486	0x08	/* Intel 80486 */
#define PROC_PENTIUM	0x10	/* Intel 586 aka P5 aka Pentium */
#define PROC_P6		0x20	/* Intel 686 aka P6 */

/* PROC_MOTOROLA: */
#define PROC_68000	0x01   	/* Motorola 68000 */
#define PROC_68020	0x02   	/* Motorola 68020 */
#define PROC_68030	0x04   	/* Motorola 68030 */
#define PROC_68040	0x08	/* Motorola 68040 */

/* Filetype - sigBYTE dsFiletype; DISTINCT VALUES */
#define FT_EXECUTABLE	0      	/* Executable Program */
#define FT_SCRIPT	1      	/* Script/Batch File??? */
#define FT_HBADRVR	2     	/* HBA Driver */
#define FT_OTHERDRVR	3	/* Other Driver */
#define FT_IFS		4	/* Installable Filesystem Driver */
#define FT_ENGINE	5	/* DPT Engine */
#define FT_COMPDRVR	6	/* Compressed Driver Disk */
#define FT_LANGUAGE	7	/* Foreign Language file */
#define FT_FIRMWARE	8	/* Downloadable or actual Firmware */
#define FT_COMMMODL	9	/* Communications Module */
#define FT_INT13       	10    	/* INT 13 style HBA Driver */
#define FT_HELPFILE	11	/* Help file */
#define FT_LOGGER	12	/* Event Logger */
#define FT_INSTALL	13	/* An Install Program */
#define FT_LIBRARY	14	/* Storage Manager Real-Mode Calls */
#define FT_RESOURCE	15	/* Storage Manager Resource File */
#define FT_MODEM_DB	16	/* Storage Manager Modem Database */

/* Filetype flags - sigBYTE dsFiletypeFlags;		FLAG BITS */
#define FTF_DLL	       	0x01	/* Dynamic Link Library */
#define FTF_NLM		0x02	/* Netware Loadable Module */
#define FTF_OVERLAYS	0x04	/* Uses overlays */
#define FTF_DEBUG	0x08	/* Debug version */
#define FTF_TSR		0x10	/* TSR */
#define FTF_SYS		0x20	/* DOS Lodable driver */
#define FTF_PROTECTED	0x40	/* Runs in protected mode */
#define FTF_APP_SPEC	0x80	/* Application Specific */

/* OEM - sigBYTE dsOEM;	DISTINCT VALUES */
#define OEM_DPT		0	/* DPT */
#define OEM_ATT		1	/* ATT */
#define OEM_NEC		2	/* NEC */
#define OEM_ALPHA	3	/* Alphatronix */
#define OEM_AST		4	/* AST */
#define OEM_OLIVETTI	5	/* Olivetti */
#define OEM_SNI		6	/* Siemens/Nixdorf */

/* Operating System	- sigLONG dsOS;		FLAG BITS */
#define OS_DOS			0x00000001 /* PC/MS-DOS */
#define OS_WINDOWS		0x00000002 /* Microsoft Windows 3.x */
#define OS_WINDOWS_NT		0x00000004 /* Microsoft Windows NT */
#define OS_OS2M			0x00000008 /* OS/2 1.2.x,MS 1.3.0,IBM 1.3.x */
#define OS_OS2L			0x00000010 /* Microsoft OS/2 1.301 - LADDR */
#define OS_OS22x		0x00000020 /* IBM OS/2 2.x */
#define OS_NW286		0x00000040 /* Novell NetWare 286 */
#define OS_NW386		0x00000080 /* Novell NetWare 386 */
#define OS_GEN_UNIX		0x00000100 /* Generic Unix */
#define OS_SCO_UNIX		0x00000200 /* SCO Unix */
#define OS_ATT_UNIX		0x00000400 /* ATT Unix */
#define OS_UNIXWARE		0x00000800 /* UnixWare Unix */
#define OS_INT_UNIX		0x00001000 /* Interactive Unix */
#define OS_SOLARIS		0x00002000 /* SunSoft Solaris */
#define OS_QN			0x00004000 /* QNX for Tom Moch */
#define OS_NEXTSTEP		0x00008000 /* NeXTSTEP */
#define OS_BANYAN		0x00010000 /* Banyan Vines */
#define OS_OLIVETTI_UNIX	0x00020000 /* Olivetti Unix */
#define OS_FREEBSD     		0x00040000 /* FreeBSD 2.2 and later */
#define OS_OTHER		0x80000000 /* Other */

/* Capabilities - sigWORD dsCapabilities; FLAG BITS */
#define CAP_RAID0	0x0001	/* RAID-0 */
#define CAP_RAID1	0x0002	/* RAID-1 */
#define CAP_RAID3	0x0004	/* RAID-3 */
#define CAP_RAID5	0x0008	/* RAID-5 */
#define CAP_SPAN	0x0010	/* Spanning */
#define CAP_PASS	0x0020	/* Provides passthrough */
#define CAP_OVERLAP	0x0040	/* Passthrough supports overlapped commands */
#define CAP_ASPI	0x0080	/* Supports ASPI Command Requests */
#define CAP_ABOVE16MB	0x0100	/* ISA Driver supports greater than 16MB */
#define CAP_EXTEND	0x8000	/* Extended info appears after description */

/* Devices Supported - sigWORD dsDeviceSupp;		FLAG BITS */
#define DEV_DASD	0x0001	/* DASD (hard drives) */
#define DEV_TAPE	0x0002	/* Tape drives */
#define DEV_PRINTER	0x0004	/* Printers */
#define DEV_PROC	0x0008	/* Processors */
#define DEV_WORM	0x0010	/* WORM drives */
#define DEV_CDROM	0x0020	/* CD-ROM drives */
#define DEV_SCANNER	0x0040	/* Scanners */
#define DEV_OPTICAL	0x0080	/* Optical Drives */
#define DEV_JUKEBOX	0x0100	/* Jukebox */
#define DEV_COMM	0x0200	/* Communications Devices */
#define DEV_OTHER	0x0400	/* Other Devices */
#define DEV_ALL		0xFFFF	/* All SCSI Devices */

/* Adapters Families Supported - sigWORD dsAdapterSupp; FLAG BITS */
#define ADF_2001	0x0001	/* PM2001 */
#define ADF_2012A	0x0002	/* PM2012A */
#define ADF_PLUS_ISA	0x0004	/* PM2011,PM2021 */
#define ADF_PLUS_EISA	0x0008	/* PM2012B,PM2022 */
#define ADF_SC3_ISA	0x0010	/* PM2021 */
#define ADF_SC3_EISA	0x0020	/* PM2022,PM2122, etc */
#define ADF_SC3_PCI	0x0040	/* SmartCache III PCI */
#define ADF_SC4_ISA	0x0080	/* SmartCache IV ISA */
#define ADF_SC4_EISA	0x0100	/* SmartCache IV EISA */
#define ADF_SC4_PCI	0x0200	/* SmartCache IV PCI */
#define ADF_ALL_MASTER	0xFFFE	/* All bus mastering */
#define ADF_ALL_CACHE	0xFFFC	/* All caching */
#define ADF_ALL		0xFFFF	/* ALL DPT adapters */

/* Application - sigWORD dsApplication;				FLAG BITS */
#define APP_DPTMGR	0x0001	/* DPT Storage Manager */
#define APP_ENGINE	0x0002	/* DPT Engine */
#define APP_SYTOS	0x0004	/* Sytron Sytos Plus */
#define APP_CHEYENNE	0x0008	/* Cheyenne ARCServe + ARCSolo */
#define APP_MSCDEX	0x0010	/* Microsoft CD-ROM extensions */
#define APP_NOVABACK	0x0020	/* NovaStor Novaback */
#define APP_AIM		0x0040	/* Archive Information Manager */

/* Requirements - sigBYTE dsRequirements;	FLAG BITS */
#define REQ_SMARTROM	0x01   	/* Requires SmartROM to be present */
#define REQ_DPTDDL	0x02   	/* Requires DPTDDL.SYS to be loaded */
#define REQ_HBA_DRIVER	0x04   	/* Requires an HBA driver to be loaded	*/
#define REQ_ASPI_TRAN	0x08   	/* Requires an ASPI Transport Modules	*/
#define REQ_ENGINE	0x10   	/* Requires a DPT Engine to be loaded	*/
#define REQ_COMM_ENG	0x20	/* Requires a DPT Communications Engine */

typedef struct dpt_sig {
	char	  dsSignature[6];  /* ALWAYS "dPtSiG" */
	u_int8_t  SigVersion;	   /* signature version (currently 1) */
	u_int8_t  ProcessorFamily; /* what type of processor */
	u_int8_t  Processor;	   /* precise processor */
	u_int8_t  Filetype;	   /* type of file */
	u_int8_t  FiletypeFlags;   /* flags to specify load type, etc. */
	u_int8_t  OEM;		   /* OEM file was created for */
	u_int32_t OS;		   /* which Operating systems */
	u_int16_t Capabilities;	   /* RAID levels, etc. */
	u_int16_t DeviceSupp;	   /* Types of SCSI devices supported */
	u_int16_t AdapterSupp;	   /* DPT adapter families supported */
	u_int16_t Application;	   /* applications file is for */
	u_int8_t  Requirements;	   /* Other driver dependencies */
	u_int8_t  Version;	   /* 1 */
	u_int8_t  Revision;	   /* 'J' */
	u_int8_t  SubRevision;	   /* '9', ' ' if N/A */
	u_int8_t  Month;	   /* creation month */
	u_int8_t  Day;		   /* creation day */
	u_int8_t  Year;		   /* creation year since 1980  */
	char	 *Description;	   /* description (NULL terminated) */
} dpt_sig_t;

/* 32 bytes minimum - with no description. Put NULL at description[0] */
/* 81 bytes maximum - with 49 character description plus NULL. */

/* This line added at Roycroft's request */
/* Microsoft's NT compiler gets confused if you do a pack and don't */
/* restore it. */
typedef struct eata_pass_through {
	u_int8_t    eataID[4];
	u_int32_t   command;

#define EATAUSRCMD	(('D'<<8)|65)  	/* EATA PassThrough Command	*/
#define DPT_SIGNATURE	(('D'<<8)|67)  	/* Get Signature Structure */
#define DPT_NUMCTRLS   	(('D'<<8)|68)	/* Get Number Of DPT Adapters */
#define DPT_CTRLINFO   	(('D'<<8)|69)  	/* Get Adapter Info Structure */ 
#define DPT_SYSINFO    	(('D'<<8)|72)  	/* Get System Info Structure	*/
#define DPT_BLINKLED   	(('D'<<8)|75)	/* Get The BlinkLED Status */

	u_int8_t   *command_buffer;
	eata_ccb_t  command_packet;
	u_int32_t   timeout;
	u_int8_t    host_status;
	u_int8_t    target_status;
	u_int8_t    retries;
} eata_pt_t;

typedef enum {
	DCCB_FREE		= 0x00,
	DCCB_ACTIVE		= 0x01,
	DCCB_RELEASE_SIMQ	= 0x02
} dccb_state;

typedef struct dpt_ccb {
	eata_ccb_t	 eata_ccb;
	bus_dmamap_t	 dmamap;
	struct callout	 timer;
	dpt_sg_t	*sg_list;
	u_int32_t	 sg_busaddr;
	dccb_state	 state;
	union		 ccb *ccb;
	struct		 scsi_sense_data sense_data;
	u_int8_t	 tag;
	u_int8_t	 retries;
	u_int8_t	 status; /* status of this queueslot */
	u_int8_t	*cmd;	 /* address of cmd */

	u_int32_t	 transaction_id;
	u_int32_t	 result;
	caddr_t		 data;
	SLIST_ENTRY(dpt_ccb) links;

#ifdef DPT_MEASURE_PERFORMANCE
	u_int32_t	 submitted_time;
	struct		 timeval command_started;
	struct		 timeval command_ended;
#endif
} dpt_ccb_t;

/*
 * This is provided for compatibility with UnixWare only.
 * Some of the fields may be bogus.
 * Others may have a totally different meaning.
 */
typedef struct dpt_scsi_ha {
    u_int32_t	 ha_state;		/* Operational state */
    u_int8_t	 ha_id[MAX_CHANNELS];	/* Host adapter SCSI ids */
    int32_t	 ha_base;		/* Base I/O address */
    int		 ha_max_jobs;		/* Max number of Active Jobs */
    int		 ha_cache:2;		/* Cache parameters */
    int		 ha_cachesize:30;	/* In meg, only if cache present*/
    int		 ha_nbus;		/* Number Of Busses on HBA */
    int		 ha_ntargets;		/* Number Of Targets Supported */
    int		 ha_nluns;		/* Number Of LUNs Supported */
    int		 ha_tshift;		/* Shift value for target */
    int		 ha_bshift;		/* Shift value for bus */
    int		 ha_npend;		/* # of jobs sent to HBA */
    int		 ha_active_jobs;	/* Number Of Active Jobs */
    char	 ha_fw_version[4];	/* Firmware Revision Level */
    void	*ha_ccb;		/* Controller command blocks */
    void	*ha_cblist;		/* Command block free list */
    void	*ha_dev;		/* Logical unit queues */
    void	*ha_StPkt_lock;		/* Status Packet Lock */
    void	*ha_ccb_lock;		/* CCB Lock */
    void	*ha_LuQWaiting;		/* Lu Queue Waiting List */
    void	*ha_QWait_lock;		/* Device Que Waiting Lock */
    int		 ha_QWait_opri;		/* Saved Priority Level */
#ifdef DPT_TARGET_MODE
    dpt_ccb_t	*target_ccb[MAX_CHANNELS]; /* Command block waiting writebuf */
#endif
} dpt_compat_ha_t;

/*
 * Describe the Inquiry Data returned on Page 0 from the Adapter. The
 * Page C1 Inquiry Data is described in the DptConfig_t structure above.
 */
typedef struct {
    u_int8_t	deviceType;
    u_int8_t	rm_dtq;
    u_int8_t	otherData[6];
    u_int8_t	vendor[8];
    u_int8_t	modelNum[16];
    u_int8_t	firmware[4];
    u_int8_t	protocol[4];
} dpt_inq_t;

/*
 * sp_EOC is not `safe', so I will check sp_Messages[0] instead!
 */
#define DptStat_BUSY(x)	 ((x)->sp_ID_Message)
#define DptStat_Reset_BUSY(x)			\
 ((x)->msg[0] = 0xA5, (x)->EOC = 0,		\
  (x)->ccb_busaddr = ~0)

#ifdef DPT_MEASURE_PERFORMANCE
#define BIG_ENOUGH	0x8fffffff	
typedef struct dpt_metrics {
	u_int32_t command_count[256]; /* We assume MAX 256 SCSI commands */
	u_int32_t max_command_time[256];
	u_int32_t min_command_time[256];

	u_int32_t min_intr_time;
	u_int32_t max_intr_time;
	u_int32_t aborted_interrupts;
	u_int32_t spurious_interrupts;

	u_int32_t max_waiting_count;
	u_int32_t max_submit_count;
	u_int32_t max_complete_count;
    
	u_int32_t min_waiting_time;
	u_int32_t min_submit_time;
	u_int32_t min_complete_time;
    
	u_int32_t max_waiting_time; 
	u_int32_t max_submit_time;
	u_int32_t max_complete_time;
    
	u_int32_t command_collisions;
	u_int32_t command_too_busy;
	u_int32_t max_eata_tries;
	u_int32_t min_eata_tries;

	u_int32_t read_by_size_count[10];
	u_int32_t write_by_size_count[10];
	u_int32_t read_by_size_min_time[10];
	u_int32_t read_by_size_max_time[10];
	u_int32_t write_by_size_min_time[10];
	u_int32_t write_by_size_max_time[10];

#define SIZE_512	0
#define SIZE_1K		1
#define SIZE_2K		2
#define SIZE_4K		3
#define SIZE_8K		4
#define SIZE_16K	5
#define SIZE_32K	6
#define SIZE_64K	7
#define SIZE_BIGGER	8
#define SIZE_OTHER	9

	struct	  timeval intr_started;

	u_int32_t warm_starts;
	u_int32_t cold_boots;
} dpt_perf_t;
#endif

struct sg_map_node {
	bus_dmamap_t		 sg_dmamap;
	bus_addr_t		 sg_physaddr;
	dpt_sg_t*		 sg_vaddr;
	SLIST_ENTRY(sg_map_node) links;
};

/* Main state machine and interface structure */
typedef struct dpt_softc {
	device_t		dev;
	struct mtx		lock;

	struct resource *	io_res;
	int			io_rid;
	int			io_type;
	int			io_offset;

	struct resource *	irq_res;
	int			irq_rid;
	void *			ih;

	struct resource *	drq_res;
	int			drq_rid;

	bus_dma_tag_t	   buffer_dmat;		/* dmat for buffer I/O */
	dpt_ccb_t	  *dpt_dccbs;		/* Array of dpt ccbs */
	bus_addr_t	   dpt_ccb_busbase;	/* phys base address of array */
	bus_addr_t	   dpt_ccb_busend;	/* phys end address of array */

	u_int32_t handle_interrupts   :1, /* Are we ready for real work? */
		  target_mode_enabled :1,
		  resource_shortage   :1,
		  cache_type	      :2,
		  spare		      :28;

	int	  total_dccbs;
	int	  free_dccbs;
	int	  pending_ccbs;
	int	  completed_ccbs;

	SLIST_HEAD(, dpt_ccb)	 free_dccb_list;
	LIST_HEAD(, ccb_hdr)     pending_ccb_list;

	bus_dma_tag_t		  parent_dmat;
	bus_dma_tag_t		  dccb_dmat;	/* dmat for our ccb array */
	bus_dmamap_t		  dccb_dmamap;
	bus_dma_tag_t		  sg_dmat;	/* dmat for our sg maps */
	SLIST_HEAD(, sg_map_node) sg_maps;

	struct cam_sim		  *sims[MAX_CHANNELS];
	struct cam_path		  *paths[MAX_CHANNELS];
	u_int32_t commands_processed;
	u_int32_t lost_interrupts;

	/*
	 * These three parameters can be used to allow for wide scsi, and
	 * for host adapters that support multiple busses. The first two
	 * should be set to 1 more than the actual max id or lun (i.e. 8 for
	 * normal systems).
	 *
	 * There is a FAT assumption here;  We assume that these will never 
	 * exceed MAX_CHANNELS, MAX_TARGETS, MAX_LUNS
	 */
	u_int	  channels;	/* # of avail scsi chan. */
	u_int32_t max_id;
	u_int32_t max_lun;

	u_int8_t  irq;
	u_int8_t  dma_channel;

	TAILQ_ENTRY(dpt_softc) links;
	int	  init_level;

	/*
	 * Every object on a unit can have a receiver, if it treats
	 * us as a target.  We do that so that separate and independent
	 * clients can consume received buffers.
	 */

#define DPT_RW_BUFFER_SIZE	(8 * 1024)
	dpt_ccb_t	*target_ccb[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS];
	u_int8_t	*rw_buffer[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS];
	dpt_rec_buff	 buffer_receiver[MAX_CHANNELS][MAX_TARGETS][MAX_LUNS];
	
	dpt_inq_t	 board_data;
	u_int8_t	 EATA_revision;
	u_int8_t	 bustype;	/* bustype of HBA	 */
	u_int32_t	 state;		/* state of HBA		 */

#define DPT_HA_FREE	       	0x00000000
#define DPT_HA_OK	       	0x00000000
#define DPT_HA_NO_TIMEOUT      	0x00000000
#define DPT_HA_BUSY	       	0x00000001
#define DPT_HA_TIMEOUT	       	0x00000002
#define DPT_HA_RESET	       	0x00000004
#define DPT_HA_LOCKED	       	0x00000008
#define DPT_HA_ABORTED	       	0x00000010
#define DPT_HA_CONTROL_ACTIVE  	0x00000020
#define DPT_HA_SHUTDOWN_ACTIVE  0x00000040
#define DPT_HA_COMMAND_ACTIVE  	0x00000080
#define DPT_HA_QUIET            0x00000100

	u_int8_t  primary;	/* true if primary */	

	u_int8_t  more_support		:1,	/* HBA supports MORE flag */
		  immediate_support	:1,	/* HBA supports IMMEDIATE */
		  broken_INQUIRY	:1,	/* EISA HBA w/broken INQUIRY */
		  spare2		:5;

	u_int8_t  resetlevel[MAX_CHANNELS];
	u_int32_t last_ccb;	/* Last used ccb */
	u_int32_t cplen;		/* size of CP in words */
	u_int16_t cppadlen;	/* pad length of cp */
	u_int16_t max_dccbs;
	u_int16_t sgsize;		/* Entries in the SG list */
	u_int8_t  hostid[MAX_CHANNELS];	/* SCSI ID of HBA */
	u_int32_t cache_size;

	volatile   dpt_sp_t *sp;		/* status packet */
	/* Copied from the status packet during interrupt handler */
	u_int8_t   hba_stat;
	u_int8_t   scsi_stat;	/* Target SCSI status */
	u_int32_t  residue_len;	/* Number of bytes not transferred */
	bus_addr_t sp_physaddr;		/* phys address of status packet */

	/*
	 * We put ALL conditional elements at the tail for the structure.
	 * If we do not, then userland code will crash or trash based on which
	 * kernel it is running with.
	 * This isi most visible with usr/sbin/dpt_softc(8)
	 */

#ifdef DPT_MEASURE_PERFORMANCE
	dpt_perf_t performance;
#endif

#ifdef DPT_RESET_HBA
	struct timeval last_contact;
#endif
} dpt_softc_t;

/*
 * This structure is used to pass dpt_softc contents to userland via the 
 * ioctl DPT_IOCTL_SOFTC.  The reason for this maddness, is that FreeBSD
 * (all BSDs ?) chose to actually assign a nasty meaning to the IOCTL word,
 * encoding 13 bits of it as size.  As dpt_softc_t is somewhere between
 * 8,594 and 8,600 (depends on options), we have to copy the data to
 * something less than 4KB long. This siliness also solves the problem of
 * varying definition of dpt_softc_t, As the variants are exluded from
 * dpt_user_softc.
 *
 * See dpt_softc_t above for enumerations, comments and such.
 */
typedef struct dpt_user_softc {
	int	  unit;
	u_int32_t handle_interrupts   :1, /* Are we ready for real work? */
		  target_mode_enabled :1,
		  spare		      :30;

	int	  total_ccbs_count;
	int	  free_ccbs_count;
	int	  waiting_ccbs_count; 
	int	  submitted_ccbs_count;
	int	  completed_ccbs_count;

	u_int32_t queue_status;
	u_int32_t free_lock;
	u_int32_t waiting_lock;
	u_int32_t submitted_lock; 
	u_int32_t completed_lock;

	u_int32_t commands_processed;
	u_int32_t lost_interrupts;

	u_int8_t  channels;
	u_int32_t max_id;
	u_int32_t max_lun;

	u_int16_t io_base; 
	u_int8_t *v_membase;
	u_int8_t *p_membase;

	u_int8_t  irq;
	u_int8_t  dma_channel;

	dpt_inq_t board_data;
	u_int8_t  EATA_revision;
	u_int8_t  bustype;
	u_int32_t state;

	u_int8_t  primary;
	u_int8_t  more_support 	    :1,
		  immediate_support :1,
		  broken_INQUIRY    :1,
		  spare2	    :5;

	u_int8_t  resetlevel[MAX_CHANNELS];
	u_int32_t last_ccb;
	u_int32_t cplen;
	u_int16_t cppadlen;
	u_int16_t queuesize;
	u_int16_t sgsize;
	u_int8_t  hostid[MAX_CHANNELS];
	u_int32_t cache_type :2,
		  cache_size :30;
} dpt_user_softc_t;

/*
 * Externals:
 * These all come from dpt_scsi.c
 *
 */
#ifdef _KERNEL
/* This function gets the current hi-res time and returns it to the caller */
static __inline struct timeval
dpt_time_now(void)
{
	struct timeval now;

	microtime(&now);
	return(now);
}

/*
 * Given a minor device number, get its SCSI Unit.
 */
static __inline int
dpt_minor2unit(int minor)
{
	return(minor2hba(minor));
}

dpt_softc_t *dpt_minor2softc(int minor_no);

#endif /* _KERNEL */

/*
 * This function subtracts one timval structure from another,
 * Returning the result in usec.
 * It assumes that less than 4 billion usecs passed form start to end.
 * If times are sensless, ~0 is returned.
 */
static __inline u_int32_t
dpt_time_delta(struct timeval start,
	       struct timeval end)
{
    if (start.tv_sec > end.tv_sec)
	return(~0);

    if ( (start.tv_sec == end.tv_sec) && (start.tv_usec > end.tv_usec) )
	return(~0);
	
    return ( (end.tv_sec - start.tv_sec) * 1000000 +
	     (end.tv_usec - start.tv_usec) );
}

extern devclass_t	dpt_devclass;

#ifdef _KERNEL
void			dpt_alloc(device_t);
int			dpt_detach(device_t);
int			dpt_alloc_resources(device_t);
void			dpt_release_resources(device_t);
#endif
void			dpt_free(struct dpt_softc *dpt);
int			dpt_init(struct dpt_softc *dpt);
int			dpt_attach(dpt_softc_t * dpt);
void			dpt_intr(void *arg);

#ifdef DEV_EISA
dpt_conf_t *		dpt_pio_get_conf(u_int32_t);
#endif

#if 0
extern void		hex_dump(u_char * data, int length,
				 char *name, int no);
extern char		*i2bin(unsigned int no, int length);
extern char		*scsi_cmd_name(u_int8_t cmd);

extern dpt_conf_t	*dpt_get_conf(dpt_softc_t *dpt, u_int8_t page,
				      u_int8_t target, u_int8_t size,
				      int extent);

extern int		dpt_setup(dpt_softc_t * dpt, dpt_conf_t * conf);
extern int		dpt_attach(dpt_softc_t * dpt);
extern void		dpt_shutdown(int howto, dpt_softc_t *dpt);
extern void		dpt_detect_cache(dpt_softc_t *dpt);

extern int		dpt_user_cmd(dpt_softc_t *dpt, eata_pt_t *user_cmd,
				     caddr_t cmdarg, int minor_no);

extern u_int8_t	dpt_blinking_led(dpt_softc_t *dpt);

extern dpt_rb_t	dpt_register_buffer(int unit, u_int8_t channel, u_int8_t target,
				    u_int8_t lun, u_int8_t mode,
				    u_int16_t length, u_int16_t offset, 
				    dpt_rec_buff callback, dpt_rb_op_t op);

extern int	dpt_send_buffer(int unit, u_int8_t channel, u_int8_t target,
				u_int8_t lun, u_int8_t mode, u_int16_t length,
				u_int16_t offset, void *data,
				buff_wr_done callback);



void dpt_reset_performance(dpt_softc_t *dpt);
#endif

#endif /* _DPT_H */
OpenPOWER on IntegriCloud