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 #define NONAMELESSUNION
34 #define NONAMELESSSTRUCT
36 #define WIN32_NO_STATUS
40 #include "ddk/ntddtape.h"
41 #include "ntdll_misc.h"
42 #include "wine/server.h"
43 #include "wine/debug.h"
45 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
47 static const char *io2str( DWORD io
)
51 #define X(x) case (x): return #x;
52 X(IOCTL_TAPE_CHECK_VERIFY
);
53 X(IOCTL_TAPE_CREATE_PARTITION
);
55 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
56 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
57 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
58 X(IOCTL_TAPE_GET_POSITION
);
59 X(IOCTL_TAPE_GET_STATUS
);
60 X(IOCTL_TAPE_PREPARE
);
61 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
62 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
63 X(IOCTL_TAPE_SET_POSITION
);
64 X(IOCTL_TAPE_WRITE_MARKS
);
66 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%ld\n", io
); return tmp
; }
70 /******************************************************************
73 static NTSTATUS
TAPE_GetStatus( int error
)
75 if (!error
) return STATUS_SUCCESS
;
76 return FILE_GetNtStatus();
79 /******************************************************************
80 * TAPE_CreatePartition
82 static NTSTATUS
TAPE_CreatePartition( int fd
, TAPE_CREATE_PARTITION
*data
)
84 #ifdef HAVE_SYS_MTIO_H
87 TRACE( "fd: %d method: 0x%08lx count: 0x%08lx size: 0x%08lx\n",
88 fd
, data
->Method
, data
->Count
, data
->Size
);
92 WARN( "Creating more than 1 partition is not supported\n" );
93 return STATUS_INVALID_PARAMETER
;
98 case TAPE_FIXED_PARTITIONS
:
99 case TAPE_SELECT_PARTITIONS
:
100 cmd
.mt_op
= MTMKPART
;
103 case TAPE_INITIATOR_PARTITIONS
:
104 cmd
.mt_op
= MTMKPART
;
105 cmd
.mt_count
= data
->Size
;
108 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
109 return STATUS_INVALID_PARAMETER
;
112 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
114 FIXME( "Not implemented.\n" );
115 return STATUS_NOT_SUPPORTED
;
119 /******************************************************************
122 static NTSTATUS
TAPE_Erase( int fd
, TAPE_ERASE
*data
)
124 #ifdef HAVE_SYS_MTIO_H
127 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
128 fd
, data
->Type
, data
->Immediate
);
132 case TAPE_ERASE_LONG
:
136 case TAPE_ERASE_SHORT
:
141 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
142 return STATUS_INVALID_PARAMETER
;
145 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
147 FIXME( "Not implemented.\n" );
148 return STATUS_NOT_SUPPORTED
;
152 /******************************************************************
153 * TAPE_GetDriveParams
155 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
157 #ifdef HAVE_SYS_MTIO_H
161 TRACE( "fd: %d\n", fd
);
163 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
165 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
166 if (status
!= STATUS_SUCCESS
)
170 data
->Compression
= FALSE
;
171 data
->DataPadding
= FALSE
;
172 data
->ReportSetmarks
= FALSE
;
173 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
174 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
175 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
176 data
->MaximumPartitionCount
= 1;
180 FIXME( "Not implemented.\n" );
181 return STATUS_NOT_SUPPORTED
;
185 /******************************************************************
186 * TAPE_GetMediaParams
188 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
190 #ifdef HAVE_SYS_MTIO_H
194 TRACE( "fd: %d\n", fd
);
196 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
198 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
199 if (status
!= STATUS_SUCCESS
)
202 data
->Capacity
.u
.LowPart
= 1024 * 1024 * 1024;
203 data
->Remaining
.u
.LowPart
= 1024 * 1024 * 1024;
204 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
205 data
->PartitionCount
= 1;
206 data
->WriteProtected
= GMT_WR_PROT(get
.mt_gstat
);
210 FIXME( "Not implemented.\n" );
211 return STATUS_NOT_SUPPORTED
;
215 /******************************************************************
218 static NTSTATUS
TAPE_GetPosition( int fd
, ULONG type
, TAPE_GET_POSITION
*data
)
220 #ifdef HAVE_SYS_MTIO_H
225 TRACE( "fd: %d type: 0x%08lx\n", fd
, type
);
227 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
229 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
230 if (status
!= STATUS_SUCCESS
)
233 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
234 if (status
!= STATUS_SUCCESS
)
239 case TAPE_ABSOLUTE_BLOCK
:
241 data
->Partition
= get
.mt_resid
;
242 data
->OffsetLow
= pos
.mt_blkno
;
243 case TAPE_LOGICAL_BLOCK
:
244 case TAPE_PSEUDO_LOGICAL_BLOCK
:
245 WARN( "Positioning type not supported\n" );
248 ERR( "Unhandled type: 0x%08lx\n", type
);
249 return STATUS_INVALID_PARAMETER
;
254 FIXME( "Not implemented.\n" );
255 return STATUS_NOT_SUPPORTED
;
259 /******************************************************************
262 static NTSTATUS
TAPE_Prepare( int fd
, TAPE_PREPARE
*data
)
264 #ifdef HAVE_SYS_MTIO_H
267 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
268 fd
, data
->Operation
, data
->Immediate
);
270 switch (data
->Operation
)
276 cmd
.mt_op
= MTUNLOAD
;
285 cmd
.mt_op
= MTUNLOCK
;
288 /* Native ignores this if the drive doesn't support it */
289 return STATUS_SUCCESS
;
291 ERR( "Unhandled operation: 0x%08lx\n", data
->Operation
);
292 return STATUS_INVALID_PARAMETER
;
295 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
297 FIXME( "Not implemented.\n" );
298 return STATUS_NOT_SUPPORTED
;
302 /******************************************************************
303 * TAPE_SetDriveParams
305 static NTSTATUS
TAPE_SetDriveParams( int fd
, TAPE_SET_DRIVE_PARAMETERS
*data
)
307 #ifdef HAVE_SYS_MTIO_H
310 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
311 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
312 TRACE( "setmarks: 0x%02x zonesize: 0x%08lx\n",
313 data
->ReportSetmarks
, data
->EOTWarningZoneSize
);
315 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
316 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
318 cmd
.mt_op
= MTCOMPRESSION
;
319 cmd
.mt_count
= data
->Compression
;
321 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
323 FIXME( "Not implemented.\n" );
324 return STATUS_NOT_SUPPORTED
;
328 /******************************************************************
329 * TAPE_SetMediaParams
331 static NTSTATUS
TAPE_SetMediaParams( int fd
, TAPE_SET_MEDIA_PARAMETERS
*data
)
333 #ifdef HAVE_SYS_MTIO_H
336 TRACE( "fd: %d blocksize: 0x%08lx\n", fd
, data
->BlockSize
);
338 cmd
.mt_op
= MTSETBLK
;
339 cmd
.mt_count
= data
->BlockSize
;
341 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
343 FIXME( "Not implemented.\n" );
344 return STATUS_NOT_SUPPORTED
;
348 /******************************************************************
351 static NTSTATUS
TAPE_SetPosition( int fd
, TAPE_SET_POSITION
*data
)
353 #ifdef HAVE_SYS_MTIO_H
356 TRACE( "fd: %d method: 0x%08lx partition: 0x%08lx offset: 0x%08lx immediate: 0x%02x\n",
357 fd
, data
->Method
, data
->Partition
, data
->Offset
.u
.LowPart
, data
->Immediate
);
359 if (data
->Offset
.u
.HighPart
> 0)
360 return STATUS_INVALID_PARAMETER
;
362 switch (data
->Method
)
367 case TAPE_ABSOLUTE_BLOCK
:
369 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
371 case TAPE_SPACE_END_OF_DATA
:
374 case TAPE_SPACE_FILEMARKS
:
375 if (data
->Offset
.u
.LowPart
>= 0) {
377 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
381 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
383 case TAPE_SPACE_SETMARKS
:
384 if (data
->Offset
.u
.LowPart
>= 0) {
386 cmd
.mt_count
= data
->Offset
.u
.LowPart
;
390 cmd
.mt_count
= -data
->Offset
.u
.LowPart
;
392 case TAPE_LOGICAL_BLOCK
:
393 case TAPE_PSEUDO_LOGICAL_BLOCK
:
394 case TAPE_SPACE_RELATIVE_BLOCKS
:
395 case TAPE_SPACE_SEQUENTIAL_FMKS
:
396 case TAPE_SPACE_SEQUENTIAL_SMKS
:
397 WARN( "Positioning method not supported\n" );
398 return STATUS_INVALID_PARAMETER
;
400 ERR( "Unhandled method: 0x%08lx\n", data
->Method
);
401 return STATUS_INVALID_PARAMETER
;
404 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
406 FIXME( "Not implemented.\n" );
407 return STATUS_NOT_SUPPORTED
;
411 /******************************************************************
414 static NTSTATUS
TAPE_WriteMarks( int fd
, TAPE_WRITE_MARKS
*data
)
416 #ifdef HAVE_SYS_MTIO_H
419 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
420 fd
, data
->Type
, data
->Count
, data
->Immediate
);
426 cmd
.mt_count
= data
->Count
;
429 case TAPE_SHORT_FILEMARKS
:
430 case TAPE_LONG_FILEMARKS
:
432 cmd
.mt_count
= data
->Count
;
435 ERR( "Unhandled type: 0x%08lx\n", data
->Type
);
436 return STATUS_INVALID_PARAMETER
;
439 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
441 FIXME( "Not implemented.\n" );
442 return STATUS_NOT_SUPPORTED
;
446 /******************************************************************
447 * TAPE_DeviceIoControl
452 NTSTATUS
TAPE_DeviceIoControl( HANDLE device
, HANDLE event
,
453 PIO_APC_ROUTINE apc
, PVOID apc_user
, PIO_STATUS_BLOCK io_status
,
454 ULONG io_control
, LPVOID in_buffer
, DWORD in_size
,
455 LPVOID out_buffer
, DWORD out_size
)
458 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
461 TRACE( "%p %s %p %ld %p %ld %p\n", device
, io2str(io_control
),
462 in_buffer
, in_size
, out_buffer
, out_size
, io_status
);
464 io_status
->Information
= 0;
466 if ((status
= wine_server_handle_to_fd( device
, 0, &fd
, NULL
)))
471 case IOCTL_TAPE_CREATE_PARTITION
:
472 status
= TAPE_CreatePartition( fd
, (TAPE_CREATE_PARTITION
*)in_buffer
);
474 case IOCTL_TAPE_ERASE
:
475 status
= TAPE_Erase( fd
, (TAPE_ERASE
*)in_buffer
);
477 case IOCTL_TAPE_GET_DRIVE_PARAMS
:
478 status
= TAPE_GetDriveParams( fd
, (TAPE_GET_DRIVE_PARAMETERS
*)out_buffer
);
480 case IOCTL_TAPE_GET_MEDIA_PARAMS
:
481 status
= TAPE_GetMediaParams( fd
, (TAPE_GET_MEDIA_PARAMETERS
*)out_buffer
);
483 case IOCTL_TAPE_GET_POSITION
:
484 status
= TAPE_GetPosition( fd
, ((TAPE_GET_POSITION
*)in_buffer
)->Type
,
485 (TAPE_GET_POSITION
*)out_buffer
);
487 case IOCTL_TAPE_GET_STATUS
:
488 status
= FILE_GetNtStatus();
490 case IOCTL_TAPE_PREPARE
:
491 status
= TAPE_Prepare( fd
, (TAPE_PREPARE
*)in_buffer
);
493 case IOCTL_TAPE_SET_DRIVE_PARAMS
:
494 status
= TAPE_SetDriveParams( fd
, (TAPE_SET_DRIVE_PARAMETERS
*)in_buffer
);
496 case IOCTL_TAPE_SET_MEDIA_PARAMS
:
497 status
= TAPE_SetMediaParams( fd
, (TAPE_SET_MEDIA_PARAMETERS
*)in_buffer
);
499 case IOCTL_TAPE_SET_POSITION
:
500 status
= TAPE_SetPosition( fd
, (TAPE_SET_POSITION
*)in_buffer
);
502 case IOCTL_TAPE_WRITE_MARKS
:
503 status
= TAPE_WriteMarks( fd
, (TAPE_WRITE_MARKS
*)in_buffer
);
506 case IOCTL_TAPE_CHECK_VERIFY
:
507 case IOCTL_TAPE_FIND_NEW_DEVICES
:
510 FIXME( "Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
511 io_control
, io_control
>> 16, (io_control
>> 14) & 3,
512 (io_control
>> 2) & 0xfff, io_control
& 3 );
516 wine_server_release_fd( device
, fd
);
519 io_status
->u
.Status
= status
;
520 io_status
->Information
= sz
;
521 if (event
) NtSetEvent( event
, NULL
);