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 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
181 data->DefaultBlockSize = get.mt_blksiz;
183 data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
185 data->MaximumBlockSize = data->DefaultBlockSize;
186 data->MinimumBlockSize = data->DefaultBlockSize;
187 data->MaximumPartitionCount = 1;
191 FIXME( "Not implemented.\n" );
192 return STATUS_NOT_SUPPORTED;
196 /******************************************************************
197 * TAPE_GetMediaParams
199 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
201 #ifdef HAVE_SYS_MTIO_H
205 TRACE( "fd: %d\n", fd );
207 memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
209 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
210 if (status != STATUS_SUCCESS)
213 data->Capacity.u.LowPart = 1024 * 1024 * 1024;
214 data->Remaining.u.LowPart = 1024 * 1024 * 1024;
215 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
216 data->BlockSize = get.mt_blksiz;
218 data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
220 data->PartitionCount = 1;
221 #ifdef HAVE_STRUCT_MTGET_GSTAT
222 data->WriteProtected = GMT_WR_PROT(get.mt_gstat);
224 data->WriteProtected = 0;
229 FIXME( "Not implemented.\n" );
230 return STATUS_NOT_SUPPORTED;
234 /******************************************************************
237 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
239 #ifdef HAVE_SYS_MTIO_H
244 TRACE( "fd: %d type: 0x%08lx\n", fd, type );
246 memset( data, 0, sizeof(TAPE_GET_POSITION) );
248 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
249 if (status != STATUS_SUCCESS)
252 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
253 if (status != STATUS_SUCCESS)
258 case TAPE_ABSOLUTE_BLOCK:
260 data->Partition = get.mt_resid;
261 data->OffsetLow = pos.mt_blkno;
263 case TAPE_LOGICAL_BLOCK:
264 case TAPE_PSEUDO_LOGICAL_BLOCK:
265 WARN( "Positioning type not supported\n" );
268 ERR( "Unhandled type: 0x%08lx\n", type );
269 return STATUS_INVALID_PARAMETER;
274 FIXME( "Not implemented.\n" );
275 return STATUS_NOT_SUPPORTED;
279 /******************************************************************
282 static NTSTATUS TAPE_Prepare( int fd, TAPE_PREPARE *data )
284 #ifdef HAVE_SYS_MTIO_H
287 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
288 fd, data->Operation, data->Immediate );
290 switch (data->Operation)
299 cmd.mt_op = MTUNLOAD;
314 cmd.mt_op = MTUNLOCK;
318 /* Native ignores this if the drive doesn't support it */
319 return STATUS_SUCCESS;
321 ERR( "Unhandled operation: 0x%08lx\n", data->Operation );
322 return STATUS_INVALID_PARAMETER;
325 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
327 FIXME( "Not implemented.\n" );
328 return STATUS_NOT_SUPPORTED;
332 /******************************************************************
333 * TAPE_SetDriveParams
335 static NTSTATUS TAPE_SetDriveParams( int fd, TAPE_SET_DRIVE_PARAMETERS *data )
337 #ifdef HAVE_SYS_MTIO_H
340 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
341 fd, data->ECC, data->Compression, data->DataPadding );
342 TRACE( "setmarks: 0x%02x zonesize: 0x%08lx\n",
343 data->ReportSetmarks, data->EOTWarningZoneSize );
345 if (data->ECC || data->DataPadding || data->ReportSetmarks ||
346 data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
348 cmd.mt_op = MTCOMPRESSION;
349 cmd.mt_count = data->Compression;
351 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
353 FIXME( "Not implemented.\n" );
354 return STATUS_NOT_SUPPORTED;
358 /******************************************************************
359 * TAPE_SetMediaParams
361 static NTSTATUS TAPE_SetMediaParams( int fd, TAPE_SET_MEDIA_PARAMETERS *data )
363 #ifdef HAVE_SYS_MTIO_H
366 TRACE( "fd: %d blocksize: 0x%08lx\n", fd, data->BlockSize );
368 cmd.mt_op = MTSETBLK;
369 cmd.mt_count = data->BlockSize;
371 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
373 FIXME( "Not implemented.\n" );
374 return STATUS_NOT_SUPPORTED;
378 /******************************************************************
381 static NTSTATUS TAPE_SetPosition( int fd, TAPE_SET_POSITION *data )
383 #ifdef HAVE_SYS_MTIO_H
386 TRACE( "fd: %d method: 0x%08lx partition: 0x%08lx offset: 0x%08lx immediate: 0x%02x\n",
387 fd, data->Method, data->Partition, data->Offset.u.LowPart, data->Immediate );
389 if (data->Offset.u.HighPart > 0)
390 return STATUS_INVALID_PARAMETER;
392 switch (data->Method)
398 case TAPE_ABSOLUTE_BLOCK:
400 cmd.mt_count = data->Offset.u.LowPart;
404 case TAPE_SPACE_END_OF_DATA:
408 case TAPE_SPACE_FILEMARKS:
409 if (data->Offset.u.LowPart >= 0) {
411 cmd.mt_count = data->Offset.u.LowPart;
415 cmd.mt_count = -data->Offset.u.LowPart;
418 case TAPE_SPACE_SETMARKS:
419 if (data->Offset.u.LowPart >= 0) {
421 cmd.mt_count = data->Offset.u.LowPart;
425 cmd.mt_count = -data->Offset.u.LowPart;
428 case TAPE_LOGICAL_BLOCK:
429 case TAPE_PSEUDO_LOGICAL_BLOCK:
430 case TAPE_SPACE_RELATIVE_BLOCKS:
431 case TAPE_SPACE_SEQUENTIAL_FMKS:
432 case TAPE_SPACE_SEQUENTIAL_SMKS:
433 WARN( "Positioning method not supported\n" );
434 return STATUS_INVALID_PARAMETER;
436 ERR( "Unhandled method: 0x%08lx\n", data->Method );
437 return STATUS_INVALID_PARAMETER;
440 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
442 FIXME( "Not implemented.\n" );
443 return STATUS_NOT_SUPPORTED;
447 /******************************************************************
450 static NTSTATUS TAPE_WriteMarks( int fd, TAPE_WRITE_MARKS *data )
452 #ifdef HAVE_SYS_MTIO_H
455 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
456 fd, data->Type, data->Count, data->Immediate );
463 cmd.mt_count = data->Count;
467 case TAPE_SHORT_FILEMARKS:
468 case TAPE_LONG_FILEMARKS:
470 cmd.mt_count = data->Count;
473 ERR( "Unhandled type: 0x%08lx\n", data->Type );
474 return STATUS_INVALID_PARAMETER;
477 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
479 FIXME( "Not implemented.\n" );
480 return STATUS_NOT_SUPPORTED;
484 /******************************************************************
485 * TAPE_DeviceIoControl
490 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
491 PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
492 ULONG io_control, LPVOID in_buffer, DWORD in_size,
493 LPVOID out_buffer, DWORD out_size )
496 NTSTATUS status = STATUS_INVALID_PARAMETER;
499 TRACE( "%p %s %p %ld %p %ld %p\n", device, io2str(io_control),
500 in_buffer, in_size, out_buffer, out_size, io_status );
502 io_status->Information = 0;
504 if ((status = wine_server_handle_to_fd( device, 0, &fd, NULL )))
509 case IOCTL_TAPE_CREATE_PARTITION:
510 status = TAPE_CreatePartition( fd, (TAPE_CREATE_PARTITION *)in_buffer );
512 case IOCTL_TAPE_ERASE:
513 status = TAPE_Erase( fd, (TAPE_ERASE *)in_buffer );
515 case IOCTL_TAPE_GET_DRIVE_PARAMS:
516 status = TAPE_GetDriveParams( fd, (TAPE_GET_DRIVE_PARAMETERS *)out_buffer );
518 case IOCTL_TAPE_GET_MEDIA_PARAMS:
519 status = TAPE_GetMediaParams( fd, (TAPE_GET_MEDIA_PARAMETERS *)out_buffer );
521 case IOCTL_TAPE_GET_POSITION:
522 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
523 (TAPE_GET_POSITION *)out_buffer );
525 case IOCTL_TAPE_GET_STATUS:
526 status = FILE_GetNtStatus();
528 case IOCTL_TAPE_PREPARE:
529 status = TAPE_Prepare( fd, (TAPE_PREPARE *)in_buffer );
531 case IOCTL_TAPE_SET_DRIVE_PARAMS:
532 status = TAPE_SetDriveParams( fd, (TAPE_SET_DRIVE_PARAMETERS *)in_buffer );
534 case IOCTL_TAPE_SET_MEDIA_PARAMS:
535 status = TAPE_SetMediaParams( fd, (TAPE_SET_MEDIA_PARAMETERS *)in_buffer );
537 case IOCTL_TAPE_SET_POSITION:
538 status = TAPE_SetPosition( fd, (TAPE_SET_POSITION *)in_buffer );
540 case IOCTL_TAPE_WRITE_MARKS:
541 status = TAPE_WriteMarks( fd, (TAPE_WRITE_MARKS *)in_buffer );
544 case IOCTL_TAPE_CHECK_VERIFY:
545 case IOCTL_TAPE_FIND_NEW_DEVICES:
548 FIXME( "Unsupported IOCTL %lx (type=%lx access=%lx func=%lx meth=%lx)\n",
549 io_control, io_control >> 16, (io_control >> 14) & 3,
550 (io_control >> 2) & 0xfff, io_control & 3 );
554 wine_server_release_fd( device, fd );
557 io_status->u.Status = status;
558 io_status->Information = sz;
559 if (event) NtSetEvent( event, NULL );