4 * Copyright 2006 Hans Leidekker
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "wine/port.h"
26 #ifdef HAVE_SYS_IOCTL_H
27 #include <sys/ioctl.h>
29 #ifdef HAVE_SYS_MTIO_H
33 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
34 #define MTCOMPRESSION MTCOMP
36 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
37 #define MTSETBLK MTSETBSIZ
39 #if !defined(MTSETBLK) && defined(MTSRSZ)
40 #define MTSETBLK MTSRSZ
42 #ifndef MT_ST_BLKSIZE_MASK
43 #define MT_ST_BLKSIZE_MASK 0xffffff
46 /* Darwin 7.9.0 has MTSETBSIZ instead of MTSETBLK */
47 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
48 #define MTSETBLK MTSETBSIZ
52 #define WIN32_NO_STATUS
53 #define NONAMELESSUNION
57 #include "ddk/ntddtape.h"
58 #include "ntdll_misc.h"
59 #include "wine/server.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
64 static const char *io2str( DWORD io
)
68 #define X(x) case (x): return #x
69 X(IOCTL_TAPE_CHECK_VERIFY
);
70 X(IOCTL_TAPE_CREATE_PARTITION
);
72 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
73 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
74 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
75 X(IOCTL_TAPE_GET_POSITION
);
76 X(IOCTL_TAPE_GET_STATUS
);
77 X(IOCTL_TAPE_PREPARE
);
78 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
79 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
80 X(IOCTL_TAPE_SET_POSITION
);
81 X(IOCTL_TAPE_WRITE_MARKS
);
83 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%d\n", io
); return tmp
; }
87 /******************************************************************
90 static inline NTSTATUS
TAPE_GetStatus( int error
)
92 if (!error
) return STATUS_SUCCESS
;
93 return FILE_GetNtStatus();
96 /******************************************************************
97 * TAPE_CreatePartition
99 static NTSTATUS
TAPE_CreatePartition( int fd
, const TAPE_CREATE_PARTITION
*data
)
101 #ifdef HAVE_SYS_MTIO_H
104 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
105 fd
, data
->Method
, data
->Count
, data
->Size
);
109 WARN( "Creating more than 1 partition is not supported\n" );
110 return STATUS_INVALID_PARAMETER
;
113 switch (data
->Method
)
116 case TAPE_FIXED_PARTITIONS
:
117 case TAPE_SELECT_PARTITIONS
:
118 cmd
.mt_op
= MTMKPART
;
121 case TAPE_INITIATOR_PARTITIONS
:
122 cmd
.mt_op
= MTMKPART
;
123 cmd
.mt_count
= data
->Size
;
127 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
128 return STATUS_INVALID_PARAMETER
;
131 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
133 FIXME( "Not implemented.\n" );
134 return STATUS_NOT_SUPPORTED
;
138 /******************************************************************
141 static NTSTATUS
TAPE_Erase( int fd
, const TAPE_ERASE
*data
)
143 #ifdef HAVE_SYS_MTIO_H
146 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
147 fd
, data
->Type
, data
->Immediate
);
151 case TAPE_ERASE_LONG
:
155 case TAPE_ERASE_SHORT
:
160 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
161 return STATUS_INVALID_PARAMETER
;
164 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
166 FIXME( "Not implemented.\n" );
167 return STATUS_NOT_SUPPORTED
;
171 /******************************************************************
172 * TAPE_GetDriveParams
174 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
176 #ifdef HAVE_SYS_MTIO_H
180 TRACE( "fd: %d\n", fd
);
182 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
184 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
185 if (status
!= STATUS_SUCCESS
)
189 data
->Compression
= FALSE
;
190 data
->DataPadding
= FALSE
;
191 data
->ReportSetmarks
= FALSE
;
192 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
193 data
->DefaultBlockSize
= get
.mt_blksiz
;
195 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
197 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
198 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
199 data
->MaximumPartitionCount
= 1;
203 FIXME( "Not implemented.\n" );
204 return STATUS_NOT_SUPPORTED
;
208 /******************************************************************
209 * TAPE_GetMediaParams
211 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
213 #ifdef HAVE_SYS_MTIO_H
217 TRACE( "fd: %d\n", fd
);
219 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
221 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
222 if (status
!= STATUS_SUCCESS
)
225 data
->Capacity
.QuadPart
= 1024 * 1024 * 1024;
226 data
->Remaining
.QuadPart
= 1024 * 1024 * 1024;
227 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
228 data
->BlockSize
= get
.mt_blksiz
;
230 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
232 data
->PartitionCount
= 1;
233 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
234 data
->WriteProtected
= (GMT_WR_PROT(get
.mt_gstat
) != 0);
236 data
->WriteProtected
= 0;
241 FIXME( "Not implemented.\n" );
242 return STATUS_NOT_SUPPORTED
;
246 /******************************************************************
249 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
251 #ifdef HAVE_SYS_MTIO_H
253 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
258 TRACE( "fd: %d type: 0x%08x\n", fd
, type
);
260 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
262 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
263 if (status
!= STATUS_SUCCESS
)
266 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
267 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
268 if (status
!= STATUS_SUCCESS
)
274 case TAPE_ABSOLUTE_BLOCK
:
276 data
->Partition
= get
.mt_resid
;
277 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
278 data
->OffsetLow
= get
.mt_blkno
;
280 data
->OffsetLow
= pos
.mt_blkno
;
283 case TAPE_LOGICAL_BLOCK
:
284 case TAPE_PSEUDO_LOGICAL_BLOCK
:
285 WARN( "Positioning type not supported\n" );
288 ERR( "Unhandled type: 0x%08x\n", type
);
289 return STATUS_INVALID_PARAMETER
;
294 FIXME( "Not implemented.\n" );
295 return STATUS_NOT_SUPPORTED
;
299 /******************************************************************
302 static NTSTATUS
TAPE_Prepare( int fd
, const TAPE_PREPARE
*data
)
304 #ifdef HAVE_SYS_MTIO_H
307 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
308 fd
, data
->Operation
, data
->Immediate
);
310 switch (data
->Operation
)
319 cmd
.mt_op
= MTUNLOAD
;
334 cmd
.mt_op
= MTUNLOCK
;
338 /* Native ignores this if the drive doesn't support it */
339 return STATUS_SUCCESS
;
341 ERR( "Unhandled operation: 0x%08x\n", data
->Operation
);
342 return STATUS_INVALID_PARAMETER
;
345 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
347 FIXME( "Not implemented.\n" );
348 return STATUS_NOT_SUPPORTED
;
352 /******************************************************************
353 * TAPE_SetDriveParams
355 static NTSTATUS
TAPE_SetDriveParams( int fd
, const TAPE_SET_DRIVE_PARAMETERS
*data
)
357 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
360 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
361 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
362 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
363 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
365 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
366 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
368 cmd
.mt_op
= MTCOMPRESSION
;
369 cmd
.mt_count
= data
->Compression
;
371 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
373 FIXME( "Not implemented.\n" );
374 return STATUS_NOT_SUPPORTED
;
378 /******************************************************************
379 * TAPE_SetMediaParams
381 static NTSTATUS
TAPE_SetMediaParams( int fd
, const TAPE_SET_MEDIA_PARAMETERS
*data
)
383 #ifdef HAVE_SYS_MTIO_H
386 TRACE( "fd: %d blocksize: 0x%08x\n", fd
, data
->BlockSize
);
388 cmd
.mt_op
= MTSETBLK
;
389 cmd
.mt_count
= data
->BlockSize
;
391 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
393 FIXME( "Not implemented.\n" );
394 return STATUS_NOT_SUPPORTED
;
398 /******************************************************************
401 static NTSTATUS
TAPE_SetPosition( int fd
, const TAPE_SET_POSITION
*data
)
403 #ifdef HAVE_SYS_MTIO_H
406 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%x%08x immediate: 0x%02x\n",
407 fd
, data
->Method
, data
->Partition
, (DWORD
)(data
->Offset
.QuadPart
>> 32),
408 (DWORD
)data
->Offset
.QuadPart
, data
->Immediate
);
410 if (sizeof(cmd
.mt_count
) < sizeof(data
->Offset
.QuadPart
) &&
411 (int)data
->Offset
.QuadPart
!= data
->Offset
.QuadPart
)
413 ERR("Offset too large or too small\n");
414 return STATUS_INVALID_PARAMETER
;
417 switch (data
->Method
)
423 case TAPE_ABSOLUTE_BLOCK
:
425 cmd
.mt_count
= data
->Offset
.QuadPart
;
429 case TAPE_SPACE_END_OF_DATA
:
433 case TAPE_SPACE_FILEMARKS
:
434 if (data
->Offset
.QuadPart
>= 0) {
436 cmd
.mt_count
= data
->Offset
.QuadPart
;
440 cmd
.mt_count
= -data
->Offset
.QuadPart
;
443 #if defined(MTFSS) && defined(MTBSS)
444 case TAPE_SPACE_SETMARKS
:
445 if (data
->Offset
.QuadPart
>= 0) {
447 cmd
.mt_count
= data
->Offset
.QuadPart
;
451 cmd
.mt_count
= -data
->Offset
.QuadPart
;
455 case TAPE_LOGICAL_BLOCK
:
456 case TAPE_PSEUDO_LOGICAL_BLOCK
:
457 case TAPE_SPACE_RELATIVE_BLOCKS
:
458 case TAPE_SPACE_SEQUENTIAL_FMKS
:
459 case TAPE_SPACE_SEQUENTIAL_SMKS
:
460 WARN( "Positioning method not supported\n" );
461 return STATUS_INVALID_PARAMETER
;
463 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
464 return STATUS_INVALID_PARAMETER
;
467 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
469 FIXME( "Not implemented.\n" );
470 return STATUS_NOT_SUPPORTED
;
474 /******************************************************************
477 static NTSTATUS
TAPE_WriteMarks( int fd
, const TAPE_WRITE_MARKS
*data
)
479 #ifdef HAVE_SYS_MTIO_H
482 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
483 fd
, data
->Type
, data
->Count
, data
->Immediate
);
490 cmd
.mt_count
= data
->Count
;
494 case TAPE_SHORT_FILEMARKS
:
495 case TAPE_LONG_FILEMARKS
:
497 cmd
.mt_count
= data
->Count
;
500 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
501 return STATUS_INVALID_PARAMETER
;
504 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
506 FIXME( "Not implemented.\n" );
507 return STATUS_NOT_SUPPORTED
;
511 /******************************************************************
512 * TAPE_DeviceIoControl
517 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
518 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
519 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
520 LPVOID out_buffer
, DWORD out_size
)
523 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
526 TRACE( "%p %s %p %d %p %d %p\n", device
, io2str(io_control
),
527 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
529 io_status
->Information
= 0;
531 if ((status
= server_get_unix_fd( device
, 0, &fd
, &needs_close
, NULL
, NULL
)))
536 case IOCTL_TAPE_CREATE_PARTITION
:
537 status
= TAPE_CreatePartition( fd
, in_buffer
);
539 case IOCTL_TAPE_ERASE
:
540 status
= TAPE_Erase( fd
, in_buffer
);
542 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
543 status
= TAPE_GetDriveParams( fd
, out_buffer
);
545 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
546 status
= TAPE_GetMediaParams( fd
, out_buffer
);
548 case IOCTL_TAPE_GET_POSITION
:
549 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
552 case IOCTL_TAPE_GET_STATUS
:
553 status
= FILE_GetNtStatus();
555 case IOCTL_TAPE_PREPARE
:
556 status
= TAPE_Prepare( fd
, in_buffer
);
558 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
559 status
= TAPE_SetDriveParams( fd
, in_buffer
);
561 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
562 status
= TAPE_SetMediaParams( fd
, in_buffer
);
564 case IOCTL_TAPE_SET_POSITION
:
565 status
= TAPE_SetPosition( fd
, in_buffer
);
567 case IOCTL_TAPE_WRITE_MARKS
:
568 status
= TAPE_WriteMarks( fd
, in_buffer
);
571 case IOCTL_TAPE_CHECK_VERIFY
:
572 case IOCTL_TAPE_FIND_NEW_DEVICES
:
575 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
576 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
577 (io_control
>> 2) & 0xfff, io_control
& 3 );
581 if (needs_close
) close( fd
);
584 io_status
->u
.Status
= status
;
585 io_status
->Information
= sz
;
586 if (event
) NtSetEvent( event
, NULL
);