⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 main.c

📁 WinAoE is an open source GPLv3 driver for using AoE (ATA over Ethernet) on Microsoft Windows
💻 C
📖 第 1 页 / 共 2 页
字号:
      cpu->eax |= 3 << 8;
      cpu->ecx &= ~0xffff;
      cpu->ecx |= realdisksize >> 16;
      cpu->edx &= ~0xffff;
      cpu->edx |= realdisksize & 0xffff;
      cpu->eflags &= ~1;
      break;

    // set media type for format
    // ch: lower 8 bits of highest cylinder number
    // cl: sectors per track (bits 0-5)
    //     high 2 bits of cylinder number (bit 6+7)
    //  dl: drive number
    // returns:
    //  clear cf on success
    //  ah: status (1 = function not available)
    //  es:di: pointer to parameter table
    case 0x18:
      if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
      cpu->eax &= ~(0xff << 8);
      cpu->eax |= 1 << 8;
      cpu->eflags &= ~1;
      break;

    // extentions
    //  bx: 0x55aa
    //  dl: drive number
    // returns:
    //  clear cf on success
    //  ah: version (1)
    //  bx: 0xaa55
    //  cx: support map (0b001)
    case 0x41:
      if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
      cpu->eax &= ~(0xff << 8);
      cpu->eax |= 1 << 8;
      cpu->ebx &= ~0xffff;
      cpu->ebx |= 0xaa55;
      cpu->ecx &= ~0xffff;
      cpu->ecx |= 1;
      cpu->eflags &= ~1;
      break;

    // extended read & extended write
    //  for write: al: write flags (bit 0: verify)
    //  dl: drive number
    //  ds:si: disk address packet
    //   (byte)0: size of packet (10h or 18h)
    //   (byte)1: reserved
    //   (word)2: count
    //   (long)4: buffer
    //   (longlong)8: lba
    // returns:
    //  ah = 0 and clear cf on success
    case 0x42:
    case 0x43:
      if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
      segmemcpy(((segment << 16) + (int)&rwpacket), ((cpu->ds << 16) + (cpu->esi & 0xffff)), sizeof(t_INT13_EXTENDED_READWRITE));
      readwrite((((cpu->eax >> 8) & 0xff) == 0x42?1:0), rwpacket.lba, rwpacket.count, rwpacket.buffersegment, rwpacket.bufferoffset);
      cpu->eax &= ~(0xff << 8);
      cpu->eflags &= ~1;
      break;

    // extended get parameters
    //  dl: drive number
    //  ds:si: drive parameters packet to fill in
    //   (word)0: packet size (1ah)
    //   (word)2: information flags (3)
    //   (long)4: cylinders
    //   (long)8: heads
    //   (long)12: sectors
    //   (longlong)16: total size in sectors
    //   (word)24: bytes per sector
    // returns:
    //  ah = 0 and clear cf on success
    case 0x48:
      if ((cpu->edx & 0xff) != aoedrive) goto unhandled;
      memset(&parameterspacket, 0, sizeof(t_INT13_EXTENDED_GET_PARAMETERS));
      parameterspacket.structsize = sizeof(t_INT13_EXTENDED_GET_PARAMETERS);
      parameterspacket.flags = 3;
      if (cylinders > 1024) {
        parameterspacket.cylinders = 1024;
      } else {
        parameterspacket.cylinders = cylinders;
      }
      parameterspacket.heads = heads;
      parameterspacket.sectors = sectors;
      parameterspacket.disksize = realdisksize;
      parameterspacket.sectorsize = SECTORSIZE;
      segmemcpy(((cpu->ds << 16) | (cpu->esi & 0xffff)), ((segment << 16) + (int)&parameterspacket), sizeof(t_INT13_EXTENDED_GET_PARAMETERS));
      cpu->eax &= ~(0xff << 8);
      cpu->eflags &= ~1;
      break;

    default:
      goto unhandled;
  }
  if (checksum != (c = chk())) {
    printf("\n\nout checksum failed on tag: %d (%08x != %08x)\n", tag, checksum, c);
    debug();
    halt();
  }
  return;

