Main Page | Directories | File List | Globals

floppy.c

Go to the documentation of this file.
00001 /*
00002  * kernel_drivers/adi_block/floppy.c
00003  *
00004  * Copyright (c) 2003-2004 Lukasz Dembinski <dembol@nasa.com.pl>
00005  * All Rights Reserved
00006  * 
00007  * Date:        2004/09
00008  * Author:      Lukasz Dembinski
00009  * Info:        floppy.c core file
00010  * Contact:     mailto: <dembol@nasa.com.pl>
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     /* TODO */
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 }
Dokumentacje wygenerowano programem Doxygen 1.4.2 dla projektu Agnix