/[dynamips]/upstream/dynamips-0.2.6-RC3/dev_pcmcia_disk.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /upstream/dynamips-0.2.6-RC3/dev_pcmcia_disk.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

upstream/dynamips-0.2.6-RC2/dev_pcmcia_disk.c revision 3 by dpavlin, Sat Oct 6 16:05:34 2007 UTC upstream/dynamips-0.2.6-RC3/dev_pcmcia_disk.c revision 4 by dpavlin, Sat Oct 6 16:06:49 2007 UTC
# Line 22  Line 22 
22    
23  #define DEBUG_ACCESS  0  #define DEBUG_ACCESS  0
24  #define DEBUG_ATA     0  #define DEBUG_ATA     0
25    #define DEBUG_READ    0
26    #define DEBUG_WRITE   0
27    
28  /* Default disk parameters: 4 heads, 32 sectors per track */  /* Default disk parameters: 4 heads, 32 sectors per track */
29  #define DISK_NR_HEADS         4  #define DISK_NR_HEADS         4
# Line 141  static int disk_read_sector(struct pcmci Line 143  static int disk_read_sector(struct pcmci
143  {  {
144     off_t disk_offset = (off_t)sect * SECTOR_SIZE;     off_t disk_offset = (off_t)sect * SECTOR_SIZE;
145    
146    #if DEBUG_READ
147       vm_log(d->vm,d->dev.name,"reading sector 0x%8.8x\n",sect);
148    #endif
149    
150     if (lseek(d->fd,disk_offset,SEEK_SET) == -1) {     if (lseek(d->fd,disk_offset,SEEK_SET) == -1) {
151        perror("read_sector: lseek");        perror("read_sector: lseek");
152        return(-1);        return(-1);
# Line 160  static int disk_write_sector(struct pcmc Line 166  static int disk_write_sector(struct pcmc
166  {    {  
167     off_t disk_offset = (off_t)sect * SECTOR_SIZE;     off_t disk_offset = (off_t)sect * SECTOR_SIZE;
168    
169    #if DEBUG_WRITE
170       vm_log(d->vm,d->dev.name,"writing sector 0x%8.8x\n",sect);
171    #endif
172    
173     if (lseek(d->fd,disk_offset,SEEK_SET) == -1) {     if (lseek(d->fd,disk_offset,SEEK_SET) == -1) {
174        perror("write_sector: lseek");        perror("write_sector: lseek");
175        return(-1);        return(-1);
# Line 182  static void ata_identify_device(struct p Line 192  static void ata_identify_device(struct p
192     sect_count = d->nr_heads * d->nr_cylinders * d->sects_per_track;     sect_count = d->nr_heads * d->nr_cylinders * d->sects_per_track;
193    
194     /* Clear all fields (for safety) */     /* Clear all fields (for safety) */
195     memset(p,0,SECTOR_SIZE);     memset(p,0x00,SECTOR_SIZE);
196    
197     /* Word 0: General Configuration */     /* Word 0: General Configuration */
198     p[0] = 0x8a;     p[0] = 0x8a;
# Line 222  static void ata_identify_device(struct p Line 232  static void ata_identify_device(struct p
232     /* Word 56: Current number of sectors per track */     /* Word 56: Current number of sectors per track */
233     p[112] = d->sects_per_track;     p[112] = d->sects_per_track;
234    
235     /* Word 57/58: Current of sectors per card (MSW/LSW) */     /* Word 57/58: Current of sectors per card (LSW/MSW) */
236     p[114] = (sect_count >> 16) & 0xFF;     p[114] = sect_count & 0xFF;
237     p[115] = (sect_count >> 24);     p[115] = (sect_count >> 8) & 0xFF;
238     p[116] = sect_count & 0xFF;  
239     p[117] = (sect_count >> 8) & 0xFF;     p[116] = (sect_count >> 16) & 0xFF;
240       p[117] = (sect_count >> 24);
241    
242    #if 0
243     /* Word 60/61: Total sectors addressable in LBA mode (MSW/LSW) */     /* Word 60/61: Total sectors addressable in LBA mode (MSW/LSW) */
244     p[120] = (sect_count >> 16) & 0xFF;     p[120] = (sect_count >> 16) & 0xFF;
245     p[121] = (sect_count >> 24);     p[121] = (sect_count >> 24);
246     p[122] = sect_count & 0xFF;     p[122] = sect_count & 0xFF;
247     p[123] = (sect_count >> 8) & 0xFF;     p[123] = (sect_count >> 8) & 0xFF;
248    #endif
249  }  }
250    
251  /* Set sector position */  /* Set sector position */
# Line 241  static void ata_set_sect_pos(struct pcmc Line 254  static void ata_set_sect_pos(struct pcmc
254     u_int cyl;     u_int cyl;
255    
256     if (d->head & ATA_DH_LBA) {     if (d->head & ATA_DH_LBA) {
257        /* TODO */        d->sect_pos  = (u_int)(d->head & 0x0F) << 24;
258     }        d->sect_pos |= (u_int)d->cyl_high << 16;
259          d->sect_pos |= (u_int)d->cyl_low  << 8;
260          d->sect_pos |= (u_int)d->sect_no;
261    
262     cyl = (((u_int)d->cyl_high) << 8) + d->cyl_low;  #if DEBUG_ATA
263     d->sect_pos = chs_to_lba(d,cyl,d->head & 0x0F,d->sect_no);        vm_log(d->vm,d->dev.name,"ata_set_sect_pos: LBA sect=0x%x\n",
264                 d->sect_pos);
265    #endif
266       } else {
267          cyl = (((u_int)d->cyl_high) << 8) + d->cyl_low;
268          d->sect_pos = chs_to_lba(d,cyl,d->head & 0x0F,d->sect_no);
269        
270    #if DEBUG_ATA
271          vm_log(d->vm,d->dev.name,
272                 "ata_set_sect_pos: cyl=0x%x,head=0x%x,sect=0x%x => "
273                 "sect_pos=0x%x\n",
274                 cyl,d->head & 0x0F,d->sect_no,d->sect_pos);
275    #endif
276       }
277  }  }
278    
279  /* ATA device identifier callback */  /* ATA device identifier callback */
# Line 292  static void ata_handle_cmd(struct pcmcia Line 320  static void ata_handle_cmd(struct pcmcia
320     vm_log(d->vm,d->dev.name,"ATA command 0x%2.2x\n",(u_int)d->ata_cmd);     vm_log(d->vm,d->dev.name,"ATA command 0x%2.2x\n",(u_int)d->ata_cmd);
321  #endif  #endif
322    
323       d->data_pos = 0;
324    
325     switch(d->ata_cmd) {     switch(d->ata_cmd) {
326        case ATA_CMD_IDENT_DEVICE:        case ATA_CMD_IDENT_DEVICE:
327           ata_identify_device(d);           ata_identify_device(d);
# Line 329  static void ata_handle_cmd(struct pcmcia Line 359  static void ata_handle_cmd(struct pcmcia
359  }  }
360    
361  /*  /*
362   * dev_pcmcia_disk_access()   * dev_pcmcia_disk_access_0()
363   */   */
364  void *dev_pcmcia_disk_access(cpu_mips_t *cpu,struct vdevice *dev,  void *dev_pcmcia_disk_access_0(cpu_mips_t *cpu,struct vdevice *dev,
365                               m_uint32_t offset,u_int op_size,u_int op_type,                                 m_uint32_t offset,u_int op_size,u_int op_type,
366                               m_uint64_t *data)                                 m_uint64_t *data)
367  {  {
368     struct pcmcia_disk_data *d = dev->priv_data;     struct pcmcia_disk_data *d = dev->priv_data;
    m_uint32_t d_offset;  
369    
370     /* Compute the good internal offset */     /* Compute the good internal offset */
371     offset = (offset >> 1) ^ 1;     offset = (offset >> 1) ^ 1;
# Line 390  void *dev_pcmcia_disk_access(cpu_mips_t Line 419  void *dev_pcmcia_disk_access(cpu_mips_t
419              *data = (d->ata_status << 8) + d->head;              *data = (d->ata_status << 8) + d->head;
420           else {           else {
421              d->ata_cmd = *data >> 8;              d->ata_cmd = *data >> 8;
422              d->head = *data & 0xFF;              d->head = *data;
423              ata_handle_cmd(d);              ata_handle_cmd(d);
424           }                       }            
425           break;           break;
# Line 400  void *dev_pcmcia_disk_access(cpu_mips_t Line 429  void *dev_pcmcia_disk_access(cpu_mips_t
429           if ((offset >= d->data_offset) &&           if ((offset >= d->data_offset) &&
430               (offset < d->data_offset + (SECTOR_SIZE/2)))               (offset < d->data_offset + (SECTOR_SIZE/2)))
431           {           {
             d_offset = offset - d->data_offset;  
   
432              if (op_type == MTS_READ) {              if (op_type == MTS_READ) {
433                 *data =  d->data_buffer[(d_offset << 1)];                 *data =  d->data_buffer[(d->data_pos << 1)];
434                 *data += d->data_buffer[(d_offset << 1)+1] << 8;                 *data += d->data_buffer[(d->data_pos << 1)+1] << 8;
435              } else {              } else {
436                 d->data_buffer[(d_offset << 1)]   = *data & 0xFF;                 d->data_buffer[(d->data_pos << 1)]   = *data & 0xFF;
437                 d->data_buffer[(d_offset << 1)+1] = *data >> 8;                 d->data_buffer[(d->data_pos << 1)+1] = *data >> 8;
438              }              }
439                
440                d->data_pos++;
441    
442              /* Validate data transfer */              /* Buffer complete: call the callback function */
443              if (d_offset == d->data_pos) {              if (d->data_pos == (SECTOR_SIZE/2)) {
444                 d->data_pos++;                 d->data_pos = 0;
445                  
446                 /* Buffer validated: call the callback function */                 if (d->ata_cmd_callback)
447                 if (d->data_pos == (SECTOR_SIZE/2)) {                    d->ata_cmd_callback(d);
                   d->data_pos = 0;  
   
                   if (d->ata_cmd_callback)  
                      d->ata_cmd_callback(d);  
                }  
448              }              }
449           }           }
450     }     }
# Line 428  void *dev_pcmcia_disk_access(cpu_mips_t Line 452  void *dev_pcmcia_disk_access(cpu_mips_t
452     return NULL;     return NULL;
453  }  }
454    
455    /*
456     * dev_pcmcia_disk_access_1()
457     */
458    void *dev_pcmcia_disk_access_1(cpu_mips_t *cpu,struct vdevice *dev,
459                                   m_uint32_t offset,u_int op_size,u_int op_type,
460                                   m_uint64_t *data)
461    {
462       struct pcmcia_disk_data *d = dev->priv_data;
463    
464       /* Compute the good internal offset */
465       offset = (offset >> 1) ^ 1;
466      
467    #if DEBUG_ACCESS
468       if (op_type == MTS_READ) {
469          cpu_log(cpu,d->dev.name,
470                  "reading offset 0x%5.5x at pc=0x%llx (size=%u)\n",
471                  offset,cpu->pc,op_size);
472       } else {
473          cpu_log(cpu,d->dev.name,
474                  "writing offset 0x%5.5x, data=0x%llx at pc=0x%llx (size=%u)\n",
475                  offset,*data,cpu->pc,op_size);
476       }
477    #endif
478          
479       switch(offset) {
480          case 0x02:   /* Sector Count + Sector no */
481             if (op_type == MTS_READ) {
482                *data = (d->sect_no << 8) + d->sect_count;
483             } else {
484                d->sect_no    = *data >> 8;
485                d->sect_count = *data & 0xFF;
486             }
487             break;
488    
489          case 0x04:   /* Cylinder Low + Cylinder High */
490             if (op_type == MTS_READ) {
491                *data = (d->cyl_high << 8) + d->cyl_low;
492             } else {
493                d->cyl_high = *data >> 8;
494                d->cyl_low  = *data & 0xFF;
495             }
496             break;
497    
498          case 0x06:   /* Select Card/Head + Status/Command register */
499             if (op_type == MTS_READ)
500                *data = (d->ata_status << 8) + d->head;
501             else {
502                d->ata_cmd = *data >> 8;
503                d->head = *data & 0xFF;
504                ata_handle_cmd(d);
505             }            
506             break;
507    
508          case 0x08:
509             if (op_type == MTS_READ) {
510                *data =  d->data_buffer[(d->data_pos << 1)];
511                *data += d->data_buffer[(d->data_pos << 1)+1] << 8;
512             } else {
513                d->data_buffer[(d->data_pos << 1)]   = *data & 0xFF;
514                d->data_buffer[(d->data_pos << 1)+1] = *data >> 8;
515             }
516    
517             d->data_pos++;
518    
519             /* Buffer complete: call the callback function */
520             if (d->data_pos == (SECTOR_SIZE/2)) {
521                d->data_pos = 0;
522                  
523                if (d->ata_cmd_callback)
524                   d->ata_cmd_callback(d);
525             }
526             break;
527    
528          case 0x0E:
529             break;
530       }
531    
532       return NULL;
533    }
534    
535  /* Shutdown a PCMCIA disk device */  /* Shutdown a PCMCIA disk device */
536  void dev_pcmcia_disk_shutdown(vm_instance_t *vm,struct pcmcia_disk_data *d)  void dev_pcmcia_disk_shutdown(vm_instance_t *vm,struct pcmcia_disk_data *d)
537  {  {
# Line 449  void dev_pcmcia_disk_shutdown(vm_instanc Line 553  void dev_pcmcia_disk_shutdown(vm_instanc
553  /* Initialize a PCMCIA disk */  /* Initialize a PCMCIA disk */
554  vm_obj_t *dev_pcmcia_disk_init(vm_instance_t *vm,char *name,  vm_obj_t *dev_pcmcia_disk_init(vm_instance_t *vm,char *name,
555                                 m_uint64_t paddr,m_uint32_t len,                                 m_uint64_t paddr,m_uint32_t len,
556                                 u_int disk_size)                                 u_int disk_size,int mode)
557  {  {
558     struct pcmcia_disk_data *d;     struct pcmcia_disk_data *d;
559     m_uint32_t tot_sect;     m_uint32_t tot_sect;
# Line 497  vm_obj_t *dev_pcmcia_disk_init(vm_instan Line 601  vm_obj_t *dev_pcmcia_disk_init(vm_instan
601     d->dev.phys_addr = paddr;     d->dev.phys_addr = paddr;
602     d->dev.phys_len  = len;     d->dev.phys_len  = len;
603     d->dev.flags     = VDEVICE_FLAG_CACHING;     d->dev.flags     = VDEVICE_FLAG_CACHING;
604     d->dev.handler   = dev_pcmcia_disk_access;  
605       if (mode == 0)
606          d->dev.handler = dev_pcmcia_disk_access_0;
607       else
608          d->dev.handler = dev_pcmcia_disk_access_1;
609    
610     /* Map this device to the VM */     /* Map this device to the VM */
611     vm_bind_device(vm,&d->dev);     vm_bind_device(vm,&d->dev);

Legend:
Removed from v.3  
changed lines
  Added in v.4

  ViewVC Help
Powered by ViewVC 1.1.26