00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/irq.h>
00016 #include <agnix/adi/adi.h>
00017 #include <agnix/memory.h>
00018 #include <agnix/ioport.h>
00019 #include <agnix/list.h>
00020 #include <agnix/spinlock.h>
00021 #include <agnix/console.h>
00022
00023 #define MOD_NAME "FLOPPY: "
00024
00025 u8 floppy_DOR = DOR_DMA_GATE_NEG | DOR_RESET_NEG;
00026 int floppy_was_request = 0;
00027
00028 extern struct chip_s dma_chip;
00029
00030 int floppy_reset(void)
00031 {
00032 return 0;
00033 }
00034
00035 int floppy_set_defaults(void)
00036 {
00037 outb(floppy_DOR, FLOPPY_DOR);
00038
00039 return 0;
00040 }
00041
00042 int floppy_request_command(u8 command)
00043 {
00044 int i;
00045 u8 msr;
00046
00047 for (i = 0; i < FLOPPY_MAX_POLL_REQ_REPLIES; i++) {
00048 msr = inb(FLOPPY_MSR);
00049 if ((msr & MSR_RQM) && (!(msr & MSR_DIO))) {
00050 printk("send command ok\n");
00051 outb(command, FLOPPY_FIFO);
00052 return 0;
00053 }
00054 }
00055
00056 floppy_was_request = 1;
00057
00058 return -1;
00059 }
00060
00061 int floppy_result_command(u8 *result_buf, int max_len)
00062 {
00063 int i;
00064 int k = 0;
00065 u8 msr;
00066
00067 for (k = 0; k < max_len; k++) {
00068 for (i = 0; i < FLOPPY_MAX_POLL_RES_REPLIES; i++) {
00069 msr = inb(FLOPPY_MSR);
00070 if ((msr & (MSR_RQM | MSR_DIO | MSR_CMD_BUSY)) == (MSR_RQM | MSR_DIO | MSR_CMD_BUSY)) {
00071 result_buf[k] = inb(FLOPPY_FIFO);
00072 break;
00073 }
00074 }
00075
00076 if (i == FLOPPY_MAX_POLL_RES_REPLIES) {
00077 printk(MOD_NAME "%d %x\n", k, msr);
00078 break;
00079 }
00080 }
00081
00082 floppy_was_request = 0;
00083
00084 return k;
00085 }
00086
00087 int floppy_interrupt_check(void)
00088 {
00089 return floppy_was_request;
00090 }
00091
00092 void floppy_interrupt(u32 irq)
00093 {
00094 printk("floppy irq\n");
00095 }
00096
00097
00098 void floppy_motor_on(void)
00099 {
00100 floppy_DOR |= DOR_MOT_EN0;
00101 outb(floppy_DOR, FLOPPY_DOR);
00102 }
00103
00104 void floppy_motor_off(void)
00105 {
00106 floppy_DOR &= ~DOR_MOT_EN0;
00107 outb(floppy_DOR, FLOPPY_DOR);
00108 }
00109
00110 int floppy_setup_DMA(struct adi_blkreq_s *blkreq)
00111 {
00112 dma_ops(&dma_chip)->dma_lock (&dma_chip);
00113 dma_ops(&dma_chip)->dma_disable (&dma_chip, FLOPPY_DMA);
00114 dma_ops(&dma_chip)->dma_clear_ff (&dma_chip, FLOPPY_DMA);
00115 dma_ops(&dma_chip)->dma_set_mode (&dma_chip, FLOPPY_DMA, DMA_MODE_READ);
00116 dma_ops(&dma_chip)->dma_set_addr (&dma_chip, FLOPPY_DMA, (u32)virt_to_phys(blkreq->req_buf));
00117 dma_ops(&dma_chip)->dma_set_count(&dma_chip, FLOPPY_DMA, (u16)blkreq->req_len_bytes);
00118 dma_ops(&dma_chip)->dma_enable (&dma_chip, FLOPPY_DMA);
00119 dma_ops(&dma_chip)->dma_unlock (&dma_chip);
00120
00121 return 0;
00122 }
00123
00124 int floppy_request_read(struct adi_blkreq_s *blkreq)
00125 {
00126 floppy_setup_DMA(blkreq);
00127
00128 int i, k;
00129 for (k = 0; k < 4; k++) {
00130 floppy_motor_on();
00131 for (i = 0; i < 200000; i++);
00132 floppy_motor_off();
00133 for (i = 0; i < 200000; i++);
00134 }
00135
00136 return 0;
00137 }
00138
00139 int floppy_request_set_data(struct adi_blkreq_s *blkreq)
00140 {
00141 u32 req_pages = 1;
00142 u8 page_order = 0;
00143
00144 while((req_pages << PAGE_SHIFT) < blkreq->req_len_bytes) {
00145 req_pages <<= 1;
00146 page_order++;
00147 }
00148
00149 blkreq->req_buf = (u8 *)get_free_dma_pages(page_order);
00150
00151 return 0;
00152 }
00153
00154 int floppy_request(struct adi_blkreq_s *blkreq)
00155 {
00156
00157
00158 blkreq->req_len_bytes = 10;
00159 floppy_request_set_data(blkreq);
00160 floppy_request_read(blkreq);
00161
00162 return 0;
00163 }
00164
00165 int floppy_get_version(void)
00166 {
00167 int result_len;
00168 u8 result_buf[16];
00169
00170 floppy_request_command(FLOPPY_CMD_DUMPREGS);
00171 if ((result_len = floppy_result_command(result_buf, 16)) <= 0) {
00172 printk(MOD_NAME "bad FDC version\n");
00173 return -1;
00174 }
00175
00176 if (result_len == 1 && result_buf[0] == 0x80) {
00177 printk(MOD_NAME "FDC 8272A detected\n");
00178 return FLOPPY_VER_8272A;
00179 }
00180 else
00181 printk(MOD_NAME "FDC version = %02x\n", result_buf[0]);
00182
00183 floppy_request_command(FLOPPY_CMD_PARTID);
00184 if ((result_len = floppy_result_command(result_buf, 16)) != 1) {
00185 printk(MOD_NAME "PARTID cmd error\n");
00186 return FLOPPY_VER_UNKNOWN;
00187 }
00188
00189 switch(result_buf[0]) {
00190 case 0x00:
00191 printk(MOD_NAME "FDC 82078 detected\n");
00192 return FLOPPY_VER_82078;
00193
00194 case 0x20:
00195 printk(MOD_NAME "FDC 44-pin 82078 detected\n");
00196 return FLOPPY_VER_82078;
00197
00198 case 0x40:
00199 printk(MOD_NAME "FDC 44-pin S82078B detected\n");
00200 return FLOPPY_VER_S82078B;
00201
00202 case 0x60:
00203 printk(MOD_NAME "FDC National Semiconductor PC87306 detected\n");
00204 return FLOPPY_VER_87306;
00205
00206 case 0x80:
00207 printk(MOD_NAME "FDC 82077 detected\n");
00208 return FLOPPY_VER_82077;
00209
00210 default:
00211 printk(MOD_NAME "FDC with unknown PARTID detected\n");
00212 return FLOPPY_VER_UNKNOWN;
00213 }
00214
00215 return -1;
00216 }
00217
00218 struct irq_routine_s floppy_irq = {
00219 .proc = floppy_interrupt,
00220 .check = floppy_interrupt_check,
00221 .flags = IRQ_FLAG_RANDOM
00222 };
00223
00224 int floppy_set_irq(void)
00225 {
00226 if (install_irq(FLOPPY_IRQ, &floppy_irq) < 0) {
00227 printk(MOD_NAME "can not install irq %d routine\n", FLOPPY_IRQ);
00228 return -1;
00229 }
00230
00231 return 0;
00232 }
00233
00234 int floppy_set_dma(void)
00235 {
00236 if (dma_ops(&dma_chip)->dma_request_channel(&dma_chip, FLOPPY_DMA) < 0) {
00237 printk(MOD_NAME "can not request dma %d channel\n", FLOPPY_DMA);
00238 return -1;
00239 }
00240
00241 return 0;
00242 }
00243
00244 int floppy_free_irq(void)
00245 {
00246 return free_irq(FLOPPY_IRQ, &floppy_irq);
00247 }
00248
00249 int floppy_free_dma(void)
00250 {
00251 if (dma_ops(&dma_chip)->dma_put_channel(&dma_chip, FLOPPY_DMA) < 0) {
00252 printk(MOD_NAME "can not free dma %d channel\n", FLOPPY_DMA);
00253 return -1;
00254 }
00255
00256 return 0;
00257 }
00258
00259 struct adi_blkdev_ops_s floppy_ops = {
00260 .block_req = floppy_request
00261 };
00262
00263 struct adi_blkdev_s floppy_dev = {
00264 .dev_name = "floppy",
00265 .dev_nr = BLKDEV_FLOPPY_NR,
00266 .dev_flags = BLKDEV_FLAG_DMA_REQ,
00267 .dev_ops = &floppy_ops
00268 };
00269
00270 int floppy_init(void)
00271 {
00272
00273 if (floppy_set_irq() < 0)
00274 return -1;
00275
00276 if (floppy_set_dma() < 0) {
00277 floppy_free_irq();
00278 return -1;
00279 }
00280
00281 adi_register_blkdev(&floppy_dev);
00282
00283 floppy_set_defaults();
00284 floppy_get_version();
00285
00286 return 0;
00287 }
00288
00289 int adi_blkdrv_floppy_init(void)
00290 {
00291 return floppy_init();
00292 }