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>
24 #include <asm/pgtable.h>
26 #include <asm/feature.h>
27 #include <asm/mediabay.h>
31 #undef MB_USE_INTERRUPTS
35 unsigned char contents
;
40 struct media_bay_info
{
41 volatile struct media_bay_hw
* addr
;
48 struct device_node
* dev_node
;
49 #ifdef CONFIG_BLK_DEV_IDE
50 unsigned long cd_base
;
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)
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.
104 struct device_node
*np
;
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;
116 np
= find_devices("media-bay");
118 while(np
&& (n
<MAX_BAYS
))
120 if (np
->n_addrs
== 0)
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
);
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
);
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
);
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;
158 printk(KERN_INFO
"Registered %d media-bay(s)\n", media_bay_count
);
160 kernel_thread(media_bay_task
, NULL
, 0);
166 media_bay_intr(int irq
, void *devid
, struct pt_regs
*regs
)
168 int id
= MB_CONTENTS();
176 check_media_bay(struct device_node
*which_bay
, int what
)
178 #ifdef CONFIG_BLK_DEV_IDE
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
)
186 media_bays
[i
].cd_index
= -1;
189 #endif /* CONFIG_BLK_DEV_IDE */
194 check_media_bay_by_base(unsigned long base
, int what
)
196 #ifdef CONFIG_BLK_DEV_IDE
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
)
204 media_bays
[i
].cd_index
= -1;
213 media_bay_set_ide_infos(struct device_node
* which_bay
, unsigned long base
,
216 #ifdef CONFIG_BLK_DEV_IDE
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
);
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.
240 media_bay_task(void *x
)
242 volatile struct media_bay_info
* bay
;
245 strcpy(current
->comm
, "media-bay");
248 bay
= &media_bays
[i
];
250 if (bay
->content_id
!= bay
->previous_id
) {
251 bay
->reset_timer
= (bay
->content_id
!= MB_NO
) ?
254 #ifdef CONFIG_BLK_DEV_IDE
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
);
262 } else if (bay
->reset_timer
) {
263 if (--bay
->reset_timer
== 0) {
264 feature_clear(bay
->dev_node
, FEATURE_Mediabay_reset
);
266 #ifdef CONFIG_BLK_DEV_IDE
268 if (bay
->content_id
== MB_CD
&& bay
->cd_base
!= 0)
269 bay
->cd_timer
= MB_IDE_WAIT
;
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) {
276 printk(KERN_DEBUG
"Registering IDE, base:0x%08lx, irq:%d\n", bay
->cd_base
, bay
->cd_irq
);
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");
282 printk(KERN_DEBUG
"media-bay %d is ide %d\n", i
, bay
->cd_index
);
286 bay
->previous_id
= bay
->content_id
;
287 current
->state
= TASK_INTERRUPTIBLE
;
289 if (signal_pending(current
))
291 i
= (i
+1)%media_bay_count
;
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
);
305 media_bays
[which
].last_value
= id
;
306 media_bays
[which
].value_count
= 0;
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
;
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
);
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
);
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
);
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",