Import 2.3.18pre1
[davej-history.git] / drivers / macintosh / mediabay.c
blob0936b8bfba4be967186d9c9576dc4931b232e1e4
1 /*
2 * Driver for the media bay on the PowerBook 3400 and 2400.
4 * Copyright (C) 1998 Paul Mackerras.
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
11 #define __KERNEL_SYSCALLS__
13 #include <linux/config.h>
14 #include <linux/types.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/delay.h>
18 #include <linux/sched.h>
19 #include <linux/timer.h>
20 #include <linux/hdreg.h>
21 #include <linux/stddef.h>
22 #include <linux/unistd.h>
23 #include <asm/prom.h>
24 #include <asm/pgtable.h>
25 #include <asm/io.h>
26 #include <asm/feature.h>
27 #include <asm/mediabay.h>
28 #include <asm/init.h>
31 #undef MB_USE_INTERRUPTS
33 struct media_bay_hw {
34 unsigned char b0;
35 unsigned char contents;
36 unsigned char b2;
37 unsigned char b3;
40 struct media_bay_info {
41 volatile struct media_bay_hw* addr;
42 int content_id;
43 int previous_id;
44 int ready;
45 int last_value;
46 int value_count;
47 int reset_timer;
48 struct device_node* dev_node;
49 #ifdef CONFIG_BLK_DEV_IDE
50 unsigned long cd_base;
51 int cd_index;
52 int cd_irq;
53 int cd_timer;
54 #endif
57 #define MAX_BAYS 2
59 static volatile struct media_bay_info media_bays[MAX_BAYS];
60 int media_bay_count = 0;
62 #define MB_CONTENTS(i) ((in_8(&media_bays[i].addr->contents) >> 4) & 7)
64 #ifdef CONFIG_BLK_DEV_IDE
65 /* check the busy bit in the media-bay ide interface
66 (assumes the media-bay contains an ide device) */
67 #define MB_IDE_READY(i) ((inb(media_bays[i].cd_base + 0x70) & 0x80) == 0)
68 #endif
71 * Consider the media-bay ID value stable if it is the same for
72 * this many consecutive samples (at intervals of 1/HZ seconds).
74 #define MB_STABLE_COUNT 4
77 * Hold the media-bay reset signal true for this many ticks
78 * after a device is inserted before releasing it.
80 #define MB_RESET_COUNT 20
83 * Wait this many ticks after an IDE device (e.g. CD-ROM) is inserted
84 * (or until the device is ready) before registering the IDE interface.
86 #define MB_IDE_WAIT 1000
88 static void poll_media_bay(int which);
89 static void set_media_bay(int which, int id);
90 static int media_bay_task(void *);
93 * It seems that the bit for the media-bay interrupt in the IRQ_LEVEL
94 * register is always set when there is something in the media bay.
95 * This causes problems for the interrupt code if we attach an interrupt
96 * handler to the media-bay interrupt, because it tends to go into
97 * an infinite loop calling the media bay interrupt handler.
98 * Therefore we do it all by polling the media bay once each tick.
101 void __pmac
102 media_bay_init(void)
104 struct device_node *np;
105 int n,i;
107 for (i=0; i<MAX_BAYS; i++)
109 memset((char *)&media_bays[i], 0, sizeof(struct media_bay_info));
110 media_bays[i].content_id = -1;
111 #ifdef CONFIG_BLK_DEV_IDE
112 media_bays[i].cd_index = -1;
113 #endif
116 np = find_devices("media-bay");
117 n = 0;
118 while(np && (n<MAX_BAYS))
120 if (np->n_addrs == 0)
121 continue;
122 media_bays[n].addr = (volatile struct media_bay_hw *)
123 ioremap(np->addrs[0].address, sizeof(struct media_bay_hw));
125 #ifdef MB_USE_INTERRUPTS
126 if (np->n_intrs == 0)
128 printk(KERN_ERR "media bay %d has no irq\n",n);
129 continue;
132 if (request_irq(np_intrs[0].line, media_bay_intr, 0, "Media bay", NULL))
134 printk(KERN_ERR "Couldn't get IRQ %d for media bay %d\n", irq, n);
135 continue;
137 #endif
138 media_bay_count++;
140 set_media_bay(n, MB_CONTENTS(n));
141 if (media_bays[n].content_id != MB_NO) {
142 feature_clear(media_bays[n].dev_node, FEATURE_Mediabay_reset);
143 udelay(500);
145 media_bays[n].ready = 1;
146 media_bays[n].previous_id = media_bays[n].content_id;
147 media_bays[n].reset_timer = 0;
148 media_bays[n].dev_node = np;
149 #ifdef CONFIG_BLK_DEV_IDE
150 media_bays[n].cd_timer = 0;
151 #endif
152 n++;
153 np=np->next;
156 if (media_bay_count)
158 printk(KERN_INFO "Registered %d media-bay(s)\n", media_bay_count);
160 kernel_thread(media_bay_task, NULL, 0);
164 #if 0
165 static void
166 media_bay_intr(int irq, void *devid, struct pt_regs *regs)
168 int id = MB_CONTENTS();
170 if (id == MB_NO)
171 set_media_bay(id);
173 #endif
175 int __pmac
176 check_media_bay(struct device_node *which_bay, int what)
178 #ifdef CONFIG_BLK_DEV_IDE
179 int i;
181 for (i=0; i<media_bay_count; i++)
182 if (which_bay == media_bays[i].dev_node)
184 if ((what == media_bays[i].content_id) && media_bays[i].ready)
185 return 0;
186 media_bays[i].cd_index = -1;
187 return -EINVAL;
189 #endif /* CONFIG_BLK_DEV_IDE */
190 return -ENODEV;
193 int __pmac
194 check_media_bay_by_base(unsigned long base, int what)
196 #ifdef CONFIG_BLK_DEV_IDE
197 int i;
199 for (i=0; i<media_bay_count; i++)
200 if (base == media_bays[i].cd_base)
202 if ((what == media_bays[i].content_id) && media_bays[i].ready)
203 return 0;
204 media_bays[i].cd_index = -1;
205 return -EINVAL;
207 #endif
209 return -ENODEV;
212 int __pmac
213 media_bay_set_ide_infos(struct device_node* which_bay, unsigned long base,
214 int irq, int index)
216 #ifdef CONFIG_BLK_DEV_IDE
217 int i;
219 for (i=0; i<media_bay_count; i++)
220 if (which_bay == media_bays[i].dev_node)
222 media_bays[i].cd_base = base;
223 media_bays[i].cd_irq = irq;
224 media_bays[i].cd_index = index;
225 printk(KERN_DEBUG "Registered ide %d for media bay %d\n", index, i);
226 return 0;
228 #endif
230 return -ENODEV;
234 * This procedure runs as a kernel thread to poll the media bay
235 * once each tick and register and unregister the IDE interface
236 * with the IDE driver. It needs to be a thread because
237 * ide_register can't be called from interrupt context.
239 int __pmac
240 media_bay_task(void *x)
242 volatile struct media_bay_info* bay;
243 int i = 0;
245 strcpy(current->comm, "media-bay");
246 for (;;)
248 bay = &media_bays[i];
249 poll_media_bay(i);
250 if (bay->content_id != bay->previous_id) {
251 bay->reset_timer = (bay->content_id != MB_NO) ?
252 MB_RESET_COUNT: 0;
253 bay->ready = 0;
254 #ifdef CONFIG_BLK_DEV_IDE
255 bay->cd_timer = 0;
256 if (bay->content_id != MB_CD && bay->cd_index >= 0) {
257 printk(KERN_DEBUG "Unregistering mb %d ide, index:%d\n", i, bay->cd_index);
258 ide_unregister(bay->cd_index);
259 bay->cd_index = -1;
261 #endif
262 } else if (bay->reset_timer) {
263 if (--bay->reset_timer == 0) {
264 feature_clear(bay->dev_node, FEATURE_Mediabay_reset);
265 bay->ready = 1;
266 #ifdef CONFIG_BLK_DEV_IDE
267 bay->cd_timer = 0;
268 if (bay->content_id == MB_CD && bay->cd_base != 0)
269 bay->cd_timer = MB_IDE_WAIT;
270 #endif
272 #ifdef CONFIG_BLK_DEV_IDE
273 } else if (bay->cd_timer && (--bay->cd_timer == 0 || MB_IDE_READY(i))
274 && bay->cd_index < 0) {
275 bay->cd_timer = 0;
276 printk(KERN_DEBUG "Registering IDE, base:0x%08lx, irq:%d\n", bay->cd_base, bay->cd_irq);
277 printk("\n");
278 bay->cd_index = ide_register(bay->cd_base, 0, bay->cd_irq);
279 if (bay->cd_index == -1)
280 printk("\nCD-ROM badly inserted. Remove it and try again !\n");
281 else
282 printk(KERN_DEBUG "media-bay %d is ide %d\n", i, bay->cd_index);
283 #endif
286 bay->previous_id = bay->content_id;
287 current->state = TASK_INTERRUPTIBLE;
288 schedule_timeout(1);
289 if (signal_pending(current))
290 return 0;
291 i = (i+1)%media_bay_count;
295 void __pmac
296 poll_media_bay(int which)
298 int id = MB_CONTENTS(which);
300 if (id == media_bays[which].last_value) {
301 if (id != media_bays[which].content_id
302 && ++media_bays[which].value_count >= MB_STABLE_COUNT)
303 set_media_bay(which, id);
304 } else {
305 media_bays[which].last_value = id;
306 media_bays[which].value_count = 0;
310 static void __pmac
311 set_media_bay(int which, int id)
313 volatile struct media_bay_info* bay;
315 bay = &media_bays[which];
317 bay->content_id = id;
318 bay->last_value = id;
320 switch (id) {
321 case MB_CD:
322 feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
323 feature_set(bay->dev_node, FEATURE_Mediabay_enable);
324 feature_set(bay->dev_node, FEATURE_CD_power);
325 feature_set(bay->dev_node, FEATURE_Mediabay_IDE_enable);
326 printk(KERN_INFO "media bay %d contains a CD-ROM drive\n", which);
327 break;
328 case MB_FD:
329 feature_clear(bay->dev_node, FEATURE_CD_power);
330 feature_set(bay->dev_node, FEATURE_Mediabay_enable);
331 feature_set(bay->dev_node, FEATURE_Mediabay_floppy_enable);
332 feature_set(bay->dev_node, FEATURE_SWIM3_enable);
333 printk(KERN_INFO "media bay %d contains a floppy disk drive\n", which);
334 break;
335 case MB_NO:
336 feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
337 feature_clear(bay->dev_node, FEATURE_CD_power);
338 printk(KERN_INFO "media bay %d is empty\n", which);
339 break;
340 default:
341 feature_clear(bay->dev_node, FEATURE_Mediabay_floppy_enable);
342 feature_clear(bay->dev_node, FEATURE_CD_power);
343 feature_set(bay->dev_node, FEATURE_Mediabay_enable);
344 printk(KERN_INFO "media bay %d contains an unknown device (%d)\n",
345 which, id);
346 break;
349 udelay(500);