aboutsummaryrefslogtreecommitdiff
path: root/w9x/inc/ios.h
blob: 59214d8d90fe8f834e405b534cfe46ee3b49af1f (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
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
#ifndef IOS_H
#define IOS_H

/** This is a big mess of IOS structs and functions.
 *  They come from the storage.doc / FAQ.
 *  There are also some VxDCall wrappers, manually generated.
 */

#include <stddef.h>
#include <stdint.h>
#include "sassert.h"

typedef void __cdecl (*IO_callback)(struct IOP *iop);

// IOS ================

#define IOS_DEVICE_ID 0x10

static inline uint32_t IOS_Get_Version(void);
#pragma aux IOS_Get_Version = \
	"int 0x20" \
	"dd ( 0x10 shl 16 ) + 0" \
	"jnc ok" \
	"xor eax, eax" \
	"ok:" \
	__parm __caller [] __value [eax] __modify [ecx edx]

static inline void IOS_Register(const struct DRP *drp);
#pragma aux IOS_Register = \
	"int 0x20" \
	"dd ( 0x10 shl 16 ) + 7" \
	__parm __caller [] __modify [eax ecx edx]

// AEP ================

typedef _Packed struct AEPHDR {
    uint16_t AEP_func;       // function; see below
    uint16_t AEP_result;     // result; set to zero if successful; see below
    uint32_t AEP_ddb;        // address of DDB
    uint8_t  AEP_lgn;        // current load group number (from DVT)
    uint8_t  AEP_align[3];   // reserved; don't use
} AEPHDR, *PAEPHDR;

typedef _Packed struct AEP_bi_init {
	AEPHDR    AEP_bi_i_hdr;
	uint32_t  AEP_bi_reference_data;  // optional value passed in from DRP
    uint8_t   AEP_bi_flags;           // flags; see below
    uint8_t   AEP_bi_i_max_target;    // max scsi target id
    uint8_t   AEP_bi_i_max_lun;       // max scsi lun
    uint32_t  AEP_bi_i_dcb;           // init DCB for port drivers
    void*     AEP_bi_i_hdevnode;      // handle to devnode for this adapter
    void*     AEP_bi_i_regkey;        // registry key for this adapter
    uint8_t   AEP_bi_i_align[1];      // reserved; don't use
} AEP_bi_init, *PAEP_bi_init;

typedef _Packed struct AEP_boot_done {
	AEPHDR    AEP_bi_i_hdr;
} AEP_boot_done, *PAEP_boot_done;

typedef _Packed struct AEP_dcb_config {
    struct AEPHDR  AEP_d_c_hdr;
    struct DCB *AEP_d_c_dcb;          // 32-bit ptr to DCB
} AEP_dcb_config, *PAEP_dcb_config;

typedef _Packed struct AEP_dcb_unconfig {
    struct AEPHDR  AEP_d_u_hdr;
    struct DCB *AEP_d_u_dcb;          // 32-bit ptr to DCB
} AEP_dcb_unconfig, *PAEP_dcb_unconfig;

typedef _Packed struct AEP_iop_timeout_occurred {
    struct AEPHDR  AEP_i_t_o_hdr;
    struct IOP *AEP_i_t_o_iop;          // address of IOP that timed out
} AEP_iop_timeout_occurred, *PAEP_iop_timeout_occurred;

typedef _Packed struct AEP_inquiry_device {
    struct AEPHDR  AEP_i_d_hdr;
    uint32_t  AEP_i_d_dcb;          // address of DCB
} AEP_inquiry_device, *PAEP_inquiry_device;

typedef _Packed struct AEP_bi_uninit {
    struct AEPHDR  AEP_bi_u_hdr;
} AEP_bi_uninit, *PAEP_bi_uninit;

typedef struct AEP_dcb_unconfig_pend {
    struct AEPHDR  AEP_d_u_p_hdr;
    struct DCB *AEP_d_u_p_dcb;        // 32-bit ptr to DCB
} AEP_dcb_unconfig_pend, *PAEP_dcb_unconfig_pend;

typedef _Packed union AEP {
	struct AEPHDR;
	struct AEP_bi_init bi_i;
	struct AEP_boot_done b_d;
	struct AEP_dcb_config d_c;
	struct AEP_dcb_unconfig d_u;
	struct AEP_iop_timeout_occurred i_t_o;
	struct AEP_inquiry_device i_d;
	struct AEP_bi_uninit bi_u;
	struct AEP_dcb_unconfig_pend d_u_p;
} AEP, *PAEP;

typedef enum AEP_result {
	AEP_SUCCESS = 0,
	AEP_FAILURE = -1,

	AEP_NO_INQ_DATA = 1,
	AEP_NO_MORE_DEVICES = 2
} AEP_result;

enum AEP_funcs {
	/** initializes driver/interface */
	AEP_INITIALIZE = 0,
	/** indicates system critical shutdown */
	AEP_SYSTEM_CRIT_SHUTDOWN = 1,
	/** booting done - switch to run time */
	AEP_BOOT_COMPLETE = 2,
	/* configure device */
	AEP_CONFIG_DCB = 3,
	/* unconfigure device */
	AEP_UNCONFIG_DCB = 4,
	/* iop timeout occured */
	AEP_IOP_TIMEOUT = 5,
	/* get device indentification data  */
	AEP_DEVICE_INQUIRY = 6,
	/* 1/2 second interval notification */
	AEP_HALF_SEC = 7,
	/* one second interval notification */
	AEP_1_SEC = 8,
	/* two second interval notification */
	AEP_2_SECS = 9,
	/* four second interval notification*/
	AEP_4_SECS = 10,
	/* parameters for '.I' debug command*/
	AEP_DBG_DOT_CMD = 11,
	/* associate logical DCBs w/ physical */
	AEP_ASSOCIATE_DCB = 12,
	/* IFSMGR about to hook in */
	AEP_REAL_MODE_HANDOFF = 13,
	/* indicates system shutdown */
	AEP_SYSTEM_SHUTDOWN = 14,
	/* uninitialize driver/interface */
	AEP_UNINITIALIZE = 15,
	/* logical dcb is going to be locked */
	AEP_DCB_LOCK = 16,
	/* notify drivers of volume mount */
	AEP_MOUNT_NOTIFY = 17,
	/* notify drivers of VRP creation */
	AEP_CREATE_VRP = 18,
	/* notify drivers of VRP destruction */
	AEP_DESTROY_VRP = 19,
	/* tell drivers to refresh drive data */
	AEP_REFRESH_DRIVE = 20,
	/** tell drivers that DCB removal is pending */
	AEP_PEND_UNCONFIG_DCB = 21,
	/**  notify int13 of a possible change in the int 1eh vector for copy protection */
	AEP_1E_VEC_UPDATE = 22,
	/** inform driver vsd to change the floppy spindle speed */
	AEP_CHANGE_RPM = 23,
};

// BlockDev ===========

typedef struct BlockDev_Scatter_Gather{
    uint32_t BD_SG_Count;		// Block count; else byte count if IORF_CHAR_COMMAND set
    void*    BD_SG_Buffer_Ptr;
}  _BlockDev_Scatter_Gather;

enum BDD_FLAGS {
	BDF_Int13_Drive = 0x01,
	BDF_Int13_Drive_Bit = 0,

	BDF_Writeable = 0x02,
	BDF_Writeable_Bit = 1,

	BDF_Removable = 0x04,
	BDF_Removable_Bit = 2,

	BDF_Remote = 0x08,
	BDF_Remote_Bit = 3,

	BDF_Serial_Cmd = 0x10,
	BDF_Serial_Cmd_Bit = 4,

	BDF_Cache = 0x20,
	BDF_Cache_Bit = 5,
};

// DCB ================

typedef _Packed struct  _DCB_COMMON {
	uint32_t  DCB_physical_dcb;        // DCB for physical device
	uint32_t  DCB_expansion_length;    // expansion length; see below
	struct DCB_cd_entry *DCB_ptr_cd;   // address of calldown list
	uint32_t  DCB_next_dcb;            // link to next DCB
	uint32_t  DCB_next_logical_dcb;    // address of next logical dcb
	uint8_t   DCB_drive_lttr_equiv;    // drive number; see below
	uint8_t   DCB_unit_number;         // drive or unit #; see below
	uint16_t  DCB_TSD_Flags;           // TSD flags; see below

	// Volume Tracking
	uint32_t  DCB_vrp_ptr;             // address of VRP for this DCB
	uint32_t  DCB_dmd_flags;           // demand bits; see below
	uint32_t  DCB_device_flags;        // general purpose flags; see DCB_DEV_FLAGS
	uint32_t  DCB_device_flags2;       // general purpose flags; see DCB_DEV_FLAGS2
	uint32_t  DCB_Partition_Start;     // partition start sector
	uint32_t  DCB_track_table_ptr;     // address of track table buffer
	//  for ioctls
	uint32_t  DCB_bds_ptr;             // DOS BDS corresp. to this DCB
	//  (logical DCB's only)
	uint32_t  DCB_Reserved1;           // reserved; must be zero
	uint32_t  DCB_Reserved2;           // reserved; must be zero
	uint8_t   DCB_apparent_blk_shift;  // log of apparent_blk_size
	uint8_t   DCB_partition_type;      // partition type
	uint16_t  DCB_sig;                 // padding and signature
	uint8_t   DCB_device_type;         // device type; see below
	uint32_t  DCB_Exclusive_VM;        // exclusive access handle
	uint8_t   DCB_disk_bpb_flags;      // BPB flags; see below
	uint8_t   DCB_cAssoc;              // # of assoc. logical drives
	uint8_t   DCB_Sstor_Host;          // indicates a sstor host volume
	uint16_t  DCB_user_drvlet;         // userdriveletter settings or 0xff
	uint16_t  DCB_Reserved3;           // reserved; must be zero
	uint32_t  DCB_Reserved4;           // reserved; must be zero
} DCB_COMMON, *PDCB_COMMON;

typedef _Packed struct  _DCB_BLOCKDEV {
	uint32_t  DCB_BDD_Next;
	uint8_t   DCB_BDD_BD_Major_Version;    // INIT <BDD_BD_Major_Ver>
	uint8_t   DCB_BDD_BD_Minor_Version;    // INIT <BDD_BD_Minor_Ver>
	uint8_t   DCB_BDD_Device_SubType;
	uint8_t   DCB_BDD_Int_13h_Number;
	uint32_t  DCB_BDD_flags;               // was BDD_Flags
	char *    DCB_BDD_Name_Ptr;

	// Apparent geometry as seen by TSD and above
	uint64_t  DCB_apparent_sector_cnt;     // # of sectors
	uint32_t  DCB_apparent_blk_size;       // blk size of device
	uint32_t  DCB_apparent_head_cnt;       // # of heads
	uint32_t  DCB_apparent_cyl_cnt;        // # of cylinders
	uint32_t  DCB_apparent_spt;            // # of secs/trk

	uint32_t  DCB_BDD_Sync_Cmd_Proc;
	uint32_t  DCB_BDD_Command_Proc;
	uint32_t  DCB_BDD_Hw_Int_Proc;         // INIT <0>
	uint32_t  DCB_BDP_Cmd_Queue_Ascending;
	uint32_t  DCB_BDP_Cmd_Queue_Descending;
	uint32_t  DCB_BDP_Current_Flags;
	uint32_t  DCB_BDP_Int13_Param_Ptr;
	uint32_t  DCB_BDP_Current_Command;
	uint32_t  DCB_BDP_Current_Position[2];
	uint32_t  DCB_BDP_Reserved[5];
	uint32_t  DCB_fastdisk_bdd;            // set for DCBs created when a
	                                       // fastdisk regs with the
	                                       // blockdev BDD for it. Else 0.
} DCB_BLOCKDEV, *PDCB_BLOCKDEV;


typedef _Packed struct DCB {
	DCB_COMMON  DCB_cmn;              // common information
	uint32_t  DCB_max_xfer_len;          // maximum transfer length

	// Actual geometry data (as seen below the TSD)
	uint64_t  DCB_actual_sector_cnt;     // number of sectors
	uint32_t  DCB_actual_blk_size;       // actual block size of the device
	uint32_t  DCB_actual_head_cnt;       // number of heads
	uint32_t  DCB_actual_cyl_cnt;        // number of cylinders
	uint32_t  DCB_actual_spt;            // number of sectors per track

	void*     DCB_next_ddb_dcb;          // link to next DCB on DDB chain
	void*     DCB_dev_node;              // address of dev node for device
	uint8_t   DCB_bus_type;              // Bus type; see below
	uint8_t   DCB_bus_number;            // channel (cable) within adapter
	uint8_t   DCB_queue_freeze;          // queue freeze depth counter
	uint8_t   DCB_max_sg_elements;       // max # s/g elements; see below

	// Volume tracking layer use only
	uint8_t   DCB_io_pend_count;         // # of pending requests for DCB
	uint8_t   DCB_lock_count;            // # of LOCK MEDIA commands

	// SCSI
	uint16_t  DCB_SCSI_VSD_FLAGS;        // Flags for SRB builder
	uint8_t   DCB_scsi_target_id;        // SCSI target ID
	uint8_t   DCB_scsi_lun;              // SCSI logical unit number
	uint8_t   DCB_scsi_hba;              // prot-driver-relative adapter #
	uint8_t   DCB_max_sense_data_len;    // Maximum sense length
	uint16_t  DCB_srb_ext_size;          // miniport srb extension length

	uint8_t   DCB_inquiry_flags[8];      // Device inquiry flags
	char      DCB_vendor_id[8];          // Vendor ID string
	char      DCB_product_id[16];        // Product ID string
	char      DCB_rev_level[4];          // Product revision level
	char      DCB_port_name[8];          //
	uint8_t   DCB_current_unit;          // current unit #; see below

	// Volume tracking layer use only
	uint32_t  DCB_blocked_iop;           // address of requests for an
	                                     //  inactive volume

	uint32_t  DCB_vol_unlock_timer;      // unlock timer handle
	uint8_t   DCB_access_timer;          // time measure between accesses

	// Volume tracking layer use only
	uint8_t   DCB_Vol_Flags;             // Volume tracking; see below

	uint8_t   DCB_q_algo;                // algorithm index; see below
	uint8_t   DCB_unit_on_ctl;           // 0-based device number on ctlr
	uint32_t  DCB_Port_Specific;         // bytes for port driver use
	uint32_t  DCB_spindown_timer;        // timer for drive spin down

	DCB_BLOCKDEV  DCB_bdd;
} DCB, *PDCB;

/** Contains information about a calldown entry. */
typedef _Packed struct DCB_cd_entry {
    IO_callback DCB_cd_io_address; // address of request routine
    uint32_t  DCB_cd_flags;        // demand bits; see below
    struct DDB *DCB_cd_ddb;        // driver's DDB pointer
    struct DCB_cd_entry *DCB_cd_next;  // address of next cd entry
    uint16_t  DCB_cd_expan_off;    // offset of expansion area
    uint8_t   DCB_cd_layer_flags;  // flags for layer's use
    uint8_t   DCB_cd_lgn;          // load group number
} DCB_cd_entry, *PDCB_cd_entry;

enum DCB_BUS {
	DCB_BUS_ESDI = 0,
	DCB_BUS_SCSI = 1,
	DCB_BUS_NEC = 2,
	DCB_BUS_SMART = 3,
	DCB_BUS_ABIOS = 4
};

enum DCB_TSD_FLAGS {
	/** Don't trust the BPB */
	DCB_TSD_INVALID_PARTITION = 1,
	/** Bad MBR (physical device only) */
	DCB_TSD_BAD_MBR = 1,
	/** User drive letters checked */
	DCB_TSD_USER_LETTERS_CHECKED = (1 << 1),
	/** User drive letters checked first time */
	DCB_TSD_FIRST_USER_CHECK = (1 << 2),
	/** User set the a drive letter range */
	DCB_TSD_USER_SET = (1 << 4),
	/** User int 13 disabled */
	DCB_TSD_NO_USER_INT13 = 0x020,
	/** Protmode only int 13 */
	DCB_TSD_PROTMODE_INT_13 = (1 << 6),
	/** Reserved drive letter */
	DCB_TSD_NONEXIST_PARTITION = (1 << 7),
	/** Recommend BPB set from PBR by TSD (from int 41 or int 46) */
	DCB_TSD_MBPB_PBR = 0x0100,
	/** Bit shift for recommended BPB initialized */
	DCB_TSD_RBPB_INIT = (1 << 9),
	/** Media BPB initialized */
	DCB_TSD_MBPB_INIT = 0x0400,
	/** Apparent set from primary PBR */
	DCB_TSD_APPARENT_PBR = 0x0800,
	/** Apparent set from ROM data */
	DCB_TSD_APPARENT_ROM = 0x1000,
	/** Actual set from apparent by TSD */
	DCB_TSD_ACTUAL_SET = 0x2000,
	/** Actual geometry set prior to TSD */
	DCB_TSD_ACTUAL_PRE_SET = 0x4000,
	/** Apparent geometry set prior to TSD */
	DCB_TSD_APPARENT_PRE_SET = 0x8000
};

enum DCB_DEV_FLAGS
{
	/** indicates drive supports spindown command */
	DCB_DEV_SPINDOWN_SUPPORTED_BIT = 31,
	DCB_DEV_SPINDOWN_SUPPORTED = (1 << DCB_DEV_SPINDOWN_SUPPORTED_BIT),

	/* indicates drive is currently spun down */
	DCB_DEV_SPUN_DOWN_BIT = 30,
	DCB_DEV_SPUN_DOWN = (1 << DCB_DEV_SPUN_DOWN_BIT),

	/* port driver use only - indicates I/O has been received for this DCB */

	DCB_DEV_IO_ACTIVE_BIT = 29,
	DCB_DEV_IO_ACTIVE = (1 << DCB_DEV_IO_ACTIVE_BIT),

	/* this device has been configured as an int 13 drive */

	DCB_DEV_INT13_CONFIGURED_BIT = 28,
	DCB_DEV_INT13_CONFIGURED = (1 << DCB_DEV_INT13_CONFIGURED_BIT),

	/* This DCB cannot handle ASPI or CAM requests */

	DCB_DEV_NO_ASPICAM_BIT = 27,
	DCB_DEV_NO_ASPICAM = (1 << DCB_DEV_NO_ASPICAM_BIT),

	/* this device is going away soon */
	DCB_DEV_REMOVAL_PENDING_BIT = 26,
	DCB_DEV_REMOVAL_PENDING = (1 << DCB_DEV_REMOVAL_PENDING_BIT),

	/* logical drives for this int 13 device are controlled by the mapper */
	DCB_DEV_RMM_INT13_BIT = 25,
	DCB_DEV_RMM_INT13 = (1 << DCB_DEV_RMM_INT13_BIT),

	/* this device has been processed by a TSD */
	DCB_DEV_TSD_PROCESSED_BIT = 24,
	DCB_DEV_TSD_PROCESSED = (1 << DCB_DEV_TSD_PROCESSED_BIT),

	/* this is an equivlaent of IRS_DRV_SINGLE_FLOPPY. This indicates that */
	/* the dmd_a_b_toggling is not set in the floppy dcb. */
	DCB_DEV_SINGLE_FLOPPY = 0x00800000,

	/* this device must be controlled by a real mode driver, and should not */
	/* be taken over in protected mode */
	DCB_DEV_REAL_MODE = 0x00400000,

	/* current queing direction is descending - used by port drivers or IOS if */
	/* DCB_SERIAL_CMD flag is set */
	DCB_DEV_QUE_DESCEND = 0x00200000,

	/* hardware indicated media change  */
	DCB_DEV_MEDIA_CHANGED = 0x00100000,

	/* bit indicates the disk geometry has become invalid. */
	DCB_DEV_INVALID_GEOM = 0x00080000,

	/* If this bit is set, it specifies not have the volume tracking layer do
	 * the 2 second timing stuff for media change. This bit is typically set
	 * if DCB_DEV_SYNC_MED_CHG_SUPPORT is set.
	 */
	DCB_DEV_INHIBIT_SW_TIMED_SUPPORT = 0x00040000, /* drive is in read only mode */

	/* drive has h/w support to indicate by interrupt that disk door has been
	 * popped open, etc.
	 */
	DCB_DEV_ASYNC_MED_CHG_SUPPORT = 0x00020000,

	/* drive has h/w sync med. chg supp. -- when u first access a drive with
	 * media changed,  drive returns an error.
	 */
	DCB_DEV_SYNC_MED_CHG_SUPPORT = 0x00010000,

	DCB_DEV_PHYSICAL = 0x00008000,	/* on = physical */
	DCB_DEV_LOGICAL = 0x00004000,	/* on = logical */
	DCB_DEV_LOGICAL_BIT = 14,

	DCB_DEV_RMM = 0x00002000,	/* on = real mode mapper DCB*/
	DCB_DEV_RMM_BIT = 13,

	DCB_DEV_UNCERTAIN_MEDIA = 0x00001000, /* media may have been changed	*/
	DCB_DEV_ROM_CFG_REQ = 0x00000800,     /* tsd must use rom chain data	*/

	DCB_DEV_MUST_CONFIGURE = 0x00000400,/* set at create dcb time 	 */
							/* cleared after all layers */
							/* get the config aep for   */
							/* this DCB.		    */

	DCB_DEV_SSTOR_VOL = 0x00000200, /* set if this is SSTOR volume */

	DCB_DEV_PAGING_DEVICE = 0x00000100, /* indicates that the paging drive */
														/* is on this DCB */

	DCB_CHAR_DEVICE = 0x00000080, /* indicates that this is a char dev*/
	/*
	 * The foll. DCB_DEV_I13_IN_PROGRESS flag is used in conjunction with RMM
	 * and the global DCB. This flag is set when an int 13 in progress, in
	 * iosint13.asm, and cleared when the int 13 is done.
	 */

	DCB_DEV_I13_IN_PROGRESS  = 0x00000040,

	/** Cached device */
	DCB_DEV_CACHE = 0x00000020 ,
	/** Serial commands */
	DCB_DEV_SERIAL_CMD = 0x00000010,
	/** Remote device */
	DCB_DEV_REMOTE =  0x00000008,
	/* Removable media */
	DCB_DEV_REMOVABLE = 0x00000004 ,
	DCB_DEV_REMOVABLE_BIT = 2,
	/** Writeable media */
	DCB_DEV_WRITEABLE = 0x00000002,
	/** Int 13h drive */
	DCB_DEV_INT13_DRIVE = 0x00000001,
};

enum DCB_DEV2_FLAGS {
	DCB_DEV2_THREAD_LOCK = 0x00000001,
	DCB_DEV2_THREAD_LOCK_BIT = 0,

	DCB_DEV2_ATAPI_DEVICE = 0x00000002,
	DCB_DEV2_ATAPI_DEVICE_BIT = 1,

	DCB_DEV2_DMF_DISK = 0x00000004,	/* indicates current media is DMF */
	DCB_DEV2_DMF_DISK_BIT = 2,

	DCB_DEV2_I13_COPY_PROT = 0x00000008,/* indicates int 13 copy protection */
	DCB_DEV2_I13_COPY_PROT_BIT = 3,		/* access to one of the floppies 	*/

	DCB_DEV2_FAIL_FORMAT = 0x00000010,  /* indicates that we cannot allow format*/
	DCB_DEV2_FAIL_FORMAT_BIT = 4,

	DCB_DEV2_FLOPTICAL = 0x00000020,    /* indicates device is floptical */
	DCB_DEV2_FLOPTICAL_BIT = 5,
};

enum DCB_TYPE {
	DCB_type_disk = 0x00,	/* All Direct Access Devices -- non-removable */
	DCB_type_tape = 0x01,	/* Sequencial Access Devices */
	DCB_type_printer = 0x02,	/* Printer Device */
	DCB_type_processor = 0x03,	/* Processor type device */
	DCB_type_worm = 0x04,	/* Write Once Read Many Device */
	DCB_type_cdrom = 0x05,	/* CD ROM Device */
	DCB_type_scanner = 0x06,	/* Scanner Device */
	DCB_type_optical_memory = 0x07,	/* some Optical disk */
	DCB_type_changer = 0x08,	/* Changer device e.g. juke box */
	DCB_type_comm = 0x09,	/* Communication devices */
	DCB_type_floppy = 0x0A,	/* devices like floppy */
	DCB_type_optical_nec = 0x84   /* NEC 5.25" optical disk */
};

enum DCB_dmd_flags {
	DCB_dmd_srb_cdb = 0x00000001,	/* there must be an srb and cdb for */
	                                /* each ior. */
	DCB_dmd_rsrv_1 = 0x00000002,	/* reserved - must be zero. */

	DCB_dmd_logical = 0x00000004,	/* media address must be logical and*/
	                                /* dcb must be for a logical device.*/

	DCB_dmd_physical = 0x00000008,	/* media adresses must be physical  */
	                                /* and dcb must be for a physical   */
	                                /* device. */

	DCB_dmd_small_memory = 0x00000010,	/* data buffers must reside in	    */
	                                /* in low 16M. */

	DCB_dmd_rsrv_2 = 0x00000020,	/* reserved - must be zero.	*/

	DCB_dmd_rsrv_3 = 0x00000040,	/* reserved - must be zero.	*/
	DCB_dmd_rsrv_4 = 0x00000080,	/* reserved - must be zero.	*/

	DCB_dmd_not_512 = 0x00000100,	/* sector size on the media is not  */
	                                /* 512 bytes */

	DCB_dmd_word_align = 0x00000200,	/* data buffers must be word */
	                                    /* aligned.	*/

	DCB_dmd_dword_align = 0x00000400,	/* data buffers must be double word */
										/* aligned.	*/

	DCB_dmd_phys_sgd = 0x00000800,	/* scatter/gather descriptors must  */
	                                /* contain physical addresses (they */
	                                /* will contain linear addresses if */
	                                /* this demand bit is not set).     */

	DCB_dmd_phys_sgd_ptr = 0x00001000,	/* the pointer to the first	    */
									/* scatter/gather descriptor        */
									/* (IOR_sgd_lin_phys) must be a     */
									/* physical address (it will be a   */
									/* linear addresses if this demand  */
									/* bit is not set).	*/

	/* If foll. bit set, single floppy drive system -- voltrack needs to do
	 * the toggling between A: and B: when accesses to made to these drive
	 * letters.	 */
	DCB_dmd_do_a_b_toggling = 0x00002000,

	DCB_dmd_query_remov = 0x00004000,	/* lower level must be called to */
	                                    /* check if media is removeable/has */
	                                    /* changed. */

	DCB_dmd_request_sns = 0x00008000,	 /* port driver cannot perform autosense  */
	DCB_dmd_lock_unlock_media = 0x00010000,  /* media supports software locking */
	DCB_dmd_load_eject_media = 0x00020000,  /* media supports electronic eject */
	DCB_dmd_clear_media_chg = 0x00040000,  /* command to clear media change */
	DCB_dmd_serialize_bit = 19,  /* layer requires request serialization */
	DCB_dmd_serialize = 1 << DCB_dmd_serialize_bit,
	DCB_dmd_prot_mode = 0x00100000,  /* override real mode checks for */
	                                 /* this device i.e. ATAPI cdrom  */
	DCB_dmd_no_xclusive = 0x00200000,  /* indicates exclusive access is */
	                                   /* not required for abs write    */
	DCB_dmd_pageability = 0x00400000, /* indicates that access to this volume */
	                                  /* can cause paging */

	DCB_dmd_rsrv = DCB_dmd_rsrv_1+DCB_dmd_rsrv_2+DCB_dmd_rsrv_3+DCB_dmd_rsrv_4
};



// DDB ================

typedef _Packed struct DDB { //
    uint32_t  DDB_phys_addr;      // Physical address of ddb
    uint32_t  DDB_Next_DDB;       // next DDB on DVT_DDB chain
    uint32_t  DDB_Next_DDB_init;  // next DDB on DVT_DDB_init chain
    uint32_t  DDB_dcb_ptr;        // address of first DCB owned by this DDB
    uint8_t   DDB_number_buses;   // # of buses supported by the adapter
    uint8_t   DDB_ios_flags;      // IOS flags; see below
    uint16_t  DDB_sig;            // DDB signature; also padding
    void*     DDB_dvt;            // address of this DDB's DVT
    void*     DDB_devnode_ptr;    // address of devnode for device
    void*     DDB_reserved;       // reserved; must be zero
} DDB , *PDDB;


// DRP ================

typedef _Packed struct DRP {
    char     DRP_eyecatch_str[8];  // eye catcher string
    uint32_t DRP_LGN;              // load group number; see below
    void*    DRP_aer;              // addr of asynchronous event routine
    struct ILB *DRP_ilb;              // address of ILB; see below
    char     DRP_ascii_name[16];   // driver name; see below
    uint8_t  DRP_revision;         // driver revision
    uint32_t DRP_feature_code;     // feature code; see below
    uint16_t DRP_if_requirements;  // I/F requirements; see below
    uint8_t  DRP_bus_type;         // type of I/O bus; see below
    uint16_t DRP_reg_result;       // registration result; see below
    uint32_t DRP_reference_data;   // data to pass with AEP_INITIALIZE
    uint8_t  DRP_reserved1[2];     // reserved
    uint32_t DRP_reserved2[1];     // reserved; must be zero
} DRP, *PDRP;

enum DRP_IF {
	DRP_IF_ISA = 0x01,
	DRP_IF_EISA = 0x02,
	DRP_IF_MCA = 0x04,
	DRP_IF_STD = 0xFF
};

enum DRP_LGN {
	/* Installable File System layer. */
	DRP_FSD = 1 << 0x02,
	/** Other port drivers. */
	DRP_MISC_PD = 1 << 0x13
};

enum DRP_reg_result {
	/* Driver should remain resident */
	DRP_REMAIN_RESIDENT = 1,
	/* Driver should minimize */
	DRP_MINIMIZE = 2,
	/* Driver should not load */
	DRP_ABORT = 3,
	/* bad layer number - abort driver */
	DRP_INVALID_LAYER = 4
};


// ILB ==================

typedef _Packed struct ILB {
	/* service routine */
	void __cdecl (*ILB_service)(struct ISP *pisp);
    void __cdecl (*ILB_dprintf)(const char *format, ...);
	/** waits for 1/10 seconds. */
	void __cdecl (*ILB_Wait_10th_Sec)(void);
    void*     ILB_internal_request;     // addr of request routine
    void*     ILB_io_criteria_rtn;      // addr of IOR criteria routine
    void*     ILB_int_io_criteria_rtn;  // addr of IOP criteria routine
    uint32_t  ILB_dvt;                  // offset to addr of driver's DVT
    uint32_t  ILB_ios_mem_virt;         // addr of IOS memory pool
    void __cdecl (*ILB_enqueue_iop)(struct IOP *iop, struct DCB *dcb);
    struct IOP * __cdecl (*ILB_dequeue_iop)(struct DCB *dcb);
    uint32_t  ILB_reserved_1;           // reserved; must be zero
    uint32_t  ILB_reserved_2;           // reserved; must be zero
    uint16_t  ILB_flags;                // flags
    uint8_t   ILB_driver_numb;          // number of calls to AEP_INITIALIZE
    uint8_t   ILB_reserved_3;           // reserved; must be zero
} ILB, *PILB;

// IOR =================

typedef _Packed struct type_sdeffsd_req_usage { /* */
   uint16_t _IOR_ioctl_drive;
   uint16_t _IOR_ioctl_function ;
   uint32_t _IOR_ioctl_control_param ;
   uint32_t _IOR_ioctl_buffer_ptr;
   uint32_t _IOR_ioctl_client_params;
   uint32_t _IOR_ioctl_return;
} _type_sdeffsd_req_usage;

typedef _Packed union urequestor_usage { /* */
   uint32_t  _IOR_requestor_usage[5];
   struct type_sdeffsd_req_usage sdeffsd_req_usage;
} _urequestor_usage;

typedef  void (* CMDCPLT)(void);

typedef _Packed struct _IOR {
    uint32_t  IOR_next;            // client link; see below
    uint16_t  IOR_func;            // function; see below
    uint16_t  IOR_status;          // request status; see below
    uint32_t  IOR_flags;           // request flags; see below
    CMDCPLT IOR_callback;          // address of callback; see below
    uint64_t  IOR_start_addr;      // starting address; see below
    uint32_t  IOR_xfer_count;      // # of sectors/bytes; see below
    void*     IOR_buffer_ptr;      // client buffer; see below
    uint32_t  IOR_private_client;  // BlockDev/IOS client reserved
    uint32_t  IOR_private_IOS;     // reserved space for IOS
    uint32_t  IOR_private_port;    // private area for port driver
    union  urequestor_usage _ureq;  // requestor usage; see below
    uint32_t  IOR_req_req_handle;  // request handle; see below
    uint32_t  IOR_req_vol_handle;  // media handle; see below
    uint32_t  IOR_sgd_lin_phys;    // first physical SGD; see below
    uint8_t   IOR_num_sgds;        // number of physical SGDs
    uint8_t   IOR_vol_designtr;    // drive letter; see below
    uint16_t  IOR_ios_private_1;   // reserved by IOS to force alignment
    uint32_t  IOR_reserved_2[2];   // reserved for internal use
} IOR, *PIOR;

/** command codes for IOR_func as defined above */
enum IOR_funcs {
	/*
	**  IOR_READ
	**
	**  Function:
	**
	**  Reads the # of sectors/bytes as specified in IOR_xfer_count.
	**  See PDK documentation for specifics of parameter setting.
	**
	**
	**  Notes:
	**
	*/

	IOR_READ = 0x00,

	/*
	**  IOR_WRITE
	**
	**  Function:
	**
	**  Writes the # of sectors/bytes as specified in IOR_xfer_count.
	**  See PDK documentation for specifics of parameter setting.
	**
	**  Notes:
	**
	*/

	IOR_WRITE = 0x01,

	/*
	**  IOR_VERIFY
	**
	**  Function:
	**
	**  Verifies the # of sectors/bytes as specified in IOR_xfer_count.
	**
	**  Notes:
	**
	*/

	IOR_VERIFY = 0x02,	  /* verify data on device	      */

	/*
	**  IOR_CANCEL
	**
	**  Function:
	**
	**  Cancels the IOR referenced in ...
	**
	**  Notes:
	**
	**  Currently not supported in Chicago
	**
	*/

	IOR_CANCEL = 0x03,

	/*
	**  IOR_WRITEV
	**
	**  Function:
	**
	**  Writes and verifies the # of sectors/bytes as specified in IOR_xfer_count.
	**
	**  Notes:
	**
	**  Some hardware (IDE, for example) does not support this function.
	**
	*/

	IOR_WRITEV = 0x04,

	/*
	**  IOR_MEDIA_CHECK
	**
	**  Function:
	**
	**  Checks to see if media has changed, and returns status in IOR_status.
	**
	**  Notes:
	**
	**  Obsolete.  Use MEDIA_CHECK_RESET below
	**
	*/

	IOR_MEDIA_CHECK = 0x05,

	/*
	**  IOR_MEDIA_CHECK_RESET
	**
	**  Function:
	**
	**  Checks to see if media has changed, and returns status in IOR_status.
	**
	**  Notes:
	**
	*/

	IOR_MEDIA_CHECK_RESET = 0x06,

	/*
	**  IOR_LOAD_MEDIA
	**
	**  Function:
	**
	**  Performs a LOAD MEDIA operation on removable drives.
	**
	**  Notes:
	**
	*/

	IOR_LOAD_MEDIA = 0x07,

	/*
	**  IOR_EJECT_MEDIA
	**
	**  Function:
	**
	**  Performs an EJECT MEDIA operation on removable drives.
	**
	**  Notes:
	**
	**	 For disk and CD-ROM devices, applications are queried before eject,
	**  and the lock count is checked for zero.  If one of these checks fails,
	**  the user is queried to see if he wants to proceed.
	*/

	IOR_EJECT_MEDIA = 0x08,

	/*
	**  IOR_LOCK_MEDIA
	**
	**  Function:
	**
	**  Performs a LOCK MEDIA operation on removable drives.
	**
	**  Notes:
	**
	**  LOCK and UNLOCK MEDIA calls must be synchronized, as a depth counter is
	**  maintained by IOS.
	*/

	IOR_LOCK_MEDIA = 0x09,

	/*
	**  IOR_UNLOCK_MEDIA
	**
	**  Function:
	**
	**  Performs an UNLOCK MEDIA operation on removable drives.
	**
	**  Notes:
	**
	**  LOCK and UNLOCK MEDIA calls must be synchronized, as a depth counter is
	**  maintained by IOS.  UNLOCK MEDIA is delayed by about 5 seconds.
	*/

	IOR_UNLOCK_MEDIA = 0x0A,

	/*
	**  IOR_REQUEST_SENSE
	**
	**  Function:
	**
	**  Performs an REQUEST SENSE operation on removable drives.
	**
	**  Notes:
	**
	**	 Currently supported for SCSI devices only.
	**
	*/

	IOR_REQUEST_SENSE = 0x0B,

	/*
	**  IOR_COMPUTE_GEOM
	**
	**  Function:
	**
	**  Results in a reexamination of volume and device characteristics.
	**
	**  Notes:
	**
	**  When this command is received, each IOS layer assumes the device has
	**  changed, and performs whatever initialization required.  For example,
	**  the disk TSD will reexamine the partitions of a device.
	**
	*/

	IOR_COMPUTE_GEOM = 0x0C,

	/*
	**  IOR_GEN_IOCTL
	**
	**  Function:
	**
	**	 Function permits device-specific IOCtl's to be issued to IOS drivers.
	**  Also supports standard Int 21 function 44xx DOS IOCtl's.  See CDIOCTL.H
	**  for examples of CD IOCtl's.
	**
	**  aliasing for fields used by IOCTL's -
	**  this section gives both the normal and IOCTL names for the fields
	**
	**  	IOR_ioctl_drive - BX from 16 bit IOCTL - usually a 1 based drive number
	**  	IOR_ioctl_function - AX from 16 bit IOCTL
	**  	IOR_ioctl_handle - useful handle? or original?
	**  	IOR_ioctl_control_param - CX zero extended to ULONG
	**  	IOR_ioctl_buffer_ptr - DS:DX mapped flat general buffer from the IOCTL
	**  	IOR_ioctl_client_params - a pointer to the parameters passed in from
	**			the calling application the IORF_16BIT_IOCTL flag must be used to
	**			determine the structure type.  If it is a 16 bit IOCTL, the pointer
	**			will be to the CLIENT_REGS structure.  32 bit is as of yet undef'ed
	**  	IOR_ioctl_return - return value to be mapped to the IOCTL caller on exit
	**  	IOR_ioctl_buffer_length - size of buffer pointed to by
	**			IOR_ioctl_buffer_ptr	(not used by int 21 440d IOCTL calls)
	**
	**  Notes:
	**
	*/

	IOR_GEN_IOCTL = 0x0D,

	/*
	**  IOR_FORMAT
	**
	**  Function:
	**
	**  Allows issuance of a low level format packet as defined in the int 13
	**  specification.
	**
	**  Notes:
	**
	**  IOR_format_address_field => low level sector map
	**  See IOP.H IOP_FORMAT_XXX fields for additional information.
	*/

	IOR_FORMAT = 0x0E,

	/*
	**  IOR_SCSI_PASS_THROUGH
	**
	**  Function:
	**
	**  Each layer passes this request down with modification to the SCSI port
	**  driver.
	**
	**  Notes:
	**
	**  The IOR must contain a pointer to a valid SRB.  Also, "ebx" must point
	**  to the BDD portion of the DCB when IOS_SendCommand is called with a
	**  passthrough request.
	*/

	IOR_SCSI_PASS_THROUGH = 0x0F,

	/*
	**  IOR_CLEAR_QUEUE
	**
	**  Function:
	**
	**  Callback of request indicates all requests issued prior to this request
	**  have been completed.
	**
	**  Notes:
	*/

	IOR_CLEAR_QUEUE = 0x10,

	/*
	**  IOR_DOS_RESET
	**
	**  Function:
	**
	**  Issued in response to an int 13 reset by the int 13 vxd
	**
	**  Notes:
	**
	**  Currently used only by and for the IOS floppy driver.
	*/

	IOR_DOS_RESET = 0x11,

	/*
	**  IOR_SCSI_REQUEST
	**
	**  Function:
	**
	**  generic function that indicates the request is for SCSI.
	**
	**  Notes:
	**
	**  SRB field in IOR must be valid.  Normally used by IOS layers to send
	**  internal requests to SCSI devices.
	*/

	IOR_SCSI_REQUEST = 0x12,

	/*
	**  IOR_SET_WRITE_STATUS
	**
	**  Function:
	**
	**  results in the correct setting of DCB_DEV_WRITABLE flag in the DCB if
	**  SUCCESS status is returned.
	**
	**  Notes:
	**
	**  Currently only supported by the IOS floppy driver.
	*/

	IOR_SET_WRITE_STATUS = 0x22,

	/*
	**  IOR_RESTART_QUEUE
	**
	**  Function:
	**
	**  "Placeholder" function that results in restarting of the queue provided
	**  by the IOS queuing services.  Has no other effect.
	**
	**  Notes:
	**
	**  Should be sent after the DCB_QUEUE_FREEZE field has been decremented to
	**  zero.
	*/

	IOR_RESTART_QUEUE = 0x23,

	/*
	**  IOR_ABORT_QUEUE
	**
	**  Function:
	**
	**	 Causes each layer to call back each queued request with status of
	**  IORS_CANCELED
	**
	**  Notes:
	**
	*/

	IOR_ABORT_QUEUE = 0x24,

	/*
	**  IOR_SPIN_DOWN
	**
	**  Function:
	**
	**  Causes the specified drive to be spun down.
	**
	**  Notes:
	**
	*/

	IOR_SPIN_DOWN = 0x25,

	/*
	**  IOR_SPIN_UP
	**
	**  Function:
	**
	**  Causes the specified drive to be spun up.
	**
	**  Notes:
	**
	*/

	IOR_SPIN_UP = 0x26,

	/*
	**  IOR_FLUSH_DRIVE
	**
	**  Function:
	**
	**  Causes layer drivers to flush out dirty data.
	**
	**  Notes:
	**
	**  This is a synchronous function and should not be called at
	**  event/interrupt time.
	**
	*/

	IOR_FLUSH_DRIVE = 0x27,


	/*
	**  IOR_FLUSH_DRIVE_AND_DISCARD
	**
	**  Function:
	**
	**  Causes layer drivers to flush out dirty data and then dicard cached
	**  data.
	**
	**  Notes:
	**
	**  This is a synchronous function and should not be called at
	**  event/interrupt time.
	**
	*/

	IOR_FLUSH_DRIVE_AND_DISCARD = 0x28,


	/*
	**  IOR_FSD_EXT
	**
	**  Function:
	**
	**  Sends private command from an IOS client to the FSD extension
	**  layer (DRP_FSD_EXT_1 or DRP_FSD_EXT_2) such as a Compressed
	**  Volume Manager (CVM).
	**
	**  Notes:
	**
	**  This call is similar in intent and usage to IOR_GEN_IOCTL;
	**  however, it can be used in the swapper path, so, in general,
	**  the handling driver should not touch pageable code or data.
	**
	*/

	IOR_FSD_EXT = 0x29,

	/*
	**  IOR_FLOPTICAL_MODE_SENSE
	**
	**  Function:
	**
	**  Issues MODE SENSE command to page 0x2e, as is required to indicate to the
	**  floptical that it is supported.
	**
	**  Notes:
	**
	**  Don't use this command, as it is used by the system.
	**
	*/

	IOR_FLOPTICAL_MODE_SENSE = 0x2A,

};

/** IOR status codes for IOR_status */

enum IOR_STATUS {
	IORS_SUCCESS = 0x00, 	/* command completed successfully 	*/

	IORS_SUCCESS_WITH_RETRY = 0x01,  /* successful, but retries required */

	IORS_SUCCESS_WITH_ECC = 0x02,	/* ditto, but with ECC 					*/

	IORS_INVALID_SECTOR = 0x10, 	/* old blockdev error code for 		*/
														/* requests on an invalid sector 	*/
														/*	number 									*/
	IORS_CANCELED = 0x11,	/* command was canceled 				*/

	IORS_CMD_IN_PROGRESS = 0x12,  /* command is in progress, and can't be canceled  */

	IORS_INVALID_CMD_PTR = 0x13,  /* cancel of an invalid command 		*/

	IORS_MEDIA_ERROR = 0x14, /* media failure */

	IORS_DEVICE_ERROR = 0x15, /* error on recalib. drive, etc. */

	IORS_INVALID_COMMAND = 0x16, /* Command not supported or invalid	*/

	IORS_NO_DEVICE = 0x17, /* physical or logical device nonexistant */

	IORS_NO_MEDIA = 0x18, /* media removed from device */

	IORS_UNCERTAIN_MEDIA = 0x19,  /* media may have changed */

	IORS_UNREC_ERROR = 0x1A,  /* un-recoverable error */

	IORS_HW_FAILURE = 0x1B,  /* general hardware failure */

	IORS_UNFORMATTED_MEDIA = 0x1C,  /* unformatted media */

	IORS_MEMORY_ERROR = 0x1D,  /* error allocating DMA buffer space for I/O	*/

	IORS_TIME_OUT = 0x1E,  /* device timed out */

	IORS_WRITE_PROTECT = 0x1F,  /* write protect error */

	IORS_NOT_READY = 0x20,  /* device not ready */

	IORS_BUSY = 0x21, /* device is busy */

	IORS_VOL_NOT_LOCKED = 0x22,  /* volume received unlock without lk*/

	IORS_VOL_LOCKED = 0x23,  /* eject received with drive locked */

	IORS_VOL_NOT_REMOVABLE = 0x24,  /* removable request to non-remov drive */

	IORS_VOL_IN_USE = 0x25,  /* volume is in use - used for eject*/

	IORS_LOCK_COUNT_EXCEEDED = 0x26,  /* volume lock count exceeded */

	IORS_VALID_EJECT_FAILED = 0x27,  /* eject command was not accepted */

	IORS_ILLEGAL_ACCESS_MODE = 0x28,  /* cdrom read on audio or attempt */
	                                  /* play on data */

	IORS_LOCK_VIOLATION = 0x29,  /* illegal access to locked device */

	IORS_WRONG_MEDIA = 0x2a,  /* wrong media in drive */

	IORS_OUT_OF_SPACE = 0x2b,  /* no space on media */

	IORS_BIG_IO_BREAKUP_FAILED = 0x2c,/* attempt to split big I/O barfed */

	IORS_ERROR_DESIGNTR = 0x10,  /* bit indicating error occurred */

	IORS_INVALID_PARM = IORS_ERROR_DESIGNTR, /* bit indicating error occurred */
};

enum IOR_FLAGS {

	IORF_HIGH_PRIORITY_BIT=0, 		/* binary priority indication 		*/
	IORF_HIGH_PRIORITY = (1 << IORF_HIGH_PRIORITY_BIT),  /* 0x0001 */

	IORF_SCATTER_GATHER_BIT=1, 		/* bit indicating BDCB physical SGD */
														/* list present 							*/
	IORF_SCATTER_GATHER = (1 << IORF_SCATTER_GATHER_BIT), /* 0x0002 */

	IORF_DONT_CACHE_BIT=2, 		/* bit indicating that the BDCB data*/
														/*  should not be cached 				*/
	IORF_DONT_CACHE = (1 << IORF_DONT_CACHE_BIT),    /* 0x0004 */

	IORF_BYPASS_VOLTRK=0x0008,		/* request will not be volume trked	*/
	IORF_BYPASS_VOLTRK_BIT=3,

	IORF_16BIT_IOCTL=0x0010,		/* if true, 16 bit IOCTL calling 	*/
														/* app, else 32 bit ioctl				*/
	IORF_16BIT_IOCTL_BIT=4,

	IORF_SWAPPER_IO=0x0020,			/* request is from the swapper 		*/
	IORF_SWAPPER_IO_BIT=5,

	IORF_DOUBLE_BUFFER=0x0040,  	/* indicates that the request is to */
														/* be completed via double 			*/
														/* buffering.  client must 			*/
														/* ensure that both the sgd buffer 	*/
														/* pointers and IOR_sgd_lin_phys		*/
														/* are virtual pointers. 			  	*/
	IORF_DOUBLE_BUFFER_BIT=6,

	IORF_SYNC_CMD_DONE=0x0080,		/* used by IOS only to indicate 		*/
														/* completion 								*/
														/* of synchronous command 				*/
	IORF_SYNC_CMD_DONE_BIT=7,

	IORF_SYNC_COMMAND=0x0100,		/* indicates synchronous command 	*/
														/* (complete before return from IOS */
	IORF_SYNC_COMMAND_BIT=8,

	IORF_CHAR_COMMAND=0x0200,		/* indicates transfer counts and 	*/
														/* scatter/gather buffer sizes are 	*/
														/* byte values 							*/
	IORF_CHAR_COMMAND_BIT=9,

	IORF_VERSION_002=0x0400,  	/* indicates use of extended BCB 	*/
														/* (IOR) format for request			*/
	IORF_VERSION_002_BIT=10,

	IORF_BYPASS_QUEUE=0x0800,  	/* request should bypass IOS queuing*/
														/* internal IOS driver use only 		*/
	IORF_BYPASS_QUEUE_BIT=11,

	IORF_BLOCKDEV_EMULATE=0x1000,	/* this request started as a BCB 	*/
	IORF_BLOCKDEV_EMULATE_BIT=12,

	IORF_POSTPONED_VOL_OPS=0x2000,
	IORF_POSTPONED_VOL_OPS_BIT=13,

	IORF_INHIBIT_GEOM_RECOMPUTE=0x4000,
	IORF_INHIBIT_GEOM_RECOMPUTE_BIT=14,
														/* force inhibit of device geometry */
													   /* recomputation. 						*/

	IORF_SRB_VALID=0x8000,			/* indicates that IOP_srb points to */
	IORF_SRB_VALID_BIT=15,				/* a valid SRB	 							*/

	IORF_BYPASS_A_B=0x10000,			/* indicates that VOLTRK should 		*/
	IOFR_BYPASS_A_B_BIT=16,			/* bypass AB check 						*/

	IORF_QUIET_VOLTRK=0x20000,		/* indicates that volume tracking 	*/
	IORF_QUIET_VOLTRL_BIT=17,			/* just return error when wrong		*/
														/* media in drive (no dialog box)	*/

	IORF_AUDIO_DATA_READ=0x40000, 	/* indicates an audio data read 		*/
	IORF_AUDIO_DATA_READ_BIT=18,

	IORF_LOGICAL_START_SECTOR=0x80000,
	IORF_LOGICAL_START_SECTOR_BIT=19,
														/* IOR_start_addr is logical			*/

	IORF_PARTITION_BIAS_ADDED=0x100000,
	IORF_PARTITION_BIAS_ADDED_BIT=20, /* set by TSD only to indicate that */
														/* it has added in the bias, as req'd */
														/* by IORF_LOGICAL_START_SECTOR      */

	IORF_DATA_IN_BIT=21,				/* indicates a data read operation 	*/
	IORF_DATA_IN = (1 << IORF_DATA_IN_BIT),

	IORF_DATA_OUT_BIT=22,				/* indicates a data write operation */
	IORF_DATA_OUT = (1 << IORF_DATA_OUT_BIT),

	IORF_VOL_RETRY_BIT=23,				/* indicates volume tracking retried*/
	IORF_VOL_RETRY = (1 << IORF_VOL_RETRY_BIT),
														/* request (internal use only)		*/

	IORF_NO_COMPRESS_BIT=24,			/* do not compress data 				*/
	IORF_NO_COMPRESS = (1 << IORF_NO_COMPRESS_BIT),

	IORF_DIRECT_IO_BIT=25,			/* E.g., INT 25h or INT 26h 			*/
	IORF_DIRECT_IO = (1 << IORF_DIRECT_IO_BIT),

	IORF_PHYS_SGDS_BIT=26,
	IORF_PHYS_SGDS = (1 << IORF_PHYS_SGDS_BIT),
														/* indicates IOR_sgd_lin_phys valid */

	IORF_IO_TOO_BIG_BIT=27,
	IORF_IO_TOO_BIG = (1 << IORF_IO_TOO_BIG_BIT),
													/* indicates I/O is too big for 		*/
														/* single pass  (set by IOS criteria*/
														/* code).									*/
	IORF_WIN32_BIT=28,
	IORF_WIN32 = (1 << IORF_WIN32_BIT),
													/* indicates I/O is from 32 bit API */
	IORF_CHAR_DEVICE_BIT=29,
	IORF_CHAR_DEVICE = (1 << IORF_CHAR_DEVICE_BIT),

	IORF_PHYS_CMD_BIT=30,				/* indicates I/O is for a physical 	*/
														/* device 									*/
	IORF_PHYS_CMD = (1 << IORF_PHYS_CMD_BIT),

	IORF_IDE_RESERVED_BIT=31,				/* indicates I/O is for a physical 	*/
														/* device 									*/
	IORF_IDE_RESERVED = (1 << IORF_IDE_RESERVED_BIT)

};

// IOP =================

#define IOP_CALLBACK_TABLE_DEPTH 6

typedef _Packed struct IOP_callback_entry {
	IO_callback	IOP_CB_address; 	/* call back address */
	uint32_t	IOP_CB_ref_data;	/* pointer to callback ref data */
} IOP_callback_entry;

typedef _Packed struct IOP {
	uint32_t IOP_physical;        // physical address of IOP
	struct DCB *IOP_physical_dcb; // address of physical DCB
	struct DCB *IOP_original_dcb; // address of DCB designated by IOR
	uint16_t IOP_timer;           // Request Control Block (RCB) current
	                              //   timeout value
	uint16_t IOP_timer_orig;      // original timeout value
	DCB_cd_entry* IOP_calldown_ptr;    // address of next calldown routine
	IOP_callback_entry* IOP_callback_ptr;    // address of current callback address
	uint32_t IOP_voltrk_private;  // for use by volume tracking
	uint32_t IOP_Thread_Handle;   // handle of thread originating
	                              //   the I/O request
	uint32_t IOP_srb;             // used by SCSI'izers to pass SRB
	                              //   address to next layer
	uint32_t IOP_reserved[2];     // reserved; must be zero
	IOP_callback_entry IOP_callback_table[IOP_CALLBACK_TABLE_DEPTH];
	                              // RCB_CallBackTable
	uint8_t  IOP_format_head;     // low level format data
	uint8_t  IOP_format_xfer_rate;
	uint16_t IOP_format_track;
	uint32_t IOP_format_num_sectors;
	IOR IOP_ior;               // I/O request descriptor
} IOP, *PIOP;

/** Let lower levels continue processing this IOP. */
static void IopCalldown(IOP* iop) {
	// Get who is supposed to be next driver in the chain
	iop->IOP_calldown_ptr = iop->IOP_calldown_ptr->DCB_cd_next;
	// Call it
	iop->IOP_calldown_ptr->DCB_cd_io_address(iop);
}

/** Finish processing this IOP, and call back previous levels. */
static void IopCallback(IOP* iop) {
	iop->IOP_callback_ptr -= 1;
	iop->IOP_callback_ptr->IOP_CB_address(iop);
}

// ISP =================

typedef uint16_t IspResult; // unspecified error codes, but zero = no error

typedef _Packed struct ISP {
	uint16_t  ISP_func;    // function to be performed; see below
	IspResult ISP_result;  // result: zero = no error
} ISP, *PISP;

enum ISP_funcs {
	/* create ddb */
	ISP_CREATE_DDB = 0,
	/* create dcb (Physical) */
	ISP_CREATE_DCB = 1,
	/* create iop */
	ISP_CREATE_IOP = 2,
	/* allocate memory */
	ISP_ALLOC_MEM = 3,
	/* deallocate memory */
	ISP_DEALLOC_MEM = 4,
	/** insert entry in calldown table */
	ISP_INSERT_CALLDOWN = 5,
	/* associate dcb & relative drive # */
	ISP_ASSOCIATE_DCB = 6,
	/* return DCB for logical volume */
	ISP_GET_DCB = 7,
	/** get first/next DCB */
	ISP_GET_FIRST_NEXT_DCB = 8,
	/* deallocate DDB */
	ISP_DEALLOC_DDB = 9,
	/* destroy DCB */
	ISP_DESTROY_DCB = 10,
	/* ask for logical-to-physical info */
	ISP_QUERY_MATCHING_DCBS = 11,
	/* ask if we can remove a device */
	ISP_QUERY_REMOVE_DCB = 12,
	/* indicate that a device has been removed */
	ISP_DEVICE_REMOVED = 13,
	/* indicate that a device has arrived */
	ISP_DEVICE_ARRIVED = 14,
	/* disassociate dcb & drive # */
	ISP_DISASSOCIATE_DCB = 15,
	/* pick a drive letter */
	ISP_DRIVE_LETTER_PICK = 16,
	/* read registry */
	ISP_REGISTRY_READ = 17,
	/* find LDM entry */
	ISP_FIND_LDM_ENTRY = 18,
	/* delete LDM entry */
	ISP_DELETE_LDM_ENTRY = 19,
	/* broadcast an AEP from a driver */
	ISP_BROADCAST_AEP = 20
};

typedef _Packed struct ISP_dcb_create {  //
    ISP      ISP_dcb_hdr;   // Standard header
    uint16_t ISP_dcb_size;  // size of DCB to create, in bytes
    uint32_t ISP_dcb_ptr;   // address of DCB
    uint8_t  ISP_pad1[2];   // Pad to DWORD boundary
} ISP_dcb_create, *PISP_dcb_create;

static PDCB IspCreateDcb(ILB* ilb, uint16_t size) {
	ISP_dcb_create isp = {{ISP_CREATE_DCB}};
	isp.ISP_dcb_size = size;
	ilb->ILB_service((PISP)&isp);
	return isp.ISP_dcb_hdr.ISP_result != 0 ? NULL : (PDCB) isp.ISP_dcb_ptr;
}

typedef _Packed struct ISP_ddb_create {  //
    ISP      ISP_ddb_hdr;    // Standard header
    uint16_t ISP_ddb_size;   // size of DDB to create, in bytes
    uint32_t ISP_ddb_ptr;    // address of DDB
    uint8_t  ISP_ddb_flags;  // flags; see below
    uint8_t  ISP_pad0[1];    // Pad to DWORD boundary
} ISP_ddb_create, *PISP_ddb_create;

static PDDB IspCreateDdb(ILB* ilb, uint16_t size) {
	ISP_ddb_create isp = {{ISP_CREATE_DDB}};
	isp.ISP_ddb_size = size;
	ilb->ILB_service((PISP)&isp);
	return isp.ISP_ddb_hdr.ISP_result != 0 ? NULL : (PDDB) isp.ISP_ddb_ptr;
}

typedef _Packed struct ISP_calldown_insert {
    ISP      ISP_i_cd_hdr;        // Standard header
    uint32_t ISP_i_cd_dcb;        // address of DCB
    void*    ISP_i_cd_req;        // address of request routine
    uint32_t ISP_i_cd_ddb;        // address of DDB
    uint16_t ISP_i_cd_expan_len;  // size of IOP expansion required by this driver
    uint32_t  ISP_i_cd_flags;     // demand flags
    uint8_t  ISP_i_cd_lgn;        // load group number; typically same as AEP_lgn
    uint8_t  ISP_pad4[1];         // Pad to DWORD boundary
} ISP_calldown_insert, *PISP_calldown_insert;

static IspResult IspInsertCalldown(ILB* ilb, PDCB dcb, void (*calldown)(PIOP), PDDB ddb, uint16_t expand_len, uint32_t flags, uint8_t lgn) {
	ISP_calldown_insert isp = {{ISP_INSERT_CALLDOWN}};
	isp.ISP_i_cd_dcb = (uint32_t) dcb;
	isp.ISP_i_cd_req = calldown;
	isp.ISP_i_cd_ddb = (uint32_t) ddb;
	isp.ISP_i_cd_expan_len = expand_len;
	isp.ISP_i_cd_flags = flags;
	isp.ISP_i_cd_lgn = lgn;
	ilb->ILB_service((PISP)&isp);
	return isp.ISP_i_cd_hdr.ISP_result;
}

typedef _Packed struct ISP_AEP_BROADCAST {
    ISP    ISP_baep_hdr;        // Standard header
    void*  ISP_baep_paep;       // address of AEP to broadcast
} ISP_AEP_BROADCAST,*PISP_AEP_BROADCAST;

static IspResult IspBroadcastAep(ILB* ilb, PAEP paep) {
	ISP_AEP_BROADCAST isp = {{ISP_BROADCAST_AEP}};
	isp.ISP_baep_paep = paep;
	ilb->ILB_service((PISP)&isp);
	return isp.ISP_baep_hdr.ISP_result;
}

// SGD =========

typedef struct _SGD {
    uint32_t SG_buff_ptr;    // address of data buffer; see below
    uint32_t SG_buff_size;   // number of bytes to transfer
} SGD, *PSGD;

#endif // IOS_H