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
32 #include <sys/types.h>
34 #include <sys/ioctl.h>
35 #ifdef HAVE_SYS_MTIO_H
39 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
40 #define MTCOMPRESSION MTCOMP
42 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
43 #define MTSETBLK MTSETBSIZ
45 #if !defined(MTSETBLK) && defined(MTSRSZ)
46 #define MTSETBLK MTSRSZ
48 #ifndef MT_ST_BLKSIZE_MASK
49 #define MT_ST_BLKSIZE_MASK 0xffffff
51 /* Darwin 7.9.0 has MTSETBSIZ instead of MTSETBLK */
52 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
53 #define MTSETBLK MTSETBSIZ
57 #define WIN32_NO_STATUS
61 #include "ddk/ntddtape.h"
62 #include "wine/server.h"
63 #include "unix_private.h"
64 #include "wine/debug.h"
66 WINE_DEFAULT_DEBUG_CHANNEL(tape
);
68 static const char *io2str( unsigned int io
)
72 #define X(x) case (x): return #x
73 X(IOCTL_TAPE_CHECK_VERIFY
);
74 X(IOCTL_TAPE_CREATE_PARTITION
);
76 X(IOCTL_TAPE_FIND_NEW_DEVICES
);
77 X(IOCTL_TAPE_GET_DRIVE_PARAMS
);
78 X(IOCTL_TAPE_GET_MEDIA_PARAMS
);
79 X(IOCTL_TAPE_GET_POSITION
);
80 X(IOCTL_TAPE_GET_STATUS
);
81 X(IOCTL_TAPE_PREPARE
);
82 X(IOCTL_TAPE_SET_DRIVE_PARAMS
);
83 X(IOCTL_TAPE_SET_MEDIA_PARAMS
);
84 X(IOCTL_TAPE_SET_POSITION
);
85 X(IOCTL_TAPE_WRITE_MARKS
);
87 default: { static char tmp
[32]; sprintf(tmp
, "IOCTL_TAPE_%d\n", io
); return tmp
; }
91 /******************************************************************
94 #ifdef HAVE_SYS_MTIO_H
95 static inline NTSTATUS
TAPE_GetStatus( int error
)
97 if (!error
) return STATUS_SUCCESS
;
98 return errno_to_status( errno
);
102 /******************************************************************
103 * TAPE_CreatePartition
105 static NTSTATUS
TAPE_CreatePartition( int fd
, const TAPE_CREATE_PARTITION
*data
)
107 #ifdef HAVE_SYS_MTIO_H
110 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
111 fd
, (int)data
->Method
, (int)data
->Count
, (int)data
->Size
);
115 WARN( "Creating more than 1 partition is not supported\n" );
116 return STATUS_INVALID_PARAMETER
;
119 switch (data
->Method
)
122 case TAPE_FIXED_PARTITIONS
:
123 case TAPE_SELECT_PARTITIONS
:
124 cmd
.mt_op
= MTMKPART
;
127 case TAPE_INITIATOR_PARTITIONS
:
128 cmd
.mt_op
= MTMKPART
;
129 cmd
.mt_count
= data
->Size
;
133 ERR( "Unhandled method: 0x%08x\n", (int)data
->Method
);
134 return STATUS_INVALID_PARAMETER
;
137 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
139 FIXME( "Not implemented.\n" );
140 return STATUS_NOT_SUPPORTED
;
144 /******************************************************************
147 static NTSTATUS
TAPE_Erase( int fd
, const TAPE_ERASE
*data
)
149 #ifdef HAVE_SYS_MTIO_H
152 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
153 fd
, (int)data
->Type
, (int)data
->Immediate
);
157 case TAPE_ERASE_LONG
:
161 case TAPE_ERASE_SHORT
:
166 ERR( "Unhandled type: 0x%08x\n", (int)data
->Type
);
167 return STATUS_INVALID_PARAMETER
;
170 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
172 FIXME( "Not implemented.\n" );
173 return STATUS_NOT_SUPPORTED
;
177 /******************************************************************
178 * TAPE_GetDriveParams
180 static NTSTATUS
TAPE_GetDriveParams( int fd
, TAPE_GET_DRIVE_PARAMETERS
*data
)
182 #ifdef HAVE_SYS_MTIO_H
186 TRACE( "fd: %d\n", fd
);
188 memset( data
, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS
) );
190 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
191 if (status
!= STATUS_SUCCESS
)
195 data
->Compression
= FALSE
;
196 data
->DataPadding
= FALSE
;
197 data
->ReportSetmarks
= FALSE
;
198 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
199 data
->DefaultBlockSize
= get
.mt_blksiz
;
201 data
->DefaultBlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
203 data
->MaximumBlockSize
= data
->DefaultBlockSize
;
204 data
->MinimumBlockSize
= data
->DefaultBlockSize
;
205 data
->MaximumPartitionCount
= 1;
209 FIXME( "Not implemented.\n" );
210 return STATUS_NOT_SUPPORTED
;
214 /******************************************************************
215 * TAPE_GetMediaParams
217 static NTSTATUS
TAPE_GetMediaParams( int fd
, TAPE_GET_MEDIA_PARAMETERS
*data
)
219 #ifdef HAVE_SYS_MTIO_H
223 TRACE( "fd: %d\n", fd
);
225 memset( data
, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS
) );
227 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
228 if (status
!= STATUS_SUCCESS
)
231 data
->Capacity
.QuadPart
= 1024 * 1024 * 1024;
232 data
->Remaining
.QuadPart
= 1024 * 1024 * 1024;
233 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
234 data
->BlockSize
= get
.mt_blksiz
;
236 data
->BlockSize
= get
.mt_dsreg
& MT_ST_BLKSIZE_MASK
;
238 data
->PartitionCount
= 1;
239 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
240 data
->WriteProtected
= (GMT_WR_PROT(get
.mt_gstat
) != 0);
242 data
->WriteProtected
= 0;
247 FIXME( "Not implemented.\n" );
248 return STATUS_NOT_SUPPORTED
;
252 /******************************************************************
255 static NTSTATUS
TAPE_GetPosition( int fd
, UINT type
, TAPE_GET_POSITION
*data
)
257 #ifdef HAVE_SYS_MTIO_H
259 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
264 TRACE( "fd: %d type: 0x%08x\n", fd
, type
);
266 memset( data
, 0, sizeof(TAPE_GET_POSITION
) );
268 status
= TAPE_GetStatus( ioctl( fd
, MTIOCGET
, &get
) );
269 if (status
!= STATUS_SUCCESS
)
272 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
273 status
= TAPE_GetStatus( ioctl( fd
, MTIOCPOS
, &pos
) );
274 if (status
!= STATUS_SUCCESS
)
280 case TAPE_ABSOLUTE_BLOCK
:
282 data
->Partition
= get
.mt_resid
;
283 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
284 data
->OffsetLow
= get
.mt_blkno
;
286 data
->OffsetLow
= pos
.mt_blkno
;
289 case TAPE_LOGICAL_BLOCK
:
290 case TAPE_PSEUDO_LOGICAL_BLOCK
:
291 WARN( "Positioning type not supported\n" );
294 ERR( "Unhandled type: 0x%08x\n", type
);
295 return STATUS_INVALID_PARAMETER
;
300 FIXME( "Not implemented.\n" );
301 return STATUS_NOT_SUPPORTED
;
305 /******************************************************************
308 static NTSTATUS
TAPE_Prepare( int fd
, const TAPE_PREPARE
*data
)
310 #ifdef HAVE_SYS_MTIO_H
313 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
314 fd
, (int)data
->Operation
, (int)data
->Immediate
);
316 switch (data
->Operation
)
325 cmd
.mt_op
= MTUNLOAD
;
340 cmd
.mt_op
= MTUNLOCK
;
344 /* Native ignores this if the drive doesn't support it */
345 return STATUS_SUCCESS
;
347 ERR( "Unhandled operation: 0x%08x\n", (int)data
->Operation
);
348 return STATUS_INVALID_PARAMETER
;
351 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
353 FIXME( "Not implemented.\n" );
354 return STATUS_NOT_SUPPORTED
;
358 /******************************************************************
359 * TAPE_SetDriveParams
361 static NTSTATUS
TAPE_SetDriveParams( int fd
, const TAPE_SET_DRIVE_PARAMETERS
*data
)
363 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
366 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
367 fd
, data
->ECC
, data
->Compression
, data
->DataPadding
);
368 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
369 (int)data
->ReportSetmarks
, (int)data
->EOTWarningZoneSize
);
371 if (data
->ECC
|| data
->DataPadding
|| data
->ReportSetmarks
||
372 data
->EOTWarningZoneSize
) WARN( "Setting not supported\n" );
374 cmd
.mt_op
= MTCOMPRESSION
;
375 cmd
.mt_count
= data
->Compression
;
377 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
379 FIXME( "Not implemented.\n" );
380 return STATUS_NOT_SUPPORTED
;
384 /******************************************************************
385 * TAPE_SetMediaParams
387 static NTSTATUS
TAPE_SetMediaParams( int fd
, const TAPE_SET_MEDIA_PARAMETERS
*data
)
389 #ifdef HAVE_SYS_MTIO_H
392 TRACE( "fd: %d blocksize: 0x%08x\n", fd
, (int)data
->BlockSize
);
394 cmd
.mt_op
= MTSETBLK
;
395 cmd
.mt_count
= data
->BlockSize
;
397 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
399 FIXME( "Not implemented.\n" );
400 return STATUS_NOT_SUPPORTED
;
404 /******************************************************************
407 static NTSTATUS
TAPE_SetPosition( int fd
, const TAPE_SET_POSITION
*data
)
409 #ifdef HAVE_SYS_MTIO_H
412 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%s immediate: 0x%02x\n",
413 fd
, (int)data
->Method
, (int)data
->Partition
, wine_dbgstr_longlong(data
->Offset
.QuadPart
),
416 if (sizeof(cmd
.mt_count
) < sizeof(data
->Offset
.QuadPart
) &&
417 (int)data
->Offset
.QuadPart
!= data
->Offset
.QuadPart
)
419 ERR("Offset too large or too small\n");
420 return STATUS_INVALID_PARAMETER
;
423 switch (data
->Method
)
429 case TAPE_ABSOLUTE_BLOCK
:
431 cmd
.mt_count
= data
->Offset
.QuadPart
;
435 case TAPE_SPACE_END_OF_DATA
:
439 case TAPE_SPACE_FILEMARKS
:
440 if (data
->Offset
.QuadPart
>= 0) {
442 cmd
.mt_count
= data
->Offset
.QuadPart
;
446 cmd
.mt_count
= -data
->Offset
.QuadPart
;
449 #if defined(MTFSS) && defined(MTBSS)
450 case TAPE_SPACE_SETMARKS
:
451 if (data
->Offset
.QuadPart
>= 0) {
453 cmd
.mt_count
= data
->Offset
.QuadPart
;
457 cmd
.mt_count
= -data
->Offset
.QuadPart
;
461 case TAPE_LOGICAL_BLOCK
:
462 case TAPE_PSEUDO_LOGICAL_BLOCK
:
463 case TAPE_SPACE_RELATIVE_BLOCKS
:
464 case TAPE_SPACE_SEQUENTIAL_FMKS
:
465 case TAPE_SPACE_SEQUENTIAL_SMKS
:
466 WARN( "Positioning method not supported\n" );
467 return STATUS_INVALID_PARAMETER
;
469 ERR( "Unhandled method: 0x%08x\n", (int)data
->Method
);
470 return STATUS_INVALID_PARAMETER
;
473 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
475 FIXME( "Not implemented.\n" );
476 return STATUS_NOT_SUPPORTED
;
480 /******************************************************************
483 static NTSTATUS
TAPE_WriteMarks( int fd
, const TAPE_WRITE_MARKS
*data
)
485 #ifdef HAVE_SYS_MTIO_H
488 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
489 fd
, (int)data
->Type
, (int)data
->Count
, data
->Immediate
);
496 cmd
.mt_count
= data
->Count
;
500 case TAPE_SHORT_FILEMARKS
:
501 case TAPE_LONG_FILEMARKS
:
503 cmd
.mt_count
= data
->Count
;
506 ERR( "Unhandled type: 0x%08x\n", (int)data
->Type
);
507 return STATUS_INVALID_PARAMETER
;
510 return TAPE_GetStatus( ioctl( fd
, MTIOCTOP
, &cmd
) );
512 FIXME( "Not implemented.\n" );
513 return STATUS_NOT_SUPPORTED
;
517 /******************************************************************
518 * tape_DeviceIoControl
520 NTSTATUS
tape_DeviceIoControl( HANDLE device
, HANDLE event
, PIO_APC_ROUTINE apc
, void *apc_user
,
521 IO_STATUS_BLOCK
*io
, UINT code
,
522 void *in_buffer
, UINT in_size
, void *out_buffer
, UINT out_size
)
525 NTSTATUS status
= STATUS_INVALID_PARAMETER
;
528 TRACE( "%p %s %p %d %p %d %p\n", device
, io2str(code
),
529 in_buffer
, in_size
, out_buffer
, out_size
, io
);
533 if ((status
= server_get_unix_fd( device
, 0, &fd
, &needs_close
, NULL
, NULL
))) goto error
;
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
= errno_to_status( errno
);
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 code
, code
>> 16, (code
>> 14) & 3, (code
>> 2) & 0xfff, code
& 3 );
581 if (needs_close
) close( fd
);
585 io
->Information
= sz
;
586 if (event
) NtSetEvent( event
, NULL
);