1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* GD ROM driver for the SEGA Dreamcast |
3 | * copyright Adrian McMenamin, 2007 |
4 | * With thanks to Marcus Comstedt and Nathan Keynes |
5 | * for work in reversing PIO and DMA |
6 | */ |
7 | |
8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
9 | |
10 | #include <linux/init.h> |
11 | #include <linux/module.h> |
12 | #include <linux/fs.h> |
13 | #include <linux/kernel.h> |
14 | #include <linux/list.h> |
15 | #include <linux/slab.h> |
16 | #include <linux/dma-mapping.h> |
17 | #include <linux/cdrom.h> |
18 | #include <linux/bio.h> |
19 | #include <linux/blk-mq.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/device.h> |
22 | #include <linux/mutex.h> |
23 | #include <linux/wait.h> |
24 | #include <linux/platform_device.h> |
25 | #include <scsi/scsi.h> |
26 | #include <asm/io.h> |
27 | #include <asm/dma.h> |
28 | #include <asm/delay.h> |
29 | #include <mach/dma.h> |
30 | #include <mach/sysasic.h> |
31 | |
32 | #define GDROM_DEV_NAME "gdrom" |
33 | #define GD_SESSION_OFFSET 150 |
34 | |
35 | /* GD Rom commands */ |
36 | #define GDROM_COM_SOFTRESET 0x08 |
37 | #define GDROM_COM_EXECDIAG 0x90 |
38 | #define GDROM_COM_PACKET 0xA0 |
39 | #define GDROM_COM_IDDEV 0xA1 |
40 | |
41 | /* GD Rom registers */ |
42 | #define GDROM_BASE_REG 0xA05F7000 |
43 | #define GDROM_ALTSTATUS_REG (GDROM_BASE_REG + 0x18) |
44 | #define GDROM_DATA_REG (GDROM_BASE_REG + 0x80) |
45 | #define GDROM_ERROR_REG (GDROM_BASE_REG + 0x84) |
46 | #define GDROM_INTSEC_REG (GDROM_BASE_REG + 0x88) |
47 | #define GDROM_SECNUM_REG (GDROM_BASE_REG + 0x8C) |
48 | #define GDROM_BCL_REG (GDROM_BASE_REG + 0x90) |
49 | #define GDROM_BCH_REG (GDROM_BASE_REG + 0x94) |
50 | #define GDROM_DSEL_REG (GDROM_BASE_REG + 0x98) |
51 | #define GDROM_STATUSCOMMAND_REG (GDROM_BASE_REG + 0x9C) |
52 | #define GDROM_RESET_REG (GDROM_BASE_REG + 0x4E4) |
53 | |
54 | #define GDROM_DMA_STARTADDR_REG (GDROM_BASE_REG + 0x404) |
55 | #define GDROM_DMA_LENGTH_REG (GDROM_BASE_REG + 0x408) |
56 | #define GDROM_DMA_DIRECTION_REG (GDROM_BASE_REG + 0x40C) |
57 | #define GDROM_DMA_ENABLE_REG (GDROM_BASE_REG + 0x414) |
58 | #define GDROM_DMA_STATUS_REG (GDROM_BASE_REG + 0x418) |
59 | #define GDROM_DMA_WAIT_REG (GDROM_BASE_REG + 0x4A0) |
60 | #define GDROM_DMA_ACCESS_CTRL_REG (GDROM_BASE_REG + 0x4B8) |
61 | |
62 | #define GDROM_HARD_SECTOR 2048 |
63 | #define BLOCK_LAYER_SECTOR 512 |
64 | #define GD_TO_BLK 4 |
65 | |
66 | #define GDROM_DEFAULT_TIMEOUT (HZ * 7) |
67 | |
68 | static DEFINE_MUTEX(gdrom_mutex); |
69 | static const struct { |
70 | int sense_key; |
71 | const char * const text; |
72 | } sense_texts[] = { |
73 | {NO_SENSE, "OK" }, |
74 | {RECOVERED_ERROR, "Recovered from error" }, |
75 | {NOT_READY, "Device not ready" }, |
76 | {MEDIUM_ERROR, "Disk not ready" }, |
77 | {HARDWARE_ERROR, "Hardware error" }, |
78 | {ILLEGAL_REQUEST, "Command has failed" }, |
79 | {UNIT_ATTENTION, "Device needs attention - disk may have been changed" }, |
80 | {DATA_PROTECT, "Data protection error" }, |
81 | {ABORTED_COMMAND, "Command aborted" }, |
82 | }; |
83 | |
84 | static struct platform_device *pd; |
85 | static int gdrom_major; |
86 | static DECLARE_WAIT_QUEUE_HEAD(command_queue); |
87 | static DECLARE_WAIT_QUEUE_HEAD(request_queue); |
88 | |
89 | struct gdromtoc { |
90 | unsigned int entry[99]; |
91 | unsigned int first, last; |
92 | unsigned int leadout; |
93 | }; |
94 | |
95 | static struct gdrom_unit { |
96 | struct gendisk *disk; |
97 | struct cdrom_device_info *cd_info; |
98 | int status; |
99 | int pending; |
100 | int transfer; |
101 | char disk_type; |
102 | struct gdromtoc *toc; |
103 | struct request_queue *gdrom_rq; |
104 | struct blk_mq_tag_set tag_set; |
105 | } gd; |
106 | |
107 | struct gdrom_id { |
108 | char mid; |
109 | char modid; |
110 | char verid; |
111 | char padA[13]; |
112 | char mname[16]; |
113 | char modname[16]; |
114 | char firmver[16]; |
115 | char padB[16]; |
116 | }; |
117 | |
118 | static int gdrom_getsense(short *bufstring); |
119 | static int gdrom_packetcommand(struct cdrom_device_info *cd_info, |
120 | struct packet_command *command); |
121 | static int gdrom_hardreset(struct cdrom_device_info *cd_info); |
122 | |
123 | static bool gdrom_is_busy(void) |
124 | { |
125 | return (__raw_readb(GDROM_ALTSTATUS_REG) & 0x80) != 0; |
126 | } |
127 | |
128 | static bool gdrom_data_request(void) |
129 | { |
130 | return (__raw_readb(GDROM_ALTSTATUS_REG) & 0x88) == 8; |
131 | } |
132 | |
133 | static bool gdrom_wait_clrbusy(void) |
134 | { |
135 | unsigned long timeout = jiffies + GDROM_DEFAULT_TIMEOUT; |
136 | while ((__raw_readb(GDROM_ALTSTATUS_REG) & 0x80) && |
137 | (time_before(jiffies, timeout))) |
138 | cpu_relax(); |
139 | return time_before(jiffies, timeout + 1); |
140 | } |
141 | |
142 | static bool gdrom_wait_busy_sleeps(void) |
143 | { |
144 | unsigned long timeout; |
145 | /* Wait to get busy first */ |
146 | timeout = jiffies + GDROM_DEFAULT_TIMEOUT; |
147 | while (!gdrom_is_busy() && time_before(jiffies, timeout)) |
148 | cpu_relax(); |
149 | /* Now wait for busy to clear */ |
150 | return gdrom_wait_clrbusy(); |
151 | } |
152 | |
153 | static void gdrom_identifydevice(void *buf) |
154 | { |
155 | int c; |
156 | short *data = buf; |
157 | /* If the device won't clear it has probably |
158 | * been hit by a serious failure - but we'll |
159 | * try to return a sense key even so */ |
160 | if (!gdrom_wait_clrbusy()) { |
161 | gdrom_getsense(NULL); |
162 | return; |
163 | } |
164 | __raw_writeb(GDROM_COM_IDDEV, GDROM_STATUSCOMMAND_REG); |
165 | if (!gdrom_wait_busy_sleeps()) { |
166 | gdrom_getsense(NULL); |
167 | return; |
168 | } |
169 | /* now read in the data */ |
170 | for (c = 0; c < 40; c++) |
171 | data[c] = __raw_readw(GDROM_DATA_REG); |
172 | } |
173 | |
174 | static void gdrom_spicommand(void *spi_string, int buflen) |
175 | { |
176 | short *cmd = spi_string; |
177 | unsigned long timeout; |
178 | |
179 | /* ensure IRQ_WAIT is set */ |
180 | __raw_writeb(val: 0x08, GDROM_ALTSTATUS_REG); |
181 | /* specify how many bytes we expect back */ |
182 | __raw_writeb(val: buflen & 0xFF, GDROM_BCL_REG); |
183 | __raw_writeb(val: (buflen >> 8) & 0xFF, GDROM_BCH_REG); |
184 | /* other parameters */ |
185 | __raw_writeb(val: 0, GDROM_INTSEC_REG); |
186 | __raw_writeb(val: 0, GDROM_SECNUM_REG); |
187 | __raw_writeb(val: 0, GDROM_ERROR_REG); |
188 | /* Wait until we can go */ |
189 | if (!gdrom_wait_clrbusy()) { |
190 | gdrom_getsense(NULL); |
191 | return; |
192 | } |
193 | timeout = jiffies + GDROM_DEFAULT_TIMEOUT; |
194 | __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); |
195 | while (!gdrom_data_request() && time_before(jiffies, timeout)) |
196 | cpu_relax(); |
197 | if (!time_before(jiffies, timeout + 1)) { |
198 | gdrom_getsense(NULL); |
199 | return; |
200 | } |
201 | outsw(GDROM_DATA_REG, addr: cmd, count: 6); |
202 | } |
203 | |
204 | |
205 | /* gdrom_command_executediagnostic: |
206 | * Used to probe for presence of working GDROM |
207 | * Restarts GDROM device and then applies standard ATA 3 |
208 | * Execute Diagnostic Command: a return of '1' indicates device 0 |
209 | * present and device 1 absent |
210 | */ |
211 | static char gdrom_execute_diagnostic(void) |
212 | { |
213 | gdrom_hardreset(cd_info: gd.cd_info); |
214 | if (!gdrom_wait_clrbusy()) |
215 | return 0; |
216 | __raw_writeb(GDROM_COM_EXECDIAG, GDROM_STATUSCOMMAND_REG); |
217 | if (!gdrom_wait_busy_sleeps()) |
218 | return 0; |
219 | return __raw_readb(GDROM_ERROR_REG); |
220 | } |
221 | |
222 | /* |
223 | * Prepare disk command |
224 | * byte 0 = 0x70 |
225 | * byte 1 = 0x1f |
226 | */ |
227 | static int gdrom_preparedisk_cmd(void) |
228 | { |
229 | struct packet_command *spin_command; |
230 | spin_command = kzalloc(size: sizeof(struct packet_command), GFP_KERNEL); |
231 | if (!spin_command) |
232 | return -ENOMEM; |
233 | spin_command->cmd[0] = 0x70; |
234 | spin_command->cmd[2] = 0x1f; |
235 | spin_command->buflen = 0; |
236 | gd.pending = 1; |
237 | gdrom_packetcommand(cd_info: gd.cd_info, command: spin_command); |
238 | /* 60 second timeout */ |
239 | wait_event_interruptible_timeout(command_queue, gd.pending == 0, |
240 | GDROM_DEFAULT_TIMEOUT); |
241 | gd.pending = 0; |
242 | kfree(objp: spin_command); |
243 | if (gd.status & 0x01) { |
244 | /* log an error */ |
245 | gdrom_getsense(NULL); |
246 | return -EIO; |
247 | } |
248 | return 0; |
249 | } |
250 | |
251 | /* |
252 | * Read TOC command |
253 | * byte 0 = 0x14 |
254 | * byte 1 = session |
255 | * byte 3 = sizeof TOC >> 8 ie upper byte |
256 | * byte 4 = sizeof TOC & 0xff ie lower byte |
257 | */ |
258 | static int gdrom_readtoc_cmd(struct gdromtoc *toc, int session) |
259 | { |
260 | int tocsize; |
261 | struct packet_command *toc_command; |
262 | int err = 0; |
263 | |
264 | toc_command = kzalloc(size: sizeof(struct packet_command), GFP_KERNEL); |
265 | if (!toc_command) |
266 | return -ENOMEM; |
267 | tocsize = sizeof(struct gdromtoc); |
268 | toc_command->cmd[0] = 0x14; |
269 | toc_command->cmd[1] = session; |
270 | toc_command->cmd[3] = tocsize >> 8; |
271 | toc_command->cmd[4] = tocsize & 0xff; |
272 | toc_command->buflen = tocsize; |
273 | if (gd.pending) { |
274 | err = -EBUSY; |
275 | goto cleanup_readtoc_final; |
276 | } |
277 | gd.pending = 1; |
278 | gdrom_packetcommand(cd_info: gd.cd_info, command: toc_command); |
279 | wait_event_interruptible_timeout(command_queue, gd.pending == 0, |
280 | GDROM_DEFAULT_TIMEOUT); |
281 | if (gd.pending) { |
282 | err = -EINVAL; |
283 | goto cleanup_readtoc; |
284 | } |
285 | insw(GDROM_DATA_REG, addr: toc, count: tocsize/2); |
286 | if (gd.status & 0x01) |
287 | err = -EINVAL; |
288 | |
289 | cleanup_readtoc: |
290 | gd.pending = 0; |
291 | cleanup_readtoc_final: |
292 | kfree(objp: toc_command); |
293 | return err; |
294 | } |
295 | |
296 | /* TOC helpers */ |
297 | static int get_entry_lba(int track) |
298 | { |
299 | return (cpu_to_be32(track & 0xffffff00) - GD_SESSION_OFFSET); |
300 | } |
301 | |
302 | static int get_entry_q_ctrl(int track) |
303 | { |
304 | return (track & 0x000000f0) >> 4; |
305 | } |
306 | |
307 | static int get_entry_track(int track) |
308 | { |
309 | return (track & 0x0000ff00) >> 8; |
310 | } |
311 | |
312 | static int gdrom_get_last_session(struct cdrom_device_info *cd_info, |
313 | struct cdrom_multisession *ms_info) |
314 | { |
315 | int fentry, lentry, track, data, err; |
316 | |
317 | if (!gd.toc) |
318 | return -ENOMEM; |
319 | |
320 | /* Check if GD-ROM */ |
321 | err = gdrom_readtoc_cmd(toc: gd.toc, session: 1); |
322 | /* Not a GD-ROM so check if standard CD-ROM */ |
323 | if (err) { |
324 | err = gdrom_readtoc_cmd(toc: gd.toc, session: 0); |
325 | if (err) { |
326 | pr_info("Could not get CD table of contents\n" ); |
327 | return -ENXIO; |
328 | } |
329 | } |
330 | |
331 | fentry = get_entry_track(track: gd.toc->first); |
332 | lentry = get_entry_track(track: gd.toc->last); |
333 | /* Find the first data track */ |
334 | track = get_entry_track(track: gd.toc->last); |
335 | do { |
336 | data = gd.toc->entry[track - 1]; |
337 | if (get_entry_q_ctrl(track: data)) |
338 | break; /* ie a real data track */ |
339 | track--; |
340 | } while (track >= fentry); |
341 | |
342 | if ((track > 100) || (track < get_entry_track(track: gd.toc->first))) { |
343 | pr_info("No data on the last session of the CD\n" ); |
344 | gdrom_getsense(NULL); |
345 | return -ENXIO; |
346 | } |
347 | |
348 | ms_info->addr_format = CDROM_LBA; |
349 | ms_info->addr.lba = get_entry_lba(track: data); |
350 | ms_info->xa_flag = 1; |
351 | return 0; |
352 | } |
353 | |
354 | static int gdrom_open(struct cdrom_device_info *cd_info, int purpose) |
355 | { |
356 | /* spin up the disk */ |
357 | return gdrom_preparedisk_cmd(); |
358 | } |
359 | |
360 | /* this function is required even if empty */ |
361 | static void gdrom_release(struct cdrom_device_info *cd_info) |
362 | { |
363 | } |
364 | |
365 | static int gdrom_drivestatus(struct cdrom_device_info *cd_info, int ignore) |
366 | { |
367 | /* read the sense key */ |
368 | char sense = __raw_readb(GDROM_ERROR_REG); |
369 | sense &= 0xF0; |
370 | if (sense == 0) |
371 | return CDS_DISC_OK; |
372 | if (sense == 0x20) |
373 | return CDS_DRIVE_NOT_READY; |
374 | /* default */ |
375 | return CDS_NO_INFO; |
376 | } |
377 | |
378 | static unsigned int gdrom_check_events(struct cdrom_device_info *cd_info, |
379 | unsigned int clearing, int ignore) |
380 | { |
381 | /* check the sense key */ |
382 | return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60 ? |
383 | DISK_EVENT_MEDIA_CHANGE : 0; |
384 | } |
385 | |
386 | /* reset the G1 bus */ |
387 | static int gdrom_hardreset(struct cdrom_device_info *cd_info) |
388 | { |
389 | int count; |
390 | __raw_writel(val: 0x1fffff, GDROM_RESET_REG); |
391 | for (count = 0xa0000000; count < 0xa0200000; count += 4) |
392 | __raw_readl(addr: count); |
393 | return 0; |
394 | } |
395 | |
396 | /* keep the function looking like the universal |
397 | * CD Rom specification - returning int */ |
398 | static int gdrom_packetcommand(struct cdrom_device_info *cd_info, |
399 | struct packet_command *command) |
400 | { |
401 | gdrom_spicommand(spi_string: &command->cmd, buflen: command->buflen); |
402 | return 0; |
403 | } |
404 | |
405 | /* Get Sense SPI command |
406 | * From Marcus Comstedt |
407 | * cmd = 0x13 |
408 | * cmd + 4 = length of returned buffer |
409 | * Returns 5 16 bit words |
410 | */ |
411 | static int gdrom_getsense(short *bufstring) |
412 | { |
413 | struct packet_command *sense_command; |
414 | short sense[5]; |
415 | int sense_key; |
416 | int err = -EIO; |
417 | |
418 | sense_command = kzalloc(size: sizeof(struct packet_command), GFP_KERNEL); |
419 | if (!sense_command) |
420 | return -ENOMEM; |
421 | sense_command->cmd[0] = 0x13; |
422 | sense_command->cmd[4] = 10; |
423 | sense_command->buflen = 10; |
424 | /* even if something is pending try to get |
425 | * the sense key if possible */ |
426 | if (gd.pending && !gdrom_wait_clrbusy()) { |
427 | err = -EBUSY; |
428 | goto cleanup_sense_final; |
429 | } |
430 | gd.pending = 1; |
431 | gdrom_packetcommand(cd_info: gd.cd_info, command: sense_command); |
432 | wait_event_interruptible_timeout(command_queue, gd.pending == 0, |
433 | GDROM_DEFAULT_TIMEOUT); |
434 | if (gd.pending) |
435 | goto cleanup_sense; |
436 | insw(GDROM_DATA_REG, addr: &sense, count: sense_command->buflen/2); |
437 | if (sense[1] & 40) { |
438 | pr_info("Drive not ready - command aborted\n" ); |
439 | goto cleanup_sense; |
440 | } |
441 | sense_key = sense[1] & 0x0F; |
442 | if (sense_key < ARRAY_SIZE(sense_texts)) |
443 | pr_info("%s\n" , sense_texts[sense_key].text); |
444 | else |
445 | pr_err("Unknown sense key: %d\n" , sense_key); |
446 | if (bufstring) /* return addional sense data */ |
447 | memcpy(bufstring, &sense[4], 2); |
448 | if (sense_key < 2) |
449 | err = 0; |
450 | |
451 | cleanup_sense: |
452 | gd.pending = 0; |
453 | cleanup_sense_final: |
454 | kfree(objp: sense_command); |
455 | return err; |
456 | } |
457 | |
458 | static int gdrom_audio_ioctl(struct cdrom_device_info *cdi, unsigned int cmd, |
459 | void *arg) |
460 | { |
461 | return -EINVAL; |
462 | } |
463 | |
464 | static const struct cdrom_device_ops gdrom_ops = { |
465 | .open = gdrom_open, |
466 | .release = gdrom_release, |
467 | .drive_status = gdrom_drivestatus, |
468 | .check_events = gdrom_check_events, |
469 | .get_last_session = gdrom_get_last_session, |
470 | .reset = gdrom_hardreset, |
471 | .audio_ioctl = gdrom_audio_ioctl, |
472 | .generic_packet = cdrom_dummy_generic_packet, |
473 | .capability = CDC_MULTI_SESSION | CDC_MEDIA_CHANGED | |
474 | CDC_RESET | CDC_DRIVE_STATUS | CDC_CD_R, |
475 | }; |
476 | |
477 | static int gdrom_bdops_open(struct gendisk *disk, blk_mode_t mode) |
478 | { |
479 | int ret; |
480 | |
481 | disk_check_media_change(disk); |
482 | |
483 | mutex_lock(&gdrom_mutex); |
484 | ret = cdrom_open(cdi: gd.cd_info, mode); |
485 | mutex_unlock(lock: &gdrom_mutex); |
486 | return ret; |
487 | } |
488 | |
489 | static void gdrom_bdops_release(struct gendisk *disk) |
490 | { |
491 | mutex_lock(&gdrom_mutex); |
492 | cdrom_release(cdi: gd.cd_info); |
493 | mutex_unlock(lock: &gdrom_mutex); |
494 | } |
495 | |
496 | static unsigned int gdrom_bdops_check_events(struct gendisk *disk, |
497 | unsigned int clearing) |
498 | { |
499 | return cdrom_check_events(cdi: gd.cd_info, clearing); |
500 | } |
501 | |
502 | static int gdrom_bdops_ioctl(struct block_device *bdev, blk_mode_t mode, |
503 | unsigned cmd, unsigned long arg) |
504 | { |
505 | int ret; |
506 | |
507 | mutex_lock(&gdrom_mutex); |
508 | ret = cdrom_ioctl(cdi: gd.cd_info, bdev, cmd, arg); |
509 | mutex_unlock(lock: &gdrom_mutex); |
510 | |
511 | return ret; |
512 | } |
513 | |
514 | static const struct block_device_operations gdrom_bdops = { |
515 | .owner = THIS_MODULE, |
516 | .open = gdrom_bdops_open, |
517 | .release = gdrom_bdops_release, |
518 | .check_events = gdrom_bdops_check_events, |
519 | .ioctl = gdrom_bdops_ioctl, |
520 | #ifdef CONFIG_COMPAT |
521 | .compat_ioctl = blkdev_compat_ptr_ioctl, |
522 | #endif |
523 | }; |
524 | |
525 | static irqreturn_t gdrom_command_interrupt(int irq, void *dev_id) |
526 | { |
527 | gd.status = __raw_readb(GDROM_STATUSCOMMAND_REG); |
528 | if (gd.pending != 1) |
529 | return IRQ_HANDLED; |
530 | gd.pending = 0; |
531 | wake_up_interruptible(&command_queue); |
532 | return IRQ_HANDLED; |
533 | } |
534 | |
535 | static irqreturn_t gdrom_dma_interrupt(int irq, void *dev_id) |
536 | { |
537 | gd.status = __raw_readb(GDROM_STATUSCOMMAND_REG); |
538 | if (gd.transfer != 1) |
539 | return IRQ_HANDLED; |
540 | gd.transfer = 0; |
541 | wake_up_interruptible(&request_queue); |
542 | return IRQ_HANDLED; |
543 | } |
544 | |
545 | static int gdrom_set_interrupt_handlers(void) |
546 | { |
547 | int err; |
548 | |
549 | err = request_irq(irq: HW_EVENT_GDROM_CMD, handler: gdrom_command_interrupt, |
550 | flags: 0, name: "gdrom_command" , dev: &gd); |
551 | if (err) |
552 | return err; |
553 | err = request_irq(irq: HW_EVENT_GDROM_DMA, handler: gdrom_dma_interrupt, |
554 | flags: 0, name: "gdrom_dma" , dev: &gd); |
555 | if (err) |
556 | free_irq(HW_EVENT_GDROM_CMD, &gd); |
557 | return err; |
558 | } |
559 | |
560 | /* Implement DMA read using SPI command |
561 | * 0 -> 0x30 |
562 | * 1 -> mode |
563 | * 2 -> block >> 16 |
564 | * 3 -> block >> 8 |
565 | * 4 -> block |
566 | * 8 -> sectors >> 16 |
567 | * 9 -> sectors >> 8 |
568 | * 10 -> sectors |
569 | */ |
570 | static blk_status_t gdrom_readdisk_dma(struct request *req) |
571 | { |
572 | int block, block_cnt; |
573 | blk_status_t err; |
574 | struct packet_command *read_command; |
575 | unsigned long timeout; |
576 | |
577 | read_command = kzalloc(size: sizeof(struct packet_command), GFP_KERNEL); |
578 | if (!read_command) |
579 | return BLK_STS_RESOURCE; |
580 | |
581 | read_command->cmd[0] = 0x30; |
582 | read_command->cmd[1] = 0x20; |
583 | block = blk_rq_pos(rq: req)/GD_TO_BLK + GD_SESSION_OFFSET; |
584 | block_cnt = blk_rq_sectors(rq: req)/GD_TO_BLK; |
585 | __raw_writel(page_to_phys(bio_page(req->bio)) + bio_offset(req->bio), |
586 | GDROM_DMA_STARTADDR_REG); |
587 | __raw_writel(val: block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); |
588 | __raw_writel(val: 1, GDROM_DMA_DIRECTION_REG); |
589 | __raw_writel(val: 1, GDROM_DMA_ENABLE_REG); |
590 | read_command->cmd[2] = (block >> 16) & 0xFF; |
591 | read_command->cmd[3] = (block >> 8) & 0xFF; |
592 | read_command->cmd[4] = block & 0xFF; |
593 | read_command->cmd[8] = (block_cnt >> 16) & 0xFF; |
594 | read_command->cmd[9] = (block_cnt >> 8) & 0xFF; |
595 | read_command->cmd[10] = block_cnt & 0xFF; |
596 | /* set for DMA */ |
597 | __raw_writeb(val: 1, GDROM_ERROR_REG); |
598 | /* other registers */ |
599 | __raw_writeb(val: 0, GDROM_SECNUM_REG); |
600 | __raw_writeb(val: 0, GDROM_BCL_REG); |
601 | __raw_writeb(val: 0, GDROM_BCH_REG); |
602 | __raw_writeb(val: 0, GDROM_DSEL_REG); |
603 | __raw_writeb(val: 0, GDROM_INTSEC_REG); |
604 | /* Wait for registers to reset after any previous activity */ |
605 | timeout = jiffies + HZ / 2; |
606 | while (gdrom_is_busy() && time_before(jiffies, timeout)) |
607 | cpu_relax(); |
608 | __raw_writeb(GDROM_COM_PACKET, GDROM_STATUSCOMMAND_REG); |
609 | timeout = jiffies + HZ / 2; |
610 | /* Wait for packet command to finish */ |
611 | while (gdrom_is_busy() && time_before(jiffies, timeout)) |
612 | cpu_relax(); |
613 | gd.pending = 1; |
614 | gd.transfer = 1; |
615 | outsw(GDROM_DATA_REG, addr: &read_command->cmd, count: 6); |
616 | timeout = jiffies + HZ / 2; |
617 | /* Wait for any pending DMA to finish */ |
618 | while (__raw_readb(GDROM_DMA_STATUS_REG) && |
619 | time_before(jiffies, timeout)) |
620 | cpu_relax(); |
621 | /* start transfer */ |
622 | __raw_writeb(val: 1, GDROM_DMA_STATUS_REG); |
623 | wait_event_interruptible_timeout(request_queue, |
624 | gd.transfer == 0, GDROM_DEFAULT_TIMEOUT); |
625 | err = gd.transfer ? BLK_STS_IOERR : BLK_STS_OK; |
626 | gd.transfer = 0; |
627 | gd.pending = 0; |
628 | |
629 | blk_mq_end_request(rq: req, error: err); |
630 | kfree(objp: read_command); |
631 | return BLK_STS_OK; |
632 | } |
633 | |
634 | static blk_status_t gdrom_queue_rq(struct blk_mq_hw_ctx *hctx, |
635 | const struct blk_mq_queue_data *bd) |
636 | { |
637 | blk_mq_start_request(rq: bd->rq); |
638 | |
639 | switch (req_op(req: bd->rq)) { |
640 | case REQ_OP_READ: |
641 | return gdrom_readdisk_dma(req: bd->rq); |
642 | case REQ_OP_WRITE: |
643 | pr_notice("Read only device - write request ignored\n" ); |
644 | return BLK_STS_IOERR; |
645 | default: |
646 | printk(KERN_DEBUG "gdrom: Non-fs request ignored\n" ); |
647 | return BLK_STS_IOERR; |
648 | } |
649 | } |
650 | |
651 | /* Print string identifying GD ROM device */ |
652 | static int gdrom_outputversion(void) |
653 | { |
654 | struct gdrom_id *id; |
655 | char *model_name, *manuf_name, *firmw_ver; |
656 | int err = -ENOMEM; |
657 | |
658 | /* query device ID */ |
659 | id = kzalloc(size: sizeof(struct gdrom_id), GFP_KERNEL); |
660 | if (!id) |
661 | return err; |
662 | gdrom_identifydevice(buf: id); |
663 | model_name = kstrndup(s: id->modname, len: 16, GFP_KERNEL); |
664 | if (!model_name) |
665 | goto free_id; |
666 | manuf_name = kstrndup(s: id->mname, len: 16, GFP_KERNEL); |
667 | if (!manuf_name) |
668 | goto free_model_name; |
669 | firmw_ver = kstrndup(s: id->firmver, len: 16, GFP_KERNEL); |
670 | if (!firmw_ver) |
671 | goto free_manuf_name; |
672 | pr_info("%s from %s with firmware %s\n" , |
673 | model_name, manuf_name, firmw_ver); |
674 | err = 0; |
675 | kfree(objp: firmw_ver); |
676 | free_manuf_name: |
677 | kfree(objp: manuf_name); |
678 | free_model_name: |
679 | kfree(objp: model_name); |
680 | free_id: |
681 | kfree(objp: id); |
682 | return err; |
683 | } |
684 | |
685 | /* set the default mode for DMA transfer */ |
686 | static int gdrom_init_dma_mode(void) |
687 | { |
688 | __raw_writeb(val: 0x13, GDROM_ERROR_REG); |
689 | __raw_writeb(val: 0x22, GDROM_INTSEC_REG); |
690 | if (!gdrom_wait_clrbusy()) |
691 | return -EBUSY; |
692 | __raw_writeb(val: 0xEF, GDROM_STATUSCOMMAND_REG); |
693 | if (!gdrom_wait_busy_sleeps()) |
694 | return -EBUSY; |
695 | /* Memory protection setting for GDROM DMA |
696 | * Bits 31 - 16 security: 0x8843 |
697 | * Bits 15 and 7 reserved (0) |
698 | * Bits 14 - 8 start of transfer range in 1 MB blocks OR'ed with 0x80 |
699 | * Bits 6 - 0 end of transfer range in 1 MB blocks OR'ed with 0x80 |
700 | * (0x40 | 0x80) = start range at 0x0C000000 |
701 | * (0x7F | 0x80) = end range at 0x0FFFFFFF */ |
702 | __raw_writel(val: 0x8843407F, GDROM_DMA_ACCESS_CTRL_REG); |
703 | __raw_writel(val: 9, GDROM_DMA_WAIT_REG); /* DMA word setting */ |
704 | return 0; |
705 | } |
706 | |
707 | static void probe_gdrom_setupcd(void) |
708 | { |
709 | gd.cd_info->ops = &gdrom_ops; |
710 | gd.cd_info->capacity = 1; |
711 | strcpy(p: gd.cd_info->name, GDROM_DEV_NAME); |
712 | gd.cd_info->mask = CDC_CLOSE_TRAY|CDC_OPEN_TRAY|CDC_LOCK| |
713 | CDC_SELECT_DISC; |
714 | } |
715 | |
716 | static void probe_gdrom_setupdisk(void) |
717 | { |
718 | gd.disk->major = gdrom_major; |
719 | gd.disk->first_minor = 1; |
720 | gd.disk->minors = 1; |
721 | gd.disk->flags |= GENHD_FL_NO_PART; |
722 | strcpy(p: gd.disk->disk_name, GDROM_DEV_NAME); |
723 | } |
724 | |
725 | static int probe_gdrom_setupqueue(void) |
726 | { |
727 | blk_queue_logical_block_size(gd.gdrom_rq, GDROM_HARD_SECTOR); |
728 | /* using DMA so memory will need to be contiguous */ |
729 | blk_queue_max_segments(gd.gdrom_rq, 1); |
730 | /* set a large max size to get most from DMA */ |
731 | blk_queue_max_segment_size(gd.gdrom_rq, 0x40000); |
732 | gd.disk->queue = gd.gdrom_rq; |
733 | return gdrom_init_dma_mode(); |
734 | } |
735 | |
736 | static const struct blk_mq_ops gdrom_mq_ops = { |
737 | .queue_rq = gdrom_queue_rq, |
738 | }; |
739 | |
740 | /* |
741 | * register this as a block device and as compliant with the |
742 | * universal CD Rom driver interface |
743 | */ |
744 | static int probe_gdrom(struct platform_device *devptr) |
745 | { |
746 | int err; |
747 | |
748 | /* |
749 | * Ensure our "one" device is initialized properly in case of previous |
750 | * usages of it |
751 | */ |
752 | memset(&gd, 0, sizeof(gd)); |
753 | |
754 | /* Start the device */ |
755 | if (gdrom_execute_diagnostic() != 1) { |
756 | pr_warn("ATA Probe for GDROM failed\n" ); |
757 | return -ENODEV; |
758 | } |
759 | /* Print out firmware ID */ |
760 | if (gdrom_outputversion()) |
761 | return -ENOMEM; |
762 | /* Register GDROM */ |
763 | gdrom_major = register_blkdev(0, GDROM_DEV_NAME); |
764 | if (gdrom_major <= 0) |
765 | return gdrom_major; |
766 | pr_info("Registered with major number %d\n" , |
767 | gdrom_major); |
768 | /* Specify basic properties of drive */ |
769 | gd.cd_info = kzalloc(size: sizeof(struct cdrom_device_info), GFP_KERNEL); |
770 | if (!gd.cd_info) { |
771 | err = -ENOMEM; |
772 | goto probe_fail_no_mem; |
773 | } |
774 | probe_gdrom_setupcd(); |
775 | |
776 | err = blk_mq_alloc_sq_tag_set(set: &gd.tag_set, ops: &gdrom_mq_ops, queue_depth: 1, |
777 | set_flags: BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); |
778 | if (err) |
779 | goto probe_fail_free_cd_info; |
780 | |
781 | gd.disk = blk_mq_alloc_disk(&gd.tag_set, NULL); |
782 | if (IS_ERR(ptr: gd.disk)) { |
783 | err = PTR_ERR(ptr: gd.disk); |
784 | goto probe_fail_free_tag_set; |
785 | } |
786 | gd.gdrom_rq = gd.disk->queue; |
787 | probe_gdrom_setupdisk(); |
788 | if (register_cdrom(disk: gd.disk, cdi: gd.cd_info)) { |
789 | err = -ENODEV; |
790 | goto probe_fail_cleanup_disk; |
791 | } |
792 | gd.disk->fops = &gdrom_bdops; |
793 | gd.disk->events = DISK_EVENT_MEDIA_CHANGE; |
794 | /* latch on to the interrupt */ |
795 | err = gdrom_set_interrupt_handlers(); |
796 | if (err) |
797 | goto probe_fail_cleanup_disk; |
798 | |
799 | err = probe_gdrom_setupqueue(); |
800 | if (err) |
801 | goto probe_fail_free_irqs; |
802 | |
803 | gd.toc = kzalloc(size: sizeof(struct gdromtoc), GFP_KERNEL); |
804 | if (!gd.toc) { |
805 | err = -ENOMEM; |
806 | goto probe_fail_free_irqs; |
807 | } |
808 | err = add_disk(disk: gd.disk); |
809 | if (err) |
810 | goto probe_fail_add_disk; |
811 | |
812 | return 0; |
813 | |
814 | probe_fail_add_disk: |
815 | kfree(objp: gd.toc); |
816 | probe_fail_free_irqs: |
817 | free_irq(HW_EVENT_GDROM_DMA, &gd); |
818 | free_irq(HW_EVENT_GDROM_CMD, &gd); |
819 | probe_fail_cleanup_disk: |
820 | put_disk(disk: gd.disk); |
821 | probe_fail_free_tag_set: |
822 | blk_mq_free_tag_set(set: &gd.tag_set); |
823 | probe_fail_free_cd_info: |
824 | kfree(objp: gd.cd_info); |
825 | probe_fail_no_mem: |
826 | unregister_blkdev(major: gdrom_major, GDROM_DEV_NAME); |
827 | gdrom_major = 0; |
828 | pr_warn("Probe failed - error is 0x%X\n" , err); |
829 | return err; |
830 | } |
831 | |
832 | static int remove_gdrom(struct platform_device *devptr) |
833 | { |
834 | blk_mq_free_tag_set(set: &gd.tag_set); |
835 | free_irq(HW_EVENT_GDROM_CMD, &gd); |
836 | free_irq(HW_EVENT_GDROM_DMA, &gd); |
837 | del_gendisk(gp: gd.disk); |
838 | if (gdrom_major) |
839 | unregister_blkdev(major: gdrom_major, GDROM_DEV_NAME); |
840 | unregister_cdrom(cdi: gd.cd_info); |
841 | kfree(objp: gd.cd_info); |
842 | kfree(objp: gd.toc); |
843 | |
844 | return 0; |
845 | } |
846 | |
847 | static struct platform_driver gdrom_driver = { |
848 | .probe = probe_gdrom, |
849 | .remove = remove_gdrom, |
850 | .driver = { |
851 | .name = GDROM_DEV_NAME, |
852 | }, |
853 | }; |
854 | |
855 | static int __init init_gdrom(void) |
856 | { |
857 | int rc; |
858 | |
859 | rc = platform_driver_register(&gdrom_driver); |
860 | if (rc) |
861 | return rc; |
862 | pd = platform_device_register_simple(GDROM_DEV_NAME, id: -1, NULL, num: 0); |
863 | if (IS_ERR(ptr: pd)) { |
864 | platform_driver_unregister(&gdrom_driver); |
865 | return PTR_ERR(ptr: pd); |
866 | } |
867 | return 0; |
868 | } |
869 | |
870 | static void __exit exit_gdrom(void) |
871 | { |
872 | platform_device_unregister(pd); |
873 | platform_driver_unregister(&gdrom_driver); |
874 | } |
875 | |
876 | module_init(init_gdrom); |
877 | module_exit(exit_gdrom); |
878 | MODULE_AUTHOR("Adrian McMenamin <adrian@mcmen.demon.co.uk>" ); |
879 | MODULE_DESCRIPTION("SEGA Dreamcast GD-ROM Driver" ); |
880 | MODULE_LICENSE("GPL" ); |
881 | |