Enable for GNU/kFreeBSD the same kernel-specific interface/parameter
[wine/testsucceed.git] / dlls / ntdll / tape.c
blob41d413171a4bff03aaa50f6f6578bc4c4abf1371
1 /*
2 * TAPE support
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
21 #include "config.h"
22 #include "wine/port.h"
24 #include <stdarg.h>
25 #include <stdio.h>
26 #ifdef HAVE_SYS_IOCTL_H
27 #include <sys/ioctl.h>
28 #endif
29 #ifdef HAVE_SYS_MTIO_H
30 #include <sys/mtio.h>
31 #endif
33 /* FreeBSD, for example, has MTCOMP instead of MTCOMPRESSION. */
34 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
35 #define MTCOMPRESSION MTCOMP
36 #endif
38 #define NONAMELESSUNION
39 #define NONAMELESSSTRUCT
40 #include "ntstatus.h"
41 #define WIN32_NO_STATUS
42 #include "windef.h"
43 #include "winternl.h"
44 #include "winioctl.h"
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 )
54 switch (io)
56 #define X(x) case (x): return #x;
57 X(IOCTL_TAPE_CHECK_VERIFY);
58 X(IOCTL_TAPE_CREATE_PARTITION);
59 X(IOCTL_TAPE_ERASE);
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);
70 #undef X
71 default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%ld\n", io); return tmp; }
75 /******************************************************************
76 * TAPE_GetStatus
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
90 struct mtop cmd;
92 TRACE( "fd: %d method: 0x%08lx count: 0x%08lx size: 0x%08lx\n",
93 fd, data->Method, data->Count, data->Size );
95 if (data->Count > 1)
97 WARN( "Creating more than 1 partition is not supported\n" );
98 return STATUS_INVALID_PARAMETER;
101 switch (data->Method)
103 #ifdef MTMKPART
104 case TAPE_FIXED_PARTITIONS:
105 case TAPE_SELECT_PARTITIONS:
106 cmd.mt_op = MTMKPART;
107 cmd.mt_count = 0;
108 break;
109 case TAPE_INITIATOR_PARTITIONS:
110 cmd.mt_op = MTMKPART;
111 cmd.mt_count = data->Size;
112 break;
113 #endif
114 default:
115 ERR( "Unhandled method: 0x%08lx\n", data->Method );
116 return STATUS_INVALID_PARAMETER;
119 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
120 #else
121 FIXME( "Not implemented.\n" );
122 return STATUS_NOT_SUPPORTED;
123 #endif
126 /******************************************************************
127 * TAPE_Erase
129 static NTSTATUS TAPE_Erase( int fd, TAPE_ERASE *data )
131 #ifdef HAVE_SYS_MTIO_H
132 struct mtop cmd;
134 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
135 fd, data->Type, data->Immediate );
137 switch (data->Type)
139 case TAPE_ERASE_LONG:
140 cmd.mt_op = MTERASE;
141 cmd.mt_count = 1;
142 break;
143 case TAPE_ERASE_SHORT:
144 cmd.mt_op = MTERASE;
145 cmd.mt_count = 0;
146 break;
147 default:
148 ERR( "Unhandled type: 0x%08lx\n", data->Type );
149 return STATUS_INVALID_PARAMETER;
152 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
153 #else
154 FIXME( "Not implemented.\n" );
155 return STATUS_NOT_SUPPORTED;
156 #endif
159 /******************************************************************
160 * TAPE_GetDriveParams
162 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
164 #ifdef HAVE_SYS_MTIO_H
165 struct mtget get;
166 NTSTATUS status;
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)
174 return status;
176 data->ECC = FALSE;
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;
185 return status;
186 #else
187 FIXME( "Not implemented.\n" );
188 return STATUS_NOT_SUPPORTED;
189 #endif
192 /******************************************************************
193 * TAPE_GetMediaParams
195 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
197 #ifdef HAVE_SYS_MTIO_H
198 struct mtget get;
199 NTSTATUS status;
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)
207 return status;
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);
215 return status;
216 #else
217 FIXME( "Not implemented.\n" );
218 return STATUS_NOT_SUPPORTED;
219 #endif
222 /******************************************************************
223 * TAPE_GetPosition
225 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
227 #ifdef HAVE_SYS_MTIO_H
228 struct mtget get;
229 struct mtpos pos;
230 NTSTATUS status;
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)
238 return status;
240 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
241 if (status != STATUS_SUCCESS)
242 return status;
244 switch (type)
246 case TAPE_ABSOLUTE_BLOCK:
247 data->Type = type;
248 data->Partition = get.mt_resid;
249 data->OffsetLow = pos.mt_blkno;
250 break;
251 case TAPE_LOGICAL_BLOCK:
252 case TAPE_PSEUDO_LOGICAL_BLOCK:
253 WARN( "Positioning type not supported\n" );
254 break;
255 default:
256 ERR( "Unhandled type: 0x%08lx\n", type );
257 return STATUS_INVALID_PARAMETER;
260 return status;
261 #else
262 FIXME( "Not implemented.\n" );
263 return STATUS_NOT_SUPPORTED;
264 #endif
267 /******************************************************************
268 * TAPE_Prepare
270 static NTSTATUS TAPE_Prepare( int fd, TAPE_PREPARE *data )
272 #ifdef HAVE_SYS_MTIO_H
273 struct mtop cmd;
275 TRACE( "fd: %d type: 0x%08lx immediate: 0x%02x\n",
276 fd, data->Operation, data->Immediate );
278 switch (data->Operation)
280 #ifdef MTLOAD
281 case TAPE_LOAD:
282 cmd.mt_op = MTLOAD;
283 break;
284 #endif
285 #ifdef MTUNLOAD
286 case TAPE_UNLOAD:
287 cmd.mt_op = MTUNLOAD;
288 break;
289 #endif
290 #ifdef MTRETEN
291 case TAPE_TENSION:
292 cmd.mt_op = MTRETEN;
293 break;
294 #endif
295 #ifdef MTLOCK
296 case TAPE_LOCK:
297 cmd.mt_op = MTLOCK;
298 break;
299 #endif
300 #ifdef MTUNLOCK
301 case TAPE_UNLOCK:
302 cmd.mt_op = MTUNLOCK;
303 break;
304 #endif
305 case TAPE_FORMAT:
306 /* Native ignores this if the drive doesn't support it */
307 return STATUS_SUCCESS;
308 default:
309 ERR( "Unhandled operation: 0x%08lx\n", data->Operation );
310 return STATUS_INVALID_PARAMETER;
313 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
314 #else
315 FIXME( "Not implemented.\n" );
316 return STATUS_NOT_SUPPORTED;
317 #endif
320 /******************************************************************
321 * TAPE_SetDriveParams
323 static NTSTATUS TAPE_SetDriveParams( int fd, TAPE_SET_DRIVE_PARAMETERS *data )
325 #ifdef HAVE_SYS_MTIO_H
326 struct mtop cmd;
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 ) );
340 #else
341 FIXME( "Not implemented.\n" );
342 return STATUS_NOT_SUPPORTED;
343 #endif
346 /******************************************************************
347 * TAPE_SetMediaParams
349 static NTSTATUS TAPE_SetMediaParams( int fd, TAPE_SET_MEDIA_PARAMETERS *data )
351 #ifdef HAVE_SYS_MTIO_H
352 struct mtop cmd;
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 ) );
360 #else
361 FIXME( "Not implemented.\n" );
362 return STATUS_NOT_SUPPORTED;
363 #endif
366 /******************************************************************
367 * TAPE_SetPosition
369 static NTSTATUS TAPE_SetPosition( int fd, TAPE_SET_POSITION *data )
371 #ifdef HAVE_SYS_MTIO_H
372 struct mtop cmd;
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)
382 case TAPE_REWIND:
383 cmd.mt_op = MTREW;
384 break;
385 #ifdef MTSEEK
386 case TAPE_ABSOLUTE_BLOCK:
387 cmd.mt_op = MTSEEK;
388 cmd.mt_count = data->Offset.u.LowPart;
389 break;
390 #endif
391 #ifdef MTEOM
392 case TAPE_SPACE_END_OF_DATA:
393 cmd.mt_op = MTEOM;
394 break;
395 #endif
396 case TAPE_SPACE_FILEMARKS:
397 if (data->Offset.u.LowPart >= 0) {
398 cmd.mt_op = MTFSF;
399 cmd.mt_count = data->Offset.u.LowPart;
401 else {
402 cmd.mt_op = MTBSF;
403 cmd.mt_count = -data->Offset.u.LowPart;
405 break;
406 case TAPE_SPACE_SETMARKS:
407 if (data->Offset.u.LowPart >= 0) {
408 cmd.mt_op = MTFSS;
409 cmd.mt_count = data->Offset.u.LowPart;
411 else {
412 cmd.mt_op = MTBSS;
413 cmd.mt_count = -data->Offset.u.LowPart;
415 break;
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;
423 default:
424 ERR( "Unhandled method: 0x%08lx\n", data->Method );
425 return STATUS_INVALID_PARAMETER;
428 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
429 #else
430 FIXME( "Not implemented.\n" );
431 return STATUS_NOT_SUPPORTED;
432 #endif
435 /******************************************************************
436 * TAPE_WriteMarks
438 static NTSTATUS TAPE_WriteMarks( int fd, TAPE_WRITE_MARKS *data )
440 #ifdef HAVE_SYS_MTIO_H
441 struct mtop cmd;
443 TRACE( "fd: %d type: 0x%08lx count: 0x%08lx immediate: 0x%02x\n",
444 fd, data->Type, data->Count, data->Immediate );
446 switch (data->Type)
448 #ifdef MTWSM
449 case TAPE_SETMARKS:
450 cmd.mt_op = MTWSM;
451 cmd.mt_count = data->Count;
452 break;
453 #endif
454 case TAPE_FILEMARKS:
455 case TAPE_SHORT_FILEMARKS:
456 case TAPE_LONG_FILEMARKS:
457 cmd.mt_op = MTWEOF;
458 cmd.mt_count = data->Count;
459 break;
460 default:
461 ERR( "Unhandled type: 0x%08lx\n", data->Type );
462 return STATUS_INVALID_PARAMETER;
465 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
466 #else
467 FIXME( "Not implemented.\n" );
468 return STATUS_NOT_SUPPORTED;
469 #endif
472 /******************************************************************
473 * TAPE_DeviceIoControl
475 * SEE ALSO
476 * NtDeviceIoControl.
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 )
483 DWORD sz = 0;
484 NTSTATUS status = STATUS_INVALID_PARAMETER;
485 int fd;
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 )))
493 goto error;
495 switch (io_control)
497 case IOCTL_TAPE_CREATE_PARTITION:
498 status = TAPE_CreatePartition( fd, (TAPE_CREATE_PARTITION *)in_buffer );
499 break;
500 case IOCTL_TAPE_ERASE:
501 status = TAPE_Erase( fd, (TAPE_ERASE *)in_buffer );
502 break;
503 case IOCTL_TAPE_GET_DRIVE_PARAMS:
504 status = TAPE_GetDriveParams( fd, (TAPE_GET_DRIVE_PARAMETERS *)out_buffer );
505 break;
506 case IOCTL_TAPE_GET_MEDIA_PARAMS:
507 status = TAPE_GetMediaParams( fd, (TAPE_GET_MEDIA_PARAMETERS *)out_buffer );
508 break;
509 case IOCTL_TAPE_GET_POSITION:
510 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
511 (TAPE_GET_POSITION *)out_buffer );
512 break;
513 case IOCTL_TAPE_GET_STATUS:
514 status = FILE_GetNtStatus();
515 break;
516 case IOCTL_TAPE_PREPARE:
517 status = TAPE_Prepare( fd, (TAPE_PREPARE *)in_buffer );
518 break;
519 case IOCTL_TAPE_SET_DRIVE_PARAMS:
520 status = TAPE_SetDriveParams( fd, (TAPE_SET_DRIVE_PARAMETERS *)in_buffer );
521 break;
522 case IOCTL_TAPE_SET_MEDIA_PARAMS:
523 status = TAPE_SetMediaParams( fd, (TAPE_SET_MEDIA_PARAMETERS *)in_buffer );
524 break;
525 case IOCTL_TAPE_SET_POSITION:
526 status = TAPE_SetPosition( fd, (TAPE_SET_POSITION *)in_buffer );
527 break;
528 case IOCTL_TAPE_WRITE_MARKS:
529 status = TAPE_WriteMarks( fd, (TAPE_WRITE_MARKS *)in_buffer );
530 break;
532 case IOCTL_TAPE_CHECK_VERIFY:
533 case IOCTL_TAPE_FIND_NEW_DEVICES:
534 break;
535 default:
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 );
539 break;
542 wine_server_release_fd( device, fd );
544 error:
545 io_status->u.Status = status;
546 io_status->Information = sz;
547 if (event) NtSetEvent( event, NULL );
548 return status;