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
|
/*
* 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.
*
*/
/*
*
* 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.
*/
#ident "$FreeBSD$"
#ifndef _DPT_H
#define _DPT_H
#include <sys/ioccom.h>
#define DPT_CDEV_MAJOR 88
#undef DPT_USE_DLM_SWI
extern u_long dpt_unit;
#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 {
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
} dpt_immediate_cmd;
#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 {
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 */
} dpt_message;
#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) (¶m[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;
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 compatability 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 {
bus_space_tag_t tag;
bus_space_handle_t bsh;
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 unit;
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 independant
* 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
#ifdef DPT_LOST_IRQ
#define DPT_LOST_IRQ_SET 0x10000000
#define DPT_LOST_IRQ_ACTIVE 0x20000000
#endif
#ifdef DPT_HANDLE_TIMEOUTS
#define DPT_HA_TIMEOUTS_SET 0x40000000
#define DPT_HA_TIMEOUTS_ACTIVE 0x80000000
#endif
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 substracts 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 TAILQ_HEAD(dpt_softc_list, dpt_softc) dpt_softcs;
extern int dpt_controllers_present;
struct dpt_softc* dpt_alloc(u_int unit, bus_space_tag_t tag,
bus_space_handle_t bsh);
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);
dpt_conf_t * dpt_pio_get_conf(u_int32_t);
#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 */
|