winedump: Add more image debug types.
[wine/multimedia.git] / dlls / ntdll / tape.c
blobfef31cb3458ee579e306310eefc2e6df4782370a
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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 #if !defined(MTCOMPRESSION) && defined(MTCOMP)
34 #define MTCOMPRESSION MTCOMP
35 #endif
36 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
37 #define MTSETBLK MTSETBSIZ
38 #endif
39 #if !defined(MTSETBLK) && defined(MTSRSZ)
40 #define MTSETBLK MTSRSZ
41 #endif
42 #ifndef MT_ST_BLKSIZE_MASK
43 #define MT_ST_BLKSIZE_MASK 0xffffff
44 #endif
46 /* Darwin 7.9.0 has MTSETBSIZ instead of MTSETBLK */
47 #if !defined(MTSETBLK) && defined(MTSETBSIZ)
48 #define MTSETBLK MTSETBSIZ
49 #endif
51 #include "ntstatus.h"
52 #define WIN32_NO_STATUS
53 #define NONAMELESSUNION
54 #include "windef.h"
55 #include "winternl.h"
56 #include "winioctl.h"
57 #include "ddk/ntddtape.h"
58 #include "ntdll_misc.h"
59 #include "wine/server.h"
60 #include "wine/debug.h"
62 WINE_DEFAULT_DEBUG_CHANNEL(tape);
64 static const char *io2str( DWORD io )
66 switch (io)
68 #define X(x) case (x): return #x
69 X(IOCTL_TAPE_CHECK_VERIFY);
70 X(IOCTL_TAPE_CREATE_PARTITION);
71 X(IOCTL_TAPE_ERASE);
72 X(IOCTL_TAPE_FIND_NEW_DEVICES);
73 X(IOCTL_TAPE_GET_DRIVE_PARAMS);
74 X(IOCTL_TAPE_GET_MEDIA_PARAMS);
75 X(IOCTL_TAPE_GET_POSITION);
76 X(IOCTL_TAPE_GET_STATUS);
77 X(IOCTL_TAPE_PREPARE);
78 X(IOCTL_TAPE_SET_DRIVE_PARAMS);
79 X(IOCTL_TAPE_SET_MEDIA_PARAMS);
80 X(IOCTL_TAPE_SET_POSITION);
81 X(IOCTL_TAPE_WRITE_MARKS);
82 #undef X
83 default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%d\n", io); return tmp; }
87 /******************************************************************
88 * TAPE_GetStatus
90 static inline NTSTATUS TAPE_GetStatus( int error )
92 if (!error) return STATUS_SUCCESS;
93 return FILE_GetNtStatus();
96 /******************************************************************
97 * TAPE_CreatePartition
99 static NTSTATUS TAPE_CreatePartition( int fd, const TAPE_CREATE_PARTITION *data )
101 #ifdef HAVE_SYS_MTIO_H
102 struct mtop cmd;
104 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
105 fd, data->Method, data->Count, data->Size );
107 if (data->Count > 1)
109 WARN( "Creating more than 1 partition is not supported\n" );
110 return STATUS_INVALID_PARAMETER;
113 switch (data->Method)
115 #ifdef MTMKPART
116 case TAPE_FIXED_PARTITIONS:
117 case TAPE_SELECT_PARTITIONS:
118 cmd.mt_op = MTMKPART;
119 cmd.mt_count = 0;
120 break;
121 case TAPE_INITIATOR_PARTITIONS:
122 cmd.mt_op = MTMKPART;
123 cmd.mt_count = data->Size;
124 break;
125 #endif
126 default:
127 ERR( "Unhandled method: 0x%08x\n", data->Method );
128 return STATUS_INVALID_PARAMETER;
131 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
132 #else
133 FIXME( "Not implemented.\n" );
134 return STATUS_NOT_SUPPORTED;
135 #endif
138 /******************************************************************
139 * TAPE_Erase
141 static NTSTATUS TAPE_Erase( int fd, const TAPE_ERASE *data )
143 #ifdef HAVE_SYS_MTIO_H
144 struct mtop cmd;
146 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
147 fd, data->Type, data->Immediate );
149 switch (data->Type)
151 case TAPE_ERASE_LONG:
152 cmd.mt_op = MTERASE;
153 cmd.mt_count = 1;
154 break;
155 case TAPE_ERASE_SHORT:
156 cmd.mt_op = MTERASE;
157 cmd.mt_count = 0;
158 break;
159 default:
160 ERR( "Unhandled type: 0x%08x\n", data->Type );
161 return STATUS_INVALID_PARAMETER;
164 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
165 #else
166 FIXME( "Not implemented.\n" );
167 return STATUS_NOT_SUPPORTED;
168 #endif
171 /******************************************************************
172 * TAPE_GetDriveParams
174 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
176 #ifdef HAVE_SYS_MTIO_H
177 struct mtget get;
178 NTSTATUS status;
180 TRACE( "fd: %d\n", fd );
182 memset( data, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) );
184 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
185 if (status != STATUS_SUCCESS)
186 return status;
188 data->ECC = FALSE;
189 data->Compression = FALSE;
190 data->DataPadding = FALSE;
191 data->ReportSetmarks = FALSE;
192 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
193 data->DefaultBlockSize = get.mt_blksiz;
194 #else
195 data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
196 #endif
197 data->MaximumBlockSize = data->DefaultBlockSize;
198 data->MinimumBlockSize = data->DefaultBlockSize;
199 data->MaximumPartitionCount = 1;
201 return status;
202 #else
203 FIXME( "Not implemented.\n" );
204 return STATUS_NOT_SUPPORTED;
205 #endif
208 /******************************************************************
209 * TAPE_GetMediaParams
211 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
213 #ifdef HAVE_SYS_MTIO_H
214 struct mtget get;
215 NTSTATUS status;
217 TRACE( "fd: %d\n", fd );
219 memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
221 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
222 if (status != STATUS_SUCCESS)
223 return status;
225 data->Capacity.QuadPart = 1024 * 1024 * 1024;
226 data->Remaining.QuadPart = 1024 * 1024 * 1024;
227 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
228 data->BlockSize = get.mt_blksiz;
229 #else
230 data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
231 #endif
232 data->PartitionCount = 1;
233 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
234 data->WriteProtected = (GMT_WR_PROT(get.mt_gstat) != 0);
235 #else
236 data->WriteProtected = 0;
237 #endif
239 return status;
240 #else
241 FIXME( "Not implemented.\n" );
242 return STATUS_NOT_SUPPORTED;
243 #endif
246 /******************************************************************
247 * TAPE_GetPosition
249 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
251 #ifdef HAVE_SYS_MTIO_H
252 struct mtget get;
253 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
254 struct mtpos pos;
255 #endif
256 NTSTATUS status;
258 TRACE( "fd: %d type: 0x%08x\n", fd, type );
260 memset( data, 0, sizeof(TAPE_GET_POSITION) );
262 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
263 if (status != STATUS_SUCCESS)
264 return status;
266 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
267 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
268 if (status != STATUS_SUCCESS)
269 return status;
270 #endif
272 switch (type)
274 case TAPE_ABSOLUTE_BLOCK:
275 data->Type = type;
276 data->Partition = get.mt_resid;
277 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
278 data->OffsetLow = get.mt_blkno;
279 #else
280 data->OffsetLow = pos.mt_blkno;
281 #endif
282 break;
283 case TAPE_LOGICAL_BLOCK:
284 case TAPE_PSEUDO_LOGICAL_BLOCK:
285 WARN( "Positioning type not supported\n" );
286 break;
287 default:
288 ERR( "Unhandled type: 0x%08x\n", type );
289 return STATUS_INVALID_PARAMETER;
292 return status;
293 #else
294 FIXME( "Not implemented.\n" );
295 return STATUS_NOT_SUPPORTED;
296 #endif
299 /******************************************************************
300 * TAPE_Prepare
302 static NTSTATUS TAPE_Prepare( int fd, const TAPE_PREPARE *data )
304 #ifdef HAVE_SYS_MTIO_H
305 struct mtop cmd;
307 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
308 fd, data->Operation, data->Immediate );
310 switch (data->Operation)
312 #ifdef MTLOAD
313 case TAPE_LOAD:
314 cmd.mt_op = MTLOAD;
315 break;
316 #endif
317 #ifdef MTUNLOAD
318 case TAPE_UNLOAD:
319 cmd.mt_op = MTUNLOAD;
320 break;
321 #endif
322 #ifdef MTRETEN
323 case TAPE_TENSION:
324 cmd.mt_op = MTRETEN;
325 break;
326 #endif
327 #ifdef MTLOCK
328 case TAPE_LOCK:
329 cmd.mt_op = MTLOCK;
330 break;
331 #endif
332 #ifdef MTUNLOCK
333 case TAPE_UNLOCK:
334 cmd.mt_op = MTUNLOCK;
335 break;
336 #endif
337 case TAPE_FORMAT:
338 /* Native ignores this if the drive doesn't support it */
339 return STATUS_SUCCESS;
340 default:
341 ERR( "Unhandled operation: 0x%08x\n", data->Operation );
342 return STATUS_INVALID_PARAMETER;
345 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
346 #else
347 FIXME( "Not implemented.\n" );
348 return STATUS_NOT_SUPPORTED;
349 #endif
352 /******************************************************************
353 * TAPE_SetDriveParams
355 static NTSTATUS TAPE_SetDriveParams( int fd, const TAPE_SET_DRIVE_PARAMETERS *data )
357 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
358 struct mtop cmd;
360 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
361 fd, data->ECC, data->Compression, data->DataPadding );
362 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
363 data->ReportSetmarks, data->EOTWarningZoneSize );
365 if (data->ECC || data->DataPadding || data->ReportSetmarks ||
366 data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
368 cmd.mt_op = MTCOMPRESSION;
369 cmd.mt_count = data->Compression;
371 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
372 #else
373 FIXME( "Not implemented.\n" );
374 return STATUS_NOT_SUPPORTED;
375 #endif
378 /******************************************************************
379 * TAPE_SetMediaParams
381 static NTSTATUS TAPE_SetMediaParams( int fd, const TAPE_SET_MEDIA_PARAMETERS *data )
383 #ifdef HAVE_SYS_MTIO_H
384 struct mtop cmd;
386 TRACE( "fd: %d blocksize: 0x%08x\n", fd, data->BlockSize );
388 cmd.mt_op = MTSETBLK;
389 cmd.mt_count = data->BlockSize;
391 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
392 #else
393 FIXME( "Not implemented.\n" );
394 return STATUS_NOT_SUPPORTED;
395 #endif
398 /******************************************************************
399 * TAPE_SetPosition
401 static NTSTATUS TAPE_SetPosition( int fd, const TAPE_SET_POSITION *data )
403 #ifdef HAVE_SYS_MTIO_H
404 struct mtop cmd;
406 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%x%08x immediate: 0x%02x\n",
407 fd, data->Method, data->Partition, (DWORD)(data->Offset.QuadPart >> 32),
408 (DWORD)data->Offset.QuadPart, data->Immediate );
410 if (sizeof(cmd.mt_count) < sizeof(data->Offset.QuadPart) &&
411 (int)data->Offset.QuadPart != data->Offset.QuadPart)
413 ERR("Offset too large or too small\n");
414 return STATUS_INVALID_PARAMETER;
417 switch (data->Method)
419 case TAPE_REWIND:
420 cmd.mt_op = MTREW;
421 break;
422 #ifdef MTSEEK
423 case TAPE_ABSOLUTE_BLOCK:
424 cmd.mt_op = MTSEEK;
425 cmd.mt_count = data->Offset.QuadPart;
426 break;
427 #endif
428 #ifdef MTEOM
429 case TAPE_SPACE_END_OF_DATA:
430 cmd.mt_op = MTEOM;
431 break;
432 #endif
433 case TAPE_SPACE_FILEMARKS:
434 if (data->Offset.QuadPart >= 0) {
435 cmd.mt_op = MTFSF;
436 cmd.mt_count = data->Offset.QuadPart;
438 else {
439 cmd.mt_op = MTBSF;
440 cmd.mt_count = -data->Offset.QuadPart;
442 break;
443 #if defined(MTFSS) && defined(MTBSS)
444 case TAPE_SPACE_SETMARKS:
445 if (data->Offset.QuadPart >= 0) {
446 cmd.mt_op = MTFSS;
447 cmd.mt_count = data->Offset.QuadPart;
449 else {
450 cmd.mt_op = MTBSS;
451 cmd.mt_count = -data->Offset.QuadPart;
453 break;
454 #endif
455 case TAPE_LOGICAL_BLOCK:
456 case TAPE_PSEUDO_LOGICAL_BLOCK:
457 case TAPE_SPACE_RELATIVE_BLOCKS:
458 case TAPE_SPACE_SEQUENTIAL_FMKS:
459 case TAPE_SPACE_SEQUENTIAL_SMKS:
460 WARN( "Positioning method not supported\n" );
461 return STATUS_INVALID_PARAMETER;
462 default:
463 ERR( "Unhandled method: 0x%08x\n", data->Method );
464 return STATUS_INVALID_PARAMETER;
467 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
468 #else
469 FIXME( "Not implemented.\n" );
470 return STATUS_NOT_SUPPORTED;
471 #endif
474 /******************************************************************
475 * TAPE_WriteMarks
477 static NTSTATUS TAPE_WriteMarks( int fd, const TAPE_WRITE_MARKS *data )
479 #ifdef HAVE_SYS_MTIO_H
480 struct mtop cmd;
482 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
483 fd, data->Type, data->Count, data->Immediate );
485 switch (data->Type)
487 #ifdef MTWSM
488 case TAPE_SETMARKS:
489 cmd.mt_op = MTWSM;
490 cmd.mt_count = data->Count;
491 break;
492 #endif
493 case TAPE_FILEMARKS:
494 case TAPE_SHORT_FILEMARKS:
495 case TAPE_LONG_FILEMARKS:
496 cmd.mt_op = MTWEOF;
497 cmd.mt_count = data->Count;
498 break;
499 default:
500 ERR( "Unhandled type: 0x%08x\n", data->Type );
501 return STATUS_INVALID_PARAMETER;
504 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
505 #else
506 FIXME( "Not implemented.\n" );
507 return STATUS_NOT_SUPPORTED;
508 #endif
511 /******************************************************************
512 * TAPE_DeviceIoControl
514 * SEE ALSO
515 * NtDeviceIoControl.
517 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
518 PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
519 ULONG io_control, LPVOID in_buffer, DWORD in_size,
520 LPVOID out_buffer, DWORD out_size )
522 DWORD sz = 0;
523 NTSTATUS status = STATUS_INVALID_PARAMETER;
524 int fd, needs_close;
526 TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
527 in_buffer, in_size, out_buffer, out_size, io_status );
529 io_status->Information = 0;
531 if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
532 goto error;
534 switch (io_control)
536 case IOCTL_TAPE_CREATE_PARTITION:
537 status = TAPE_CreatePartition( fd, in_buffer );
538 break;
539 case IOCTL_TAPE_ERASE:
540 status = TAPE_Erase( fd, in_buffer );
541 break;
542 case IOCTL_TAPE_GET_DRIVE_PARAMS:
543 status = TAPE_GetDriveParams( fd, out_buffer );
544 break;
545 case IOCTL_TAPE_GET_MEDIA_PARAMS:
546 status = TAPE_GetMediaParams( fd, out_buffer );
547 break;
548 case IOCTL_TAPE_GET_POSITION:
549 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
550 out_buffer );
551 break;
552 case IOCTL_TAPE_GET_STATUS:
553 status = FILE_GetNtStatus();
554 break;
555 case IOCTL_TAPE_PREPARE:
556 status = TAPE_Prepare( fd, in_buffer );
557 break;
558 case IOCTL_TAPE_SET_DRIVE_PARAMS:
559 status = TAPE_SetDriveParams( fd, in_buffer );
560 break;
561 case IOCTL_TAPE_SET_MEDIA_PARAMS:
562 status = TAPE_SetMediaParams( fd, in_buffer );
563 break;
564 case IOCTL_TAPE_SET_POSITION:
565 status = TAPE_SetPosition( fd, in_buffer );
566 break;
567 case IOCTL_TAPE_WRITE_MARKS:
568 status = TAPE_WriteMarks( fd, in_buffer );
569 break;
571 case IOCTL_TAPE_CHECK_VERIFY:
572 case IOCTL_TAPE_FIND_NEW_DEVICES:
573 break;
574 default:
575 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
576 io_control, io_control >> 16, (io_control >> 14) & 3,
577 (io_control >> 2) & 0xfff, io_control & 3 );
578 break;
581 if (needs_close) close( fd );
583 error:
584 io_status->u.Status = status;
585 io_status->Information = sz;
586 if (event) NtSetEvent( event, NULL );
587 return status;