unhandled:
#ifndef MINIMAL
  printf("\n\nUnhandled INT13...\n");
  printf("eax:%08x ebx:%08x ecx:%08x edx:%08x esi:%08x edi:%08x\n", cpu->eax, cpu->ebx, cpu->ecx, cpu->edx, cpu->esi, cpu->edi);
  printf("ds:%04x es:%04x fs:%04x gs:%04x", cpu->ds, cpu->es, cpu->fs, cpu->gs);
  printf(" ID:%d VIP:%d VIF:%d AC:%d VM:%d RF:%d NT:%d IOPL:%d%d\n", ((cpu->eflags >> 21) & 1), ((cpu->eflags >> 20) & 1), ((cpu->eflags >> 19) & 1), ((cpu->eflags >> 18) & 1), ((cpu->eflags >> 17) & 1), ((cpu->eflags >> 16) & 1), ((cpu->eflags >> 14) & 1), ((cpu->eflags >> 13) & 1), ((cpu->eflags >> 12) & 1));
  printf("OF:%d DF:%d IF:%d TF:%d SF:%d ZF:%d AF:%d PF:%d CF:%d  EFLAGS:%08x  aoedrive:%02x\n", ((cpu->eflags >> 11) & 1), ((cpu->eflags >> 10) & 1), ((cpu->eflags >> 9) & 1), ((cpu->eflags >> 8) & 1), ((cpu->eflags >> 7) & 1), ((cpu->eflags >> 6) & 1), ((cpu->eflags >> 4) & 1), ((cpu->eflags >> 2) & 1), ((cpu->eflags >> 0) & 1), cpu->eflags, aoedrive);
#endif
//  _CHAININTERRUPT(_oldint13, cpu);
  printf("\n\nUnhandled INT13...\n");
  halt();
}

void readwrite(unsigned char read, unsigned int lba, int count, unsigned short seg, unsigned short off) {
  unsigned char sendbuffer[MAXPACKETSIZE];
  unsigned char receivebuffer[MAXPACKETSIZE];
  t_aoe* send = (t_aoe*)sendbuffer;
  t_aoe* receive = (t_aoe*)receivebuffer;
  unsigned int s = lba;
  int i, n, c;

printf("tag:%d rw:%d seg:%04x off:%04x\n", tag, read, seg, off);
  while (count > 0) {
    if (count == 1) {
      c = 1;
      count = 0;
    } else {
      c = 2;
      count -= 2;
    }

    memset(send, 0, sizeof(t_aoe));
    memcpy(send->dst, servermac, 6);
    memcpy(send->src, clientmac, 6);
    send->protocol = htons(AOE_PROTOCOL);
    send->ver = AOE_VERSION;
    send->major = htons(major);
    send->minor = minor;
    send->tag = tag;
    send->command = 0;
    send->aflags = 0;
    send->count = c;
    if (read) {
      send->cmd = 0x24;			// READ SECTOR
    } else {
      send->cmd = 0x34;			// WRITE SECTOR
    }
    send->lba0 = (s >> 0) & 255;
    send->lba1 = (s >> 8) & 255;
    send->lba2 = (s >> 16) & 255;
    send->lba3 = (s >> 24) & 255;
//    send->lba4 = (s >> 32) & 255;
//    send->lba5 = (s >> 40) & 255;
    send->lba4 = 0;
    send->lba5 = 0;

    if (read) {
      n = 0;
    } else {
      segmemcpy(((segment << 16) + (int)send->data), ((seg << 16) + off), c * SECTORSIZE);
      n = c;
    }

    sendreceive(send, sizeof(t_aoe) - (2 * SECTORSIZE), receive, &i);

    if (read) {
      segmemcpy(((seg << 16) + off), ((segment << 16) + (int)receive->data), c * SECTORSIZE);
    }

    s += c;
    off += c * SECTORSIZE;
  }
}

int pollisr() {
  t_PXENV_UNDI_ISR isr;
  memset((void *)&isr, 0, sizeof(isr));
  isr.FuncFlag = PXENV_UNDI_ISR_IN_START;
  if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
  if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_OURS) return 1;
  return 0;
}

