d3d: Add a test for double surface locking.
[wine.git] / dlls / ntdll / tape.c
blob1a32efb2a00d32e62395dfb026454e93f8a9f44e
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 #define NONAMELESSUNION
52 #define NONAMELESSSTRUCT
53 #include "ntstatus.h"
54 #define WIN32_NO_STATUS
55 #include "windef.h"
56 #include "winternl.h"
57 #include "winioctl.h"
58 #include "ddk/ntddtape.h"
59 #include "ntdll_misc.h"
60 #include "wine/server.h"
61 #include "wine/debug.h"
63 WINE_DEFAULT_DEBUG_CHANNEL(tape);
65 static const char *io2str( DWORD io )
67 switch (io)
69 #define X(x) case (x): return #x;
70 X(IOCTL_TAPE_CHECK_VERIFY);
71 X(IOCTL_TAPE_CREATE_PARTITION);
72 X(IOCTL_TAPE_ERASE);
73 X(IOCTL_TAPE_FIND_NEW_DEVICES);
74 X(IOCTL_TAPE_GET_DRIVE_PARAMS);
75 X(IOCTL_TAPE_GET_MEDIA_PARAMS);
76 X(IOCTL_TAPE_GET_POSITION);
77 X(IOCTL_TAPE_GET_STATUS);
78 X(IOCTL_TAPE_PREPARE);
79 X(IOCTL_TAPE_SET_DRIVE_PARAMS);
80 X(IOCTL_TAPE_SET_MEDIA_PARAMS);
81 X(IOCTL_TAPE_SET_POSITION);
82 X(IOCTL_TAPE_WRITE_MARKS);
83 #undef X
84 default: { static char tmp[32]; sprintf(tmp, "IOCTL_TAPE_%d\n", io); return tmp; }
88 /******************************************************************
89 * TAPE_GetStatus
91 static NTSTATUS TAPE_GetStatus( int error )
93 if (!error) return STATUS_SUCCESS;
94 return FILE_GetNtStatus();
97 /******************************************************************
98 * TAPE_CreatePartition
100 static NTSTATUS TAPE_CreatePartition( int fd, const TAPE_CREATE_PARTITION *data )
102 #ifdef HAVE_SYS_MTIO_H
103 struct mtop cmd;
105 TRACE( "fd: %d method: 0x%08x count: 0x%08x size: 0x%08x\n",
106 fd, data->Method, data->Count, data->Size );
108 if (data->Count > 1)
110 WARN( "Creating more than 1 partition is not supported\n" );
111 return STATUS_INVALID_PARAMETER;
114 switch (data->Method)
116 #ifdef MTMKPART
117 case TAPE_FIXED_PARTITIONS:
118 case TAPE_SELECT_PARTITIONS:
119 cmd.mt_op = MTMKPART;
120 cmd.mt_count = 0;
121 break;
122 case TAPE_INITIATOR_PARTITIONS:
123 cmd.mt_op = MTMKPART;
124 cmd.mt_count = data->Size;
125 break;
126 #endif
127 default:
128 ERR( "Unhandled method: 0x%08x\n", data->Method );
129 return STATUS_INVALID_PARAMETER;
132 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
133 #else
134 FIXME( "Not implemented.\n" );
135 return STATUS_NOT_SUPPORTED;
136 #endif
139 /******************************************************************
140 * TAPE_Erase
142 static NTSTATUS TAPE_Erase( int fd, const TAPE_ERASE *data )
144 #ifdef HAVE_SYS_MTIO_H
145 struct mtop cmd;
147 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
148 fd, data->Type, data->Immediate );
150 switch (data->Type)
152 case TAPE_ERASE_LONG:
153 cmd.mt_op = MTERASE;
154 cmd.mt_count = 1;
155 break;
156 case TAPE_ERASE_SHORT:
157 cmd.mt_op = MTERASE;
158 cmd.mt_count = 0;
159 break;
160 default:
161 ERR( "Unhandled type: 0x%08x\n", data->Type );
162 return STATUS_INVALID_PARAMETER;
165 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
166 #else
167 FIXME( "Not implemented.\n" );
168 return STATUS_NOT_SUPPORTED;
169 #endif
172 /******************************************************************
173 * TAPE_GetDriveParams
175 static NTSTATUS TAPE_GetDriveParams( int fd, TAPE_GET_DRIVE_PARAMETERS *data )
177 #ifdef HAVE_SYS_MTIO_H
178 struct mtget get;
179 NTSTATUS status;
181 TRACE( "fd: %d\n", fd );
183 memset( data, 0, sizeof(TAPE_GET_DRIVE_PARAMETERS) );
185 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
186 if (status != STATUS_SUCCESS)
187 return status;
189 data->ECC = FALSE;
190 data->Compression = FALSE;
191 data->DataPadding = FALSE;
192 data->ReportSetmarks = FALSE;
193 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
194 data->DefaultBlockSize = get.mt_blksiz;
195 #else
196 data->DefaultBlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
197 #endif
198 data->MaximumBlockSize = data->DefaultBlockSize;
199 data->MinimumBlockSize = data->DefaultBlockSize;
200 data->MaximumPartitionCount = 1;
202 return status;
203 #else
204 FIXME( "Not implemented.\n" );
205 return STATUS_NOT_SUPPORTED;
206 #endif
209 /******************************************************************
210 * TAPE_GetMediaParams
212 static NTSTATUS TAPE_GetMediaParams( int fd, TAPE_GET_MEDIA_PARAMETERS *data )
214 #ifdef HAVE_SYS_MTIO_H
215 struct mtget get;
216 NTSTATUS status;
218 TRACE( "fd: %d\n", fd );
220 memset( data, 0, sizeof(TAPE_GET_MEDIA_PARAMETERS) );
222 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
223 if (status != STATUS_SUCCESS)
224 return status;
226 data->Capacity.u.LowPart = 1024 * 1024 * 1024;
227 data->Remaining.u.LowPart = 1024 * 1024 * 1024;
228 #ifdef HAVE_STRUCT_MTGET_MT_BLKSIZ
229 data->BlockSize = get.mt_blksiz;
230 #else
231 data->BlockSize = get.mt_dsreg & MT_ST_BLKSIZE_MASK;
232 #endif
233 data->PartitionCount = 1;
234 #ifdef HAVE_STRUCT_MTGET_MT_GSTAT
235 data->WriteProtected = (GMT_WR_PROT(get.mt_gstat) != 0);
236 #else
237 data->WriteProtected = 0;
238 #endif
240 return status;
241 #else
242 FIXME( "Not implemented.\n" );
243 return STATUS_NOT_SUPPORTED;
244 #endif
247 /******************************************************************
248 * TAPE_GetPosition
250 static NTSTATUS TAPE_GetPosition( int fd, ULONG type, TAPE_GET_POSITION *data )
252 #ifdef HAVE_SYS_MTIO_H
253 struct mtget get;
254 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
255 struct mtpos pos;
256 #endif
257 NTSTATUS status;
259 TRACE( "fd: %d type: 0x%08x\n", fd, type );
261 memset( data, 0, sizeof(TAPE_GET_POSITION) );
263 status = TAPE_GetStatus( ioctl( fd, MTIOCGET, &get ) );
264 if (status != STATUS_SUCCESS)
265 return status;
267 #ifndef HAVE_STRUCT_MTGET_MT_BLKNO
268 status = TAPE_GetStatus( ioctl( fd, MTIOCPOS, &pos ) );
269 if (status != STATUS_SUCCESS)
270 return status;
271 #endif
273 switch (type)
275 case TAPE_ABSOLUTE_BLOCK:
276 data->Type = type;
277 data->Partition = get.mt_resid;
278 #ifdef HAVE_STRUCT_MTGET_MT_BLKNO
279 data->OffsetLow = get.mt_blkno;
280 #else
281 data->OffsetLow = pos.mt_blkno;
282 #endif
283 break;
284 case TAPE_LOGICAL_BLOCK:
285 case TAPE_PSEUDO_LOGICAL_BLOCK:
286 WARN( "Positioning type not supported\n" );
287 break;
288 default:
289 ERR( "Unhandled type: 0x%08x\n", type );
290 return STATUS_INVALID_PARAMETER;
293 return status;
294 #else
295 FIXME( "Not implemented.\n" );
296 return STATUS_NOT_SUPPORTED;
297 #endif
300 /******************************************************************
301 * TAPE_Prepare
303 static NTSTATUS TAPE_Prepare( int fd, const TAPE_PREPARE *data )
305 #ifdef HAVE_SYS_MTIO_H
306 struct mtop cmd;
308 TRACE( "fd: %d type: 0x%08x immediate: 0x%02x\n",
309 fd, data->Operation, data->Immediate );
311 switch (data->Operation)
313 #ifdef MTLOAD
314 case TAPE_LOAD:
315 cmd.mt_op = MTLOAD;
316 break;
317 #endif
318 #ifdef MTUNLOAD
319 case TAPE_UNLOAD:
320 cmd.mt_op = MTUNLOAD;
321 break;
322 #endif
323 #ifdef MTRETEN
324 case TAPE_TENSION:
325 cmd.mt_op = MTRETEN;
326 break;
327 #endif
328 #ifdef MTLOCK
329 case TAPE_LOCK:
330 cmd.mt_op = MTLOCK;
331 break;
332 #endif
333 #ifdef MTUNLOCK
334 case TAPE_UNLOCK:
335 cmd.mt_op = MTUNLOCK;
336 break;
337 #endif
338 case TAPE_FORMAT:
339 /* Native ignores this if the drive doesn't support it */
340 return STATUS_SUCCESS;
341 default:
342 ERR( "Unhandled operation: 0x%08x\n", data->Operation );
343 return STATUS_INVALID_PARAMETER;
346 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
347 #else
348 FIXME( "Not implemented.\n" );
349 return STATUS_NOT_SUPPORTED;
350 #endif
353 /******************************************************************
354 * TAPE_SetDriveParams
356 static NTSTATUS TAPE_SetDriveParams( int fd, const TAPE_SET_DRIVE_PARAMETERS *data )
358 #if defined(HAVE_SYS_MTIO_H) && defined(MTCOMPRESSION)
359 struct mtop cmd;
361 TRACE( "fd: %d ECC: 0x%02x, compression: 0x%02x padding: 0x%02x\n",
362 fd, data->ECC, data->Compression, data->DataPadding );
363 TRACE( "setmarks: 0x%02x zonesize: 0x%08x\n",
364 data->ReportSetmarks, data->EOTWarningZoneSize );
366 if (data->ECC || data->DataPadding || data->ReportSetmarks ||
367 data->EOTWarningZoneSize ) WARN( "Setting not supported\n" );
369 cmd.mt_op = MTCOMPRESSION;
370 cmd.mt_count = data->Compression;
372 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
373 #else
374 FIXME( "Not implemented.\n" );
375 return STATUS_NOT_SUPPORTED;
376 #endif
379 /******************************************************************
380 * TAPE_SetMediaParams
382 static NTSTATUS TAPE_SetMediaParams( int fd, const TAPE_SET_MEDIA_PARAMETERS *data )
384 #ifdef HAVE_SYS_MTIO_H
385 struct mtop cmd;
387 TRACE( "fd: %d blocksize: 0x%08x\n", fd, data->BlockSize );
389 cmd.mt_op = MTSETBLK;
390 cmd.mt_count = data->BlockSize;
392 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
393 #else
394 FIXME( "Not implemented.\n" );
395 return STATUS_NOT_SUPPORTED;
396 #endif
399 /******************************************************************
400 * TAPE_SetPosition
402 static NTSTATUS TAPE_SetPosition( int fd, const TAPE_SET_POSITION *data )
404 #ifdef HAVE_SYS_MTIO_H
405 struct mtop cmd;
407 TRACE( "fd: %d method: 0x%08x partition: 0x%08x offset: 0x%08x immediate: 0x%02x\n",
408 fd, data->Method, data->Partition, data->Offset.u.LowPart, data->Immediate );
410 if (data->Offset.u.HighPart > 0)
411 return STATUS_INVALID_PARAMETER;
413 switch (data->Method)
415 case TAPE_REWIND:
416 cmd.mt_op = MTREW;
417 break;
418 #ifdef MTSEEK
419 case TAPE_ABSOLUTE_BLOCK:
420 cmd.mt_op = MTSEEK;
421 cmd.mt_count = data->Offset.u.LowPart;
422 break;
423 #endif
424 #ifdef MTEOM
425 case TAPE_SPACE_END_OF_DATA:
426 cmd.mt_op = MTEOM;
427 break;
428 #endif
429 case TAPE_SPACE_FILEMARKS:
430 if (data->Offset.u.LowPart >= 0) {
431 cmd.mt_op = MTFSF;
432 cmd.mt_count = data->Offset.u.LowPart;
434 else {
435 cmd.mt_op = MTBSF;
436 cmd.mt_count = -data->Offset.u.LowPart;
438 break;
439 #if defined(MTFSS) && defined(MTBSS)
440 case TAPE_SPACE_SETMARKS:
441 if (data->Offset.u.LowPart >= 0) {
442 cmd.mt_op = MTFSS;
443 cmd.mt_count = data->Offset.u.LowPart;
445 else {
446 cmd.mt_op = MTBSS;
447 cmd.mt_count = -data->Offset.u.LowPart;
449 break;
450 #endif
451 case TAPE_LOGICAL_BLOCK:
452 case TAPE_PSEUDO_LOGICAL_BLOCK:
453 case TAPE_SPACE_RELATIVE_BLOCKS:
454 case TAPE_SPACE_SEQUENTIAL_FMKS:
455 case TAPE_SPACE_SEQUENTIAL_SMKS:
456 WARN( "Positioning method not supported\n" );
457 return STATUS_INVALID_PARAMETER;
458 default:
459 ERR( "Unhandled method: 0x%08x\n", data->Method );
460 return STATUS_INVALID_PARAMETER;
463 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
464 #else
465 FIXME( "Not implemented.\n" );
466 return STATUS_NOT_SUPPORTED;
467 #endif
470 /******************************************************************
471 * TAPE_WriteMarks
473 static NTSTATUS TAPE_WriteMarks( int fd, const TAPE_WRITE_MARKS *data )
475 #ifdef HAVE_SYS_MTIO_H
476 struct mtop cmd;
478 TRACE( "fd: %d type: 0x%08x count: 0x%08x immediate: 0x%02x\n",
479 fd, data->Type, data->Count, data->Immediate );
481 switch (data->Type)
483 #ifdef MTWSM
484 case TAPE_SETMARKS:
485 cmd.mt_op = MTWSM;
486 cmd.mt_count = data->Count;
487 break;
488 #endif
489 case TAPE_FILEMARKS:
490 case TAPE_SHORT_FILEMARKS:
491 case TAPE_LONG_FILEMARKS:
492 cmd.mt_op = MTWEOF;
493 cmd.mt_count = data->Count;
494 break;
495 default:
496 ERR( "Unhandled type: 0x%08x\n", data->Type );
497 return STATUS_INVALID_PARAMETER;
500 return TAPE_GetStatus( ioctl( fd, MTIOCTOP, &cmd ) );
501 #else
502 FIXME( "Not implemented.\n" );
503 return STATUS_NOT_SUPPORTED;
504 #endif
507 /******************************************************************
508 * TAPE_DeviceIoControl
510 * SEE ALSO
511 * NtDeviceIoControl.
513 NTSTATUS TAPE_DeviceIoControl( HANDLE device, HANDLE event,
514 PIO_APC_ROUTINE apc, PVOID apc_user, PIO_STATUS_BLOCK io_status,
515 ULONG io_control, LPVOID in_buffer, DWORD in_size,
516 LPVOID out_buffer, DWORD out_size )
518 DWORD sz = 0;
519 NTSTATUS status = STATUS_INVALID_PARAMETER;
520 int fd, needs_close;
522 TRACE( "%p %s %p %d %p %d %p\n", device, io2str(io_control),
523 in_buffer, in_size, out_buffer, out_size, io_status );
525 io_status->Information = 0;
527 if ((status = server_get_unix_fd( device, 0, &fd, &needs_close, NULL, NULL )))
528 goto error;
530 switch (io_control)
532 case IOCTL_TAPE_CREATE_PARTITION:
533 status = TAPE_CreatePartition( fd, (TAPE_CREATE_PARTITION *)in_buffer );
534 break;
535 case IOCTL_TAPE_ERASE:
536 status = TAPE_Erase( fd, (TAPE_ERASE *)in_buffer );
537 break;
538 case IOCTL_TAPE_GET_DRIVE_PARAMS:
539 status = TAPE_GetDriveParams( fd, (TAPE_GET_DRIVE_PARAMETERS *)out_buffer );
540 break;
541 case IOCTL_TAPE_GET_MEDIA_PARAMS:
542 status = TAPE_GetMediaParams( fd, (TAPE_GET_MEDIA_PARAMETERS *)out_buffer );
543 break;
544 case IOCTL_TAPE_GET_POSITION:
545 status = TAPE_GetPosition( fd, ((TAPE_GET_POSITION *)in_buffer)->Type,
546 (TAPE_GET_POSITION *)out_buffer );
547 break;
548 case IOCTL_TAPE_GET_STATUS:
549 status = FILE_GetNtStatus();
550 break;
551 case IOCTL_TAPE_PREPARE:
552 status = TAPE_Prepare( fd, (TAPE_PREPARE *)in_buffer );
553 break;
554 case IOCTL_TAPE_SET_DRIVE_PARAMS:
555 status = TAPE_SetDriveParams( fd, (TAPE_SET_DRIVE_PARAMETERS *)in_buffer );
556 break;
557 case IOCTL_TAPE_SET_MEDIA_PARAMS:
558 status = TAPE_SetMediaParams( fd, (TAPE_SET_MEDIA_PARAMETERS *)in_buffer );
559 break;
560 case IOCTL_TAPE_SET_POSITION:
561 status = TAPE_SetPosition( fd, (TAPE_SET_POSITION *)in_buffer );
562 break;
563 case IOCTL_TAPE_WRITE_MARKS:
564 status = TAPE_WriteMarks( fd, (TAPE_WRITE_MARKS *)in_buffer );
565 break;
567 case IOCTL_TAPE_CHECK_VERIFY:
568 case IOCTL_TAPE_FIND_NEW_DEVICES:
569 break;
570 default:
571 FIXME( "Unsupported IOCTL %x (type=%x access=%x func=%x meth=%x)\n",
572 io_control, io_control >> 16, (io_control >> 14) & 3,
573 (io_control >> 2) & 0xfff, io_control & 3 );
574 break;
577 if (needs_close) close( fd );
579 error:
580 io_status->u.Status = status;
581 io_status->Information = sz;
582 if (event) NtSetEvent( event, NULL );
583 return status;