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
51 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
54 #define WIN32_NO_STATUS
58 #include "ddk/ntddtape.h"
59 #include "ntdll_misc.h"
60 #include "wine/server.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
65 static const char *io2str( DWORD io
)
69 #define X(x) case (x): return #x
70 X(IOCTL_TAPE_CHECK_VERIFY
);
71 X(IOCTL_TAPE_CREATE_PARTITION
);
73 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
74 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
75 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
76 X(IOCTL_TAPE_GET_POSITION
);
77 X(IOCTL_TAPE_GET_STATUS
);
78 X(IOCTL_TAPE_PREPARE
);
79 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
80 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
81 X(IOCTL_TAPE_SET_POSITION
);
82 X(IOCTL_TAPE_WRITE_MARKS
);
84 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%d\n", io
); return tmp
; }
88 /******************************************************************
91 static inline NTSTATUS
TAPE_GetStatus( int error
)
93 if (!error
) return STATUS_SUCCESS
;
94 return FILE_GetNtStatus();
97 /******************************************************************
98 * TAPE_CreatePartition
100 static NTSTATUS
TAPE_CreatePartition( int fd
, const TAPE_CREATE_PARTITION
*data
)
102 #ifdef HAVE_SYS_MTIO_H
105 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
106 fd
, data
->Method
, data
->Count
, data
->Size
);
110 WARN( "Creating more than 1 partition is not supported\n" );
111 return STATUS_INVALID_PARAMETER
;
114 switch (data
->Method
)
117 case TAPE_FIXED_PARTITIONS
:
118 case TAPE_SELECT_PARTITIONS
:
119 cmd
.mt_op
= MTMKPART
;
122 case TAPE_INITIATOR_PARTITIONS
:
123 cmd
.mt_op
= MTMKPART
;
124 cmd
.mt_count
= data
->Size
;
128 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
129 return STATUS_INVALID_PARAMETER
;
132 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
134 FIXME( "Not implemented.\n" );
135 return STATUS_NOT_SUPPORTED
;
139 /******************************************************************
142 static NTSTATUS
TAPE_Erase( int fd
, const TAPE_ERASE
*data
)
144 #ifdef HAVE_SYS_MTIO_H
147 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
148 fd
, data
->Type
, data
->Immediate
);
152 case TAPE_ERASE_LONG
:
156 case TAPE_ERASE_SHORT
:
161 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
162 return STATUS_INVALID_PARAMETER
;
165 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
167 FIXME( "Not implemented.\n" );
168 return STATUS_NOT_SUPPORTED
;
172 /******************************************************************
173 * TAPE_GetDriveParams
175 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
177 #ifdef HAVE_SYS_MTIO_H
181 TRACE( "fd: %d\n", fd
);
183 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
185 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
186 if (status
!= STATUS_SUCCESS
)
190 data
->Compression
= FALSE
;
191 data
->DataPadding
= FALSE
;
192 data
->ReportSetmarks
= FALSE
;
193 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
194 data
->DefaultBlockSize
= get
.mt_blksiz
;
196 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
198 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
199 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
200 data
->MaximumPartitionCount
= 1;
204 FIXME( "Not implemented.\n" );
205 return STATUS_NOT_SUPPORTED
;
209 /******************************************************************
210 * TAPE_GetMediaParams
212 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
214 #ifdef HAVE_SYS_MTIO_H
218 TRACE( "fd: %d\n", fd
);
220 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
222 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
223 if (status
!= STATUS_SUCCESS
)
226 data
->Capacity
.u
.LowPart
= 1024 * 1024 * 1024;
227 data
->Remaining
.u
.LowPart
= 1024 * 1024 * 1024;
228 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
229 data
->BlockSize
= get
.mt_blksiz
;
231 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
233 data
->PartitionCount
= 1;
234 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
235 data
->WriteProtected
= (GMT_WR_PROT(get
.mt_gstat
) != 0);
237 data
->WriteProtected
= 0;
242 FIXME( "Not implemented.\n" );
243 return STATUS_NOT_SUPPORTED
;
247 /******************************************************************
250 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
252 #ifdef HAVE_SYS_MTIO_H
254 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
259 TRACE( "fd: %d type: 0x%08x\n", fd
, type
);
261 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
263 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
264 if (status
!= STATUS_SUCCESS
)
267 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
268 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
269 if (status
!= STATUS_SUCCESS
)
275 case TAPE_ABSOLUTE_BLOCK
:
277 data
->Partition
= get
.mt_resid
;
278 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
279 data
->OffsetLow
= get
.mt_blkno
;
281 data
->OffsetLow
= pos
.mt_blkno
;
284 case TAPE_LOGICAL_BLOCK
:
285 case TAPE_PSEUDO_LOGICAL_BLOCK
:
286 WARN( "Positioning type not supported\n" );
289 ERR( "Unhandled type: 0x%08x\n", type
);
290 return STATUS_INVALID_PARAMETER
;
295 FIXME( "Not implemented.\n" );
296 return STATUS_NOT_SUPPORTED
;
300 /******************************************************************
303 static NTSTATUS
TAPE_Prepare( int fd
, const TAPE_PREPARE
*data
)
305 #ifdef HAVE_SYS_MTIO_H
308 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
309 fd
, data
->Operation
, data
->Immediate
);
311 switch (data
->Operation
)
320 cmd
.mt_op
= MTUNLOAD
;
335 cmd
.mt_op
= MTUNLOCK
;
339 /* Native ignores this if the drive doesn't support it */
340 return STATUS_SUCCESS
;
342 ERR( "Unhandled operation: 0x%08x\n", data
->Operation
);
343 return STATUS_INVALID_PARAMETER
;
346 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
348 FIXME( "Not implemented.\n" );
349 return STATUS_NOT_SUPPORTED
;
353 /******************************************************************
354 * TAPE_SetDriveParams
356 static NTSTATUS
TAPE_SetDriveParams( int fd
, const TAPE_SET_DRIVE_PARAMETERS
*data
)
358 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
361 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
362 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
363 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
364 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
366 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
367 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
369 cmd
.mt_op
= MTCOMPRESSION
;
370 cmd
.mt_count
= data
->Compression
;
372 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
374 FIXME( "Not implemented.\n" );
375 return STATUS_NOT_SUPPORTED
;
379 /******************************************************************
380 * TAPE_SetMediaParams
382 static NTSTATUS
TAPE_SetMediaParams( int fd
, const TAPE_SET_MEDIA_PARAMETERS
*data
)
384 #ifdef HAVE_SYS_MTIO_H
387 TRACE( "fd: %d blocksize: 0x%08x\n", fd
, data
->BlockSize
);
389 cmd
.mt_op
= MTSETBLK
;
390 cmd
.mt_count
= data
->BlockSize
;
392 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
394 FIXME( "Not implemented.\n" );
395 return STATUS_NOT_SUPPORTED
;
399 /******************************************************************
402 static NTSTATUS
TAPE_SetPosition( int fd
, const TAPE_SET_POSITION
*data
)
404 #ifdef HAVE_SYS_MTIO_H
407 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%x%08x immediate: 0x%02x\n",
408 fd
, data
->Method
, data
->Partition
, (DWORD
)(data
->Offset
.QuadPart
>> 32),
409 (DWORD
)data
->Offset
.QuadPart
, data
->Immediate
);
411 if (sizeof(cmd
.mt_count
) < sizeof(data
->Offset
.QuadPart
) &&
412 (int)data
->Offset
.QuadPart
!= data
->Offset
.QuadPart
)
414 ERR("Offset too large or too small\n");
415 return STATUS_INVALID_PARAMETER
;
418 switch (data
->Method
)
424 case TAPE_ABSOLUTE_BLOCK
:
426 cmd
.mt_count
= data
->Offset
.QuadPart
;
430 case TAPE_SPACE_END_OF_DATA
:
434 case TAPE_SPACE_FILEMARKS
:
435 if (data
->Offset
.QuadPart
>= 0) {
437 cmd
.mt_count
= data
->Offset
.QuadPart
;
441 cmd
.mt_count
= -data
->Offset
.QuadPart
;
444 #if defined(MTFSS) && defined(MTBSS)
445 case TAPE_SPACE_SETMARKS
:
446 if (data
->Offset
.QuadPart
>= 0) {
448 cmd
.mt_count
= data
->Offset
.QuadPart
;
452 cmd
.mt_count
= -data
->Offset
.QuadPart
;
456 case TAPE_LOGICAL_BLOCK
:
457 case TAPE_PSEUDO_LOGICAL_BLOCK
:
458 case TAPE_SPACE_RELATIVE_BLOCKS
:
459 case TAPE_SPACE_SEQUENTIAL_FMKS
:
460 case TAPE_SPACE_SEQUENTIAL_SMKS
:
461 WARN( "Positioning method not supported\n" );
462 return STATUS_INVALID_PARAMETER
;
464 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
465 return STATUS_INVALID_PARAMETER
;
468 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
470 FIXME( "Not implemented.\n" );
471 return STATUS_NOT_SUPPORTED
;
475 /******************************************************************
478 static NTSTATUS
TAPE_WriteMarks( int fd
, const TAPE_WRITE_MARKS
*data
)
480 #ifdef HAVE_SYS_MTIO_H
483 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
484 fd
, data
->Type
, data
->Count
, data
->Immediate
);
491 cmd
.mt_count
= data
->Count
;
495 case TAPE_SHORT_FILEMARKS
:
496 case TAPE_LONG_FILEMARKS
:
498 cmd
.mt_count
= data
->Count
;
501 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
502 return STATUS_INVALID_PARAMETER
;
505 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
507 FIXME( "Not implemented.\n" );
508 return STATUS_NOT_SUPPORTED
;
512 /******************************************************************
513 * TAPE_DeviceIoControl
518 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
519 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
520 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
521 LPVOID out_buffer
, DWORD out_size
)
524 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
527 TRACE( "%p %s %p %d %p %d %p\n", device
, io2str(io_control
),
528 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
530 io_status
->Information
= 0;
532 if ((status
= server_get_unix_fd( device
, 0, &fd
, &needs_close
, NULL
, NULL
)))
537 case IOCTL_TAPE_CREATE_PARTITION
:
538 status
= TAPE_CreatePartition( fd
, in_buffer
);
540 case IOCTL_TAPE_ERASE
:
541 status
= TAPE_Erase( fd
, in_buffer
);
543 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
544 status
= TAPE_GetDriveParams( fd
, out_buffer
);
546 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
547 status
= TAPE_GetMediaParams( fd
, out_buffer
);
549 case IOCTL_TAPE_GET_POSITION
:
550 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
553 case IOCTL_TAPE_GET_STATUS
:
554 status
= FILE_GetNtStatus();
556 case IOCTL_TAPE_PREPARE
:
557 status
= TAPE_Prepare( fd
, in_buffer
);
559 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
560 status
= TAPE_SetDriveParams( fd
, in_buffer
);
562 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
563 status
= TAPE_SetMediaParams( fd
, in_buffer
);
565 case IOCTL_TAPE_SET_POSITION
:
566 status
= TAPE_SetPosition( fd
, in_buffer
);
568 case IOCTL_TAPE_WRITE_MARKS
:
569 status
= TAPE_WriteMarks( fd
, in_buffer
);
572 case IOCTL_TAPE_CHECK_VERIFY
:
573 case IOCTL_TAPE_FIND_NEW_DEVICES
:
576 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
577 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
578 (io_control
>> 2) & 0xfff, io_control
& 3 );
582 if (needs_close
) close( fd
);
585 io_status
->u
.Status
= status
;
586 io_status
->Information
= sz
;
587 if (event
) NtSetEvent( event
, NULL
);