UHCI Counter in VMware?
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
UHCI Counter in VMware?
Hello All,
I was trying to implement a UHCI Driver. I have my initialization code that sets the frame list base address, frame list counter, and sets RUN/STOP to 1. Monitoring the counter, in QEMU, it works well and counts from 0 to 2047. but in VMWare, it counts slowly until it reach 300s, when it is increaded by one each second in a very slow way. Is there something wrong have been done? and I would be happy to know about the steps of initialization process of UHCI.
Regards,
Mostafa.
I was trying to implement a UHCI Driver. I have my initialization code that sets the frame list base address, frame list counter, and sets RUN/STOP to 1. Monitoring the counter, in QEMU, it works well and counts from 0 to 2047. but in VMWare, it counts slowly until it reach 300s, when it is increaded by one each second in a very slow way. Is there something wrong have been done? and I would be happy to know about the steps of initialization process of UHCI.
Regards,
Mostafa.
Re: UHCI Counter in VMware?
Hi mostafazizo: See http://forum.osdev.org/viewtopic.php?f=11&t=21679 for help with getting the USB debug info. Vmware is probably just a lot more demanding than QEMU (I don't know, I never used QEMU successfully) is, and from working with it (i.e., VMWARE), I think it expects perfection. As far as the steps for initialization go, you will need to read the USB specs. The UHCI specs don't really go over that, I think it is sort of implied (or I am continuously overlooking it). You can try to take a look at linux code too. Or, you can post what you have so far and I will take a look at it for you. Whatever floats your boat.
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
Dear osdnlo,
Thanks much for your answer, i have edited my vmx file, and now i run VMware in debug mode, but i don't know how to get debug info, or how to know about errors taking place in VMware.
I had read UHCI specs before trying to implement it, but i didn't find any about initialization. i also tried to look for it in USB Specification, but i failed. Do you know where i could find about this??? (notice that i want to initialize UHCI Host Controller only to get it work well on VMware).
Regards,
Mostafa.
Thanks much for your answer, i have edited my vmx file, and now i run VMware in debug mode, but i don't know how to get debug info, or how to know about errors taking place in VMware.
I had read UHCI specs before trying to implement it, but i didn't find any about initialization. i also tried to look for it in USB Specification, but i failed. Do you know where i could find about this??? (notice that i want to initialize UHCI Host Controller only to get it work well on VMware).
Regards,
Mostafa.
Re: UHCI Counter in VMware?
Well, if you do, then please share with the rest of us. I have been trying to get vmware to play nice for about a month now and it's been pretty rough.
The log file is located in the same directory that your vmx is located when vmware starts. Probably. C:\DOCUME~1\MYVIRT~1\<name of your vmx>, you know, something like that. Inside your My Documents folder, nested in another folder named My Virtual Machines. The file you want to keep an eye is called vmware.log. What I do is I open that file in Firefox, and I have a plug-in that reloads the page every N seconds, and I just watch it fill up as the vm is running. Look for things like: USBGW, USBIO, UHCI, etc. Vmware even has a program they wrote to parse your log, but it doesn't work well on Windows, says the horses mouth.
I would suggest looking at linux code. I think it is some of the best example of code I have seen to date, in regards to UHCI. They have a real sophisticated way of initializing the controller that I too have been inspired by. You might also track down good ol' Geezer code. I know he wrote a nice example, but it is highly incomplete. However, it does demonstrate how to create the TDs and QH properly, so it's worth a look.
http://www.google.com/codesearch/p?hl=e ... temp/usb.c
I hope this helps. Post back if you run into any more trouble.
The log file is located in the same directory that your vmx is located when vmware starts. Probably. C:\DOCUME~1\MYVIRT~1\<name of your vmx>, you know, something like that. Inside your My Documents folder, nested in another folder named My Virtual Machines. The file you want to keep an eye is called vmware.log. What I do is I open that file in Firefox, and I have a plug-in that reloads the page every N seconds, and I just watch it fill up as the vm is running. Look for things like: USBGW, USBIO, UHCI, etc. Vmware even has a program they wrote to parse your log, but it doesn't work well on Windows, says the horses mouth.
I would suggest looking at linux code. I think it is some of the best example of code I have seen to date, in regards to UHCI. They have a real sophisticated way of initializing the controller that I too have been inspired by. You might also track down good ol' Geezer code. I know he wrote a nice example, but it is highly incomplete. However, it does demonstrate how to create the TDs and QH properly, so it's worth a look.
http://www.google.com/codesearch/p?hl=e ... temp/usb.c
I hope this helps. Post back if you run into any more trouble.
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
thnxxxxxxxxxx a lot osdnlo, i had a look on the link, i've read the function of initializing uhci, but it seems really no difference!!!!!!
i found that he did something i didn't do, which is resetting PORT1 and PORT2, i tried to reset them, but absolutely no difference.
here is my uhci.cpp:
i found that he did something i didn't do, which is resetting PORT1 and PORT2, i tried to reset them, but absolutely no difference.
here is my uhci.cpp:
Code: Select all
#define UHCI 0x00 // Universal Host Controller Interface. Supports USB1 and USB1.1.
#define UHCI_REG_USBCMD 0x00
#define UHCI_REG_USBSTS 0x02
#define UHCI_REG_USBINTR 0x04
#define UHCI_REG_FRNUM 0x06
#define UHCI_REG_FRBASEADD 0x08
#define UHCI_REG_SOFMOD 0x0C
#define UHCI_REG_PORTSC1 0x10
#define UHCI_REG_PORTSC2 0x12
struct tdstr {
unsigned char T; // Termination (1: Link is not valid, 0: Link is valid).
unsigned char QH; // Queue Head (1: Link is to a QH, 0: Link is to a TD).
unsigned char Vf; // Depth/Breadth Select (1: Depth First, 0: Breadth First).
unsigned int link; // 32-Bit Memory Address of next descriptor.
unsigned short ActLen; // Actual Length.
unsigned char status; // Status.
unsigned char IOC; // Interrupt on Complete (1: Issue IOC after the current time frame).
unsigned char IOS; // Isochronous Select (1: Isochronous TD, 0: Non-isochronous).
unsigned char LS; // Low Speed Drive (1: Low Speed, 0: Full Speed).
unsigned char C_ERR; // Counter Errot.
unsigned char SPD; // Short Packet Detect (1: Enable, 0: Disable).
unsigned char PID; // Packet Identification (0x69: IN, 0xE1: OUT, 0x2D: Setup).
unsigned char device; // Device Address.
unsigned char EndPt; // End Point.
unsigned char D; // Data Toggle Synchronization.
unsigned short MaxLen; // Maximum Length.
unsigned int buffer; // Buffer Pointer.
};
struct sixteenbytelen {
unsigned int lng[4];
};
struct eightbytelen {
unsigned int lng[2];
};
unsigned int uhci_data[0x2000]; // 0x2000(Array size) * 4(int size) = 0x8000 byte (32KB).
unsigned int* uhci_frlst; // 4KB Frame List.
sixteenbytelen* uhci_tdlst; // TD List.
eightbytelen* uhci_qhlst; // QH List.
void set_td(tdstr *td, unsigned int index) {
uhci_tdlst[index].lng[0] = (td[0].T << 0)|
(td[0].QH << 1)|
(td[0].Vf << 2)|
(td[0].link << 0);
uhci_tdlst[index].lng[1] = (td[0].ActLen << 0)|
(td[0].status << 16)|
(td[0].IOC << 24)|
(td[0].IOS << 25)|
(td[0].LS << 26)|
(td[0].C_ERR << 27)|
(td[0].SPD << 29);
uhci_tdlst[index].lng[2] = (td[0].PID << 0)|
(td[0].device << 8)|
(td[0].EndPt << 15)|
(td[0].D << 19)|
(td[0].MaxLen << 21);
uhci_tdlst[index].lng[3] = (td[0].buffer << 0);
}
void uhci_init() {
unsigned short ds; asm("movw %%ds, %%ax":"=a"(ds));
unsigned int i;
printk(" Initializing UHCI USB Device Driver ...\n");
// I: Initialize Pointers:
uhci_frlst = (unsigned int *) ((unsigned int) uhci_data & 0xFFFFF000); // 4KB Frame List.
uhci_tdlst = (sixteenbytelen *) ((unsigned int) &uhci_frlst[1024]); // 16KB TD List.
uhci_qhlst = (eightbytelen *) ((unsigned int) &uhci_tdlst[1024]); // 8KB QH List.
// II: Resetting USB Host Controller:
usbio.writeregw(0x04, UHCI_REG_USBCMD);
sleep(10); // 10ms delay is so enough.
usbio.writeregw(0x00, UHCI_REG_USBCMD);
sleep(100); // 100ms delay is so enough.
// III: Initialize Frame List:
//1: Make Pointers:
for (i = 0; i < 0x400; i++) {
uhci_qhlst[i].lng[0] = uhci_qhlst[i].lng[1] = 0x00000001;
uhci_frlst[i] = krnl_get_selector_base(ds) + (unsigned int) &uhci_qhlst[i] + 0x2;
}
// 2: Set the frame-list base in the Host Controller:
usbio.writeregl(krnl_get_selector_base(ds) +
(unsigned int) uhci_frlst, UHCI_REG_FRBASEADD);
// 3: Set the time of frames:
// For a 12MHz Motor, a value of 12000 makes each frame takes 1ms of time
// (12000 vibration). the number of vibrations is calulated by adding the value of
// first 7 bits of SOFMOD Register to 11936.
usbio.writeregb(64, UHCI_REG_SOFMOD); // 64+11936=12000. (1ms for each frame).
// 4: Set Frame Number:
usbio.writeregw(0x00, UHCI_REG_FRNUM); // Start from first frame.
// IV: Start the controller:
usbio.writeregw(0x01,UHCI_REG_USBCMD);
while (1) {
printk(" Frame List Counter: %d.\n", usbio.readregw(UHCI_REG_FRNUM) & 0x3FF);
}
}
Re: UHCI Counter in VMware?
Nice start. Your code looks real fine and clean. Good work thus far.
Some things that pop out at me right away is:
01. Now take a look at the LEGACY section of the USB UHCI spec. You need to make a check to see if it is on, if it is, turn it off.
02. You are not checking if the device is Low Speed or Full Speed. Make a check for that as you build the TDs. Don't just assume it is LS.
03. You should clear the CSC bit from all ports before you make your transaction, after you find a UHCI controller.
04. Make sure you also enable the port, then reset it before your first transaction. This causes the controller to force a port resume, which may not be necessary. You can check if the port is suspended first. b12.
05. Make sure the device you are testing is not High-Speed. If it is, then you will need to take ownership. See http://forum.osdev.org/viewtopic.php?f=1&t=21681
06. You may need to GRESUME if the controller is suspended. Make a check for that.
Other than that, you have a pretty good ideal of what needs to be done. And, like I said, take a look at linux code. You'll be glad you did.
And, are you by chance using the Fat DS/nearptr hack?
Some things that pop out at me right away is:
01. Now take a look at the LEGACY section of the USB UHCI spec. You need to make a check to see if it is on, if it is, turn it off.
02. You are not checking if the device is Low Speed or Full Speed. Make a check for that as you build the TDs. Don't just assume it is LS.
03. You should clear the CSC bit from all ports before you make your transaction, after you find a UHCI controller.
04. Make sure you also enable the port, then reset it before your first transaction. This causes the controller to force a port resume, which may not be necessary. You can check if the port is suspended first. b12.
05. Make sure the device you are testing is not High-Speed. If it is, then you will need to take ownership. See http://forum.osdev.org/viewtopic.php?f=1&t=21681
06. You may need to GRESUME if the controller is suspended. Make a check for that.
Other than that, you have a pretty good ideal of what needs to be done. And, like I said, take a look at linux code. You'll be glad you did.
And, are you by chance using the Fat DS/nearptr hack?
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
osdnlo wrote:Nice start. Your code looks real fine and clean. Good work thus far.
DONEosdnlo wrote:01. Now take a look at the LEGACY section of the USB UHCI spec. You need to make a check to see if it is on, if it is, turn it off.
I check a usb gamepad, but i'm still programming UHCI initialization. i don't assume that they are LS because there are no TDs already.osdnlo wrote:02. You are not checking if the device is Low Speed or Full Speed. Make a check for that as you build the TDs. Don't just assume it is LS.
DONEosdnlo wrote:03. You should clear the CSC bit from all ports before you make your transaction, after you find a UHCI controller.
DONE (but without checking)osdnlo wrote:04. Make sure you also enable the port, then reset it before your first transaction. This causes the controller to force a port resume, which may not be necessary. You can check if the port is suspended first. b12..
I check a full-speed usb gamepad, but i'm still programming UHCI initialization.osdnlo wrote:05. Make sure the device you are testing is not High-Speed. If it is, then you will need to take ownership. See http://forum.osdev.org/viewtopic.php?f=1&t=21681
DONEosdnlo wrote:06. You may need to GRESUME if the controller is suspended. Make a check for that.
Despite all of that, i am still facing this strange behavior of VMware. here is my new code:
Code: Select all
#define UHCI 0x00 // Universal Host Controller Interface. Supports USB1 and USB1.1.
#define UHCI_REG_USBCMD 0x00
#define UHCI_REG_USBSTS 0x02
#define UHCI_REG_USBINTR 0x04
#define UHCI_REG_FRNUM 0x06
#define UHCI_REG_FRBASEADD 0x08
#define UHCI_REG_SOFMOD 0x0C
#define UHCI_REG_PORTSC1 0x10
#define UHCI_REG_PORTSC2 0x12
struct tdstr {
unsigned char T; // Termination (1: Link is not valid, 0: Link is valid).
unsigned char QH; // Queue Head (1: Link is to a QH, 0: Link is to a TD).
unsigned char Vf; // Depth/Breadth Select (1: Depth First, 0: Breadth First).
unsigned int link; // 32-Bit Memory Address of next descriptor.
unsigned short ActLen; // Actual Length.
unsigned char status; // Status.
unsigned char IOC; // Interrupt on Complete (1: Issue IOC after the current time frame).
unsigned char IOS; // Isochronous Select (1: Isochronous TD, 0: Non-isochronous).
unsigned char LS; // Low Speed Drive (1: Low Speed, 0: Full Speed).
unsigned char C_ERR; // Counter Errot.
unsigned char SPD; // Short Packet Detect (1: Enable, 0: Disable).
unsigned char PID; // Packet Identification (0x69: IN, 0xE1: OUT, 0x2D: Setup).
unsigned char device; // Device Address.
unsigned char EndPt; // End Point.
unsigned char D; // Data Toggle Synchronization.
unsigned short MaxLen; // Maximum Length.
unsigned int buffer; // Buffer Pointer.
};
struct sixteenbytelen {
unsigned int lng[4];
};
struct eightbytelen {
unsigned int lng[2];
};
unsigned int uhci_data[0x2000]; // 0x2000(Array size) * 4(int size) = 0x8000 byte (32KB).
unsigned int* uhci_frlst; // 4KB Frame List.
sixteenbytelen* uhci_tdlst; // TD List.
eightbytelen* uhci_qhlst; // QH List.
void set_td(tdstr *td, unsigned int index) {
uhci_tdlst[index].lng[0] = (td[0].T << 0)|
(td[0].QH << 1)|
(td[0].Vf << 2)|
(td[0].link << 0);
uhci_tdlst[index].lng[1] = (td[0].ActLen << 0)|
(td[0].status << 16)|
(td[0].IOC << 24)|
(td[0].IOS << 25)|
(td[0].LS << 26)|
(td[0].C_ERR << 27)|
(td[0].SPD << 29);
uhci_tdlst[index].lng[2] = (td[0].PID << 0)|
(td[0].device << 8)|
(td[0].EndPt << 15)|
(td[0].D << 19)|
(td[0].MaxLen << 21);
uhci_tdlst[index].lng[3] = (td[0].buffer << 0);
}
void uhci_init() {
unsigned short ds; asm("movw %%ds, %%ax":"=a"(ds));
unsigned int i;
printk(" Initializing UHCI USB Device Driver ...\n");
// I: Initialize Pointers:
uhci_frlst = (unsigned int *) ((unsigned int) uhci_data & 0xFFFFF000); // 4KB Frame List.
uhci_tdlst = (sixteenbytelen *) ((unsigned int) &uhci_frlst[1024]); // 16KB TD List.
uhci_qhlst = (eightbytelen *) ((unsigned int) &uhci_tdlst[1024]); // 8KB QH List.
// II: Resetting USB Host Controller:
usbio.writeregw(0x04, UHCI_REG_USBCMD);
sleep(10); // 10ms delay is so enough.
usbio.writeregw(0x00, UHCI_REG_USBCMD);
sleep(100); // 100ms delay is so enough.
// III: Rsetting Ports:
usbio.writeregw(0x024E, UHCI_REG_PORTSC1); // Reset, Enable, Clear CSC
sleep(10); // 10ms delay is so enough.
usbio.writeregw(0x004E, UHCI_REG_PORTSC1);
usbio.writeregw(0x024E, UHCI_REG_PORTSC2);
sleep(10); // 10ms delay is so enough.
usbio.writeregw(0x004E, UHCI_REG_PORTSC2);
// IV: Enable Legacy Support for KB and Mouse:
unsigned char bus = usb_pack[0x12];
unsigned char device = usb_pack[0x13];
unsigned char function = usb_pack[0x14];
outl((1<<31) | (bus<<16) | (device<<11) | (function<<8) | 0xC0, 0xCF8);
outw(0x20FF, 0xCFC);
// V: Initialize Frame List:
// 1: Set the time of frames:
// For a 12MHz Motor, a value of 12000 makes each frame takes 1ms of time
// (12000 vibration). the number of vibrations is calulated by adding the value of
// first 7 bits of SOFMOD Register to 11936.
usbio.writeregb(64, UHCI_REG_SOFMOD); // 64+11936=12000. (1ms for each frame).
// 2: Make Pointers:
for (i = 0; i < 0x400; i++) {
uhci_qhlst[i].lng[0] = uhci_qhlst[i].lng[1] = 0x00000001;
uhci_frlst[i] = krnl_get_selector_base(ds) + (unsigned int) &uhci_qhlst[i] + 0x2;
}
// 3: Set the frame-list base in the Host Controller:
usbio.writeregl(krnl_get_selector_base(ds) +
(unsigned int) uhci_frlst, UHCI_REG_FRBASEADD);
// VI: Start the controller:
usbio.writeregw(0x01,UHCI_REG_USBCMD); // RUN
while (1) {
printk(" Frame List Counter: %d.\n", usbio.readregw(UHCI_REG_FRNUM) & 0x3FF);
}
}
Believe me, i have been checking Linux Source Code since your first post in this topic according to ur advice.osdnlo wrote:Other than that, you have a pretty good ideal of what needs to be done. And, like I said, take a look at linux code. You'll be glad you did.
???????????And, are you by chance using the Fat DS/nearptr hack?
Regards,
Mostafa
Re: UHCI Counter in VMware?
Well, it seems like you are doing everything correctly, so it may be a vmware thing. The best thing to do now would be to ask the horse itself. See http://communities.vmware.com/search.jspa. Post back if you find a solution.
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
hello again,
i tried the driver on Bochs, and it runs perfectly with no error, so the error might be from VMware 7 itself. but i tried to test the driver on VMware 6 simulation, and i found something strange:
The SOF frame time takes 1 second rather than 1ms.
i don't know the reason of that, may be the counter is 12 KHz and not 12MHz?
the strange is that i tested a variety of operating systems like Microsoft Windows XP, Linux Ubuntu and Linux Kubuntu on VMware (6, 7) and they control UHCI correctly and without reporting errors.
plz anyone have any idea????
Regards,
Mostafa
i tried the driver on Bochs, and it runs perfectly with no error, so the error might be from VMware 7 itself. but i tried to test the driver on VMware 6 simulation, and i found something strange:
The SOF frame time takes 1 second rather than 1ms.
i don't know the reason of that, may be the counter is 12 KHz and not 12MHz?
the strange is that i tested a variety of operating systems like Microsoft Windows XP, Linux Ubuntu and Linux Kubuntu on VMware (6, 7) and they control UHCI correctly and without reporting errors.
plz anyone have any idea????
i searched for a topic that discusses this problem, but found nothing, i reported there for my error, but no reply till now!Well, it seems like you are doing everything correctly, so it may be a vmware thing. The best thing to do now would be to ask the horse itself. See http://communities.vmware.com/search.jspa. Post back if you find a solution.
Regards,
Mostafa
Re: UHCI Counter in VMware?
They are probably still trying to replicate your issue and haven't found an answer yet. Just give them some more time and I am sure they will address it soon.
I am using the VMware Player 3.0.1 and I am not able to replicate your issue myself. The frames pass by really fast for me, as expected. Why not post your vmware log the next time you make a test and notice this issue. Perhaps the answer is in there.
I am using the VMware Player 3.0.1 and I am not able to replicate your issue myself. The frames pass by really fast for me, as expected. Why not post your vmware log the next time you make a test and notice this issue. Perhaps the answer is in there.
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
Hi Again,
UPDATE: I noticed something maddening in the log file:
Mar 21 06:54:43.253: mks| MKS: Base polling period is 1000000us
1000000us (micro-second) = 1000ms (millisecond) = 1s (second), may be this is relating to our problem?
Regards,
Mostafa.
Waiting ...They are probably still trying to replicate your issue and haven't found an answer yet. Just give them some more time and I am sure they will address it soon.
I have attached my log file, notice that i am running VMware in debug mode.Why not post your vmware log the next time you make a test and notice this issue. Perhaps the answer is in there.
UPDATE: I noticed something maddening in the log file:
Mar 21 06:54:43.253: mks| MKS: Base polling period is 1000000us
1000000us (micro-second) = 1000ms (millisecond) = 1s (second), may be this is relating to our problem?
Regards,
Mostafa.
- Attachments
-
- vmware.zip
- (13.89 KiB) Downloaded 282 times
Re: UHCI Counter in VMware?
Hi, I took a look at your log and right away I see this:
What's going on here? Are you resetting the VM, is it resetting on you? I noticed right after this, your driver begins echoing output to the screen, but you did not allow it to run long enough to demonstrate that the FRNUM is changing too slowly, so I cannot verify what's wrong based on this log. I know you must be getting frustrated by now. Just hang in there, we'll figure it out.Mar 21 06:54:35.285: vcpu-0| UHCI: HCReset
Mar 21 06:54:35.533: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x1041d0
Mar 21 06:54:36.543: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x104f62
Mar 21 06:54:37.543: vcpu-0| VMSAMPLE32: cs=0x38, eip=0x322
Mar 21 06:54:38.563: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x104f61
Mar 21 06:54:39.615: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x101dd2
Mar 21 06:54:40.623: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x1051bc
Mar 21 06:54:40.674: mks| MKS lock releasing
Mar 21 06:54:41.632: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x1041d0
Mar 21 06:54:42.651: vcpu-0| VMSAMPLE32: cs=0x8, eip=0x1050bc
Mar 21 06:54:43.194: vmx| VMXVmdbCbVmVmxExecState: Exec state change requested to state poweredOff without reset, hard.
Mar 21 06:54:43.194: vmx| Stopping VCPU threads...
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
The Driver resets the HC, then it waits for me to press any key from keyboard, and then it prints the current frame number. and then it waits again to repeat the same process.
what happened is that i kept my finger pressing on 'Enter' and it the driver printed 4 many times for a second, then 5 for another second, then 6 for another second.... the log file captured a random screen that is full with '4'.
In QEMU and Bochs, when i do that, numbers change quickly, because it prints 4 in a millisecond, 5 in a millisecond ...
No, i am not getting frustrated, because nothing is wrong till now, but when we find that this problem is a result of something wrong in my code, i will be frustrated in a way that will make me not programme again
what happened is that i kept my finger pressing on 'Enter' and it the driver printed 4 many times for a second, then 5 for another second, then 6 for another second.... the log file captured a random screen that is full with '4'.
In QEMU and Bochs, when i do that, numbers change quickly, because it prints 4 in a millisecond, 5 in a millisecond ...
Code: Select all
I know you must be getting frustrated by now. Just hang in there, we'll figure it out.
Re: UHCI Counter in VMware?
Well, you're a better man than I am. I would have tossed my computer out the window and called it a day by now. Hmmm... I never saw where you performed an HCRESET. You know when you HCRESET you reset the internal counters and such, so you might try doing that (i.e. (1<<1)).
Yes, I see that you have proven it, but my question was, 'How did you know that would work?'.
- iocoder
- Member
- Posts: 208
- Joined: Sun Oct 18, 2009 5:47 pm
- Libera.chat IRC: iocoder
- Location: Alexandria, Egypt | Ottawa, Canada
- Contact:
Re: UHCI Counter in VMware?
how?I never saw where you performed an HCRESET.
Code: Select all
#define UHCI 0x00 // Universal Host Controller Interface. Supports USB1 and USB1.1.
#define UHCI_REG_USBCMD 0x00
#define UHCI_REG_USBSTS 0x02
#define UHCI_REG_USBINTR 0x04
#define UHCI_REG_FRNUM 0x06
#define UHCI_REG_FRBASEADD 0x08
#define UHCI_REG_SOFMOD 0x0C
#define UHCI_REG_PORTBASE 0x10
#define UHCI_USBLEGSUP 0xc0 /* legacy support */
#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */
#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */
#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */
#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */
#define UHCI_USBCMD_GRESET 0x0004 /* Global Reset */
#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */
#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */
#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */
#include <keypad.h>
struct tdstr {
unsigned char T; // Termination (1: Link is not valid, 0: Link is valid).
unsigned char QH; // Queue Head (1: Link is to a QH, 0: Link is to a TD).
unsigned char Vf; // Depth/Breadth Select (1: Depth First, 0: Breadth First).
unsigned int link; // 32-Bit Memory Address of next descriptor.
unsigned short ActLen; // Actual Length.
unsigned char status; // Status.
unsigned char IOC; // Interrupt on Complete (1: Issue IOC after the current time frame).
unsigned char IOS; // Isochronous Select (1: Isochronous TD, 0: Non-isochronous).
unsigned char LS; // Low Speed Drive (1: Low Speed, 0: Full Speed).
unsigned char C_ERR; // Counter Errot.
unsigned char SPD; // Short Packet Detect (1: Enable, 0: Disable).
unsigned char PID; // Packet Identification (0x69: IN, 0xE1: OUT, 0x2D: Setup).
unsigned char device; // Device Address.
unsigned char EndPt; // End Point.
unsigned char D; // Data Toggle Synchronization.
unsigned short MaxLen; // Maximum Length.
unsigned int buffer; // Buffer Pointer.
};
struct sixteenbytelen {
unsigned int lng[4];
};
struct eightbytelen {
unsigned int lng[2];
};
unsigned int uhci_data[0x2000]; // 0x2000(Array size) * 4(int size) = 0x8000 byte (32KB).
unsigned int* uhci_frlst; // 4KB Frame List.
sixteenbytelen* uhci_tdlst; // TD List.
eightbytelen* uhci_qhlst; // QH List.
unsigned int uhci_ports; // Number of Ports.
void set_td(tdstr td, unsigned int index) {
uhci_tdlst[index].lng[0] = (td.T << 0)|
(td.QH << 1)|
(td.Vf << 2)|
(td.link << 0);
uhci_tdlst[index].lng[1] = (td.ActLen << 0)|
(td.status << 16)|
(td.IOC << 24)|
(td.IOS << 25)|
(td.LS << 26)|
(td.C_ERR << 27)|
(td.SPD << 29);
uhci_tdlst[index].lng[2] = (td.PID << 0)|
(td.device << 8)|
(td.EndPt << 15)|
(td.D << 19)|
(td.MaxLen << 21);
uhci_tdlst[index].lng[3] = (td.buffer << 0);
}
void uhci_init() {
unsigned short ds; asm("movw %%ds, %%ax":"=a"(ds));
unsigned int i;
unsigned char bus = usb_pack[0x12];
unsigned char dev = usb_pack[0x13];
unsigned char func = usb_pack[0x14];
unsigned char reset = 0;
printk(" Initializing UHCI USB Device Driver ...\n");
// I: Initialize Pointers:
// ----------------------------
uhci_frlst = (unsigned int *) ((unsigned int) uhci_data & 0xFFFFF000); // 4KB Frame List.
uhci_tdlst = (sixteenbytelen *) ((unsigned int) &uhci_frlst[1024]); // 16KB TD List.
uhci_qhlst = (eightbytelen *) ((unsigned int) &uhci_tdlst[1024]); // 8KB QH List.
// II: Get Number of Ports:
// ----------------------------
for (i = 0; i < 0x10; i+=2)
if (!(usbio.readregw(UHCI_REG_PORTBASE + i) & 0x0080)
|| usbio.readregw(UHCI_REG_PORTBASE + i) == 0xffff) break;
if((uhci_ports = (i/2)) > 7) uhci_ports = 2;
// III: Restart UHCI:
// ----------------------------
/* Turn on PIRQ enable and SMI enable.
* This turns on legacy support for keyboard and mouse.
*/
pci_writew(0xFFFF, bus, dev, func, UHCI_USBLEGSUP);
/* Reset the HC - this will force us to get a
* new notification of any already connected
* ports due to the virtual disconnect that it
* implies.
*/
usbio.writeregw(UHCI_USBCMD_HCRESET, UHCI_REG_USBCMD);
while (usbio.readregw(UHCI_REG_USBCMD) & UHCI_USBCMD_HCRESET); // Wait
/* Just to be safe, disable interrupt requests and
* make sure the controller is stopped.
*/
usbio.writeregw(0, UHCI_REG_USBINTR);
usbio.writeregw(0, UHCI_REG_USBCMD);
/* HCRESET doesn't affect the Suspend, Reset, and Resume Detect
* bits in the port status and control registers.
* We have to clear them by hand.
*/
for (i = 0; i < 2; ++i)
usbio.writeregw(0, UHCI_REG_PORTBASE + (i * 2));
// IV: Initialize the HC:
// ----------------------------
// 1: Set the time of frames:
// For a 12MHz Motor, a value of 12000 makes each frame takes 1ms of time
// (12000 vibration). the number of vibrations is calulated by adding the value of
// first 7 bits of SOFMOD Register to 11936.
usbio.writeregb(64, UHCI_REG_SOFMOD); // 64+11936=12000. (1ms for each frame).
// 2: Make Pointers:
static tdstr std;
std.T = 1;
std.device = 0x7f;
std.PID = 0x69;
for (i = 0; i < 0x400; i++) {
set_td(std, i);
uhci_qhlst[i].lng[0] = 0x00000003;
uhci_qhlst[i].lng[1] = (krnl_get_selector_base(ds) + (int) &uhci_tdlst[i]);
uhci_frlst[i] = 0x1;
}
// 3: Set the frame-list base in the Host Controller:
usbio.writeregl(krnl_get_selector_base(ds) +
(unsigned int) uhci_frlst, UHCI_REG_FRBASEADD);
// V: Start the controller:
usbio.writeregw(0x01, UHCI_REG_USBCMD); // RUN
int x;
while(1) {
x = usbio.readregw(UHCI_REG_FRNUM);
printk(" Frame List Counter: %d.\n", x & 0x3FF);
printk(" Status: %x.\n", usbio.readregw(UHCI_REG_USBSTS));
getc();
}
}