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 /* FreeBSD, for example, has MTCOMP instead of MTCOMPRESSION. */
34 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
35 #define MTCOMPRESSION MTCOMP
38 #define NONAMELESSUNION
39 #define NONAMELESSSTRUCT
41 #define WIN32_NO_STATUS
45 #include "ddk/ntddtape.h"
46 #include "ntdll_misc.h"
47 #include "wine/server.h"
48 #include "wine/debug.h"
50 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
52 static const char *io2str( DWORD io
)
56 #define X(x) case (x): return #x;
57 X(IOCTL_TAPE_CHECK_VERIFY
);
58 X(IOCTL_TAPE_CREATE_PARTITION
);
60 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
61 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
62 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
63 X(IOCTL_TAPE_GET_POSITION
);
64 X(IOCTL_TAPE_GET_STATUS
);
65 X(IOCTL_TAPE_PREPARE
);
66 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
67 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
68 X(IOCTL_TAPE_SET_POSITION
);
69 X(IOCTL_TAPE_WRITE_MARKS
);
71 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%ld\n", io
); return tmp
; }
75 /******************************************************************
78 static NTSTATUS
TAPE_GetStatus( int error
)
80 if (!error
) return STATUS_SUCCESS
;
81 return FILE_GetNtStatus();
84 /******************************************************************
85 * TAPE_CreatePartition
87 static NTSTATUS
TAPE_CreatePartition( int fd
, TAPE_CREATE_PARTITION
*data
)
89 #ifdef HAVE_SYS_MTIO_H
92 TRACE( "fd: %d method: 0x%08lx count: 0x%08lx size: 0x%08lx\n",
93 fd
, data
->Method
, data
->Count
, data
->Size
);
97 WARN( "Creating more than 1 partition is not supported\n" );
98 return STATUS_INVALID_PARAMETER
;
101 switch (data
->Method
)
104 case TAPE_FIXED_PARTITIONS
:
105 case TAPE_SELECT_PARTITIONS
:
106 cmd
.mt_op
= MTMKPART
;
109 case TAPE_INITIATOR_PARTITIONS
:
110 cmd
.mt_op
= MTMKPART
;
111 cmd
.mt_count
= data
->Size
;
115 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
116 return STATUS_INVALID_PARAMETER
;
119 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
121 FIXME( "Not implemented.\n" );
122 return STATUS_NOT_SUPPORTED
;
126 /******************************************************************
129 static NTSTATUS
TAPE_Erase( int fd
, TAPE_ERASE
*data
)
131 #ifdef HAVE_SYS_MTIO_H
134 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
135 fd
, data
->Type
, data
->Immediate
);
139 case TAPE_ERASE_LONG
:
143 case TAPE_ERASE_SHORT
:
148 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
149 return STATUS_INVALID_PARAMETER
;
152 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
154 FIXME( "Not implemented.\n" );
155 return STATUS_NOT_SUPPORTED
;
159 /******************************************************************
160 * TAPE_GetDriveParams
162 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
164 #ifdef HAVE_SYS_MTIO_H
168 TRACE( "fd: %d\n", fd
);
170 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
172 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
173 if (status
!= STATUS_SUCCESS
)
177 data
->Compression
= FALSE
;
178 data
->DataPadding
= FALSE
;
179 data
->ReportSetmarks
= FALSE
;
180 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
181 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
182 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
183 data
->MaximumPartitionCount
= 1;
187 FIXME( "Not implemented.\n" );
188 return STATUS_NOT_SUPPORTED
;
192 /******************************************************************
193 * TAPE_GetMediaParams
195 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
197 #ifdef HAVE_SYS_MTIO_H
201 TRACE( "fd: %d\n", fd
);
203 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
205 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
206 if (status
!= STATUS_SUCCESS
)
209 data
->Capacity
.u
.LowPart
= 1024 * 1024 * 1024;
210 data
->Remaining
.u
.LowPart
= 1024 * 1024 * 1024;
211 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
212 data
->PartitionCount
= 1;
213 data
->WriteProtected
= GMT_WR_PROT(get
.mt_gstat
);
217 FIXME( "Not implemented.\n" );
218 return STATUS_NOT_SUPPORTED
;
222 /******************************************************************
225 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
227 #ifdef HAVE_SYS_MTIO_H
232 TRACE( "fd: %d type: 0x%08lx\n", fd
, type
);
234 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
236 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
237 if (status
!= STATUS_SUCCESS
)
240 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
241 if (status
!= STATUS_SUCCESS
)
246 case TAPE_ABSOLUTE_BLOCK
:
248 data
->Partition
= get
.mt_resid
;
249 data
->OffsetLow
= pos
.mt_blkno
;
251 case TAPE_LOGICAL_BLOCK
:
252 case TAPE_PSEUDO_LOGICAL_BLOCK
:
253 WARN( "Positioning type not supported\n" );
256 ERR( "Unhandled type: 0x%08lx\n", type
);
257 return STATUS_INVALID_PARAMETER
;
262 FIXME( "Not implemented.\n" );
263 return STATUS_NOT_SUPPORTED
;
267 /******************************************************************
270 static NTSTATUS
TAPE_Prepare( int fd
, TAPE_PREPARE
*data
)
272 #ifdef HAVE_SYS_MTIO_H
275 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
276 fd
, data
->Operation
, data
->Immediate
);
278 switch (data
->Operation
)
287 cmd
.mt_op
= MTUNLOAD
;
302 cmd
.mt_op
= MTUNLOCK
;
306 /* Native ignores this if the drive doesn't support it */
307 return STATUS_SUCCESS
;
309 ERR( "Unhandled operation: 0x%08lx\n", data
->Operation
);
310 return STATUS_INVALID_PARAMETER
;
313 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
315 FIXME( "Not implemented.\n" );
316 return STATUS_NOT_SUPPORTED
;
320 /******************************************************************
321 * TAPE_SetDriveParams
323 static NTSTATUS
TAPE_SetDriveParams( int fd
, TAPE_SET_DRIVE_PARAMETERS
*data
)
325 #ifdef HAVE_SYS_MTIO_H
328 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
329 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
330 TRACE( "setmarks: 0x%02x zonesize: 0x%08lx\n",
331 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
333 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
334 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
336 cmd
.mt_op
= MTCOMPRESSION
;
337 cmd
.mt_count
= data
->Compression
;
339 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
341 FIXME( "Not implemented.\n" );
342 return STATUS_NOT_SUPPORTED
;
346 /******************************************************************
347 * TAPE_SetMediaParams
349 static NTSTATUS
TAPE_SetMediaParams( int fd
, TAPE_SET_MEDIA_PARAMETERS
*data
)
351 #ifdef HAVE_SYS_MTIO_H
354 TRACE( "fd: %d blocksize: 0x%08lx\n", fd
, data
->BlockSize
);
356 cmd
.mt_op
= MTSETBLK
;
357 cmd
.mt_count
= data
->BlockSize
;
359 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
361 FIXME( "Not implemented.\n" );
362 return STATUS_NOT_SUPPORTED
;
366 /******************************************************************
369 static NTSTATUS
TAPE_SetPosition( int fd
, TAPE_SET_POSITION
*data
)
371 #ifdef HAVE_SYS_MTIO_H
374 TRACE( "fd: %d method: 0x%08lx partition: 0x%08lx offset: 0x%08lx immediate: 0x%02x\n",
375 fd
, data
->Method
, data
->Partition
, data
->Offset
.u
.LowPart
, data
->Immediate
);
377 if (data
->Offset
.u
.HighPart
> 0)
378 return STATUS_INVALID_PARAMETER
;
380 switch (data
->Method
)
386 case TAPE_ABSOLUTE_BLOCK
:
388 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
392 case TAPE_SPACE_END_OF_DATA
:
396 case TAPE_SPACE_FILEMARKS
:
397 if (data
->Offset
.u
.LowPart
>= 0) {
399 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
403 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
406 case TAPE_SPACE_SETMARKS
:
407 if (data
->Offset
.u
.LowPart
>= 0) {
409 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
413 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
416 case TAPE_LOGICAL_BLOCK
:
417 case TAPE_PSEUDO_LOGICAL_BLOCK
:
418 case TAPE_SPACE_RELATIVE_BLOCKS
:
419 case TAPE_SPACE_SEQUENTIAL_FMKS
:
420 case TAPE_SPACE_SEQUENTIAL_SMKS
:
421 WARN( "Positioning method not supported\n" );
422 return STATUS_INVALID_PARAMETER
;
424 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
425 return STATUS_INVALID_PARAMETER
;
428 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
430 FIXME( "Not implemented.\n" );
431 return STATUS_NOT_SUPPORTED
;
435 /******************************************************************
438 static NTSTATUS
TAPE_WriteMarks( int fd
, TAPE_WRITE_MARKS
*data
)
440 #ifdef HAVE_SYS_MTIO_H
443 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
444 fd
, data
->Type
, data
->Count
, data
->Immediate
);
451 cmd
.mt_count
= data
->Count
;
455 case TAPE_SHORT_FILEMARKS
:
456 case TAPE_LONG_FILEMARKS
:
458 cmd
.mt_count
= data
->Count
;
461 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
462 return STATUS_INVALID_PARAMETER
;
465 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
467 FIXME( "Not implemented.\n" );
468 return STATUS_NOT_SUPPORTED
;
472 /******************************************************************
473 * TAPE_DeviceIoControl
478 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
479 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
480 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
481 LPVOID out_buffer
, DWORD out_size
)
484 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
487 TRACE( "%p %s %p %ld %p %ld %p\n", device
, io2str(io_control
),
488 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
490 io_status
->Information
= 0;
492 if ((status
= wine_server_handle_to_fd( device
, 0, &fd
, NULL
)))
497 case IOCTL_TAPE_CREATE_PARTITION
:
498 status
= TAPE_CreatePartition( fd
, (TAPE_CREATE_PARTITION
*)in_buffer
);
500 case IOCTL_TAPE_ERASE
:
501 status
= TAPE_Erase( fd
, (TAPE_ERASE
*)in_buffer
);
503 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
504 status
= TAPE_GetDriveParams( fd
, (TAPE_GET_DRIVE_PARAMETERS
*)out_buffer
);
506 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
507 status
= TAPE_GetMediaParams( fd
, (TAPE_GET_MEDIA_PARAMETERS
*)out_buffer
);
509 case IOCTL_TAPE_GET_POSITION
:
510 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
511 (TAPE_GET_POSITION
*)out_buffer
);
513 case IOCTL_TAPE_GET_STATUS
:
514 status
= FILE_GetNtStatus();
516 case IOCTL_TAPE_PREPARE
:
517 status
= TAPE_Prepare( fd
, (TAPE_PREPARE
*)in_buffer
);
519 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
520 status
= TAPE_SetDriveParams( fd
, (TAPE_SET_DRIVE_PARAMETERS
*)in_buffer
);
522 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
523 status
= TAPE_SetMediaParams( fd
, (TAPE_SET_MEDIA_PARAMETERS
*)in_buffer
);
525 case IOCTL_TAPE_SET_POSITION
:
526 status
= TAPE_SetPosition( fd
, (TAPE_SET_POSITION
*)in_buffer
);
528 case IOCTL_TAPE_WRITE_MARKS
:
529 status
= TAPE_WriteMarks( fd
, (TAPE_WRITE_MARKS
*)in_buffer
);
532 case IOCTL_TAPE_CHECK_VERIFY
:
533 case IOCTL_TAPE_FIND_NEW_DEVICES
:
536 FIXME( "Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
537 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
538 (io_control
>> 2) & 0xfff, io_control
& 3 );
542 wine_server_release_fd( device
, fd
);
545 io_status
->u
.Status
= status
;
546 io_status
->Information
= sz
;
547 if (event
) NtSetEvent( event
, NULL
);