~ubuntu-branches/ubuntu/oneiric/sg3-utils/oneiric

« back to all changes in this revision

Viewing changes to lib/sg_pt_win32.c

  • Committer: Bazaar Package Importer
  • Author(s): Michael Biebl
  • Date: 2009-11-05 20:42:13 UTC
  • mfrom: (5.2.2 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091105204213-ug7wrb6m7l9kmvyg
Tags: 1.28-2
* QA upload.
* Add libsgutils2-2.symbols.kfreebsd. Some of the symbols are Linux
  specific causing FTBFS on kfreebsd.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 *
28
28
 */
29
29
 
30
 
/* sg_pt_win32 version 1.07 20090204 */
 
30
/* sg_pt_win32 version 1.10 20090818 */
31
31
 
32
32
#include <stdio.h>
33
33
#include <stdlib.h>
40
40
#include "sg_lib.h"
41
41
#include "sg_pt_win32.h"
42
42
 
 
43
#ifdef HAVE_CONFIG_H
 
44
#include "config.h"
 
45
#endif
 
46
 
43
47
/* Use the Microsoft SCSI Pass Through (SPT) interface. It has two
44
48
 * variants: "SPT" where data is double buffered; and "SPTD" where data
45
49
 * pointers to the user space are passed to the OS. Only Windows
46
 
 * 2000, 2003 and XP are supported (i.e. not 95,98 or ME).
47
 
 * Currently there is no ASPI interface which relies on a dll
48
 
 * from adpatec.
 
50
 * 2000 and later (i.e. not 95,98 or ME).
 
51
 * There is no ASPI interface which relies on a dll from adaptec.
49
52
 * This code uses cygwin facilities and is built in a cygwin
50
53
 * shell. It can be run in a normal DOS shell if the cygwin1.dll
51
54
 * file is put in an appropriate place.
 
55
 * This code can build in a MinGW environment.
 
56
 *
 
57
 * N.B. MSDN says that the "SPT" interface (i.e. double buffered)
 
58
 * should be used for small amounts of data (it says "< 16 KB").
 
59
 * The direct variant (i.e. IOCTL_SCSI_PASS_THROUGH_DIRECT) should
 
60
 * be used for larger amounts of data but the buffer needs to be
 
61
 * "cache aligned". Is that 16 byte alignment or greater?
 
62
 *
 
63
 * This code will default to indirect (i.e. double buffered) access
 
64
 * unless the WIN32_SPT_DIRECT preprocessor constant is defined in
 
65
 * config.h .
52
66
 */
53
67
 
54
68
#define DEF_TIMEOUT 60       /* 60 seconds */
67
81
struct sg_pt_handle handle_arr[MAX_OPEN_SIMULT];
68
82
 
69
83
struct sg_pt_win32_scsi {
70
 
#ifdef SPTD
71
 
    SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
72
 
#else
73
 
    SCSI_PASS_THROUGH_WITH_BUFFERS swb;
74
 
#endif
75
84
    unsigned char * dxferp;
76
85
    int dxfer_len;
77
86
    unsigned char * sensep;
82
91
    int in_err;
83
92
    int os_err;                 /* pseudo unix error */
84
93
    int transport_err;          /* windows error number */
 
94
#ifdef WIN32_SPT_DIRECT
 
95
    SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER swb;
 
96
#else
 
97
    /* Last entry in structure so data buffer can be extended */
 
98
    SCSI_PASS_THROUGH_WITH_BUFFERS swb;
 
99
#endif
85
100
};
86
101
 
 
102
/* embed pointer so can change on fly if (non-direct) data buffer
 
103
 * is not big enough */
87
104
struct sg_pt_base {
88
 
    struct sg_pt_win32_scsi impl;
 
105
    struct sg_pt_win32_scsi * implp;
89
106
};
90
107
 
91
108
 
226
243
construct_scsi_pt_obj()
227
244
{
228
245
    struct sg_pt_win32_scsi * psp;
 
246
    struct sg_pt_base * vp = NULL;
229
247
 
230
 
    psp = (struct sg_pt_win32_scsi *)malloc(sizeof(struct sg_pt_win32_scsi));
 
248
    psp = (struct sg_pt_win32_scsi *)calloc(sizeof(struct sg_pt_win32_scsi),
 
249
                                            1);
231
250
    if (psp) {
232
 
        memset(psp, 0, sizeof(struct sg_pt_win32_scsi));
233
251
        psp->swb.spt.DataIn = SCSI_IOCTL_DATA_UNSPECIFIED;
234
252
        psp->swb.spt.SenseInfoLength = SCSI_MAX_SENSE_LEN;
235
253
        psp->swb.spt.SenseInfoOffset =
236
254
                offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS, ucSenseBuf);
237
255
        psp->swb.spt.TimeOutValue = DEF_TIMEOUT;
 
256
        vp = malloc(sizeof(struct sg_pt_win32_scsi *)); // yes a pointer
 
257
        if (vp)
 
258
            vp->implp = psp;
 
259
        else
 
260
            free(psp);
238
261
    }
239
 
    return (struct sg_pt_base *)psp;
 
262
    return vp;
240
263
}
241
264
 