void sendreceive(t_aoe* sendbuffer, int sendsize, t_aoe* receivebuffer, int* receivesize) {
int old_21, old_a1;
int volatile oldisr;
int volatile oldint0;
int volatile oldint1;
int volatile oldint2;
int volatile oldint3;
int volatile oldint4;
int volatile oldint5;
int volatile oldint6;
int volatile oldint7;
int volatile oldint8;

cli();
  timer = RECEIVETIMEOUT + 1;
  sendbuffer->tag = tag;
  gotisr = 0;
old_21 = inb(0x21);
old_a1 = inb(0xa1);
oldint0 = GETVECTOR(0x0);
oldint1 = GETVECTOR(0x1);
oldint2 = GETVECTOR(0x2);
oldint3 = GETVECTOR(0x3);
oldint4 = GETVECTOR(0x4);
oldint5 = GETVECTOR(0x5);
oldint6 = GETVECTOR(0x6);
oldint7 = GETVECTOR(0x7);
oldint8 = GETVECTOR(0x8);
SETVECTOR(0x0, (segment << 16) + (int)i0);
SETVECTOR(0x1, (segment << 16) + (int)i1);
SETVECTOR(0x2, (segment << 16) + (int)i2);
SETVECTOR(0x3, (segment << 16) + (int)i3);
SETVECTOR(0x4, (segment << 16) + (int)i4);
SETVECTOR(0x5, (segment << 16) + (int)i5);
SETVECTOR(0x6, (segment << 16) + (int)i6);
SETVECTOR(0x7, (segment << 16) + (int)i7);
SETVECTOR(0x8, (segment << 16) + (int)int8);
  if (irq == 0) {
outb(~0, 0xa1);
outb(~1, 0x21);
  } else {
    if (irq <= 7) {
      oldisr = GETVECTOR(irq + 0x8);
      SETVECTOR(irq + 0x8, (segment << 16) + (int)isr);
//      outb((inb(0x21) & (~(1 << irq))), 0x21);
outb(~0, 0xa1);
outb(~(1 << irq) & ~1, 0x21);
    } else {
      oldisr = GETVECTOR(irq + 0x70 - 0x8);
      SETVECTOR(irq + 0x70 - 0x8, (segment << 16) + (int)isr);
//      outb((inb(0xa1) & (~(1 << (irq - 8)))), 0xa1);
//      outb((inb(0x21) & (~(1 << 2))), 0x21);
outb(~(1 << (irq - 8)), 0xa1);
outb(~(1 << 2) & ~1, 0x21);
    }
  }
  while (1) {
//if (tag >= 732) printf("lets crash?\n");
    if (timer > RECEIVETIMEOUT) {
      sendpacket(sendbuffer, sendsize);
      timer = 0;
    }
//if (tag >= 732) printf("ok...\n");
    gotisr = 0;
    if (irq == 0) {
      sti();
      while (!(gotisr = pollisr()) && timer <= RECEIVETIMEOUT);
      cli();
    } else {
      sti();
      while (!gotisr && timer <= RECEIVETIMEOUT);
      cli();
    }
    if (!gotisr) continue;
    if (processpacket(receivebuffer, receivesize) <= 0) continue;
    if (ntohs(receivebuffer->protocol) != AOE_PROTOCOL) continue;
    if (ntohs(receivebuffer->major) != major) continue;
    if (receivebuffer->minor != minor) continue;
    if (!(receivebuffer->flags & (1 << 3))) continue;
    if (receivebuffer->tag != tag) continue;
    if (!(receivebuffer->status & (1 << 6))) continue;         // Drive not ready
    if (receivebuffer->status & (1 << 5)) {
      printf("AoE ATA Drive error.\n");
      halt();
    }
    break;
  }
  if (memcmp(servermac, "\xff\xff\xff\xff\xff\xff", 6) == 0) memcpy(servermac, receivebuffer->src, 6);
outb(old_a1, 0xa1);
outb(old_21, 0x21);
SETVECTOR(0x0, oldint0);
SETVECTOR(0x1, oldint1);
SETVECTOR(0x2, oldint2);
SETVECTOR(0x3, oldint3);
SETVECTOR(0x4, oldint4);
SETVECTOR(0x5, oldint5);
SETVECTOR(0x6, oldint6);
SETVECTOR(0x7, oldint7);
SETVECTOR(0x8, oldint8);
  if (irq != 0) {
    if (irq <= 7) {
      SETVECTOR(irq + 0x8, oldisr);
//      outb((inb(0x21) | (1 << irq)), 0x21);
    } else {
      SETVECTOR(irq + 0x70 - 0x8, oldisr);
//      outb((inb(0xa1) | (1 << (irq - 8))), 0xa1);
    }
  }
  tag++;
}

