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