242
265
void
243
266
destruct_scsi_pt_obj(struct sg_pt_base * vp)
244
267
{
245
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
268
    if (vp) {
 
269
        struct sg_pt_win32_scsi * psp = vp->implp;
246
270
 
247
 
    if (psp) {
248
 
        free(psp);
 
271
        if (psp) {
 
272
            free(psp);
 
273
        }
 
274
        free(vp);
249
275
    }
250
276
}
251
277
 
252
278
void
253
279
clear_scsi_pt_obj(struct sg_pt_base * vp)
254
280
{
255
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
281
    struct sg_pt_win32_scsi * psp = vp->implp;
256
282
 
257
283
    if (psp) {
258
284
        memset(psp, 0, sizeof(struct sg_pt_win32_scsi));
268
294
set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
269
295
                int cdb_len)
270
296
{
271
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
297
    struct sg_pt_win32_scsi * psp = vp->implp;
272
298
 
273
299
    if (psp->swb.spt.CdbLength > 0)
274
300
        ++psp->in_err;
284
310
set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
285
311
                  int sense_len)
286
312
{
287
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
313
    struct sg_pt_win32_scsi * psp = vp->implp;
288
314
 
289
315
    if (psp->sensep)
290
316
        ++psp->in_err;
298
324
set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
299
325
                    int dxfer_len)
300
326
{
301
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
327
    struct sg_pt_win32_scsi * psp = vp->implp;
302
328
 
303
329
    if (psp->dxferp)
304
330
        ++psp->in_err;
314
340
set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
315
341
                     int dxfer_len)
316
342
{
317
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
343
    struct sg_pt_win32_scsi * psp = vp->implp;
318
344
 
319
345
    if (psp->dxferp)
320
346
        ++psp->in_err;
334
360
void
335
361
set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag __attribute__ ((unused)))
336
362
{
337
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
363
    struct sg_pt_win32_scsi * psp = vp->implp;
338
364
 
339
365
    ++psp->in_err;
340
366
}
343
369
set_scsi_pt_task_management(struct sg_pt_base * vp,
344
370
                            int tmf_code __attribute__ ((unused)))
345
371
{
346
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
372
    struct sg_pt_win32_scsi * psp = vp->implp;
347
373
 
348
374
    ++psp->in_err;
349
375
}
353
379
                      int attrib __attribute__ ((unused)),
354
380
                      int priority __attribute__ ((unused)))
355
381
{
356
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
382
    struct sg_pt_win32_scsi * psp = vp->implp;
357
383
 
358
384
    ++psp->in_err;
359
385
}
365
391
do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
366
392
{
367
393
    int index = device_fd - WIN32_FDOFFSET;
368
 
    struct sg_pt_win32_scsi * psp = &vp->impl;
 
394
    struct sg_pt_win32_scsi * psp = vp->implp;
369
395
    struct sg_pt_handle * shp;
370
396
    BOOL status;
371
397
    ULONG returned;
398
424
        psp->os_err = ENODEV;
399
425
        return -psp->os_err;
400
426
    }
401
 
#ifdef SPTD
 
427
#ifdef WIN32_SPT_DIRECT
402
428
    psp->swb.spt.Length = sizeof (SCSI_PASS_THROUGH_DIRECT);
403
429
#else
404
430
    if (psp->dxfer_len > (int)sizeof(psp->swb.ucDataBuf)) {
405
 
        if (verbose)
406
 
            fprintf(sg_warnings_strm, "dxfer_len (%d) too large (limit %d "
407
 
                    "bytes)\n", psp->dxfer_len, sizeof(psp->swb.ucDataBuf));
408
 
        psp->os_err = ENOMEM;
409
 
        return -psp->os_err;
 
431
        int extra = psp->dxfer_len - (int)sizeof(psp->swb.ucDataBuf);
 
432
        struct sg_pt_win32_scsi * epsp;
410
433
 
 
434
        if (verbose > 4)
 
435
            fprintf(sg_warnings_strm, "dxfer_len (%d) too large for initial "
 
436
                    "data buffer (%d bytes), try enlarging\n", psp->dxfer_len,
 
437
                    sizeof(psp->swb.ucDataBuf));
 
438
        epsp = (struct sg_pt_win32_scsi *)
 
439
               calloc(sizeof(struct sg_pt_win32_scsi) + extra, 1);
 
440
        if (NULL == epsp) {
 
441
            fprintf(sg_warnings_strm, "do_scsi_pt: failed to enlarge data "
 
442
                    "buffer to %d bytes\n", psp->dxfer_len);
 
443
            psp->os_err = ENOMEM;
 
444
            return -psp->os_err;
 
445
        }
 
446
        memcpy(epsp, psp, sizeof(struct sg_pt_win32_scsi));
 
447
        free(psp);
 
448
        vp->implp = epsp;
 
449
        psp = epsp;
411
450
    }
412
451
    psp->swb.spt.Length = sizeof (SCSI_PASS_THROUGH);
413
452
    psp->swb.spt.DataBufferOffset =
428
467
                "DataTransferLength=%lu\n",
429
468
                (int)psp->swb.spt.CdbLength, (int)psp->swb.spt.SenseInfoLength,
430
469
                (int)psp->swb.spt.DataIn, psp->swb.spt.DataTransferLength);