void sendpacket(void* packet, int size) {
  t_PXENV_UNDI_TRANSMIT transmit;
  t_PXENV_UNDI_TBD tbd;

  memset((void *)&transmit, 0, sizeof(transmit));
  memset((void *)&tbd, 0, sizeof(tbd));
  transmit.Protocol = P_UNKNOWN;
  transmit.XmitFlag = XMT_DESTADDR;
  transmit.TBD.segment = segment;
  transmit.TBD.offset = (unsigned int)&tbd;
  tbd.ImmedLength = size;
  tbd.Xmit.segment = segment;
  tbd.Xmit.offset = (unsigned int)packet;
  tbd.DataBlkCount = 0;
  if (api(PXENV_UNDI_TRANSMIT, (void *)&transmit)) apierror("PXENV_UNDI_TRANSMIT", transmit.Status);
}

int processpacket(void* buffer, int* size) {
  t_PXENV_UNDI_ISR isr;
  int receiveddata = 0;
  int r = 0;

  memset((void *)&isr, 0, sizeof(isr));
  isr.FuncFlag = PXENV_UNDI_ISR_IN_PROCESS;
  if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
  if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_DONE || isr.FuncFlag == PXENV_UNDI_ISR_OUT_BUSY) return 0;

next:
  if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_TRANSMIT) goto release;
  if (isr.FuncFlag == PXENV_UNDI_ISR_OUT_RECEIVE) {
    if (isr.BufferLength > MAXPACKETSIZE) {
      printf("Received packet too large... (%d)\n", isr.BufferLength);
      goto release;
    }
    *size = isr.FrameLength;
    segmemcpy(((segment << 16) + (int)buffer + receiveddata), ((isr.Frame.segment << 16) + isr.Frame.offset), isr.BufferLength);
    receiveddata += isr.BufferLength;
    r = 1;
    goto release;
  }

  printf("Unknown function?...\n");

release:
  memset((void *)&isr, 0, sizeof(isr));
  isr.FuncFlag = PXENV_UNDI_ISR_IN_GET_NEXT;
  if (api(PXENV_UNDI_ISR, (void *)&isr)) apierror("PXENV_UNDI_ISR", isr.Status);
  if (isr.FuncFlag != PXENV_UNDI_ISR_OUT_DONE && isr.FuncFlag != PXENV_UNDI_ISR_OUT_BUSY) goto next;
  return r;
}

#ifndef MINIMAL
void printbuffer(unsigned short seg, unsigned short off, size_t n) {
  int i, l, s;
  unsigned char buffer[16];

  l = 0;
  while (n > 0) {
    s = (n > 16?16:n);
    segmemcpy((int)((segment << 16) + ((int)&buffer)), (((int)(seg << 16)) + off), s);
    printf("%04x:%04x  ", seg, off);
    for (i = 0; i < s; i++) {
      printf("%02x ", buffer[i]);
    }
    for (i = s; i < 16; i++) printf("   ");
    for (i = 0; i < s; i++) {
      if (buffer[i] > 32) {
        putchar(buffer[i]);
      } else {
        putchar('.');
      }
    }
    putchar('\n');
    l++;
    if ((l == 16) && (n > 16)) {
      l = 0;
      printf("Press a key\n");
      getkey(0);
    }
    n -= s;
    off += 16;
  }
}
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -