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 #define NONAMELESSUNION
47 #define NONAMELESSSTRUCT
49 #define WIN32_NO_STATUS
53 #include "ddk/ntddtape.h"
54 #include "ntdll_misc.h"
55 #include "wine/server.h"
56 #include "wine/debug.h"
58 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
60 static const char *io2str( DWORD io
)
64 #define X(x) case (x): return #x;
65 X(IOCTL_TAPE_CHECK_VERIFY
);
66 X(IOCTL_TAPE_CREATE_PARTITION
);
68 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
69 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
70 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
71 X(IOCTL_TAPE_GET_POSITION
);
72 X(IOCTL_TAPE_GET_STATUS
);
73 X(IOCTL_TAPE_PREPARE
);
74 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
75 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
76 X(IOCTL_TAPE_SET_POSITION
);
77 X(IOCTL_TAPE_WRITE_MARKS
);
79 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%d\n", io
); return tmp
; }
83 /******************************************************************
86 static NTSTATUS
TAPE_GetStatus( int error
)
88 if (!error
) return STATUS_SUCCESS
;
89 return FILE_GetNtStatus();
92 /******************************************************************
93 * TAPE_CreatePartition
95 static NTSTATUS
TAPE_CreatePartition( int fd
, TAPE_CREATE_PARTITION
*data
)
97 #ifdef HAVE_SYS_MTIO_H
100 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
101 fd
, data
->Method
, data
->Count
, data
->Size
);
105 WARN( "Creating more than 1 partition is not supported\n" );
106 return STATUS_INVALID_PARAMETER
;
109 switch (data
->Method
)
112 case TAPE_FIXED_PARTITIONS
:
113 case TAPE_SELECT_PARTITIONS
:
114 cmd
.mt_op
= MTMKPART
;
117 case TAPE_INITIATOR_PARTITIONS
:
118 cmd
.mt_op
= MTMKPART
;
119 cmd
.mt_count
= data
->Size
;
123 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
124 return STATUS_INVALID_PARAMETER
;
127 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
129 FIXME( "Not implemented.\n" );
130 return STATUS_NOT_SUPPORTED
;
134 /******************************************************************
137 static NTSTATUS
TAPE_Erase( int fd
, TAPE_ERASE
*data
)
139 #ifdef HAVE_SYS_MTIO_H
142 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
143 fd
, data
->Type
, data
->Immediate
);
147 case TAPE_ERASE_LONG
:
151 case TAPE_ERASE_SHORT
:
156 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
157 return STATUS_INVALID_PARAMETER
;
160 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
162 FIXME( "Not implemented.\n" );
163 return STATUS_NOT_SUPPORTED
;
167 /******************************************************************
168 * TAPE_GetDriveParams
170 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
172 #ifdef HAVE_SYS_MTIO_H
176 TRACE( "fd: %d\n", fd
);
178 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
180 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
181 if (status
!= STATUS_SUCCESS
)
185 data
->Compression
= FALSE
;
186 data
->DataPadding
= FALSE
;
187 data
->ReportSetmarks
= FALSE
;
188 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
189 data
->DefaultBlockSize
= get
.mt_blksiz
;
191 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
193 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
194 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
195 data
->MaximumPartitionCount
= 1;
199 FIXME( "Not implemented.\n" );
200 return STATUS_NOT_SUPPORTED
;
204 /******************************************************************
205 * TAPE_GetMediaParams
207 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
209 #ifdef HAVE_SYS_MTIO_H
213 TRACE( "fd: %d\n", fd
);
215 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
217 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
218 if (status
!= STATUS_SUCCESS
)
221 data
->Capacity
.u
.LowPart
= 1024 * 1024 * 1024;
222 data
->Remaining
.u
.LowPart
= 1024 * 1024 * 1024;
223 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
224 data
->BlockSize
= get
.mt_blksiz
;
226 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
228 data
->PartitionCount
= 1;
229 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
230 data
->WriteProtected
= GMT_WR_PROT(get
.mt_gstat
);
232 data
->WriteProtected
= 0;
237 FIXME( "Not implemented.\n" );
238 return STATUS_NOT_SUPPORTED
;
242 /******************************************************************
245 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
247 #ifdef HAVE_SYS_MTIO_H
249 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
254 TRACE( "fd: %d type: 0x%08x\n", fd
, type
);
256 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
258 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
259 if (status
!= STATUS_SUCCESS
)
262 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
263 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
264 if (status
!= STATUS_SUCCESS
)
270 case TAPE_ABSOLUTE_BLOCK
:
272 data
->Partition
= get
.mt_resid
;
273 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
274 data
->OffsetLow
= get
.mt_blkno
;
276 data
->OffsetLow
= pos
.mt_blkno
;
279 case TAPE_LOGICAL_BLOCK
:
280 case TAPE_PSEUDO_LOGICAL_BLOCK
:
281 WARN( "Positioning type not supported\n" );
284 ERR( "Unhandled type: 0x%08x\n", type
);
285 return STATUS_INVALID_PARAMETER
;
290 FIXME( "Not implemented.\n" );
291 return STATUS_NOT_SUPPORTED
;
295 /******************************************************************
298 static NTSTATUS
TAPE_Prepare( int fd
, TAPE_PREPARE
*data
)
300 #ifdef HAVE_SYS_MTIO_H
303 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
304 fd
, data
->Operation
, data
->Immediate
);
306 switch (data
->Operation
)
315 cmd
.mt_op
= MTUNLOAD
;
330 cmd
.mt_op
= MTUNLOCK
;
334 /* Native ignores this if the drive doesn't support it */
335 return STATUS_SUCCESS
;
337 ERR( "Unhandled operation: 0x%08x\n", data
->Operation
);
338 return STATUS_INVALID_PARAMETER
;
341 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
343 FIXME( "Not implemented.\n" );
344 return STATUS_NOT_SUPPORTED
;
348 /******************************************************************
349 * TAPE_SetDriveParams
351 static NTSTATUS
TAPE_SetDriveParams( int fd
, TAPE_SET_DRIVE_PARAMETERS
*data
)
353 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
356 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
357 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
358 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
359 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
361 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
362 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
364 cmd
.mt_op
= MTCOMPRESSION
;
365 cmd
.mt_count
= data
->Compression
;
367 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
369 FIXME( "Not implemented.\n" );
370 return STATUS_NOT_SUPPORTED
;
374 /******************************************************************
375 * TAPE_SetMediaParams
377 static NTSTATUS
TAPE_SetMediaParams( int fd
, TAPE_SET_MEDIA_PARAMETERS
*data
)
379 #ifdef HAVE_SYS_MTIO_H
382 TRACE( "fd: %d blocksize: 0x%08x\n", fd
, data
->BlockSize
);
384 cmd
.mt_op
= MTSETBLK
;
385 cmd
.mt_count
= data
->BlockSize
;
387 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
389 FIXME( "Not implemented.\n" );
390 return STATUS_NOT_SUPPORTED
;
394 /******************************************************************
397 static NTSTATUS
TAPE_SetPosition( int fd
, TAPE_SET_POSITION
*data
)
399 #ifdef HAVE_SYS_MTIO_H
402 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%08x immediate: 0x%02x\n",
403 fd
, data
->Method
, data
->Partition
, data
->Offset
.u
.LowPart
, data
->Immediate
);
405 if (data
->Offset
.u
.HighPart
> 0)
406 return STATUS_INVALID_PARAMETER
;
408 switch (data
->Method
)
414 case TAPE_ABSOLUTE_BLOCK
:
416 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
420 case TAPE_SPACE_END_OF_DATA
:
424 case TAPE_SPACE_FILEMARKS
:
425 if (data
->Offset
.u
.LowPart
>= 0) {
427 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
431 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
434 #if defined(MTFSS) && defined(MTBSS)
435 case TAPE_SPACE_SETMARKS
:
436 if (data
->Offset
.u
.LowPart
>= 0) {
438 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
442 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
446 case TAPE_LOGICAL_BLOCK
:
447 case TAPE_PSEUDO_LOGICAL_BLOCK
:
448 case TAPE_SPACE_RELATIVE_BLOCKS
:
449 case TAPE_SPACE_SEQUENTIAL_FMKS
:
450 case TAPE_SPACE_SEQUENTIAL_SMKS
:
451 WARN( "Positioning method not supported\n" );
452 return STATUS_INVALID_PARAMETER
;
454 ERR( "Unhandled method: 0x%08x\n", data
->Method
);
455 return STATUS_INVALID_PARAMETER
;
458 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
460 FIXME( "Not implemented.\n" );
461 return STATUS_NOT_SUPPORTED
;
465 /******************************************************************
468 static NTSTATUS
TAPE_WriteMarks( int fd
, TAPE_WRITE_MARKS
*data
)
470 #ifdef HAVE_SYS_MTIO_H
473 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
474 fd
, data
->Type
, data
->Count
, data
->Immediate
);
481 cmd
.mt_count
= data
->Count
;
485 case TAPE_SHORT_FILEMARKS
:
486 case TAPE_LONG_FILEMARKS
:
488 cmd
.mt_count
= data
->Count
;
491 ERR( "Unhandled type: 0x%08x\n", data
->Type
);
492 return STATUS_INVALID_PARAMETER
;
495 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
497 FIXME( "Not implemented.\n" );
498 return STATUS_NOT_SUPPORTED
;
502 /******************************************************************
503 * TAPE_DeviceIoControl
508 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
509 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
510 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
511 LPVOID out_buffer
, DWORD out_size
)
514 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
517 TRACE( "%p %s %p %d %p %d %p\n", device
, io2str(io_control
),
518 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
520 io_status
->Information
= 0;
522 if ((status
= wine_server_handle_to_fd( device
, 0, &fd
, NULL
)))
527 case IOCTL_TAPE_CREATE_PARTITION
:
528 status
= TAPE_CreatePartition( fd
, (TAPE_CREATE_PARTITION
*)in_buffer
);
530 case IOCTL_TAPE_ERASE
:
531 status
= TAPE_Erase( fd
, (TAPE_ERASE
*)in_buffer
);
533 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
534 status
= TAPE_GetDriveParams( fd
, (TAPE_GET_DRIVE_PARAMETERS
*)out_buffer
);
536 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
537 status
= TAPE_GetMediaParams( fd
, (TAPE_GET_MEDIA_PARAMETERS
*)out_buffer
);
539 case IOCTL_TAPE_GET_POSITION
:
540 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
541 (TAPE_GET_POSITION
*)out_buffer
);
543 case IOCTL_TAPE_GET_STATUS
:
544 status
= FILE_GetNtStatus();
546 case IOCTL_TAPE_PREPARE
:
547 status
= TAPE_Prepare( fd
, (TAPE_PREPARE
*)in_buffer
);
549 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
550 status
= TAPE_SetDriveParams( fd
, (TAPE_SET_DRIVE_PARAMETERS
*)in_buffer
);
552 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
553 status
= TAPE_SetMediaParams( fd
, (TAPE_SET_MEDIA_PARAMETERS
*)in_buffer
);
555 case IOCTL_TAPE_SET_POSITION
:
556 status
= TAPE_SetPosition( fd
, (TAPE_SET_POSITION
*)in_buffer
);
558 case IOCTL_TAPE_WRITE_MARKS
:
559 status
= TAPE_WriteMarks( fd
, (TAPE_WRITE_MARKS
*)in_buffer
);
562 case IOCTL_TAPE_CHECK_VERIFY
:
563 case IOCTL_TAPE_FIND_NEW_DEVICES
:
566 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
567 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
568 (io_control
>> 2) & 0xfff, io_control
& 3 );
572 wine_server_release_fd( device
, fd
);
575 io_status
->u
.Status
= status
;
576 io_status
->Information
= sz
;
577 if (event
) NtSetEvent( event
, NULL
);