diff options
author | Borislav Petkov <bbpetkov@yahoo.de> | 2008-02-01 17:09:29 -0500 |
---|---|---|
committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-02-01 17:09:29 -0500 |
commit | f9afd18b5827be93fd9fb3cc84ab9bba38b00db8 (patch) | |
tree | 5bf5a34a970720f6e3856e0a1c2bbf7015520a2f /drivers/ide/ide-cd_ioctl.c | |
parent | d554336514a63342c2e4b06b4287ad93c112b00f (diff) |
ide-cd: move the remaining cdrom.c ioctl handling code to ide-cd_ioctl.c
There should be no functional changes from this.
Signed-off-by: Borislav Petkov <bbpetkov@yahoo.de>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
Diffstat (limited to 'drivers/ide/ide-cd_ioctl.c')
-rw-r--r-- | drivers/ide/ide-cd_ioctl.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/drivers/ide/ide-cd_ioctl.c b/drivers/ide/ide-cd_ioctl.c index ec698c44e8bf..b68284de4e85 100644 --- a/drivers/ide/ide-cd_ioctl.c +++ b/drivers/ide/ide-cd_ioctl.c | |||
@@ -9,9 +9,188 @@ | |||
9 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
10 | #include <linux/cdrom.h> | 10 | #include <linux/cdrom.h> |
11 | #include <linux/ide.h> | 11 | #include <linux/ide.h> |
12 | #include <scsi/scsi.h> | ||
12 | 13 | ||
13 | #include "ide-cd.h" | 14 | #include "ide-cd.h" |
14 | 15 | ||
16 | /**************************************************************************** | ||
17 | * Other driver requests (open, close, check media change). | ||
18 | */ | ||
19 | int ide_cdrom_open_real(struct cdrom_device_info *cdi, int purpose) | ||
20 | { | ||
21 | return 0; | ||
22 | } | ||
23 | |||
24 | /* | ||
25 | * Close down the device. Invalidate all cached blocks. | ||
26 | */ | ||
27 | void ide_cdrom_release_real(struct cdrom_device_info *cdi) | ||
28 | { | ||
29 | ide_drive_t *drive = cdi->handle; | ||
30 | struct cdrom_info *cd = drive->driver_data; | ||
31 | |||
32 | if (!cdi->use_count) | ||
33 | cd->cd_flags &= ~IDE_CD_FLAG_TOC_VALID; | ||
34 | } | ||
35 | |||
36 | /* | ||
37 | * add logic to try GET_EVENT command first to check for media and tray | ||
38 | * status. this should be supported by newer cd-r/w and all DVD etc | ||
39 | * drives | ||
40 | */ | ||
41 | int ide_cdrom_drive_status(struct cdrom_device_info *cdi, int slot_nr) | ||
42 | { | ||
43 | ide_drive_t *drive = cdi->handle; | ||
44 | struct media_event_desc med; | ||
45 | struct request_sense sense; | ||
46 | int stat; | ||
47 | |||
48 | if (slot_nr != CDSL_CURRENT) | ||
49 | return -EINVAL; | ||
50 | |||
51 | stat = cdrom_check_status(drive, &sense); | ||
52 | if (!stat || sense.sense_key == UNIT_ATTENTION) | ||
53 | return CDS_DISC_OK; | ||
54 | |||
55 | if (!cdrom_get_media_event(cdi, &med)) { | ||
56 | if (med.media_present) | ||
57 | return CDS_DISC_OK; | ||
58 | else if (med.door_open) | ||
59 | return CDS_TRAY_OPEN; | ||
60 | else | ||
61 | return CDS_NO_DISC; | ||
62 | } | ||
63 | |||
64 | if (sense.sense_key == NOT_READY && sense.asc == 0x04 | ||
65 | && sense.ascq == 0x04) | ||
66 | return CDS_DISC_OK; | ||
67 | |||
68 | /* | ||
69 | * If not using Mt Fuji extended media tray reports, | ||
70 | * just return TRAY_OPEN since ATAPI doesn't provide | ||
71 | * any other way to detect this... | ||
72 | */ | ||
73 | if (sense.sense_key == NOT_READY) { | ||
74 | if (sense.asc == 0x3a && sense.ascq == 1) | ||
75 | return CDS_NO_DISC; | ||
76 | else | ||
77 | return CDS_TRAY_OPEN; | ||
78 | } | ||
79 | return CDS_DRIVE_NOT_READY; | ||
80 | } | ||
81 | |||
82 | int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi, | ||
83 | int slot_nr) | ||
84 | { | ||
85 | ide_drive_t *drive = cdi->handle; | ||
86 | struct cdrom_info *cd = drive->driver_data; | ||
87 | int retval; | ||
88 | |||
89 | if (slot_nr == CDSL_CURRENT) { | ||
90 | (void) cdrom_check_status(drive, NULL); | ||
91 | retval = (cd->cd_flags & IDE_CD_FLAG_MEDIA_CHANGED) ? 1 : 0; | ||
92 | cd->cd_flags &= ~IDE_CD_FLAG_MEDIA_CHANGED; | ||
93 | return retval; | ||
94 | } else { | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | } | ||
98 | |||
99 | /* Eject the disk if EJECTFLAG is 0. | ||
100 | If EJECTFLAG is 1, try to reload the disk. */ | ||
101 | static | ||
102 | int cdrom_eject(ide_drive_t *drive, int ejectflag, | ||
103 | struct request_sense *sense) | ||
104 | { | ||
105 | struct cdrom_info *cd = drive->driver_data; | ||
106 | struct cdrom_device_info *cdi = &cd->devinfo; | ||
107 | struct request req; | ||
108 | char loej = 0x02; | ||
109 | |||
110 | if ((cd->cd_flags & IDE_CD_FLAG_NO_EJECT) && !ejectflag) | ||
111 | return -EDRIVE_CANT_DO_THIS; | ||
112 | |||
113 | /* reload fails on some drives, if the tray is locked */ | ||
114 | if ((cd->cd_flags & IDE_CD_FLAG_DOOR_LOCKED) && ejectflag) | ||
115 | return 0; | ||
116 | |||
117 | ide_cd_init_rq(drive, &req); | ||
118 | |||
119 | /* only tell drive to close tray if open, if it can do that */ | ||
120 | if (ejectflag && (cdi->mask & CDC_CLOSE_TRAY)) | ||
121 | loej = 0; | ||
122 | |||
123 | req.sense = sense; | ||
124 | req.cmd[0] = GPCMD_START_STOP_UNIT; | ||
125 | req.cmd[4] = loej | (ejectflag != 0); | ||
126 | |||
127 | return ide_cd_queue_pc(drive, &req); | ||
128 | } | ||
129 | |||
130 | /* Lock the door if LOCKFLAG is nonzero; unlock it otherwise. */ | ||
131 | static | ||
132 | int ide_cd_lockdoor(ide_drive_t *drive, int lockflag, | ||
133 | struct request_sense *sense) | ||
134 | { | ||
135 | struct cdrom_info *cd = drive->driver_data; | ||
136 | struct request_sense my_sense; | ||
137 | struct request req; | ||
138 | int stat; | ||
139 | |||
140 | if (sense == NULL) | ||
141 | sense = &my_sense; | ||
142 | |||
143 | /* If the drive cannot lock the door, just pretend. */ | ||
144 | if (cd->cd_flags & IDE_CD_FLAG_NO_DOORLOCK) { | ||
145 | stat = 0; | ||
146 | } else { | ||
147 | ide_cd_init_rq(drive, &req); | ||
148 | req.sense = sense; | ||
149 | req.cmd[0] = GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL; | ||
150 | req.cmd[4] = lockflag ? 1 : 0; | ||
151 | stat = ide_cd_queue_pc(drive, &req); | ||
152 | } | ||
153 | |||
154 | /* If we got an illegal field error, the drive | ||
155 | probably cannot lock the door. */ | ||
156 | if (stat != 0 && | ||
157 | sense->sense_key == ILLEGAL_REQUEST && | ||
158 | (sense->asc == 0x24 || sense->asc == 0x20)) { | ||
159 | printk(KERN_ERR "%s: door locking not supported\n", | ||
160 | drive->name); | ||
161 | cd->cd_flags |= IDE_CD_FLAG_NO_DOORLOCK; | ||
162 | stat = 0; | ||
163 | } | ||
164 | |||
165 | /* no medium, that's alright. */ | ||
166 | if (stat != 0 && sense->sense_key == NOT_READY && sense->asc == 0x3a) | ||
167 | stat = 0; | ||
168 | |||
169 | if (stat == 0) { | ||
170 | if (lockflag) | ||
171 | cd->cd_flags |= IDE_CD_FLAG_DOOR_LOCKED; | ||
172 | else | ||
173 | cd->cd_flags &= ~IDE_CD_FLAG_DOOR_LOCKED; | ||
174 | } | ||
175 | |||
176 | return stat; | ||
177 | } | ||
178 | |||
179 | int ide_cdrom_tray_move(struct cdrom_device_info *cdi, int position) | ||
180 | { | ||
181 | ide_drive_t *drive = cdi->handle; | ||
182 | struct request_sense sense; | ||
183 | |||
184 | if (position) { | ||
185 | int stat = ide_cd_lockdoor(drive, 0, &sense); | ||
186 | |||
187 | if (stat) | ||
188 | return stat; | ||
189 | } | ||
190 | |||
191 | return cdrom_eject(drive, !position, &sense); | ||
192 | } | ||
193 | |||
15 | int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock) | 194 | int ide_cdrom_lock_door(struct cdrom_device_info *cdi, int lock) |
16 | { | 195 | { |
17 | ide_drive_t *drive = cdi->handle; | 196 | ide_drive_t *drive = cdi->handle; |
@@ -263,3 +442,34 @@ int ide_cdrom_audio_ioctl(struct cdrom_device_info *cdi, | |||
263 | return -EINVAL; | 442 | return -EINVAL; |
264 | } | 443 | } |
265 | } | 444 | } |
445 | |||
446 | /* the generic packet interface to cdrom.c */ | ||
447 | int ide_cdrom_packet(struct cdrom_device_info *cdi, | ||
448 | struct packet_command *cgc) | ||
449 | { | ||
450 | struct request req; | ||
451 | ide_drive_t *drive = cdi->handle; | ||
452 | |||
453 | if (cgc->timeout <= 0) | ||
454 | cgc->timeout = ATAPI_WAIT_PC; | ||
455 | |||
456 | /* here we queue the commands from the uniform CD-ROM | ||
457 | layer. the packet must be complete, as we do not | ||
458 | touch it at all. */ | ||
459 | ide_cd_init_rq(drive, &req); | ||
460 | memcpy(req.cmd, cgc->cmd, CDROM_PACKET_SIZE); | ||
461 | if (cgc->sense) | ||
462 | memset(cgc->sense, 0, sizeof(struct request_sense)); | ||
463 | req.data = cgc->buffer; | ||
464 | req.data_len = cgc->buflen; | ||
465 | req.timeout = cgc->timeout; | ||
466 | |||
467 | if (cgc->quiet) | ||
468 | req.cmd_flags |= REQ_QUIET; | ||
469 | |||
470 | req.sense = cgc->sense; | ||
471 | cgc->stat = ide_cd_queue_pc(drive, &req); | ||
472 | if (!cgc->stat) | ||
473 | cgc->buflen -= req.data_len; | ||
474 | return cgc->stat; | ||
475 | } | ||