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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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
40 #define NONAMELESSUNION
41 #define NONAMELESSSTRUCT
43 #define WIN32_NO_STATUS
47 #include "ddk/ntddtape.h"
48 #include "ntdll_misc.h"
49 #include "wine/server.h"
50 #include "wine/debug.h"
52 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
54 static const char *io2str( DWORD io
)
58 #define X(x) case (x): return #x;
59 X(IOCTL_TAPE_CHECK_VERIFY
);
60 X(IOCTL_TAPE_CREATE_PARTITION
);
62 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
63 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
64 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
65 X(IOCTL_TAPE_GET_POSITION
);
66 X(IOCTL_TAPE_GET_STATUS
);
67 X(IOCTL_TAPE_PREPARE
);
68 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
69 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
70 X(IOCTL_TAPE_SET_POSITION
);
71 X(IOCTL_TAPE_WRITE_MARKS
);
73 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%ld\n", io
); return tmp
; }
77 /******************************************************************
80 static NTSTATUS
TAPE_GetStatus( int error
)
82 if (!error
) return STATUS_SUCCESS
;
83 return FILE_GetNtStatus();
86 /******************************************************************
87 * TAPE_CreatePartition
89 static NTSTATUS
TAPE_CreatePartition( int fd
, TAPE_CREATE_PARTITION
*data
)
91 #ifdef HAVE_SYS_MTIO_H
94 TRACE( "fd: %d method: 0x%08lx count: 0x%08lx size: 0x%08lx\n",
95 fd
, data
->Method
, data
->Count
, data
->Size
);
99 WARN( "Creating more than 1 partition is not supported\n" );
100 return STATUS_INVALID_PARAMETER
;
103 switch (data
->Method
)
106 case TAPE_FIXED_PARTITIONS
:
107 case TAPE_SELECT_PARTITIONS
:
108 cmd
.mt_op
= MTMKPART
;
111 case TAPE_INITIATOR_PARTITIONS
:
112 cmd
.mt_op
= MTMKPART
;
113 cmd
.mt_count
= data
->Size
;
117 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
118 return STATUS_INVALID_PARAMETER
;
121 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
123 FIXME( "Not implemented.\n" );
124 return STATUS_NOT_SUPPORTED
;
128 /******************************************************************
131 static NTSTATUS
TAPE_Erase( int fd
, TAPE_ERASE
*data
)
133 #ifdef HAVE_SYS_MTIO_H
136 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
137 fd
, data
->Type
, data
->Immediate
);
141 case TAPE_ERASE_LONG
:
145 case TAPE_ERASE_SHORT
:
150 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
151 return STATUS_INVALID_PARAMETER
;
154 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
156 FIXME( "Not implemented.\n" );
157 return STATUS_NOT_SUPPORTED
;
161 /******************************************************************
162 * TAPE_GetDriveParams
164 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
166 #ifdef HAVE_SYS_MTIO_H
170 TRACE( "fd: %d\n", fd
);
172 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
174 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
175 if (status
!= STATUS_SUCCESS
)
179 data
->Compression
= FALSE
;
180 data
->DataPadding
= FALSE
;
181 data
->ReportSetmarks
= FALSE
;
182 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
183 data
->DefaultBlockSize
= get
.mt_blksiz
;
185 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
187 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
188 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
189 data
->MaximumPartitionCount
= 1;
193 FIXME( "Not implemented.\n" );
194 return STATUS_NOT_SUPPORTED
;
198 /******************************************************************
199 * TAPE_GetMediaParams
201 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
203 #ifdef HAVE_SYS_MTIO_H
207 TRACE( "fd: %d\n", fd
);
209 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
211 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
212 if (status
!= STATUS_SUCCESS
)
215 data
->Capacity
.u
.LowPart
= 1024 * 1024 * 1024;
216 data
->Remaining
.u
.LowPart
= 1024 * 1024 * 1024;
217 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
218 data
->BlockSize
= get
.mt_blksiz
;
220 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
222 data
->PartitionCount
= 1;
223 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
224 data
->WriteProtected
= GMT_WR_PROT(get
.mt_gstat
);
226 data
->WriteProtected
= 0;
231 FIXME( "Not implemented.\n" );
232 return STATUS_NOT_SUPPORTED
;
236 /******************************************************************
239 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
241 #ifdef HAVE_SYS_MTIO_H
243 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
248 TRACE( "fd: %d type: 0x%08lx\n", fd
, type
);
250 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
252 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
253 if (status
!= STATUS_SUCCESS
)
256 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
257 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
258 if (status
!= STATUS_SUCCESS
)
264 case TAPE_ABSOLUTE_BLOCK
:
266 data
->Partition
= get
.mt_resid
;
267 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
268 data
->OffsetLow
= get
.mt_blkno
;
270 data
->OffsetLow
= pos
.mt_blkno
;
273 case TAPE_LOGICAL_BLOCK
:
274 case TAPE_PSEUDO_LOGICAL_BLOCK
:
275 WARN( "Positioning type not supported\n" );
278 ERR( "Unhandled type: 0x%08lx\n", type
);
279 return STATUS_INVALID_PARAMETER
;
284 FIXME( "Not implemented.\n" );
285 return STATUS_NOT_SUPPORTED
;
289 /******************************************************************
292 static NTSTATUS
TAPE_Prepare( int fd
, TAPE_PREPARE
*data
)
294 #ifdef HAVE_SYS_MTIO_H
297 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
298 fd
, data
->Operation
, data
->Immediate
);
300 switch (data
->Operation
)
309 cmd
.mt_op
= MTUNLOAD
;
324 cmd
.mt_op
= MTUNLOCK
;
328 /* Native ignores this if the drive doesn't support it */
329 return STATUS_SUCCESS
;
331 ERR( "Unhandled operation: 0x%08lx\n", data
->Operation
);
332 return STATUS_INVALID_PARAMETER
;
335 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
337 FIXME( "Not implemented.\n" );
338 return STATUS_NOT_SUPPORTED
;
342 /******************************************************************
343 * TAPE_SetDriveParams
345 static NTSTATUS
TAPE_SetDriveParams( int fd
, TAPE_SET_DRIVE_PARAMETERS
*data
)
347 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
350 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
351 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
352 TRACE( "setmarks: 0x%02x zonesize: 0x%08lx\n",
353 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
355 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
356 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
358 cmd
.mt_op
= MTCOMPRESSION
;
359 cmd
.mt_count
= data
->Compression
;
361 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
363 FIXME( "Not implemented.\n" );
364 return STATUS_NOT_SUPPORTED
;
368 /******************************************************************
369 * TAPE_SetMediaParams
371 static NTSTATUS
TAPE_SetMediaParams( int fd
, TAPE_SET_MEDIA_PARAMETERS
*data
)
373 #ifdef HAVE_SYS_MTIO_H
376 TRACE( "fd: %d blocksize: 0x%08lx\n", fd
, data
->BlockSize
);
378 cmd
.mt_op
= MTSETBLK
;
379 cmd
.mt_count
= data
->BlockSize
;
381 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
383 FIXME( "Not implemented.\n" );
384 return STATUS_NOT_SUPPORTED
;
388 /******************************************************************
391 static NTSTATUS
TAPE_SetPosition( int fd
, TAPE_SET_POSITION
*data
)
393 #ifdef HAVE_SYS_MTIO_H
396 TRACE( "fd: %d method: 0x%08lx partition: 0x%08lx offset: 0x%08lx immediate: 0x%02x\n",
397 fd
, data
->Method
, data
->Partition
, data
->Offset
.u
.LowPart
, data
->Immediate
);
399 if (data
->Offset
.u
.HighPart
> 0)
400 return STATUS_INVALID_PARAMETER
;
402 switch (data
->Method
)
408 case TAPE_ABSOLUTE_BLOCK
:
410 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
414 case TAPE_SPACE_END_OF_DATA
:
418 case TAPE_SPACE_FILEMARKS
:
419 if (data
->Offset
.u
.LowPart
>= 0) {
421 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
425 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
428 #if defined(MTFSS) && defined(MTBSS)
429 case TAPE_SPACE_SETMARKS
:
430 if (data
->Offset
.u
.LowPart
>= 0) {
432 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
436 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
440 case TAPE_LOGICAL_BLOCK
:
441 case TAPE_PSEUDO_LOGICAL_BLOCK
:
442 case TAPE_SPACE_RELATIVE_BLOCKS
:
443 case TAPE_SPACE_SEQUENTIAL_FMKS
:
444 case TAPE_SPACE_SEQUENTIAL_SMKS
:
445 WARN( "Positioning method not supported\n" );
446 return STATUS_INVALID_PARAMETER
;
448 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
449 return STATUS_INVALID_PARAMETER
;
452 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
454 FIXME( "Not implemented.\n" );
455 return STATUS_NOT_SUPPORTED
;
459 /******************************************************************
462 static NTSTATUS
TAPE_WriteMarks( int fd
, TAPE_WRITE_MARKS
*data
)
464 #ifdef HAVE_SYS_MTIO_H
467 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
468 fd
, data
->Type
, data
->Count
, data
->Immediate
);
475 cmd
.mt_count
= data
->Count
;
479 case TAPE_SHORT_FILEMARKS
:
480 case TAPE_LONG_FILEMARKS
:
482 cmd
.mt_count
= data
->Count
;
485 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
486 return STATUS_INVALID_PARAMETER
;
489 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
491 FIXME( "Not implemented.\n" );
492 return STATUS_NOT_SUPPORTED
;
496 /******************************************************************
497 * TAPE_DeviceIoControl
502 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
503 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
504 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
505 LPVOID out_buffer
, DWORD out_size
)
508 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
511 TRACE( "%p %s %p %ld %p %ld %p\n", device
, io2str(io_control
),
512 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
514 io_status
->Information
= 0;
516 if ((status
= wine_server_handle_to_fd( device
, 0, &fd
, NULL
)))
521 case IOCTL_TAPE_CREATE_PARTITION
:
522 status
= TAPE_CreatePartition( fd
, (TAPE_CREATE_PARTITION
*)in_buffer
);
524 case IOCTL_TAPE_ERASE
:
525 status
= TAPE_Erase( fd
, (TAPE_ERASE
*)in_buffer
);
527 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
528 status
= TAPE_GetDriveParams( fd
, (TAPE_GET_DRIVE_PARAMETERS
*)out_buffer
);
530 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
531 status
= TAPE_GetMediaParams( fd
, (TAPE_GET_MEDIA_PARAMETERS
*)out_buffer
);
533 case IOCTL_TAPE_GET_POSITION
:
534 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
535 (TAPE_GET_POSITION
*)out_buffer
);
537 case IOCTL_TAPE_GET_STATUS
:
538 status
= FILE_GetNtStatus();
540 case IOCTL_TAPE_PREPARE
:
541 status
= TAPE_Prepare( fd
, (TAPE_PREPARE
*)in_buffer
);
543 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
544 status
= TAPE_SetDriveParams( fd
, (TAPE_SET_DRIVE_PARAMETERS
*)in_buffer
);
546 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
547 status
= TAPE_SetMediaParams( fd
, (TAPE_SET_MEDIA_PARAMETERS
*)in_buffer
);
549 case IOCTL_TAPE_SET_POSITION
:
550 status
= TAPE_SetPosition( fd
, (TAPE_SET_POSITION
*)in_buffer
);
552 case IOCTL_TAPE_WRITE_MARKS
:
553 status
= TAPE_WriteMarks( fd
, (TAPE_WRITE_MARKS
*)in_buffer
);
556 case IOCTL_TAPE_CHECK_VERIFY
:
557 case IOCTL_TAPE_FIND_NEW_DEVICES
:
560 FIXME( "Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
561 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
562 (io_control
>> 2) & 0xfff, io_control
& 3 );
566 wine_server_release_fd( device
, fd
);
569 io_status
->u
.Status
= status
;
570 io_status
->Information
= sz
;
571 if (event
) NtSetEvent( event
, NULL
);