431
 
#ifdef SPTD
 
470
#ifdef WIN32_SPT_DIRECT
432
471
        fprintf(stderr, "    TimeOutValue=%lu SenseInfoOffset=%lu\n",
433
472
                psp->swb.spt.TimeOutValue, psp->swb.spt.SenseInfoOffset);
434
473
#else
437
476
                psp->swb.spt.DataBufferOffset, psp->swb.spt.SenseInfoOffset);
438
477
#endif
439
478
    }
440
 
#ifdef SPTD
 
479
#ifdef WIN32_SPT_DIRECT
441
480
    psp->swb.spt.DataBuffer = psp->dxferp;
442
481
    status = DeviceIoControl(shp->fh, IOCTL_SCSI_PASS_THROUGH_DIRECT,
443
482
                            &psp->swb,
465
504
        psp->os_err = EIO;
466
505
        return 0;       /* let app find transport error */
467
506
    }
468
 
#ifndef SPTD
 
507
#ifndef WIN32_SPT_DIRECT
469
508
    if ((psp->dxfer_len > 0) && (SCSI_IOCTL_DATA_IN == psp->swb.spt.DataIn))
470
509
        memcpy(psp->dxferp, psp->swb.ucDataBuf, psp->dxfer_len);
471
510
#endif
488
527
int
489
528
get_scsi_pt_result_category(const struct sg_pt_base * vp)
490
529
{
491
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
530
    const struct sg_pt_win32_scsi * psp = vp->implp;
492
531
 
493
532
    if (psp->transport_err)     /* give transport error highest priority */
494
533
        return SCSI_PT_RESULT_TRANSPORT_ERR;
506
545
int
507
546
get_scsi_pt_resid(const struct sg_pt_base * vp)
508
547
{
509
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
548
    const struct sg_pt_win32_scsi * psp = vp->implp;
510
549
 
511
550
    return psp->resid;
512
551
}
514
553
int
515
554
get_scsi_pt_status_response(const struct sg_pt_base * vp)
516
555
{
517
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
556
    const struct sg_pt_win32_scsi * psp = vp->implp;
518
557
 
519
558
    return psp->scsi_status;
520
559
}
522
561
int
523
562
get_scsi_pt_sense_len(const struct sg_pt_base * vp)
524
563
{
525
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
564
    const struct sg_pt_win32_scsi * psp = vp->implp;
526
565
    int len;
527
566
 
528
567
    len = psp->sense_len - psp->sense_resid;
532
571
int
533
572
get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
534
573
{
535
 
    // const struct sg_pt_freebsd_scsi * psp = &vp->impl;
 
574
    // const struct sg_pt_freebsd_scsi * psp = vp->implp;
536
575
 
537
576
    return -1;
538
577
}
540
579
int
541
580
get_scsi_pt_transport_err(const struct sg_pt_base * vp)
542
581
{
543
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
582
    const struct sg_pt_win32_scsi * psp = vp->implp;
544
583
 
545
584
    return psp->transport_err;
546
585
}
548
587
int
549
588
get_scsi_pt_os_err(const struct sg_pt_base * vp)
550
589
{
551
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
590
    const struct sg_pt_win32_scsi * psp = vp->implp;
552
591
 
553
592
    return psp->os_err;
554
593
}
558
597
get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
559
598
                              char * b)
560
599
{
561
 
    struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)&vp->impl;
 
600
    struct sg_pt_win32_scsi * psp = (struct sg_pt_win32_scsi *)vp->implp;
562
601
    LPVOID lpMsgBuf;
563
602
    int k, num, ch;
564
603
 
593
632
char *
594
633
get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
595
634
{
596
 
    const struct sg_pt_win32_scsi * psp = &vp->impl;
 
635
    const struct sg_pt_win32_scsi * psp = vp->implp;
597
636
    const char * cp;
598
637
 
599
638
    cp = safe_strerror(psp->os_err);